Skip to content

Refuse email addresses in the publication scan - #1002

Draft
seathatflowsinourveins wants to merge 10 commits into
mainfrom
claude/api-actions-email-rule-20261011
Draft

seathatflowsinourveins wants to merge 10 commits into
mainfrom
claude/api-actions-email-rule-20261011

Conversation

@seathatflowsinourveins

@seathatflowsinourveins seathatflowsinourveins commented Oct 11, 2026 •

Copy link
Copy Markdown
Collaborator

Scope

  • What this PR changes: scripts/validate.py PRIVATE_CONTENT gains an email address rule. Claude Code puts the signed-in account's address in every session's context, and nothing refused one before it reached a public evidence file. scripts/public_email_matches.json lists the 79 reviewed matches, each public upstream or vendor text, in four groups with a reason; an entry keeps its local part's case and lowers its domain. A text passes the rule only when every match in it is listed. The waiver applies to this rule alone, in validate.py's publication scan and in host_receipts.py's receipt scan. scripts/native_token_ci.py now redacts addresses in its sanitized fixture evidence.
  • Base commit: 2a330b0a0 (main after Rule text: work compounds through reviewed, cited repository records #1020). Rebased from 8bffa2c41, from f1f6c0c20 and, with the terminal commit, from 3a8a8461e, each time for a manifest-only conflict (without manifests/evidence.json the four earlier commits' patch-ids are identical; 4c916e14 is now 6db753db). The deleted scripts/public_email_paths.json's manifest row is dropped in the commit that deletes the file.
  • Lane: lane:foundation
  • Owned paths touched: scripts/validate.py, scripts/public_email_matches.json, scripts/host_receipts.py, scripts/native_token_ci.py, tests/test_validate.py, tests/test_host_receipts.py, tests/test_native_token_ci.py, docs/decisions/2026-10-11-email-address-publication-rule.md, manifests/evidence.json (re-registration); scripts/verdict_review_gate.py (one TRUST_PATHS entry, addendum 04)

Review rounds:

  • Codex's GitHub review of 308033f6 (one P1, three P2s) is answered in e0862d8d:
    • P1: a path waiver passed any later address added to a listed file. This was reproduced at 308033f6: an operator-shaped address appended to a listed file gave no email finding. The list now holds the reviewed matches, so the same edit gives one finding on that file, and the address is never printed.
    • P2: the rule no longer exempts a git local part at any domain. The tree's only Git-host form, the git user at github.com (7 matches in 6 files), is a reviewed entry.
    • P2: the last label may be an IDNA A-label (xn--, RFC 5890).
    • P2: native_token_ci.py redacts addresses as <EMAIL>. Its copies of validate.py's rules sit in REDACTIONS, and a test holds each copy equal to its original.
  • host_receipts.py now judges the raw receipt and each decoded JSON string on its own, so an address a JSON escape hides is not waived by the raw bytes. A test covers this. (It decoded one level until addendum 04 below, which judges every view.)
  • The command center's Claude read and the GPT read at e0862d8d (three P1, three P2 and two false claims) are answered in one commit, 51f45b5d, as the command center ruled:
    • B1: a ( after a match exempts nothing. The 7 tree matches it hid, decorator calls after an escaped newline, are reviewed entries.
    • B2: the local part and its left boundary take every RFC 5322 atext character, so a match is the whole dot-atom and private!<listed> is a different, unlisted match. The registry is re-reviewed. A local part needs a letter or a digit; the command center kept that guard (measured at main 900835c6 with this rule minus its guard over every tracked blob: 125 symbol-only local parts in 76 files, each a backtick, quote or slash before an @-name, none an address; the first figure, 139, came from an ad-hoc search and does not reproduce). Residual: local parts made only of RFC 5322 atext symbols are not detected, though they are valid; no observed instance is identity-bearing.
    • B3: the dead-entry check leaves the registry out.
    • B4 (correction 2026-09-24 community sweep: effort-guard SessionStart notice, working plugin-install commands, dated dispositions #161): native_token_ci.py publishes digests of sanitized text only; raw_sha256 and the raw stdout, stderr and MCP digests are gone.
    • C1: RFC 2606's three names exactly, with their subdomains. example.* under other TLDs, and chained labels, are no longer exempt.
    • C2: target is a TLD, so it is no longer an exempt unit type.
    • C3: the counts are measured at this head.
    • The rebase onto main 3a8a8461 brought Verify the code citations in a PR's SOTA sources (W1b phase A, report-only) #1003's URL-userinfo fixture, reviewed in the same commit (78 entries).
  • The GPT delta read at 51f45b5d (two P1s, two P2s, seven P3s) is answered in one commit, 4c916e14, as the command center ruled (fix round 2):
    • P1-1, split: the letter-or-digit guard stays. The code comment and the record said a symbol-only local part "names no mailbox", which is false: CPython 3.13.16's parser accepts one (Lib/email/_header_value_parser.py:1219, :1360, :1486, :1682 at cbc944f4). Both copies' comments, the record and this description now state the residual above.
    • P1-2: an address whose @ a JSON escape hid (\u0040) passed Run.clean(), and the published receipt or artifact decoded back to it. Run.publish() cleans each decoded key and string value of JSON or JSON Lines output, nested JSON four levels deep (the terminal commit refuses deeper nesting and splits lines at line feeds only), for every published argument, stream, artifact and MCP digest; each digest is of the published bytes. (This said host_receipts.py judges decoded values the same way; it decoded one level until addendum 04, the micro's C1.) Codex's thread 4242033284 is answered and resolved.
    • P2-3: the waiver lowered the whole match, so a local part differing in case passed as the reviewed one. email_key keeps the local part (RFC 5321 2.4, rfc5321.txt:869) and lowers the domain, in the loader, the dead-entry check and the waiver. The registry lists the tree's spellings: 7 entries respelled and 1 added, where one public agreement carries a contact in two spellings (79 entries). Codex's thread 4242033279 is answered and resolved.
    • P2-4: the counts at 51f45b5d were 532 and 454, not 533 and 455; they are measured below at 4c916e14.
    • P3s folded: the strict consumers' wording in the record, and the receipt's limitation text, which now says which digests are of published text.
    • The new tests fail on 51f45b5d (3 failures, 6 errors) and pass at 4c916e14.
  • The command center's micro at 4c916e14 (CHANGES_REQUESTED; fix round 2 closed 21 of the 36 encoded leaks it probed) is answered in one terminal commit, adc2adb2 (written on 4c916e14 as a94c07d5, rebased with the branch onto main 2a330b0a; the reviewed delta is 6db753db..adc2adb2), as the command center ruled:
    • B1: publish() split JSON Lines with str.splitlines(), which also breaks at U+2028, U+2029 and U+0085 (CPython cbc944f4 Objects/unicodetype_db.h:6418-6430); RFC 8259 7 allows them raw in a string, so such a line was never decoded and its escaped address was published. A line now ends only at a line feed.
    • B2: JSON text nested in string values deeper than four levels was passed through. publish() now refuses it with the fixed PUBLISH_REFUSED message and publishes nothing (in the framings publish() parses; behind a lone CR or RS it went out until addendum 04, the micro's D5); a command, artifact or MCP session that meets one fails. Real receipts nest at most two levels.
    • B3 to B5 and B7 to B9: the registry's spelling, the table (8/39/27/5), the respelling count, the depth limit and line rule in the receipt's limitation text, the 139 figure (now 125 in 76 files, method named; the command center's correction Secret-storage practice: per-host 0600 store, agent read guard hook + deny rules, managed-profile install, names-only checker #182), and the escape mechanism's sources (RFC 8259 7, rfc8259.txt:433; CPython Lib/json/decoder.py:60, :118).
    • B6: the reply on thread 4242033284 now shows the escape as written (\u0040); it had been decoded when typed.
    • Threads: 4242033265 (strict consumers) is answered with its by-design disposition, and the six outdated threads with the commits that fixed them; all are resolved.
    • The new tests fail on 4c916e14 (16 failures) and pass at adc2adb2.
  • The GPT read at adc2adb2 (fix3): ACK. The command center's addenda 01 and 02 (its micro at adc2adb2 and the GPT read at 4c916e14) are answered in one commit, 66036a74:
    • Duplicate names: json.loads kept only the last member, so an earlier member's escaped address went out uninspected. publish() parses through an object_pairs_hook that refuses such an object (RFC 8259 4, rfc8259.txt:322).
    • N1: splitting JSON Lines only at line feeds left JSON beside a lone CR, or after RS, FF, VT, FS, GS, U+0085, U+2028 or U+2029, undecoded, while universal newlines, splitlines() and jq read the address back. publish() now verifies its own output (recoverable()): each reader's line splitting, a stream decoder, every member, nested JSON to the same depth, numbers as text (which also covers the micro's N2, a number past CPython's 4,300-digit limit). A recovery by one of these readers is PUBLISH_REFUSED, with no output (addendum 04 adds the readers this lacked and refuses what they cannot finish).
    • The new tests fail on adc2adb2 (35 failures) and pass at 66036a74; byte-for-byte controls pass on both.
  • The GPT read at 66036a74 (fix4): ACK, three P3s. The command center's addendum 03 (a shadow review the co-op reproduced at 66036a74) is answered in one commit, 6aaa204a:
    • CR_MULTILINE and JSONSEQ_RECOVERY: a pretty-printed object after a lone CR, or behind RS framing (RFC 7464 2), was cut by every split view, so its escaped address went out while readline-then-json.load and jq --seq read it back. The verifier now also decodes every RFC 8259 7 string escape across the whole output, framing aside, up to PUBLISH_DEPTH times over, and runs the sanitizer's rules on each projection.
    • Duplicate names in more framings ("every framing" was false, the micro's F1; addendum 04 below): the verifier's decoder (RS framing, numbers as text) refuses them too, so an RS-framed duplicate object and duplicates after a long number are refused.
    • The record's stale scope sentence (:316-318) is corrected.
    • From fix4: the MCP session closes the parent's pipe ends once its readers finish (ResourceWarnings in the module's tests: 12 before, printed on 24 lines; 0 after); the refusal and recovery ordering is unchanged.
    • A test of P1-2 had put the escaped address in a command's own argv, which is published too; the child now reads it from a file.
    • The new tests fail on 66036a74 (13 failures: the two framings and a doubly escaped address through publish(); the two framings through an artifact, a command and an MCP answer; three duplicate shapes; the receipt's own check) and pass at 6aaa204a. Over the committed native-token receipts, the published streams pass unchanged (this said 765, a selector not recorded; addendum 04 states its census).
  • The GPT read at 6aaa204a (fix5, CHANGES_REQUESTED: two P1s, three P2s) and the command center's Claude micro at 6aaa204a (CHANGES_REQUESTED: D5, F1, C1) are answered in one commit, 167eb00a, under the command center's addendum 04:
    • P1-1 and D5: an address escaped five or more times, or JSON nested four or more times, behind a lone CR or RS framing was published (also an ordinary document holding CR-framed levels, and an MCP answer one level up). The escape projection now refuses when a further pass would still decode something, and the views read RS records whole and resume at each line, a lone CR included, so the depth rule applies there too. An address escaped past the bound is refused in every framing; clean text nested past it is refused in the framings the views read. (This said "whatever it holds" until 171b0811: behind a prefix on the same line, a form feed, a vertical tab, U+0085 or U+2028, clean text nested deeper is not read as JSON, the micro's FC1.)
    • P1-2 (thread 4245873460): a receipt's output_excerpt holding JSON with an escaped address passed the receipt scan, which decoded once. One verifier, publication_views() in native_token_ci.py, now serves Run.publish and the receipt scan, and a receipt it cannot finish is refused.
    • P2-3 and F1: a duplicate name is refused in a pretty object after a lone CR, after a malformed RS record (pretty, or on the same line), after a byte order mark, after a progress line, nested under a CR-framed object, and beside a long number. The views skip a byte order mark before a text (RFC 8259 8.1 allows ignoring one at the beginning of a text; jq skips a leading one only, so the views read more than jq does) and resume at the next line where no JSON text starts, as readline-then-json.load does.
    • P2-4 (thread 4245873473): a rewrite that would merge two names is refused.
    • P2-5 (thread 4245873477): a rewrite that would change a number as written is refused; with nothing to clean, the document keeps every byte.
    • Codex's thread 4246182992: the noreply exemption keeps the local part's case ((?-i:noreply), RFC 5321 2.4).
    • The micro's P3s: JSON too deep for Python's decoder is refused, not raised; the surrogate-pair locator is rfc8259.txt:455-459; the record's addendum 02 and 03 sentences, the 765 figure, the itemized fail-before and the warning count are corrected.
    • The GPT read's P3s: the command tests read their payloads from files, so the refusal is the output's; the pipe close cites CPython's Popen.__exit__ (Lib/subprocess.py:1106-1113 at cbc944f4) and a test asserts both ends are closed; the census selectors are stated in the record.
    • The verifier is a function in native_token_ci.py, not a module of its own: the push gate's read analysis counts a call into a non-stdlib module as running its argument, so a module added an advisory location. native_token_ci.py joins the verdict-review gate's TRUST_PATHS because host_receipts.py imports it.
    • The new tests fail on 6aaa204a (46 failures, 4 errors) and pass at 167eb00a; 14 of 14 weakened copies fail them (named in the record).
  • The GPT read at 167eb00a (fix6): ACK, six P3s (in Follow-ups). The command center's Claude micro at 167eb00a (CHANGES_REQUESTED: one new P1, three Codex threads, four false or loose claims) is answered in one commit, 171b0811:
    • N1 (thread 4247416401): Run.observe() recorded the names a tool wrote under its state directory through clean() alone, so a file name that is JSON holding an escaped address reached receipt.json and a reader decoded it back. flush() now verifies every string of the receipt, names and values, as publish() verifies its output; one that fails is replaced by the fixed refusal text and the run fails. This covers every field recorded through clean() alone (error messages, doctor lines, environment values, working directories). Over the 6 committed receipts Run wrote (16,224 strings), none is refused.
    • Thread 4247416418: an address right after a JSON escape took the escape's last character, and the document went out as invalid JSON. A JSON document clean() changed is now read as written, its decoded values are cleaned, and clean()'s text is kept only if it reads as the same document, at each level of JSON in strings.
    • Thread 4247416409: a rewrite holding a lone surrogate raised UnicodeEncodeError in a command or an artifact; it is refused.
    • FC2: a JSON text left unclosed was read to the end again from each later line that opens another (300 such lines in 1.1 MB: 18.3 s). That re-reading is counted and refused past 16 times the text's length (4.3 s for that input; ordinary truncated output stays inside the bound).
    • FC1, FC3, FC4 and the P3s: the "whatever it holds" claim, the byte order mark's attribution and the addendum-04 label are corrected in the code, the tests and the record; the duplicate residual is disclosed; the too-deep test gains the lone-CR case; the 14 earlier weakened copies are named in the record.
    • The new tests fail on 167eb00a (6 failures, 23 errors) and pass at 171b0811; 13 of 13 weakened copies fail them. Census A and B are unchanged; the push gate's advisory counts are unchanged.
    • Codex's three threads are answered and resolved.
  • The GPT read and the command center's Claude read at 171b0811 (both CHANGES_REQUESTED, on one ground: the claim that the work is bounded by a multiple of the length, P2, availability) are answered in one commit, 6ba4206a:
    • Every failed decode builds a JSONDecodeError that counts line breaks from the start of what it decodes (python/cpython@cbc944f4 Lib/json/decoder.py:31-32, also from the C scanner, Modules/_json.c:299-312), and the read across lines decoded the whole piece from each line, so each failure cost its position: the decoder was handed 1,250 to 20,000 times the length of the PR's own control. The read across lines now decodes growing slices that start where the text does, and every slice's length counts against RESCANS: 1.92 times the length at every size, 0.38 s at 960,002 characters (9.6 s before).
    • P3s in this delta's code: refused names are numbered instead of merged, and the report's own names are verified; a document holding NaN that clean() changes is published cleaned again; the unread framings are worded as measured (U+2029 included); the lone-CR too-deep case no longer depends on the interpreter; two tests close the CC's test gaps; the surrogate refusal cites RFC 3629 3.
    • The new tests fail on 171b0811 (4 failures) and pass at 6ba4206a; 8 of 8 weakened copies fail them. Census A and B are unchanged at both heads.

Follow-ups (not in this change):

  • From both reads at 171b0811:
    • behind a lone CR, an RS or a prefix on the same line, a document with an address right after a JSON escape is still published as invalid JSON with the address redacted (no address is published): apply the read-as-written rule to those framings, or refuse a framing that cleaning breaks;
    • pinned upstream citations for the receipt decoding and the escape-preserving rewrite (CPython Lib/json/decoder.py:351-364, the encoder);
    • the merged-tree verification gap: tools/sota-convergence/landscape-sweep/convert.py on main now calls the native publication scanner, which cannot collect host names in the GPT read's sandbox; verify those modules in a worktree with the host-name source at the landing rebase;
    • the reader residuals and the registry's rule-input classification, as below;
    • a lead from the CC's read, not reproduced: when flush() refuses a string, it rebuilds that entry's nested containers, so a reference a fixture holds goes stale in a run that already fails.
  • From the GPT read at 167eb00a (fix6, ACK):
    • a reader that splits at str.splitlines() breaks and rejoins the rest still reads a pretty duplicate object after U+2028 (no private content is recovered); support that composed reader or keep the boundary explicit, as the record now states it;
    • classify scripts/public_email_matches.json (PUBLIC_EMAIL_REGISTRY) as a rule input of the verdict-review gate and add it to the named-input derivation test, with a registry change beside a verdict change;
    • retain the thirteen cited public captures (RFC 8259, RFC 7464, RFC 5890, the IANA TLD list, RFC 5322, RFC 2606, RFC 4343, systemd.unit, the two GitHub pages, the Claude memory page, RFC 5321, Python re);
    • cite the pinned CPython operations in the merged-name, number and RecursionError corrections (python/cpython@cbc944f4 Lib/json/decoder.py:216, :307-329, Lib/json/encoder.py:226-241, Modules/_json.c:1033, :1041);
    • the locator, strict-consumer and hostname items, as before;
    • research queue: the shared maintained email detector (its layer binding is not in the catalogs yet).
  • From the micro at 167eb00a:
    • clean text nested past the bound, and a pretty duplicate object, are not read as JSON behind a prefix on the same line, a form feed, a vertical tab, U+0085 or U+2028 (an escaped address there is still refused);
    • a run of 32 or more backslashes, or 16 before an escape letter, is refused whatever it holds, by design;
    • host_receipts.py validate now takes about 3.5 s over the 183 host receipts the micro measured (2.5 s before the shared views).
  • The narrower exemption, in place of the letter-or-digit guard: strip the leading delimiters seen on main (`, ', /, *) and keep the rest of atext. It belongs with the command center's research-queue row for one maintained, cited email detector shared with Local pages: a command-center page for lanes, PR waves, tokens, skills, manifests and owner items #1012, which is meant to replace this hand-written rule (rule 4).
  • Forms the rule does not detect: quoted local parts; a comment or spaces around the @; non-ASCII local parts, U-label domains, and an address glued to a non-ASCII word character; a fullwidth at sign or a zero-width space; percent-encoding (%40 in a captured login or OAuth URL first), HTML entities, base64, JWT payloads, quoted-printable and line wrapping; an address followed by _, - or a digit; a domain ending .com.service.
  • The same 2026-09-24 community sweep: effort-guard SessionStart notice, working plugin-install commands, dated dispositions #161 class: in native_token_ci.py, the RTK exactness digests (rtk_exactness_fixture) and the Serena parity digests (serena_fixture), which the receipt's limitation names (the locators :1356, :1384, :1515 given here before no longer point at them); the off-host app-state and restore runs; usage_record.py's raw_output_sha256; bundle.py:133, :158. Committed evidence holds 16 JSON files with stdout_raw_sha256 and 70 with raw_sha256.
  • Past native-token artifacts: 161 native-token-e2e-results artifacts are retained on GitHub. They come from hosted runners with the runner's home and a fixture configuration, and no owner address appears in them. They expire by 2026-10-25 (14-day retention), so none is deleted.
  • From the GPT read at e0862d8d: non-receipt JSON decoding stays a stated boundary; the PR-body gate carries the email rule at this PR's landing rebase after Scan the pull request description for home paths and credentials #991; adjacent consumers differ on the waiver by design; some unpinned prose locators moved; machine-name references in the manifest's existing content.
  • RFC 5322, RFC 2606 and the IANA TLD list are not mirrored locally (both reads fetched them; the sha256s match the record).
  • Forms readable only by a person (\x40, a fullwidth at sign, %40) go to the shared email-detector research row (rule 4) and the unified-detector follow-up. (For an address, the escape projection reads all four of two values on one line, a BOM, a trailing comma and a log prefix; the JSON reading covers the first three since addendum 04, so a duplicate name behind a log prefix on the same line is not refused.)
  • From the GPT read at 66036a74 (fix4): retain the twelve named source captures (RFC 8259 and RFC 7464 among them) and the timing inputs (the census selectors are now stated in the record); keep the refusal and recovery ordering; carry the locator, strict-consumer and hostname follow-ups below.
  • From the GPT read and the micro at 6aaa204a:
    • retained captures for the 13 cited public sources the read names;
    • readers outside JSON (an XML parser decodes &#64;, a Markdown renderer decodes entities, a followed link decodes %40) stay with the shared email-detector row;
    • Run.publish rewrites only JSON it reads whole or by line feed; a CR- or RS-framed document that needs cleaning is refused rather than rewritten (none of the committed streams is);
    • the locator, strict-consumer and hostname items below, as before.
  • From the GPT delta read at 51f45b5d:
    • pinned captures for the ten fetched pages the record cites, and their own upstream citations for B3's and B4's corrections;
    • strict consumers (--scan-file, host_requests.py, hardware_profile.py, component_matrix.py, the handbook builder, the OpenHands guards) do not read the reviewed list, by design: a capture carrying a public contact needs redaction there;
    • the remaining fixture digests before sanitization, the RTK exactness and Serena parity hashes (native_token_ci.py, now named in the receipt's limitation), and historical evidence;
    • 506 colon locators at or below moved lines in the changed files (the reader's inventory);
    • the PR-body gate's email rule, carried at this PR's landing rebase after Scan the pull request description for home paths and credentials #991;
    • 18 existing machine-name lines in the manifest, none in the patch.

SOTA sources

Read 2026-10-11 at 02:08Z unless noted. The decision record lists each page's byte count or sha256.

Evidence-class table

Claim Evidence class Command / receipt
A path waiver passed a later address; reviewed matches do not local_integration an operator-shaped address appended to a listed file and re-registered, then validate.py: 0 email findings at 308033f6, 1 on that file at this head (address not printed)
The new tests fail before the fix local_integration the new tests/test_validate.py and tests/test_native_token_ci.py on 308033f6: 7 failures, 6 errors
Every weakened copy fails local_integration 9 of 9 (any listed match waiving the file, case-sensitive lookup, loader checks, git@ exemption, no or unbounded A-label, raw text deciding the decoded receipt scan, the sanitizer's email copy drifting or skipped)
The list and the tree agree exactly local_integration the publication scan passes; every one of the 79 entries occurs in a tracked file other than the registry (test); at adc2adb2, 533 matches in 106 files, 454 in 105 outside the registry (at 51f45b5d: 532 and 454)
Each defect of the two reads at e0862d8d is fixed local_integration five regressions fail on e0862d8d's code (rc 1) and pass at 51f45b5d (rc 0): the annotated address and the chained example and .target names in the rule's cases; the 15 glued atext characters in the rule, the waiver and validate(); the registry-only orphan; the whole-token redaction; no published digest confirming a removed address
No operator address is listed source_review each original file reviewed from its matched domains plus masked context; the 63 values compared locally against the known owner addresses: none equal
The tests pass local_integration 13 modules that use PRIVATE_CONTENT or the manifest: 1225 tests OK (4 skips) before the rebase; 337 OK after it
Each defect of the GPT delta read at 51f45b5d is fixed local_integration the new tests fail on 51f45b5d's code (3 failures, 6 errors) and pass at 4c916e14: a JSON-escaped address, nested too, in a command's output, an artifact and an MCP answer; a local part's case variant in the waiver, validate(), the dead-entry check and the loader
Each defect of the micro at 4c916e14 is fixed local_integration the new tests fail on 4c916e14's code (16 failures) and pass at adc2adb2: a JSON line holding U+2028, U+2029 or U+0085, alone and among other lines; five to seven levels of nesting in values and keys, through publish(), an artifact and a command
Each defect of the reads at 6aaa204a is fixed local_integration the new tests fail on 6aaa204a's code (46 failures, 4 errors) and pass at 167eb00a; 14 of 14 weakened copies fail them; census A (26 native_cli_e2e files, 1,518 strings) unchanged, B (198 files, 4,867 strings) none refused, at both heads
Each defect of the micro at 167eb00a is fixed local_integration the new tests fail on 167eb00a's code (6 failures, 23 errors) and pass at 171b0811; 13 of 13 weakened copies fail them; census A and B unchanged at both heads; every string of the 6 committed receipts Run wrote passes the flush check
Both reads at 171b0811 are answered local_integration the new tests fail on 171b0811's code (4 failures) and pass at 6ba4206a; 8 of 8 weakened copies fail them; the decoder is handed 1.92 times the length of the control dump at 60,002 to 960,002 characters (1,251 to 20,001 times at 171b0811)
The repository validates local_integration python3 scripts/validate.py at adc2adb2: passed, 11744 hashed files

Local commands run

$ python3 scripts/validate.py
{"components": 70, "hashed_files": 11472, "profiles": 4, "receipts": 239, "status": "passed"}  exit 0
$ python3 -m unittest tests.test_validate tests.test_native_token_ci tests.test_host_receipts <and 10 more modules that use PRIVATE_CONTENT or the manifest>
Ran 1225 tests ... OK (skipped=4)
$ python3 -m unittest tests.test_validate tests.test_native_token_ci tests.test_host_receipts tests.test_evidence_manifest   # after the rebase
Ran 337 tests ... OK
$ gitleaks git --log-opts="$(git merge-base origin/main HEAD)..HEAD" .
no leaks found  exit 0
$ git range-diff 8bffa2c41..9d5d3411d f1f6c0c20..e0862d8d9
only manifests/evidence.json differs between the two

At 6ba4206a (on main 2a330b0a; it merges cleanly with main d8f7e2051):

$ python3 scripts/validate.py
exit 0 (11744 hashed files); evidence_manifest.py --check: exit 0
$ python3 -m unittest <every module that uses host_receipts, native_token_ci, PRIVATE_CONTENT or TRUST_PATHS> tests.test_evidence_manifest tests.test_runtime_worker_openhands_push_gate tests.test_gitleaks_config
Ran 3442 tests ... OK (skipped=29)
$ python3 -m unittest tests.test_native_token_ci tests.test_host_receipts tests.test_validate   # the new test files on 171b0811's code
FAILED (failures=4)
$ gitleaks git --log-opts="171b0811..HEAD" .
no leaks found

At 171b0811 (on main 2a330b0a; it merges cleanly with main d8f7e2051):

$ python3 scripts/validate.py
exit 0 (11744 hashed files); evidence_manifest.py --check: exit 0
$ python3 -m unittest <every module that uses host_receipts, native_token_ci, PRIVATE_CONTENT or TRUST_PATHS> tests.test_evidence_manifest tests.test_runtime_worker_openhands_push_gate tests.test_gitleaks_config
Ran 3438 tests ... OK (skipped=29)
$ python3 -m unittest tests.test_native_token_ci tests.test_host_receipts tests.test_validate tests.test_evidence_manifest tests.test_verdict_review_gate
Ran 542 tests ... OK
$ python3 -m unittest tests.test_native_token_ci tests.test_host_receipts tests.test_validate   # the new test files on 167eb00a's code
FAILED (failures=6, errors=23)
$ gitleaks git --log-opts="167eb00a..HEAD" .
no leaks found

At 167eb00a (on main 2a330b0a; it merges cleanly with main 66584736c):

$ python3 scripts/validate.py
exit 0 (11744 hashed files); evidence_manifest.py --check: exit 0
$ python3 -m unittest <every module that uses host_receipts, native_token_ci, PRIVATE_CONTENT or TRUST_PATHS> tests.test_evidence_manifest tests.test_runtime_worker_openhands_push_gate
Ran 3386 tests ... FAILED (failures=2, skipped=29): both in BetterleaksTrialJobTests, a gitleaks child exiting 1 at load 24
$ python3 -m unittest tests.test_workflow_hardening tests.test_gitleaks_config   # alone, the same head
OK (skipped=1)
$ python3 -m unittest tests.test_native_token_ci tests.test_host_receipts tests.test_validate tests.test_evidence_manifest tests.test_verdict_review_gate
Ran 538 tests ... OK
$ python3 -m unittest tests.test_native_token_ci tests.test_host_receipts tests.test_validate   # the new test files on 6aaa204a's code
FAILED (failures=46, errors=4)
$ gitleaks git --log-opts="6aaa204a..HEAD" .
no leaks found

At 6aaa204a (on main 2a330b0a; it merges cleanly with main 83cec12ee):

$ python3 scripts/validate.py
exit 0 (11744 hashed files); evidence_manifest.py --check: exit 0
$ python3 -m unittest <the 13 modules above> tests.test_verify_sources_family_findings
Ran 1255 tests ... OK (skipped=4)
$ python3 -m unittest tests.test_native_token_ci   # the new test file on 66036a74's code
FAILED (failures=13)
$ python3 -W always::ResourceWarning -m unittest tests.test_native_token_ci
OK, 0 ResourceWarnings (24 at 66036a74)
$ gitleaks git --log-opts="66036a74..HEAD" .
no leaks found

At adc2adb2 (on main 2a330b0a):

$ python3 scripts/validate.py
exit 0 (11744 hashed files); evidence_manifest.py --check: exit 0 (rows outside this PR's 8 files equal main's)
$ python3 -m unittest <the 13 modules above> tests.test_verify_sources_family_findings tests.test_runtime_worker_openhands_push_gate
Ran 1373 tests ... OK (skipped=4) at a94c07d5 on 3a8a8461; at adc2adb2 the native-token, validate and receipt modules: OK
$ python3 -m unittest tests.test_native_token_ci   # the new test file on 4c916e14's code
FAILED (failures=16)
$ python3 -m unittest tests.test_validate tests.test_native_token_ci   # round 2's test files on 51f45b5d's code
FAILED (failures=3, errors=6)
$ gitleaks git --log-opts="$(git merge-base origin/main HEAD)..HEAD" .
no leaks found

Decision record

docs/decisions/2026-10-11-email-address-publication-rule.md covers the rule, its exemptions, the reviewed matches, Codex's review, both reads at e0862d8d, the GPT delta read at 51f45b5d, the command center's micro at 4c916e14 and its addenda 01 to 06 (the reads at 6aaa204a, the Claude micro at 167eb00a and both reads at 171b0811). Consequences: the sweep, convert.py, bundle.py and counter_readings.py apply the rule, and native_token_ci.py redacts it. #991 adds a test that fails when validate.py has a rule the PR-body gate does not carry. #991 lands first, and this PR's landing rebase carries the email rule into the gate. To undo, revert the commits.

Host evidence

Not applicable: no receipt changes.

Checklist

  • New/changed GitHub Actions are pinned to a full commit SHA with a
    version comment (no floating tags). (none changed)
  • New/changed workflows declare top-level permissions: {} and grant each job
    only what it needs (contents: read, or an explicitly justified addition). (none changed)
  • No secrets are printed, logged or committed; no new required secret was
    added without a documented owner.
  • No new paid hosting, subscription or billing surface was introduced.
  • Peer-owned untracked files and worktrees were preserved (not deleted,
    moved or overwritten).

🤖 Generated with Claude Code

@seathatflowsinourveins seathatflowsinourveins added the lane:foundation Foundation lane: Claude/Codex setup, hosts, memory, RAG, research, workers label Oct 11, 2026
@seathatflowsinourveins

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-12T11:19:55.375068Z 167eb00 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 308033f6c1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/validate.py Resolved
Comment thread scripts/validate.py Resolved
Comment thread scripts/validate.py Resolved
Comment thread scripts/validate.py Resolved
@seathatflowsinourveins
seathatflowsinourveins force-pushed the claude/api-actions-email-rule-20261011 branch from 308033f to bc41822 Compare October 11, 2026 14:44
@seathatflowsinourveins

Copy link
Copy Markdown
Collaborator Author

@codex review

@seathatflowsinourveins
seathatflowsinourveins force-pushed the claude/api-actions-email-rule-20261011 branch from bc41822 to e0862d8 Compare October 11, 2026 14:48

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bc41822cae

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/validate.py Resolved
Comment thread scripts/validate.py Resolved
Comment thread tests/test_validate.py Resolved
Comment thread scripts/validate.py Resolved
Comment thread scripts/native_token_ci.py Resolved
Claude Code puts the signed-in account's email address in every session's
context, and nothing in scripts/validate.py refused one, so it could reach a
public evidence file. PRIVATE_CONTENT gains an "email address" rule: an
RFC 5322 addr-spec, case-insensitive, that exempts GitHub noreply addresses,
the Anthropic and GitHub noreply commit identities, the RFC 2606 reserved
names with example.* under any TLD, the git@ SSH user, systemd instance
units and decorator calls.

The tree scan found 86 tracked files with public upstream or vendor addresses
or address-shaped text (signing keys, package maintainers, upstream captures,
fixtures). scripts/public_email_paths.json lists them with a reason per
group; validate.py's publication scan and host_receipts.py's receipt scan
waive only this rule for them. A test keeps every entry live.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Codex's GitHub review of 308033f (1 P1, 3 P2):

- P1: a path waiver passed any later address added to a listed file
  (reproduced at 308033f). scripts/public_email_matches.json now lists
  the 64 reviewed matches; a text passes the email rule only when every
  match in it is listed. The loader refuses a non-lower-case or repeated
  entry, and a test fails on an entry no tracked file carries.
- P2: the rule no longer skips a git local part; [email protected], the
  only Git-host form in the tree, is a reviewed entry.
- P2: the last label may be an IDNA A-label (RFC 5890 2.3.2.1).
- P2: native_token_ci.py redacts addresses as <EMAIL>; its copies of
  validate.py's rules sit in REDACTIONS, held equal by a test.

host_receipts.py judges the raw receipt and each decoded JSON string on
its own, so an escaped address is not waived by the raw bytes.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…mes, safe digests

The command center's Claude read and the co-op's GPT read (P1 B1, B2, B4;
P2 B3, C1; C2, C3), in one commit as the command center ruled:

- B1: a "(" after a match exempts nothing; the 7 tree matches it hid,
  decorator calls after an escaped newline, are reviewed entries.
- B2: the local part and its left boundary take every RFC 5322 atext
  character (rfc5322.txt:679-690), so a match is the whole dot-atom and
  private!<listed> is a different, unlisted match. A local part needs a
  letter or a digit (a code span of an @import names no mailbox).
- B3: the dead-entry check leaves the registry out.
- B4 (correction #161): native_token_ci.py publishes digests of sanitized
  text only; raw_sha256 and the stdout, stderr and MCP raw digests are gone.
- C1: RFC 2606's three names exactly, with their subdomains; example.*
  under other TLDs and chained labels are no longer exempt.
- C2: target is a TLD (IANA 2026101001), so it is no longer an exempt
  unit type.
- The registry is re-reviewed at main 3a8a846: 78 values, including
  #1003's URL-userinfo fixture; the record's counts are measured here.

Each regression fails on e0862d8 and passes here.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…case

The GPT delta read at 51f45b5, as the command center ruled it:
- P1-2: Run.publish() cleans each decoded key and string value of JSON or
  JSON Lines output, nested JSON too, for every published argument, stream,
  artifact and MCP digest, so a @-escaped address is removed.
- P2-3: the waiver keys a match by its local part as written and its domain
  in lower case (RFC 5321 2.4, rfc5321.txt:869); the registry lists the tree's
  spellings (79 entries).
- P1-1: the letter-or-digit guard stays; "names no mailbox" is restated as
  the residual it is (CPython 3.13.16 _header_value_parser.py accepts one).
- P2-4: the counts are measured: 532/454 at 51f45b5, 533/454 here.

The new tests fail on 51f45b5 (3 failures, 6 errors) and pass here.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
…decode depth

The command center's terminal adjudication at 4c916e1:
- B1: publish() split lines with str.splitlines(), which also breaks at
  U+2028, U+2029 and U+0085 (CPython cbc944f4 unicodetype_db.h:6418-6430);
  RFC 8259 7 allows them raw in a string, so such a line was never decoded
  and its \u0040-escaped address was published. A line now ends only at a
  line feed.
- B2: JSON text nested in strings deeper than PUBLISH_DEPTH (4) is refused
  with the fixed PUBLISH_REFUSED message, and nothing is published.
- B3-B5, B7-B9: the registry's spelling, the table (39), the respelling
  count (7 and 1), the symbol-only figure (125 in 76 files at 900835c,
  method named; correction #182), the limitation text, and the escape's
  sources (RFC 8259 7 rfc8259.txt:433; json/decoder.py:60, :118).

The new tests fail on 4c916e1 (16 failures) and pass here.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@seathatflowsinourveins
seathatflowsinourveins force-pushed the claude/api-actions-email-rule-20261011 branch from 4c916e1 to adc2adb Compare October 12, 2026 06:33
seathatflowsinourveins added a commit that referenced this pull request Oct 12, 2026
…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]>
…reader

The command center's addenda 01 and 02 at 4c916e1:
- Duplicate names (the GPT read's P1-2): json.loads keeps only the last
  member, so an earlier member's escaped address went out uninspected.
  publish() parses through an object_pairs_hook that refuses such an
  object (RFC 8259 4, rfc8259.txt:322).
- N1 (the micro at adc2adb): splitting only at line feeds left JSON beside
  a lone CR, or after RS, FF, VT, FS, GS, U+0085, U+2028 or U+2029,
  undecoded, while universal newlines (Lib/_pyio.py:153-154), splitlines()
  and jq read the address back. publish() now verifies its own output
  (recoverable()): every reader's splitting, a stream decoder, all members,
  nested JSON to the same depth and numbers kept as text (the micro's N2);
  if any reader recovers private content, PUBLISH_REFUSED, no output.
  Clean output keeps every byte.

The new tests fail on adc2adb (35 failures) and pass here.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@seathatflowsinourveins

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 66036a74ad

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/host_receipts.py Resolved
Comment thread scripts/native_token_ci.py Resolved
Comment thread scripts/native_token_ci.py Resolved
…n every framing

The command center's addendum 03 at 66036a7 (a shadow review, reproduced by
the co-op): a pretty-printed object after a lone CR, or behind RS framing
(RFC 7464 2), was cut by every split view, so its escaped address went out
while readline-then-json.load and jq --seq read it back. The verifier now
also decodes every RFC 8259 7 string escape across the whole output,
framing aside, up to PUBLISH_DEPTH times, and runs the sanitizer's rules on
each projection. Its decoder refuses a duplicate name too, so RS-framed
duplicates and duplicates after a long number are refused. The record's
stale scope sentence is corrected; a test's argv no longer carries the
escaped address. From the GPT read at 66036a7 (ACK): the MCP session closes
the parent's pipe ends once its readers finish (ResourceWarnings 24 to 0).

The new tests fail on 66036a7 (13 failures) and pass here.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@seathatflowsinourveins

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6aaa204a74

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/validate.py Resolved
The command center's addendum 04, from the GPT read and its Claude micro
at 6aaa204:
- P1-1, D5: an address escaped five or more times, or JSON nested four
  or more times, behind a lone CR or RS framing was published: the
  escape projection stopped after PUBLISH_DEPTH passes and the record
  views cut the multiline object. publication_views() now refuses when
  a further pass would still decode something, reads RS records whole,
  skips a byte order mark (RFC 8259 8.1) and resumes at the next line
  where no JSON text starts; text past the bound is refused whatever it
  holds.
- P1-2: host_receipts.py decoded a receipt once, so JSON in an
  output_excerpt kept its escaped address. It imports the same views,
  and a receipt they cannot finish is refused. native_token_ci.py joins
  the verdict-review gate's TRUST_PATHS.
- P2-3, F1: a duplicate name after a CR, an RS, a byte order mark or a
  progress line, nested, or beside a long number is refused.
- P2-4, P2-5: a rewrite that would merge two names or change a number
  as written is refused.
- Codex: the noreply exemption keeps the local part's case (RFC 5321
  2.4).
- P3s: JSON too deep for Python's decoder is refused, not raised; the
  surrogate-pair locator; the pipe close's CPython citation and a
  closure test; command tests read their payloads from files; the
  record's stale sentences, the 765 figure and the warning count.

The new tests fail on 6aaa204 (46 failures, 4 errors) and pass here.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
@seathatflowsinourveins

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 167eb00a98

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread scripts/native_token_ci.py Resolved
Comment thread scripts/native_token_ci.py Resolved
Comment thread scripts/native_token_ci.py Resolved
The command center's Claude micro at 167eb00:
- N1 (Codex's thread 4247416401): Run.observe() recorded the names a
  tool wrote under its state directory through clean() alone, so a file
  name that is JSON holding an escaped address reached receipt.json.
  flush() now verifies every string of the receipt, names and values,
  as publish() verifies its output; one that fails is replaced by the
  fixed refusal text and the run fails.
- Thread 4247416418: an address right after a JSON escape took the
  escape's last character, leaving invalid JSON. A document clean()
  changed is read as written and its decoded values are cleaned, at each
  level of JSON in strings.
- Thread 4247416409: a rewrite holding a lone surrogate is refused, not
  raised as UnicodeEncodeError.
- FC2: re-reading of JSON text left unclosed is bounded (RESCANS); past
  it the text is refused.
- FC1, FC3, FC4: the nesting bound applies in the framings the views
  read, not "whatever it holds"; the byte order mark's attribution; the
  addendum-04 label. The duplicate residual is disclosed.

The new tests fail on 167eb00 (6 failures, 23 errors) and pass here.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Both reads at 171b081: the claim that the decoding work is bounded by a
multiple of the length was false. Every failed decode builds a
JSONDecodeError that counts line breaks from the start of what it
decodes (CPython Lib/json/decoder.py:31-32), and the read across lines
decoded the whole piece from each line. It now decodes growing slices
that start where the text does, and every slice's length counts against
RESCANS, so the work is a multiple of the length.

In this delta's code: refused names are numbered instead of merged and
the report's own names are verified; a document holding NaN that
clean() changes is published cleaned again; the unread framings are
worded as measured; the lone-CR too-deep case no longer depends on the
interpreter; the surrogate refusal cites RFC 3629 3.

The new tests fail on 171b081 (4 failures) and pass here.

Co-Authored-By: Claude Opus 5.5 <[email protected]>

This branch has not been deployed

No deployments
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