Skip to content

Preserve PR561 lifecycle fixes and retire source-host evidence - #679

Merged
seathatflowsinourveins merged 21 commits into
mainfrom
foundation/pr561-port-20261003
Oct 4, 2026
Merged

seathatflowsinourveins merged 21 commits into
mainfrom
foundation/pr561-port-20261003

Conversation

@seathatflowsinourveins

@seathatflowsinourveins seathatflowsinourveins commented Oct 4, 2026 •

Copy link
Copy Markdown
Owner

Scope

Preserve PR561's hook ownership boundaries, explicit no-project Serena parity and opt-in saved-workflow installer. Retain its source-host facts in a dated retirement record and carry 17 anti-pattern rows after comparing all 19 candidates against current main; two duplicates stay represented by main's existing rows.

  • Base commit: 7d0174168d478d8e3a01602db2138905b6130f8a (main). Head: 3758ce5218321a421476248e97b70034a3c0ab2f.
  • Lane: lane:foundation.
  • Owned paths: the settings merger, native-token fixture and profile installer with their three test modules; two bounded bootstrap edits; anti-pattern table rows; the new retirement record; four unchanged Serena preimage files; evidence file registrations in the last commit.
  • Commits: 86b98f24e ("Port PR561 hook isolation, Serena parity and opt-in workflows", 13 paths) and 8fea93403 ("Refresh evidence bindings for the PR561 lifecycle port", manifests/evidence.json only), then the review repair round: c1ae00392 ("Mark PR561-only references in the ported anti-pattern rows": docs/harness-defaults.md, the retirement record and tests/test_install_claude_profile.py) and 3758ce521 ("Refresh evidence bindings after the PR561 review repair", manifests/evidence.json only, the last commit).
  • Registry: 8fea93403 starts from main's registry at the base and registers the five new files and the eight changed files main already lists; 3758ce521 re-registers the three files the repair changed. The component-matrix and grand-list --check runs passed in both rounds, so no report was regenerated. The other 9,562 rows stay byte-equal to main's, in main's order. No receipts[] or convergence_records[] entry is added.
  • Main is at e0c329ae98efb6ac5e11a49220b69ec6eddbb658 (macOS CI scope: validate-macos stays required, running the full suite for Mac-relevant changes, only changed test modules for test-only changes, and skipping otherwise (decision record, receipt, tests) #677), past the base. This PR is not rebased onto it. The merge-tree landing check of head 3758ce52 against it returns LANDABLE: main's 34 changed paths share only manifests/evidence.json with this PR, and that file's foreign rows stay equal and in order. The merge-time hot-file rebase covers it.
  • Keep this PR a draft until the Codex root lane's exact-head read and all eight required contexts pass at the final head. The custody contract requires no other-lane ack.

SOTA sources

Evidence-class table

Claim Evidence class Command / receipt
Ownership classifier, ancestor activation and saved-file layout justify the integrations source_review Exact pinned originals and official workflow documentation above
Ported code and the unchanged new-WSL integration tests pass at the head local_integration Four-module command: 326 tests, 4 skips, exit 0; all 159 new-WSL tests pass unchanged
Canonical template hook entries stay separate, and existing mixed entries split into contiguous runs local_integration tests.test_apply_claude_settings: 25 tests, exit 0. Discriminating control below: the three hook-ownership tests fail against the base merger
Explicit workflow selection, default no-access behavior, conflicts, readback, rollback and scoped removal pass local_integration WorkflowInstallTests: 15 tests, no skips, exit 0. Discriminating control below: the default no-access test fails once the default steps include workflows
Four Serena files retain the historical no-project observations native_proven (source host, 2026-09-30; not rerun) The four committed blobs are identical to fe4729d's; both stdout SHA-256 values equal the observation's file_sha256
Historical f03fb80 CI returned 259 commands / 82 checks source_review of retained native execution Run 36792680424, job 110148966262 (native-token-tools, success, head f03fb80) metadata and returned log reread; no job rerun
Evidence, catalog, host-receipt, anti-pattern-table and generated-report structure passes at the head structural_validation validate.py (9,575 hashed files), all-recorded convergence (29 valid records), host receipts (182), catalog validator, component matrix (32 rows), grand list (32 layers, 66 winners), ecosystem check, evidence-manifest order check (9,575 rows), workflow checksums (14 OK) and the docs-consistency module (39 tests, 1 skip), each exit 0
The head merges cleanly and the registry keeps every foreign row structural_validation Merge-tree landing check: clean three-way merge, foreign rows equal and in order, 13 PR-owned rows, sorted files[] (9,601 merged rows); LANDABLE against e0c329ae at head 3758ce52

Discriminating controls

Each control ran on a git archive copy of head 3758ce52 with Python 3.13.15, nice -n 19 and a TMPDIR under /var/tmp. <repo> stands for the copy's root. Only the named file was changed in the copy, and the repository was not edited.

Claim Passing run (as merged) Condition removed Failing run
A default run never reads or creates workflows tests.test_install_claude_profile.WorkflowInstallTests.test_default_profile_never_reads_or_creates_workflows: exit 0, Ran 1 test, OK tools/adoption/install_claude_profile.py line 458 set to steps = args.only or ["guard", "agents", "workflows", "mcp"] exit 1, FAILED (failures=1): AssertionError: default run accessed workflows: <repo>/examples/claude-native/workflows/readiness-audit.js
Template entries stay separate; mixed entries split MergeSettingsTests test_absent_and_empty_matchers_keep_their_own_groups, test_existing_mixed_entry_is_split_without_changing_hook_values_or_order and test_same_matcher_keeps_native_memory_and_carrier_entries_separate: exit 0, Ran 3 tests, OK tools/adoption/apply_claude_settings.py replaced by the base 7d0174168 merger (blob f07168fc) exit 1, FAILED (failures=3): AssertionError: 2 != 4, AssertionError: 1 != 3, and a Lists differ on the canonical entries

The same two controls also failed and passed identically on a copy of the reviewed head 8fea9340.

Fresh CI starts with the push of 3758ce52; no result for it is claimed here. At the reviewed head 8fea9340, every completed check passed, including native-token-tools; validate-macos was cancelled at 2026-10-04T01:24:03Z because this push superseded that run (adoption-bootstrap.yml sets cancel-in-progress for its pull-request concurrency group). Native-preimage replay and historical CI reads establish no new provider run. Exact source-host activation clock times and the eight-Claude-hook count retain custody-contract provenance rather than a stronger independently observed claim.

Local commands run

Every command ran at head 3758ce52, outside any sandbox, with nice -n 19 and a writable TMPDIR under /var/tmp. origin/main was e0c329ae; the merge-base stays the base 7d0174168. An earlier sandboxed preparation run is not acceptance evidence: its read-only /var/tmp and cgroupfs caused failures, and none of its counts are carried here.

$ python3 -m unittest tests.test_apply_claude_settings tests.test_install_claude_profile tests.test_native_token_ci tests.test_new_wsl_client_config tests.test_windows_terminal_defaults tests.test_currency_due_notice tests.test_adoption_bootstrap tests.test_adoption_bootstrap_macos -v
exit 1: Ran 631 tests in 101.691s; FAILED (failures=1, skipped=36)
The one failure is pre-existing on main (classification below).

$ python3 -m unittest tests.test_apply_claude_settings tests.test_install_claude_profile tests.test_native_token_ci tests.test_new_wsl_client_config -v
exit 0: Ran 326 tests in 41.357s; OK (skipped=4)

$ python3 -m unittest tests.test_new_wsl_client_config
exit 0: Ran 159 tests in 38.167s; OK

$ python3 -m unittest tests.test_install_claude_profile.WorkflowInstallTests -v
exit 0: Ran 15 tests in 0.642s; OK

$ python3 -m unittest tests.test_apply_claude_settings -v
exit 0: Ran 25 tests in 0.027s; OK

$ python3 -m unittest tests.test_adoption_docs_consistency
exit 0: Ran 39 tests in 11.612s; OK (skipped=1)

$ python3 -m unittest
Not run locally. Per the custody contract's publication amendment, CI's validate job runs the full suite on this head.

$ python3 scripts/validate.py
exit 0: 69 components, 9575 hashed files, 4 profiles, 193 receipts; passed

$ python3 scripts/host_receipts.py validate
exit 0: 182 receipts; passed

$ python3 scripts/validate_catalogs.py
exit 0: catalog structure and evidence classes validated; source claims and native executions were not rerun

$ python3 scripts/validate_convergence.py --all-recorded --root . --json
exit 0: valid true, 29 records

$ python3 scripts/component_matrix.py --check
exit 0: 32 rows, checked

$ python3 scripts/new_host_grand_list.py --check
exit 0: 32 layers, 66 winners, passed

$ python3 scripts/build_ecosystem.py --check
exit 0: passed; the existing architecture pin drift stays reported

$ python3 scripts/evidence_manifest.py --check
exit 0: 9575 files, passed

$ (cd examples/claude-native/workflows && sha256sum --check --strict SHA256SUMS)
exit 0: all 14 files OK

$ git diff --check origin/main...HEAD -- . ':!evidence/artifacts'
exit 0, no output

$ git diff --check origin/main...HEAD
exit 0, no output

$ convergence rebinding query (contract step 19) over main's convergence_records at e0c329ae
exit 1, empty output: no record cites a changed path, so nothing is rebound

$ four Serena files against the fe4729d9 blobs and the observation's file_sha256 values
exit 0: all four identical; both stdout hashes match

$ merge-tree landing check, origin/main e0c329ae against head 3758ce52
exit 0: LANDABLE (clean three-way merge; 14 merged-vs-main paths, none outside the PR; no overlap with main's 34 changed paths besides the registry; foreign rows equal and in order; 9601 merged rows sorted)

$ git push (pre-push hook: three registry tests on 3758ce52)
exit 0: Ran 3 tests; OK. The gitleaks pre-commit hook passed on both repair commits.

Failure classification

Test Class Main baseline
tests.test_windows_terminal_defaults.OverlayTests.test_the_installed_client_knows_no_notification_type_without_a_decision pre-existing: fails identically on main. It reads this host's installed Claude Code client, which reports auth_storage_failure with no DECISIONS entry. Same eight-module command at 7d0174168: exit 1, Ran 613 tests, FAILED (failures=1, skipped=36), the same assertion. The single test on a copy of current main e0c329ae: exit 1, the same Lists differ: ['auth_storage_failure'] != []

The 36 skips have identical reasons on main and at the head: 32 macOS bootstrap prerequisites (17 without a bash 3.2 binary, 14 without PyYAML, 1 without shellcheck), 3 PyYAML frontmatter cases and 1 unset Context Mode security module path. This PR adds no skip and introduces no failure.

Decision record

docs/decisions/2026-10-03-pr561-token-lifecycle-retirement.md records alternatives, upstream pins, all 139 source paths (13 ported / 126 retired), unique source-host facts, explicit non-claims, two dropped duplicate rows, the ten current-enforcer and seven historical-only ported rows, and the comparison/acceptance conditions that reopen each retired category.

Host evidence

No evidence/hosts files or platform-status claims change. The four copied artifacts retain their original source-host/date scope.

Checklist

  • No GitHub Actions workflow is added or changed.
  • Workflow script bytes and their checksum manifest remain unchanged.
  • Main's pins, templates, narrow installer APIs and default steps remain.
  • File registrations use the maintained protocol; receipts[] and convergence_records[] remain unchanged.
  • Peer-owned paths and the stale PR's branch/head are preserved.
  • No credentials, raw conversations or client configuration quotations are published.
  • No paid hosting or new billing surface is introduced.
  • Based on main 7d0174168, not rebased onto e0c329ae (the landing check covers it); reran the contract's local checks at head 3758ce52 with a writable TMPDIR; the full suite is left to CI's validate job.
  • Fresh native-token-tools and all eight required contexts pass at the final head.
  • Independent Claude Opus/max exact-head review (of 8fea9340, verdict repair) and its one repair round are recorded; the dispositions are in the review-record comment.

🤖 Generated with Claude Code

Scout and others added 2 commits October 3, 2026 20:28
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@seathatflowsinourveins seathatflowsinourveins added the lane:foundation Foundation lane: Claude/Codex setup, hosts, memory, RAG, research, workers label Oct 4, 2026
@seathatflowsinourveins

Copy link
Copy Markdown
Owner Author

Claude session native-agent-stack-0c: wsl-architecture-design: merge_settings, imported by new_wsl_client_config.py, now keeps canonical template entries separate and splits existing mixed entries into contiguous runs without changing hook values or order. test_new_wsl_client_config passed unchanged at 8fea934 (159 tests). This is informational, not an acknowledgement gate.

Scout and others added 2 commits October 3, 2026 21:19
Review repair round for the PR561 lifecycle port:
- docs/harness-defaults.md, the 17 ported rows only: drop the whole-cell
  historical tag from the four rows whose named enforcer exists at this head,
  put "(historical: PR561 head fe4729d)" after every reference to the PR561-only
  CI-repair record, and link each such reference to its fe4729d blob.
- Retirement record: name the base 7d01741 (prepared on cac8700, identical
  table), restate the split as ten current / seven historical-only rows and list
  them, and label the 2026-09-30T22:52Z refresh link with its own figures.
- tests/test_install_claude_profile.py: restore two blank lines before
  SecretGuardProfileTests, as at fe4729d.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Re-register the three files the repair round changed (docs/harness-defaults.md,
the PR561 retirement record and tests/test_install_claude_profile.py) with
host_receipts.register_file. component_matrix.py --check and
new_host_grand_list.py --check passed, so no report was regenerated. No
receipts[] or convergence_records[] entry changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@seathatflowsinourveins

Copy link
Copy Markdown
Owner Author

Claude session native-agent-stack-0c: review record and repair round for this port.

Review. An independent, read-only Claude Opus 5.5 review at max effort, run as a separate headless session, read head 8fea9340375b. Verdict: repair, with 0 blocking, 2 should-fix and 4 minor findings.

What the reviewer checked (as it reported them, one line each):

  • Contract content against fe4729d: apply_claude_settings.py differs only by the contracted v2.5.2 docstring. Two test modules are identical to the source. native_token_ci.py keeps the ai-memory 2.4.1 pin and changes only the comment block and the --project-from-cwd argv; the SERENA_* hashes are unchanged. The installer keeps default steps guard/agents/mcp and the narrow options, bootstrap.md has exactly 2 hunks, and the bootstrap scripts are unchanged.
  • Byte identity: the four serena-no-project blobs equal fe4729d's (4f6d3406, 3bf7f69b, f2313641, 7d5cc8c5), and both stdout SHA-256 values equal the observation's file_sha256.
  • Paths: 14 files, all inside the allowed paths, and no forbidden or owner path is touched. 86b98f24e holds the 13 content paths and 8fea93403 only manifests/evidence.json. Qualify native Claude/Codex token profile and memory lifecycle #561 is still open, draft, head fe4729d.
  • Anti-pattern table: of 19 source rows, 17 were added and 2 dropped as duplicates (both listed in the record). No existing row changed, and the base table is an ordered subsequence of the head. The 6/11 split became finding 1.
  • Retirement record: all 139 of 139 Qualify native Claude/Codex token profile and memory lifecycle #561 paths are listed (126 retired, 13 ported) with matching blob URLs. The non-claims are verbatim and the facts match the fe4729d blobs. Run 36792680424 rests on the custody chronology plus a GitHub reread.
  • Upstream citations (ai-memory L1583, L1619, uninstall.rs L825 and a0ca8d1 L1513; Serena cli.py L369-383 and agent.py L699-701, L839-848) match the copies the builder fetched. The reviewer did not fetch them independently.
  • Evidence policy: historical runs stay labelled historical, and no replay or local test is presented as a new run or as upstream acceptance. The missing controls and class labels became findings 2 and 5.
  • Registry: rows went from 9,570 to 9,575, with exactly 5 added and 8 changed for the port's 13 files, all recomputed OK. The other 9,562 rows equal main's, in main's order. receipts[] and convergence_records[] equal the base. evidence_manifest.py --check exited 0.
  • Merge claim: main e0c329ae changed 34 paths and shares only manifests/evidence.json with this PR. A three-way merge of that file is clean, the merged files[] is sorted with no duplicates, and both sides' rows are kept.
  • Privacy: 1,033 added lines and 129 body lines show no user name, home path, private file name, email address or token pattern. The only hit is the public distro name inside a non-claim the contract requires.
  • Reproduced at 8fea934: the four-module run passed 326 tests (4 skipped) and new-WSL passed 159. WorkflowInstallTests plus apply_claude_settings passed 40. The Windows Terminal and currency modules ran 64 tests whose only failure is the pre-existing auth_storage_failure test. validate.py, host receipts, catalogs, convergence, component matrix, grand list and ecosystem check each exited 0, SHA256SUMS returned 14 OK and both git diff --check forms exited 0.
  • Not reproduced locally: the bootstrap modules, the 631-test 8-module total, the pre-push hook and gitleaks. At review time CI on 8fea934 showed native-token-tools, sota-sources and bootstrap-linux green, with the others still running.
  • PR body: ### SOTA sources is present and complete, and the commit, row and count claims match the files. The 8 checked items hold, and the 2 unchecked ones (CI, review) were stated honestly.
  • Tests: none was removed (apply_claude_settings went from 23 to 25, install_claude_profile from 79 to 94, native_token_ci from 47 to 48). The 3 changed tests are contract-assigned adaptations, and none was weakened.

Findings and dispositions:

  1. should-fix, docs/harness-defaults.md ported rows: fixed in c1ae00392. Only the port's 17 rows changed, and main's rows stay byte-identical and in order. Four rows lost their whole-cell historical tag because their enforcer exists at the head: "Calling all function definitions methods", "Merging lifecycle hooks solely because their matchers match", "Checking only the first matching hook entry" and "Implicit Serena ancestor activation". The last one now names scripts/native_token_ci.py and the ported serena-no-project/ directory. Its receipts are the ported preimages, present at the head, so they carry their path rather than the tag. This is a deliberate reading of the fix's ":101 receipt mentions". In the ten rows with a current enforcer, every reference to the PR561-only CI-repair record now carries (historical: PR561 head fe4729d9) and links its fe4729d blob. That covers all four full ci-repair.json paths, and each cited section was confirmed in the blob first. The seven historical-only rows keep the tag closing their cell. The record now gives the split as ten current and seven historical-only rows and names them.
  2. should-fix, missing discriminating controls in the body: fixed. This session reran both controls itself, on archive copies of 8fea9340 and of 3758ce52, and reproduced the reviewer's results. With the default steps including workflows, test_default_profile_never_reads_or_creates_workflows exits 1 with default run accessed workflows: <repo>/examples/claude-native/workflows/readiness-audit.js; as merged it exits 0. With the base 7d0174168 merger, the three hook-ownership tests exit 1 (failures=3: 2 != 4, 1 != 3, and a canonical-entry list diff); with the head merger they exit 0. Both pairs sit in a new "Discriminating controls" table.
  3. minor, record base commit: fixed (wording). The record now names base 7d0174168. It says the port was prepared on cac8700ba and rebased onto that base, notes that docs/harness-defaults.md is byte-identical at both (empty diff), and links the 7d0174168 table.
  4. minor, three blank lines before SecretGuardProfileTests: fixed (formatting only). One blank line was removed. The edit changes no behaviour and no assertion, the file is not one of the four byte-carried blobs, and it restores the fe4729d spacing.
  5. minor, body evidence classes: fixed. The structure row and the merge row are relabelled structural_validation.
  6. minor, record refresh link: fixed (wording). The quoted 2026-10-01T02:15:27Z figures now name native_lifetime_snapshot_20261001 in the CI-repair record as their source. The other link is labelled as the earlier 2026-09-30T22:52Z refresh, with its own 83,275,349 and 55,255,271 figures read from that blob.

No residuals.

New head: 3758ce5218321a421476248e97b70034a3c0ab2f. c1ae00392 holds the three content files. 3758ce521, the last commit, re-registers those three files in manifests/evidence.json; the generator checks passed, so no report was rewritten. It went out as a normal push. Main has moved to e0c329ae (#677); this branch was neither merged nor rebased.

Exit codes at 3758ce52 (nice 19, TMPDIR under /var/tmp, outside any sandbox):

  • The contract's 8-module run exited 1: 631 tests, 36 skips and one failure, the pre-existing auth_storage_failure test, which fails the same way on a copy of e0c329ae. The four-module run exited 0 (326 tests, 4 skips), new-WSL 0 (159), WorkflowInstallTests 0 (15), apply_claude_settings 0 (25) and the docs-consistency module 0 (39 tests, 1 skip).
  • validate.py exited 0, as did evidence_manifest.py --check, host_receipts.py validate, validate_catalogs.py, validate_convergence.py --all-recorded (29 valid), component_matrix.py --check, new_host_grand_list.py --check, build_ecosystem.py --check and SHA256SUMS (14 OK).
  • git diff --check origin/main...HEAD exited 0 in both forms with no output. The contract's rebinding query exited 1 with empty output.
  • The merge-tree landing check against e0c329ae exited 0 and printed LANDABLE. The pre-push hook exited 0.

Remaining before merge: no other-lane ack, since the custody contract requires none for lane:foundation and the new-WSL heads-up is informational. Still needed are the Codex root lane's exact-head read of 3758ce52 and 8/8 required checks on 3758ce52.

Scout and others added 5 commits October 3, 2026 23:16
…fore the final registry commit

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tocol: every registry 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 registry commit

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tocol: every registry edit in the last commit)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@seathatflowsinourveins
seathatflowsinourveins marked this pull request as ready for review October 4, 2026 03:21
Scout and others added 12 commits October 3, 2026 23:58
…egistry plus the owned rows)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fore the final registry commit

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tocol: every registry 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>
…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>
…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>
@seathatflowsinourveins

Copy link
Copy Markdown
Owner Author

Claude session native-agent-stack-5f: landing at head d5191821ef5ea6c0fa3ced17c855d7cf597de98e. The command center (wsl-architecture-design) gave its ACK at 2eff2970af7b, which reaches this head only through recorded mechanical refreshes whose owned non-registry patch-ids are equal (its carry rule); under the user's 2026-10-04 decision it owns merges that touch the hot registry. The read-only cross-family review (GPT-6.1 Sol max, the packaged Codex SDK worker) returned FINDINGS at 3758ce521832; this head is reached from it through recorded carry edges (equal owned patch-ids, or a cross-family delta read returning ACCEPT at the edge's target), with its 1 P1 item(s) resolved in one repair round as recorded.

Observed main f77a35eb2bf30bc4bf6f3b4ee51bc9ce5397b4c5. coordination/merge_tree_landing_check.py (sha256 a11649fcf2e5844c…) exit 0:

main f77a35eb2bf30bc4bf6f3b4ee51bc9ce5397b4c5 head d5191821ef5ea6c0fa3ced17c855d7cf597de98e base f77a35eb2bf30bc4bf6f3b4ee51bc9ce5397b4c5 merged-tree 9246e075d3b4138a588703ed62c1817bc1c2c282 merge-tree-exit 0
ok   1: clean three-way merge
ok   2: merged-vs-main paths 14, outside PR-owned 0 []
ok   3: main drift 0 paths, overlap with PR-owned inputs (registry excluded) []
ok   4: registry foreign rows equal True, order preserved True, PR-owned rows 13, unowned top-level keys differing []
ok   5: merged files[] sorted by path with no duplicates: True (9869 rows)
LANDABLE
condition 5: merged files[] sorted and unique (tree 9246e075d3b4138a588703ed62c1817bc1c2c282)

Required checks at this head: 8 pass . Unresolved review threads: 0.

@seathatflowsinourveins
seathatflowsinourveins merged commit 33efbc3 into main Oct 4, 2026
26 checks passed
@seathatflowsinourveins

Copy link
Copy Markdown
Owner Author

Claude session native-agent-stack-5f: post-merge observation. Landed as 33efbc3b6a46df556bdedf39cd8ea65762f38867 (parent f77a35eb2bf30bc4bf6f3b4ee51bc9ce5397b4c5), tree 9246e075d3b4138a588703ed62c1817bc1c2c282. The landed tree equals the checked merged tree and the parent is the observed main.

@seathatflowsinourveins
seathatflowsinourveins deleted the foundation/pr561-port-20261003 branch October 4, 2026 08:01
seathatflowsinourveins pushed a commit that referenced this pull request Oct 4, 2026
…ry; this branch's rows in the last commit)

The merge brings main's #672, #626, #679 and #681. #681 (CI least privilege) rewrites
19 workflows (top-level permissions {}, job-level contents: read, cache-mode none on
pull requests, concurrency groups) and adds tests/test_workflow_policy.py; CI's zizmor
flags in validate.yml are unchanged. manifests/evidence.json is main's copy; the
branch's rows are re-registered in the final commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
seathatflowsinourveins pushed a commit that referenced this pull request Oct 4, 2026
…erge with main 6af8e55)

On the merge with main 6af8e55 the derivation protected 10,218 of 10,591 tracked
files, all 2,608 under blueprints/ among them, and the repository breadth test failed.
Main's #679 made tools/adoption/install_claude_profile.py, which the bootstrap runs,
read the three examples/claude-native/workflows/*.js files to hash and install them.
The round-3 fixpoint followed every code file that gate code read, and the names in
those scripts' text (blueprints, fixtures) became protected directories.

A code file is now followed only when gate code runs it. A code file in another
language still runs, or hands on, every code file its text names. A Python file runs a
file when the file's location, or text read from it, reaches a call that executes code
(GateReads.executed): subprocess, os exec/spawn/system, asyncio subprocesses, pty.spawn,
runpy, importlib's file loaders, exec and compile, matched by name; a function or
method of the same module that passes a parameter on to one (to a fixpoint); or a
function imported from outside the standard library (sys.stdlib_module_names). Code
that is only read stays protected as a file (ci_read). An executing call whose argument
is a computed location may run any file under it, so it refuses every commit
(gate_input_unresolved), as an unresolved read does; there is none on this repository.

On the merged tree: 7,617 of 10,591 files protected (444 before the gate followed
reads), 632 of 3,447 outside evidence/, tests/ and .github/, 12 of 2,608 under
blueprints/, nothing unresolved. Tests: each executing form on one script, with hashed,
copied and parsed code left as data; a fixture gate script that hashes and copies a
workflow script whose text names src/app.py and docs/a.md (both stay editable, the
script is refused) and runs a check through a wrapper (its data is refused); a computed
run refuses every commit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
seathatflowsinourveins pushed a commit that referenced this pull request Oct 4, 2026
…ocol)

Brings #626 (Codex 0.159.3 -> 0.160.0, f77a35e), #679 and #681 (CI least
privilege) under this branch. manifests/evidence.json is main's copy; the
branch's rows are re-registered in the last commit.

Conflicts resolved:
- tools/adoption/apply_codex_lane.py: main's comment block and
  CODEX_VERSION = "0.160.0", followed by this branch's required-server
  constants unchanged.
- tests/test_codex_worker_lane.py: this branch's version-free docstring
  line and skip reason (lane.CODEX_VERSION), which read 0.160.0 at main's pin.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
seathatflowsinourveins added a commit that referenced this pull request Oct 4, 2026
…ges 1-2, offline-tested) (#489)

### Scope

This PR adds the host driver for the OpenHands issue-to-PR resolver on top of the merged #425 recipe. One explicitly scoped, owner-authored issue can produce one validated patch, one draft PR, one COMMENT review and one repair round. The model's patch is not executed on the host. A draft PR can execute it in GitHub CI under the resolver-mode amendment decided on 2026-10-04: option 1, with a trusted pre-push gate that checks every agent commit before any push (see "Pre-push gate" below).

- **Base commit:** `d2fc3803e01178b4687771d0bf91faf453bb6933`, merged in `db24156b9` without rebasing or force-pushing. The original PR head `501bcc9e50bf3ffa3acc82b6ecf20aa4e23c593b` remains in history. Head: `7c1d24cc5600bed8b56435aef37ec8d267f889fe`. On top of `0f7b27578` it corrects this round's dates to 2026-10-04, as `date -u` gives them, in `b763cb294` (text only; the commit also resets the registry to main's copy), and re-registers the rows in `7c1d24cc5` (the last commit). On top of `4eb6b4cc9`, `0f7b27578` added the merge `4f963c9b2` of main `6af8e55bd` (#681, CI least privilege, with #672, #626 and #679). It also adds the gate fix that merge needed: the derivation follows code that gate code runs, not code it only reads (`GateReads.executed`), in `57d0dc065`. Main's #679 made `tools/adoption/install_claude_profile.py` read three workflow scripts, and following them had protected all of `blueprints/`. The decision record, `RESOLVER.md` and evidence part 8 are in `85262b1f8`, and the registry rows in `0f7b27578` (the last commit). The main-merge list below predates this merge. On top of `21b24dede`, `4eb6b4cc9` added the repair round for the cross-family read of `40f12ba5` (GPT-6.1 Sol, findings P1 and P2): the merge `db287ea72` of main `3bdacabd5`, the gate-data reader, the instruction fix and their tests in `86688e1e1`, the decision record, `RESOLVER.md` and evidence part 7 in `0092ae213`, the merge `4a03dd796` of main `ba0e8c48f`, the figures on that merge in `1ec9d04c3`, a receipt test and the final control runs in `e1b4f5c68`, and the registry rows in `4eb6b4cc9` (the last commit). Before that, on top of `050bca5d5`: the zizmor pin read from `.github/requirements-ci.txt` in `a5194090b` (registry `4009a96ec` and `40f12ba51`), then the CI-blocker round for CodeQL alert 90 and validate-macos (the merge `d1bb9cf15` of main `f474f6d22`, `36440d64a`, `9602c2274`, `8be0c1d39`, registry `21b24dede`). On top of `456f8fee6`, `050bca5d5` added the decided amendment's trusted pre-push gate: code and tests in `00905292d` and `48831bc65`, the decision record, `RESOLVER.md` and the evidence log in `868f02501`, and the registry rows in `050bca5d5`. Before that, on top of `b0c11c324`, came wording-only fixes for the [independent re-check](#issuecomment-5973091307) and the coordinator's follow-up: content in `f4e7aa2a2` and `54438ce7f`, registry rows in `d89ad3b44` and `456f8fee6`. This description was written for `b0c11c324`. Parts were updated for `050bca5d5`: the "Pre-push gate" bullet, the SOTA "Pre-push gate" line, the evidence rows and commands, the "Decision record" section and the decision item under "What is not done". For `4eb6b4cc9`, this line, the main merges, the owned paths, the "Pre-push gate" bullet and a SOTA "Gate data" line are updated; the evidence table and the commands still describe `050bca5d5`, and the later rounds' evidence is in `evidence/push-gate-fail-first.txt` parts 6 and 7 and the PR comments. The SOTA "Step 6 repair round" line was updated for `456f8fee6`.
- **Main merges during custody.** Each followed the hot-file protocol: main's `manifests/evidence.json`, then this PR's owned rows re-registered.
  - `9b0b8d6d2` in `37cb51899`;
  - `4ced29230`, which carried main's `AGENTS.md` update, in `85830e815`;
  - `59f8a1e36` in `d35633fad`;
  - `d2fc3803e`, which contains `ecea28654`, in `db24156b9`;
  - `f474f6d22`, which carried main's macOS CI scope step (`e0c329ae9`), in `d1bb9cf15`;
  - `3bdacabd5` in `db287ea72`;
  - `ba0e8c48f`, which carried the OSV and SARIF hardening port, in `4a03dd796`.

  Main has since advanced to `b5b9c9ddb` (#672), which is not merged. Its 13 paths are jCodeMunch carrier files, documents, one test and evidence; none is a workflow or a gate script. The coordination merge-tree landing check of `4eb6b4cc9` against it reports LANDABLE: a clean three-way merge, 21 merged-vs-main paths and none outside the PR-owned set, no overlap with main's 13 drifted paths, the registry's foreign rows equal and in order, 20 PR-owned rows, and a sorted `files[]` without duplicates (9823 rows).
- **Lane:** `lane:foundation`.
- **Owned content paths:** `blueprints/runtime-workers/openhands/RESOLVER.md`, `resolver.py`, `resolver/{patch_policy,gh_harness,outgoing_guard,push_gate,gate_reads}.py`, `skills/resolver/SKILL.md`, `host.py`, `dispatch.py`, `worker.py`, `receipt.py`, `e2e/task.py`, both `evidence/stage2-*fail-first.txt` logs and `evidence/push-gate-fail-first.txt`, `docs/decisions/2026-09-28-openhands-resolver-isolation.md`, and the three OpenHands test modules (`tests/test_runtime_worker_openhands_push_gate.py` is new). The registry commits re-register these files over main's `manifests/evidence.json` and regenerate the four foundation reports through their supported commands. The last full pass is in the merge `db24156b9`. `b0c11c324` refreshes the rows of the three files that the step 6 repair round changed. `050bca5d5` refreshes the six rows the gate change touched and adds three new files' rows. `4eb6b4cc9` registers the 20 PR-owned files over main `ba0e8c48f`'s registry: 7 rows updated and 13 added, `resolver/gate_reads.py` among them. Both generators' `--check` passed each time, so no report was rewritten.
- **Existing main defect disclosed.** Commits `0c9b7acf6` and `3e3877979` fix the SWE-bench skill contract and instruction. At the merged base, `host.py:382` requires `verification-before-completion` and `e2e/task.py:52` tells the worker to invoke it, while the runtime manifest lists that skill under `excluded`. The fix keeps the excluded skill out of both contracts and preserves the instruction to run and report the reproducing tests before finishing.
- **Custody repair.** The alias-refusal fixture now builds all seven entries directly in a scratch Git index. It preserves case and decomposed Unicode names on filesystems that fold them, disables Git's macOS argument precomposition for those insertion commands, and exports the cached patch without restaging the worktree. All existing refusal assertions remain, with an added check that every intended name reached the validator.
- **Review-round repair** (`2ede7b871`, tests only; its registry row in `b2d556c95`). The outgoing-guard fixtures no longer depend on `TMPDIR`. Two `host_path` assertions now use a synthetic absolute host root. The symlink case needs a real temporary root, so it probes that prerequisite. It skips with an explicit message when the root matches a `scripts/validate.py` `PRIVATE_CONTENT` pattern, such as a personal home path; the reason was reworded in `cf42c6d08`. No assertion or reason label changed.
- **Step 6 repair round** (`cf42c6d08`: documentation and one test's comment and skip text; its registry rows in `b0c11c324`).
  - The decision record's option 2 and `RESOLVER.md` now state that the resolver pushes to and opens PRs only in this repository. A fork therefore needs a separately reviewed harness change before any run.
  - Both options now address condition 3 and CI egress.
  - The G4 residual gives the actual refusal order.
  - No behaviour changed.
- **Pre-push gate** (the amendment's decision of 2026-10-04; content in `00905292d`, `48831bc65` and `868f02501`, registry in `050bca5d5`; the cross-family repair in `86688e1e1`, `0092ae213`, `1ec9d04c3` and `e1b4f5c68`, registry in `4eb6b4cc9`).
  - **Push path.** `GhHarness.push` runs `resolver/push_gate.py` on the exact agent commit before any push and pushes that commit by name (`<sha>:refs/heads/<branch>`, never `HEAD`). `GhHarness.run` refuses any push of a commit the gate did not pass, and any push without a gate.
  - **Refusals.** The gate diffs the commit against its base. It refuses, with no push, changes to `.github/**`, a `CODEOWNERS` anywhere, the resolver's gate and harness code, the workflow-policy tests (`tests/**.py` naming `.github`), and every file that a workflow reachable from the push or the PR executes or reads as a gate. That last list is derived from the workflow files by a text-level reader that reuses `patch_policy.names_in_text`: the files `run:` steps name, the import closure of the gate scripts, unittest discovery and local actions. It also refuses a step that interpolates untrusted event text.
  - **Gate data** (cross-family P1). The gate also refuses changes to the data those gate scripts read (`ci_read`, `resolver/gate_reads.py`), such as `blueprints/convergence-practice/contract.schema.json`, which `scripts/validate_convergence.py` reads. Each gate script's expressions are evaluated to the repository paths they spell. An exact path protects that file, and a computed one protects the directory or glob it resolves under. Code that gate code runs or reads is followed to a fixpoint. A read the reader cannot resolve refuses every commit (`gate_input_unresolved`) rather than protecting the whole tree; none is unresolved on the merged tree. The cost is breadth. The merged tree `4a03dd796` has 10,528 tracked files, and the gate protects 7,559 of them (441 before). Outside `evidence/`, `tests/` and `.github/` it protects 633 of 3,444 (122 before). Most of it comes from `tools/sota-convergence/gap_wave_ledger.py`'s computed `evidence/artifacts` and `docs/*.md` paths. The decision record's residual risks name the two deferred narrowings, and a repository test bounds the breadth.
  - **zizmor.** The gate runs the zizmor CI pins (1.30.1) with its own flags (no config, no ignores, offline). The excessive-permissions, dangerous-triggers, cache-poisoning, artipacked and template-injection audits refuse, and a missing or wrong zizmor fails closed.
  - **Trusted copy.** The gate runs only from the checkout it sits in, never from inside an agent tree. Its four files (`push_gate.py`, `patch_policy.py`, `gate_reads.py`, `gh_harness.py`) must equal the trusted commit's and the base's blobs, the trusted commit must be on main at the base, and the trusted commit is recorded. Each check leaves one record per commit in `resolver-outcome.json` (`push_gate`) and a code-and-count projection in the receipt.
  - **CLI.** `run` takes `--zizmor`, and the plan reports `push_gate: trusted_copy_checked`.
  - **Agent instructions** (cross-family P2). The resolver skill and the generated instruction name every category the gate refuses. When a fix would need such a change, including a new or changed test (`tests/**` is protected here), they tell the agent to stop and report instead of editing. A test keeps both in step with the gate's rules and the receipt's.

The resolver's Stage 1 logic covers owner/edit provenance, a patch policy derived from the base's host-executed files, fixed `gh` templates, guarded outgoing text and a bounded PR loop. Stage 2 adds:
- the same O1 containment topology;
- fresh P0-P2 receipts and `stage-gates.json`;
- G5 checks before container creation and at dispatch;
- a pinned-main checkout with no MCP servers, and a fixed skill set;
- a validated patch whose committed diff must match byte for byte.

Its receipt does not infer successful completion from model-writable data.

### Independent review history

1. Stage 1 received a read-only GPT cross-family review (`gpt-6-astra`, max). Four findings were repaired, and a Claude closure review confirmed them closed: import shadowing, edited issue provenance, missing required contexts, and a review bound to a different commit.
2. Stage 2 received three independent Claude reviews. The verifier accepted with low notes; the security and design reviewers requested changes. The retained repair round addressed:
   - patch-content checking before `git apply`;
   - binding the G4 reviewer argv to a recorded hash;
   - retaining a PR record when GitHub holds the PR;
   - the residuals comment;
   - the receipt after a dispatch failure;
   - the excluded-skill instruction;
   - containment evidence;
   - fourteen smaller items.

   Both fail-first logs are unchanged: their blob SHAs at this head (`ed55377f`, `3f41c01b`) equal those at `501bcc9e`.
3. Stage 2's requested separate read-only GPT-6.1 Astra/max review through the packaged lane (custody contract step 6(a)) was pending at `b2d556c95`. It ran at `db24156b9` (job `rev-489-astra`) and returned **repair** with one should-fix finding, which `cf42c6d08` repairs (see "Step 6 reviews" and "Step 6 repair round"). The builder's diagnosis and tests do not count as that review.
4. The headless Opus 5.5 closure review of the whole repaired head (step 6(b)) was also pending at `b2d556c95`. It returned **repair** at `db24156b9`, with two should-fix and seven minor findings; "Step 6 repair round" gives each disposition. Before the PR leaves draft, the coordinator must still:
   - have the reviewers re-read this delta (contract step 6);
   - resolve every review thread;
   - confirm the required contexts on the final head.
5. A read-only Opus 5.5 custody review of `d35633fad` returned **repair**, with two should-fix and six minor findings. Their dispositions are under "Review round" below; reviews 3 and 4 cover the resulting head.

### Step 6 reviews (2026-10-03, head db24156b92ac)

Items 3 and 4 of "Independent review history" and row 7 of "Review round" call these two reviews pending at `b2d556c95`; this section records their returned verdicts at `db24156b92ac`. Findings are condensed to one line each (severity, location, problem) without the reviews' fix proposals. Host paths are replaced by repository-relative paths or `<private path>`. Line numbers cited for the PR body are those of the body as read at 2026-10-03T19:20Z, before this section was added.

**(a) GPT-6 Astra/max cross-family review**, run through the packaged lane, job `rev-489-astra`. Verdict: **repair**. One finding.

- **should-fix** | `docs/decisions/2026-09-28-openhands-resolver-isolation.md:228-236`; `blueprints/runtime-workers/openhands/RESOLVER.md:535-537` | The fork option needs explicit implementation and safety prerequisites. The runbook permits proceeding after either choice, but `gh_harness.py:44-47,257-259,704-708` still targets the upstream repository and rejects a fork push URL, so following it after choosing a fork would use the same-repository path. Forking also leaves networked CI and final-message publication unresolved, while the unconditional token/secrets guarantee is explicitly unverified.

**(b) Opus closure review.** Verdict: **repair**. Nine findings: two should-fix and seven minor.

- **should-fix** | `docs/decisions/2026-09-28-openhands-resolver-isolation.md:227-236`; `blueprints/runtime-workers/openhands/RESOLVER.md:519-521` (also `:420-422`) | The fork option (option 2) is described incompletely, and `RESOLVER.md` files it under the wrong kind of change, so the owner cannot see what it costs or leaves open. (i) `RESOLVER.md:519-521` lists "pushing to an owner fork" among the "workflow changes outside this PR", but it changes this PR's own harness, which only targets this repository (`gh_harness.py:44`, `:241-254`, `:257-259`, `:448`, `:627-628`, `:684-689`, `:704-709`; the record's ruleset section, `:131-178`, binds only this repository's `openhands/*` refs), so option 2 needs harness changes, a ruleset on the fork and its own review before any run, while option 1 needs no code change. (ii) Option 2 (`:230-232`) says nothing about condition 3: `build_pr_body` (`resolver.py:547-550`, `:590-592`) publishes up to 6000 characters of the agent's final message wherever the branch lives, so option 2 leaves that deviation open while option 1 explicitly accepts it, and the record's closing sentence (`:235-236`) implies that accepting either option lets the first live run go ahead. (iii) The fork's owner is not named (the repository is public and owned by a User account; isFork false, forkCount 0), and the record already says GitHub's fork-PR limits were not re-read.
- **should-fix** | PR #489 body (`gh pr view 489 --json body`, read 2026-10-03T19:20Z): lines 5, 6, 8, 46, 52, 149 ("CI on this head"), 151 | The body still describes `b2d556c95`, not the reviewed head `db24156b9`: line 5 (base and head); line 6 (main `ecea2865` "not merged", and the merge list omits `db24156b9`, which merges main `d2fc3803e`, already containing `ecea28654`); line 8 (last full registry pass `d35633fad`); lines 46 and 151 (`d35633fad` as the Linux full-suite evidence, "differs from this head only in the repaired test module"); line 52 and the "CI on this head" paragraph, line 149 (`validate` failed on main's unsorted registry pair). At `db24156b9` the registry has 0 unsorted pairs and `validate` passed: job `111264954786` (head_sha `db24156b9`, CI merge `69650a33` onto `d2fc3803e`) shows `validate.py` `{"hashed_files": 9550, "receipts": 193, "status": "passed"}`, `component_matrix.py --check` `{"rows": 32, "status": "checked"}`, the new-host grand-list check passed, and `python3 -m unittest` "Ran 10078 tests ... OK (skipped=968)". Contract step 8 requires the merged main SHA, the local commands with exit codes and an evidence table for the head that lands.
- **minor** | `tests/test_runtime_worker_openhands_resolver.py:1582-1589` | The probe and the assertions are correct; only the skip message is too narrow. The probe string `f"{self.tmp}/"` (`:1584`) fires exactly when the guard (`outgoing_guard.py:165-170`) would refuse as `private_content` before `host_path`, and no assertion is weakened (`host_path` is still asserted at `:1565` on the synthetic root, the ValueError cases moved unchanged to `:1570-1573` ahead of the skip, and the symlink and realpath assertions at `:1590-1592` are unchanged). The skip message (`:1588-1589`) and the comment (`:1582`) blame "TMPDIR is under a personal home path", but the probe fires on any `scripts/validate.py` `PRIVATE_CONTENT` pattern (`validate.py:25-37`), such as a session-UUID, task-handle or Windows-user-path `TMPDIR`, and then the skip names the wrong cause.
- **minor** | PR #489 body line 175; `blueprints/runtime-workers/openhands/RESOLVER.md:514-516`; order at `blueprints/runtime-workers/openhands/resolver.py:1589-1591` and `host.py:1359-1361` | The body says "G4 remains unrecorded, so a real run refuses with `stage_gate_g4_not_recorded`", but that reason code applies only once the other gates are recorded. Today there is no `<state>/stage-gates.json`: `plan_run` calls `host.verify_stage_gates` first (`resolver.py:1589`), and `read_stage_gates` raises `stage_gates_not_recorded` (`host.py:1360-1361`) before `verify_reviewer_gate` (`resolver.py:1591`) can raise `stage_gate_g4_not_recorded`. The gates themselves are intact: no bypass flag or environment override exists, `_cmd_run` requires `--reviewer-command` (`resolver.py:1663-1664`), and at dispatch start `verify_isolation` (`dispatch.py:319`) re-checks P0-P2 freshness (`host.py:1445-1447`), the stage gates and G5 (`host.py:1463-1464`).
- **minor** | Required context `validate-macos` on `db24156b9` (run `37144290967`, job `111264957003`) | Verification gap, not a defect: `validate-macos` was still pending (queued) at 2026-10-03T19:20:37Z; the other seven required contexts passed on `db24156b9`. The native-macOS evidence the review read is from the earlier head `d35633fad` (artifact `11278304065` of run `37129286224`, `full-suite-macos.log`: "Ran 10070 tests ... OK (skipped=1329)", `test_case_unicode_and_filesystem_aliases_are_refused ... ok`, no FAIL or ERROR in `tests.test_runtime_worker_openhands_resolver`). That confirms the git-plumbing alias fixture on APFS but predates the `TMPDIR` repair `2ede7b871`; the `db24156b9` run is the first native-macOS run of that repair.
- **minor** | Contract step 6(a) (`<private path>:71`); PR #489 review state | Verification gap, not a defect: the separate read-only GPT-6.1 Astra/max cross-family review was still pending when this review ran; GraphQL at 19:20Z showed 0 review threads and 0 reviews on the PR.
- **minor** | `origin/main` `1f5a791b02a230aced670c88bab3d3d0ebcf401a` versus the merged base `d2fc3803e01178b4687771d0bf91faf453bb6933`; `manifests/evidence.json` | Verification gap, not a defect: main moved after the custody merge (#640, #648). Three registry rows changed: `docs/harness-defaults.md`, `observability/grand-dashboard/state.json` and `docs/token-session-handbook.md`. Their hunks do not overlap this PR's `evidence.json` hunks, but the landing head no longer merges current main.
- **minor** | Contract step 5 commands at `db24156b9` | Verification gap, not a defect: the review ran no acceptance command (it had no Bash; those are the coordinator's commands). Not re-run at `db24156b9`: the unit-test pair under a neutral `TMPDIR` and a home-path `TMPDIR`, the planted-defect mutations, `resolver.py --help` and `run --help`, `git diff --check` and the pre-push gitleaks scan. The body records them only at `b2d556c95`. CI on `db24156b9` covers the Linux full suite, `validate.py`, the generator checks and secret-scan.
- **minor** | Items 3-4 and the safety boundary, verified at `db24156b9` | No defect (verification record). Scope: `d2fc3803e..db24156b9` is exactly the 17 allowed paths (`README.md`, `.github/` and `blueprints/us-equities/` untouched; owned files equal `b2d556c95`). Hot-file merge: all 9541 rows of main's `evidence.json` kept in order, 9 new and 7 updated owned rows added, all 16 sha256/bytes values match HEAD, `receipts[]` and `convergence_records[]` equal main's, `files[]` sorted with no duplicates. Preserved: both fail-first blobs (`ed55377f`, `3f41c01b`), decision-record lines 1-15 (match `501bcc9e` and main), the amendment heading at `:208`, the skill-contract fix (`host.py:408-413`, `e2e/task.py:46-56`) and the A7 env-name read in teardown (`host.py:1095`). At the merged base the 11 `pull_request` workflows still declare `contents: read` and use no secrets, and the SARIF upload jobs still skip `pull_request`. `fold()`, `HFS_IGNORABLE` and the alias rules (`patch_policy.py:116-129`, `:893-897`, `:953-958`) decide from git data, and the outgoing guard's check order and 0600 `O_EXCL|O_NOFOLLOW` body files are intact.

### SOTA sources

- [git/git `v2.43.0`](https://github.com/git/git/tree/v2.43.0), matching installed Git 2.43.0: [the native index-fixture reference](https://github.com/git/git/blob/v2.43.0/t/t2107-update-index-basic.sh#L59), [git-hash-object(1)](https://github.com/git/git/blob/v2.43.0/Documentation/git-hash-object.txt#L18), [git-update-index(1)](https://github.com/git/git/blob/v2.43.0/Documentation/git-update-index.txt#L75), and [index insertion implementation](https://github.com/git/git/blob/v2.43.0/builtin/update-index.c#L421). The additional macOS requirement follows [git.c's argument conversion](https://github.com/git/git/blob/v2.43.0/git.c#L449), [precompose_utf8.c](https://github.com/git/git/blob/v2.43.0/compat/precompose_utf8.c#L67), and [core.precomposeUnicode](https://github.com/git/git/blob/v2.43.0/Documentation/config/core.txt#L44). Installed help, versioned release notes and these primary sources were read on 2026-10-03. Earlier resolver patch handling also follows `git-apply(1)`, `git-diff(1)` and `git-merge-base(1)` at this revision.
- [Gitleaks `v8.30.1`](https://github.com/gitleaks/gitleaks/tree/v8.30.1): [release notes](https://github.com/gitleaks/gitleaks/releases/tag/v8.30.1), [native Git-range and directory commands](https://github.com/gitleaks/gitleaks/blob/v8.30.1/README.md#L196), and installed CLI help. The sandbox tests select the same installed upstream binary directly because the host wrapper's lock directory is outside the writable sandbox.
- Existing resolver implementation references: [OpenHands/extensions `bea7a20`](https://github.com/OpenHands/extensions/tree/bea7a20), `skills/github-issue-to-pr/scripts/main.py` (branch naming and loop) and `skills/github-pr-reviewer/scripts/worker.py`; [OpenHands/software-agent-sdk `fcc102a`](https://github.com/OpenHands/software-agent-sdk/tree/fcc102a), v1.49.6; [OpenHands/OpenHands `7bc33009`](https://github.com/OpenHands/OpenHands/tree/7bc33009), the retired resolver comparison. These are the original implementation's historical reviewed pins; the custody change adds no runtime or orchestration alternative.
- [cli/cli `v2.101.0`](https://github.com/cli/cli/tree/v2.101.0) (`0cf10924`), including `pkg/cmd/pr/checks/aggregate.go`, credential-helper behavior and fixed `api`/PR operations; [GitHub create-review documentation](https://docs.github.com/en/rest/pulls/reviews#create-a-review-for-a-pull-request) (`commit_id`) and [GraphQL issue/edit provenance](https://docs.github.com/en/graphql/reference/objects#issue), read in the original 2026-09-28/29 implementation review; CPython `v3.12.3`, `importlib._bootstrap_external.FileFinder`, for package-before-module resolution.
- Repository: `docs/decisions/2026-09-28-openhands-resolver-isolation.md`, `docs/lanes.md`, `.github/pull_request_template.md`, the merged #425 recipe, #429's runtime skill exclusion and #465's agent-branch ruleset. The registry follows the hot-file protocol: main's copy at each merge, then `scripts/host_receipts.py:register_file` for the owned rows and the supported report generators.
- Review-round fixture repair: [git/git `v2.43.0` `t/test-lib-functions.sh`](https://github.com/git/git/blob/v2.43.0/t/test-lib-functions.sh#L750) (`test_lazy_prereq`, a probed prerequisite; filesystem examples such as `SYMLINKS` and `CASE_INSENSITIVE_FS` in [`t/test-lib.sh`](https://github.com/git/git/blob/v2.43.0/t/test-lib.sh#L1773)), and [CPython `v3.13.15` `Lib/unittest/case.py`](https://github.com/python/cpython/blob/v3.13.15/Lib/unittest/case.py#L54) (`_Outcome.testPartExecutor` records a `SkipTest` raised inside `subTest` as that subtest's skip; `subTest`, `:538-565`, resumes after the block and stops the method under failfast). Read on 2026-10-03; the installed interpreter's `case.py` is byte-identical to that tag.
- Step 6 repair round: repository source read at `b0c11c324`, covering `resolver/gh_harness.py` (`REPO`, `op_push`, `push`, `op_pr_create` and its allowlist entry, `check_repository` and `branch_rules`), `resolver.py` `build_pr_body` and `plan_run`, and `host.py` `read_stage_gates`. The repository's owner type, visibility and fork count were read with `gh api` on 2026-10-03. GitHub's fork-PR token and secret limits come from [Events that trigger workflows, "Workflows in forked repositories"](https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows), for `pull_request` runs from a fork. [Forks, "Which repositories can be forked?"](https://docs.github.com/en/pull-requests/reference/forks) says nothing on forking one's own repository, so the decision record marks the fork's holder undetermined. Both pages were read 2026-10-03 and re-read 2026-10-04T00:23Z.
- Pre-push gate (2026-10-04). The GPT-family job 004's six sources, which also cover the command center's proposal, were each fetched on 2026-10-04 (HTTP 200) and quoted in the decision record:
  - [GitHub Secure use reference](https://docs.github.com/en/actions/reference/security/secure-use): "Any user with write access to your repository has read access to all secrets configured in your repository", plus untrusted checkout and hosted runners;
  - [Workflow syntax](https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax): unspecified permissions are set to none, `cache-mode`, `steps[*].run`, `working-directory` and local `uses: ./`;
  - [Events that trigger workflows](https://docs.github.com/en/actions/reference/workflows-and-actions/events-that-trigger-workflows): `push` "includes workflows that are not merged into the default branch", and the fork limits;
  - [Dependency caching reference](https://docs.github.com/en/actions/reference/workflows-and-actions/dependency-caching): PR runs restore base and default-branch caches, and their own caches are scoped to the merge ref;
  - [OpenSSF Scorecard checks](https://github.com/ossf/scorecard/blob/main/docs/checks.md): Token-Permissions and Dangerous-Workflow;
  - [zizmor audits](https://docs.zizmor.sh/audits/): the five audits the gate fails on, each working offline.
  The gate's mechanisms add three more: [GitHub Script injections](https://docs.github.com/en/actions/concepts/security/script-injections) (the untrusted-context endings), [Python unittest, "Test Discovery"](https://docs.python.org/3/library/unittest.html#test-discovery) with the installed CPython 3.13.15 `unittest/loader.py`, and the installed zizmor 1.30.1 `--help`. In-repository references: `patch_policy.py`'s reviewed derivation, `tests/test_workflow_hardening.py`'s text-level workflow reading, and `.github/requirements-ci.txt` and `validate.yml` for CI's zizmor pin and flags.
- Gate data (cross-family repair, 2026-10-04). The Python behaviour the reader models, from docs.python.org/3.13 (read 2026-10-04, HTTP 200) and checked on the installed CPython 3.13.15: [pathlib](https://docs.python.org/3.13/library/pathlib.html) ("If a segment is an absolute path, all previous segments are ignored (like os.path.join())"; `Path.rglob`), [fnmatch](https://docs.python.org/3.13/library/fnmatch.html) ("the filename separator ('/' on Unix) is not special to this module"), [tomllib](https://docs.python.org/3.13/library/tomllib.html) and [csv](https://docs.python.org/3.13/library/csv.html) (read through a file object), and the comprehension scopes of the [Language Reference 6.2.4](https://docs.python.org/3.13/reference/expressions.html#displays-for-lists-sets-and-dictionaries) and [PEP 572](https://peps.python.org/pep-0572/). In-repository: `scripts/validate_convergence.py` (P1's example) and `tools/sota-convergence/gap_wave_ledger.py` (the main source of breadth).

### Evidence-class table

| Claim | Evidence class | Command / receipt |
| --- | --- | --- |
| Resolver templates, patch policy, outgoing guard, PR loop, host mode and end-to-end fake scenarios | `local_integration` | Required OpenHands test pair at `b0c11c324` with a neutral `TMPDIR`: 248 tests, exit 0. It uses fake Docker, GitHub and agent-server operations and real local Git |
| The pair no longer depends on `TMPDIR` | `local_integration` | The same pair at `b0c11c324` with a throwaway `TMPDIR` under the host's home path: exit 0, `OK (skipped=2)`. The two symlink subtests are skipped by the probed prerequisite with the reworded reason. At `d35633fad` the same run exited 1 with failures=2 (`'private_content' != 'host_path'`) |
| The repaired guard assertions still catch planted defects | `synthetic`, at `2ede7b871` | Scratch worktree at `2ede7b871`. With the `host_path` refusal disabled, both tests fail under both `TMPDIR`s (exit 1). With the realpath form dropped, the symlink subtest fails under a neutral `TMPDIR` (exit 1) and is skipped under a home-path `TMPDIR`. Not re-run at `b0c11c324`: `cf42c6d08` changes only that test's comment and skip text, not an assertion |
| The previous alias fixture fails when its three names collapse | `synthetic` | Existing unittest with only the three alias writes remapped: three matching failed assertions, exit 1 before repair; exit 0 after repair |
| All seven alias paths reach the unchanged validator and retain every refusal check | `local_integration` | All 11 `PatchValidatorTests` inside the pair run at `b0c11c324`, exit 0 on Linux with real Git 2.43.0; no platform skip |
| The repaired alias fixture and the `TMPDIR` repair pass on native macOS | `source_review` of retained CI execution output | `db24156b9`: `validate-macos` job `111264957003` (run `37144290967`), artifact `full-suite-macos.log`: `Ran 10078 tests`, `OK (skipped=1329)`, no FAIL or ERROR block. `test_case_unicode_and_filesystem_aliases_are_refused`, `test_host_paths_and_the_user_name_are_refused` and `test_pr_body_follows_the_template_and_renders_model_text_inert` are each `ok`. This is the first native macOS run of `2ede7b871`. Earlier, `d35633fad`'s job `111220987307` passed the alias test. `b0c11c324`: pending |
| The old native macOS suite failed at exactly the three alias subtests | `source_review` of retained historical execution output | Run `36524134513` (head `501bcc9e`), job `109263298833`, artifact `11015337319`, `full-suite-macos.log`: 7339 tests, failures=3, skipped=959. Its three FAIL blocks are the subtests `docs/A.md`, `Docs/z.md` and `docs/café.md` at test line 725, each `('case_or_unicode_alias', path) not found`. Re-downloaded read-only in the custody review round |
| The original tests catch planted defects | `synthetic`, historical | 9 of 9 repair-round mutations detected; unchanged `evidence/stage2-*fail-first.txt` logs |
| Git's macOS argument precomposition needs an explicit fixture override | `source_review` | git/git `v2.43.0` `git.c:449`, `compat/precompose_utf8.c:67-105`, `Documentation/config/core.txt:44-51` |
| The resolver as built pushes to and opens PRs only in this repository, so the fork option needs a harness change | `source_review` | At `b0c11c324`: `resolver/gh_harness.py:44`, `:241-254`, `:257-259`, `:448`, `:627-628`, `:684-689`, `:704-709`; the final message reaches the PR body through `resolver.py:547-550`, `:590-592` |
| A real run refuses at the gates stage before G4 today | `source_review` | At `b0c11c324`: `plan_run` checks the stage gates, G5 and then G4 (`resolver.py:1589-1591`). `read_stage_gates` raises `stage_gates_not_recorded` when `stage-gates.json` is absent (`host.py:1357-1361`) |
| The original workflow/token bounds | `source_review`, historical scope | Stage 2 security review of 20 workflows at `94894f54`; this is not current-base CI or fork acceptance |
| Linux full suite in CI | `source_review` of retained CI execution output | `db24156b9`: `validate` job `111264954786`, CI merge `69650a33` of `db24156b9` into `d2fc3803e`, `python3 -m unittest`: `Ran 10078 tests in 1664.615s`, `OK (skipped=968)`. `b0c11c324`: pending |
| Linux full suite on the host | `local_integration`, before the step 6 round | Registry commit `96b96c681` (only `.github/workflows/validate.yml` and `manifests/evidence.json` differ at `d35633fad`), home-path `TMPDIR`: exit 1; 10,070 tests, failures=12, errors=1, skipped=850. Its 13 failing IDs are the 2 fixture cases repaired in `2ede7b871` and the 11 compared in the next row. Not re-run at `b0c11c324`: it takes about 43 minutes on this host, which would overrun a scheduled measurement window. The builder's sandbox run (10,046 tests, 485 failures) is superseded |
| None of the 11 remaining IDs is specific to this PR | `local_integration`, at `b2d556c95` | Same command and `TMPDIR` at `b2d556c95`, in a fresh detached worktree at origin/main `ecea2865`, and at the then-merged base `59f8a1e36`. With a neutral `TMPDIR`, the same 1 failure on every tree; with a home-path `TMPDIR`, the same 9 failures on every tree. Supersedes the builder's 607-method archive comparison and the earlier `4ced2923` clone control |
| Publication validation | `local_integration` | `scripts/validate.py` with a neutral `TMPDIR` at `b0c11c324`: exit 0, `"status": "passed"` (9,550 hashed files, 193 receipts). CI's `validate.py` passed on `db24156b9` (job `111264954786`). The builder's exit 1 (the `AGENTS.md` mismatch before the `4ced2923` merge) is superseded |
| Registry rebuild and generated reports | `local_integration` | At `db24156b9`: all 16 owned rows over main `d2fc3803e`'s registry. At `b0c11c324`: the rows of the record, `RESOLVER.md` and the resolver test module are refreshed. Both generators exit 0 and change no file, and `scripts/evidence_manifest.py --check` passes (9,550 files) |
| Configured Gitleaks scan of history | `local_integration` | Gitleaks 8.30.1 over `origin/main..HEAD` at `b0c11c324`: 36 commits, exit 0, no leaks found. The pre-commit scans of both step 6 commits found no leaks |
| Required contexts on the pushed head | `source_review` of CI status | `db24156b9`: all eight passed (`validate` job `111264954786`, `validate-macos` job `111264957003`). A later `validate` re-run there (job `111278594671`) was cancelled at 19:56:39Z, after `b0c11c324` was pushed. `b0c11c324` at 19:58:50Z: dependency-review, osv-scanner, sota-sources, token-report and verdict-review-gate passed; validate and secret-scan were in progress; validate-macos was queued |
| The pre-push gate refuses planted protected changes before any push, passes a benign commit, refuses from inside the agent tree and fails closed without zizmor | `local_integration` | `tests.test_runtime_worker_openhands_push_gate` at `050bca5d5`: 31 tests, exit 0, `OK (skipped=1)`, the PyYAML cross-check, which this interpreter cannot run; its real-zizmor 1.30.1 test ran |
| The gate's workflow reader matches PyYAML on all 21 workflows | `local_integration` | `/usr/bin/python3` (PyYAML 6.0.1) `-m unittest ...push_gate.RepositoryWorkflowTests`: 3 tests, exit 0 |
| The new and updated tests fail without the gate | `synthetic`, failing-first | Base `456f8fee6` with the new tests copied in: gate module exit 1 (errors=7), resolver module exit 1 (failures=1, errors=56), each traced to the missing gate API (`evidence/push-gate-fail-first.txt`, part 1) |
| The gate's tests catch planted defects | `synthetic` | 17 mutations of `push_gate.py` and `gh_harness.py`, each failing its named tests (exit 1); the unmutated copy passes (part 2) |
| The gate on this repository's own trees, with real zizmor | `local_integration`, rehearsal | Local clones of `48831bc65` with one planted commit each, real zizmor 1.30.1, no resolver, container or GitHub call. The benign edit passes. Workflow, CODEOWNERS, gate-script, helper, policy-test, new-test, `.gitleaks.toml` and gate-code edits are refused with their rules, and a planted template injection is refused by zizmor. About 2 s per check (part 4) |
| Live resolver containment, model/gateway behavior, GitHub writes | not run / not accepted | The CI posture is decided (option 1 with the trusted pre-push gate). The first live run waits until the gate lands on main, its negative controls pass there, and G2/P3/G5 and G4 are recorded with fresh P0-P2. No live resolver run occurred |

### Local commands run

```text
# Head 050bca5d5 (pre-push gate), 2026-10-04 04:00-04:02Z. TMPDIR=/var/tmp/489-gate, nice -n 19, after
# git fetch origin main (origin/main aecfaaaa6, merge base d2fc3803e). The tree was clean at this head.
$ python3 -m unittest tests.test_runtime_worker_openhands_resolver tests.test_runtime_worker_openhands
exit 0; Ran 249 tests in 20.319s; OK
$ python3 -m unittest -v tests.test_runtime_worker_openhands_push_gate
exit 0; Ran 31 tests in 8.958s; OK (skipped=1: the PyYAML cross-check; the real-zizmor test ran)
$ /usr/bin/python3 -m unittest tests.test_runtime_worker_openhands_push_gate.RepositoryWorkflowTests
exit 0; Ran 3 tests; OK (PyYAML 6.0.1 cross-check of the workflow reader)
$ python3 scripts/validate.py
exit 0; {"components": 69, "hashed_files": 9553, "profiles": 4, "receipts": 193, "status": "passed"}
$ python3 scripts/evidence_manifest.py --check
exit 0; {"files": 9553, "status": "passed"}
$ python3 scripts/component_matrix.py --check; python3 scripts/new_host_grand_list.py --check   # before the registry commit
exit 0 {"rows": 32, "status": "checked"}; exit 0 {"status": "passed", "layers": 32, "winners": 66}; no --write needed
$ git diff --check origin/main...HEAD
exit 0
$ python3 blueprints/runtime-workers/openhands/resolver.py --help; ... run --help
exit 0; exit 0 (run --help lists --zizmor)
$ gitleaks git . --config .gitleaks.toml --log-opts=origin/main..HEAD --redact --timeout 600
exit 0; 44 commits scanned; no leaks found (the four commits' pre-commit scans: no leaks)
$ python3 <the coordinator's merge-tree landing check> aecfaaaa6 050bca5d5
exit 0; clean three-way merge; merged-vs-main paths 20, outside PR-owned 0; main drift 304 paths, overlap 0;
registry foreign rows equal, order preserved, PR-owned rows 19; merged files[] sorted, no duplicates (9735 rows); LANDABLE
$ git push origin HEAD:claude/openhands-resolver-20260928
exit 0; pre-push registry tests: Ran 3 tests, OK; 456f8fee6..050bca5d5, no force
Failing-first, planted-defect and rehearsal runs: blueprints/runtime-workers/openhands/evidence/push-gate-fail-first.txt.
Not run: the host full suite (about 43 minutes here); CI runs it on the pushed head.

# Head b0c11c324 (step 6 repair round), 2026-10-03 19:53-19:56Z. TMPDIR is a neutral
# directory outside the home directory and every repository, unless the line says
# home-path TMPDIR. The commands ran on the working tree, which was then committed
# unchanged as cf42c6d08 and b0c11c324.
$ git diff --check
exit 0
$ nice -n 19 python3 -c '<host_receipts.register_file(Path("."), p) for each path>' <the record> <RESOLVER.md> <the resolver test module>
exit 0
$ nice -n 19 python3 scripts/component_matrix.py --write
exit 0; {"flip_rule_violations": 0, "rows": 32, "status": "written"}; no file changed
$ nice -n 19 python3 scripts/new_host_grand_list.py --write
exit 0; {"status": "written", "layers": 32, "winners": 66}; no file changed
$ nice -n 19 python3 scripts/evidence_manifest.py --check
exit 0; {"files": 9550, "status": "passed"}
$ nice -n 19 python3 scripts/validate.py
exit 0; {"components": 69, "hashed_files": 9550, "profiles": 4, "receipts": 193, "status": "passed"}
$ nice -n 19 python3 -m unittest tests.test_runtime_worker_openhands_resolver tests.test_runtime_worker_openhands
exit 0; Ran 248 tests in 22.014s; OK
$ (home-path TMPDIR, a throwaway directory removed afterwards) nice -n 19 python3 -m unittest -v <the same pair>
exit 0; Ran 248 tests in 24.993s; OK (skipped=2); both skips give the reworded reason
$ nice -n 19 python3 blueprints/runtime-workers/openhands/resolver.py --help
exit 0
$ nice -n 19 python3 blueprints/runtime-workers/openhands/resolver.py run --help
exit 0
$ nice -n 19 git diff --check origin/main...HEAD
exit 0 (origin/main 463a57b98, merge base d2fc3803e); git diff --name-only origin/main...HEAD: the 17 contract paths
$ cmp <(git show 501bcc9e:<record> | sed -n 1,15p) <(sed -n 1,15p <record>)    # and the same against origin/main
exit 0; exit 0
$ git rev-parse HEAD:<log> 501bcc9e:<log>    # both evidence/stage2-*fail-first.txt logs
ed55377f232aa64f46f1b7dce004fce1be5cc7a7 and 3f41c01b05feff7bf199c16266ea96c73ffa14c5, equal at both commits
$ nice -n 19 gitleaks git . --config .gitleaks.toml --log-opts=origin/main..HEAD --redact --timeout 600
exit 0; 36 commits scanned; no leaks found (the pre-commit scans of cf42c6d08 and b0c11c324: no leaks)
$ nice -n 19 python3 <the coordinator's merge-tree landing check> 463a57b98 b0c11c324
exit 0; clean three-way merge; merged-vs-main paths 17, outside PR-owned 0; main drift 30 paths, overlap 0;
registry foreign rows equal, order preserved, PR-owned rows 16; merged files[] sorted, no duplicates (9571 rows); LANDABLE
$ git push origin HEAD:claude/openhands-resolver-20260928
exit 0; pre-push registry tests: Ran 3 tests, OK; db24156b9..b0c11c324, no force
Not run in this round: the host full suite (about 43 minutes here, which would overrun a scheduled
measurement window; the CI full suites on db24156b9 are below) and the planted-defect mutations
(recorded at 2ede7b871; no assertion has changed since).

# Head b2d556c95, 2026-10-03 17:08-17:10Z (historical). Same TMPDIR convention.
$ nice -n 19 python3 scripts/validate.py
exit 0; {"components": 69, "hashed_files": 9429, "profiles": 4, "receipts": 187, "status": "passed"}
$ nice -n 19 python3 -m unittest tests.test_runtime_worker_openhands_resolver tests.test_runtime_worker_openhands
exit 0; Ran 248 tests in 19.862s; OK
$ (home-path TMPDIR) nice -n 19 python3 -m unittest tests.test_runtime_worker_openhands_resolver tests.test_runtime_worker_openhands
exit 0; Ran 248 tests in 20.310s; OK (skipped=2)
$ nice -n 19 python3 blueprints/runtime-workers/openhands/resolver.py --help
exit 0
$ nice -n 19 python3 blueprints/runtime-workers/openhands/resolver.py run --help
exit 0
$ nice -n 19 git diff --check origin/main...HEAD
exit 0 (origin/main ecea2865, merge base 59f8a1e36)
$ git diff --name-only origin/main...HEAD
exit 0; exactly the 17 contract paths
$ nice -n 19 gitleaks git . --config .gitleaks.toml --log-opts=origin/main..HEAD --redact --timeout 600
exit 0; 34 commits scanned; no leaks found
$ nice -n 19 python3 scripts/component_matrix.py --write
exit 0; {"flip_rule_violations": 0, "rows": 32, "status": "written"}; no file changed
$ nice -n 19 python3 scripts/new_host_grand_list.py --write
exit 0; {"status": "written", "layers": 32, "winners": 66}; no file changed
$ git push origin HEAD:claude/openhands-resolver-20260928
exit 0; pre-push registry tests: Ran 3 tests, OK; d35633fad..b2d556c95, no force

# Head d35633fad, before the fixture repair, 16:55-16:57Z
$ nice -n 19 python3 scripts/validate.py
exit 0; "status": "passed"
$ nice -n 19 python3 -m unittest tests.test_runtime_worker_openhands_resolver tests.test_runtime_worker_openhands
exit 0; Ran 248 tests in 20.274s; OK
$ (home-path TMPDIR) the same pair
exit 1; Ran 248 tests in 20.300s; FAILED (failures=2)
OutgoingGuardTests.test_host_paths_and_the_user_name_are_refused and
PullRequestLoopTests.test_pr_body_follows_the_template_and_renders_model_text_inert: 'private_content' != 'host_path'

# Clean-main comparison of the 11 non-OpenHands IDs that failed in the host full suite below
$ git worktree add --detach <scratch> origin/main      # ecea28654a835fff2cc3651bab77ca0e46b9bec5, clean
$ git -C <scratch> checkout --detach 59f8a1e36          # the then-merged base, clean
$ nice -n 19 python3 -m unittest <the 11 IDs>          # same command in every tree and TMPDIR
tree                     neutral TMPDIR          home-path TMPDIR
b2d556c95                exit 1; failures=1      exit 1; failures=9
d35633fad                exit 1; failures=1      exit 1; failures=9
origin/main ecea2865     exit 1; failures=1      exit 1; failures=9
merged base 59f8a1e36    exit 1; failures=1      exit 1; failures=9
Within each TMPDIR, the failing IDs are identical on every tree:
- under both: tests.test_windows_terminal_defaults.OverlayTests.test_the_installed_client_knows_no_notification_type_without_a_decision
  (the installed client knows a notification type, auth_storage_failure, that has no decision)
- under the home-path TMPDIR only, in tests.test_token_e2e_grader:
  F19c_Stage3Mutants.test_M17c_manifest_canary_off, F19d_RepairRoundMutants.test_M56c_the_export_backstop_is_off,
  F29_Export (3 tests), F29b_CheckHtml (2 tests), F29c_ArgvSanitizer.test_a_grade_run_that_spells_its_flags_with_equals_records_no_path
- passed on every tree under both:
  tests.test_gpt6_family_tiering_20260926.RunnerTests.test_sigterm_records_the_running_call_as_interrupted_without_counting_it,
  tests.test_order_throughput.CapacityRunTests.test_cli_refuses_live_base_url_from_env_file_without_network
$ git worktree remove <scratch>; git worktree prune
exit 0

# Host full suite, registry commit 96b96c681, home-path TMPDIR (coordinator run before the custody review round)
$ nice -n 19 python3 -m unittest
exit 1; Ran 10070 tests in 2568.426s; FAILED (failures=12, errors=1, skipped=850)
13 failing IDs: the 2 OpenHands fixture cases (repaired in 2ede7b871) and the 11 IDs compared above
earlier control, superseded by the comparison above: the 11 IDs in a clean 4ced2923 clone, FAILED (failures=10, errors=1)

# CI, read-only, 2026-10-03T19:57-19:59Z (gh api jobs and check-runs, gh run view --log, gh run download)
db24156b9 validate job 111264954786: success. CI merge 69650a33 (db24156b9 into d2fc3803e);
validate.py {"components": 69, "hashed_files": 9550, "profiles": 4, "receipts": 193, "status": "passed"};
component matrix {"rows": 32, "status": "checked"}; new-host grand list {"status": "passed", "layers": 32, "winners": 66};
python3 -m unittest: Ran 10078 tests in 1664.615s; OK (skipped=968)
db24156b9 validate-macos job 111264957003: success at 19:29:18Z. full-suite-macos.log: Ran 10078 tests in 1794.871s;
OK (skipped=1329); no FAIL or ERROR block; the alias test and both TMPDIR-repair tests ok
db24156b9 required contexts: all eight success; a later validate re-run (job 111278594671) was cancelled at
19:56:39Z, after b0c11c324 was pushed
b0c11c324 at 19:58:50Z: dependency-review, osv-scanner, sota-sources, token-report and verdict-review-gate success;
validate and secret-scan in progress; validate-macos queued

# CI, read-only, historical
$ gh pr checks 489 --required        # 2026-10-03T17:16:15Z
b2d556c95: dependency-review, osv-scanner, secret-scan, sota-sources, token-report and verdict-review-gate pass;
validate fail, job 111250877246: "files[2392]: files[] must be sorted by path (found
'docs/decisions/2026-10-03-omniroute-sdk-worker-0160.md' after
'docs/decisions/2026-10-03-retire-pr320-loki-denominator-host-receipts.md')", the pair main's job 111240392112 reports;
validate-macos pending
d35633fad: all eight passed: dependency-review, osv-scanner, secret-scan, sota-sources, token-report,
validate (29m39s), validate-macos (36m58s), verdict-review-gate
d35633fad validate job 111220987213: Ran 10070 tests in 1679.211s; OK (skipped=968)
d35633fad validate-macos job 111220987307, full-suite-macos.log: Ran 10070 tests in 1849.584s; OK (skipped=1329)

# Builder's sandbox record, before the 4ced2923 and 59f8a1e36 merges (superseded where marked).
# Its first pair run, with the host Gitleaks wrapper, exited 1 on the wrapper's unavailable lock;
# that failed attempt is retained separately, and PATH then selected native Gitleaks 8.30.1.
$ nice -n 19 python3 -m unittest tests.test_runtime_worker_openhands_resolver.PatchValidatorTests
exit 0; Ran 11 tests in 1.185s; OK
$ nice -n 19 python3 -m unittest        # superseded by the host and CI runs above
exit 1; Ran 10046 tests; FAILED (failures=485, errors=195, skipped=863); errors=168 with native Gitleaks on PATH
$ nice -n 19 gitleaks git . --config .gitleaks.toml --pre-commit --redact --timeout 600
exit 0; actual working diff scanned; no leaks found
$ nice -n 19 python3 scripts/validate.py   # superseded: the 4ced2923 merge brought main's AGENTS.md
exit 1; only the AGENTS.md SHA-256 and byte-count mismatch
```

These are repository integration checks, not unchanged upstream acceptance suites.

**CI on this head.** The workflows test GitHub's merge of the head with main.

On the reviewed head `db24156b9`, all eight required contexts passed:
- `validate` job `111264954786` tested merge `69650a33` (`db24156b9` into `d2fc3803e`). `validate.py` reported `"status": "passed"` with 9,550 hashed files and 193 receipts. The component matrix and new-host grand list checks passed. `python3 -m unittest` ran 10,078 tests: `OK (skipped=968)`.
- `validate-macos` job `111264957003` passed. Its `full-suite-macos.log` shows 10,078 tests, `OK (skipped=1329)` and no FAIL or ERROR block.

The merged registry is sorted. The `b2d556c95` `validate` failure (job `111250877246`) on main's unsorted registry pair no longer applies.

The new head `b0c11c324` changes only the decision record, `RESOLVER.md`, one test's comment and skip text, and three registry rows. Its required contexts were still running when this description was written. The head that lands must show all eight SUCCESS, and a macOS full-suite artifact with no failure in `tests.test_runtime_worker_openhands_resolver`.

**Linux full-suite acceptance item.**
- CI's Linux and macOS full suites passed on `db24156b9`, which differs from `b0c11c324` only in the files listed above.
- On the host, the PR's two test modules pass at `b0c11c324` under both `TMPDIR`s.
- The host full suite was not re-run in this round. At `b2d556c95`, its 11 other failing IDs failed identically on clean main and on the then-merged base, environment by environment.

### Review round

The custody review of `d35633fad` (independent Opus 5.5, read-only) returned **repair**. This is its one repair round. Numbers are the findings' indices in the review record, counted from 0, as in commit `2ede7b871`'s message.

| # | Severity | Finding | Disposition |
| --- | --- | --- | --- |
| 0 | should-fix | The description still described the state before the custody merge (`4ced2923` unmerged, `validate.py` exit 1) | Fixed. Scope, the SOTA "Repository" bullet, the evidence table and the commands now state the merged state: base `59f8a1e36` (merged in `d35633fad`), with `4ced2923` merged in `85830e815`. `scripts/validate.py` with a neutral `TMPDIR`: exit 0, `"status": "passed"` at `d35633fad` and `b2d556c95`. The builder's exit 1 remains only as superseded history |
| 1 | should-fix | The Linux full-suite state was contradictory, with no recorded clean-main comparison | Fixed. "Local commands run" records the comparison: a fresh detached worktree, at origin/main `ecea2865` and then at the merged base `59f8a1e36`, the 11 IDs, the command and every exit code under two `TMPDIR`s. The failing sets match this head's. The builder's sandbox numbers are marked superseded, and the "remains an acceptance blocker" paragraph is replaced by the evidence summary |
| 2 | minor | "Including unittest's trailing spaces" is false for the fail-first logs | Fixed. The clause is removed. The blob SHAs `ed55377f` and `3f41c01b` are unchanged from `501bcc9e`. The same wording in the custody contract, which lives outside the repository, is reported to the coordinator |
| 3 | minor | The home-path `TMPDIR` failure was called an environment artifact, but the fixtures and the check order come from this PR | Fixed in `2ede7b871` (tests only), with its registry row in `b2d556c95`. A synthetic absolute host root serves the two `host_path` assertions. The symlink case probes its prerequisite, following git's `test_lazy_prereq` pattern, and skips its two subtests with an explicit message. No assertion or reason label changed. Fail-first at `d35633fad`: exit 1, failures=2. After the fix: exit 0 under both `TMPDIR`s. Two planted defects are caught (see the evidence table) |
| 4 | minor | `validate-macos` had not run on `d35633fad` | Closed for `d35633fad`: job `111220987307` passed, and its log shows `OK (skipped=1329)` with the alias test `ok`. On `b2d556c95`, `validate-macos` is pending and `validate` failed on main's registry order; see "CI on this head" |
| 5 | minor | The reviewer did not re-run the local acceptance commands | Closed: the final-head runs and their exit codes are recorded above |
| 6 | minor | The reviewer did not download the historical macOS artifact | No change needed. Artifact `11015337319` was re-downloaded read-only in this round, and its three FAIL blocks are cited in the evidence table |
| 7 | minor | Neither contract review has a recorded verdict | Open and listed as pending: 6(a), GPT-6.1 Astra/max, after 19:03Z when the GPT-free slot ends; 6(b), the Opus closure review of `b2d556c95`. The PR had no review threads at 17:16Z |

### Step 6 repair round

This is the one repair round for the two step 6 reviews of `db24156b9`. A is the GPT-6 Astra/max review, and O1-O9 are the Opus closure review's findings in the order listed under "Step 6 reviews". The fixes are in `cf42c6d08`, with their registry rows in `b0c11c324`.

| # | Severity | Finding | Disposition |
| --- | --- | --- | --- |
| A | should-fix | Fork option prerequisites; the runbook permits a run after either choice; CI egress and final message; the fork guarantee is unverified | **Fixed.** The record's option 2 now states that the harness pushes to and opens PRs only in this repository, and lists what option 2 needs before a first run: a fork remote and push-URL check, `--head <owner>:<branch>`, the rules lookup and a `non_fast_forward` ruleset on the fork, and its own review. CI egress and condition 3 are addressed under both options, and the "not re-read" caveat is kept. The `RESOLVER.md` runbook precondition now also stops for option 2 until that change lands. The amendment heading, record lines 1-15 and the live-run wait are unchanged |
| O1 | should-fix | Option 2 incomplete; filed under the wrong kind of change; condition 3; the fork's owner | **Fixed** with A. `RESOLVER.md` Residuals separate the egress block (a workflow change outside this PR) from the fork option (a change to this PR's harness). The record names the fork's owner: the repository's owning User account, which is also the admin login the resolver acts through. The amendment summary in `RESOLVER.md` is updated to match |
| O2 | should-fix | The PR body describes `b2d556c95` | **Fixed** in this description: base and head, the merge list, "CI on this head", the evidence rows, and the local commands at `b0c11c324` with exit codes |
| O3 | minor | The skip message is too narrow | **Fixed.** The comment and skip reason name any `scripts/validate.py` `PRIVATE_CONTENT` pattern, such as a personal home path. No assertion changed, and the reworded reason appears in the home-path `TMPDIR` run |
| O4 | minor | The G4 reason-code order is wrong | **Fixed** in the `RESOLVER.md` G4 residual and under "What is not done" below |
| O5 | minor | `validate-macos` on `db24156b9` | **Closed for `db24156b9`:** job `111264957003` passed, and its artifact is cited in the evidence table. **Open:** `validate-macos` on `b0c11c324` |
| O6 | minor | The 6(a) review is pending | **Closed:** 6(a) returned (A above). **Open:** the reviewers' re-read of this delta |
| O7 | minor | Main moved after the custody merge | **Open, not merged in this round.** The landing check against `463a57b98` reports LANDABLE. Contract step 7's "repeat steps 2 and 7" remains the coordinator's call before landing |
| O8 | minor | The step-5 commands were not re-run | **Closed at `b0c11c324`**, except the host full suite and the planted-defect mutations (see "Local commands run") |
| O9 | minor | Verification record | No change needed |

### Decision record

`docs/decisions/2026-09-28-openhands-resolver-isolation.md` records the resolver-mode narrowing and its amendment, **proposed 2026-09-28 and decided 2026-10-04: option 1 with trusted pre-push enforcement**.

The decision section records the following:
- the owner's delegation, in their words: "max quality sota convergenced resolution automation workflow at highest quality";
- the command center's proposal (option 1 with an in-CI tripwire);
- the GPT-family job 004 vote: disagree on sufficiency, because a check inside PR CI cannot protect against the commit under test. Each reason is re-checked against the GitHub, OpenSSF Scorecard and zizmor sources;
- the gate and its trusted-copy invariant;
- the separate defence-in-depth PR for workflow hardening;
- the residuals, the evidence, and the overturn to option 2 if the gate cannot be kept immutable to the agent.

Option 2's text stays as the alternative; only its line citations moved with the harness change.

The history below describes the amendment before the decision. After `cf42c6d08` and the wording fixes `f4e7aa2a2` and `54438ce7f`, the amendment's option 2:
- states that the resolver as built pushes to and opens PRs only in this repository;
- lists the separately reviewed harness change and fork ruleset it needs before a first run;
- marks the fork's holder undetermined: an organization the owner creates, or a second account. The choice changes the push identity, the fork's ruleset and the `--head <holder>:<branch>` value;
- sources the token and secret guarantee, for `pull_request` runs from a fork, in GitHub's "Workflows in forked repositories".

Both options now address condition 3 and CI egress. The 2026-10-03 fixture-repair section records native Git sources, the skipped-check alternative, the argument-normalization completeness finding, evidence limits and the native macOS condition that would overturn the repair. Lines 1-15 remain unchanged.

### What is not done, and what needs the owner

- **Owner decision: decided 2026-10-04.** It chose option 1 with trusted pre-push enforcement; the owner delegated the choice to converged practice. Still open:
  - workflow hardening, in a separate defence-in-depth PR: `permissions: {}` defaults, `persist-credentials: false`, cache, runner and timeout policy, a protected zizmor configuration, and a strict tripwire test on main. Until then, code under test runs with network, and that residual is accepted;
  - the first live run, which waits until this gate lands on main, its negative controls pass there and the stage gates are recorded;
  - the protected list, which is broad by design: all of `tests/**`, and every file a reachable step names. A resolver task that needs those files fails at the gate with no push;
  - option 2, an owner fork, which stays the overturn target and would need its own harness change.

  Resolver-PR check results are still not evidence of model-code safety.
- G4 remains unrecorded. Because no `stage-gates.json` exists, a real run today refuses earlier, at the gates stage, with `stage_gates_not_recorded`. Once the recorded stage gates and G5 pass, it refuses with `stage_gate_g4_not_recorded` until the coordinator records the isolated reviewer argv hash.
- G5 and `stage-gates.json` remain required. Both gateways' provider settings and the confinement design still need their own acceptance.
- These remain separate required steps:
  - fresh P0-P2 receipts, P3-P5 and G2 image qualification;
  - the reviewers' re-read of the step 6 delta;
  - the required contexts on the final head;
  - the first live draft-PR attempt.

  The native macOS check of the alias repair and the `TMPDIR` repair passed on `db24156b9`. A7's environment-name read at teardown stays in place.

### Host evidence

Not applicable: no file under `evidence/hosts/` changes. The historical macOS artifact is distinguished from a new native run, and no live resolver acceptance is claimed.

### Checklist

- [x] No GitHub Actions or workflow files changed; workflow hardening remains a separate defence-in-depth PR.
- [x] New Actions permissions or pins are not introduced by this change.
- [x] No credential value was read or published. Gitleaks scans of the history (36 commits at `b0c11c324`) and of both step 6 commits report no leaks, and the pre-push registry tests passed.
- [x] No new paid hosting, subscription or billing surface.
- [x] Peer-owned files and worktrees preserved.
- [x] Separate Stage 2 GPT review and whole-head Opus closure verdicts recorded, including residuals.
- [ ] The reviewers' re-read of the step 6 delta recorded.
- [ ] Every review thread resolved and all eight required contexts SUCCESS on the pushed head.
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