Skip to content

fix(cli): check names an anchor that belongs to another project - #886

Merged
blafourcade merged 3 commits into
nextfrom
fix/telemetry-check-foreign-anchor
Sep 21, 2026
Merged

blafourcade merged 3 commits into
nextfrom
fix/telemetry-check-foreign-anchor

Conversation

@blafourcade

Copy link
Copy Markdown
Contributor

What

aidd telemetry check graded hook fired FAIL whenever the anchored session left no run file in this project — including for a session that never ran here. The anchor is inherited: any process nested inside a Claude Code session sees CLAUDE_CODE_SESSION_ID, whatever directory it runs in, so a check run from a shell another project's session spawned was told the chain was broken when it was not.

The claim now answers the third state it already models: an anchor decidably another project's reads unknown, naming that project. fail keeps its meaning — this project's own session ran and the hook wrote nothing.

How

  • anchorProjectElsewhere (cli/src/contexts/telemetry/domain/session-project.ts) compares what the sink holds for the anchor against the projects this project's own run files name.
  • Two values are compared only when the same field named them: project_id is a directory name, project_remote a URL, and both are live on a real machine (31507 records naming project_remote, 7 naming project_id in my own sink). Across the two, a match would read as a mismatch.
  • One record naming a project this project's run files also name settles the session as ours, whatever the others say.
  • The sink is asked only about an anchor that left no run file here, and only when a run file here names a project at all. No new port, no new wiring: readRecordsForVendor was already on TelemetrySink and the sink already injected into DiagnoseTelemetryUseCase.
  • The new branch is read before the Codex trust gate: local trust state says nothing about another project's session.

Limitation, stated rather than hidden

The sink decides it only when it holds figures for that anchor — a session whose project was never read locally is still undecidable, and falls through to today's fail. Strict improvement: nothing that used to be graded correctly changes, and no new unknown is produced from a guess.

Evidence

Tests were written first and watched fail for the reason they name:

× names the other project the anchored session belongs to, rather than failing
  → expected 'fail' to be 'unknown'
× prefers the other project over an untrusted Codex hook
  → expected 'untrusted-codex-hook' to be 'anchor-in-another-project'

The user's own scenario, against the built binary (cli/dist/cli.js), in a throwaway repository whose remote is acme/widgets, with a stored record placing session s-foreign under acme/other:

  hook fired            --    this session belongs to git@github.com:acme/other.git, not to this project — its stored figures name that project, and nothing here is evidence about its hook. The newest run file here is from 2026-09-16T03:30:54Z

Same tree, an anchor no stored record places, and the project's own session:

  hook fired            FAIL  this session left no run file — the newest one is from 2026-09-16T03:30:54Z
  hook fired            ok    1 run file(s), most recent session_start 2026-09-16T03:30:54Z

Gates: pnpm lint, pnpm typecheck, check-cli-type-honesty, pnpm test (6261 passed), pnpm knip, all green. node scripts/run-mutation.mjs --changed origin/next scores the changed lines 97.7 (77 before the guards were given cases that see them); the two survivors are a type narrowing the field filter makes unobservable.

tests/architecture/comments.arch.test.ts's src baseline is raised 4471 → 4481, with its reason recorded in that file as the guard's own convention requires.

Fixes #872

🤖 Generated with Claude Code

blafourcade and others added 3 commits September 18, 2026 15:58
`hook fired` graded FAIL whenever the anchored session left no run file
here, including for a session that never ran in this project: the anchor is
inherited by any process nested inside a session, whatever directory it runs
in, so a `check` run from a shell another project's session spawned was told
the chain was broken when it was not.

The stored records already decide it. `anchorProjectElsewhere` compares what
the sink holds for the anchor against the projects this project's own run
files name, and the claim reads `unknown`, naming that project, instead of
`fail`. `fail` keeps its meaning: this project's own session ran and the hook
wrote nothing.

Two values are compared only when the same field named them — `project_id`
is a directory name, `project_remote` a URL — so an anchor no stored record
places, or places by a field this project never used, decides nothing and
falls through to the verdict it already had.

Fixes #872

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
AIDD-Session-Id: 58b68db5-0bfc-485b-aefa-1fcb609ac8f7
A run file in another project is not something this command read; the stored
figures naming that project are. The wording says that, and the details suite
pins it word for word like every other claim's.

Refs #872

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
AIDD-Session-Id: 58b68db5-0bfc-485b-aefa-1fcb609ac8f7
`run-mutation --changed` scored the new lines 77: the sink was asked for the
anchor in every case the tests could see, so the two guards that keep it from
being asked — an anchor this project journalled itself, and a project no run
file here names — were indistinguishable from nothing. The double now records
which vendors it was asked about, and the cases assert it was asked none.

The domain cases were comparing a record the field filter already dropped,
never `projectOfRecord` itself; they now name a project by both fields so the
record reaches it. Score 97.7, the two survivors being a type narrowing the
field filter makes unobservable.

Refs #872

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
AIDD-Session-Id: 58b68db5-0bfc-485b-aefa-1fcb609ac8f7
@blafourcade
blafourcade marked this pull request as ready for review September 21, 2026 04:01
@blafourcade
blafourcade requested a review from a team as a code owner September 21, 2026 04:01
@blafourcade
blafourcade merged commit 1333e32 into next Sep 21, 2026
37 checks passed
@aidd-bot aidd-bot Bot mentioned this pull request Sep 24, 2026
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.

1 participant