Observed behavior: Preliminary project metadata reads bypass the final route writer's owner and single-link validation. ensureProjectDirForIdentity reads through readBoundedRegularFile with only allowedRoot/maxBytes at src/daemon/project.ts:384-388, then may copy existing fields into a replacement. SQLite factory project opening invokes this default path at src/storage/sqlite/factory.ts:93-95 before compact reaches its final timestamp writer.
Expected behavior: Define and enforce owner/single-link policy before existing metadata bytes are consumed by preliminary project initialization. Preserve new-project discovery and deliberate malformed-metadata recovery semantics; do not simply suppress all factory metadata writes.
Root cause: Preliminary initialization does not supply expectedUid or requireSingleLink. Final compact/ingest writer hardening in #888 does not cover this earlier stage.
Safe reproduction: In a worker-private project fixture, supply an owner-local hard-linked metadata file and exercise ensureProjectDirForIdentity with a differing canonical cwd. Assert the preliminary reader currently accepts the link and propagates its fields. Deterministic mocks may cover mismatched owner; no live daemon, production HOME, or privileged mutation is needed.
Review context: Bug #888 planning GLM/Grok/Opus, baseline cfb8242; final-writer-only repair. Final-writer repair: #1011. Separate native Bug outside Epic968 frozen S1; not a claimed #888 resolution. Audit sibling preliminary reader in worktree-reconciliation.ts while scoping its own remediation.
Environment:
- Agent: Codex Astra Bug888 owner with GLM/Grok/Opus planning review
- Connector: static repository inspection
- OS: Fedora Linux
Observed behavior: Preliminary project metadata reads bypass the final route writer's owner and single-link validation.
ensureProjectDirForIdentityreads throughreadBoundedRegularFilewith only allowedRoot/maxBytes at src/daemon/project.ts:384-388, then may copy existing fields into a replacement. SQLite factory project opening invokes this default path at src/storage/sqlite/factory.ts:93-95 before compact reaches its final timestamp writer.Expected behavior: Define and enforce owner/single-link policy before existing metadata bytes are consumed by preliminary project initialization. Preserve new-project discovery and deliberate malformed-metadata recovery semantics; do not simply suppress all factory metadata writes.
Root cause: Preliminary initialization does not supply expectedUid or requireSingleLink. Final compact/ingest writer hardening in #888 does not cover this earlier stage.
Safe reproduction: In a worker-private project fixture, supply an owner-local hard-linked metadata file and exercise ensureProjectDirForIdentity with a differing canonical cwd. Assert the preliminary reader currently accepts the link and propagates its fields. Deterministic mocks may cover mismatched owner; no live daemon, production HOME, or privileged mutation is needed.
Review context: Bug #888 planning GLM/Grok/Opus, baseline cfb8242; final-writer-only repair. Final-writer repair: #1011. Separate native Bug outside Epic968 frozen S1; not a claimed #888 resolution. Audit sibling preliminary reader in worktree-reconciliation.ts while scoping its own remediation.
Environment: