Repository navigation
Align code graph MCP server key with native client registrations - #834
seathatflowsinourveins wants to merge 3 commits into
Conversation
## Scope Add per-lane tool/API rates, separate estimated Claude/Codex costs, and gateway provider/model/outcome/HTTP-status panels to the existing cc-lanes dashboard. #848 already supplies the five collector dimensions on main; this PR has no collector YAML delta after its landing rebase. Host publication remains the CC's operation. - Base commit: `e450e378c6bf1b21dd0bb565812f84afe028bad5` (CC091807Z landing rebase). - Lane: `lane:foundation`. - Owned paths: `observability/lanes_dashboard.py`; generated plan `config/grafana-lanes.json`; the existing writer-identity test fixture; dated decision; own evidence registry entries. ## Pipeline exactness Dropped the old #851 `traces.span.metrics.*` statements from `transform/privacy`. They matched only direct OTLP metrics named `traces.span.metrics.calls/duration` entering the `metrics` pipeline. Gateway/Harbor connector output instead uses `metrics/spans` and `transform/metric_export_privacy`; it never passes through those statements. No reviewed shipped producer is bound to sending connector-named metrics through that direct OTLP metrics route. Main's collector YAML is retained byte-for-byte, including #848's five-dimension flow-form line and comment. Its existing export guard retains provider/model/status/outcome. The synthetic test follows that actual connector pipeline and proves dimension export, not causality from the dropped exceptions. ## SOTA sources - [open-telemetry/opentelemetry-collector-contrib@v0.162.0, spanmetricsconnector README](https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/v0.162.0/connector/spanmetricsconnector/README.md): additional dimensions and default `traces.span.metrics.calls/duration` names. [Main's processor/pipeline source](https://github.com/seathatflowsinourveins/native-agent-stack/blob/e450e378c6bf1b21dd0bb565812f84afe028bad5/evidence/artifacts/new-wsl-install-plan-20261002/config/otel.yaml#L86) establishes the exact routing and retained dimensions. - [open-telemetry/semantic-conventions-genai@06ec68e, client-inference.md](https://github.com/open-telemetry/semantic-conventions-genai/blob/06ec68e722c45a7218e23ea1bc1339fe4e21ecae/docs/gen-ai/client-inference.md): `gen_ai.provider.name`; current conventions are Development. - [diegosouzapw/OmniRoute@c1e30b7, routing/otel.ts:193](https://github.com/diegosouzapw/OmniRoute/blob/c1e30b7676975feb298b49eff6ff58923c04b89e/open-sse/services/routing/otel.ts#L193): vendor `omniroute.routing.status/outcome`, provider/model fields and absent lane/session parentage. Routing status is distinct from OTel `status.code`. - [openai/codex@9790114, cost emission](https://github.com/openai/codex/blob/979011409de0a60b52f179721948e65531d26144/codex-rs/otel/src/events/session_telemetry.rs#L368), [Claude Code monitoring](https://code.claude.com/docs/en/monitoring-usage#cost-counter), and [Prometheus rate/increase](https://prometheus.io/docs/prometheus/latest/querying/functions/#increase): reset-aware counter queries, micro-USD conversion, separate cost sources and interval-extrapolation limits. - Existing Grafana13.2.3/Loki3.7.8 native renderer and provisioning formats are reused. ## Evidence-class table | Claim | Evidence class | Command / receipt | | --- | --- | --- | | Dimension names, native cost contracts and processor ownership | source_review | Versioned sources above, immutable main/old-head inspection and dated correction below | | Generated dashboard matches source; existing publisher contracts remain passing | local_integration | Renderer check and 17 dashboard contract tests | | Native connector retains provider/status/outcome and merges equal groups | synthetic | Existing fixture sends four synthetic spans through main's connector pipeline; 3 exported groups have counts 2/1/1 | | Source publisher produces an exact copy; collector accepts it | local_integration | Repository `observability_config.py otel` into a temporary destination, then native `otelcol-contrib validate` | | Native query parsers accept the eight new targets | local_integration | Read-only Prometheus/Loki query APIs returned success; missing Codex-cost/gateway series remain unknown | | Deployed collector/gateway export and complete cost coverage | unverified | CC host publication/read-back; no host restart or configuration apply in this PR | ## Local commands run ```text python3 observability/ns2604_dashboards.py python3 observability/ns2604_dashboards.py --check rc=0 python3 -m unittest tests.test_ns2604_dashboards tests.test_j775_panel_contracts tests.test_observability_writer_identity -v rc=0; 43 collected, 39 passed, 4 optional pinned-Prometheus/promtool checks skipped NS2604_OBSERVABILITY_DATA=<temporary>/data python3 evidence/artifacts/new-wsl-install-plan-20261002/config/observability_config.py otel --source-root <checkout>/evidence/artifacts/new-wsl-install-plan-20261002/config --config-root <temporary>/config rc=0; published YAML matches source and named main byte-for-byte NS2604_OBSERVABILITY_DATA=<temporary>/data otelcol-contrib validate --config=<temporary>/config/otel.yaml rc=0; installed collector 0.162.0 python3 scripts/component_matrix.py --write python3 scripts/new_host_grand_list.py --write rc=0; no derived-report changes python3 scripts/validate.py rc=0 git diff --check rc=0 ``` ## Decision record `docs/decisions/2026-10-08-cc-lanes-rate-cost-gateway.md` records the corrected processor assumption. Costs are estimates with source-specific coverage. Codex provider enrichment is conditional; `increase()` is not an exact total or guaranteed lower bound. No zero fill is used for missing costs or gateway routing data. Gateway events lack lane/session parentage and are not assigned to client lanes. ## Host evidence No files under `evidence/hosts/` change, and no deployment acceptance is claimed. The existing native collector integration uses temporary configuration and loopback ports with synthetic input. The runtime lock, broker keys, live Grafana, services and gateway are untouched. ## Checklist - [x] No GitHub Actions changes. - [x] No secrets, new credentials, paid hosting or billing surface. - [x] Peer worktrees preserved; #834 retains its separate landing cue. - [x] Main registry taken; only own changed files re-registered last. - [x] Source-only scope respects the paper freeze and quiet window.
### Scope - What this PR changes, in one or two sentences: the secret-path guard's PreToolUse hook declares Claude Code 2.1.295's `onFailure: "block"` in both repository declarations, so a guard that can't start, times out or exits with an unexpected code blocks the Bash call instead of letting it through. A new test pins that the guard hooks carry the key and no other hook does. - Base commit: `9f7b38b23d15e47ceb6f68c6651b86088f621797` - Lane: `lane:foundation` - Owned paths touched: `.claude/settings.json`, `adoption/templates/claude.settings.template.json`, `adoption/new-wsl/client-config-map.json` (the guard entry's note), `tests/test_install_claude_profile.py`, `docs/decisions/2026-10-08-guard-hook-fails-closed.md`, `manifests/evidence.json` (hashes re-registered with `scripts/host_receipts.py` `register_file`) ### SOTA sources - [anthropics/claude-code `CHANGELOG.md` at `602df92bf481ed904533e95c09f740f40aab5aed`](https://github.com/anthropics/claude-code/blob/602df92bf481ed904533e95c09f740f40aab5aed/CHANGELOG.md#L5), entry `2.1.295`, line 5: "Added `onFailure: "block"` for command and HTTP hooks: a hook that can't start, times out, or exits with an unexpected code blocks the action instead of letting it through". The file's SHA256 is `c0b1f9aa313a8021d863ec0053c047b0acc792d74e04af9c7741d3ecd23c3d1a`, the same bytes as `main` when read on 2026-10-08. - The installed Claude Code 2.1.295 client (binary SHA256 `4503bfe11a6c7fcc1e0b39b5e0d347c04248f750b03b0977b3ad6b531fe6f358`). Its hook schema declares `onFailure` on command and HTTP hooks. Its runner skips the key on `async` and `asyncRewake` command hooks and ignores it on `Stop`, `SubagentStop`, `TaskCompleted` and `TeammateIdle`. - [Claude Code hooks reference](https://code.claude.com/docs/en/hooks.md), read 2026-10-08: "Other exit codes" (only exit 2 blocks without the key; exit 1 is a non-blocking error) and "Disable or remove hooks" (`--settings '{"disableAllHooks": true}'` for one run; file edits are normally picked up by the file watcher). The page does not document `onFailure` yet. ### Changed existing test expectations None. One test method is added: `tests/test_install_claude_profile.py` `SecretGuardProfileTests.test_only_the_secret_guard_hook_fails_closed`. It walks every command hook in `.claude/settings.json` and in every JSON file under `adoption/`. Every hook that runs `secret_path_guard.py` must carry `onFailure: "block"`, no other hook may carry the key, and both known declarations must be found. No existing assertion changed. ### Evidence-class table | Claim | Evidence class | Command / receipt | | --- | --- | --- | | With the key on the hook entry, a PreToolUse Bash hook that exits 3, is not found (127) or times out blocks the call. Without the key, the call runs. On the matcher group the key does nothing, and a hook that exits 0 is unaffected. | `native_proven` | Ten `claude -p --model claude-haiku-5-5 --strict-mcp-config` runs on this host, 2026-10-08 22:13Z to 22:48Z: cases A to J in the decision record, with transcript hashes | | The key also works from a `--settings` file; a user settings file has the same hook shape | `native_proven` / `source_review` | Cases I and J; the user scope was not run, because a probe must not edit the live user settings | | Client 2.1.294 loads the file, ignores the key and runs the call | `native_proven` | Case B run with the 2.1.294 binary | | Only the guard hooks carry the key | `local_integration` | New test method; four mutations each fail it (either guard without the key, `rtk` with it, effort guard with it), and the files were restored byte for byte | | A new-WSL render writes the key on the guard hook only | `local_integration` | `new_wsl_client_config.py --render --host example --out <scratch>`: rc 0; `settings.json` has the key on the guard and on none of the other 15 command hooks | | `apply_claude_settings.py` does not carry the key to a host that already runs the guard | `local_integration` | `merge_settings` run against an existing-host base and an empty base (see open points) | ### Local commands run ``` $ timeout 600 python3 -m unittest tests.test_install_claude_profile # rc 0, Ran 110, OK (skipped=1) $ timeout 600 python3 -m unittest tests.test_adoption_docs_consistency # rc 0, Ran 39, OK (skipped=1) $ timeout 600 python3 -m unittest tests.test_new_wsl_client_config # rc 0, Ran 228, OK $ timeout 600 python3 -m unittest tests.test_apply_claude_settings # rc 0, Ran 53, OK $ timeout 600 python3 -m unittest tests.test_workflow_policy # rc 0, Ran 29, OK $ timeout 600 python3 -m unittest tests.test_upstream_surface_watch # rc 0, Ran 114, OK (skipped=6) $ timeout 600 python3 -m unittest tests.test_credential_status # rc 0, Ran 48, OK $ timeout 600 python3 -m unittest tests.test_task_model_routing # rc 0, Ran 10, OK $ timeout 900 python3 scripts/validate.py # rc 0, {"hashed_files": 10901, "status": "passed"} $ python3 scripts/evidence_manifest.py --check # rc 0 $ python3 -B tools/adoption/new_wsl_client_config.py --render --host example --out <scratch> # rc 0 ``` The first six modules were run again at the committed head, with the same results. ### Decision record [`docs/decisions/2026-10-08-guard-hook-fails-closed.md`](docs/decisions/2026-10-08-guard-hook-fails-closed.md). It holds the sources, the evidence table and the risk: a broken guard now blocks every Bash call, and the guard's median run time was 74 to 87 ms against its 10 s timeout. It also notes the SchemaStore schema (no `onFailure`, `additionalProperties: false`) and the inverse: delete the key, or for one run pass `--settings '{"disableAllHooks": true}'`. ### Open points - **Existing hosts.** `tools/adoption/apply_claude_settings.py` merges hooks by command and keeps the existing hook object. On a host that already runs the guard, applying this template therefore leaves the live hook without the key. A new host and a new-WSL build do get it. On an existing host the live change is one key added by hand to the guard's PreToolUse `Bash` hook object. Changing the merge contract is a separate change. - **Minimum client.** The key needs Claude Code 2.1.295. Older clients ignore it and keep failing open. - **One SocratiCode registration (the brief's second change) is not in this PR, by coordinator ruling.** On this host Claude Code skips the plugin's server because the user-scope entry has the same command line, so each Claude session connects one SocratiCode server. The standing decision (`docs/decisions/2026-10-07-clean-upstream-install-finalizes-a-candidate.md:150-152`) pairs the plugin with that entry. The repository lags that host state: - `adoption/mcp/claude-user.json` still declares the older command form. - The map's `claude/mcp/server/socraticode` row cites a 1.15.0 path. - No template enables the plugin or sets `SOCRATICODE_SPEC`. Drafts #776, #810 and #834 touch the same file. This is an open item for a single owner, to be assigned by the coordinator. ### Host evidence Not applicable: no file under `evidence/hosts/` changes. ### Checklist - [x] New/changed GitHub Actions are pinned to a full commit SHA with a version comment (no floating tags). (No workflow change.) - [x] New/changed workflows declare top-level `permissions: {}` and grant each job only what it needs (`contents: read`, or an explicitly justified addition). (No workflow change.) - [x] No secrets are printed, logged or committed; no new required secret was added without a documented owner. - [x] No new paid hosting, subscription or billing surface was introduced. - [x] Peer-owned untracked files and worktrees were preserved (not deleted, moved or overwritten). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
Superseded by #1034, as the command center ruled on 2026-10-12 (fold this draft into the MCP template reconciliation, or rebase it onto it; not both). #1034's first commit carries this draft's rename (its commit |
…emory-mcp Carries the rename of draft #834 (its commit 6c6d817) onto current main: the typed registration key and tool namespace in the Claude and Codex templates, the client-config map, the token-lane carriers, the child-usage accounting and the tests that pin them. The instruction sources no longer name the server on main, so the instruction copies and their byte pins need no change and the draft's four-byte trim is not carried. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…emory-mcp Carries the rename of draft #834 (its commit 6c6d817) onto current main: the typed registration key and tool namespace in the Claude and Codex templates, the client-config map, the token-lane carriers, the child-usage accounting and the tests that pin them. The instruction sources no longer name the server on main, so the instruction copies and their byte pins need no change and the draft's four-byte trim is not carried. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ey, promptfoo and a drift report (#1034) * Register the code graph MCP server under the vendor's name codebase-memory-mcp Carries the rename of draft #834 (its commit 6c6d817) onto current main: the typed registration key and tool namespace in the Claude and Codex templates, the client-config map, the token-lane carriers, the child-usage accounting and the tests that pin them. The instruction sources no longer name the server on main, so the instruction copies and their byte pins need no change and the draft's four-byte trim is not carried. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Wire the promptfoo MCP server for Claude Code in the new distribution's template promptfoo mcp --transport stdio from the installed package of the manifest's promptfoo slot (Promptfoo 0.123.1), with the distribution's own state directory and telemetry and the update check off, as the host registers it. Registered for Claude Code only: the Codex entry forwards a gateway key by name and is a separate decision. The client-config map gains the piece, the record its dated counts (403 pieces, 363 wired), and the tests that pin the rendered server list, the installing slots and the stub registration list expect it. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Add a read-only report of where the MCP templates and the live registrations differ tools/adoption/mcp_template_drift.py renders the new-WSL templates in process with the functions of new_wsl_client_config.py --render, reads the user scope of Claude Code and the mcp_servers tables of Codex, and prints one row per client and server (SAME, DIFFERS with its fields, TEMPLATE-ONLY, LIVE-ONLY) without any env, header, URL userinfo or query value. adoption/new-wsl/mcp-drift-acknowledged.json lists the 12 differences the decision record accepts; an entry that no longer matches a row fails the run. The record carries the measurement, the jcodemunch admission-gate result, the four-route Origin and Host table and the specification citations. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Register the reconciliation files in the evidence manifest Last commit of the change: the rows of every file it adds or changes, at their final bytes. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Print no registration value in the MCP drift report; contain acknowledgement sources; apply the ecosystem root to Codex; call the code graph server by its registered name Four blockers of the first reads of #1034 (Astra at 6a7a7ce and the open review threads), one commit: - Credential-bearing arguments reached both output formats (28 of 28 checks over seven forms, two clients, two formats). A description is now built from names, counts and fixed words: option names, scheme://host, a command's file name, environment and header names; every other argument, and a URL's userinfo, port, path and query, is the placeholder <withheld>. Values are still compared in memory. Names that do not have the shape of a name are withheld too. Tests: the seven forms x two clients x two formats, 300 seeded random values at every position, option-name look-alikes, odd names. - Acknowledgement sources accepted /etc/passwd and ../x. A source is now a relative path to a regular file beneath the repository: absolute paths and `..` are refused and symlinks are resolved before the containment check. - --eco-root (and ECO_INSTALL_ROOT) reached the Claude renderer only, so Codex kept the default prefix (six false DIFFERS rows). The root is set in the host values of the shared render. Test: a non-default prefix renders in both clients and compares SAME from the option and from the environment. - The renamed example registers only `codebase-memory-mcp`, but the published calls selected `codebase-memory.<tool>`, which MCPorter rejects (openclaw/mcporter@e4cb0022 src/cli/call-command.ts L309-346, src/runtime.ts L229-235). The calls in manifests/stack.json, recipes/README.md, docs/token-efficiency-stack.json, the saturation audit and the foundation-memory catalog now select the registered name; the transcript classifiers keep the old alias for sessions recorded before the rename. Test: tests/test_mcporter_selectors.py resolves each published selector against the example. catalogs/landscape/final-stack.json is regenerated from the changed manifests/stack.json (python3 scripts/final_stack.py --write; its digest line is the only change). The evidence rows of the changed files are re-registered at their final bytes. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Count arguments in the MCP drift report, end a malformed registration with exit 2, withhold a URL that holds an @, and correct the record Fix wave 2 of #1034, on 4916d3a: the Codex review threads of 4916d3a, the second GPT read (blockers 1 and 2) and the command center's full read (two blockers, six stale claims, P3-a to P3-f). - A token that looks like an option can be a value: the operand of a short option (`-k --x`), a positional value after `--`, the credential in `--api-key --secret-token`. The shape of a token cannot decide what may be printed (CPython Lib/argparse.py L1964 and L2503 at v3.12.3, and Lib/getopt.py, return such tokens as values), so arguments are counted ("2 args") and never shown, on both sides of a row. - A malformed number reached float(), whose ValueError quotes the value with %R (CPython Objects/floatobject.c, float_from_string_inner: v3.12.3 L190-193, v3.13.16 L183-186), and main() caught only DriftError, so the traceback printed it and the exit code was 1. A field of an unexpected shape (a non-numeric timeout, a list that is a string, a table that is a list, a Codex mcp_servers that is not a table) now ends the run with exit 2 and a message that names the server and never the value. - A userinfo that holds an unescaped `/`, `?` or `#` parses as the host (CPython Lib/urllib/parse.py urlsplit, v3.13.16 L472), so a URL that holds an `@` anywhere, a port that does not parse, or a scheme or host of another shape is withheld whole; the transport is one of stdio, http, sse (else withheld); paths are printed relative to the home; a read error names the kind of error, not its text. - recipes/README.md ran `mcporter ... list codebase-memory`, which works only through MCPorter's auto-correction: it names the registered key, and the selector test scans `list SERVER` too. - The decision record states the installed promptfoo (0.124.0 on the first host, pinned 0.123.1), SocratiCode's launcher per client, the four promptfoo tools that only read local state (run_assertion and validate_promptfoo_config do not) and the 2026 transport locator (L58-L61); the property test names the positions it covers. Fail-first: the final tests (37) give 45 failures and 10 errors against the implementation of 4916d3a and 82 failures and 26 errors against 6a7a7ce, and pass here; 29 of 29 mutants killed. The evidence rows of the changed files are updated. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Withhold a rejected acknowledgement source in the drift report, place the port in its property test, end three more unreadable inputs with exit 2, and say which shapes the checks name Fix wave 3 of #1034, on cecf039 (the rebased head of the second fix wave): Astra's delta read (~/.cache/ns2604-gpt-reads/fix2-pr1034-cecf039f9/VERDICT.md, one P1) and the command center's Claude micro read (pr1034-claude-micro-cecf039f.md: B2 and P3-1, P3-2, P3-3, P3-5; B1, B3, B4 and P3-4 are claims of the PR body and are corrected there). - P1 (Astra): the refusal of an acknowledgement source interpolated the rejected value with `!r`, so a path of the account, or a malformed object holding a token, reached stderr with rc 2 in both formats (CPython Doc/reference/lexical_analysis.rst v3.13.16 L785-L786: `!r` calls repr, which quotes the operand and does not redact it). A source must now be a string, and the refusal names the entry and the field, never what was given. Tests: the real command as a subprocess, eight kinds of rejected value (an account path, an object and a list holding a token, a number, text, a null byte, a null, a missing file) x text and JSON. - B2 (CC): the property test's docstring listed the port among the positions of the 300 seeded values, but no spec put a value there (a mutant that appends `:{parts.port}` passed the test alone). Two specs are added, a URL without an `@` holding the value as its path, query and fragment and one holding it as the port (a port that is not a number withholds the URL whole), and a valid five-digit port is asserted absent from the description (it is below the 8-character piece the test looks for). - P3-1: `Path.is_file()` re-raises EACCES for a directory that cannot be searched (CPython Lib/pathlib/_abc.py, v3.13.16 L476-L488), outside the conversion, so the run ended with exit 1 and a traceback naming an absolute path. It is now `cannot read ~/.codex/config.toml: PermissionError` and exit 2. - P3-2: the fields of a DIFFERS acknowledgement must be a list of strings; `sorted(entry["fields"])` raised TypeError for a list that mixes types. - P3-3: json and tomllib raise RecursionError on deeply nested input; it is an input that cannot be read (exit 2, the kind of error named), for the live files and the acknowledged file. - P3-5: the sentence "a field of an unexpected shape ends the run with exit 2" is as wide as the checks: it names them, and says that a `type` or `command` of another kind is compared and withheld. Fail-first: the new tests (41 in the module and its selector test) give 16 failures and 3 errors against the implementation of cecf039 (4 tests) and pass here; 36 of 36 mutants of the module killed. The evidence rows of the changed files are updated. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> * Build the stale acknowledgement from its defined keys, refuse what the schema does not define, and withhold a command that is not text Adjudicated commit of #1034 on 55dba7f (the CC's ruling adjudication-pr1034-55dba7f4-20261012.md; Astra's third read ~/.cache/ns2604-gpt-reads/fix3-pr1034-55dba7f4c/VERDICT.md: one P1, two P2, four P3; the CC's micro pr1034-claude-micro-55dba7f4.md: L1, B5, B6, P3-6 to P3-9). - P1 (Astra): shown_stale copied the whole acknowledgement entry (`{**e, ...}`), so a key of the acknowledged file that the schema does not define, nested or not, reached stdout in the JSON format (CPython Doc/reference/expressions.rst L359-L361: dictionary unpacking adds every mapping item; Lib/json/encoder.py L354-L358, _iterencode_dict reads dct.items()); a `reason` that is an object holding a token was accepted and serialised the same way. An entry now holds the keys of ACK_FIELDS and no other (a key outside them ends the run with exit 2 and a message that names the entry and never the value), its `reason` is text, `fields` are a list of strings for every kind of row (Astra's follow-up 1 and the CC's P3-7: a stale LIVE-ONLY entry with `fields: 42` ended in a TypeError traceback), and the report builds the stale entry from the defined keys, so even a loader that let a key through publishes none of it (tested with a stub loader). - P2 (Astra) and B6 (the CC): shown_command called str() on the command, so a number, a float or a boolean, which has the shape of a file name, was printed (90817263 in all four combinations of client and format) although the docstring, the record and the body say that a command of another kind is withheld. A command that is not text is withheld; an absent or empty command stays "(no command)". The code now matches the sentence; the three places keep it, as "a `type` or a `command` that is not text". - P3-6 (the CC): the RecursionError catch of load_acknowledged had no test (dropping it left the module green); the acknowledged file joins the deeply nested live files in that test. - P3-8 (the CC): the mechanisms of two earlier corrections are cited at the pin, python/cpython@v3.13.16 (cbc944f4): sorted() over a list that mixes kinds raises TypeError (Objects/object.c L1032); nested JSON raises RecursionError (Modules/_json.c L1033 and L1041) and nested TOML does too (Lib/tomllib/_parser.py L432 and L628: parse_array and parse_value call each other with no depth guard of their own). - B5 (the CC): the corrected fail-first figures. The tests of 55dba7f over cecf039: 41 tests, FAILED (failures=17, errors=3) in 5 tests (the message of 55dba7f says 16, 3 and 4: it cannot change without a new head, and the squash body states these). The tests of this commit over 55dba7f: 48 tests, FAILED (failures=70, errors=1) in 6 tests; at this head they pass. 43 of 43 mutants of the module killed. - L1 (the CC): the branch sits on main 9cfe3a9, rebased commit by commit: the registry rows, the two rows of examples/claude-native/workflows/SHA256SUMS (child-usage.mjs and test-child-usage.mjs, recomputed over the merged files) and catalogs/landscape/final-stack.json (regenerated by scripts/final_stack.py --write) were written again by their owning tools; the PR body records the equal patch-ids. The evidence rows of the changed files are updated. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Scope
Align the code graph's typed MCP registration key and tool namespace with
codebase-memory-mcp. A separate named commit removes the four ASCII bytestoofrom the repository-authored Codexgit showexception and re-rendersits repository copies, preserving the existing 20,103-byte startup ceiling.
003804f24fa5d998ba429dff3235b0d7dba9fa93.lane:foundation; draft.0aae66bd9ca5ff68c007cd00de47bceac7e25388.6c6d817, then separate trim0aae66bd.256ece4f3ce8a04908f8bb3c49082a0329b78e90.sources/projections and ten Codex role copies; current setup/handbook/README
references; nine Python contract modules and the native accounting
source/fixture; four checksum inventories; the source-qualification receipt
and owned evidence-registry entries.
and the exclusions record belong to the separate exclusions PR.
SOTA sources
the pinned vendor repository, executable identity and native installation
channel. The namespace choice follows the canonical key ruled from actual
registrations; no engine replacement or install is claimed by this PR.
unchanged upstream awareness. The four-byte trim is in the repository's
separate exception wording, authorized by RULING-Q26.
the existing repository renderer for derived copies.
the role fragment comes from the maintained template's native managed block.
task-ns2604-coop-20261007T142046Z, decided item 2;task-ns2604-coop-20261007T144733Z, RULING-Q26;task-ns2604-coop-20261007T150457Z, section 1;task-ns2604-coop-20261007T150807Z, CONTRACT-CHANGES.Evidence-class table
source_reviewsource_reviewlocal_integrationsyntheticlocal_integrationLocal commands run
Contract changes
Each row declares a main test or fixture binding changed intentionally. The
landing read checks the source and the cited ruling; an undeclared main-version
failure blocks. Exact set/cardinality assertions remain exact, and the Codex
budget remains 20,103 bytes.
tests.test_codex_agents.CustomAgentInstructionsTests.test_shipped_sha256sums_pin_the_two_carriersadoption/agents/codex/SHA256SUMStests.test_codex_agents.CustomAgentInstructionsTests.test_byte_mutants_fire_exactly_one_ruleadoption/agents/codex/SHA256SUMStests.test_codex_agents.CustomAgentInstructionsTests.test_readme_rows_and_dated_sectionexamples/codex-native/README.md; adoption/agents/codex/SHA256SUMStests.test_codex_agents.CustomAgentInstructionsTests.test_readme_checker_controlsexamples/codex-native/README.md; adoption/agents/codex/SHA256SUMStests.test_codex_roles.Sha256SumsTests.test_the_shipped_file_reads_as_the_two_pinned_rowsadoption/agents/codex/SHA256SUMStests.test_codex_roles.Sha256SumsTests.test_a_missing_trailing_newline_is_readadoption/agents/codex/SHA256SUMStests.test_codex_roles.Sha256SumsTests.test_each_malformed_line_is_refused_with_a_message_that_holds_no_textadoption/agents/codex/SHA256SUMStests.test_codex_roles.Sha256SumsTests.test_the_reader_is_no_looser_than_sha256sum_check_strictadoption/agents/codex/stack-researcher.toml; adoption/agents/codex/SHA256SUMStests.test_codex_roles.SourceProblemsTests.test_a_changed_row_breaks_only_that_fileadoption/agents/codex/SHA256SUMStests.test_codex_roles.SourceProblemsTests.test_a_third_or_missing_name_in_the_sums_file_is_a_names_problemadoption/agents/codex/SHA256SUMStests.test_codex_roles.SourceProblemsTests.test_a_file_that_is_not_toml_is_namedadoption/agents/codex/SHA256SUMStests.test_codex_roles.SourceProblemsTests.test_a_consistent_edit_that_breaks_a_structural_rule_is_still_refusedadoption/agents/codex/SHA256SUMStests.test_codex_worker_lane.TemplateTests.test_top_rule_is_pinned_and_rendered_rtk_is_the_unchanged_pinned_sourceadoption/templates/codex.AGENTS.template.mdtests.test_codex_worker_lane.TemplateTests.test_worker_startup_timeouts_layer_over_user_serversadoption/templates/codex.config.template.toml; adoption/templates/codex.stack-worker.config.tomltests.test_codex_worker_lane.ApplyFlowTests.test_start_up_allowances_are_written_for_registered_servers_and_rolled_backadoption/templates/codex.config.template.tomltests.test_codex_worker_lane.SerenaReadbackTests.test_a_recorded_lookup_error_fails_the_read_backadoption/templates/codex.config.template.tomltests.test_codex_worker_lane.CodexIntegrationTests.test_real_app_server_apply_and_byte_exact_rollbackadoption/templates/codex.config.template.tomltests.test_codex_worker_lane.CodexIntegrationTests.test_a_project_config_outranks_the_profile_but_not_the_pinned_flagsadoption/templates/codex.config.template.toml; adoption/templates/codex.stack-worker.config.tomltests.test_command_position_oracle.CommandPositionOracle.test_probes_read_what_real_bash_runsexamples/claude-native/workflows/child-usage.mjs:718,976tests.test_command_position_oracle.CommandPositionOracle.test_generated_commands_read_what_real_bash_runsexamples/claude-native/workflows/child-usage.mjs:718,976tests.test_command_position_oracle.CommandPositionOracle.test_extended_generated_commands_read_what_real_bash_runsexamples/claude-native/workflows/child-usage.mjs:718,976tests.test_install_claude_profile.McpTemplateShapeTests.test_template_names_the_expected_serversadoption/mcp/claude-user.jsontests.test_install_claude_profile.McpCarrierCoverageTests.test_the_carrier_names_the_lane_serversadoption/hooks/claude/token-lanes-block.md; adoption/mcp/claude-user.jsontests.test_install_claude_profile.McpCodexParityTests.test_the_parity_check_rejects_each_kind_of_driftadoption/mcp/claude-user.json; adoption/templates/codex.config.template.tomltests.test_install_claude_profile.McpCodexParityTests.test_codebase_memory_is_the_bare_frontend_of_the_shared_daemonadoption/mcp/claude-user.jsontests.test_landscape_sweep_harness.OmniRouteLaneBuildTests.test_lane_home_carries_provider_mcp_servers_and_profileadoption/templates/codex.config.template.tomltests.test_new_wsl_client_config.AgentGapTests.test_the_gaps_are_the_servers_and_skills_the_agents_name_beyond_the_wired_ones_and_the_plans_skillsadoption/new-wsl/client-config-map.jsontests.test_new_wsl_client_config.RenderTests.test_the_wired_servers_are_registered_and_serena_and_qmd_by_the_command_their_readmes_giveadoption/new-wsl/client-config-map.json; adoption/mcp/claude-user.json; adoption/templates/codex.config.template.tomltests.test_new_wsl_client_config.RenderTests.test_the_stack_worker_profile_keeps_the_wired_servers_and_the_settings_that_need_no_tooladoption/templates/codex.stack-worker.config.tomltests.test_new_wsl_client_config.ApplyTests.test_the_first_run_writes_what_the_wired_pieces_name_and_nothing_elseadoption/new-wsl/client-config-map.json; adoption/mcp/claude-user.jsontests.test_task_model_routing.TaskModelRoutingRecordTests.test_the_token_efficiency_profile_is_accepted_by_this_record_and_leaves_the_three_tools_outadoption/hooks/claude/token-lanes-block.mdtests.test_token_lanes_subagent_start.TokenLanesHookTests.test_injected_bootstrap_names_granted_lane_tools_explicitlyadoption/hooks/claude/token-lanes-block.md; adoption/mcp/claude-user.jsontests.test_token_lanes_subagent_start.TokenLanesHookTests.test_serena_manual_loader_and_role_grants_precede_navigationadoption/hooks/claude/token-lanes-block.md; adoption/mcp/claude-user.jsontests.test_token_lanes_subagent_start.TokenLanesHookTests.test_native_navigation_front_doors_keep_manual_and_policy_sequenceadoption/hooks/claude/token-lanes-block.md; adoption/mcp/claude-user.jsontests.test_token_lanes_subagent_start.TokenLanesHookTests.test_researcher_catalog_lane_hands_ungranted_semantic_retrieval_to_coordinatoradoption/hooks/claude/token-lanes-block.md; adoption/mcp/claude-user.jsontests.test_token_lanes_subagent_start.TokenLanesHookTests.test_injected_text_names_only_tools_each_shipped_allowlist_grantsadoption/hooks/claude/token-lanes-block.md; adoption/mcp/claude-user.jsonexamples/claude-native/workflows/test-child-usage.mjs::cli lanes: the stack's own servers are read by name in every selector formexamples/claude-native/workflows/child-usage.mjs:718,976; examples/claude-native/workflows/test-child-usage.mjs:717Record locators above expand as follows: SERVER-KEY is
task-ns2604-coop-20261007T142046Z, decided item 2; Q26 istask-ns2604-coop-20261007T144733Z, RULING-Q26, first two bullets; RENAME-PR istask-ns2604-coop-20261007T150457Z, section 1, first bullet;CONTRACT-CHANGES is
task-ns2604-coop-20261007T150807Z, the named Kind.KEY-DECISION is
docs/decisions/2026-10-07-codegraph-server-key.mdat the frozensource head: its new current-key behavior supersedes the earlier
docs/decisions/2026-09-25-codex-mcp-scope.mdcurrent-key contract. Kind 5 rowsname maintained current-state bindings in their row, rather than using a dated
record as the binding. Shared-global/helper consumers are declared
conservatively even where their present pass/fail outcome remains unchanged.
Exact status-line field (kind 2 rows are subtype 2a, as their ruling specifies):
Adapted instruction text
Trim first, then every typed-key instruction hunk; file and line references will
name the frozen PR head. Repository instruction copies are renderer-derived.
adoption/templates/codex.AGENTS.template.md:42toofrom the second git-show exampleadoption/new-wsl/codex-user-instructions.md:66adoption/agents/codex/stack-researcher.toml:60adoption/agents/codex/stack-verifier.toml:59adoption/agents/codex/workers/evidence-reviewer.toml:60adoption/agents/codex/workers/isolated-builder.toml:60adoption/agents/codex/workers/semantic-evidence-reviewer.toml:60examples/codex-native/agents/stack-researcher.toml:60examples/codex-native/agents/stack-verifier.toml:59examples/codex-native/agents/evidence-reviewer.toml:43examples/codex-native/agents/isolated-builder.toml:43examples/codex-native/agents/semantic-evidence-reviewer.toml:70adoption/templates/codex.AGENTS.template.md:20adoption/new-wsl/codex-user-instructions.md:20adoption/scaffold/AGENTS.md:21adoption/hooks/claude/token-lanes-block.md:2adoption/hooks/claude/token-lanes-block.md:8adoption/hooks/claude/token-lanes-block.main.md:8docs/token-session-handbook.md:279docs/token-session-handbook.md:305docs/token-session-handbook.md:341docs/token-session-handbook.md:372docs/token-session-handbook.md:456adoption/bootstrap.md:471The retained receipt's older 23 locations are classified as inspected anchors,
including five unchanged context locations. The formal declaration here counts
24 actual changed instruction/setup hunks and includes the six changed
setup/copied-guidance locations absent from that inspection list.
Decision record
docs/decisions/2026-10-07-codegraph-server-key.md. The sourcechoices and separate trim are ruled by the four CC items listed above. Kind 5
bindings point to maintained current-state files, not to historical decision
snapshots.
Landing path
The rename PR has the named landing path granted by
task-ns2604-coop-20261007T150457Z, section 1: co-op exact-head read → CC ACK →5f's next landing turn → #776 immediately afterward with its reviewed content
unchanged. That item exempts this rename PR from the lane's two-open-PR cap.
Root holds the qualified head and publishes the status line. The full suite
uses the prepared landing environment when a landing push is needed; a hosted
validate pass at a head already on main's tip may supply the landing full suite
under
task-ns2604-coop-20261007T150807Z.full-suite=: PENDING: verified landing-scope result.suite-env=: PENDING: verified environment recipe/version when required.Source qualification
The receipt
retains the failed attempt, source-only repair, disjoint modular accounting and
all skips. Receipt SHA-256:
4e2c9294a802776753434536b74a6e3aa011360f909d841adc5dd88ce37f78df.The final metadata clarification preserves every observed counter and inspected
anchor value; source/tests remain byte-identical to the qualified tree.
Native UTF-8 source measurements are compact 8076, rendered 9142 and aggregate
Codex startup 20101 bytes against the unchanged 20103 ceiling. Main registration
counts remain Claude 7, Codex 8 and worker profile 6. Transport, command,
environment, permission, model and effort values are preserved. These are
repository integration/fixture/source results, with no host adoption or live
MCP/model acceptance claim.
Host evidence
Not applicable: this PR adds no host receipt or host-status claim.
Checklist
adapted=, trim first.