Repository navigation
Landing scripts: validate the merge with the shard-0 currency checks, and an optional squash body file - #1027
seathatflowsinourveins wants to merge 4 commits into
Conversation
…176) and take a squash body file The CC patched its live copies of the landing scripts twice on 2026-10-12. This ports both patches into tools/landing, with tests that fail at 86fa384: - nas_land.sh, CC correction #176: #1007 bound a file's sha256 in final-stack.json and #1018 changed that file. Each was green on its own base, and validate.py passed on the merge, so #1018 landed and main's validate-shard-0 failed on scripts/final_stack.py --check. After validate.py, merge_validate now runs every shard-0 step of validate.yml that runs a Python script with --check, as the step runs it and in the workflow's order: audit_reports, build_verdicts, component_matrix, new_host_grand_list, final_stack, gap_crosswalk build, gap_wave_ledger (its --wave and --owner arguments) and build_ecosystem. #176 named seven; the CC's ruling of 2026-10-12 added the ledger check. Each check runs only when its script is in the merge. The first that fails is exit 10, named by its command. Its output stays in the validation's 0600 file and is not printed (the live copy prints its last 300 bytes, which #975 P2-C removed for validate.py). On main at 86fa384 the eight exit 0 in about 8 s. - both scripts, SQUASH_BODY_FILE: both repositories' squash default is COMMIT_MESSAGES, so a commit message whose claim was corrected after review landed in main. When the variable is set, the merge passes the file with gh pr merge --body-file. A value that is not a readable, non-empty regular file stops with exit 2 before the lock and any call. That includes "-", which gh reads as standard input. The check is the group's first statement after the arguments; the live copies put it after set -u and before the group, which this copy parses whole. - README digest cells withheld (CC #161): the provenance table keeps the line counts of the live copies and the digests of the repository copies only. uet_land.sh needs no currency step: the trading repository's main rules count ci-gate only on a head that is up to date with main (strict), so its CI ran on the tree the squash merge makes. This repository's rules are not strict. Tests: - merge_validate's checks equal validate.yml's shard-0 Python --check steps, in order, the folded run: >- one included. The step reader is also run on a synthetic workflow. - The provenance section carries a 64-hex digest only in its "Here" column. - A merge that fails final_stack.py --check stops with 10. It merged at 86fa384. - A check runs only when its script is in the merge. - A missing, empty, directory, "-" or unreadable SQUASH_BODY_FILE stops both scripts with 2 before any call. - A body file whose path has a space reaches the merge as one --body-file argument. The fake python3 answers currency checks itself, so they never take one of the gate's answers. The CC's own regression, test_merge_validate_currency.sh, passes on this merge_validate and fails on 86fa384's. The README records the checks, the body file, the exit codes, the variable, the port's three differences from the live copies, the sources (cli/cli v2.102.0, the GraphQL schema, the REST description and GitHub Docs) and the new digests of the repository copies. Co-Authored-By: Claude Opus 5.5 <[email protected]>
…e scanned snapshot (#1027 P1) Astra's P1 at d6be1b0 (CHANGES_REQUESTED, reproduced on this PR's own EndToEndTests harness): nas_land.sh and uet_land.sh checked that SQUASH_BODY_FILE was a readable, non-empty regular file and nothing more, so a body holding a home path, an account name, an address that is not a no-reply one or a token shape went into main's permanent history through gh pr merge --body-file (her four synthetic payloads each gave exit 0 and one merge call). gh reads the file when the merge call starts (cli/cli v2.102.0 pkg/cmd/pr/merge/merge.go:146-153; :292-293 and http.go:72-75 send it as CommitBody; pkg/cmdutil/file_input.go:8-16), up to an hour or more after any check, so the scanned bytes must also be the bytes gh reads. When SQUASH_BODY_FILE is set, both scripts now, before the lock and every gh and git call: - copy the file once to a snapshot (mktemp in TMPDIR, mode 0600; an EXIT trap removes it on every exit, SIGTERM and SIGHUP included); - scan the snapshot with the new tools/landing/squash_body_scan.py (the repository's PRIVATE_CONTENT table from scripts/validate.py, a WSL UNC home path that table misses, an address that is not a no-reply one, and the names of the CC's landing-prohibited-names list; the list is parsed, never sourced) and with scripts/validate.py --scan-file (the scan the pre-push hook runs); - stop with exit 2 and one fixed line on a match, a copy or scan that fails, a scanner or names file that is missing or unreadable, and any answer that is not a scan's own clean line (fail closed); nothing of the body, no path and no scanner output is printed; - give gh the same snapshot, never the caller's file. New variables: LANDING_BODY_SCAN, LANDING_SCANNER (default: scripts/validate.py of LANDING_NAS_REPO, which also fits the CC's live copies) and LANDING_NAMES_FILE (default: the file under the coordination tree). Three allowances, the CC's rulings of 2026-10-12, each with its tests: - a names-list entry equal to the running host's own name (compared with hostname when the scan runs, never printed) is a warning count, not a refusal; every other name still refuses; - a systemd unit instance, <name>@<instance>.service|timer|socket|target|path|mount (systemd/systemd man/systemd.unit.xml:121-135), is not an address; - a short list of vendor co-author trailer addresses, each with the vendor source it comes from, passes: [email protected], as the vendor's own repository carries it (openai/codex@db22c91, message line 38). #1002's email registry replaces the list. A real-provider address is still refused (the control). Tests (22 new or changed; at d6be1b0 they give 140 failures and 5 errors, here they pass; the allowance tests also fail on the scan without the allowance): - a body with a home path of each form (Linux, macOS, Windows with either slash, the WSL mount, the WSL UNC forms with one or doubled backslashes, the dash-encoded and graph-id forms, percent-encoded), a name of a synthetic names file, an address that is not a no-reply one (with look-alikes) or a token shape (seven kinds) is refused by both scripts with exit 2 before any call; - a missing or failing scanner, names file or validate.py, a scanner that prints nothing or another line, and every answer of validate.py --scan-file but its clean one refuse the landing; - the valid-body control lands (exit 0, one merge call) with the body's bytes read from a mode-0600 snapshot, after both scans ran on it; - a file rewritten after the scan does not reach the merge; the snapshot exists during the run and is gone after exits 0, 3 and 7 and after SIGTERM and SIGHUP; the defaults of the new variables; the real validate.py --scan-file where Betterleaks is installed; - the allowances: a body naming the host lands with the count printed and the name not, and another listed name still refuses; unit instances land, their look-alikes and a provider address do not; the vendor address lands, another local part at the vendor's domain, the vendor's local part at another domain and a provider address do not; - squash_body_scan.py by itself: the names file's formats and that no line of it runs, the address, unit and vendor rules, the host name, a name as a whole token, and its one output line. Measured on the last 600 commit messages of main at 3a8a846 (counts only): 8 refused: 0 names, 5 addresses, 3 home paths; 26 messages name the host (a warning); 402 carry the vendor noreply trailer, which passes. main's history keeps 3 messages with a home path and 3 with an address at a mail provider; history is immutable, as for CC correction #177, and nothing here rewrites it. The README records the scan, the variables, the exit-2 cases, the known gaps and the sources: cli/cli v2.102.0, MicrosoftDocs/WSL, github/docs, systemd/systemd, openai/codex, the bash manual, CPython's -I and socket. The README digests and manifests/evidence.json follow the changed files. Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
|
@codex review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e203d014b4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…er does, and keep no target units (#1027 round 2) Round 2 of 2 of #1027, under the CC's adjudication at e203d01 (2026-10-12T09:03:43Z): both families landed an address through both real scanners at e203d01. - P1-a (Astra 1): a quoted local part, "x"@<provider>, matched no address shape. The shape's local part now holds quoted strings too, and squash_body_scan.py reads each address with CPython's RFC 5322 parser (email._header_value_parser get_addr_spec, Lib/email/_header_value_parser.py:1682-1696 at v3.13.16, cbc944f4bc59): quotes and quoted pairs are undone, so a quoted form is refused or passed as its unquoted form is (RFC 5322 3.2.4, rfc5322.txt:746-757). - P1-b (Astra 2): the vendor allowance stripped every leading non-word character, so +codex at the vendor's domain was compared as the vendor's address. The allowances now compare the whole address, local part and domain as the parser reads them; backticks, asterisks and quotes are outside an address only when they wrap it, and an address the parser reads with a defect passes no allowance. - P1-c (Claude B1): <local>@<provider>.com followed by a unit type had a unit instance's shape, for all six types. A unit is kept only when its instance is not an address's domain, and target is no longer a kept type: .target is a delegated top-level domain (IANA tlds-alpha-by-domain.txt, version 2026101200). - B2: the README's paragraph on the live copies is in the past tense and records the CC's sync of the live cc-tools copies to d6be1b0's scripts at 2026-10-12T03:15:27Z; the CC syncs them again after #1027 lands (ruling C). - B3: the README's cli/cli provenance names the contents API at fc4b137c, with the sha256 values matching; the local mirror, a blobless clone at ec5b5120, did not hold that commit. Tests: through both scripts, once with the canned validate.py --scan-file answer and once with the real scan where Betterleaks is at its pin, the quoted, prefixed and unit-suffixed addresses, an address at .target and a target instance are refused (exit 2, no gh or git call, no snapshot left), and the controls land (the exact vendor trailer, the no-reply forms, real unit instances, markup that wraps an allowed address). The oracle is the installed CPython parser; its answers on every text the tests give it are the same on CPython 3.12.3, 3.13.16 and 3.14.4. One test runs 24 local parts at 17 domains in nine forms (3,672 cases) against the allowances applied to the oracle's reading. At e203d01 the 14 tests of the squash body scan gave 2,685 failing cases in 8 tests, 106 of them landings; here they pass. The 600-message figure at 3a8a846 is unchanged: 8 refused (0 names, 5 addresses, 3 home paths). The README's sources, known gaps and tests sections and manifests/evidence.json follow the changed files. Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
@codex review |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
… parser; currency checks from the merge (#1027 round 3) Round 3 of #1027, one commit on 37e242c. Its inputs hold the reproductions, which are not repeated here: the CC's Claude micro at 37e242c (W1, W2, C1, P3-A to P3-C), the GPT family's fix3 verdict at 37e242c (blockers 1 to 3, follow-ups 2 and 3), the Codex connector's three threads on e203d01 (nas:430, nas:259, the address rule) and the CC's rulings of 2026-10-12 on the allowances and on the host-name fix. Each change is stated by what it guarantees. - No address passes for want of a pattern that finds it. squash_body_scan.py no longer searches for an address shape: on each line it judges every at sign with CPython's get_addr_spec (Lib/email/_header_value_parser.py at v3.13.16, cbc944f4bc59), reading the local part before it and the domain after it as the parser does, with quoted strings, comments and white space around the at sign, domain literals and domains of any form (RFC 5322 3.4.1, rfc5322.txt:959-969). An at sign inside a quoted string is judged inside it too. One with no local part before it or no domain after it is no address, and text the parser cannot read whole and without a defect is refused. - An allowance passes only a whole address that holds no other address and that no other touches. - By the CC's ruling, two shapes are not addresses: a source locator, a repository path, an at sign and a git object name of 7 to 64 hex digits as the whole domain (git v2.53.0 Documentation/revisions.adoc:14-16, object-name.h:137, hash.h:201-208; this repository's locator form, CLAUDE.md:7), and the one co-author address of this repository's synthetic scratch identity, cited to its source in the repository. A tag, a branch and every other domain without a dot stay refused. - A body whose only hit is the host's own name lands with the warning on any host, and an identity spelled as the host is still refused: the scripts run validate.py --scan-file with NATIVE_AGENT_PUBLIC_HOSTNAME=1, a new opt-in of scripts/host_name_scan.py that drops the hostname source, as that file does on a WSL host whose hostname is its WSL_DISTRO_NAME, and a Windows computer name of the same spelling. Nothing else sets it. - No listed identity goes unchecked for text that a shell and the scan would read differently: the names file's value is read only as a bare list or a list in one pair of quotes, and any other form fails closed. - A merge is validated with the shard-0 checks that main's CI will run on it: nas_land.sh holds no list any more and reads the steps from the merge's own .github/workflows/validate.yml, in the workflow's order (GitHub Docs at be38ec5d, data/reusables/actions/about-triggers.md:18: a run uses the workflow of the event's commit). The reader fails closed on a validate.yml in which it reads no check and on a step whose words are not plain ones (exit 10, the step's text not printed); a merge with no validate.yml runs none. - The scan's cost is linear in the text: 60 KB on one line takes at most 0.18 s, where round 2's rule took 24 s on one of the measured texts. - README: the signals after which the snapshot is removed are named (SIGINT, SIGTERM and SIGHUP, each tested; SIGKILL leaves it), #975's cli/cli row names the mirror that holds the pinned commit, and the sources, known gaps and tests sections follow the change. docs/decisions/2026-10-09-host-name-scan.md gains one sentence on the opt-in. Tests: on a git archive of 37e242c with this commit's two test files, the 19 new or changed tests give 2,254 failing cases and one error in 16 tests (100 landings of a refused address, 12 landings past a names file read otherwise, a landing with a failing check that the merge added); the three that pass there are the controls' test, the signal test and #176's own. Here all 19 pass, on CPython 3.12.3, 3.13.16 and 3.14.4, and the landing module's 150 tests pass. The oracle's test runs 29 local parts at 29 domains in nine forms (7,569 cases). Measured on the last 600 commit messages of main at 5421e5d (counts only): 70 refused, 0 names, 67 addresses and 3 home paths (round 2's rule: 8); 341 messages with the scratch co-author trailer and 62 with a source locator pass. The CC's own regression for #176 needs a validate.yml in its scratch repository to pass on this merge_validate. Co-Authored-By: Claude Opus 5.5 <[email protected]>
|
@codex review |
|
Codex Review: Didn't find any major issues. Can't wait for the next one! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Scope
tools/landing. Afterscripts/validate.py,nas_land.shnow also validates the merge onto currentmainwith every shard-0 step ofvalidate.ymlthat runs a Python script with--check(CC correction macOS arm64 SYN evidence for the adaptive-paper engine and mover trial mode #176, exit 10; since round 3 the steps are read from the merge's ownvalidate.yml). Both scripts take an optionalSQUASH_BODY_FILEas the squash commit's body (gh pr merge --body-file; exit 2 before any call when it is not a readable, non-empty file). The tests fail at the base. README digest cells withheld (CC 2026-09-24 community sweep: effort-guard SessionStart notice, working plugin-install commands, dated dispositions #161).SQUASH_BODY_FILE, so a body holding a home path, an account name, an address that is not a no-reply one or a token shape went intomain's history (her four synthetic payloads each gave exit 0 and one merge call). Both scripts now copy the file once to a private snapshot (mktempinTMPDIR, mode 0600, removed on every exit), scan the snapshot with the newtools/landing/squash_body_scan.pyand withscripts/validate.py --scan-file, and giveghthat same snapshot. A match, a copy or scan that fails, a missing scanner or names file and any answer that is not a scan's own clean line stop the landing with exit 2 and one fixed line, before the lock and everyghandgitcall (fail closed). Nothing of the body, no path and no scanner output is printed, but one count (below).hostnamewhen the scan runs, never printed) is a warning count and not a refusal, every other name still refuses; (2) a systemd unit instance,<name>@<instance>.service|.timer|.socket|.path|.mountwhose<name>@<instance>is no address, is not an address (round 2 dropped.target); (3) a short list of vendor co-author trailer addresses, each with its vendor source, passes (now one, the Codex co-author address in the vendor's own history), compared whole, and a real-provider address is still refused. Measured on the last 600 commit messages ofmain, the scan refuses 8: 0 names, 5 addresses, 3 home paths (37 before the allowances: 26 names, 8 addresses, 3 home paths), with round 2's rule as before it.<name>@<instance>is no address, withtargetdropped. Both README blockers are fixed. One commit on e203d01; the scripts are unchanged.@of a squash body is judged by CPython's RFC 5322 parser itself; two shapes pass by ruling, a source locator<repository>@<object name>and the repository's scratch co-author address; the host's own name is a warning through both real scans on any host; the names file is read only in a form a shell reads as the same list; andnas_land.shreads the currency checks from the merge's ownvalidate.yml.86fa384421b1ca50134bd56d89cc72e0f7547816lane:shared, as tools(landing): move the CC's landing scripts into the repository, with offline tests #975 was: the scripts land both lanes' pull requests (uet_land.shthe trading repository's).tools/landing/nas_land.sh,tools/landing/uet_land.sh,tools/landing/README.md,tools/landing/squash_body_scan.py(new),tests/test_landing_scripts.py, and since round 3scripts/host_name_scan.py(one opt-in, off unless set),tests/test_host_name_scan.pyanddocs/decisions/2026-10-09-host-name-scan.md(one sentence on it);manifests/evidence.jsononly re-registers those eight files.Round 2
The CC's adjudication at e203d01 (2026-10-12T09:03:43Z; both families CHANGES_REQUESTED) upheld three P1s, each a way for an address to pass both real scanners into the merge, and two README blockers. Commit
37e242c0, one commit on e203d01, fixes them insquash_body_scan.py, the tests and the README;nas_land.sh,uet_land.shandcodex_gate.pyare unchanged, so the README's "Here" digests stand."x"@<provider>is a valid RFC 5322 address that the atext-only shape never matched (squash_body_scan.py:46-47at e203d01). The shape's local part now also holds quoted strings, and the scan reads each address with CPython's RFC 5322 parser,email._header_value_parser.get_addr_spec: quotes and quoted pairs are undone, so a quoted local part is refused or passed as its unquoted form is (RFC 5322 3.2.4, "quoted-string is identical to atom, semantically"). Decision point for the readers: a quoted form of an allowed address (the vendor's local part, ornoreply, in quotes) therefore passes, as RFC 5322 makes it the same address; refusing every quoted local part instead is a one-line change.:100-106at e203d01), so+codexat the vendor's domain was compared as the vendor's address. The allowances now compare the whole local part and the whole domain as the parser reads them:+codex,!codex,+noreply,!no-replyand a domain that goes on past the vendor's are other addresses. Backticks, asterisks and quotes count as markup only when they wrap the address, closing right after its domain; a mark that does not close stays in the local part, as the parser reads it. An address the parser reads with a defect, an obsolete form included, passes no allowance.<local>@<provider>.comfollowed by any of the six unit types had a unit instance's shape (:107-108at e203d01; 12 of 12 end-to-end runs landed). A unit is kept only when its instance is not an address's domain, so that<name>@<instance>is no address, andtargetis no longer a kept type:.targetis a delegated top-level domain (IANA list version 2026101200), so an address at<x>.targethad the shape too. A bare unit has no@and needs no allowance. A dotted instance shaped like a domain (client.conf) is now refused (fail closed).codex_gate.pybyte for byte, nosquash_body_scan.py, read on 2026-10-12), and that the CC syncs them again after this PR lands (ruling C). The live-copy column's header no longer reads as current.cli/clirow says the files were read through the GitHub contents API atfc4b137c, with the sha256 values matching (read again for round 2: the same three); the local mirror, a blobless clone atec5b5120, did not hold that commit. The section's intro no longer says that every row was read from a mirror.get_addr_spec,Lib/email/_header_value_parser.py:1682-1696at v3.13.16,cbc944f4bc59; the installed 3.13.16 file has the pinned bytes). On every text the tests give it, CPython 3.12.3 (CI's), 3.13.16 and 3.14.4 answer the same (measured 2026-10-12). Each test has it read its addresses first, and one test checks 3,672 cases against the allowances applied to its reading..service), 1 vendor co-author address and 402 vendornoreplytrailers passing, 37 refused without the allowances; onmain's last 600 at bb945f1, the same 8.Round 3
One commit,
cb0429d7, on37e242c0. Its inputs, which hold the reproductions (they are not repeated here; each fix is stated by what it guarantees):command-center/research-cc-role-20261008/pr1027-claude-micro-37e242c0.md(W1, W2, C1, P3-A to P3-C);fix3-pr1027-37e242c03/GPT-VERDICT.md(blockers 1 to 3, follow-ups 1 to 8);nas:430,nas:259and the address rule);scripts/host_name_scan.py.What the commit guarantees:
No address passes for want of a pattern that finds it (Claude W1, W2 and C1; GPT blockers 1 and 2; the Codex address thread).
squash_body_scan.pyno longer searches for an address shape. On each line it judges every@with the oracle, CPython'sget_addr_spec(Lib/email/_header_value_parser.pyat v3.13.16,cbc944f4bc59): the local part before the@and the domain after it are read as the parser reads them, with quoted strings, comments and white space around the@, domain literals and domains of any form, and an@inside a quoted string is judged inside it as well. An@with no local part before it or no domain after it is no address. Text around an@that the parser cannot read whole and without a defect is refused.An allowance passes only a whole address that holds no other address and that no other touches (Claude W1 and W2). The allowances compare the complete parsed address, refuse a local part that holds an
@, and refuse an address whose domain a quote or an@follows; since each@is judged by itself, an address inside or beside an allowed one is refused there too.The allowances of the CC's ruling on this round. Judging every
@makes this repository's own locators and its scratch co-author trailer addresses to the parser; onmain's last 600 commit messages the rule alone would refuse 399. The CC ruled two shapes not addresses:<repository>@<object name>, this repository'srepo@pin:path:lineform (CLAUDE.md:7): the whole domain is a git object name, 7 to 64 hex digits, and the local part has only the characters of a repository's path;A tag, a branch or any other revision after an
@, and every other domain without a dot, stay refused; such a body is rewritten (<repo>at<tag>; a mention in a code span of its own).A body whose only hit is the host's own name lands with the warning on any host, and an identity spelled as the host is still refused (GPT blocker 3; the Codex thread on
nas:259). The scripts run their second scan withNATIVE_AGENT_PUBLIC_HOSTNAME=1, a new opt-in ofscripts/host_name_scan.pythat drops the hostname source, as that file already does on a WSL host whose hostname is itsWSL_DISTRO_NAME, and with it a Windows computer name of the same spelling (on WSL the hostname is by default that name); the account, profile and email sources stay. Nothing else sets it, so the pre-push scan is unchanged.No listed identity goes unchecked for text that a shell and the scan would read differently (Claude P3-1 at e203d01; GPT follow-up 2). The names file's value is read only as a bare list or a list in one pair of quotes; any other form stops both scripts as unscannable. The CC's names file is in a documented form (checked by count, 3 names).
A merge is validated with the shard-0 checks that
main's CI will run on it (the Codex thread onnas:430; neither read reproduced it, and this round did, through the PR's harness at 37e242c).nas_land.shholds no list any more:shard0_checksreads the steps from the merge's own.github/workflows/validate.yml, in the workflow's order, so a step that the merge adds or changes runs as the merge writes it. The reader fails closed: avalidate.ymlin which it reads no check, and a step whose words are not plain ones, stop the landing with exit 10 before any check runs, the step's text not printed. A merge with novalidate.ymlruns none:main's CI has no such workflow to run on it, and a head that removes the file has novalidatecheck run, which the CI gate requires.The scan's cost is linear in the text (Claude P3-A). 60 KB on one line takes at most 0.18 s; round 2's rule took 24 s on 60 KB of one of the measured texts.
The README says which signals remove the snapshot (Claude P3-2 at e203d01; GPT follow-up 3): SIGINT, SIGTERM and SIGHUP, each measured and tested; SIGKILL leaves the mode-0600 snapshot, and the README says how to remove it.
Provenance (Claude P3-B): tools(landing): move the CC's landing scripts into the repository, with offline tests #975's
cli/clirow names the mirror that holdsfc4b137c(cli/cli-2.102.0; the three digests read again from it).The three threads, for the CC's replies:
nas:430(thread 4245825570): reproduced at 37e242c and fixed here; the checks are read from the merge's ownvalidate.yml.@is judged by the parser, whatever the domain's form.nas:259(thread 4245825585): reproduced by the GPT read and fixed here; the second scan drops the host's own name only, on any host.Measured (2026-10-12, counts only): on the last 600 commit messages of
mainat 5421e5d the scan refuses 70: 0 names, 67 addresses, 3 home paths (round 2's rule: 8, with 5 addresses). Of the 67, 31 hold a tag or a version after an@, 21 another domain without a dot, 13 white space or a comment at the@, 5 the addresses round 2 refused, 3 text the parser reads with a defect and 1 a commit id after a local part that is no repository path (a message may hold several kinds). It passes the 400 messages with a no-reply local part, the 341 with the scratch co-author trailer, the 78 with GitHub's no-reply domain, the 62 with a source locator, the 2 with a unit instance, the 1 that names a template unit and the 1 with the vendor co-author address; 26 messages (66 occurrences) name the host, a warning. Without the CC's allowances it refuses 417 (26 names, 400 addresses, 3 home paths).Fail before, pass after: on a git archive of 37e242c with this round's two test files, the 19 new or changed tests give 2,254 failing cases and one error in 16 tests; the three that pass there are the controls' test, the signal test and #176's own test. At the fix all 19 pass, on CPython 3.12.3, 3.13.16 and 3.14.4, and the module's 150 tests pass.
For the CC to know:
<name>@.<type>, passes: the parser reads no address there (no domain starts with a dot), and 1 of the 600 messages names one. It is not an allowance of an address, and it is tested.test_merge_validate_currency.shin its tools directory) reports a failure on thismerge_validate, because its scratch repository holds novalidate.yml. A copy whose scratch repository holds one, and which cutsshard0_checksout withmerge_validate, passes. It is a deployment item beside ruling C.nas:430thread and the address thread is 4245825578.SOTA sources
gh pr merge --body-file(GitHub CLI):cli/[email protected](commitfc4b137c),pkg/cmd/pr/merge/merge.go::176-177defines--bodyand--body-file/-F, "Read body text fromfile(use "-" to read from standard input)";:138-144makes the two mutually exclusive;:146-153reads the file when the command starts and setsBodySet. This is the mechanism of Astra's P1:ghreads the file when the merge call starts, over an hour after a check made at the start of a landing (the Codex wait takes up to 20 minutes, the CI wait up to 50), so the scanned bytes must be the bytesghreads. The scripts scan a snapshot and giveghthe snapshot;:292-293puts the body in the merge payload.pkg/cmd/pr/merge/http.go:72-75turns a set body, an empty one included, into the mutation'sCommitBody.pkg/cmdutil/file_input.go:8-16:-reads standard input. The gh manual: https://cli.github.com/manual/gh_pr_merge. (The reader function ispkg/cmdutil/file_input.go;pkg/cmd/pr/shared/file_input.godoes not exist at the tag.)The merge's body field: the GitHub GraphQL schema, https://docs.github.com/public/fpt/schema.docs.graphql, lines 26080-26082. Its sha256 is
3ed09565…, the bytes the README's earlier rows cite.MergePullRequestInput.commitBodyis "Commit body to use for the merge commit; if omitted, a default message will be used".The squash commit message setting:
github/rest-api-description@58b1e0c00b39descriptions/api.github.com/api.github.com.json:138199-138208.full-repository.squash_merge_commit_messageis one ofPR_BODY,COMMIT_MESSAGESandBLANK, where "COMMIT_MESSAGES- default to the branch's commit messages". GitHub Docs atgithub/docs@be38ec5d:Both repositories read
COMMIT_MESSAGESfromGET /repos/{owner}/{repo}at 2026-10-12T02:23:46Z.The merge-queue rationale: GitHub Docs "Managing a merge queue" (https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queue) at
github/docs@be38ec5d:data/reusables/pull_requests/merge-queue-overview.md:1,:3,:7: a queue keeps "the branch ... never broken by incompatible changes", like Require branches to be up to date before merging, by testing each pull request "applied to the latest version of the target branch and any pull requests already in the queue";managing-a-merge-queue.md:84;data/reusables/gated-features/merge-queue.md:2: queues are available in organization-owned repositories only.The queue is the native control for the Generate the canonical final-stack manifest (W4 PR 2) #1007/Move the claude-native-practice skill row to the commit that holds #1001, #1005 and #986 #1018 class. Both repositories are owned by one user account, so until the owner's organization step the landing script runs the merge check itself, as CC correction macOS arm64 SYN evidence for the adaptive-paper engine and mover trial mode #176 records. The rules of both
mainbranches were read fromGET /repos/{owner}/{repo}/rules/branches/mainat 2026-10-12T02:23:46Z:strict_required_status_checks_policy: trueforci-gate, so its CI already ran on the merge's tree anduet_land.shneeds no such step (itsci.ymlat0e987311has no generated-artifact check);false.The checks themselves: this repository's
.github/workflows/validate.yml:135-177at the base (shard 0). Since round 3 the script reads them from the merge's own copy of that file, and a test holds its reader to those steps, in their order, the foldedrun: >-step ofgap_wave_ledger.py(:166-174) included. Which file CI runs:github/docs@be38ec5ddata/reusables/actions/about-triggers.md:18, "Each workflow run will use the version of the workflow that is present in the associated commit SHA or Git ref of the event" (sha25676d0a30b…), andcontent/actions/reference/workflows-and-actions/events-that-trigger-workflows.md:780-784, apushruns at the "Tip commit pushed to the ref" (sha25669e251c1…);workflow-syntax.md:619-621and:849-851for a step'sifandrun(sha25650c73cf5…). A folded>-run is its lines joined by spaces: YAML 1.2.2 (https://yaml.org/spec/1.2.2/, fetched 2026-10-12, sha2562fe1bf40…), 6.5 "the line break is converted to a single space", 8.1.3 and 8.1.1.2.The squash body scan (the P1 fix and the CC's rulings):
scripts/validate.py:38-61(PRIVATE_CONTENT, the table for published text),:316-345(scan_file_for_private_content) and:737-780(--scan-file, the scan the pre-push hook runs: exit 0 clean, 1 findings, 2 unavailable),scripts/host_name_scan.py:164(the nativeprivate-emailrule whose character classessquash_body_scan.pyuses for addresses) and:144-150(the boundary rule for a name). Nothing of them is copied.PRIVATE_CONTENTdoes not match (measured 2026-10-12: no finding for either form, one for the same path with forward slashes):MicrosoftDocs/WSL@a1473a69d10cWSL/release-notes.md:24, "Switch the \wsl prefix to \wsl.localhost to avoid issues when there is a machine on the network named "wsl". \wsl$ will continue to work." (sha2567c889022…), andWSL/wsl-config.md:162, the path of a distribution's file as\\wsl.localhost\<distro>\etc\wsl.conf(2f846065…).github/docs@be38ec5dcontent/account-and-profile/reference/email-addresses-reference.md:47-48:[email protected](accounts created after July 18, 2017) and[email protected](older accounts that kept their address private) (sha256fbbf1c5f…). The vendor trailerCo-Authored-By: ... <[email protected]>is this repository's convention: 402 of the last 600 commit messages ofmainat 3a8a846 carry it.systemd/systemd@c7a8e871de34man/systemd.unit.xml(sha256520150b1…)::121-124a unit name prefix is ASCII letters, digits,:,-,_,.and\;:125-128the type suffix is one of eleven (.service,.socket,.device,.mount,.automount,.swap,.target,.path,.timer,.slice,.scope; the ruling named six, and round 2 keeps five);:130-135an instance name is inserted between the@and the type suffix. So an instance of a template such as[email protected]has the shape of an address and is a unit.openai/codexcommitdb22c91e61cc80defa5bbafc22bd8a8c7672e5e1(2026-05-05), message line 38: theCo-authored-by: Codextrailer with the local partcodexat the vendor's domain, the vendor's own repository carrying the form, which is why it is on the list. The vendor's current attribution code writesCo-authored-by: Codex <[email protected]>(openai/codex@092d3acd6beccodex-rs/ext/git-attribution/src/world_state.rs:11and:19, sha2565d202fa0…), which passes as a no-reply address. No other primary source holds the older form: the fiveopenai/*mirrors at their HEADs and the 36 Codex pages of developers.openai.com hold no such address (measured 2026-10-12). GitHub code search finds the exact trailer in 988 files (a count, not a source).cb459acc…)::961local-part = dot-atom / quoted-string / obs-local-part;:735-744a quoted-string is qtext or quoted pairs between two DQUOTEs;:746-757"quoted-string is identical to atom, semantically", the quote characters not part of it;:939-940"Comments and folding white space SHOULD NOT be used around the "@" in the addr-spec";:1939obs-local-part. CPython's parser,python/[email protected](cbc944f4bc59, the local mirror; sha2567beea37a…, the bytes of the installed 3.13.16 file):Lib/email/_header_value_parser.py:1682-1696get_addr_spec,:1486-1523get_local_part,:1525-1575get_obs_local_part,:1235-1275get_bare_quoted_string,:1315-1331get_quoted_string,:1644-1680get_domain,:634-654LocalPart.local_part,:544-547AddrSpec.domain. The scan reads each address with it (the CC's ruling allowed importing the stdlib parser), and the tests take it as the oracle.@is judged by the parser: RFC 5322 (the same file, sha256cb459acc…)::959-969addr-spec = local-part "@" domain,domain = dot-atom / domain-literal / obs-domainand the domain literal's grammar;:695dot-atom = [CFWS] dot-atom-text [CFWS], so comments and white space may stand on either side of the@;:939-940says they "SHOULD NOT be used" there, which leaves them valid. CPython's parser at the same pin (cbc944f4bc59, sha2567beea37a…)::83-97its specials and white space,:1219-1233get_atext(an atom's text is any character that is neither, letters of any script included),:1277-1300get_comment,:1302-1313get_cfws,:1605-1642get_domain_literal,:1644-1680get_domain(a domain needs no dot). Measured on 3.13.16, and asserted by the tests: it reads an address at an undotted domain, at a domain of CJK labels, with a comment or white space around the@, at a domain literal and with an address inside its quoted local part, each with no defect.git/[email protected](the local upstream mirror at67ad4214):Documentation/revisions.adoc:14-16, an object name is "the full SHA-1 object name (40-byte hexadecimal string), or a leading substring that is unique within the repository" (sha2563835ec56…);object-name.h:137FALLBACK_DEFAULT_ABBREV 7andobject-name.c:857-858, git's own abbreviation is never shorter (sha2566703e4d1…,9fcb9e54…);hash.h:201-202,:208, the longest name is SHA-256's 64 hex digits (sha256d7467a59…). This repository's locator form isrepo@pin:path:line(CLAUDE.md:7). A domain without a dot is a top-level domain, and none of the 1,437 in IANA's list (version 2026101200, the same bytes as above) is a run of 7 to 64 hex digits (the longest of hex digits alone has 4), so no address at a delegated domain has a locator's form.evidence/artifacts/omniroute-post-terminal-drain-20261005/scripts/build-drain.sh.txt:36, the name and address the scratch scripts commit with; a test reads that line.localis no top-level domain of IANA's list..target: IANA, https://data.iana.org/TLD/tlds-alpha-by-domain.txt, version 2026101200 (fetched 2026-10-12, sha25645d9f126…):TARGETis listed;SERVICE,TIMER,SOCKET,PATHandMOUNTare not.python/[email protected]Doc/library/socket.rst:988-991:socket.gethostname()returns "the hostname of the machine where the Python interpreter is currently executing" (sha256fa1ad5f4…; measured equal touname -non the CC's host).scripts/host_name_scan.py:65-68drops the hostname source ofvalidate.py --scan-filewhen it equalsWSL_DISTRO_NAME: "WSL can expose its public distro/project label as the Linux hostname. Exclude that hostname source only; coincident private sources remain." On the CC's host it does (measured 2026-10-12: a body naming the host passed both scans).python/[email protected]Doc/using/cmdline.rst:308-316:-I"also implies -E, -P and -s" and leaves "neither the script's directory nor the user's site-packages directory" insys.path. Measured 2026-10-12:python3 -I scripts/validate.py --scan-fileexits 2 (host_name_scanis not importable),python3 -E -s -Bexits 0, which is why the scripts run it with-E -s -Basmerge_validaterunsvalidate.py(sha256ef999234…).EXITtrap: the bash manual,[email protected]doc/bashref.texi:4777-4778, "If a sigspec is 0 or EXIT, action is executed when the shell exits" (sha256f3d37d57…, from git.savannah.gnu.org). The manual does not say that a terminating signal counts, so it was measured with bash 5.3.9: SIGTERM and SIGHUP each ran the trap, which removed the file, and the shell then died of the signal. A test repeats it on both scripts.mktempcreates it with mode 0600; the README's earlier row foruutils/[email protected]andStebalien/[email protected](imp/unix.rs:23) is the source.How the sources were read: from local upstream mirrors at the pins, except where noted.
cli/clifiles fetched fromraw.githubusercontent.com/cli/cli/v2.102.0/...at 2026-10-12T02:37Z have the mirror's sha256 (ca3849b4…,17eb5418…,94076f62…).cli/climirror is a blobless clone atec5b5120with no tags and nofc4b137c, so the same three files were read again through the GitHub contents API atfc4b137cdef0a6bd28fd461b7cf9c84a5812a8cd; their sha256 equal the digests above (follow-up 7).github/docs(be38ec5d),python/cpython(v3.13.16),systemd/systemd(c7a8e871de34) andopenai/codex(092d3acd6bec, and the commitdb22c91e61) were read from the local mirrors,MicrosoftDocs/WSLthrough the contents API ata1473a69d10c, and the bash manual fromgit.savannah.gnu.orgatbash-5.3.github/docscontent files atbe38ec5d, and the published pages may have changed since.Evidence-class table
validate.pyand failsscripts/final_stack.py --checkstopsnas_land.shwith 10. The output names the check, nothing is merged and the check's output is not printed. It merged at 86fa384.syntheticEndToEndTests.test_nas_stops_with_10_when_the_merge_passes_validate_py_but_fails_a_currency_check: fails at 86fa384, passes herenas_land.shruns are exactly the shard-0 Python--checksteps of the merge'svalidate.yml, in order; its reader gives the eight on this repository's workflow. A landing whose checks pass merges.synthetictest_nas_runs_the_currency_checks_of_validate_ymls_shard_0_in_the_workflows_order,test_nas_runs_each_currency_check_of_the_merges_own_workflow_and_then_lands,test_the_workflow_reader_takes_one_line_and_folded_runs_and_nothing_else(each fails at 37e242c, which held a list)synthetictest_the_provenance_section_carries_a_digest_only_for_the_repository_copies(fails at 86fa384)merge_validateup to 37e242c. On round 3's it reports a failure, because its scratch repository holds novalidate.yml; a copy whose scratch repository holds one, and which cutsshard0_checksout withmerge_validate, passeslocal_integrationtest_merge_validate_currency.sh: exit 0 on 37e242c'snas_land.sh, exit 1 on this one; the adapted copy on this one: exit 0, PASS (2026-10-12)SQUASH_BODY_FILEthat is missing, empty, a directory,-or unreadable stops both scripts with 2 before any call, printing no pathsynthetictest_a_squash_body_file_that_is_not_a_readable_non_empty_file_stops_both_scripts_with_2_before_any_call(10 subtests fail at 86fa384)ghorgitcall; no merge, nothing of the body printed, no snapshot leftsyntheticEndToEndTests.test_a_squash_body_with_a_home_path_...,..._with_a_name_of_the_names_file_...,..._with_an_address_that_is_not_a_no_reply_one_...,..._with_a_token_shape_...(64 subtests fail at d6be1b0: exit 0 and one merge call)validate.py, scanner or names file, a scanner that exits 2, prints nothing, another line or a warning count that is not a number, has a syntax error, or refuses, and every answer ofvalidate.py --scan-filebut its clean line, refuse the landing (fail closed)synthetictest_a_squash_body_is_not_landed_when_a_scanner_or_the_names_file_is_missing_or_fails(36 subtests fail at d6be1b0)noreplytrailer, a synthetic name inside a longer word, the placeholder account's home path) lands with exit 0 and one merge call; the merge reads the body's bytes, byte for byte, from a mode-0600 snapshot in aTMPDIRwhose name has a space, not from the caller's file, both scans having run on that snapshot first; an empty value adds no scan and no--body-filesynthetictest_a_squash_body_file_is_passed_to_the_merge_as_one_body_file_argument(replaces the d6be1b0 test of that name; 2 subtests fail at d6be1b0)synthetictest_the_merge_reads_the_scanned_bytes_even_when_the_file_changes_after_the_scan(2 subtests fail at d6be1b0)synthetictest_the_snapshot_exists_while_the_landing_runs_and_is_removed_wherever_it_stops,test_the_snapshot_is_removed_when_a_signal_ends_the_landing(4 and 4 subtests fail at d6be1b0; with the trap line deleted both fail)LANDING_SCANNERandLANDING_NAMES_FILEthe scan uses the clone'sscripts/validate.pyand the names file under the coordination tree, and fails closed when it is absentsynthetictest_the_scanner_and_the_names_default_to_the_clone_and_the_coordination_tree(4 failures and 2 errors at d6be1b0)validate.py --scan-filepasses the clean body and refuses a body naming the account that runs the testslocal_integrationtest_the_repository_scanner_runs_on_the_snapshot_with_the_hosts_own_sources(2 subtests fail at d6be1b0; skipped where Betterleaks 1.9.0 is not installed, as in CI)squash_body_scan.pyby itself (the names file's formats and that no line of it runs, the address, unit and vendor rules, the host name, a name as a whole token, its one output line)syntheticScriptTextTests.test_the_squash_body_is_scanned_before_the_lock_and_the_merge_is_given_only_the_snapshot(2 errors at d6be1b0),SquashBodyScanTests(7 tests; the class errors at d6be1b0, the scanner not existing)synthetictest_a_squash_body_that_names_this_host_lands_with_a_count_and_the_other_names_still_refuse(4 subtests fail at d6be1b0, 2 on the scan without the allowance);SquashBodyScanTests.test_a_name_equal_to_the_hosts_own_name_is_counted_and_never_refusedsynthetictest_a_squash_body_with_a_systemd_unit_instance_lands_and_a_look_alike_does_not(10 subtests fail at d6be1b0, 2 on the scan without the allowance);SquashBodyScanTests.test_systemd_unit_instances_are_not_addresses_and_their_look_alikes_arenoreplyform; another local part at the vendor's domain, the vendor's local part at another domain, a longer local part and a provider address (the control) are refusedsynthetictest_a_squash_body_with_a_vendor_co_author_trailer_lands_and_a_provider_address_does_not(8 subtests fail at d6be1b0, 4 on the scan without the allowance);SquashBodyScanTests.test_a_vendor_trailer_address_passes_only_as_the_exact_addresswarnings=2and passesvalidate.py --scan-file; a body naming the host and the account is refused by both; neither output holds either namelocal_integrationsquash_body_scan.pyandvalidate.py --scan-filerun by hand on two bodies built fromhostnameand the account, 2026-10-12main's last 600 commit messages at 3a8a846: 8 refused (0 names, 5 addresses, 3 home paths); 26 messages (66 occurrences) name the host (a warning); 2 carry a unit instance, 1 the vendor co-author address and 402 the vendornoreplytrailer, all passing. Before the three rulings: 37 refused (26 names, 8 addresses, 3 home paths). The 5 addresses: 3 at a mail provider, 2 at a reserved test domainmeasuredgit log -600, counts only (follow-up 5)mainat 86fa384 in about 8 s (6.3 s of itbuild_ecosystem.py)local_integrationmerge_validateruns it,python3 -E -s -B <script> ... --check, at 2026-10-12T02:18ZCOMMIT_MESSAGESsource_reviewgh apireads of the rules and the repositories at 2026-10-12T02:23:46Z;ci.ymlat0e987311ghorgitcall, no snapshot left, with the canned and with the realvalidate.py --scan-filesyntheticEndToEndTests.test_a_quoted_local_part_is_refused_by_both_scripts_as_its_unquoted_form_is(28 of its 32 subtests fail at e203d01 with exit 0 and a merge; the percent-encoded form's raw text was refused there)+or!(in its trailer, in prose, in a code span, quoted) or behind a backtick that does not close, andnoreplyorno-replybehind+or!, stop both scripts with exit 2synthetictest_a_vendor_or_no_reply_local_part_behind_a_prefix_is_refused_by_both_scripts(32 subtests fail at e203d01).targetand atargetinstance stop both scripts with exit 2synthetictest_an_address_before_a_unit_type_and_an_address_at_target_are_refused_by_both_scripts(44 subtests fail at e203d01); thetargetlook-alike intest_a_squash_body_with_a_systemd_unit_instance_lands_and_a_look_alike_does_not(2)noreplytrailer, GitHub's two no-reply forms, a no-reply local part, two real unit instances and markup that wraps an allowed address land (exit 0, one merge call, no snapshot left) in both scripts and both scan modessynthetictest_the_vendor_trailer_the_no_reply_forms_and_unit_instances_still_land_through_both_scripts(passes at e203d01 and here: a control)syntheticSquashBodyScanTests.test_each_address_is_judged_as_the_rfc_5322_oracle_reads_it_and_markup_counts_only_when_it_wraps_it(2,544 cases fail at e203d01),test_the_address_rule_passes_no_reply_addresses_and_refuses_every_other(12),test_systemd_unit_instances_are_not_addresses_and_their_look_alikes_are(13),test_a_vendor_trailer_address_passes_only_as_the_exact_address(10)+codexand!codexat the vendor's domain, a provider address before.serviceand an address at.targetlanded at e203d01 (exit 0, one merge call) and stop at37e242c0(exit 2, no merge, no snapshot left)local_integrationFAKE_VALIDATE_SCAN_PYTHON, five probes on each script, 2026-10-12local_integrationmeasuredghorgitcall, no snapshot left, with the canned and with the realvalidate.py --scan-filesynthetictest_an_address_in_a_quoted_local_part_or_glued_to_an_allowed_one_is_refused_by_both_scripts(52 subtests fail at 37e242c: each landed)@, at a domain literal, and a quoted local part over a line end stop both scripts with exit 2synthetictest_an_address_at_any_domain_or_with_comments_or_white_space_around_its_at_is_refused_by_both_scripts(28 subtests fail at 37e242c: each landed)@, six hex digits, an object name inside a longer domain, and another local part or a longer domain beside the scratch identity's stop both scripts with exit 2synthetictest_a_source_locator_and_the_scratch_identity_land_and_their_look_alikes_are_refused_by_both_scripts(20 subtests fail at 37e242c),SquashBodyScanTests.test_a_source_locator_and_the_scratch_identity_pass_only_in_their_whole_forms(an error at 37e242c, which has no such table; it reads the cited line of the scratch script)@with no local part, a mention and a decorator in code spans, a template unit, a quoted no-reply address and one in parentheses, and a body with CRLF line ends land in both scripts and both scan modessynthetictest_an_at_with_no_address_and_the_allowed_forms_of_round_3_still_land_through_both_scripts(passes at 37e242c too: a control)@is judged, also inside a quoted stringsyntheticSquashBodyScanTests.test_each_address_is_judged_as_the_rfc_5322_oracle_reads_it_and_markup_counts_only_when_it_wraps_it(2,100 subtests fail at 37e242c),test_every_at_is_judged_and_an_allowance_passes_only_a_whole_address_that_holds_no_other(12),test_the_address_rule_passes_no_reply_addresses_and_refuses_every_other(3)local_integrationtest_a_body_whose_only_hit_is_the_hosts_name_lands_through_the_real_second_scan_on_any_host(2 subtests fail at 37e242c; skipped where Betterleaks 1.9.0 is not installed, as in CI),tests.test_host_name_scantest_a_public_hostname_is_excluded_on_any_host_only_from_the_hostname_source(fails at 37e242c)synthetictest_a_names_file_that_a_shell_would_read_otherwise_stops_both_scripts_before_any_call(12 subtests fail at 37e242c: each landed),SquashBodyScanTests.test_the_names_file_is_parsed_and_never_executed(9)nas:430: a failing check that the merge'svalidate.ymladds stopsnas_land.shwith 10; a step whose arguments the merge changes runs as the merge writes it; avalidate.ymlin which no check can be read, or one of whose steps is not plain words (eight kinds), stops it with 10 before any check runs, the step's text not printedsynthetictest_nas_validates_a_merge_with_the_checks_that_its_own_workflow_adds_or_changes(fails at 37e242c: it landed),test_nas_stops_with_10_when_it_cannot_read_or_run_the_merges_currency_checks_as_written(9 subtests fail at 37e242c)synthetic,measuredtest_the_snapshot_is_removed_when_a_signal_ends_the_landing(now with SIGINT; passes at 37e242c too); both scripts signalled by hand through the harness, 2026-10-12measuredmeasuredlocal_integrationLocal commands run
Round 2 (commit
37e242c0, 2026-10-12):Round 3 (commit
cb0429d7on37e242c0, 2026-10-12):Decision record
No new record. Round 3 adds one sentence to
docs/decisions/2026-10-09-host-name-scan.md, on the hostname opt-in that the landing scripts set for their second scan. The change carries CC correction #176 (the CC's corrections log), the CC'sSQUASH_BODY_FILEpatch and the CC's ruling of 2026-10-12 (the ledger check; README digest cells withheld, CC #161). The P1 fix carries Astra's finding at d6be1b0 and the CC's three rulings of 2026-10-12 on its scan (the host's own name, systemd unit instances, vendor co-author trailers).tools/landing/README.md("The currency checks", "The squash body", "Provenance and digests") records the evidence and the port's differences from the live copies. A merge queue on an organization-owned repository would replace the merge check. Round 2 carries the CC's adjudication at e203d01 (P1-a, P1-b, P1-c, B2, B3, the tests, the follow-ups, rule 4's oracle). Round 3 carries the two reads at 37e242c, the Codex connector's three threads and the CC's rulings of 2026-10-12 on the two allowances and on the host-name fix (Round 3, above).Host evidence
Not applicable: no file under
evidence/hosts/changes.Checklist
version comment (no floating tags). (none changed)
permissions: {}and grant each jobonly what it needs (
contents: read, or an explicitly justified addition). (none changed)added without a documented owner.
moved or overwritten).
Follow-ups
--checksteps run on the merge (README, "Known gaps"). The shard's validators (validate_catalogs.py,validate_convergence.pyand others) and its checks that are not one Python command (the example workflows'sha256sum --check, the contract suites, zizmor and actionlint) do not. Since round 3 the steps are read from the merge'svalidate.ymlin the one form this repository writes them; a--checkstep written another way (a literal block, a pipe, another spelling of the condition, a step with no condition) is not read, and the steps and scripts the landing runs are the merge's own (the sandboxing follow-up).cc-toolscopies from the merged repository copies, the three host paths filled in (README, "Provenance and digests"), and installssquash_body_scan.pybeside them, as with tools(landing): move the CC's landing scripts into the repository, with offline tests #975. The scan findsscripts/validate.pyin the cloneLANDING_NAS_REPOnames (the CC's checkout by default, for both scripts) and the names list at its default path under the coordination tree, so no further host path is needed. Until then the CC scans each squash body by hand. A copy without the scanner stops every landing that setsSQUASH_BODY_FILEwith exit 2 (fail closed).\u, HTML entities or doubly encoded text; it finds a WSL UNC home path and no other UNC share; the names file is parsed in Python and not sourced (a line of it never runs), and only its lastLANDING_PROHIBITED_NAMESassignment counts.validate.py --scan-fileruns only where Betterleaks athost_name_scan.py's pin is installed and, on WSL,powershell.exeanswers: elsewhere, and in CI, a landing withSQUASH_BODY_FILEexits 2 and the test of the real scan skips. Since round 3 its hostname source is dropped on any host, and a names file in another form than the documented ones stops the landing.NATIVE_AGENT_HOST_NAMES_JSONin the CC's shell makesvalidate.pyreport synthetic sources, which the scripts refuse.squash_body_scan.py(VENDOR_TRAILER_ADDRESSES) when Refuse email addresses in the publication scan #1002 lands.main's last 600 commit messages (5 and 4 in the whole history at the base) already sit inmain's commit history. It is immutable, as for CC correction Linux/WSL2 bootstrap keeps a newer native Claude Code: the pin is a floor (stacked on #159) #177, and this change rewrites none of it. Check whether any of them is identity-bearing.cli/climirror is a blobless clone atec5b5120that did not holdfc4b137cwhen the files were read (a later reader's lazy fetch, at 07:57:07Z, added that commit's objects); the contents-API read above, with its matching sha256, stands as the record. A sibling mirror,cli/cli-2.102.0, is checked out at the pin (since 2026-10-11T13:59:41Z) and holds the same bytes. Make the mirror the README rows name carry the pin (CC rule 9). README:616 (tools(landing): move the CC's landing scripts into the repository, with offline tests #975's row, already onmain) says "the local upstream mirror atfc4b137c" too; that sibling holds its three digests, so the phrase may be accurate there, and the record should name the mirror.getty.target.wants/before an instance, fromsystemd.unit.xml) are refused, since/is atext; decide whether A2 should cover them (a conservative refusal, not a bypass).mktempsources, the rules API responses, the trading CI file, the page captures, the historical measurement); keep them as receipts.manifests/evidence.jsonholds 20 inherited occurrences of the host's name on 18 lines outside this PR's edits (hygiene, by the CC's 10-11 ruling)./var/tmp/nas-land-*worktree template).validate.py) are done in round 3. Open: P3-3, "before any of the landing's ownghorgitcalls" (validate.py --scan-filerunsgit config); P3-4, a crashingvalidate.py --scan-fileis reported as a refusal; P3-5, loadvalidate.pyat a pinned revision; P3-6, the README's "every shard-0 step that runs a Python script with--check" (the reader takes one-line and folded runs that end in--check).@, a domain literal, a quoted local part over a line end, the scan's cost). What round 3 declares instead (README, "Known gaps"): the rule does not join lines, and it refuses some text that names no one, which a body writes another way: a word, white space and an@, a tag or a branch after an@, a placeholder such as<repo>@pin, an address atlocalhost, a URL whose path holds an@, and a code span that holds more than the@-name. For the shared module of follow-up 6.test_merge_validate_currency.shneeds avalidate.ymlin its scratch repository andshard0_checkscut out withmerge_validate(Round 3, above); the live copies needsquash_body_scan.pybeside them, as before, and a checkout whosescripts/host_name_scan.pyhas the opt-in (until then the second scan refuses the host's name where the hostname is notWSL_DISTRO_NAME, as it did).@is refused, since nothing tells such a revision from a host name. If squash bodies need<repo>@<tag>, that is a ruling for the shared module of follow-up 6 (31 of the last 600 messages hold one).🤖 Generated with Claude Code