Skip to content

fix(core): complete a prepared binding change only under the exclusive admission - #1035

Merged
qnbs merged 9 commits into
mainfrom
feat/445-gate4e-e2c-exclusive-recovery
Oct 13, 2026
Merged

qnbs merged 9 commits into
mainfrom
feat/445-gate4e-e2c-exclusive-recovery

Conversation

@qnbs

@qnbs qnbs commented Oct 13, 2026 •

Copy link
Copy Markdown
Owner

User description

Depends on #1033. This PR was stacked on #1033's branch for review and now targets main, as docs/PR-CI-MERGE-WORKFLOW.md requires before a base PR is merged (a stacked PR gets no hosted CI). Until #1033 lands, the diff includes #1033's six commits; the E2c delta is the last two commits (81a7c353, bff6e34b). #1033 stays open with its P2-B thread until this is proven; the merge order needs the owner's final merge admission. delete_branch_on_merge=false; no branch is deleted.

What

Closes the defect recorded in GH #359 comment 6151082206 (Codex P2-B on #1033): a phase transition that a crash stops after the anchor was prepared was completed by recover_root under whatever lock its caller held, including the shared admission of an ordinary operation.

  • recover_root completes a prepared root only when it keeps the binding of the committed root (including none to none). A prepared root that changes the binding is refused as BindingChangeNeedsExclusiveRecovery before any directory sync, pointer write or anchor write, and stays prepared.
  • New recover_root_exclusive takes the root event of the exclusive admission by type (AdmittedRootCommitGuard<'_, ExclusiveAdmission>) and completes any authenticated target. A compile_fail doctest (shared event) pairs with one that compiles.
  • The shared operation path maps the refusal to the existing OperationError::RecoveryPending and writes nothing.
  • begin_conversion, the only exclusive entry, resolves a pending preparation through the exclusive recovery before it reads the journal. It now takes the provider as &mut P; the test call sites changed accordingly.
  • The classification compares the committed root with the prepared target, both authenticated against the anchor's digests. It is the binding, not the phase: the phase would need the journal locator, which is not admitted.

Scope as admitted: GH #359 comment 6151692274.

Evidence

  • Hosted CI is the authority. Locally, one job at a time: cargo clippy --all-targets -D warnings, cargo fmt --check, and the full test suite of the crate (all passing), including the new tests below.
  • Red without the change, green with it (checked by neutralizing the refusal and, separately, the gate's resolution): the reproduction from the defect record, the pointer case, the ordinary-operation case and the classification matrix fail without the refusal; the conversion test fails with PreparationPending without the gate's resolution.
  • New tests (gate4e_phase_transition_test/crash_recovery.rs, faulty_fs.rs): the reproduction with a snapshot of root files, journal names and anchor before and after a refused shared recovery; the crash points (before and after the anchor prepare, a slot that was never written, a pointer that never moved, an ambiguous commit); the classification (none to a binding, one binding to another, a binding to none refused; an unchanged binding and none to none complete); a held shared admission stopping the exclusive recovery; an ordinary operation refused with RecoveryPending without a write; and, in gate4d_conversion_entry_test.rs, the gate resolving the root a crash left prepared in enter_convert.
  • Existing gate3c, gate4a, gate4b and conversion tests are unchanged except for the &mut provider argument of begin_conversion.
  • Review follow-up in bff6e34b: recover_root_exclusive resolves the root to its canonical path once (Codex P1, with a Unix test that is red without it), and the duplicated test sequence is shared (CodeScene).

Not in scope

Journal locator, E3 and capture writers, PREPARE/DONE windows, a phase-precise classification, any change to the C to F commit protocol, Gate 5 and later, release.

Part of #359. Owner: #922 / QNB-168.

Summary by CodeRabbit

  • New Features

    • Migration phase changes can be committed through a dedicated transition requiring exclusive access to the admitted storage root.
    • Conversion startup can resolve a pending prepared-root recovery under exclusive access before reading the migration journal.
  • Bug Fixes

    • Ordinary checkpoints reject phase changes, while phase transitions reject updates that keep the same phase.
    • Shared recovery refuses prepared roots that change the migration binding without modifying stored data; exclusive recovery can complete them.

CodeAnt-AI Description

Require exclusive access for migration phase changes and recovery

What Changed

  • Phase changes can no longer be published as ordinary progress checkpoints; they require exclusive access.
  • Ordinary operations leave a prepared root binding change untouched and report recovery pending. Exclusive recovery can complete it, and conversion resolves it before reading the journal.

Impact

✅ Phase changes wait until ordinary operations finish
✅ Interrupted phase changes recover under exclusive access
✅ Ordinary operations stop safely while recovery is pending

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

qnbs added 7 commits October 13, 2026 16:30
…sion (#445)

A phase change ends the window in which one phase admitted what the next one
forbids, so it cannot be published while an ordinary operation may be in flight.
Until now only the conversion gate held that by type; the public checkpoint and
binding advance accepted a phase change from any caller.

commit_phase_transition takes the installation's ExclusiveAdmissionGuard by mutable
borrow, so a shared guard does not compile, and commits the root below that
admission. An admission that does not guard the root of its layout is refused as
NotAdmitted before anything is read.

The progress checkpoint, the binding advance and the journal-level checkpoint publish
now refuse a successor that changes the phase (PhaseChangeNotACheckpoint), and the
transition refuses one that keeps it (NotAPhaseChange), each before a journal byte is
written. The root classifies the advance with a new BindingStep::PhaseTransition, so a
generation promoted directly becomes authoritative only through the transition.
Capture, renewal and takeover keep their own relations.

The conversion driver's two phase changes use the held form of the transition; its
behaviour is unchanged. Existing tests that moved the phase through the checkpoint are
migrated: the root-binding fixture picks the path by the committed phase, and the
binding-advance scenario keeps the phase of its bootstrap revision.

This adds no producer of a binding, opens no PREPARE/DONE window and leaves the capture
writers, the writer journal locator and E3 closed.
…lusive event type (#445)

The admitted root event now carries the mode of the admission it was taken from
(AdmittedRootCommitGuard<'_, Mode>). The held form of the transition takes the exclusive
event, so a shared admission or a bare root lock cannot reach it; a compile_fail doctest on
try_root_commit pairs with one that compiles. Both routes to the held form, the public
commit and the conversion driver, hand it the event of their exclusive admission.

commit_phase_transition resolves the root to its canonical path once, when the admission is
proven, and uses that path for every read and write of the commit. An alias that is retargeted
after the proof can no longer redirect the commit to another root: a test points the alias at
a second root during the call and asserts the admitted root advanced and the other one is
untouched, and a second test refuses an alias that already leads to another root before
anything is written. Both are Unix-only because they need a symbolic link.

The test helper that bundled a checkpoint takes the journal source as one argument instead of
five.
…attempt (#445)

CodeScene counts the receiver, so the helper that runs a transition over a chosen file system
under a chosen spelling of the root had five arguments. The two now travel as one value; the
helper takes four and the tests are unchanged.
…wn module (#445)

CodeScene reports Low Cohesion for the test file once it holds the fixture, the manifest
builders, the transition cases and a hook file system with its alias cases. The alias cases
are a separate responsibility, so they move to a module file included like the submodules of
gate2_identity_test. No test changed.
The raw commit_root publishes whatever live-migration binding it is given. The relation of a
changed binding to the committed one (phase, owner, inventory, lease) is proven only by the
authority commits, so a caller with a bare root lock could still name a directly promoted
phase change and bypass the exclusive transition.

commit_root is now exported only with the test-only test-support feature, like load_catalog and
list_records. The production publications (the authority commits and write_key_epoch) call the
crate-private commit_root_primitive, so nothing changes for them and for bootstrap and recovery.
Tests keep the raw commit as scaffolding for states that have no production producer yet, such as
the binding that a later finalization will clear.

A first attempt to refuse a changed binding at run time broke exactly such a test and would still
be bypassed by clearing and rebinding, so the restriction is the visibility of the primitive.
…ecord the open recovery point (#445)

publish_phase_transition_fenced without a committed predecessor reached the journal write for the
bootstrap revision, because the successor relation was skipped when nothing was committed. A bootstrap is
no phase change: the publisher now refuses it as NotAPhaseChange before any journal I/O, and the regular
publisher keeps the bootstrap. A test asserts the refusal leaves the journal directory empty and that the
regular publisher still writes generation 0 afterwards.

The contract, the evidence and the rustdoc no longer say that the transition is the only way a phase change
becomes authoritative. It is the only way to start one in the production crate. A transition that a crash
interrupts after the anchor was prepared is completed forward by recover_root, which asks for no exclusive
admission; that is recorded as open instead of claimed closed.
…e admission (#445)

A phase transition that a crash stops after the anchor was prepared left a prepared root that
recover_root completed under whatever lock its caller held, including the shared admission of an
ordinary operation. The exclusive admission that began the transition was long gone, so the
exclusivity the transition claims did not extend to its completion.

recover_root now completes a prepared root only when it keeps the binding of the committed root
(including a root that binds nothing). A prepared root that changes the binding is refused as
BindingChangeNeedsExclusiveRecovery before any directory sync, pointer write or anchor write, and stays
prepared. The classification compares the committed root with the prepared target, both authenticated
against the anchor's digests; it is the binding and not the phase, because the phase would need the
journal locator, which is not admitted.

recover_root_exclusive takes the root event of the exclusive admission by type and completes any
authenticated target. The shared operation path maps the refusal to RecoveryPending and writes nothing.
begin_conversion, the only exclusive entry, resolves a pending preparation through the exclusive recovery
before it reads the journal; it now takes the provider by mutable reference, so the tests that call it
pass &mut.

The tests pin the reproduction from the defect record (red without the change), the crash points
(before and after the anchor prepare, a slot that was never written, a pointer that never moved, an
ambiguous commit), the classification of none/some/other/cleared bindings, the exclusion by a held
shared admission, the ordinary operation refused with RecoveryPending without a write, and the
conversion gate resolving the root a crash left prepared in enter_convert.

No journal locator, no E3 writer, no PREPARE/DONE window, no change of the C-F commit protocol.
@sourcery-ai

sourcery-ai Bot commented Oct 13, 2026

Copy link
Copy Markdown

Sorry @qnbs, you've used your own review budget of 250,000 diff characters for the last 7 days.

You can request another review in 1 day and 9 hours by commenting @sourcery-ai review. Upgrade to get a review now.

@vercel

vercel Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
worldscript-studio Ready Ready Preview Oct 13, 2026 8:04pm UTC

@coderabbitai

coderabbitai Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: qnbs/WorldScript-Studio/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: a1f71d46-573d-4734-9cd0-00791fee5f9d
📥 Commits

Reviewing files that changed from the base of the PR and between bff6e34 and a31cd40.

📒 Files selected for processing: 1
  • CHANGELOG.md
🚧 Files skipped from review as they are similar to previous changes: 1
  • CHANGELOG.md

Included review availability: This review used your included allowance. 0 included reviews remain after this review. Your included PR review attempts over the past 7 days set your current allowance at 1 review per hour.

📝 Walkthrough

Journal checkpoints now preserve phase, while phase transitions require exclusive admission. Shared recovery refuses prepared roots with changed migration bindings. Exclusive recovery can complete them, and conversion startup resolves pending preparation before reading the journal.

Changes: Secure-storage phase control

Layer / File(s) Summary
Journal checkpoint and transition rules
crates/worldscript-secure-storage/src/journal/*, crates/worldscript-secure-storage/tests/gate4d_journal_durable_test.rs, docs/native/r15/GATE4D-JOURNAL-DURABLE-EVIDENCE.md
Journal successor checks and fenced publishers distinguish same-phase checkpoints from phase-changing transitions. Tests and documentation cover the separate publication rules.
Exclusive phase-transition commit path
crates/worldscript-secure-storage/src/admission.rs, crates/worldscript-secure-storage/src/authority.rs, crates/worldscript-secure-storage/src/conversion.rs, crates/worldscript-secure-storage/src/lib.rs, crates/worldscript-secure-storage/tests/gate4d_root_binding_test.rs, crates/worldscript-secure-storage/tests/gate4e_phase_transition_test.rs, CHANGELOG.md
Admission events carry their mode in the type system. commit_phase_transition validates exclusive admission and uses the transition publisher and root commit. Conversion phase changes use this path. Tests cover phase rules, admission, and state preservation on refusal.
Binding-aware recovery and conversion startup
crates/worldscript-secure-storage/src/root_store.rs, crates/worldscript-secure-storage/src/operations.rs, crates/worldscript-secure-storage/src/conversion.rs, crates/worldscript-secure-storage/tests/gate4d_conversion_entry_test.rs, crates/worldscript-secure-storage/tests/gate4d_journal_route_test.rs, crates/worldscript-secure-storage/tests/gate4e_phase_transition_test/*, docs/native/R15-SECURE-STORAGE-CONTRACT.md, docs/native/r15/GATE4D-JOURNAL-DURABLE-EVIDENCE.md
Shared recovery refuses a prepared root with a changed migration binding; exclusive recovery can complete it. Conversion resolves pending preparation before journal reads. Tests cover interrupted commits, filesystem failures, admission contention, and aliases.

Priority: ➖ Normal

Merge Risk: ⚪ Minimal · up to a31cd

The supplied change adds changelog entries only, and no actionable merge-blocking risk is evident from it. The underlying recovery and transition code was not supplied for review.

- [ ] Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

@codeant-ai

codeant-ai Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

🤖 CodeAnt AI — Review Status

Status Commit Started (UTC) Finished (UTC)
✅ Incremental review completed a31cd40 Oct 13, 2026 · 20:03 20:04
✅ Reviewed your PR 81a7c35 Oct 13, 2026 · 18:17 18:23

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-13T20:52:51.061489Z a31cd40 Manual request
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@codeant-ai

codeant-ai Bot commented Oct 13, 2026

Copy link
Copy Markdown

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@sourcery-ai

sourcery-ai Bot commented Oct 13, 2026

Copy link
Copy Markdown

Reviewer's Guide

This PR closes the prepared-root recovery gap by making authenticated binding changes complete only through a typed exclusive-admission path, while shared recovery refuses without writing, ordinary operations surface RecoveryPending, and the conversion gate resolves pending preparations before journal access; extensive crash and classification tests document the resulting protocol.

Sequence diagram for exclusive recovery of a prepared binding change

sequenceDiagram
    participant Conversion as begin_conversion
    participant Admission as ExclusiveAdmissionGuard
    participant Recovery as recover_root_exclusive
    participant RootStore as RootStore
    participant Journal as CommittedJournal

    Conversion->>Admission: try_root_commit()
    Admission-->>Conversion: AdmittedRootCommitGuard<ExclusiveAdmission>
    Conversion->>Recovery: recover_root_exclusive(fs, provider, layout, event)
    Recovery->>RootStore: authenticate committed root and prepared target
    RootStore-->>Recovery: binding change accepted
    Recovery->>RootStore: sync directory and publish pointer/root
    Recovery-->>Conversion: recovery complete
    Conversion->>Journal: read_committed_journal(fs, provider, layout, source)
Loading

Sequence diagram for shared recovery refusal

sequenceDiagram
    participant Operation as OrdinaryOperation
    participant Recovery as recover_root
    participant RootStore as RootStore
    participant Admission as SharedAdmission

    Operation->>Admission: root_guard()
    Admission-->>Operation: RootCommitGuard
    Operation->>Recovery: recover_root(fs, provider, layout, held)
    Recovery->>RootStore: authenticate committed root and prepared target
    RootStore-->>Recovery: BindingChangeNeedsExclusiveRecovery
    Recovery-->>Operation: refusal before sync or write
    Operation-->>Operation: RecoveryPending
Loading

Flow diagram for prepared-root recovery admission

flowchart TD
    A[Prepared root detected] --> B{Prepared binding matches committed binding?}
    B -->|Yes| C[recover_root completes recovery]
    B -->|No, shared path| D[recover_root returns BindingChangeNeedsExclusiveRecovery]
    D --> E[Ordinary operation returns RecoveryPending]
    B -->|No, exclusive path| F[recover_root_exclusive completes recovery]
    F --> G[begin_conversion reads committed journal]
    E --> H[Preparation remains pending without writes]
Loading

File-Level Changes

Change Details Files
Restrict completion of prepared root binding changes to exclusive admission.
  • Classify committed and prepared roots by authenticated live-migration binding.
  • Make shared recovery refuse binding changes before synchronization or writes, leaving preparation pending.
  • Add typed exclusive recovery and compile-time coverage preventing shared admission use.
crates/worldscript-secure-storage/src/root_store.rs
crates/worldscript-secure-storage/src/lib.rs
crates/worldscript-secure-storage/src/authority.rs
Route pending recovery safely through operations and conversion entry.
  • Map shared recovery refusal to OperationError::RecoveryPending with no writes.
  • Resolve pending preparations under exclusive admission before reading the conversion journal.
  • Change begin_conversion and affected callers to use a mutable key provider.
crates/worldscript-secure-storage/src/operations.rs
crates/worldscript-secure-storage/src/conversion.rs
crates/worldscript-secure-storage/tests/gate4d_conversion_entry_test.rs
crates/worldscript-secure-storage/tests/gate4d_journal_route_test.rs
Add crash-recovery coverage for admission, durability, and binding classifications.
  • Test refused shared recovery snapshots, exclusive completion, crash points, missing slots, unmoved pointers, ambiguous commits, and held shared admissions.
  • Verify unchanged bindings complete under shared recovery while binding changes require exclusive recovery.
  • Verify ordinary operations write nothing and conversion entry resolves pending roots before journal reads.
crates/worldscript-secure-storage/tests/gate4e_phase_transition_test.rs
crates/worldscript-secure-storage/tests/gate4e_phase_transition_test/crash_recovery.rs
crates/worldscript-secure-storage/tests/gate4e_phase_transition_test/faulty_fs.rs
crates/worldscript-secure-storage/tests/gate4d_conversion_entry_test.rs
Update release notes and secure-storage contract documentation for the new recovery boundary.
  • Document exclusive recovery semantics, error mapping, authenticated binding classification, and unchanged out-of-scope protocol areas.
  • Record the new test evidence and conversion-gate behavior.
CHANGELOG.md
docs/native/R15-SECURE-STORAGE-CONTRACT.md
docs/native/r15/GATE4D-JOURNAL-DURABLE-EVIDENCE.md

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@codeant-ai

codeant-ai Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

🏁 CodeAnt Quality Gate Results

Commit: a31cd406
Scan Time: 2026-10-13 20:06:06 UTC

✅ Overall Status: PASSED

Quality Gate Details

Quality Gate Status Details
Secrets ✅ PASSED 0 secrets found
Duplicate Code ✅ PASSED 2.1% duplicated
SAST ✅ PASSED No security issues
Bugs ✅ PASSED Rating S: No bugs
IAC ✅ PASSED No IAC issues

View Full Results

@codeant-ai codeant-ai Bot added the size:XL This PR changes 500-999 lines, ignoring generated files label Oct 13, 2026
codescene-access[bot]

This comment was marked as outdated.

@codeant-ai

codeant-ai Bot commented Oct 13, 2026

Copy link
Copy Markdown

CodeAnt Nitpicks

1 code suggestion

1. If the root directory is renamed during recovery, path-based reads and writes can use its replacement and commit anchor state before the lost identity is noticed.

Race condition · crates/worldscript-secure-storage/src/root_store.rs:347

@codeant-ai

codeant-ai Bot commented Oct 13, 2026

Copy link
Copy Markdown

CodeAnt PR Risk: Low Risk

  • The PR appears safe to merge; prepared migration-binding changes are completed only under exclusive admission.
  • New tests cover shared recovery refusal, exclusive recovery completion, interrupted commits, and conversion-gate recovery.

Assessed commit: 81a7c353f618

@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: 81a7c353f6

ℹ️ 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 crates/worldscript-secure-storage/src/root_store.rs
…nd share the refusal check (#445)

recover_root_exclusive took the event of the exclusive admission but passed the caller's spelling of
the root to every later read, sync and write of the recovery. An alias retargeted after the event was
taken could then send them to another root while the anchor of the admitted installation is committed
or aborted. It now resolves the root to its canonical path once, as commit_phase_transition does, and the
lock is checked against that path. A Unix test points the alias at a second root during the recovery and
asserts that the admitted root is completed and the other tree is untouched; it fails without the change.

The two tests that assert "refused under a shared recovery, completed under the exclusive one" share one
helper instead of repeating the sequence.
@qnbs
qnbs changed the base branch from feat/445-gate4e-e2b-phase-transition-admission to main October 13, 2026 18:34
codescene-access[bot]

This comment was marked as outdated.

@github-actions

github-actions Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

[check-pr-size] PR size is over the hard tier (normal profile): 21 files, 2232 meaningful lines, 9 commits — limit ≤20 files / ≤1200 lines / ≤10 commits. Consider splitting into smaller, independently reviewable PRs.

@codecov

codecov Bot commented Oct 13, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

@qnbs

qnbs commented Oct 13, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

PR #1033 is closed unmerged and superseded: its six commits are part of
this stacked branch and land with the single protected squash of #1035.
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@codeant-ai codeant-ai Bot added size:XXL This PR changes 1000+ lines, ignoring generated files and removed size:XL This PR changes 500-999 lines, ignoring generated files labels Oct 13, 2026

@codescene-access codescene-access 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.

Gates Passed
3 Quality Gates Passed

See analysis details in CodeScene

Quality Gate Profile: The Bare Minimum
Install CodeScene MCP: safeguard and uplift AI-generated code. Catch issues early with our IDE extension and CLI tool.

@qnbs

qnbs commented Oct 13, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Swish!

Reviewed commit: a31cd406ad

ℹ️ 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".

@qnbs
qnbs merged commit 2f01b8e into main Oct 13, 2026
65 of 67 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL This PR changes 1000+ lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant