Repository navigation
Landscape sweep: link killed attempts re-run under a changed call key; redact dash-encoded project dirs - #696
Conversation
…; redact dash-encoded project dirs After a usage-limit pause, a workflow resumed from its cache can re-run a unit under a changed call key, because the unit's prompt embeds earlier stages' outputs. child-usage.mjs (vendored, unchanged) then leaves the killed attempt as an incomplete child, the record reads "incomplete", and convert.py turns its empty effort list into an effort_deviation retained failure that reopens the layer. - usage_record.py: in post-processing, links an incomplete child only to a LATER complete attempt with the same label in the same run (journal order), as superseded_by with the reason "re-run under a changed call key after a usage-limit pause"; its usage still counts in by_resolved_model; the tool's raw exit_code and raw_output_sha256 stay as recorded, and measurement.post_processing names the linking. - convert.py: a superseded attempt whose same-label re-run completed at max is not an effort_deviation failure; it stays visible under superseded_retained per layer. It also redacts the dash-encoded Claude projects-directory home segment (-home-<user>-...) as <project-dir> wherever it occurs. - make_result.py: the same supersession rule for actual and listed effort deviations. - Failing-first fixtures: a killed critic under a changed key, a killed follow-up refuter, the redaction forms; controls: no later attempt, a later incomplete attempt, an earlier complete attempt, a non-superseded non-max attempt, ordinary words containing -home-. Built by the GPT-6.1 Sol worker; committed by the coordinator; a Claude read follows. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…; anchor the home redaction (review P2s) - usage_record.py links only children whose issues include 'no result entry in journal' and only when the label has exactly one complete child; the reason records only what was observed; post_processing keeps source_reason, the linked and covered agent ids and the covered mismatches; multi_model_children is recomputed; the summary prints raw_exit_code and exit_code separately. - convert.py derives the encoded home from Path.home() (and its realpath), redacts it as a whole segment, bare form included, anchors the generic form after projects/ or claude-<uid>/, never ends a match on a period, and redacts dict keys and the printed summary. - Tests: partial link, make_result negatives, redaction controls (prose, sentence end, dict key, stdout); the native test fails clearly without node. README: unsupported failing-first counts removed. Built by the GPT-6.1 Sol worker after a bounded Claude Opus read (ACCEPT, six P2s). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3fef158268
ℹ️ 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".
…d and bare; checkout-derived local forms (review P1 on convert.py:695) GPT-6.1 Sol rounds sweep-superseded-d and -e through the packaged SDK worker: - the anchored generic form now covers -home-, -Users-, -mnt-<d>-Users- and <D>--Users- profile roots; - a generic bare-home slug followed by /, a quote, whitespace or the end is redacted unanchored; - local forms come from the home, the resolved checkout and the work dir. Acceptance: 477 tests OK (8 skips), validate.py 0, evidence_manifest --check 0, git diff --check 0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fore the final hot-file commit Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… (hot-file protocol: every hot-file edit in the last commit) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ary; fail closed on redacted-key collisions (Opus read P1, P2s) GPT-6.1 Sol repair round through the packaged SDK worker; acceptance in the round's result. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fore the final hot-file commit Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… (hot-file protocol: every hot-file edit in the last commit) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…re, URLs included, aligned with #697's publication rule (Opus read P1, P2s) GPT-6.1 Sol round sweep-superseded-g: - the local rule and the generic rules run over URL tokens again; - redacted-key collisions fail closed; - the docs state that until #697 lands, the publication check detects no dash-encoded path. 486 tests OK (8 skips), including a run with #697's candidate pattern added. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fore the final hot-file commit Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… (hot-file protocol: every hot-file edit in the last commit) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… claims, publication-safe refusals (round h) - convert.py: every Users branch (bare -Users-, Windows drive and /mnt forms) matches in any case, as #697's rule does at 0d2a38b; -home- and the example exemption stay case-sensitive. Fixtures cover case variants in bare text, after projects/ and claude-<uid>/, in URLs, assignments, JSON keys and values (c5 P1). - README and docstrings name #697 at 0d2a38b and state exactly which roots and contexts both rules cover (P2). - Dots-only names are redacted; the example boundary matches #697's; the local rule consumes dotted and underscore name continuations; residues are checked before any artifact or summary is written (exit 3, nothing written); collision errors print index locators, never key text (P3a-e). - A regression test runs the redactor's output through the actual encoded-home rule in scripts/validate.py; it fails until #697 is on the base (no skip), and passed 113,400 constructed cases with #697's validate.py overlaid. GPT-6.1 Sol round sweep-superseded-h through the packaged SDK worker; the coordinator commits. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fore the final hot-file commit Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… (hot-file protocol: every hot-file edit in the last commit) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ocations and re-pin their hashes (#697) ### Scope - **Pattern:** `scripts/validate.py` PRIVATE_CONTENT gains an **encoded home path** pattern. It catches the dash-encoded paths that Claude Code uses for project and scratchpad directories: `-home-<name>-`, `-Users-<name>-` and the Windows `<drive>--Users-<name>-`. The existing `/home/<name>/` pattern missed them, so an evidence redaction could report zero remaining hits. - **Redactions:** the new pattern found 11 committed locations, now redacted to `-home-<user>-` (the 2026-09-26 precedent): - six socraticode token-comparison run outputs; - five lines of the blind-catalog-convergence coverage review. These held another host's user name inside encoded paths. - **Pins:** every hash that pinned a redacted file is updated: the gap-wave2 receipt raw-artifact hashes, the closure provenance and the convergence record frozen inputs. - **Test literal:** a planted literal in `tests/test_token_e2e_grader.py` is now built at run time, so the source no longer matches. The tested input is unchanged. - **Base:** origin/main. **Lane:** `lane:foundation`. ## SOTA sources - Repository redaction precedent: `evidence/artifacts/landscape-sweep-20260926/returns.json` (`-home-<user>-`). - Claude Code stores sessions under `~/.claude/projects/<encoded cwd>/`: https://code.claude.com/docs/en/settings - Found by the Claude read of #692. The paired converter fix, which redacts this form at write time, is #696. ### Local commands, run at the head with TMPDIR outside /tmp - `python3 scripts/validate.py`: passed. It includes the full tracked-tree scan, now 0 hits. - `python3 scripts/validate_convergence.py --all-recorded --root . --json`: 0. - 18 test modules, including test_validate, test_token_e2e_grader, test_sota_convergence and test_host_receipts: 1,320 tests OK, 5 skipped. - Merge-tree landing check: LANDABLE. ### Review - Built on the GPT lane (Sol, max), over two rounds. - [ ] Claude cross-family read: requested. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
…egistry plus the owned rows) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fore the final hot-file commit Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… (hot-file protocol: every hot-file edit in the last commit) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…f the exact emitted bytes - convert.py: the private-name rule now ends on a name-start lookahead. It removes punctuation, Unicode and control-character tails in bare, anchored and URL contexts. The example controls, root-case rules and prose controls still pass through. Local name continuations consume Unicode word characters, dots and dashes. - Before the output directory is created, artifacts and the summary are serialized with write_json's own serialization. The decoded documents and the exact emitted text are scanned, and the inspected UTF-8 bytes are what gets written. Serialized residue exits 3 and publishes nothing. - README and docstrings: the delimiter coverage is unrestricted (distinct from #697's terminator rule), projects/ and claude-<uid>/ use the same generic rule, and the scan is described as covering both decoded and serialized output. - Tests: non-name tails in every context, serialized profile tails with a Unicode summary, refusal on serialized residue, and the CLI wiring of the selected checkout's PRIVATE_CONTENT. Built by GPT-6.1 Sol through the packaged SDK worker (round sweep-superseded-i); committed by the coordinator. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fore the final hot-file commit Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… (hot-file protocol: every hot-file edit in the last commit) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…egistry plus the owned rows) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fore the final hot-file commit Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… (hot-file protocol: every hot-file edit in the last commit) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Claude session native-agent-stack-5f: landing at head Observed main Required checks at this head: 7 pass . Unresolved review threads: 0. |
|
Claude session native-agent-stack-5f: post-merge observation. Landed as |
…into the Codex rtk hook branch Conflicts were only in the generated and hot files: docs/new-wsl-handbook.md, the handbook receipt and manifests/evidence.json. Resolved by the hot-file protocol (docs/lanes.md): main's copies taken, the branch's 44 registry entries re-registered from the pre-merge snapshot, the handbook regenerated with main's generator (#724) and the receipt's output digests refreshed, component_matrix and new_host_grand_list rewritten. validate.py, validate_convergence.py --all-recorded, build_new_wsl_handbook.py --check and check_plan.py (80 rows, 163 commands, 101 acceptance entries) pass on the merged tree. The branch's own content, including the 705g repairs of 1b8d4c0, is unchanged by the merge. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…(second of two; the user's relayed pointer yes) (#705) ### Scope - Second of the two pull requests of `docs/decisions/2026-10-04-codex-rtk-hook-qualified.md` (the first, #701, landed as `287514581`; this branch was based on main `4c897418f`, after #699 and #704, and carries main `4af7417b7`, after #720, #712, #696 and #724, as a merge commit). The install plan's `command-output` row now installs RTK's Codex PreToolUse hook with upstream's own command and trusts it: 1. two commands after the existing four: `rtk init -g --codex`, then `python3 tools/adoption/codex_hook_trust.py --command "rtk hook codex" --apply`; 2. its post_install acceptance gains the two Global `[ok]` lines of `rtk init --show --codex` and `codex_hook_trust.py --check`; a new after_sign_in acceptance runs a fresh `codex exec` told to add no prefix and requires the first `rtk git status` command item to have `exit_code == 0` and `status == "completed"` (review thread 1; **UNRUN**: the model call needs the sign-in); 3. the trust tool's execution-rule review and `--check`. Codex rewrites a call to `rtk <command>` before it matches execution rules on the command words, so a `forbidden` or `prompt` rule on a command rtk can rewrite no longer matches it, and the rewrite space is not finite (env prefixes, global options such as `git -C`, absolute paths, wrappers, PHP tool spellings, user filters and Unicode word boundaries all change what rtk rewrites, and the rewrite changes words after `rtk` too: `cat f` becomes `rtk read f`). Three GPT reads each found a bypass in an analysing version of the review, so the tool now **parses nothing** (the design 5f recommended after 705f): it reads each regular `*.rules` file of `<codex home>/rules` as bytes and accepts it only if (1) its sha256 is on `tools/adoption/exec_rules_reviewed.json`, an exact-bytes review for one rtk version (`rtk --version` must match the entry, `rtk config` must show `transparent_prefixes = []`, `rtk trust --list` must say `No trusted filters.`, `RTK_TRUST_PROJECT_FILTERS` must be unset, the user TOML filters file beside rtk's config must hold no filter; today one entry, #713's `hcom-deny.rules` at head `7fbe586f3`, sha256 `ac6254ee…`, after its repair round 2 changed comments and justification strings only), or (2) it holds nothing but allow rules in Codex's own format byte for byte (the lines `amend.rs` writes, hcom's own `hcom.rules` with its one comment line, empty lines), none containing the letters `rtk` anywhere (the rewrite inserts that word, as a token or inside a shell-script token, so such a rule matches the rewritten command and not the original: codex-cli 0.159.3 `execpolicy check` allows `rtk git push origin main` under `["rtk"]`, and the script token `FOO=1 rtk git push origin main` under `["/bin/bash", "-lc", ...]`, and gives no decision for the originals; 705g P1-1). Anything else is an exposure: `--apply` refuses with exit 2 before the app-server starts (so before any write, even for an already trusted hook), `--check` exits 6 for a trusted hook beside one (so the post_install acceptance catches a rule file added or edited after the grant), `--allow-exec-rules` accepts it. The listing is Codex's `collect_policy_files` mirrored fail-closed (only opening the directory may report it missing; each entry's type comes from its own `lstat`, so an entry that vanished raises; a symlink, directory or named pipe is not loaded and never opened). `--check` exits 0 only while every named hook is trusted and no rule file is exposed, 5 when a hook is not trusted, 4 when none matches, 6 when it is trusted beside an exposure; mutually exclusive with `--apply`, no edit, no backup. The plan's trust and check commands pass `--rtk "$e/bin/rtk"`. 81 unit tests (local stand-ins for the app-server and for `rtk --version`, `rtk config` and `rtk trust --list`), 63 mutants each failing one; 4. text that follows the row: the plan README sentence, the token session handbook paragraph (Codex runs RTK through the hook, and the exclusions are what make it leave `git show REV:path`, `diff`, `jq` and `git branch` alone), a dated note on the RTK card (cards are dated editions), the F9 recipe sentence and its owner-list test (`command-output` joins the after-sign-in owners), the new-WSL profile (`adoption/new-wsl-profile.{json,md}`), the definitive manifest and the consensus record it copies, which no longer say that `rtk init --global --codex` is never run (review thread 2; the manifest's declared consensus digest follows), the regenerated new-WSL handbook and its receipt's digests (the `wsl-new-distro-image` convergence record needs no re-pin: #704 freezes copies of the recipe and its test); the F9 owner list is #704's, with `command-output` added; 5. the decision record's addendum, which quotes the user's answer **as relayed by the command center**: "yes for rtk pointer" (00:49:16Z in the command center's transcript, part of a longer message), and a standing rule, "for the practice like rtk, always proceed with sota convergence highest quality practice with upstream repos" (00:50:08Z, a queued message; the command center first relayed both as "about 00:55Z", an estimate, and corrected the times). The writing session heard neither; both rest on that relay, which the user may withdraw. The answer covers what `rtk init -g --codex` does beyond the hook (RTK.md and an inert `@<Codex home>/RTK.md` pointer line in the Codex `AGENTS.md`; there is no hook-only mode with `--codex`), and a second addendum answering review thread 3: Codex rewrites the call before approval and matches execution rules on the rewritten words, rtk rewrites 36 of 55 measured commands including mutating ones, and rtk has no allow-list, so the trust step is guarded instead of limited (sources at both Codex pins and rtk 0.51.0, alternatives and the untested boundary in the record). - Base commit: `4af7417b7` (main after #720, #712, #696 and #724; the branch's own base was `4c897418f`) - Lane: `lane:foundation` - Owned paths touched: `evidence/artifacts/new-wsl-install-plan-20261002/{install-plan.json,install.sh,accept.sh,README.md}`, `evidence/artifacts/token-stack-fresh-session-e2e-20261004/**` (README, the scratch-run script and its output, `fixtures/hcom-deny.rules`, the mutation check, the heads derivation, its binary check and the heads file `rtk-rewrite-heads.json`, now review evidence beside them), `tools/adoption/exec_rules_reviewed.json`, `evidence/artifacts/new-wsl-handbook-20261001/receipt.json`, `docs/{token-session-handbook.md,token-efficiency-stack.json,new-wsl-handbook.json,new-wsl-handbook.md}`, `adoption/new-wsl-profile.{json,md}`, `evidence/artifacts/new-wsl-definitive-defaults-20261001/definitive-manifest.json`, `evidence/artifacts/new-wsl-layer-consensus-20261002/consensus.json`, `docs/decisions/2026-10-04-codex-rtk-hook-qualified.md`, `adoption/platforms/linux-wsl2-new-distro.md`, `tools/adoption/codex_hook_trust.py`, the tests, and `manifests/evidence.json` (last commit, `registry:`). Nothing is installed or trusted on any host by this change. ### SOTA sources - RTK: rtk-ai/rtk v0.51.0 at `e001f773f80b22b7dc4c7a79521b30e35aaef026`, `README.md` L133 (`rtk init -g --codex`), the installed `rtk init --help` (`--codex`: "uses PreToolUse hook + AGENTS.md + RTK.md"; `--hook-only`, `--no-patch` and `--auto-patch` refused with it), `rtk init --show --codex` and `rtk-init-codex-probe.json`. - Codex hook trust: openai/codex rust-v0.159.3, commit `01fc69f4026735edfdf6789820549727a4867b11`, `codex-rs/tui/src/hooks_rpc.rs` L58-L91 (`write_hook_trusts`: the `/hooks` review persists trust with `config/batchWrite` of `hooks.state`) and `codex-rs/hooks/src/engine/discovery.rs` L775-L815 (hash and status), which `codex_hook_trust.py` reproduces. - Codex hook dispatch and approval (review thread 3), identical lines at rust-v0.159.3 `01fc69f40267` and rust-v0.160.0 `a956835d0207`: `codex-rs/core/src/tools/registry.rs` L603-L660 (PreToolUse hook, `invocation = updated_invocation` L632, handler L689), `codex-rs/core/src/exec_policy.rs` L327-L420 and L770-L850 (rules matched on the command words; unmatched fallback), `codex-rs/shell-command/src/command_safety/is_dangerous_command.rs` L133-L143 (forced `rm`, unwrapping `sudo` and `env`), `codex-rs/hooks/src/events/pre_tool_use.rs` L357 and L388-L405, and `codex-rs/exec/src/exec_events.rs` L151-L166 (`CommandExecutionItem`: `exit_code`, `status`); `codex execpolicy check`, Codex's own rule evaluator. - Execution-rule review, rust-v0.160.0 `a956835d0207`: `codex-rs/core/src/exec_policy.rs` L1121-L1170 (`collect_policy_files`: only opening the directory may report it missing, errors on the iteration and on an entry's file type propagate, every entry's type is asked before its extension, symlinks are not loaded), L645-L660 (`load_exec_policy_with_warning`: a parse error in any rules file makes Codex load no file rules), `codex-rs/execpolicy/src/amend.rs` (`blocking_append_allow_prefix_rule`: the format of the allow-only `default.rules`), `codex-rs/execpolicy/README.md` (`prefix_rule` and `host_executable` builtins, strictest decision wins). The 705f counterexamples rest on: `codex-rs/execpolicy/src/parser.rs` L64 and facebook/starlark-rust `starlark_syntax/src/lexer.rs` L415 at `0c8d107ab963` (a raw CR inside a string is dropped), `codex-rs/shell-command/src/bash.rs` L492, `codex-rs/core/src/exec_policy.rs` L876 and `codex-rs/core/src/shell.rs` L22 (assignment-prefixed scripts fall back to the whole shell argv); rtk v0.51.0 `e001f773f80b`: `src/discover/registry.rs` L393-L418 and L1811 (PHP tool normalization), `src/core/toml_filter.rs` L199-L227 and L456-L495 (filters load only while trusted; trusted user filters keep the complete pattern, alternative branches allowed), `src/hooks/trust.rs` L51-L166 and `run_trust` (the global trust store, `rtk trust --list`, and the `RTK_TRUST_PROJECT_FILTERS` + CI override), `src/discover/registry.rs` L1743-L1763 (`exclude_commands` is applied before the TOML-filter rewrite), `src/filters/gcc.toml` L3 and the rust-lang/regex word-class contract (Unicode `\b`), `src/discover/rules.rs` (94 `RULES` patterns, each `^`-anchored), `src/discover/registry.rs` L64 (`ENV_PREFIX`), L194-L215 (`classify_command` normalization), L438 and L568 (global options, absolute paths), L1386-L1498 (`PROCESS_WRAPPERS`, shell keywords, `uv run`), L1743-L1760 (the TOML filters are a second rewrite source), `src/filters/*.toml` (62 builtin filters), `src/core/config.rs` L119-L145 (`transparent_prefixes`), `src/main.rs` L3072-L3100 (`rtk hook check`: exit 0 with the rewrite, exit 1 with `No rewrite for:`) and `rtk config`'s output (`show_config`). hcom's own rule file (aannoo/hcom `7151660a3`): `src/hooks/codex.rs` `build_codex_rules` L1508-L1534 and `HCOM_TOOL_NAMES` L578-L585, `src/hooks/common.rs` `SAFE_HCOM_COMMANDS` L52-L72. - rtk v0.51.0 `e001f773f80b`: `hooks/codex/README.md` L14-L24 (the rewrite precedes Codex's approval and sandbox checks), `src/hooks/permissions.rs` L64-L72 (no Codex rule source), `src/core/config.rs` L119-L123 and `src/discover/registry.rs` L1548-L1582 (`exclude_commands` is exclusion-only), `rtk hook check --agent codex`. - Codex expands no `@` reference in `AGENTS.md`: `docs/token-efficiency-stack.md`, citing `codex-rs/codex-home/src/instructions/mod.rs` at rust-v0.157.1. - The plan's own conventions: `check_plan.py` (commands, acceptance and scripts agree), the hot-file protocol of `docs/lanes.md`, and #694's re-pin of the recipe-freezing convergence record. ### Evidence-class table | Claim | Evidence class | Command / receipt | | --- | --- | --- | | The row's steps, read from `install-plan.json` and run in scratch HOMEs with rtk 0.51.0 and codex app-server 0.159.3: `--check` exit 4 before the hook exists; `rtk init -g --codex` 0 (the hook lands at `pre_tool_use:1:0`, after a memory hook's group); `--check` 5 before the trust; the trust 0 ("read back from hooks/list by key and hash"); the post_install program 0; and nineteen homes for the rule review: #713's `hcom-deny.rules` by its exact bytes lets the trust proceed, and a `git push` rule added after the grant makes `--check` exit 6 and the trust refuse; the same bytes plus one comment line, a configured rtk transparent prefix, a user TOML filter beside the reviewed file, a trusted project filter and the CI override variable `RTK_TRUST_PROJECT_FILTERS` (the last two each make the real rtk rewrite `hcom kill luna`, recorded before and after, and with rtk exclusions for `hcom` and `uvx hcom` in its config the same filters leave both commands alone) are each refused; Codex's `default.rules` format and hcom's `hcom.rules` format let the trust proceed; a `git push` forbid rule is refused (exit 2, nothing written; `--check` 5), accepted with `--allow-exec-rules`, after which `--check` exits 6; the same rule with its `rtk git push` twin is still refused; the counterexamples of 705e (`git -C .`, broad `uv` and `npx`, the nested `host_executable` file, under which the real codex evaluator forbids `git push origin main`) and of 705f (a raw CR in a token, a `bash -lc` script rule, `phpunit.exe`, `g++` plus a combining mark, each of which the real rtk rewrites or the real evaluator reads differently), an allow rule that holds `rtk` (the evaluator allows `rtk git push origin main` under `["rtk"]` and the script token `FOO=1 rtk git push origin main` under a `bash -lc` rule, and gives no decision for the originals; the real hook produces the second from `FOO=1 git push origin main`) and an unreadable rules directory are refused (79 steps, all as expected) | `local_integration`: one run, one host | `plan_row_scratch_run.py`; `plan-row-scratch-run.json` (the trust command carries `--codex-process-name no-such-process-name` because other codex processes ran on the host; recorded in the file) | | The after_sign_in filter and test, taken from the plan's own text, over six streams in the shape of Codex's JSONL command item: the good one (`rtk git status`, exit 0, completed) ends 0, and five negative fixtures (exit 127, completed with exit 1, declined, no rtk prefix, no command item) end 1 | `synthetic` | same file, the six after_sign_in steps | | The after_sign_in check with a real fresh `codex exec` and a signed-in launcher | **not run** | untested boundary: the host step after the sign-in; the earlier arms R1 and R2 of `codex_hook_qual.py` showed the same prefix through the gateway route | | `--check` and the review, with local stand-ins for the app-server and for `rtk --version` and `rtk config` (`FakeRtk`): `--check` 0 when trusted and no rule file is exposed, 5 untrusted or modified, 4 none matches, 6 trusted beside an exposure; no edit and no backup; `--apply` refused with exit 2 before the app-server starts (no `AppServer` call, no backup, no write) for every counterexample above, a reviewed file with one changed byte, another rtk version, a failing rtk, config or trust-list command, a configured prefix, a trusted filter, the override variable or a user filter, a missing or malformed reviewed list, an unreadable file, and 29 near-misses of the allow-only grammar (a prompt line, CRLF, a tab, an escape, a non-ASCII byte, a justification, alternatives, a second statement, ...); accepted: the reviewed bytes under another name, Codex's and hcom's allow-only files (hcom's rebuilt from its installer's source lists), empty and comment-only files, tokens that merely contain the letters `rtk`; a listing in which an entry vanished, an iteration or an open raised, or a path that is a file is refused, while a symlink, directory or named pipe is not loaded (the pipe is never opened) | `synthetic` (fake app-server, fake rtk, fake `scandir`) | `tests/test_codex_hook_trust.py` (81 tests) | | The reviewed entry rests on the real rtk 0.51.0: the derived heads (`rtk-rewrite-heads.json`, 142 from the 94 RULES patterns and 62 builtin TOML filters, the wrappers and the env prefix) agree with the binary: a positive control for each of the 94 patterns, 13,041 scanned commands (1,449 names, 9 argument shapes) with 623 rewrites and none outside the heads, 67 wrapper prefixes in front of `git status` (24 rewritten, all led by a head), 8,884 spellings of the 101 literal heads with 480 rewrites and none outside the heads; and the entry's own first tokens `hcom` and `uvx` in 22 spellings and 8 shapes (352 commands) are never rewritten. The derivation had 101 gaps in the first scan (the `r#"..."#` sbt rule, the TOML filters, `\b` continuations such as `gcc-13`), now 0. Review evidence, not a gate: the tool reads neither file | `local_integration` (the scan can falsify the review, not prove it) | `derive_rtk_rewrite_heads.py`, `check_rtk_rewrite_heads.py`; `rtk-rewrite-heads-check.json` | | The tests discriminate: 63 mutants (listing: a `FileNotFoundError` on an entry or the iteration or an open error read as no rules, the extension before the file type, a followed symlink, a named pipe loaded, any name ending in `rules`, an unsorted listing; grammar: a prompt rule, a quote, a backslash, a tab or CR in a token or comment, trailing text, `any` for `all`, no empty lines, any comment, spacing, an empty pattern, an allow rule that holds `rtk` in four variants (a token after a wrapper, whole-token only, inside a shell-script token, only a leading token); the reviewed list: a malformed, uppercase or over-long hash, a malformed list read as empty or not blocking, the list read with no rule file; the decision: every file reviewed, every file allow-only, an unreadable file not blocking, rtk asked for allow-only files; rtk conditions: the version gate, exit statuses, the `Config:` line, transparent prefixes, the trust list (ignored, exit status ignored, matched loosely), the override variable (ignored, only the value 1), user filters, the schema line, comments, an unreadable or non-UTF-8 filters file, no rtk, no PATH lookup, telemetry, a terminal, no time limit; the flow: `--apply` not refusing, the flag accepting nothing or not accepting, `--check` ignoring an exposure or answering 6 before 5, `--rtk` not passed, no dry-run note) each fail at least one test; the tests were written after the code, so this is the check that they are not vacuous | `local_integration` | `rule_review_mutation_check.py`; `rule-review-mutation-check.txt` | | Codex applies the hook's rewrite before approval and matches execution rules on the rewritten words: with a rule forbidding `git push` and one prompting `git commit`, `git push` is `forbidden` and `git commit` is `prompt`, while `rtk git push` and `rtk git commit` get no decision (each answer needs exit 0 and a valid response) | `local_integration` (Codex's own evaluator, codex-cli 0.159.3) and `source_review` for the dispatch order at both pins | `plan-row-scratch-run.json`, `execpolicy_check`; the decision record's addendum | | rtk 0.51.0 rewrites mutating commands: 36 of 55 measured, among them `git push`, `git commit`, `gh pr merge`, `docker run`, `pip install`, `rsync --delete`; 19 are not (`git reset --hard`, `rm -rf`, `npm publish`, `terraform apply` and others); the five `exclude_commands` change none of these | `local_integration`: one run, one host | `rtk_behaviour_probe.py`; `rtk-behaviour-probe.json`, `codex_hook_check` | | A live Codex session with a forbidding execution rule and the hook active | **not run** | untested boundary: derived from the dispatch order and the evaluator above; project and managed rule layers are not visible to the tool; `RTK_TRUST_PROJECT_FILTERS` is checked in the tool's own environment, not in the one Codex runs the hook in, and a filter trusted after the review shows at the next `--check` (705g P1-2: a point-in-time check cannot establish what a global hook does in every working directory; the exclusions of alternative (j) are the enforced hardening and are not enforced here); the reviewed list covers rtk's default hook configuration of one version; hcom's installer itself was not run (its file is rebuilt from its source) | | `install-plan.json`, `install.sh` and `accept.sh` agree | `local_integration` | `check_plan.py`: 80 rows, 163 commands, 101 acceptance entries (with #704's rows) | | The generated handbook and its receipt follow the edited recipe, and the convergence record stays valid without a re-pin | `local_integration` | `build_new_wsl_handbook.py --check` 0; `test_new_wsl_handbook` OK; `validate_convergence.py --all-recorded` 0 | | The user's yes for the pointer and the standing rule | relayed, not heard | the decision record's addendum | ### Local commands run ``` $ python3 scripts/validate.py ; python3 scripts/validate_convergence.py --all-recorded exit 0 ; exit 0 $ python3 -B evidence/artifacts/new-wsl-install-plan-20261002/check_plan.py OK: 80 rows ... 163 commands and 101 acceptance entries agree with the scripts $ python3 -B scripts/build_new_wsl_handbook.py --check exit 0 $ python3 -B -m unittest <24 modules that name a changed file> Ran 1028 tests ... OK (skipped=2) (17 modules that name a changed file, on the merged head; 1522 tests in 24 modules before the merge) $ python3 evidence/artifacts/token-stack-fresh-session-e2e-20261004/plan_row_scratch_run.py <outfile> 79 steps, all as expected $ python3 evidence/artifacts/token-stack-fresh-session-e2e-20261004/rule_review_mutation_check.py 63 mutants, survivors: [] $ gitleaks detect --log-opts="4c897418f..HEAD" no leaks found ``` ### Decision record `docs/decisions/2026-10-04-codex-rtk-hook-qualified.md` gains the 2026-10-05 addendum (the relayed answer, its effect, and the one-command undo: `rtk init -g --codex --uninstall` removes the hook, `RTK.md` and the pointer together), its Residuals sentence now says the user approved the pointer edit, and a second addendum, "approval and execution rules": five sourced findings (item 5 corrected: approvals off do not switch execution rules off, and NativeStack2604 has no user-layer `rules` directory), the decision (the hash-list rule above, why three analysing versions failed, the reviewed list and its conditions, **the pin-move rule: a move of the rtk pin re-reviews the list**, tied to the RTK row of `docs/token-efficiency-stack.json`), the evidence, the limits and what would overturn it, the review rounds, and ten alternatives (an `exclude_commands` read-only limit, whose probe shows `git -C /tmp push` still rewritten; a never-rewrites-mutating proof; holding the hook out; shipping `rtk` rules; refusing on any rules file; the probe-and-sample review; a wrapper hook; derived heads with a parser; a purpose-written parser; (j) enforced `exclude_commands` entries for `hcom` and `uvx hcom`, measured and not enforced, with why). ### Review threads Three Codex-connector threads, each answered with its fix and source in the thread and resolved at head 4739ea8: after_sign_in exit status (`accept.sh`), the profile's "never runs `rtk init`" statement (`install.sh` L446), and approval classification against the rewrite (`install.sh` L448). Cross-family reads of the guard, four versions: 4739ea8 (refuse on any rules file) was read by 705d (Sol, through 5f: P1 a failed listing of the rules directory read as no rules, P2 the refusal came after the app-server started, P2 the scratch run accepted a failed evaluator) and job-071 (through the command center: P2 the same listing hole, P2 rules reported only for a hook still to be trusted, P3 the claim that approvals-off hosts consult no rules). `e6321c0b8` (a behavioural review with `rtk hook check` and `codex execpolicy check`) was read by 705e: three P1s that sampling cannot close (an entry-level `FileNotFoundError`, a `prefix_rule` nested in a `host_executable` argument, extensions of a prefix rtk leaves alone). `c771da9eb` (heads derived from rtk's source and a literal-only `ast` reader) was read by 705f: five P1s (a raw CR in a Starlark string, a rule on the whole shell argv, PHP tool suffix spellings, user filter regexes with a second branch, Unicode word boundaries) and a P2 (`DirEntry.is_file()` swallows a missing entry). `3a2bb97ba` (content `2d052a659`) replaced the analysis with the hash list on 5f's recommendation and added one exclusion found while checking the design against the real evaluator: an allow rule that names `rtk`. 705g (Sol, through 5f, at `3a2bb97ba`) found two P1s and no P2 in it: (P1-1) the exclusion refused only a whole token `rtk`, but Codex evaluates an assignment-prefixed script as one token of the shell argv and the hook inserts `rtk` inside it, so `["/bin/bash", "-lc", "FOO=1 rtk git push origin main"]` allowed the rewritten script and not the original; (P1-2) project filters, which rtk loads from the hook's working directory and which `rtk trust --yes` or `RTK_TRUST_PROJECT_FILTERS=1` with a CI variable activate, rewrote `hcom kill luna` out of the reviewed forbid rules while the reviewed hash still passed. This head's repair (`b7f758768`, registry `1b8d4c074`; merge of main `9080bc324`) repairs both in one bounded round: `rtk` is refused anywhere in an allow rule (regression cases, a whole-token mutant, a scratch home); the reviewed-file conditions also need an empty `rtk trust --list` and no `RTK_TRUST_PROJECT_FILTERS` (the reviewer's second option: classify the exposure so that it needs `--allow-exec-rules`), with rtk's exclusions measured as the enforced alternative and recorded, not enforced. It also follows #713's repair round 2 (the entry holds `ac6254ee…`, the 7fbe586 bytes; only comments and justification strings differ from 5f295f2). 705h (Sol, through 5f, at `14a8b119f`; verdict `verdict-705h.json`) **ACCEPTed**: no P1 and no P2. Both 705g P1s were verified fixed against the real binaries (a lowercase `rtk` anywhere in an allow line is refused, and the whole-token mutant dies with 36 test failures; the trust list and the override variable classify both project-filter activation routes, `--apply` exit 2 and `--check` exit 6, with the default and the XDG layouts, and `rtk trust --list` detected the filter from another directory), and no additional bypass was found in the pinned rewrite paths and inputs. Two boundaries stay not verified and are recorded as residuals: runtime coverage (codex-cli 0.159.3 and rtk 0.51.0 were probed, rust-v0.160.0 was read from source, no fresh model session) and the point-in-time and environment limits (the classification observes the current user-layer rule bytes and the tool process's RTK environment and trust store; no atomic snapshot across listing, loading and the grant, and no enforcement after a later change of rules, filters, HOME or XDG paths or the hook's environment; project and managed Codex policies are outside its scope). ### Merge of main `9080bc324` merges main `4af7417b7` (#720 re-pin to v2026.10.05.1, #712, #696, #724) into the branch. Conflicts were only in the generated and hot files (`docs/new-wsl-handbook.md`, the handbook receipt, `manifests/evidence.json`), resolved by the hot-file protocol of `docs/lanes.md`: main's copies, the branch's 44 registry entries re-registered from the pre-merge snapshot, the handbook regenerated with main's generator (#724), the receipt digests refreshed. Carry check: of every file this PR changes against its old base, only `docs/new-wsl-handbook.{json,md}`, the receipt and `manifests/evidence.json` differ between the pre-merge head `1b8d4c074` and the merge head (`git diff 1b8d4c0 <merge head> -- <the PR's files>`); the 705g repairs are `3a2bb97ba..1b8d4c0`. The merged tree failed two tests of main's new rules, fixed in `a7990f56a` (registry `14a8b119f`): the F9 unit says `tools/adoption/exec_rules_reviewed.json` was added after `v2026.10.05.1` (main's unreleased-path marker rule, #720), and the receipt's frozen profile digest is the branch's (the merge took main's receipt); the handbook and the receipt follow. ### Host evidence No files under `evidence/hosts/` change. The scratch run used a scratch HOME; the live `~/.codex` and rtk configuration were neither read nor written. ### Checklist - [x] No new or changed GitHub Actions or workflows. - [x] No secrets printed, logged or committed (gitleaks above). - [x] No new paid hosting, subscription or billing surface. - [x] Peer-owned untracked files and worktrees preserved. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Scope
effort_deviationthat reopens its layer. The converter also redacts the dash-encoded Claude projects-directory home segment, which can carry the host user name.3fef158268cd00af4b74992165fd17d6bb9726df.8c32a84b2.lane:foundationtools/sota-convergence/landscape-sweep/usage_record.pytools/sota-convergence/landscape-sweep/convert.pytools/sota-convergence/landscape-sweep/make_result.pytools/sota-convergence/landscape-sweep/README.mdtests/test_landscape_sweep_harness.pymanifests/evidence.json, in the last commit.examples/claude-native/workflows/child-usage.mjsis unchanged; it stays byte-identical to agent-lab.scripts/validate.pyis unchanged too: a separate PR adds the dash-encoded pattern toPRIVATE_CONTENT.Why. Claude usage limits stopped workflow agents mid-run on 2026-10-04, and the workflow was resumed from its cache.
child-usage.mjslinks a stopped attempt to its re-run only when the call key matches.make_result.pyrefused the completed run.convert.pyalso turned every stopped attempt, which has an empty effort list, into aneffort_deviationretained failure. That reopened all 20 layers.What changes:
usage_record.py, in post-processing. It links only children whose issues include upstream's own precondition, "no result entry in journal", and only when the label has exactly one complete child. The link points to a later complete attempt with the same label, in journal order.exit_codeandraw_output_sha256stay as recorded.measurement.post_processingnames the source status and reason, the linked and covered agent ids, and the covered mismatches.multi_model_childrenis recomputed after the move.convert.pyandmake_result.py. A superseded attempt whose same-label re-run completed at max effort is not an effort deviation. It stays visible undersuperseded_retained.convert.pyredacts the encoded home, derived fromPath.home(), as a whole segment, the bare form included. It also catches generic forms anchored afterprojects/orclaude-<uid>/, and it covers dict keys and the printed summary.SOTA sources
examples/claude-native/workflows/child-usage.mjs, byte-identical to agent-lab): itssummarizeRunsupersedes only attempts that have no result entry and whose call key matches. Its children array keeps the journal's started-row order. The wrapper reuses that precondition and that order and does not change the tool.pathlib.Path.home()andPath.resolve(), which supply the encoded home's source path.docs/acceptance-evidence-policy.md): the evidence classes below. The README drops failing-first counts that no retained run backs.Evidence-class table
synthetic(fixtures)python3 -m unittest tests.test_landscape_sweep_harness tests.test_saturation_ledger tests.test_landscape_sweep_skills, exit 0wf_7e4cef36-e0c, the wrapper links the three stopped attempts and reports complete usagelocal_integrationusage_record.py --transcript-dir <run transcripts>exited 0 withstatus complete. The raw tool exit was 1.post_processing.linked_agent_idsheld 3 ids, 32 effort mismatches were covered, and 0 children were incomplete.local_integrationconvert.pyon the redacted run record exited 4, for the genuine copy check. It reportedreopened_layers ['hosting-services', 'web-research'],effort_deviations 0, and 0 encoded-home hits inreturns.json.Local commands run
Decision record
None. This is a harness correction under the existing sweep recipe; the README carries a dated note.
Review
Checklist
Recorded residuals (bounded review, 2026-10-05)
The Claude Opus delta read of round i at
894a2e9ef5c5returned ACCEPT with no p1. Under the bounded review rule these p2 items land as recorded residuals, each owed as a follow-up:tools/sota-convergence/landscape-sweep/convert.py:790-793 (summary text built at :774 by json_text with ensure_ascii=False, sweep_common.py:: a robustness regression in the summary print: writing the non-ASCII summary can raise UnicodeEncodeError (non-UTF-8 stdout, or a lone surrogate from a run record) after the artifacts were written. Not a privacy hole, because the scan passes first.tests/test_landscape_sweep_harness.py:4278: The comment '# Only lowercase example followed by the publication rule's tail is exempt.' is now false.🤖 Generated with Claude Code