Skip to content

Define retention roots and GC liveness - #68

Merged
flyingrobots merged 23 commits into
mainfrom
adr/retention-roots-gc-liveness
Jul 30, 2026
Merged

Define retention roots and GC liveness#68
flyingrobots merged 23 commits into
mainfrom
adr/retention-roots-gc-liveness

Conversation

@flyingrobots

Copy link
Copy Markdown
Owner

Problem

M4 lacked an accepted authority model for retention roots, release, immutable liveness snapshots, and fail-closed garbage collection.

Invariant affected

Keep may collect physical material only when an exact immutable snapshot proves that no retained reconstruction anchor requires it.

Approach

Add ADR-0009, index it, record the unreleased design contract, and enforce its core laws with a repository-owned xtask test. The decision uses validated namespaces, BlobId/LayoutId anchors, bounded canonical closure, monotonic root and liveness generations, a nonzero deterministic realization profile, and shared exclusive writer authority for retention, publication, recovery, and GC execution.

Alternatives rejected

Git refs, leases, reference counts, unversioned tracing, caller-supplied physical closure, and retaining every representation are rejected in the ADR.

Failure modes

Stale generations, missing or corrupt closure members, ambiguous physical realizations, zero witnesses, changed catalog or liveness views, and active safety fences all refuse rather than weaken liveness.

Tests

The new contract test passes 4/4 in debug and release. Full workspace checks, strict Clippy, debug/release tests, doctests, MSRV 1.96, fuzz-crate checks, both 105-case crash matrices, documentation refusal/integrity, whitespace, cargo-deny, and cargo-audit pass locally.

Benchmark impact

No runtime implementation changes; no benchmark delta.

Format/API compatibility

No shipped format or public API changes. ADR-0009 constrains the future #19 implementation and requires versioned canonical formats.

Recovery implications

Retention and GC execution share the existing exclusive store writer authority with catalog publication and recovery. Interrupted future publication must follow the durable-store recovery law.

Security implications

Receipts prove narrow physical claims only and expose no content, keys, or unbounded paths. Release makes no secure-erasure claim.

Closes #18.

@flyingrobots

Copy link
Copy Markdown
Owner Author

Code Lawyer Activity Summary

# Priority Source Issue Commit RED Outcome
1 P1 Self Absent/recreated namespaces could reuse generation 1 and create an ABA hazard b9ee732 Generation contract omitted initial/root/liveness continuity Initial generations and retained empty namespace generations are explicit
2 P1 Self Multiple physical realizations had no deterministic selection authority eaa39d7 Contract omitted RetentionRealizationProfile Named versioned profile selects admitted witnesses canonically and fail-closed
3 P0 Self GC could mutate after revalidation without excluding publication/recovery ac2ba76 Contract omitted lock lifetime GC holds shared exclusive store writer authority through mutation and durability
4 P1 Self A realization profile could lawfully require zero witnesses 9f9ba36 Contract omitted a nonzero lower bound Every logical closure member requires an exact nonzero witness count
5 P1 Self Retention closure verification could straddle catalog publication 8123107 Contract omitted shared publication authority Retention holds the same writer authority through proof, commit, sync, and receipt

All five were resolved one at a time with deterministic RED → GREEN contract cycles and separate commits. Final local evidence is fully green: 4/4 new laws in debug and release; all workspace, strict Clippy, doctest, MSRV, fuzz-crate, 105-case debug/release crash-matrix, documentation, whitespace, deny, and audit gates passed.

@codex review please

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@flyingrobots, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 6 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: afdcb3aa-6325-446a-b65d-83c3e6149ea1

📥 Commits

Reviewing files that changed from the base of the PR and between 8123107 and 9953c23.

📒 Files selected for processing (2)
  • docs/adr/0009-retention-roots-release-and-gc-liveness.md
  • xtask/tests/retention_liveness_protocol_contract.rs

Summary by CodeRabbit

  • Documentation

    • Added ADR-0009 documenting retention roots, release semantics, liveness snapshots, garbage-collection boundaries, and evidence limitations.
    • Added ADR-0009 to the architecture decision record index.
    • Updated the unreleased changelog with the new design contract.
  • Tests

    • Added contract checks to verify that required retention and GC decisions remain documented and indexed.

Walkthrough

Changes

Retention and GC liveness contract

Layer / File(s) Summary
Retention roots and canonical closure
docs/adr/0009-retention-roots-and-gc-liveness.md, xtask/tests/retention_liveness_protocol_contract.rs
ADR-0009 defines retention namespaces, reconstruction anchors, verified canonical closure, bounded traversal, and fail-closed handling; tests assert the required terminology.
Retention transitions and GC evidence
docs/adr/0009-retention-roots-and-gc-liveness.md
The ADR specifies generation-checked transitions, protocol states, release semantics, immutable GC snapshots, receipts, and evidence nonclaims.
ADR publication and validation
docs/adr/README.md, CHANGELOG.md, docs/adr/0009-retention-roots-and-gc-liveness.md, xtask/tests/retention_liveness_protocol_contract.rs
The ADR is indexed and changelogged, while feature-gated tests validate metadata, fail-closed rules, snapshot constraints, alternatives, and evidence boundaries.

Estimated code review effort: 2 (Simple) | ~10 minutes

Poem

Roots are named, the closures shine,
Generations guard the line.
Snapshots hold what GC must know,
Receipts say what claims can show.
No silent drops, no phantom lore—
ADR-0009 guards the door.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: defining retention roots and GC liveness.
Description check ✅ Passed The description covers the required problem, invariant, approach, alternatives, failures, tests, compatibility, recovery, and security sections.
Linked Issues check ✅ Passed The ADR and tests cover the issue's scope: namespaces, generations, closure, release semantics, immutable GC snapshots, evidence, and rejected alternatives.
Out of Scope Changes check ✅ Passed The changes stay within ADR documentation, indexing, changelog, and contract tests; no unrelated implementation changes are present.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/adr/0009-retention-roots-release-and-gc-liveness.md`:
- Around line 96-102: Update the closure traversal and GC planning contract
described in the “Closure traversal” section to define implementation-enforced
hard ceilings for every caller-supplied resource limit, including roots, nodes,
depth, encoded bytes, and physical bytes inspected. Validate and reject any
request exceeding those ceilings before traversal or materialization begins,
while preserving the existing fail-closed behavior.
- Around line 79-94: Bind the exact RetentionRealizationProfile identity,
version, and digest into retained transition state, liveness snapshots, and
minimum receipt evidence. During revalidation and snapshot admission, require
the referenced profile to be available and exactly matching; reject unavailable
or mismatched profiles instead of resolving through the current registry entry.
Update the related namespace-generation and snapshot evidence paths
consistently.
- Around line 154-176: Revise the “State meanings” section to explicitly scope
Staged, Retained, and Released to candidate bytes or namespace generations, and
Orphaned and Collectible to physical material. Replace the “A path cannot move”
statement with a rule that these state transitions require the defined evidence
and cannot be inferred from existence, age, recent access, or absence from a
single catalog.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 04ae9b59-d76e-43e1-8e1d-4eb771334817

📥 Commits

Reviewing files that changed from the base of the PR and between fa105da and 8123107.

📒 Files selected for processing (4)
  • CHANGELOG.md
  • docs/adr/0009-retention-roots-release-and-gc-liveness.md
  • docs/adr/README.md
  • xtask/tests/retention_liveness_protocol_contract.rs
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
  • GitHub Check: Runtime fuzz smoke
  • GitHub Check: Documentation and workflow integrity
  • GitHub Check: Rust quality gates
🧰 Additional context used
📓 Path-based instructions (5)
docs/adr/**/*.md

📄 CodeRabbit inference engine (AGENTS.md)

Cross-subsystem decisions affecting identity, formats, durability, recovery, concurrency, GC, encryption, or public compatibility require a slugged ADR under docs/adr/, never a bare number.

Files:

  • docs/adr/README.md
  • docs/adr/0009-retention-roots-release-and-gc-liveness.md
**/*.{rs,toml}

📄 CodeRabbit inference engine (AGENTS.md)

Use stable, pinned Rust with edition 2024; cargo fmt --check and Clippy with -D warnings must pass.

Files:

  • xtask/tests/retention_liveness_protocol_contract.rs
**/*.rs

📄 CodeRabbit inference engine (AGENTS.md)

**/*.rs: Do not use unwrap, expect, panic!, todo!, unimplemented!, dbg!, stdout/stderr printing, unchecked indexing, lossy casts, or unsafe code. Unsafe requires a dedicated crate with documented invariants, tests, and measured necessity.
Use checked arithmetic for externally influenced values and TryFrom/try_from instead of potentially lossy as conversions.
Public functions must not take boolean parameters; use enums instead. Prefer typed newtypes for IDs, lengths, offsets, generations, and namespaces.
Parse and validate untrusted bytes before admitting them as trusted types; make illegal states unrepresentable where practical.
Prefer concrete types, synchronous core APIs, and traits only at real substitution boundaries; do not introduce async without demonstrated consumer need.
Do not let HashMap iteration order affect identity, serialization, tests, or behavior.
Use hexagonal architecture: domain and port modules own invariants and semantic capabilities, dependencies point inward, and core/ports must not import adapters, filesystems, networks, CLIs, runtimes, or application policy.
Keep codecs at ingress and egress boundaries. Ports exchange semantic or validated types, not serializer-owned JSON, CBOR, or wire values.
Keep files near 200 lines, review files over 300, and do not exceed 500; keep functions near 20 logical lines, review over 40, do not exceed 60; limit nesting to 3 and parameters to 5.
Do not create generic utils.rs, helpers.rs, common.rs, misc.rs, shared.rs, manager.rs, service.rs, types.rs, or models.rs; name files after the concept they own.
Keep items private by default; use pub(crate) unless external consumers require public visibility. Public validated types must have private fields and checked constructors, and consequential staged work, plans, commits, and results should use #[must_use].
Use Option for normal absence, typed errors by boundary, preserved error sources, and expected/observed state in...

Files:

  • xtask/tests/retention_liveness_protocol_contract.rs
**/*.{rs,json,cbor}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{rs,json,cbor}: Identity, persistence, comparison, tests, and protocol behavior must be deterministic and independent of iteration order, host state, clocks, locale, and serializer defaults.
Boundary JSON and CBOR must use a named canonical profile with golden fixtures; reject duplicate fields and noncanonical identity-bearing encodings. Hash only typed, domain-separated canonical bytes.

Files:

  • xtask/tests/retention_liveness_protocol_contract.rs
**/*.{rs,bin}

📄 CodeRabbit inference engine (AGENTS.md)

Durable formats must define magic bytes, versioning, canonical encoding, explicit endianness, bounds, checksums, and golden fixtures; reject trailing bytes, duplicate fields, noncanonical encodings, overflow, invalid ordering, excessive depth, and unknown mandatory flags. Do not use arbitrary Serde or Rust struct output as a durable format.

Files:

  • xtask/tests/retention_liveness_protocol_contract.rs
🧠 Learnings (2)
📚 Learning: 2026-07-27T22:37:16.896Z
Learnt from: flyingrobots
Repo: flyingrobots/keep PR: 49
File: src/layout/record_length.rs:29-29
Timestamp: 2026-07-27T22:37:16.896Z
Learning: This repository targets Rust 1.96 (per `Cargo.toml` `rust-version` and `rust-toolchain.toml`). When writing or reviewing Rust code, only use APIs/language features stabilized in Rust 1.96 or earlier. Avoid using newer std/library APIs that wouldn’t be available on Rust 1.96 (e.g., you may rely on `u64::is_multiple_of` since it’s stabilized by 1.96).

Applied to files:

  • xtask/tests/retention_liveness_protocol_contract.rs
📚 Learning: 2026-07-29T05:54:58.524Z
Learnt from: flyingrobots
Repo: flyingrobots/keep PR: 63
File: xtask/src/golden_file_worldline/b3sum_oracle.rs:15-21
Timestamp: 2026-07-29T05:54:58.524Z
Learning: In the flyingrobots/keep Rust codebase, prefer fallible conversions using `TryFrom`/`try_from` (e.g., `u64::try_from(payload.len())`) instead of potentially lossy `as` casts. If the chosen target architecture makes conversion failure logically unreachable, still keep the `TryFrom`-based conversion per repository policy, and do not require fabricated negative-test cases solely to cover an unreachable defensive failure path.

Applied to files:

  • xtask/tests/retention_liveness_protocol_contract.rs
🔇 Additional comments (5)
docs/adr/0009-retention-roots-release-and-gc-liveness.md (1)

1-78: LGTM!

Also applies to: 104-153, 177-192, 200-219, 228-240, 242-305

xtask/tests/retention_liveness_protocol_contract.rs (2)

1-2: LGTM!

Also applies to: 5-106


3-3: 📐 Maintainability & Code Quality

No change needed here.

CI runs cargo test --workspace --all-features for both debug and release profiles, so this repository-tasks-gated test module is enabled by the coverage path.

docs/adr/README.md (1)

63-63: LGTM!

CHANGELOG.md (1)

306-311: LGTM!

Comment thread docs/adr/0009-retention-roots-release-and-gc-liveness.md Outdated
Comment thread docs/adr/0009-retention-roots-release-and-gc-liveness.md Outdated
Comment thread docs/adr/0009-retention-roots-release-and-gc-liveness.md Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 81231078d8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docs/adr/0009-retention-roots-release-and-gc-liveness.md Outdated
Comment thread docs/adr/0009-retention-roots-release-and-gc-liveness.md
Comment thread docs/adr/0009-retention-roots-release-and-gc-liveness.md
Comment thread docs/adr/0009-retention-roots-release-and-gc-liveness.md Outdated
Comment thread docs/adr/0009-retention-roots-release-and-gc-liveness.md Outdated
Comment thread docs/adr/0009-retention-roots-release-and-gc-liveness.md Outdated
Comment thread docs/adr/0009-retention-roots-release-and-gc-liveness.md Outdated
Comment thread docs/adr/0009-retention-roots-release-and-gc-liveness.md
Comment thread docs/adr/0009-retention-roots-release-and-gc-liveness.md
@flyingrobots

Copy link
Copy Markdown
Owner Author

Review Remediation Activity Summary

# Priority Source File Commit RED GREEN / outcome
1 P1 CodeRabbit docs/adr/0009-retention-roots-release-and-gc-liveness.md 62cae09 Contract omitted exact profile identity/version/digest Namespace generations, snapshots, revalidation, and receipts bind the exact canonical profile coordinate and refuse unavailable/mismatched profiles
2 P1 CodeRabbit docs/adr/0009-retention-roots-release-and-gc-liveness.md 006579c Caller limits had no implementation maximum Versioned hard ceilings cap roots, nodes, depth, encoded bytes, and physical bytes before traversal/materialization
3 P2 CodeRabbit docs/adr/0009-retention-roots-release-and-gc-liveness.md 327a779 State subjects mixed logical retention with physical GC material Logical and physical state families now have explicit disjoint subjects; path observations cannot imply transitions

Each finding was resolved in its own RED → GREEN commit. Consolidated verification passed: strict xtask Clippy; contract 4/4 in debug and release; source-structure and documentation-refusal checks; pinned markdownlint-cli2 0.23.2 documentation integrity; whole-history whitespace; clean worktree.

@codex review please

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 327a77915b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread docs/adr/0009-retention-roots-release-and-gc-liveness.md
Comment thread docs/adr/0009-retention-roots-release-and-gc-liveness.md Outdated
Comment thread docs/adr/0009-retention-roots-release-and-gc-liveness.md
@flyingrobots

Copy link
Copy Markdown
Owner Author

Self-audit finding

Priority File Evidence Infraction Required mitigation
P1 docs/adr/0009-retention-roots-release-and-gc-liveness.md Generation continuity says “Version 1 does not delete or reuse namespace identity,” while the same ADR explicitly refuses retention state in keep.segment-store/v1 and assigns it to keep.segment-store/v2. Protocol-version contradiction Add a deterministic contract assertion that namespace continuity belongs to version 2, correct the ADR, and rerun the focused contract plus documentation gates.

@codex Please confirm this protocol-version correction during the replacement-head review.

@flyingrobots

Copy link
Copy Markdown
Owner Author

Additional self-audit finding

Priority File Evidence Infraction Required mitigation
P1 docs/adr/0009-retention-roots-release-and-gc-liveness.md The immutable snapshot and revalidation sections bind root, manifest, and catalog generation-plus-digest coordinates, while the retention receipt still records only generations. Evidence-contract mismatch Add a failing contract assertion for root, global-manifest, and catalog generation-plus-canonical-digest receipt coordinates; strengthen the receipt and physical-claim wording; rerun the focused contract and documentation gates.

@codex Please verify that the replacement head makes receipt evidence as exact as the snapshot it proves.

@flyingrobots

Copy link
Copy Markdown
Owner Author

Activity Summary — replacement head a5f9dfe

Source Priority File Finding Commit Outcome
Codex P0 ADR-0009 GC could retire record spans inside immutable segments bcb8efb Whole-segment liveness and compaction-successor law pinned
Codex P0 ADR-0009 Segment unlink could precede catalog retirement c5265ea Durable catalog successor now precedes every unlink
Codex P0 ADR-0009 Recovery-protected artifacts lacked explicit disposition 6c22f84 Durable finalize-or-retire receipt required
Codex P0 ADR-0009 GC mutation lacked crash-state and retry protocol 7453b40 Intent, ordered sync, receipt, and idempotent recovery defined
Codex P1 ADR-0009 Retention artifacts conflicted with the exact v1 root shape bd8dbb5 Versioned v2 namespace and one-way recovery-safe migration defined
Codex P1 ADR-0009 Permanent namespace tombstones had no total bound 6fca251 Fixed admission ceiling refuses before persistent staging
Codex P1 ADR-0009 Snapshot roots and catalog were generation-only f6b54d1 Full generation-plus-digest coordinates required
Codex P1 ADR-0009 Historical retry could report current success 55aa9ed Already-committed succeeds only while exact successor is current
Self P1 ADR-0009 Namespace continuity was assigned to forbidden v1 state 7a2fb0f Rule corrected and pinned to version 2
Self P1 ADR-0009 Retention receipts were weaker than snapshot evidence a5f9dfe Root, manifest, and catalog receipt digests required

Each item used an isolated RED → GREEN contract-test cycle and its own commit. Final local evidence: cargo fmt --all --check; strict xtask Clippy; focused contract 4/4 in debug and release; source-structure check; documentation-refusal check; pinned markdownlint-cli2 0.23.2, lychee 0.21.0, and actionlint 1.7.12 documentation-integrity check; branch and whole-history whitespace checks; no Python sources; ADR 493/500 lines. Worktree clean and branch exactly matches the pushed head.

@codex review please — confirm the exact replacement head a5f9dfea1f55dc623c3e6c684cef4f23b6c9c91c.

@flyingrobots

Copy link
Copy Markdown
Owner Author

Self-audit finding — unpublished replacement slice

Priority File Evidence Infraction Required mitigation
P2 docs/adr/0009-retention-roots-release-and-gc-liveness.md The local reader-fence remediation produced a 501-line ADR; Keep sets 500 lines as an absolute maximum. This commit has not been pushed. Structural hard-limit breach Add a deterministic <= 500 line-count law, demonstrate RED at 501, tighten redundant prose without changing semantics, and keep that guard in the contract suite.

@codex Please include the permanent size guard in the replacement-head review.

@flyingrobots

Copy link
Copy Markdown
Owner Author

Activity Summary — second replacement head 9953c23

Source Priority Finding Commit RED Outcome
Codex P1 Active readers had no observable GC safety-fence lifecycle 356033a Contract omitted ReaderFence, acquisition order, lifetime, and drain law v2 readers take shared reader.lock before HEAD; GC takes writer authority then the exclusive reader lock and retains both through durable retirement
Self P2 Reader-fence prose crossed the 500-line hard maximum 9e788bf Exact line-count test failed at 501 Permanent <= 500 law added; redundant prose tightened; ADR is exactly 500 lines
Codex P1 A catalog successor could invalidate a currently retained closure a1c2e56 Contract omitted retained-root validation during catalog publication Candidate catalog now proves every current retained closure before HEAD replacement and binds the preserved manifest coordinate
Codex P2 Ordinary anchors were incorrectly claimed to retain physical representations 9953c23 Contract omitted the representation expressiveness boundary Specific representation requires a future typed extension; only a distinct LayoutId can use its own anchor

Each issue used a deterministic RED → GREEN cycle and a separate commit. Final local evidence on 9953c23ca5067d01b845fbb02f214b78492b65ee: strict xtask Clippy; focused contract 5/5 in debug and release; source-structure check; documentation-refusal check; pinned documentation-integrity check; branch and whole-history whitespace; pure-Rust tracked-source inventory; 500/500 ADR size law. Worktree clean and branch equals the pushed head.

@codex review please — review this exact replacement head.

@flyingrobots
flyingrobots merged commit 57fa4ee into main Jul 30, 2026
5 checks passed
@flyingrobots
flyingrobots deleted the adr/retention-roots-gc-liveness branch July 30, 2026 01:34

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9953c23ca5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +180 to +183
Before replacing `HEAD`, version-2 catalog publication holds that authority,
admits the current global retention manifest, and verifies every current
retained closure against the candidate catalog with its exact profile and
limits. Candidate publication refuses before mutation when closure evidence is

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Persist closure limits with retained generations

When a caller admits a root with limits below the protocol ceilings, this new catalog-publication check requires the candidate to verify that closure with its exact limits, but the durable namespace generation described at lines 111–114 stores only the profile coordinate and anchors. After restart there is therefore no authoritative value for publication to use: choosing current request/default limits can accept or reject the same catalog successor differently. Bind the admitted limits into each namespace generation and its digest so this validation is reproducible.

AGENTS.md reference: AGENTS.md:L38-L40

Useful? React with 👍 / 👎.

Comment on lines +332 to +334
Planning is observational and carries no mutation authority. A version-2 reader
takes a kernel-managed shared lock on persistent `reader.lock` before opening
`HEAD`. Its admitted snapshot owns a `ReaderFence` that retains that lock for

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Verify both sides lock the same reader-fence inode

If the reader.lock directory entry is replaced after a reader acquires its shared lock but before GC opens the entry, the reader and GC can hold locks on different inodes; GC then obtains its supposedly exclusive fence and may unlink a segment still needed by that reader. Persistence and lock lifetime alone do not prevent this filesystem race, so both acquisition paths must open without following links and verify after acquisition that the locked device/inode is still the canonical admitted entry, refusing any drift.

AGENTS.md reference: AGENTS.md:L80-L81

Useful? React with 👍 / 👎.

Comment on lines +362 to +365
- the current catalog successor that names none of the candidates;
- the admitted segment-pool identity; and
- the exact candidate segment digests, lengths, and verification evidence in
canonical segment-digest order.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Define retirement for superseded metadata generations

With repeated catalog or retention updates, old catalogs, namespace generations, and global manifests become unreachable, but this execution protocol authorizes only the segment-digest candidates recorded in the intent. Those immutable metadata artifacts are not segments and no other retirement transition is defined for them, so even a single bounded namespace can grow the store without bound until publication fails for lack of space. Add a bounded, crash-safe liveness and retirement protocol for superseded metadata artifacts, or explicitly include typed metadata retirement units in GC.

Useful? React with 👍 / 👎.

Comment on lines +163 to +169
Every namespace has an immutable `RootGeneration`. A transition supplies:

1. the exact `RetentionNamespace`;
2. an expected state of either absent or one exact `RootGeneration`;
3. the complete candidate anchor set; and
4. one exact `RetentionRealizationProfileId`; and
5. explicit closure-admission limits.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Compare the expected root digest in retention CAS

When a client retries against a restored or forked store whose current namespace has the same RootGeneration but different canonical bytes, this request shape treats the states as equal because its expectation contains only the generation. The transition can then replace a root the client never observed and later permit collection of its closure; require the expected state to include the root's canonical digest (and compare the complete coordinate) rather than relying on generation alone.

AGENTS.md reference: AGENTS.md:L7-L9

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ADR: define retention roots, release, and GC liveness

1 participant