Observed behavior: Reconciliation can replace a journal that becomes unsafe after the locked read and before an inner recovery write. At before-source-patterns-merge, create a hard link to the current journal or change its mode from 0600 to 0644, then throw a generic observer error. The inner blocked-state recording writes a new 0600 inode over the journal pathname without authenticating the existing leaf. The pathname's original bytes and inode are lost in the mode case; an external hard link retains the original inode in the link case, but the journal pathname no longer exposes that evidence.
Expected behavior: Authenticate the current journal leaf and its admitted identity before replacing it during recovery; refuse unsafe/changed leaves without overwriting their inode or bytes. Preserve the primary failure and recording failure together, retaining the journal-parent authority and one-attempt contract. Initial absent journal publication must remain safe.
Root cause: throwAfterBlockedRecording sets recording attempted and invokes writeJournal; the latter uses parent-authenticated atomicWritePrivateFile but does not authenticate its destination leaf before rename. The outer authenticated reread is then skipped because recording was attempted.
How to reproduce: Use the hermetic linked-worktree reconciliation fixture with a legacy source pattern. After its planned journal is published, at before-source-patterns-merge save the journal inode/bytes, create a fixture hard link or chmod only that fixture to 0644, and throw a generic error. Calling public reconcileWorktrees replaces the journal with phase=blocked. Assert the pathname's original inode/bytes/mode/link count: both variants fail. The source owner ran the two public-seam reproductions against candidate 3971ac0 and baseline 7c19172; both fail identically. The candidate worktree remained unchanged.
Severity: P2. This is inherited late-write behavior and incomplete leaf hardening, requiring same-owner journal-directory mutation during an attempt. It does not parse unsafe bytes, publish a malicious map, or overwrite the external hard-link alias. The unsafe-mode case does discard the original journal inode from the namespace.
Origin: Follow-up to #1109 and #1107, PR #1149. External review thread on PR #1149 ("Authenticate the journal before the first recovery write") and candidate round-three review/independent Daybreak validation. Outside the frozen S5 campaign scope; preserve as independently actionable follow-up. The original fix authenticates journal readers; this report concerns the later recovery writer, not a duplicate of reader admission.
Environment:
- Agent: Codex Daybreak Blue high validation, Astra owner
- Connector: CLI/public reconciliation seam
- OS: Fedora Linux; Node 25.9.0; Vitest 4.1.10
Observed behavior: Reconciliation can replace a journal that becomes unsafe after the locked read and before an inner recovery write. At
before-source-patterns-merge, create a hard link to the current journal or change its mode from 0600 to 0644, then throw a generic observer error. The inner blocked-state recording writes a new 0600 inode over the journal pathname without authenticating the existing leaf. The pathname's original bytes and inode are lost in the mode case; an external hard link retains the original inode in the link case, but the journal pathname no longer exposes that evidence.Expected behavior: Authenticate the current journal leaf and its admitted identity before replacing it during recovery; refuse unsafe/changed leaves without overwriting their inode or bytes. Preserve the primary failure and recording failure together, retaining the journal-parent authority and one-attempt contract. Initial absent journal publication must remain safe.
Root cause:
throwAfterBlockedRecordingsets recording attempted and invokeswriteJournal; the latter uses parent-authenticatedatomicWritePrivateFilebut does not authenticate its destination leaf before rename. The outer authenticated reread is then skipped because recording was attempted.How to reproduce: Use the hermetic linked-worktree reconciliation fixture with a legacy source pattern. After its planned journal is published, at
before-source-patterns-mergesave the journal inode/bytes, create a fixture hard link or chmod only that fixture to 0644, and throw a generic error. Calling publicreconcileWorktreesreplaces the journal with phase=blocked. Assert the pathname's original inode/bytes/mode/link count: both variants fail. The source owner ran the two public-seam reproductions against candidate 3971ac0 and baseline 7c19172; both fail identically. The candidate worktree remained unchanged.Severity: P2. This is inherited late-write behavior and incomplete leaf hardening, requiring same-owner journal-directory mutation during an attempt. It does not parse unsafe bytes, publish a malicious map, or overwrite the external hard-link alias. The unsafe-mode case does discard the original journal inode from the namespace.
Origin: Follow-up to #1109 and #1107, PR #1149. External review thread on PR #1149 ("Authenticate the journal before the first recovery write") and candidate round-three review/independent Daybreak validation. Outside the frozen S5 campaign scope; preserve as independently actionable follow-up. The original fix authenticates journal readers; this report concerns the later recovery writer, not a duplicate of reader admission.
Environment: