Skip to content

docs: live Claude lineage capture and signed-in proofs replace the scripted stand-in - #436

Merged
ScriptedAlchemy merged 7 commits into
mainfrom
docs/claude-live-lineage-capture
Sep 3, 2026
Merged

docs: live Claude lineage capture and signed-in proofs replace the scripted stand-in#436
ScriptedAlchemy merged 7 commits into
mainfrom
docs/claude-live-lineage-capture

Conversation

@ScriptedAlchemy

@ScriptedAlchemy ScriptedAlchemy commented Sep 3, 2026

Copy link
Copy Markdown
Owner

Summary

Redo everything PR #421 had to do against a scripted Anthropic Messages API stand-in, now against the real model (Claude Code 2.1.257 / claude-sonnet-5). The real ~/.claude was read-only throughout and its file mtimes are unchanged.

  • Live capture — two live examples/host-test captures replace the stand-in fixture: fixtures/host-lineage/claude-2.1.257.ndjson (root spawns a background subagent, which spawns a nested one) and claude-2.1.257-foreground.ndjson (foreground spawns). probe:uninstall claude removed the isolated home and workspace; verified.
  • Authentication — the harness's byte-for-byte .credentials.json copy had expired (claude auth statusloggedIn: false), so the isolated home's credentials file was re-seeded with the operator's long-lived claude setup-token token by a one-off local step outside the checked-in harness. No credential-reading code was added to the repo: examples/host-test is unchanged from main. Both audit notes state this.
  • Stand-in vs live diff (docs/audits/2026-09-03-host-lineage-matrix.md §8): every Claude-column claim held — root ↔ child via SubagentStart/Stop agent_id + shared root session_id, MCP correlation via _meta["claudecode/toolUseId"] = the open PreToolUse tool_use_id, depth 2 nesting. Differences: live hook payloads carry effort (and permission_mode) the stand-in lacked; the Agent PostToolUse.tool_response is an array [{type:'text',…}] naming the child in agentId and reports async_launched for background spawns vs completed for foreground; background_tasks[] lists only background subagents; the model uses ToolSearch before deferred tools; nested subagents run and are attributed correctly. No lineage/projection code change was needed — lineage-registry.test.ts now runs against both live fixtures and asserts the agentId/status shapes.
  • Signed-in proofs (docs/audits/2026-09-03-claude-live-session-proofs.md): pnpm test:host-install:session:claude pass 2/2; pnpm test:packed:native:claude pass 8/8 after two harness fixes; native-claude-contract.test.ts signed-in leg 17/18 — the smoke's own evidence is a clean pass but runNativeClaudeSmoke reports claude-native.normal-home.changed because it digests .claude.json, which Claude Code 2.1.257 rewrites on every real turn. Filed as native-claude-contract: normal-home guard digests .claude.json, which Claude Code 2.1.257 rewrites on every signed-in turn #439 (the test file is owned by the concurrent determinism lane).
  • Fixes: pnpm test:packed:native:{claude,codex} now call scripts/run-packed-native-smoke.mjs (under pnpm, pack --json is a bare object and install --omit=dev is rejected, so the proof never reached a host); the packed smoke's Claude leg guards settings + plugins instead of the whole home (normalHome: 'settings-and-plugins-unchanged'), with a unit test.
  • Capability table claude-2.1.250.json evidence on the lineage.* rows now reads "live model 2026-09-03, Claude Code 2.1.257"; emitted output and adapterRevision unchanged. Changeset: .changeset/claude-live-lineage-evidence.md (patch).

Evidence

  • Live capture provenance: claude -p in /tmp/host-test/claude-home, Claude Code 2.1.257, 2026-09-03 16:55Z and 17:02Z; env.names show no ANTHROPIC_*.
  • Fixture counts (re-verified by script): primary 48 rows = 42 hook + 6 MCP, PostToolUse 6 string / 10 object; foreground 51 rows = 46 hook + 5 MCP, 5 string / 14 object.
  • Real home untouched: ~/.claude/.credentials.json 05:34Z, settings.json 08:12Z, plugins/installed_plugins.json 08:12Z, ~/.claude.json 08:23Z — all before the first isolated turn.
  • Proof counts and exact assertions: docs/audits/2026-09-03-claude-live-session-proofs.md.

Test plan

Review status

  • Codex auto-review and the first @codex review request answered "usage limits reached"; later requests produced reviews of dd5991fb5 (3 threads), dc2c5239a (1 thread), ac1489c2b ("no major issues"), and the final head c2f30e537 ("no major issues", summary cites the SHA). Two more threads came from the parallel retry lane.
  • All six threads answered: the probe.mjs/README auth-fallback commit is dropped (lane-rule thread, docs-locale P1, 0600 P2), the fixture counts are corrected (both count threads), and the proofs note describes the packed-smoke environment filter by its actual patterns (P2).
  • No unreviewed SHAs. Merged on green CI after rebasing onto fix(doctor): validate the Cursor hooks document the manifest names (#438) #442.

@changeset-bot

changeset-bot Bot commented Sep 3, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: c2f30e5

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
agent-bundle Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits. You can see your limits in the Codex usage dashboard.

@ScriptedAlchemy

Copy link
Copy Markdown
Owner Author

@codex review

ScriptedAlchemy added a commit that referenced this pull request Sep 3, 2026
@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, add credits to your account and enable them for code reviews in your settings.

@pkg-pr-new

pkg-pr-new Bot commented Sep 3, 2026

Copy link
Copy Markdown
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle@436
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle/create-agent-bundle@436
npm i https://pkg.pr.new/ScriptedAlchemy/agent-bundle/@agent-bundle/runtime@436

commit: c2f30e5

Comment thread examples/host-test/scripts/probe.mjs Outdated
* `subscriptionType`). The token is written only into the isolated home and
* never logged; `probe:uninstall` removes it with the home.
*/
const transplantClaudeAuth = (config) => {

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Lane-rule conflict (from the parallel Claude-recapture retry lane, not Codex): the shared lane rules for this task say "Do not write any new code that reads or copies sign-in state; if the existing harness cannot start a signed-in isolated session, fall back to … and say so." transplantClaudeAuth reads ~/.claude/.claude_code_oauth_token and writes it into the isolated .credentials.json, so this commit (feat(host-test): authenticate isolated Claude homes with the long-lived setup token…) is exactly what the rule forbids, and examples/host-test/README.md now documents it as harness behaviour.

Requested change: drop this commit (restore probe.mjs / README.md to origin/main, keeping the byte-for-byte copyOpaque only), and state in the matrix header row, §7 gap row, and docs/audits/2026-09-03-claude-live-session-proofs.md that the isolated home was re-seeded by hand, outside the checked-in harness, because the harness copy had expired (claude auth statusloggedIn: false; the operator's normal configuration failed the same way, so the documented fallback was unavailable). The fixtures themselves are fine to keep — they are real Claude Code 2.1.257 / claude-sonnet-5 runs.

If this PR merges before that lands, the retry lane will open the revert + wording fix as a follow-up on docs/claude-live-capture.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

A ready-made version of this fix is on branch docs/claude-live-capture (head 61b394a919ceb1ae78611b4b6fb00676cafea4c3, based on origin/main at #435): it carries this PR's four non-harness commits (fixtures + replay test, packed-native fix, audits, changeset) unchanged, no probe.mjs/README.md change, and one extra commit docs(audits): state the by-hand Claude sign-in seeding and correct the live fixture counts that also fixes the numbers in the other thread and cites the live model on every Claude lineage capability row. Cherry-picking that commit onto this branch after dropping 578e30500 should apply cleanly. The .claude.json contract-guard defect is filed as #439.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Done in dc2c523: the branch is now your docs/claude-live-capture head (61b394a) plus one docs commit — examples/host-test is byte-identical to origin/main, the four non-harness commits are unchanged, and your correction commit is included. I tightened two sentences so the notes say exactly what happened: the isolated .credentials.json was re-seeded by a one-off local, uncommitted edit of probe:install (discarded afterwards), and no turn was run against the real home — claude auth status on the normal configuration already reported loggedIn: false, which is why the documented fallback was unavailable. #439 is linked from the proofs note.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Done in dc2c523: the branch is now your docs/claude-live-capture head (61b394a) plus one docs commit — examples/host-test is byte-identical to origin/main, the four non-harness commits are unchanged, and your correction commit is included. I tightened two sentences so the notes say exactly what happened: the isolated .credentials.json was re-seeded by a one-off local, uncommitted edit of probe:install (discarded afterwards), and no turn was run against the real home — claude auth status on the normal configuration already reported loggedIn: false, which is why the documented fallback was unavailable. #439 is linked from the proofs note.

| Child events carry the root `session_id` and their own `agent_id`, never a parent | Every subagent and nested hook payload in both runs | Held |
| MCP correlation via `_meta["claudecode/toolUseId"]` = the open `PreToolUse` `tool_use_id` | Three probes per run, one per depth, all equal; still exact when two MCP calls ran in parallel | Held, strengthened |
| Depth 2 reachable; `subagent_stats.max_depth: 2` | Both runs | Held |
| `PostToolUse` `tool_response` is a string for MCP tools, an object otherwise | 6 strings / 10 objects (primary), 6 / 13 (*fg*) | Held |

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Re-verified both live fixtures independently (node over fixtures/host-lineage/claude-2.1.257*.ndjson); three numbers in this file are off:

  • §3 / §8: the foreground fixture has 5 MCP PostToolUse string payloads and 14 object payloads (rows 13, 14, 27, 28, 45 are strings), not "6 / 13". It has 5 MCP records because the nested agent called only probe.
  • §5 "Can a plugin … know its parent/root": the foreground fixture has 46 hook payloads, so "all 42 + 45 hook payloads" should read 42 + 46 (the capability JSON's "88 hook payloads" is already right).
  • §3 request.lineage at depth 1 also resolved on row 43 and on fg rows 10 (depth 0) and 26 (depth 1); neither live nested agent called dump, so depth 2 lineage is only exercised by the replay test — worth saying.

Also worth a note on the SubagentStop row: row 40 (the nested agent's SubagentStop) lists aebe95… in background_tasks[], which happens to be its parent, only because that parent was a running background task; nothing marks it as a parent.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Confirmed by an independent recount (primary: 42 hook + 6 MCP, 6 string / 10 object PostToolUse; foreground: 46 hook + 5 MCP, 5 string / 14 object) and fixed in dc2c523 via your correction commit: §3 and §8 now read 5 / 14 for fg, §5 reads 42 + 46, the MCP-correlation row lists rows 11, 29, 43 and fg 10, 26 and says depth 2 dump lineage is exercised only by the replay test, and the SubagentStop row carries the row-40 note that aebe95… appears only because the parent was a running background task.

@ScriptedAlchemy

Copy link
Copy Markdown
Owner Author

@codex review

ScriptedAlchemy added a commit that referenced this pull request Sep 3, 2026
@ScriptedAlchemy
ScriptedAlchemy force-pushed the docs/claude-live-lineage-capture branch from 4c7b8ce to dd5991f Compare September 3, 2026 19:23
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 3, 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-09-03T20:28:58.337939Z c2f30e5 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.

@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: dd5991fb54

ℹ️ 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 examples/host-test/README.md Outdated
Comment on lines +71 to +75
`CLAUDE_CONFIG_DIR`, or `CODEX_HOME` pointed at the isolated home. For Claude,
when the copied `.credentials.json` is missing or its `expiresAt` has passed
(the only field read) and `~/.claude/.claude_code_oauth_token` from
`claude setup-token` exists, the isolated credentials file carries that
long-lived token instead — still the real model, still never the real home;

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 Add the host-test flow to both documentation locales

This changes the user-facing host-test example's probe:install claude authentication behavior, but only its README is updated; a repo-wide search under website/docs/{en,zh} finds no host-test, setup-token, or probe lifecycle coverage. Add matching English and Chinese site documentation so the published Rspress site describes the new fallback.

AGENTS.md reference: AGENTS.md:L24-L30

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Resolved by removal in dc2c523: the probe:install claude behaviour change is dropped, so the README is back to main and there is no new host-test flow to document on the site.

| Host | Root | Parent |
| --- | --- | --- |
| Claude | Yes — `session_id` on every event is the root session | Only through the runtime's registry (inferred at `SubagentStart`); nothing in the child's payload |
| Claude | Yes — `session_id` on every event is the root session (re-verified live: all 42 + 45 hook payloads across both runs carry the root id, `CLAUDE_CODE_SESSION_ID` in every plugin process is the root id) | Only through the runtime's registry (inferred at `SubagentStart`); nothing in the child's payload |

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 Correct the foreground hook count

The foreground fixture contains 46 hook-event records (51 total records minus 5 MCP records), so this 42 + 45 statement accounts for only 87 events and conflicts with the newly added capability evidence claiming 88. Change the second count to 46 so the audit matches its checked-in source evidence.

AGENTS.md reference: AGENTS.md:L31-L34

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in dc2c523: the §5 count now reads 42 + 46 (= the 88 hook payloads the capability evidence cites); the foreground fixture has 51 rows = 46 hook events + 5 MCP records.

Comment thread examples/host-test/scripts/probe.mjs Outdated
scopes: Array.isArray(session.scopes) ? session.scopes : ['user:inference', 'user:profile'],
...(typeof session.subscriptionType === 'string' ? { subscriptionType: session.subscriptionType } : {}),
},
}), { mode: 0o600 });

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 Force restrictive permissions on the replacement token

When an expired .credentials.json exists, copyOpaque has already created destination with the source file's mode. Node applies writeFileSync's mode only when creating a file, so a restored or migrated credentials file with mode 0644 remains 0644 after its contents are replaced with the long-lived setup token. Explicitly chmod the destination or recreate it atomically with mode 0600 to avoid exposing that credential to other local users.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Moot as of dc2c523: the setup-token fallback commit is dropped entirely (see the lane-rule thread), so probe.mjs is unchanged from main and no replacement credentials file is written by the harness.

@ScriptedAlchemy
ScriptedAlchemy force-pushed the docs/claude-live-lineage-capture branch from dd5991f to dc2c523 Compare September 3, 2026 19:40
@ScriptedAlchemy

Copy link
Copy Markdown
Owner Author

@codex review

@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: dc2c5239a3

ℹ️ 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 +40 to +43
- The `packedNativeEnvironment` allowlist strips every credential-shaped
variable name (`*TOKEN*`, `*KEY*`, …), so a `CLAUDE_CODE_OAUTH_TOKEN`
environment transplant would not reach the host; the on-disk credentials
file is the only route these proofs can authenticate through.

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 Narrow the claimed environment-variable filtering

The stated *KEY* guarantee does not match credentialEnvironmentKey in packages/agent-bundle/tests/support/packed-native-smoke.ts: its regex recognizes apikey and several token/secret patterns, but generic credential names such as SSH_PRIVATE_KEY or AWS_ACCESS_KEY_ID remain in the environment. This makes the audit overstate the isolation provided by the signed-in proof; either expand the filter to cover the documented pattern or describe only the patterns actually removed.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed in ac1489c: the note now lists the patterns credentialEnvironmentKey actually removes (apikey, apitoken, authtoken, accesstoken, authorization, credential, password, secret, token, plus NODE_PATH and the alternate-provider names) and says explicitly that generic names such as AWS_ACCESS_KEY_ID are not filtered. The conclusion is unchanged: CLAUDE_CODE_OAUTH_TOKEN matches token, so the on-disk credentials file is the only authentication route. Left the filter itself alone — widening it is a test-support change outside this docs lane.

@ScriptedAlchemy

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Chef's kiss.

Reviewed commit: ac1489c2bd

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

… only Claude settings and plugins across a real turn
…e live fixture counts

The checked-in host-test harness copies ~/.claude/.credentials.json
byte-for-byte and nothing else; the expired session meant the two live
captures and the signed-in proofs ran from an isolated home whose
credentials file was re-seeded by hand with the operator's setup token.
Say so in the matrix header, gap table, and proofs note instead of
describing a harness fallback that does not exist. Fix the foreground
fixture's counts (5 string / 14 object PostToolUse payloads, 46 hook
payloads), list every row where request.lineage resolved, and note that
row 40's background_tasks entry is the parent only by coincidence. Cite
the live model as provenance on every Claude lineage capability row.
@ScriptedAlchemy
ScriptedAlchemy force-pushed the docs/claude-live-lineage-capture branch from ac1489c to c2f30e5 Compare September 3, 2026 20:24
@ScriptedAlchemy

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Bravo.

Reviewed commit: c2f30e5379

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

@ScriptedAlchemy
ScriptedAlchemy merged commit 11847a5 into main Sep 3, 2026
13 checks passed
@ScriptedAlchemy
ScriptedAlchemy deleted the docs/claude-live-lineage-capture branch September 3, 2026 20:38
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