Skip to content

Reconcile the MCP templates with the live registrations: code graph key, promptfoo and a drift report - #1034

Merged
seathatflowsinourveins merged 8 commits into
mainfrom
claude/cc-native-practice-mcp-template-reconcile-20261012
Oct 12, 2026
Merged

seathatflowsinourveins merged 8 commits into
mainfrom
claude/cc-native-practice-mcp-template-reconcile-20261012

Conversation

@seathatflowsinourveins

@seathatflowsinourveins seathatflowsinourveins commented Oct 12, 2026 •

Copy link
Copy Markdown
Collaborator

Scope

  • What this PR changes, in one or two sentences: reconciles the committed new-WSL MCP templates with the servers the first host's clients have registered. The code graph server is registered as codebase-memory-mcp (the rename of draft Align code graph MCP server key with native client registrations #834, carried onto current main), promptfoo is wired for Claude Code, and a new read-only report, tools/adoption/mcp_template_drift.py, names every remaining difference, with adoption/new-wsl/mcp-drift-acknowledged.json listing the ones a decision record accepts. No stored client configuration is changed.
  • Base commit: d8f7e2051b61bde6361a85b64f41413798015353 (main after Apply verified event scopes to CI secret scans #949, the target of the latest rebase of 2026-10-12, below). The branch was cut at 83cec12eec323cf3fc3d62177e38fe4163dbd3bb (main after Add fenced Claude usage sampling and Grafana panels #954); the reads before the latest rebase were made on a365d8becd8d9463ea4b58c6003de0c6f1250e82.
  • Lane: lane:foundation
  • Owned paths touched: adoption/new-wsl/ (client-config map, the Claude MCP additions template, the new acknowledged-differences file), adoption/mcp/claude-user.json, adoption/templates/codex.config.template.toml, adoption/templates/codex.stack-worker.config.toml, adoption/hooks/claude/ (two token-lane carriers and their checksums), examples/claude-native/workflows/ (child-usage accounting and its checksums), tools/adoption/mcp_template_drift.py, docs/decisions/ (one new record, one dated addendum), docs/token-session-handbook.md, examples/mcporter.json.example, the published MCPorter calls (the selector only: manifests/stack.json, recipes/README.md, docs/token-efficiency-stack.json, blueprints/token-native-focus/saturation-audit.json, catalogs/us-equities/foundation-memory.json and .md), the tests that pin these names, and manifests/evidence.json.
  • Commits, in order: (1) the code graph key, carrying draft Align code graph MCP server key with native client registrations #834's rename (its commit 6c6d8179f) without its trim; (2) promptfoo for Claude Code; (3) the drift report with its tests, acknowledged differences and decision record; (4) the evidence registry; (5) the fix wave for the first reads of 6a7a7ce7; (6) the fix wave for the second reads of 4916d3a4; (7) the fix wave for the reads of cecf039f; (8) the adjudicated commit for the reads of 55dba7f4 (both below). Each fix wave is one commit that re-registers its own files. Draft Align code graph MCP server key with native client registrations #834 is superseded by this change and is closed with a pointer to it.
  • Rebased on 2026-10-12 onto main a365d8bec (the PR was DIRTY: a conflict in manifests/evidence.json only). It is a pure rebase: each commit's diff without the registry has the same patch-id, so has the whole branch diff, and the registry rows of the 36 files the branch registers or changes are identical to those of the old head; the registry conflict was resolved by writing each commit's rows again with scripts/host_receipts.py (register_file) at the rebased bytes. The commit names in this description are the heads the reads were made on (the latest rebase, below, renames them again): 6a7a7ce7 is now 71bc0e925, 4916d3a4 is 95064ff58, 2d131c02a is cecf039f9.
  • Rebased again on 2026-10-12 onto main d8f7e2051 (the PR conflicted with fix(landscape): bind completed supersessions and redact scratch sessions #995, Preserve missing-vote candidates in final-stack survivors #1026 and Apply verified event scopes to CI secret scans #949 in three generated files, the CC's finding L1). Each commit was applied with git cherry-pick --no-commit and the generated files were written again by their owning tools: manifests/evidence.json (the rows of the files the commit changed, scripts/host_receipts.py register_file, at the rebased bytes), examples/claude-native/workflows/SHA256SUMS and adoption/hooks/claude/SHA256SUMS (the rows the commit changed, recomputed over the merged files: child-usage.mjs and test-child-usage.mjs differ from both sides), and catalogs/landscape/final-stack.json (scripts/final_stack.py --write: it carries the digest of manifests/stack.json). Pure-rebase evidence: the diff of each of the 8 commits without those three kinds of file has the same git patch-id --stable as before, so has the whole branch diff; 31 of the 36 registry rows of the files the branch registers or changes are identical to the old head's, and the 5 that differ are files main changed too (final-stack.json, the workflows SHA256SUMS, child-usage.mjs, test-child-usage.mjs, tests/test_landscape_sweep_harness.py). sha256sum -c passes on both checksum files; git merge-tree --write-tree against main is clean. The names of the commits before and after: aca46e24a is 5cba90b65, 905a23b9a is f7bc43719, 2713c59e7 is 338e50f81, 71bc0e925 is ba3e038d2, 95064ff58 (the fix wave for 6a7a7ce7) is 1454e0b64, cecf039f9 is 60a984c34, 55dba7f4c is 7b2e40098, and the adjudicated commit f3bc47ae0 is 03d92cbde.

The adjudicated commit (commit 8), for the reads at 55dba7f4

By the command center's ruling (adjudication-pr1034-55dba7f4-20261012.md: two fix rounds spent; scope-locked to the P1 of Astra's third read, the rebase, B5 and B6 of the Claude micro; the two P2 of the GPT file only where each is small with its test). Inputs: Astra's third read (CHANGES_REQUESTED: 1 P1, 2 P2, 4 P3) and the command center's Claude micro (CHANGES_REQUESTED: no new P1, no P2; L1, B5, B6, P3-6 to P3-9). Fail-first: the tests of this commit run 48 tests and give FAILED (failures=70, errors=1) in 6 tests on 55dba7f4 (fail-before-55dba7f4c-final.txt); at the new head they pass (45 + 3, OK).

Finding Fix Regression test
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; a reason that is an object holding a token was accepted and serialised the same way An entry holds the keys of ACK_FIELDS and no other (any other key ends the run with exit 2 and a message that names the entry, never what it holds), its reason is text, and the report builds the stale entry from the defined keys, so a loader that let a key through still publishes none of it. CPython Doc/reference/expressions.rst L359-L361 (dictionary unpacking adds every mapping item), Lib/json/encoder.py L354-L358 (_iterencode_dict reads dct.items()), v3.13.16 test_an_acknowledgement_with_a_key_the_schema_does_not_define_is_refused_and_never_published (5 shapes x 2 formats, the real command), test_the_reason_of_an_acknowledgement_is_text (7 kinds x 2 formats), test_a_stale_acknowledgement_is_published_from_its_defined_keys_only, test_the_report_copies_no_entry_whatever_the_loader_returned (a stub loader)
P2 (Astra) and B6 (command center): 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 said 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 matches the sentence, which now reads "a type or a command that is not text" in the three places test_a_command_that_is_not_text_is_withheld_for_either_client_in_either_format (an integer, a float, true, false, a list, a table x 2 clients x 2 formats)
Astra follow-up 1 and P3-7 (command center): fields was checked for DIFFERS only; a stale LIVE-ONLY entry with fields: 42 ended in a TypeError traceback fields, when given, is a list of strings for every kind of row test_fields_of_an_acknowledgement_are_a_list_of_names_for_every_kind_of_row (2 row kinds x 7 shapes x 2 formats, and the accepted forms)
P3-6 (command center): the RecursionError catch of load_acknowledged had no test A deeply nested acknowledged file joins the nested live files test_a_deeply_nested_acknowledged_file_ends_the_run_with_exit_two_and_a_fixed_message
P3-8 (command center): the mechanisms of two earlier corrections cited no upstream line Cited at python/cpython v3.13.16 in the tool and the commit: Objects/object.c L1032 (the TypeError of sorted() over mixed kinds), Modules/_json.c L1033 and L1041 and Lib/tomllib/_parser.py L432 and L628 (the RecursionError of nested JSON and TOML) none (citations)
B5 (command center): the fail-first figures of the previous commit were stale The tests of 55dba7f4 over cecf039f give Ran 41 tests, FAILED (failures=17, errors=3) in 5 tests (measured by both families and again here, fail-before-cecf039f9-of-55dba7f4c.txt); the commit message of 55dba7f4 says 16, 3 and 4 and cannot change without a new head. The sixteenth failure was the case "a number that spells a file" of the source test, which also fails there. The corrected figures are in this body none
L1 (command center): the head conflicted with main Rebased (the paragraph above) the patch-id comparison above, sha256sum -c, scripts/validate.py
P3-9 (command center): "three existing occurrences of the host name" counted one spelling manifests/evidence.json holds 3 in the exact case and 20 in any case (18 lines), the same at the base, so none is added here none (the body)

Mutation check of the module: 43 mutants (the 36 of commit 7 and these: unknown keys accepted, a reason of any kind, fields checked for DIFFERS only, a command stringified, a falsy command taken for no command, the stale entry copied, a nested acknowledged file not converted, the command directory printed and the names of acknowledged fields not text, both re-anchored): all killed (survivors: none).

Fix wave 3 (commit 7), for the reads at cecf039f

Inputs: Astra's delta read of cecf039f (CHANGES_REQUESTED: 1 P1, 4 P3) and the command center's Claude micro read (CHANGES_REQUESTED: four claims of the body, five P3). Fail-first, corrected by the adjudicated commit: the tests of this commit run 41 tests and give FAILED (failures=17, errors=3) in 5 tests on cecf039f (the commit message of 55dba7f4 says 16, 3 and 4: stale); at that head they passed (41 tests, OK).

Finding Fix Regression test
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 A source must be a string; the refusal names the entry and the field (acknowledged[0]: source must be a relative path to a regular file beneath this repository), never what was given. CPython Doc/reference/lexical_analysis.rst (v3.13.16 L785-L786): !r calls repr, which quotes the operand and does not redact it test_a_rejected_acknowledgement_source_is_never_printed (the real command as a subprocess; an account path, an object and a list holding a token, a number, text, a null byte, a null, a missing file; text and JSON; neither stream); the source test also refuses a number that spells a file
B2 (command center): the property test never placed a value in the URL port, though its docstring and the body said so (a mutant that appends the port passed it 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 valid five-digit port is asserted absent from the description test_a_description_is_built_from_names_and_fixed_words_only
P3-1: an unsearchable ~/.codex directory ended the run with exit 1 and a traceback naming an absolute path Path.is_file() re-raises EACCES (CPython Lib/pathlib/_abc.py, v3.13.16 L476-L488); it is converted: cannot read ~/.codex/config.toml: PermissionError, exit 2 test_a_home_whose_codex_directory_cannot_be_searched_ends_the_run_with_exit_two
P3-2: a DIFFERS acknowledgement whose fields mixes types crashed sorted() The fields must be a list of strings test_the_fields_of_a_differing_acknowledgement_are_a_list_of_names (six shapes)
P3-3: deeply nested JSON or TOML ended in RecursionError (exit 1, traceback) An input that cannot be read: exit 2, the kind of error named; for the live files and the acknowledged file test_an_input_that_cannot_be_read_ends_the_run_with_exit_two_and_a_fixed_message
P3-5: "a field of an unexpected shape ends the run with exit 2" was broader than the checks The docstring, the record and the body name the shapes the checks name, and say that a type or command of another kind is compared and withheld none (wording)
B1, B3, B4, P3-4: claims of the body Corrected in the body: the base commit; the research row is filed (2026-10-12T11:43:12Z); the ruling on the host label and the file name is cited as the command center's message of 2026-10-12 about 10:33Z; the handbook locator is L456 none

Fix wave 2 (commit 6), for the second reads at 4916d3a4

Inputs: the four review threads opened on 4916d3a4 (two fixed here, two answered in the threads: below), Astra's second read (CHANGES_REQUESTED: 2 P1) and the command center's full read (CHANGES_REQUESTED: 2 blockers, 6 stale claims, P3-a to P3-f). Fail-first, re-measured with the final tests: on 4916d3a4 they run 37 tests and give FAILED (failures=45, errors=10) (10 of the 37 tests fail); on 6a7a7ce7 FAILED (failures=82, errors=26) (16 of 37); at the new head they pass (37 tests, OK).

Finding Fix Regression test
P1 (Astra blocker 1; thread on shown_arg; the command center's item 1): a token that has the shape of an option is printed, and it can be a value: the credential in --api-key --secret-token, the operand of a short option (-k --x), a positional value after -- (24 of 24 probe runs of the command center, 8 of 8 of Astra's). The wave-1 direction ("flag names with one placeholder") had the same hole Arguments are counted ("2 args") on both sides of a row, in both formats, and never shown; no function prints an argument. CPython Lib/argparse.py L1964 and L2503 (v3.12.3) and Lib/getopt.py execute such tokens as values, so the spelling of a token cannot decide what may be printed test_no_argument_token_is_printed_whatever_it_looks_like (twelve hostile tokens), test_a_credential_that_looks_like_an_option_is_not_printed_by_either_client_in_either_format (5 forms x 2 clients x 2 formats, stdout and stderr), the seven wave-1 credential forms
P1 (Astra blocker 2) and P3 (thread): a malformed Codex timeout reached float(), whose error quotes the value (%R); main() caught only DriftError, so the traceback put the value on stderr and the exit code was 1 Shapes are checked, a conversion error is dropped (not chained), and a field of a shape the checks name (a timeout that is not a number, a list given as text, a table given as a list, a registration that is not a table, an argument that is not a string) ends the run with exit 2 and a message that names the server only. CPython Objects/floatobject.c float_from_string_inner (v3.12.3 L190-193, v3.13.16 L183-186) the real command as a subprocess with a secret in each timeout field, text and JSON: exit 2, empty stdout, no value on either stream; a string, a list and a table as the value
P3-a (command center): a userinfo that holds an unescaped /, ? or # parses as the host, which was printed (32 of 32 runs); one form contradicted the docstring ("a URL that does not parse is withheld whole") A URL that holds an @ anywhere, a port that does not parse (not a number, out of range), or a scheme or host of another shape is withheld whole. CPython Lib/urllib/parse.py urlsplit (v3.13.16 L472) 5 URL forms x 2 clients x 2 formats; notaport, 99999, -1 as ports
P3-b: args given as text printed its length as a count; a Codex mcp_servers that is not a table ended in an uncaught AttributeError (exit 1) args, env_vars, enabled_tools, disabled_tools must be lists, args holds strings, env, headers, http_headers are tables, mcp_servers is a table; else exit 2, naming the server only 13 shapes (a string, a number, a list of pairs, a table) in both clients; [[mcp_servers]]
P3-c: the notes and the read errors printed the account's home Paths print relative to the home (~/.claude.json), else the file name; a read error names the kind of error (JSONDecodeError, IsADirectoryError), not its text test_paths_are_printed_relative_to_the_home (inside the home, outside it, an error from each client)
P3-d: the transport type printed any name-shaped text; the host label and the command's file name still print The transport is one of stdio, http, sse, else <withheld>. The host label and the command's file name are printed as names, not as values, and the module docstring now says so test_the_description_keeps_what_a_reader_needs_without_a_value, the property test
P3-e (the part that runs): recipes/README.md L790 ran mcporter ... list codebase-memory, which works only through MCPorter's auto-correction (installed 0.14.2: "Auto-corrected server name"; at the pin src/cli/list-command.ts L493-521) The line names the registered key; the selector test scans list SERVER as well as call SERVER.TOOL tests/test_mcporter_selectors.py (3 tests; failed on 4916d3a4 for this line)
C1 (stale numbers), C2 (promptfoo is 0.124.0 on the first host), C3 (SocratiCode runs through node in Codex), C4 (two promptfoo tool classes), C5 (the 403 line is L61), C6 (the property test did not place a value in every position) The numbers above are re-measured with the final tests. The record says: pinned 0.123.1, installed 0.124.0 with the same 14 tool names and mcp --transport (a currency item for the version owner); Claude Code through npx and Codex through node; four of the 14 tools only read local state, run_assertion runs javascript, python and webhook assertions locally (src/commands/mcp/tools/runAssertion.ts L19-24) and validate_promptfoo_config imports a JavaScript configuration as code (validatePromptfooConfig.ts L5, L62; src/util/config/load.ts L383-385); streamable-http.mdx L58-61. The property test now names its positions and adds the URL username and the whole transport type; the host label and the command's file name are excluded because they print as names by design test_a_description_is_built_from_names_and_fixed_words_only (300 seeded values: arguments, an environment value, a header value, the command's directory, a URL's username, password, port, path, query and fragment, the whole type)

The two threads answered in place (the command center's rulings on 4916d3a4): binding an acknowledgement to the accepted value is deferred to the research queue (rule 8: a committed signature of a live value is a digest of unsanitized bytes, #161, and a value predicate needs a schema first); removing the legacy codebase-memory registration is a follow-up installer migration (the first host already runs the vendor key).

Mutation check of the module: 29 mutants (every argument shown again, the singular, a shape error not converted, a URL's path, port or userinfo printed, an @ URL not withheld, a port that does not parse not withheld, the command directory printed, the type printed as it is, unchecked names, a list, a table or a non-string argument accepted, the shape not checked in either normaliser, a path printed in full inside or outside the home, a read error printing its text for either client, a Codex mcp_servers that is not a table accepted, absolute or .. sources allowed, symlink escape, directory source, the root not applied or not passed): all killed by the module's tests (survivors: none). Dropping the isinstance(spec, dict) test of check_shape is an equivalent mutant, because compare also converts the AttributeError that .get then raises.

Fix wave 1 (commit 5), for the first reads at 6a7a7ce7

Astra's read (CHANGES_REQUESTED: 1 P1, 3 P2) and the four review threads, each fail-first (the new tests failed on 6a7a7ce7; they pass at every later head):

Finding Fix Regression test
P1: credential-bearing arguments reached both output formats (--api-key VALUE, its percent-encoded value, --api-key=VALUE, URL userinfo or query in an argument, --header 'Authorization: Bearer VALUE', a long credential containing !) Values are compared in memory only and no digest of a withheld value is printed. Wave 1 printed option names; wave 2 counts every argument (above) the seven forms x two clients x two formats (28 outputs, text and JSON, stdout plus stderr, raw and encoded needles)
P2: the MCPorter rename broke the published commands (Unknown MCP server 'codebase-memory') Every published mcporter ... call selects codebase-memory-mcp.<tool>; the transcript classifiers keep the short alias for sessions recorded before the rename tests/test_mcporter_selectors.py resolves each published selector against examples/mcporter.json.example (8 selectors in 6 files failed before); the classifier tests keep one case per spelling
P2: an acknowledgement source accepted /etc/passwd and ../x A source is a relative path to a regular file beneath the repository; absolute paths and .. are refused and symlinks are resolved before the containment check. CPython Lib/pathlib/_local.py resolve and is_relative_to (v3.13.16 L664, L393) accepted: a document, a document with #heading, a repository symlink to a repository file; refused: absolute (inside and outside), .. (also when it returns inside), a symlink to an outside file, a directory, a missing file, a null byte; end to end through main() (exit 2)
P2: --eco-root (and ECO_INSTALL_ROOT) reached the Claude renderer only ECO_ROOT is set in the host values of the shared render, before either client is rendered a non-default prefix renders in both clients and compares SAME from the option and from the environment (six false DIFFERS rows before)

SOTA sources

  • DeusData/codebase-memory-mcp v0.11.0 (commit 8972ea69c6ad94b1ef1d4ffbf0a92d78d2db1798), README.md L450-L460: the vendor's own registration is "mcpServers": {"codebase-memory-mcp": {...}}. Both clients show that key on the host (claude mcp list, Codex [mcp_servers.codebase-memory-mcp]).
  • promptfoo/promptfoo 0.123.1 (commit 34f74d34e140b5e17d23770dfb2340057b1936b8), site/docs/integrations/mcp-server.md L37 (promptfoo mcp --transport stdio), L49-L52 (the client entry), L169 (stdio is the transport of desktop AI tools); src/commands/mcp/server.ts L94-L112 registers the 14 tools; src/commands/mcp/tools/runAssertion.ts L19-L24, L43, L166 and validatePromptfooConfig.ts L5, L62 with src/util/config/load.ts L383-L385 (the two tools that look read-only and are not). The manifest pins 0.123.1; the first host runs 0.124.0 (14 tool names, mcp --transport http|stdio). The entry runs the installed binary, not npx promptfoo@latest, so the version is the installed one and never a floating one.
  • Claude Code MCP documentation, "MCP installation scopes" (read 2026-10-12): user-scoped servers are stored in ~/.claude.json, which is the file the report reads; project (.mcp.json), local and plugin servers are not read and the report says so.
  • modelcontextprotocol/modelcontextprotocol at 1f520964b295d58494d944f2aea8a5ab51c79f77: docs/specification/2025-06-18/basic/transports.mdx L76 (servers MUST validate Origin), docs/specification/2025-11-25/basic/transports.mdx L78-L79 and docs/specification/2026-07-28/basic/transports/streamable-http.mdx L58-L61 (an invalid Origin MUST get HTTP 403). This is the gate that the loopback routes measured here are held to; the lines were re-read in the local mirror ~/code/upstream/modelcontextprotocol/modelcontextprotocol (HEAD is the pin).
  • openclaw/mcporter at e4cb002200e44460279d414b0d1dec597b978f06 (the pin of MIRRORS.json, v0.13.13; the installed client is 0.14.2): src/cli/call-command.ts L309-L346 (resolveCallTarget and splitServerToolSelector: the server is the text before the first . of the selector) and src/runtime.ts L229-L235 (getDefinition looks the server up by exact name and throws Unknown MCP server '<name>'.); src/cli/list-command.ts L493-L521 (a near name is auto-corrected: a guess, not a contract). Measured on the installed 0.14.2 with examples/mcporter.json.example as committed (its command paths are placeholders, so nothing starts): call codebase-memory.search_graph answers rc 1 Unknown MCP server 'codebase-memory'.; call codebase-memory-mcp.search_graph resolves the server and stops at the placeholder command (spawn ... ENOENT).
  • python/cpython at f6650f9ad73359051f3e558c2431a109bc016664 (v3.12.3): Lib/argparse.py L1964 and L2503 (end-of-options handling: what follows -- is a value) and Objects/floatobject.c L190-L193 (float_from_string_inner formats its error with %R of the input); and at cbc944f4bc59639a444dd971c737788ba2283a91 (v3.13.16, the interpreter that runs the tool): Objects/floatobject.c L183-L186, Lib/urllib/parse.py L472 (urlsplit) and L165 (hostname), Lib/pathlib/_local.py L664 (resolve) and L393 (is_relative_to). Lib/getopt.py returns the operand of a short option as a value: getopt(['-k', '--x'], 'k:') gives [('-k', '--x')].
  • This repository at the base: tools/adoption/new_wsl_client_config.py (analyse, host_values, render: the report calls them, it does not re-implement the render) and tools/adoption/install_claude_profile.py (render_servers, default_eco_root); the closed-world map adoption/new-wsl/client-config-map.json; the admission gate in .claude/skills/claude-native-practice/reference/mcp-surfaces.md L24-L32.

Evidence-class table

Claim Evidence class Command / receipt
The rename leaves every contract that names the server consistent: templates, map, Codex tables, token-lane carriers, child-usage accounting and the test modules that pin them local_integration the module runs under Local commands below; scripts/validate.py exit 0
promptfoo renders for Claude Code with the host's own command, arguments and environment names, and its record counts (403 pieces, 363 wired) are the ones --check prints local_integration tests.test_new_wsl_client_config (incl. RecordTests), tests.test_mcp_template_drift.test_templates_carry_the_live_names_of_the_two_reconciled_servers
The report finds every kind of difference, compares an env-wrapped registration as the same server, prints no value of a registration (arguments are counted, environment and header values are withheld, a URL prints as scheme://host only when it holds no @ and its port parses, the transport is one of three words, paths are home-relative), ends a registration with a field of a shape the checks name with exit 2 and a message that names the server only, withholds a type or a command that is not text, builds the stale entry from the schema's keys and refuses any other key and a reason that is not text, fails on a stale acknowledgement, refuses a malformed one and refuses an acknowledgement source outside the repository without printing the rejected value synthetic (fixture) tests/test_mcp_template_drift.py (45 tests; with the selector module, 48: 70 failures and 1 error in 6 tests on 55dba7f4, none at the new head; commit 7's tests: 17 and 3 in 5 tests on cecf039f; commit 6's tests: 45 and 10 on 4916d3a4, 82 and 26 on 6a7a7ce7); 43 of 43 mutants killed
Every published mcporter ... call and list selects a server that examples/mcporter.json.example registers; the old selector is rejected by the installed MCPorter 0.14.2 and the new one resolves native_proven (the installed client, placeholder command paths, nothing started) + local_integration tests/test_mcporter_selectors.py (3 tests); the two calls under "SOTA sources"
A non-default ecosystem prefix, from --eco-root or ECO_INSTALL_ROOT, renders in both clients and compares SAME synthetic (fixture) test_the_ecosystem_root_reaches_both_templates, test_a_non_default_prefix_compares_the_same_for_both_clients_from_the_option_and_the_environment
On the first host, after this change, mcp_template_drift.py --with-authorization-settings --acknowledged adoption/new-wsl/mcp-drift-acknowledged.json exits 0: 13 SAME, 7 DIFFERS and 5 LIVE-ONLY rows, all 12 acknowledged, 0 stale; claude: promptfoo and claude: codebase-memory-mcp are SAME native_proven the command under Local commands below, run 2026-10-12 against the host's real ~/.claude.json and ~/.codex/config.toml with the tool at this head (it prints names and counts only); the sanitized output is retained locally
Before the change the same report, with no options, listed 19 rows that nothing accepted (8 SAME, 9 DIFFERS, 2 TEMPLATE-ONLY, 8 LIVE-ONLY) native_proven the report run on the base tree, same host, 2026-10-12
jcodemunch's shared HTTP service fails the admission gate (invalid Origin answered 200); qmd passes; ai-memory validates Host but not Origin; hindsight validates neither native_proven initialize-only probes of the four loopback routes (statuses only), tabulated in the decision record; PSS 45.3 MiB (stdio child) against 47.8 MiB (service), tool parity 6 and 6 with equal hashes

Local commands run

(this head, the adjudicated commit 8, rebased onto main d8f7e2051; `git merge-tree` clean:)
$ python3 -m unittest tests.test_mcp_template_drift tests.test_mcporter_selectors
  the final tests on 55dba7f4: Ran 48 tests, FAILED (failures=70, errors=1); at this head: Ran 48 tests, OK (45 + 3)
$ python3 -E -s -B <mutation script over the module>  ->  43 of 43 mutants killed (survivors: none)
$ python3 -m unittest <the 114 modules that name a file this branch changes, or that main changed in #995, #1026 or #949, one process each, three at a time, temporary directory on the repository's filesystem>
  114 modules, 6677 tests, OK (skipped=88)
$ python3 scripts/validate.py  ->  exit 0 (11,800 files); scripts/evidence_manifest.py --check  ->  exit 0; scripts/final_stack.py --check  ->  exit 0; tools/adoption/new_wsl_client_config.py --check  ->  exit 0; sha256sum -c on both SHA256SUMS files  ->  exit 0
(commit 7:)
$ python3 -m unittest tests.test_mcp_template_drift tests.test_mcporter_selectors
  the tests of 55dba7f4 over the implementation of cecf039f: Ran 41 tests, FAILED (failures=17, errors=3) in 5 tests; at 55dba7f4: Ran 41 tests, OK
  (CORRECTED: this line first read failures=16, which was false; it left out the case "a number that spells a file" of the source test, which also fails on cecf039f. Measured twice by the command center, once by Astra
  with the actual cecf039f source and the 55dba7f4 tests, and here: fail-before-cecf039f9-of-55dba7f4c.txt)
$ python3 -E -s -B <mutation script over the module>  ->  36 of 36 mutants killed (survivors: none)
$ python3 -m unittest tests.test_mcp_template_drift tests.test_mcporter_selectors tests.test_evidence_manifest tests.test_final_stack tests.test_published_digest_privacy tests.test_new_wsl_client_config  ->  Ran 364 tests, OK (skipped=1)
$ python3 scripts/validate.py  ->  exit 0 (11,776 files); scripts/evidence_manifest.py --check  ->  exit 0; scripts/final_stack.py --check  ->  exit 0
(commit 6:)
$ python3 -m unittest tests.test_mcp_template_drift tests.test_mcporter_selectors
  the final tests on 4916d3a4: Ran 37 tests, FAILED (failures=45, errors=10); on 6a7a7ce7: FAILED (failures=82, errors=26); at this head: Ran 37 tests, OK
$ python3 -E -s -B <mutation script over the module>  ->  29 of 29 mutants killed (survivors: none)
$ python3 -m unittest <the 64 modules that name a changed file, one process each, three at a time>
  64 modules, 4159 tests, OK (skipped=51), except one: tests.test_token_e2e_grader failed 1 of 624 (F27c_KeysOnRealContent: `git clone --local` into a temporary directory on tmpfs, "Invalid cross-device link"); with the temporary directory on the repository's filesystem it passes: Ran 1 test, OK
$ python3 scripts/validate.py
exit 0 ({"components": 70, "hashed_files": 11761, "profiles": 4, "receipts": 239, "status": "passed"})
$ python3 scripts/evidence_manifest.py --check
exit 0 ({"files": 11761, "status": "passed"})
$ python3 scripts/final_stack.py --check
exit 0
$ python3 tools/adoption/new_wsl_client_config.py --check
exit 0 (check passed)
$ python3 tools/adoption/mcp_template_drift.py --with-authorization-settings --acknowledged adoption/new-wsl/mcp-drift-acknowledged.json
exit 0 (summary: SAME 13, DIFFERS 7, TEMPLATE-ONLY 0, LIVE-ONLY 5; acknowledged 12; unacknowledged 0; stale acknowledgements 0)
(after the rebase onto main a365d8bec, head cecf039f9:)
$ python3 scripts/evidence_manifest.py --check, python3 scripts/validate.py, python3 scripts/final_stack.py --check  ->  exit 0, 0, 0 (11,776 files)
$ python3 -m unittest tests.test_mcp_template_drift tests.test_mcporter_selectors tests.test_evidence_manifest tests.test_final_stack tests.test_published_digest_privacy tests.test_memory_landscape_capture_doc tests.test_new_wsl_client_config  ->  Ran 376 tests, OK (skipped=1)
(earlier heads:)
$ python3 -m unittest tests.test_new_wsl_client_config tests.test_install_claude_profile tests.test_codex_worker_lane tests.test_command_position_oracle tests.test_landscape_sweep_harness tests.test_task_model_routing tests.test_token_lanes_subagent_start tests.test_adoption_docs_consistency tests.test_codex_roles tests.test_codex_agents tests.test_mcp_template_drift tests.test_evidence_manifest tests.test_final_stack tests.test_skills_manifest tests.test_install_skills
  Ran 1120 tests in 481.7s, OK (skipped=17); then tests.test_local_pages_adoption ... tests.test_token_full_save_evidence: Ran 764 tests in 208.6s, OK (skipped=26) (the tree before the rebase onto main 83cec12ee)
  commit 5: the 64 modules that read manifests/stack.json, recipes/README.md, docs/token-efficiency-stack.json, the saturation audit, the foundation-memory catalog, the example or the drift tool, in three batches: Ran 1094, 1326 and 1194 tests; the only failures were five in tests.test_final_stack, because catalogs/landscape/final-stack.json carries the digest of manifests/stack.json (scripts/final_stack.py --write changed that one line; tests.test_final_stack then Ran 72 tests, OK)

Decision record

docs/decisions/2026-10-12-mcp-template-live-reconciliation.md carries the measurement, the decision, the gate evidence, the alternatives (rebase #834, put the four live-only servers into the templates, keep the short key, fix the host from here) and the conditions that overturn it. The new-WSL client configuration record gains a dated addendum with its counts.

Host evidence

Only relevant when this PR adds or changes files under evidence/hosts/. This PR changes none.

Checklist

  • New/changed GitHub Actions are pinned to a full commit SHA with a version comment (no floating tags). None changed.
  • New/changed workflows declare top-level permissions: {} and grant each job only what it needs. None changed.
  • No secrets are printed, logged or committed; no new required secret was added without a documented owner. The report prints no value of a registration: names, counts, fixed words, and two fields that are printed as names (the host label and the command's file name); tests scan both output formats and both streams for the seven credential-bearing argument forms, five option-shaped forms, five URL forms, a sentinel in every kind of value, and 300 seeded random values placed in the positions the test names. The pre-commit gitleaks scan of the fix-wave commits found no leak; the co-op's scan of the PR's earlier added lines found no credential (its only URL-credential match is the synthetic sentinel fixture).
  • No new paid hosting, subscription or billing surface was introduced.
  • Peer-owned untracked files and worktrees were preserved (not deleted, moved or overwritten).

Follow-ups

  • Stored client configuration is the command center's act on a reviewed diff. The 12 acknowledged rows stay as they are, each with a reason in the acknowledged file and the decision record: 5 LIVE-ONLY (agentsview, grafana and hindsight in Claude Code; hindsight and promptfoo in Codex) and 7 DIFFERS (headroom's proxy port and SocratiCode 1.16.0's launch and environment in both clients; Codex chrome-devtools enabled, Codex codebase-memory-mcp env_vars, Codex jcodemunch enabled_tools).
  • Legacy registration (the command center's ruling on 4916d3a4): an installer migration for hosts installed from the previous template that removes codebase-memory when the vendor key is present, with a test that starts from the old registration, is a follow-up PR; the first host already runs the vendor key.
  • Codex promptfoo: the ruling names the Claude template; the Codex entry forwards a gateway key by name and is a separate decision. promptfoo currency is done on the command center's side (the mirror ref is 0.124.0, 30949931, synced 2026-10-12 09:46:05Z).
  • Research rows for the two loopback routes that accept any Origin (ai-memory: validates Host only; hindsight: neither) go to the co-op's research queue (rule 8) with the specification citations above; the shared jcodemunch service is not retried until a version answers an invalid Origin with 403.
  • The four-byte trim of draft Align code graph MCP server key with native client registrations #834 (RULING-Q26) is not carried: the instruction sources no longer name the server, so the rename adds no startup bytes (checked by the pinned-byte tests above). Align code graph MCP server key with native client registrations #834 is closed as superseded.
  • The report reads user scope only. Project-scope .mcp.json, local-scope entries and plugin servers (plugin:context-mode:context-mode) are out of its reach by design; claude mcp list remains the check for those.
  • Command center dispositions (2026-10-12): the Codex jcodemunch entry is narrowed to the template in the stored configuration after this lands, and its enabled_tools acknowledgement is removed in the same step (it goes stale by design); Codex chrome-devtools stays disabled (acknowledged); the CBM_* forwarded variables stay; the headroom port and SocratiCode 1.16.0 stay acknowledged until the currency decision (lupe / FIX-6).
  • P3s still open, for a later change (not blockers under the scope lock): (1) the short graph key survives in adoption/templates/codex.config.template.toml L60 (a comment), examples/claude-native/workflows/child-usage.mjs L716 and L973 (comments citing stack.json:280, stale since the base), adoption/update.md L149 (the short key, in the present tense) and docs/token-session-handbook.md L456 (six Codex servers and local-scope jcodemunch): correct them with a dated supersession and, as history, adoption/bootstrap.md L566-L567 (add the current key); (2) unpinned moved-line locators in evidence/receipts/codex-serena-startup-port-20261003.json and catalogs/foundation/upstream-surface-dispositions.json: bind them to their recorded revision or add a correction (no rewrite of historical receipts as new measurements); (3) three existing occurrences of the host name in manifests/evidence.json, none added here; (4) an acknowledgement source need not be a tracked file (repository_file accepts an untracked file, or .git in a worktree, beneath the root, which is all the contract asks); (5) the codebase-memory-mcp v0.11.0 source has no local mirror, so its README lines were read from the raw file at the pin: mirror it.
  • Findings of Astra's fourth read and of the command center's verification at 03d92cbd that stay follow-ups (P3; no P1 was reproduced, the one P2 is the receipt corrected above): (1) missing captures and one correction-provenance omission: the packet captures of the pinned CPython, MCPorter, Promptfoo and MCP specification sources, the vendor pin DeusData/codebase-memory-mcp v0.11.0 (unmirrored), the dated Claude MCP page, the live registration, version and launcher reports, the Origin, PSS and parity probes, research-queue.tsv, the earlier scope-ruling message and the thread reply bodies are not attached and stay measurement boundaries; the correction for a command that is not text names no CPython locator for the str() coercion it removes (add one beside it); (2) retained prose and moved-line references: adoption/update.md L149, docs/token-session-handbook.md L456, the old-key installer migration (with a pre-existing-registration control), the unpinned locators of evidence/receipts/codex-serena-startup-port-20261003.json L1843 and catalogs/foundation/upstream-surface-dispositions.json L997, and 234 inline numeric references at or after lines this change moves (candidates, none asserted by a test); (3) the host name in eight changed files (68 lines, none in the patch or the body); (4) retain the mutation script and the module list behind the two figures of the adjudicated commit (the 43 mutants and the 114 modules, 6,677 tests): they are kept in the private research record (fix-wave-3/: drift_mutants.py, modules-r4.txt, modules-results-r4.txt, mutants-adjudicated.txt) and publish with the next change to this tool.
  • Findings of Astra's third read and of the command center's Claude micro at 55dba7f4 that stay follow-ups (P3): the corrections C2 to C5 and the mixed-fields and recursion fixes have no fail-first assertion that pins their sentences (supply the captures and source-consistency checks, or keep the measurement boundary); the numeric references at or after lines this change moves (239 candidates, none asserted by a test); retained prose and the old-registration migration (above); the missing captures (codebase-memory-mcp v0.11.0 is unmirrored; historical live reports, service probes, mutation receipts, queue and ruling captures, reply bodies); the host name in the changed files (3 occurrences in the exact case and 20 in any case in manifests/evidence.json, none added here).
  • Findings of Astra's delta read of cecf039f that stay follow-ups (P3): the corrections C2 to C5 of the record have no fail-first assertion that pins their sentences (supply the captures and source-consistency checks, or keep the measurement boundary); the numeric references at or after lines this change moves (237 detected, none asserted by a test); the host name in eight changed files (68 lines, none in the patch or the body).
  • Stricter printing of the host label and the command's file name, as a follow-up: they stay as names (the command center's ruling to this lane on 2026-10-12, about 10:33Z: they stay as names under the scope lock, they are not argument values, and the stricter option is kept as a follow-up), documented as such. The stricter choice is to print the host only for a loopback literal and the command only from a fixed set of known launchers; it would cost the report the information which remote host or program a registration reaches.
  • Research queue (rule 8, not a blocker): acknowledgements match field names, not value predicates (a changed headroom argument stays acknowledged although only the port was meant); whether the schema should constrain values as well is a policy change for the owners of the mcp-surfaces layer. The row is filed in the co-op's research-queue.tsv (2026-10-12T11:43:12Z) and routed to the research backlog of cc-native-practice (queued; the readiness trigger is this PR landing).

🤖 Generated with Claude Code

Follow-ups after landing

Landed at 2f59d74 on 2026-10-12T17:05:25Z from head 03d92cb (Claude-family verification PASS_WITH_P3; GPT delta with no P1, its P2 a body figure corrected before landing; Codex unavailable). The follow-ups listed above carry forward; none blocks.

@seathatflowsinourveins seathatflowsinourveins added the lane:foundation Foundation lane: Claude/Codex setup, hosts, memory, RAG, research, workers label Oct 12, 2026
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 12, 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-10-12T09:13:38.841134Z 4916d3a 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: 6a7a7ce799

ℹ️ 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/mcporter.json.example
Comment thread tools/adoption/mcp_template_drift.py Outdated
Comment thread tools/adoption/mcp_template_drift.py Outdated
Comment thread tools/adoption/mcp_template_drift.py Outdated
seathatflowsinourveins added a commit that referenced this pull request Oct 12, 2026
…dgement 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>
@seathatflowsinourveins

Copy link
Copy Markdown
Collaborator 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: 4916d3a479

ℹ️ 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 adoption/mcp/claude-user.json
Comment thread tools/adoption/mcp_template_drift.py
Comment thread tools/adoption/mcp_template_drift.py
Comment thread tools/adoption/mcp_template_drift.py Outdated
seathatflowsinourveins added a commit that referenced this pull request Oct 12, 2026
… 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>
@seathatflowsinourveins
seathatflowsinourveins force-pushed the claude/cc-native-practice-mcp-template-reconcile-20261012 branch from 2d131c0 to cecf039 Compare October 12, 2026 10:50
seathatflowsinourveins added a commit that referenced this pull request Oct 12, 2026
…dgement 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>
seathatflowsinourveins added a commit that referenced this pull request Oct 12, 2026
… 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>
@seathatflowsinourveins

Copy link
Copy Markdown
Collaborator Author

@codex review

@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.

seathatflowsinourveins added a commit that referenced this pull request Oct 12, 2026
… 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>
@seathatflowsinourveins

Copy link
Copy Markdown
Collaborator Author

@codex review

@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.

…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>
…'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>
…rations 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>
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>
…dgement 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>
… 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>
… 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>
…e 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>
@seathatflowsinourveins
seathatflowsinourveins force-pushed the claude/cc-native-practice-mcp-template-reconcile-20261012 branch from 55dba7f to 03d92cb Compare October 12, 2026 15:34
@seathatflowsinourveins

Copy link
Copy Markdown
Collaborator Author

@codex review

@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.

@seathatflowsinourveins

Copy link
Copy Markdown
Collaborator Author

@codex review

@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.

@seathatflowsinourveins
seathatflowsinourveins merged commit 2f59d74 into main Oct 12, 2026
38 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lane:foundation Foundation lane: Claude/Codex setup, hosts, memory, RAG, research, workers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant