Repository navigation
SIPP income, assets, pension and SSI readers (D2) - #581
Merged
Merged
Conversation
Pins the documentation the SIPP income-and-resources registry is verified
against, with no microdata requested or opened:
- the Census SIPP variable API for 2022-2025 (2018-2021 return HTTP 404;
the 404 bodies are kept);
- each release's data dictionary PDF, its pdftotext layout and the parsed
per-variable metadata, the public-use and replicate storage schemas,
the replicate dictionaries and Census's Python input examples;
- the locator pages they were found from.
capture_manifest.{txt,json} records every URL, UTC retrieval time, byte
size and SHA-256; derived_manifest.json pins the derived files and the
parser. The parser now refuses an inverted range (min above max) instead
of admitting an empty domain: the 2021 dictionary prints EHRESIDENCID as
"Minimum 100001, Maximum 40999". A folder .gitattributes keeps the CRLF
pages and input examples byte-identical to their pinned hashes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sipp_income_registry.py embeds, per release 2018-2025, each admitted
concept's Census name, label, type, value codes and ranges, generated by
data/external/sipp_income/build_registry.py from the committed metadata
only (API for 2022-2025, the release dictionary and storage schema for
2018-2021). Unknown releases, concepts and codes raise; a concept absent,
suppressed or without a verified domain in a release is refused there,
with the reason in refused_concepts.json.
sipp_income.py reads a pipe-delimited pu{year} file with usecols, every
column as a string first, then validates each token against that
release's exact domain before conversion. SSUID stays a string; the
person key is panel:SSUID:PNUM; replicate weights attach many-to-one on
SSUID, PNUM and MONTHCODE only when the sidecar's keys are unique and
complete and REPWGT0 equals WPFINWGT.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Invented pipe-delimited files only (INVENTED_* names); no staging directory is read. Covers column selection, dtypes, refusal of unverified releases, concepts and codes, release-specific sentinels, the entry-year and roster crosswalks, replicate linkage, and Hypothesis properties: row count and order preserved, person ids stable across months and waves, weights carried unchanged, unverified codes refused. The evidence tests replay the registry from the committed metadata. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…otes Verification now uses every Census source a release has and records each disagreement: - 2018-2021 labels come from the release dictionary (the verifying source); the storage-schema label is kept and checked against it. Four conflicts: 2018 EJSOWNRE/EJSOWNRP resolve to the dictionary on Census's user note; 2020 TDIS6AMT (state vs local) and EDIS8MNYN (military vs railroad) stay open and are refused. - 2022-2025 values must satisfy both the variable API and the release dictionary (API missing codes exempt). This admits GHLFSAM and GVARSTR, whose API entries list only a missing code, and narrows owner pointers to Census's documented codes (domain_checks.json lists all 72 cases). - source_rulings.json holds every hand ruling with its evidence; the generator stops on an unruled label conflict. Open: ESSI_BRSN in 2021 and 2022 (code order flips against Census's 2018 correction note) and 70 joint-asset concept-years in 2020 whose metadata predate Census's 2020 joint-assets note. - TSSSAMT for 2018-2021 is gated on the download date: Census re-released those files on 2025-07-24 with corrected amounts under the same names. - Captured the release notes, Census's 2018-2022 crosswalks, the 2018 metadata and topic dictionaries, and screened all 355 user-note pages; the 109 naming an admitted variable are stored and attached per concept. - release_changes.json lists every change in name, label, universe, codes, domain, missing codes or admission across releases. - Census's input examples are stored as .py.txt (bytes unchanged) so the repository-wide black and ruff checks skip them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…walk Unit tier (107, invented pipe-delimited files only): - design codes in 2022-2025 come from the dictionary when the API lists only a missing code; a value one source admits and the other does not refuses (owner pointers 70 versus 80); - the TSSSAMT gate refuses 2018-2021 reads without, or before, a 2025-07-24 download date, before any file is opened; - ESSI_BRSN, the 2020 joint families and the 2020 disability sources are refused where their sources conflict; universes travel per release; - Hypothesis: row count and order preserved, person ids stable across months, waves and releases, weights and replicate weights carried unchanged, an unverified code always refuses, and a differential test that the reader admits exactly what an independent restatement of the domain rule admits (400 examples over every numeric concept). Artifact tier (72): the registry replays from each release's own metadata; schema labels agree with the dictionary or carry a ruling; every refusal has a cause in the evidence; each ruling's claim appears in the Census note it cites; the crosswalk agrees with Census's 2018-2022 crosswalk workbooks except one recorded Census anomaly; the change ledger holds the documented universe and label changes; user notes, captures, derived files and the regenerated tables match their pins. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The variable API documents a missing code for WPFINWGT in 2022-2025 (-99900000000 in 2022, -999.00000000 in 2023-2025). The reader admitted it as a value and never checked the weight, so a file carrying it would have entered with a weight of -999. Every structural key and the weight must now be present and differ from each of that release's documented missing codes, compared as decimals. A parametrized test covers all 32 documented key and weight missing codes; on the previous reader the four weight cases loaded without error. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
metadata_notes.md now records the captures, the per-release verification rules, every ruling and open question, and the Census anomalies found. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Two adversarial reviews (code, and claims against the Census evidence) found problems; each fixed one was reproduced first. Reader (sipp_income.py): - Count fields on every line before parsing. With usecols pandas stops checking, so a short row's missing fields read as structural blanks and an extra field shifted values between columns. Repeated header names and corrupt or truncated gzip files also refuse. - Tokens must be plain ASCII decimals, and string-stored identifiers the dictionary's fixed-width digits (SSUID 14, ERESIDENCEID 6, SHHADID 3, GVARSTR 3, GHLFSAM 2). Decimal() accepted "+11", "1.2345E4", "0_1" and full-width digits, which split one key into several or put the record value into a pandas error message. - downloaded_on accepts a datetime. Registry and generator: - Blanks are refused for items whose universe is all persons or all households (citizenship, nativity, household status, design codes). - 2022-2025 API labels are checked against the dictionary too (no conflicts); a variable one source suppresses and another documents is a ruled conflict (2018 EDIS8MNYN, open). - 2018 EJSOWNRE/EJSOWNRP take label and universe verbatim from Census's correcting user note; the dictionary's EJSOWNRP universe read "or". - Misprinted universes are cleared under cited rulings: 2021 ERETTYPnYN (empty as printed) and 2024-2025 TRET1AMT-TRET7AMT (all name source 8). - The dictionary parser reads comma-grouped codes (TSCNTAMT1/2's 9,999,999 special code now verifies and is labelled) and marks 2018-2020 entries whose value list runs onto an unjoined page as unverified (30, 33 and 33 entries; none selected). - Census record levels: SSI spell items and child Social Security flags are person-month (period monthly); ETENURE and TLIVQTR household; SSUID, SPANEL, SWAVE design keys; EHRESIDENCID person. - The registry embeds its tables as one JSON string literal, so regeneration needs no formatter pass over megabytes of tables. - Text corrections: 101 user notes are stored (plus 8 index pages; the earlier commit said 109 notes), the 2020 joint-debt treatment, the roster slot 15 years, the ERETANY and TSSAGESS changes, and the correction ruling no longer claims unchanged file names. Tests: the evidence suite passes (77) with an independent boundary probe of every API-dictionary difference and a record-level check; reader tests gain layout, spelling, universe-blank, datetime and string-identifier differential cases (full reader run pending on a loaded host). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Attempt a2 stopped on a network error while rerunning the reader tests; these edits have not yet passed that run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Eight design-code cases now supply zero-padded tokens and check that an unpadded token is refused; the ninth expects the recorded Census correction note as the label source. The notes' count of concept-years where the API and dictionary domains differ is 64, not 72. Co-Authored-By: Codex <noreply@openai.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The birth-evidence identity check seals every source under src/populace_dynamics except listed opt-in modules. List the two new reader modules as post-review exclusions, in the test's expected tuple, and in the reachability test, which asserts the historical reducer cannot import them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Record-bearing user notes (high). Eight stored Census user notes carried individual survey identifiers with case values. Their whole-page captures are removed. The note inventory keeps each one's URL, title, release and variables, marked excluded with no stored body. The capture script now refuses those URLs before any request and refuses any note page whose tables or text carry identifier columns or identifiers followed by values. A test checks every stored capture with that guard, and its failure message names only the file. The evidence pins drop the eight bodies, and metadata_notes.md corrects its claim and its counts (93 stored notes). CSV quoting (medium). The reader's pandas call now passes csv.QUOTE_NONE, so its record boundaries agree with the physical-line layout validator. A quote in an unselected field can no longer absorb the next person-month. Adds the minimized invented regression and a property with quotes in selected and unselected fields. Domain rulings (medium). source_rulings.json gains 13 named domain-conflict rulings covering all 64 API/dictionary disagreements, each listing its members and citing both sources' locations. The generator now refuses a disagreement without an exact, cited, settled ruling. Every admitted domain is unchanged: only the ruling references and their pins move. Also adds Hypothesis properties for the vintage gate, malformed layouts, replicate keys and the registry's source-conflict, ownership and evidence-pin invariants, on invented inputs through the production code. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
M1, the capture guard. record_bearing_note now refuses a page holding any of these forms, and its docstring lists them: - a column headed by an identifier name, including a heading that opens with one, such as "SSUID (sample unit)"; - a table row with an identifier name and, in another cell, three or more digits, even in a variable-definition table; - a table row of three or more numeric cells; - an identifier name followed by digits with only punctuation between, or by three or more digits within 40 characters of the same sentence, in the text or inside an HTML comment, which is stored though not shown; - a run of nine or more digits in the text a reader sees; - a preformatted block naming an identifier and holding a digit. Variable-definition rows and prose may still name an identifier without a value. Tests add 16 invented record pages, which the guard refuses (the parent guard missed 13 of them), and 4 invented definition pages, which it admits. Three properties cover identifier-and-value sentences, long digit runs where rendered, and rows of three numbers. Every stored user note still passes the guard. metadata_notes.md now states the guard as these forms. M2, physical records. _check_layout strips one LF and then one CR from each line, and refuses any other carriage return in a record. The line check and pandas therefore see the same records: QUOTE_NONE already kept quotes from joining lines, and a lone CR can no longer split one. Tests add the review's minimized regression (two invented rows joined by a CR in an unselected field, which gave two person-months before), a CRLF file that keeps every record, and a carriage return in the quote property's alphabet. The property expects one row per LF-delimited data line, or a refusal. L1. The THEQ_BUS ruling's reason now describes the printed range as it is: its upper bound is malformed, and its lower bound differs from the API's. The registry pin of source_rulings.json is regenerated. L2. build_registry checks that a ruling member's PDF citations name its own release's dictionary at exactly the pages its dictionary entry holds. The invented ruling cites its page, and the damage property adds a wrong page and another release's PDF. Invariants: - No stored page shows a form record_bearing_note refuses. - The reader yields one person-month per LF-delimited data line, or refuses. - Every ruling member's PDF citations equal its dictionary pages. Tests (invented data only): test_sipp_income 183 passed; test_sipp_income_evidence 106 passed; test_sipp_income_refusal_properties 6 passed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Round 4 approved 7521c6d with seven low findings and four notes. This commit answers each. L1, rules without a failing test. Every invented record page carried the 15-digit invented SSUID, so the digit-run rules refused each page before the rule it was meant to test. INVENTED_RULE_TWINS pairs a refused page with a twin that differs only in what one rule reads, and the test requires the rule to refuse the page and admit the twin. There are eight pairs: an identifier beside a three-digit value in a definition row, an exact identifier heading, a preformatted identifier with a digit, a preformatted line of three numbers, a table row of three numbers, and short values in an attribute, a script and a comment with markup inside it. L2, stored content not shown. The identifier rules now also read the page source with its tags, attributes and scripts, entities decoded, and a run of 14 or more digits, an SSUID's length, refuses the page wherever it appears. The nine-digit rule still skips comments, noscript blocks, scripts, styles and tags, where tracking numbers sit; the tracking definition pages now put a 12-digit number in comment text after a ">", in a noscript block and in an attribute, each admitted. L3, years beside identifier names. The 40-character and same-row rules no longer count a year from 1900 to 2099. Admitted pages add a universe footer without a period, a panel year, an index link titled with a year and a definition row with a year, and a property draws identifier sentences ending in any such year, in text, a comment or an attribute. An identifier followed directly by digits, such as "SSUID 2022", still refuses. L4, numeric forms. A numeric cell now admits Census's negative-dollar forms (-$250, $-250, the Unicode minus) and bracketed amounts, and a preformatted line of three or more such numbers refuses. The property's numeric text draws these forms too. L5, claims. The docstring, metadata_notes.md and the module header now state the rules as the code applies them. A correction to 7521c6d's message: it said a column headed by a heading that opens with an identifier, "such as SSUID (sample unit)", refuses. Only a cell that is exactly an identifier name refuses as a heading; a cell that opens with one refuses only when a cell of digits alone sits below it or a value of three or more digits sits in its row. L6, PDF citations. Every citation containing ".pdf", in any case, now counts: a member's PDF citations must equal one "{year}_dictionary.pdf#page={page}" per page of its dictionary entry. The damage property adds a pageless own-release PDF, a pageless other-release PDF and a release-notes PDF with a page. Each damage now runs as its own case and must fail at its own check, by message. With the parent check, the two pageless damages pass generation. L7, the window. A test pins the 40-character window: 40 characters between an identifier and a three-digit value refuse, 41 admit. Notes. The THEQ_BUS reason now says only the malformed upper bound makes the entry unverified, and that its lower bound also differs from the API's; the regenerated registry changes only the source_rulings.json pin. The reader's docstring now says quotes are literal characters, so the line check and pandas split the same records, and only a stray carriage return refuses. Invariants: - No stored page shows a form record_bearing_note refuses (all 101 stored captures pass). - Each guard rule alone refuses its minimal page and admits its twin. - Every ruling member's PDF citations equal its dictionary pages, one citation per page. Results: - 17 of the 129 evidence tests fail against 7521c6d's guard. - 16 mutants, one per guard rule or exemption, are all caught. - Tests (invented data only): test_sipp_income 183 passed; test_sipp_income_evidence 129 passed; test_sipp_income_refusal_properties 15 passed. Tiers: unit 183, artifact 144. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # scripts/first_estimates_birth_evidence.py # tests/estimates/test_birth_evidence_artifact.py
The round-5 delta review (an Opus 5.5 reviewer, at ffc4d48) approved, with five low findings and some notes. - L1: reading the page source refused pages that only name an identifier, and index links, because the 40-character window ran across attribute boundaries and the adjacency rule fired on link slugs such as "ssuid-2024". In the source, the window now holds no quote or equals sign as well as no period or tag, so it stays inside one attribute value or string, and href and src values are removed from tags before the two identifier rules read it. The 14-digit rule still reads them. The review's four pages that only name an identifier, and an anchor whose title is an identifier name, are now admitted definition pages, as are a tracking number in a link target outside noscript and a row header outside a definition table. A 14-digit run in a link target, such as a timestamp, is still refused. - L2: the mutants that survived now fail tests. Twins pin the window and the adjacency rule each alone in the source, a tag and a quote as window limits, and the removal of link targets; record pages pin the year exemption's lookahead and its absence from the adjacency rule; a definition page with two numbers per preformatted line and a property over preformatted lines pin that rule's threshold and line split; and a row header outside a definition table pins that exemption. - L3: twins now cover the digit-below, adjacency, nine-digit and 14-digit rules too, so every rule, and each limit on what the identifier rules read, has a refused page and an admitted twin (17 pairs). The 40-character window in visible text is pinned by the width test, which has letters between. - L4: the notes and the docstring now say which rules read the source ("the two rules that follow an identifier name"), that the same-row rule needs a cell that begins with an identifier name, and that the window allows no period between, and in the source no tag either. - L5a: a first-row or header cell that names an identifier anywhere, as in "Person number (PNUM)", with a cell of digits alone below it, is now refused. The other forms the review lists (a value before its identifier, <br> CSV text with no identifier, div grids) stay out of scope, as the docstring states. - Notes: the reader's carriage-return sentence now says a CR is allowed at a line's end, before its LF or last in a final line without one. The other notes need no change: the top-code row is the three-number rule's accepted cost, and the year exemption admits a 1900-2099 value after an identifier with words between. Found by this fix's own mutants: the visible-text window stopped at an angle bracket, though the text holds no tags by then, so a decoded < or > between an identifier name and a value admitted the page. The window there now stops only at a period, as the round-3 rule meant ("within 40 characters of the same sentence"); in the text and comments a tag counts as a space, and the source reading still stops at tags. A twin pins it, 18 pairs in all, and mutant G23 puts the old limit back. Corrections to 04a2b89's message: - "Each guard rule alone refuses its minimal page and admits its twin" held for the eight pairs then present, which covered five rules and three readings; the digit-below, adjacency, nine-digit and 14-digit rules had no twin until now. - "16 mutants, one per guard rule or exemption": the 16 had two for the window width and none for the digit-below rule or the row-header and definition-table exemptions. - "With the parent check, the two pageless damages pass generation": pageless_pdf does, but pageless_other_release_pdf stops earlier on a file missing from the invented folder. - "Every invented record page carried the 15-digit invented SSUID": 14 of the 16 did; header_after_title_row_with_dashed_values and person_months_without_identifier don't. - The heading correction's "a value of three or more digits sits in its row" omits "that is not a year". Checks: - Each of the 18 twins isolates its rule or limit: disabling the rule admits its page, and dropping the limit refuses its twin, with the head refusing each page and admitting each twin. - All 32 guard mutants fail at least one test, in Hypothesis seeds 0 and 7, and the guard is restored after each. - With ffc4d48's guard, 9 of the 153 tests in test_sipp_income_evidence.py fail, the same 9 in each of three Hypothesis seeds. - Every stored capture still passes the guard (the stored-capture test). - The three D2 test modules through the wrapper: 351 passed. By collection, unit 183 and artifact 168, 24 artifact tests more than at ffc4d48. - black and ruff are clean. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Master brings SM1 (#570). The merge has no conflicts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Round 6 reviewed c1a3c7b and its merge 60b67f8 and returned APPROVE, with three low findings and four notes. This commit answers each. - Low 1: the source window's limits admit an identifier and its value that sit in different attribute values or script strings, or that a quote or equals sign splits within one, and a value in an href or src value other than a 14-digit run. The docstring said the window stays "inside one attribute value or string", which overstated it. This commit takes the review's first option: the docstring, metadata_notes.md and the PR body now list these forms as out of scope, with a value before its identifier, CSV text, div grids and a body cell that names an identifier after other words. The review's second option, reading each attribute value and script string alone, would close three of the seven forms; the script forms would need a rule of their own, and the link-target form would stay. - Low 2: nine of the review's ten mutants of the changed rules survived, so "every rule and each limit has a twin" overstated the tests. New twins pin each mark that stops the source window alone (equals sign, single quote, double quote), unquoted href values and src values, adjacency in the text reading alone, and both heading-cell rules: 26 twins in all. Two record pages pin the heading-names rule's cell conditions, a header cell after the first row and a first-row cell that is not a header cell, and a definition page pins its limit to those cells. - Low 3: a first-row or header cell that names an identifier after other words now also counts for the same-row rule, so a run of three or more digits that is not a year elsewhere in its row is refused (the review's K2). A twin pins it. A body cell that names an identifier after other words stays out of scope; the review's K1 would also refuse such definition tables. - Note 1: the heading-cell rule refuses some definition and index tables. The docstring and the notes now say so; no stored capture is refused. - Note 2: a tag now opens with a letter, "!" or "/", so a comparison such as "1 < 2" in a script no longer hides a src assignment from the source reading. A record page pins it, and the test comment says so. - Note 3, corrections to c1a3c7b's message and to the notes: - "the other L5 forms stay out of scope, as the docstring states": only the PR body stated it; the docstring does from this commit; - "are now admitted definition pages": the parent already admitted tracking_number_in_link_target and row_header_outside_definition_table; they are new test pages, not new admissions; - "The 40-character window in visible text is pinned by the width test": the width page is also refused by the source reading, so the test pins the width in both readings; comment_text and text_window_crosses_decoded_brackets pin the text reading alone; - the notes said the table rules read cells without their attributes, but the row-header exemption reads scope. The notes now say so, and their unreflowed line is reflowed. - Note 4: "PNUM > 100" is now refused, as "PNUM greater than 100" already was. No change. Checks: - each of the 26 twins isolates its rule or limit (twin_isolation_r7.py); - all 44 guard mutants fail a test in Hypothesis seeds 0 and 7: round 6's 32, and 12 new ones, for the review's R1-R7, R9 and R10, the double quote, the same-row rule's heading cells and the tag pattern (mutate_guard_r7.py); - with c1a3c7b's guard, 2 of the 165 evidence tests fail, the same 2 in seeds 0, 1 and 2: the script-comparison record page and the twin for the same-row rule's heading cells, which pin this commit's two code changes. The other new tests pin limits the parent already kept; - the guard refuses none of the 101 stored captures (counts only), and the stored-capture test passes; - 375 passed and 1 failed over D2's three modules and the birth-evidence check: 363 from D2's modules and 12 birth-evidence tests. The failure is the track-U assertion, which needs modules this sparse clone leaves out; CI runs it; - tiers by collection: unit 183, artifact 180 (12 more artifact tests); - black -l 79 --check, ruff check and git diff --check are clean. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Round 8 reviewed 6e96c64 and its merge 085a33b and returned APPROVE, with four low findings and five notes. This commit answers each under one added rule: no page that 085a33b's guard refuses may be admitted. So every reading that guard made is kept, with the same result, and now runs in linear time; the new readings are only added to it. - Low 1: two new value patterns took quadratic time on long runs, a word in a tag (78 s for 40 kB) or escaped quotes after an unpaired quote in a script. Attribute names now start only where a run of name characters starts, as the review proposed. Script strings keep round 8's reading, in which an escaped quote mark outside a string can still open one; a mark after the last unescaped mark of its kind can open no string, so it is set aside before the scan rather than read to the end each time. (The review's form consumes escapes outside strings, which would change which strings are read.) Timing every slow form found more in the parent's patterns: tag, script, style, table, row, cell and preformatted openings with no closing ">", script and style start tags with no end tag (round 8's 0.25 MB case), unclosed "<a" tags (its 0.5 MB case), unclosed comments and noscript blocks, and table rows and cells that name an identifier. Each is now linear: element and tag patterns stop searching at the page's last ">", a script or style opening that no end tag of its name follows is skipped, comment and noscript removal stop at the last end tag, and the table rules read each row and column once. A timing test reads seven invented pages of 200 to 600 kB, one in each form, in a child process that the operating system stops after 6 s of CPU time, and needs each under 5 s. They take 0.03 to 0.68 s of CPU here; by their growth over a tenth of each page, 085a33b's guard would take 2.3 to 7.1 minutes. A differential property checks each linear helper against the plain pattern it stands for. - Low 2: the script and style split found "<script" inside a quoted value, so '<a href="<script src="PNUM=101">' was admitted, which the parent refused. The source is now also read with script and style elements found where a browser starts them, in one left-to-right scan (the review's C1). The split reading stays, since C1 alone admits pages it refuses. Record pages pin F3 and its "<b>" form F6, which both guards refuse, and a twin that moves the quote so src is a real attribute pins the browser scan alone. Two record pages pin each reading alone. - Low 3: template literals are now read as script strings, apart from the double- and single-quoted strings, so that a backtick changes no other string; record pages pin T1, T3, T4 and T5. The text is also read as a browser reads it: a tag opens only with a letter, "!" or "/", script and style contents are left out, and title, textarea and xmp contents are text. That refuses V1-V3 and R1 and R3 (and an xmp page), and quoted strings in styles are read alone, which refuses S16; record pages pin each, and twins pin the browser text's "<" rule and title contents, template literals and style strings. U1 and U2 (markup in a text/template script) and Q12 (an unquoted attribute value) stay admitted and are named out of scope, in the review's words. The lists now say what the code reads: "each double- or single-quoted string in a script, as a scan from the script's start finds them, even one that an escaped quote mark opens", and the text "read twice, each time with a tag counted as a space". - Low 4: record pages pin each of the review's O1-O10, and each of the ten mutants, ported to this code, now changes its page in process. Full-module runs of the mutants at seeds 0 and 7 follow this commit. - Note 1: the guard's Hypothesis properties, and the three tests the review saw miss their deadline, run with deadline=None. - Note 2: the quoted-value reading still skips only values named href or src, since narrowing it would admit pages the parent refuses. The docstring and the notes name the asymmetry and the xlink:href, :href and img.src slugs it refuses. - Note 3: the newly refused definition and index forms (W1, W3, N1 and N3-N7) are named among the pages the rules refuse, W1's definition row and N4's page summary among them. - Note 4: of the four mutants that only round 8's record pages pinned, three were new in round 8 (G64, G65, G67); G32, round 5's "data-src removed too", was left unpinned by the new reading of quoted values. - Note 5: no change. Found by this commit's own checks: - the linear text reading raised on a script name that "(?i)" reads with a long s or a dotted capital I, as in "<SCRİPT>x</script>": its end-tag lookup keyed names by casefold, where Python's re compares a repeated name a letter at a time in lower case. Names are now keyed that way, which agrees with re over every spelling of script and style on Python 3.10 to 3.14. A record page, a definition page and two examples of the differential property pin it; - the script-string reading had moved to an element pattern whose end tag repeats the opening's name, so '<ſcript>a = "x</script>' read on past "</script>" and admitted a later script's string that the parent refuses. It ends at any "</script>" again, as before, and a record page pins it; - a script string after a quote mark in a template literal, as after a comment's "it's", is admitted by both guards; the out-of-scope list now names a lone quote mark in a comment, a regular expression or a template literal; - the over-refusal list names "a definition that prints a comparison such as PNUM < 101 in the text", now that the text reading refuses it. Checks: - 188 invented pages behave as expected (44 new); - no page 085a33b's guard refuses is admitted: over the test pages, round 8's probes (69 pages, and 16 same-row pages written from the names of its 13, whose text was not kept) and round 7's (34 probes, 6 round-6 forms and 7 fix pages), and 4 x 100,000 random invented pages from each of prescreen_r8's and fuzz8's generators, with 4 x 100,000 more that add unicode script names; 201, 1,657 and 1,305 of those pages are refused at the head alone, none by the parent alone; - each of the 38 twins isolates its rule or limit; - 105 guard mutants: round 8's 67, ported where the code moved, the review's O1-O10 and 28 new ones. In process, 97 change an invented page or an example of the differential property; the other 8 only make a reading quadratic, and the timing test alone pins them; - with 085a33b's guard, 26 of the 171 guard tests fail in seeds 0, 1 and 2, the same 26 in each: 13 new record pages, the 5 new twins, the 7 long pages and the differential property. The other 21 new tests pass there: 17 record pages it already refuses, which pin readings kept from it and the review's ten mutants, and 4 definition pages it admits; - the guard refuses none of the 101 stored captures (counts only); they take 5.58 s at the head and 2.66 s at the parent, the worst page 0.09 s and 0.04 s (CPU); - the four test modules give 458 passed and 1 failed, the known test_post_review_exclusions_are_unreachable_from_birth_evidence, which needs modules this sparse checkout leaves out. The exact command passed the shell's 10-minute limit, so each module ran alone, or in parts of its test functions, through the same wrapper with -n 2; - tiers by collection: unit 183, artifact 263 (47 new), and none in integration_psid, reproduction_legacy or oracle_policyengine; _classify_test_module still gives unit, artifact and artifact; - black -l 79 --check, ruff check and git diff --check are clean. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ger page Mutant G89 sums the same row's values once per cell, in quadratic time. It survived at c501f04, because the timing test's row of identifier cells stayed under the 5 s limit even with that sum. The test now reads 60,000 identifier cells in one row (780 kB), and G89 fails it in Hypothesis seeds 0 and 7. G82 to G88, the other mutants that only make a reading quadratic, still fail it in seed 0. This corrects c501f04's message, which said the timing test alone pins those 8 mutants. It pinned 7 of them. metadata_notes.md and the test's header now give the pages' range as 200 to 780 kB. The other 97 mutants were not rerun, since this commit changes only one test page and two notes. Checks, on these bytes: the guard and reader tests pass, 458 in all with the seven linear-time pages; the one failure is the birth-evidence reachability test, which needs modules this partial checkout leaves out, and CI runs it. black, ruff and git diff --check are clean. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Round 9 approved 16ea8c9 with four low findings and six notes. This commit answers them under the round's rule, that the guard admits no page 085a33b's guard refuses, and adds nothing else. Low 1 needed a test of that rule. A frozen copy of 085a33b's guard now sits in the test tree as text, tests/income_resources/fixtures/capture_user_notes_085a33b9.py.txt, and a test pins its sha256; no run collects it and the tier classifier never reads it. A Hypothesis property draws pages from the parts of the forms the review found (a script in an unclosed tag, over lines, in upper case or after an end tag in a string, and a string across a template literal), with invented tokens between them, and asserts that the guard refuses every page the copy refuses. Its explicit examples and four new record pages are the review's X1, X3, X5 and X9. The differential property now also checks the attribute pattern against the pattern without its lookbehind, and the table rules against the copy's cell-by-cell reading. Low 2 needed the browser readings to read names as a browser does. The browser text and the browser scan of the source now fold ASCII letters only in element names, in an end tag's repeat of its opening's name and in a tag's first letter, so a long s, the Kelvin sign and a dotless or dotted capital i open no tag and name no element. The ASCII flags cover only those parts: a global one would also change \b, so that "<scripté>" opened a script the round-9 head shows as text. shown() compares names in lower case, not casefold, so "<ſcript>" stays text. Raw-text elements end at "</" and the name followed by whitespace, "/" or ">", through the next ">". The guard now refuses E1, E2, E4, U1, U4 and L1-L4, and record pages hold them. The docstring, metadata_notes.md and the PR text now name the forms that stay admitted: an identifier name split by a tag or an invisible character, values in separate style strings, a comment that holds a script or style opening, a tag that ends with "-->", which the text readings run on to the next ">", and nine digits after a "--!>" comment end. This commit's own checks found the "-->" form. These changes touch only the browser readings, so 085a33b's readings stand and the rule holds. They do not only add refusals against 16ea8c9, though: they follow a browser where 16ea8c9 did not, and some pages that 16ea8c9 refused for that reason the guard now admits; 085a33b admits each of them too. The most common is a "<SCRİPT>" or "<scrıpt>" element, whose contents 16ea8c9 read as raw text and a browser parses as markup; others are an end tag "</scrİpt>", which 16ea8c9 took to end a script and a browser does not, and "<ſ", which 16ea8c9 took for a tag. Low 3 needed the new readings pinned. Record pages pin X2, X4, X7, X8 and X10, a definition page pins X11, and X12's page is a record page, since a browser shows a "<ſcript>" element's contents. Record or definition pages pin this commit's own mutants of the new parts, N1-N13. N14 (an end tag with no ">" ends nothing) and X12r (X12's port: casefold for lower) give the head's result on every page: the first text reading reads the text after the last ">" as it stands, and the browser readings' names are ASCII, which casefold and lower fold alike. Low 4 needed the timing test to pin Q1-Q6. Five new long pages, of 100 kB to 2.1 MB, take one form each, and the escaped-quote page grows from 200 kB to 1 MB for Q5. By the mutants' growth, each takes 20 s or more of CPU on its page; the head reads each of the 12 pages in under 1 s. N1: this message and the PR text correct the claims N1 lists. c501f04's differential property left out the attribute pattern and the table rules; its ten ported mutants survived when ported to the split alone; both guards refuse F6, but 085a33b admits F3; its "7 fix pages" were 8; 16ea8c9's 458 tests include 12 birth-evidence tests, and that commit also rewrote the timing test's comment. N2: the docstring, the notes and the PR text name D8 (a template literal that holds JSON) and F2 (a malformed href value that holds a script opening) among the pages the rules refuse. N5: _finditer's docstring says it relies on (?s) in each pattern that can end with $. N6: the tests ran in parts. N3 and N4 need no change. Checks: - Pages and probes: all 217 invented test pages behave as expected, 29 of them new; round 8's probe8 (69), round 7's probes (34), round 6's forms (6), round 7's fix pages (8), round 9's own probes (16) and same-row pages (16) give no page that 085a33b or 16ea8c9 refuses and the head admits. Of the round-9 reviewer's 34 record probes, the head refuses 26, up from 17. Its definition probes give the round-9 head's results. - The rule: 300,000 random invented pages from round 9's three token sets (100,000 each) and 100,000 from the round-9 reviewer's alphabet, with its identity checks of every linear helper: 0 pages that 085a33b refuses and the head admits, and 0 identity failures. The head alone refuses 40, 437, 390 and 545 of them. 16ea8c9 refuses 0, 0, 27 and 64 pages that the head admits, for the reasons above. - Stored captures: the head and 085a33b each refuse 0 of 101. - Twins: each of the 38 isolates its rule or limit, as in round 9. - Tests, in parts through the wrapper with two workers: the evidence module's guard tests other than the timing test, 194 passed; the timing test, 12 passed; its other tests, 78 passed in two parts; the refusal properties and birth-evidence tests, 27 passed and the known test_post_review_exclusions_are_unreachable_from_birth_evidence failure. Of test_sipp_income.py, which reads no file this commit changes, the first of four parts passed 74 tests before the 575 s cap stopped it; the other parts run after this commit. - Lint: black -l 79 --check and ruff check pass on the two Python files, and git diff --check is clean on all four changed files. The mutant module runs, the parent check and the tier counts follow this commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
7ae8edb added five long pages to the timing test and enlarged a sixth, but metadata_notes.md still said the test reads pages of 200 to 780 kB in round 9's forms. The notes now give the range, 100 kB to 2.1 MB, and name the forms where a slower form of a linear helper, found in review, takes quadratic time. No test or hash pins the notes, and this commit changes no other file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Round 10 approved d7442ef with five low findings and five notes. This commit closes them under the same rule: the guard admits no page that 085a33b's guard refuses. Low 2, where a browser element's name ends. _browser_element now ends an opening's name where a browser ends it, at whitespace, "/" or ">", with the review's lookahead (?=[\t\n\f\r />]) in place of \b. So <script-x>, <script.x>, <script\0>, <script\v>, <script"x">, <script=x> and <style:x> open no script or style in the browser readings, and a browser shows their contents. Seven record pages hold those forms: each mark passes \b, and the vertical tab also passes \s. <textarea.x> needs no page, since d7442ef already refuses it. A definition page holds a script opening ended by each of the six marks. Low 1, a comment or hidden text between an identifier and its value. The text has a third reading, _browser_view, which reads the page as a browser with scripting on shows it. It keeps the browser text's rules, leaves comments out where a browser starts and ends them (COMMENT: at "-->" or "--!>", or the end of the page, with "<!-->" and "<!--->" empty), and hides iframe, noembed, noframes, noscript and template contents. A browser reads the first four as raw text, so a script opening inside one opens nothing. - This goes beyond candidate C2 as written. _browser_text(body) reads a comment as a tag that ends at its first ">", so commented-out markup such as <!-- <span class="label">Person no.</span> --> still shows text and its period. A record page holds that form. - The review's fifth page needs template hidden. A browser parses template contents but shows none of them. The view ends them at the first </template>, and a browser's end falls there or later, so the view hides no text a browser shows. - The browser text over comments kept, the scripting-off reading, stays unchanged apart from Low 2's opening. So every reading that read noscript contents still reads them, and <noscript>PNUM <b>101</b> </noscript> (RB8) stays refused. - The browser source reading needs no such change. It reads a script's contents as they stand, so a script that a browser would not open there hides no text from it; it only leaves the href and src values of the tags it spans in place. Reading those elements as raw text there would either read their tags' link targets, refusing the admitted noscript_link_target and iframe_link_target pages, or drop their contents from the reading meant to read the whole source. - Record pages hold the review's six pages and 13 more: the other three raw-text elements with a script opening inside, a period inside each of the four raw-text elements, commented-out markup, "<!-->", "<!--->" and "--!>" ends, and two forms the old lists named: a comment that holds a script opening and a tag ending with "-->". Both stay admitted inside noscript contents, which only the readings that keep comments read there, and the lists now say so. Low 3, the rule property. Record pages hold <p>PNUM #7</p>, [7, '7 and (7, each refused by the adjacency pattern and admitted when its mark leaves the pattern, and <noscript>PNUM <b>101</b></noscript>. - A second test draws pages from LINEAR_TOKENS plus RECORD_TOKENS (the adjacency marks, digit runs of each rule's length, comment, preformatted, noscript and table tokens and quoted values). - Both rule tests call _assert_round_8_rule. Before the verdict, it checks that the readings made by functions both guards share agree on the drawn page: note_text (with and without comment marks), _rendered_text, the source split at every script or style, and the quoted values, whose head list begins with the fixture's. - No comparison exists for the browser readings, the head's browser scan of the source, its template literals and style strings, or the way record_bearing_note joins and reads the readings. The fixture has no counterpart for any of them. - The property alone catches RB3, RB4 and RB7, in seeds 0 and 7 in process. RB1, RB2, RB5, RB6, RB8 and RB9 pass it. Every RB mutant changes guard test pages: RB6 and RB8 fail number_sign_before_digit and identifier_in_noscript, and RB9 the 40-character window test. Low 4, this round's end-tag and opening rules. Record pages hold M1's form feed, M2's carriage return and M3's no-break space in a script's end tag, and M5's <scripts>, which an opening that checks no name end would read as a script whichever check item 1 used. Low 5, the timing test. Three long pages join it: - "<script>" * 50_000 + "</script>"; - "<script>x</script>" * 120_000, twice the brief's 60,000: at 60,000 T1 and T3 took 10.6 s and 9.6 s of CPU, about twice the 5 s bound; - "<!--<b>" * 50_000, the slow form of the view's comment without the end of the page (T14). In CPU-capped children: - T10 passed the 25 s limit on the first page, and T1, T3 and the view's list concatenation (T13) passed the 20 s limit on the second; - T14 passed it on the third, and a view searched past the last ">" (T15) passed it on unclosed_tags; - the head took 0.19 s, 1.02 s and 0.25 s, and at most 1.65 s on any of the 15 pages, against 1.55 s for d7442ef on the same loaded host. Notes. - N1: 7ae8edb's message overstated two counts. The head refuses 25 of the round-9 reviewer's 34 record probes, up from 16, not 26 up from 17. - N1: the round-10 report's claim that plain token lists found none of the four forms in 3,000 pages holds for its RULE_TOKENS list alone. Its 24-token list of the forms' chunks found X1, X3 and X5 first after 306, 101 and 526 pages; the comment above RULE_PARTS now says so. - N1: the comment in _browser_text now says the pattern captures names in ASCII letters only, so <ſcript> opens no element, and lower and casefold agree. The TAG comment and the notes say "an ASCII letter". - N2: no third pair of readings. Of the 91 pages that 16ea8c9 refused and d7442ef admits, the head refuses 4 and 085a33b refuses 0. html5lib shows a record on 3, all of them refused. - N4: the out-of-scope lists name S5 (other characters, such as fullwidth letters) and the review's other contrived forms that stay admitted: plaintext contents, a character reference glued to the name in xmp, svg and math markup, and a value split by a tag. This commit's checks found and named three more: hidden text, a "<?" instruction beside an empty comment, and markup a browser ignores in a select. The view now refuses the review's "<!-->", "<!--->", "<![CDATA[-->", "<!- -->" and noembed forms. - N3, N5: no change. - The lists also name a new form the rules refuse that holds no case record. A "-->" in a quoted attribute value, as in an arrow alt="Next -->", ends the tag in the browser view. Masking. The view refuses on its own the pages that pinned eight ported mutants of the browser text alone: X7, N3, N5, N7 and N10 of round 10's set and G74-G76 of round 9's. This round's C1a-txt and V13 have the same trouble. Seven record pages pin them. Six put those forms inside a comment or a noscript block, which only the browser text reads, and one puts a textarea after a comment, which only the view shows beside the identifier. Two round-8 twins (browser_text_lt_opens_no_tag, browser_text_title_contents) moved inside a comment for the same reason. Four new twins hold the view, its comment ends, its hidden contents and the opening's name end. Checks, in process (logs in d2-r11-fix/): - Pages: all 269 page entries behave as expected at the head (148 record, 37 definition, 42 twins), 52 of them new since d7442ef. d7442ef refuses none the head admits. - Probes: probe8 69, round 7 34, round-6 forms 6, fix pages 8, round 9's own 16 and same-row 16 give 0 parent-only and 0 d7442ef-only pages, with no verdict changed from d7442ef. The reviewer's 34 record probes: 25 refused. - Rule: over 100,000 pages each of fuzz_slice_r10's prescreen, fuzz8 and unicode token sets (seed 11), parent-only 0, 0 and 0. Over the review's oracle grammar, 205,000 pages (seed 11, and seeds 2-4 as in the review), the head admits no page 085a33b refuses, and nothing raised. - Record forms the head admits, by html5lib, over seeds 2-4: 446 hits in 330 forms, against the review's 846 in 611. Raw ">" in a quoted value 188, plaintext 91, glued xmp references 15, noscript comment marks 17, svg or math 12, select 4, "<?" beside an empty comment 3, a value split by a tag 1. All are named. - Departures: over 400,000 pages (the three token sets and grammar seed 11), the head admits 171 that d7442ef refuses, all from the grammar. 085a33b admits all 171. html5lib shows a record on 9: plaintext 6, raw ">" 1, noscript comment marks 1, svg 1. - Newly refused: the head refuses 518 pages that d7442ef admits. html5lib shows a record on 455. The other 63 hold a raw ">" in a quoted value (35), svg or math (9), plaintext (3), select (2), a tag left open at the end of the page (2) or a mix (12). - Stored captures: the head refuses 0 of 101, and so do d7442ef and 085a33b. - Twins: 42 of 42 isolate their rule or limit. - Mutants, prescreened: of 190, every one that is not timing-only changes at least one test page, apart from four: - X12r and N14, equivalent as in round 10; - G99, which the differential test's examples pin; - C1a-src, the browser source alone with \b, where the split at every <script also opens a script and no page found tells the two apart. - Lint: black -l 79 and ruff pass on both Python files, and git diff --check is clean. The host runs the rest: the whole test command, this round's mutants at seeds 0 and 7, the older sets at seed 0, the new tests against 085a33b's guard in seeds 0, 1 and 2, and the tier counts (d2-r11-fix/host_pass.sh). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The host pass at 955db50 found that the slower form T12 passes the timing test: it builds the quoted values by list concatenation, and no long page held scripts with strings in them, so the claim that T10-T15 each fail on their own page was wrong for T12. Add a page of 200,000 closed scripts that each hold a string, 4 MB. The guard reads it in 1.2 s of CPU time, and T12 in 15.7 s against the test's 5 s bound. At a tenth of T12's time the head stays well inside the bound. The guard is unchanged; the notes name the new form and the new largest size. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Round 11 approved 076e431 with six low findings and four notes. The rule still stands: the guard admits no page that 085a33b's guard refuses, since every change here is to the browser readings, which have no counterpart in that guard, and the new reading joins the text after a period, which neither identifier rule crosses. Low 2, round 10's forms inside noscript contents. No reading both left out comments and showed noscript contents. The text now has a fourth reading, the view with scripting off: BROWSER_VIEW_SCRIPTING_OFF is the view's pattern without noscript, and _browser_view takes the pattern as an argument. It refuses all 11 of the reviewer's noscript probes, the named <b--> form among them, so the out-of-scope clause on comment marks in noscript contents goes. Four record pages hold the forms. Round 11's matter 1 and Low 6, forms a browser shows: - Plaintext. A plaintext element now runs to the end of the page in the browser text and both views, as in a browser, and the views show its contents undecoded. Five record pages pin it, in all three readings at once and in each alone. The browser scan of the source does not change: plaintext there (PT7) changed no verdict on any test page or on 520,000 invented pages. - "<?" instructions. The views read one as a comment up to the next ">", and to the end of the page after the last ">", as a browser does. - NUL. The views drop a NUL from the text and show one in title, textarea, xmp and plaintext contents as U+FFFD, as html5lib does outside svg and math. - xmp contents. The views no longer decode them, as a browser shows them. - These close the reviewer's NUL, "<?", plaintext and xmp forms, so the clauses that named the "<?" form beside an empty comment, plaintext contents and a reference glued to a name in xmp go. - The double-escaped script and a template that a browser ends after the first </template> stay admitted: closing them needs a reading that tracks the script escape states or template nesting. The docstring and the notes name them, and plaintext joins the svg, math and select clauses, where a browser opens no plaintext element. - The split-value clause now names a plural name and other words before the value, as in PNUMs 10<b>1, which the fuzz found. - A new classifier puts each admitted form in one bucket, the first named cause whose removal ends the hit, so the buckets sum to the total. Low 1, rule-breaking mutants the pages missed. Record pages hold <!-- 12345678901234 -->, <img alt="PNUM\t7"> and <script>PNUM\n7</script>, so RN4 and RN6 now fail them. A third rule property builds records from an identifier, a separator, a value of 1, 3, 9 or 14 digits, plain or as references, and a wrapper, with RN4's and RN6's forms as examples. _assert_round_8_rule now also compares the tables and preformatted blocks the round-8 guard found and _identifier_column on each table, and its comment names them. Low 3, C1a-src. A definition page holds the reviewer's <script-x>x</script\x0b> page: html5lib shows the link's text and no slug, and the head admits it, while C1a-src refuses it. Low 4, the view's own rules. Record pages hold W3, W9, W18 and W19's forms after a comment. A new test, test_browser_views_read_invented_pages _as_stated, checks both views against 25 invented pages and the texts html5lib shows of them, written out, so it does not depend on BROWSER_VIEW; one, a nested template, holds the view's stated departure. Every mutant of the views' own rules changes one of them: W1, W3, W4, W8, W9, W16, W18 and W19, this round's PT1, PT3 to PT6, PI1 to PI3, NU1, NU3 and DX1 to DX3, and round 11's V2 to V14 as ported. Low 5 and N2, the timing test. Two pages join it: a script of 500,000 strings (2 MB) and 60,000 quoted values, comments and style strings (2.2 MB). The page of closed scripts with strings falls from 4 MB to 3 MB. In CPU-capped children on this host: - SF1 took 10.7 s, SF2 7.0 s and SF3 28.4 s, and SF4 passed 30 s; - T12 and SF6 passed 15 s on the 3 MB page, and SV1, the view with scripting off searched past the last ">", 15 s on unclosed tags; - the guard took at most 2.08 s on any of the 18 pages under Python 3.13 and 2.19 s under 3.14.7, both on the 3 MB page, against the 5 s bound. Notes: - N1: _browser_view's docstring now says that after a double-escaped script the view can open an element a browser never opens. The timing test's comment gives the measured 2.2 s and the closest slow form's 7.0 s, in place of "under 2 s" and "20 s or more". - N3: X12r and N14 are equivalent, and C1a-src is not; a search of 20,000 pages found a page that tells C1a-src apart and none for the other two. Found by this round's checks: - The view with scripting off masks three older mutants' pages, so record pages put N3's and G76's forms in a comment and RB8's comment text in a noscript block. - Three round-10 mutants, X6, N5 and N6, edited "</(?a:\1)" at run time, which the plaintext lookahead now splits; mutants_r12 ports them. - Five twins pin the new readings, 47 in all. Checks, all in process unless marked; logs in d2-r12-fix: - Pages: all 305 page entries behave as expected (171 record, 40 definition, 47 twins) and all 25 view examples. 076e431 refuses one new page the head admits, instruction_after_last_bracket, which html5lib shows no record on. - Probes: rounds 10 and 11's sets on this round's list, 253 pages, parent-only 0. Round 7's and 8's probe files are not on the list. - The rule: parent-only 0 over the three token sets (100,000 pages each), round 11's grammar (100,000) and the round-11 review's grammar (100,000, seeds 21 to 24), and 0 raised. - Admitted record forms over the review's seeds 21 to 23: 353 in 3,189 hits, against the review's 526 in 3,385: raw ">" in a quoted value 249, a value split by a tag 59, double-escaped scripts 23, template ends 18 and svg or math 4, none unexplained. - Departures: over the token sets and round 11's grammar (400,000 pages) the head admits 9 pages that 076e431 refuses, and 46 more over the review's grammar. 085a33b admits all 55. html5lib shows a record on one, a plaintext opening inside math, a named form. - Stored captures: the guard refuses 0 of 101, and so do 076e431 and 085a33b. - Twins: 47 of 47 isolate their rule or limit. - Mutants, prescreened: 235, none a no-op. Apart from the timing-only ones, each changes a test page or view example, but PT7, which changed no verdict on any page tried, RN3 and RN5, which the properties reach, and X12r, N14 and G99, as in earlier rounds. - Lint: black -l 79 --check, ruff check and git diff --check pass. Waiting for the host (host_pass.sh): the whole test command, this round's 45 mutants at seeds 0 and 7, the 190 older ones at seed 0, the 64 new or changed tests against 085a33b's guard in seeds 0, 1 and 2, and the tier counts. I started no pytest run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… bounds The host pass of d576600 showed three mutants the tests did not hold: - SF2 (attribute values added per tag by concatenation) passed the timing test on the host at both seeds, and SF1 (style strings added by concatenation) passed it at seed 0, because the shared page spent its budget on all three forms. Each now has a page of its own under 3 MB. On the host the guard reads each in under 1 s of CPU time, SF2 reads its page for about 35 s and SF1 reads its page for about 9.5 s. - RN3 (a wider year range) failed only when a property drew the right value. Two twins pin 1899 and 2100 against 1900 and 2099. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Text only. Both files' syntax trees match bc40837's, docstrings aside. Round 12 found the out-of-scope clause too narrow: a template's first end tag can also sit inside a comment, a <? instruction or raw-text contents, where a browser does not read it as one. The docstring and the notes now name that case in general terms. The refused list gains markup a browser ignores inside a select element or after a frameset opening, and references to control characters with or without a NUL. Three test comments overstated: two of the view's rules change no view example, the token lists hold a few character references, and the 2.2 s comes from one host run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Master's #573 (SSI0) and #574 (D4) each added a block to the birth-evidence exclusions, their expected tuple and the reachability test, where D2 adds its own. Keep master's blocks and put D2's after them in all three places. Both sides add the same empty tests/income_resources/__init__.py. The merge takes master's tier files, and the next commit recounts them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Master at 97003ac holds unit 23,653, artifact 4,527, integration_psid 1,471, reproduction_legacy 520, oracle_policyengine 337, total 30,508. D2 adds 183 unit and 415 artifact tests, so the files now read unit 23,836, artifact 4,942, total 31,106. CI's tier policy test checks the count on the full collection. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
marked this pull request as ready for review
November 6, 2026 09:50
Master's #583 (CE1) added a block to the birth-evidence exclusions, their expected tuple and the reachability test, where D2 adds its own. Keep master's blocks and put D2's after them in all three places. The merge takes master's tier files, and the next commit recounts them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Master at 02897ed holds unit 23,736, artifact 6,726, integration_psid 1,471, reproduction_legacy 520, oracle_policyengine 337, total 32,790. D2 adds 183 unit and 415 artifact tests, so the files now read unit 23,919, artifact 7,141, total 33,388. CI's tier policy test checks the count on the full collection. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
Author
|
I merged this PR at
|
MaxGhenis
added a commit
that referenced
this pull request
Nov 6, 2026
…nch's tests Master adds CE1 (#583) and D2 (#581), which change no Track B file. Master and this branch both add lines to scripts/first_estimates_birth_evidence.py and its test, and git keeps both sets. The tier files take master's counts plus the 2,735 unit tests this branch adds since 97003ac: 26,654 unit and 36,123 in all. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Round 13 approved
9e4849f9with no high or medium finding. The head,25057f4d, merges master02897edeinto that commit and recounts the tiers, and CI passes there. The note guard,record_bearing_note, refuses every page085a33b9's guard refuses across the 412,000 invented pages round 12's reviewer tried. It refuses none of the 101 stored captures, and each of its 49 twin pages isolates its rule or limit.What it adds
src/populace_dynamics/data/sipp_income.py:read_sipp_income_months, a person-month reader.usecols.quoting=csv.QUOTE_NONE), so it sees the same physical records as the layout validator.src/populace_dynamics/data/sipp_income_registry.py: canonical concepts and each release's Census definitions: labels, source and storage types, codes, ranges, universes, ownership level, period, corrections and user notes. It needs no network access at run time.data/external/sipp_income/: the evidence and its tooling..gitattributesmarks every file-text, so git stores the bytes the registry hashes, CRLF line endings included.tests/income_resources/test_sipp_income.py,test_sipp_income_evidence.pyandtest_sipp_income_refusal_properties.py.Concepts: we select 561, covering:
Verification sources: the Census variable API verifies the 2022–2025 releases. Its 2018–2021 endpoints return 404, so we verify each of those releases against its own dictionary and storage schema.
Each disagreement between sources carries a named ruling, or the registry generator refuses it:
source_rulings.jsonnames 13 domain rulings covering all 64 release-and-variable disagreements indomain_checks.json, with both sources' locations and intervals;User notes: the inventory lists 355 Census user notes and indexes. The branch stores 101 of them (93 notes and 8 indexes). Eight notes quoted individual survey cases, so the inventory keeps them as exclusions: their URL, title, release and variables stay, but not their bodies. The capture script refuses those URLs before any request. A guard,
record_bearing_note, refuses to store any new page holding a case record in any form it lists:The two rules that follow an identifier name read three things, all with entities decoded, apart from xmp and plaintext contents in the browser views:
<to the next>taken for a tag and each script or style element that an end tag closes left out, and once as a browser with scripting off reads it, where a tag opens only with an ASCII letter,!or/, an element's name, folded as ASCII, ends at whitespace,/or>, the reading leaves out script and style contents, and reads title, textarea and xmp contents as text, each up to</and its name followed by whitespace,/or>, or to the end of the page, and plaintext contents as text to the end of the page. The third and fourth times it reads the text as a browser with scripting on and with scripting off shows it: the same way, but with comments left out where a browser starts and ends them, at-->or--!>, with<!-->and<!--->empty, and<?instructions up to the next>; with iframe, noembed, noframes and template contents left out too, and with scripting on noscript contents, all but template contents read as raw text, as a browser reads them, so that a script opening inside one opens nothing; with xmp and plaintext contents not decoded; and with a NUL dropped from the text outside title, textarea, xmp and plaintext contents, where a browser shows it as U+FFFD;<in script code hides asrcassignment. It reads the source twice: once with those elements found where a browser starts and ends them, in one scan from the start of the page, so that a<scriptinside a quoted value opens none, and once with one starting at every<scriptor<style, even inside another tag;The guard reads the text and the source each more than one way because the browser's way, alone, would admit some pages that the first way refuses, and the text with comments kept reads comment text, which no browser shows, and noscript contents, which a browser with scripting on does not show. A tag opens with an ASCII letter,
!or/. The table and preformatted rules read each cell's or block's text without its tags; the row-header exemption also reads a header cell'sscopeattribute. The nine-digit rule skips comments and noscript blocks, whose tracking numbers are not page content. Each reading takes time linear in the page's length. A test times invented pages of 100 kB to 3 MB in the forms found to take quadratic time before (a long word in a tag, escaped quotes after an unpaired quote in a script, unclosed tags and comments, script start tags with no end tag, and table rows and cells that name an identifier) and in those where a slower form of a linear helper, found in review, does (a hyphenated word in a tag, unclosed tags after closed ones, script start tags with no>, after end tags or before one end tag, identifier rows after rows of digits, scripts that end tags close, empty or each holding a string, one script of many strings, many quoted attribute values, comments and style strings, together or the values and strings alone, and unclosed comments before tags).We leave these forms out of scope: a value before its identifier name;
<br>-separated CSV text without an identifier; div grids; an identifier name split by a tag or an invisible character, as inPN<b></b>UMorSS­UID, or written in other characters, such as fullwidth letters; text that a style or thehiddenattribute hides between an identifier and its value, since a browser hides it by its styles rather than as it parses the page; an identifier name and its value in different attribute values, script strings or style strings, or one of them in a string and the other in script code; a script string after a lone quote mark in a comment, a regular expression or a template literal, which the scan of double- and single-quoted strings takes to open one, as in a comment such as// it's; an identifier and its value split by a tag, quote or equals sign in script or style code outside a quoted string, as in a comparisonPNUM < 101or markup in atext/templatescript, or in an unquoted attribute value, as inalt=PNUM's-101; a value inside a tag after an identifier in the text, as inPNUM <i 101; a run of digits split by a tag, which the readings count as a space, after a mark the adjacency rule does not allow, a plural name or other words, as inPNUM >11<th>7orPNUMs 10<b>1; a script that a<!--and a<scriptinside it double-escape, which a browser runs on past its first</script>, as in<script><!--<script>.</script> . </script>between an identifier and its value, where every reading ends it at that end tag and shows the period; template contents that a browser ends after the first</template>, which the views take to end the template, in a template nested in another or wherever a browser does not read that end tag as one: inside a tag, as in<e</template>, a comment, a<?instruction or raw-text contents; markup inside svg or math, where a browser reads a CDATA section as text and the name of a raw-text or plaintext element as an ordinary element's; markup that a browser ignores inside a select element, such as a style, noembed or plaintext opening; nine digits after a comment closed by--!>, which the nine-digit rule reads as still open; a quoted attribute value in an end tag or a<!declaration, or after a name with marks other than_ : . -, as in[alt]; an attribute value that holds a raw>, which ends its tag; a value in an href or src value, unless it is a run of 14 or more digits; and a cell outside a table's first row and header cells that names an identifier after other words.The rules in turn refuse some pages that hold no case record, and such a page stops the capture loudly:
SSUID. Values start at 101.or an index rowSSUIDs. See 112 notes.;The SSUID's format in the 2018 panel, as 112 notes say;`{"name": "SSUID", "pages": "112"}`, since the rules read a template literal whole;ssuid-2024in a script string or atext/templatescript, or in anxlink:href,:hreforimg.srcvalue: the source reading removes those values as link targets, but the quoted-value reading skips only values named href or src;<a href="<script src="/ssuid-2024.js">: the browser scan of the source removes the href value, which closes at the quote mark before the slug, and reads the slug;PNUM < 101in the visible text;-->in a quoted attribute value, as in an arrowalt="Next -->", after an identifier and before a value in the value's rest, as inPNUM<img alt="--> 7">: the browser views end the tag at that>and read the rest of the value as text;<plaintext>tag inside a comment or inside iframe, noembed, noframes or template contents, which the text with comments kept takes to open plaintext there, as in<!--<plaintext>PNUM<e101>; character references in plaintext contents, which that text decodes, as in<plaintext>PNUM<!101>; a plaintext or xmp opening or a NUL inside svg, math or select, or a NUL after a frameset opening; other markup that a browser ignores inside a select element or after a frameset opening; a reference to a control character, such as, which Python'shtml.unescapedrops; an empty end tag</>, which a browser drops and the readings count as a space, as inPNUM</>a567; and a page that ends inside a tag, whose rest a browser drops, as in<a/b="><plaintext><PNUM>101.A decimal character reference of more than 4,300 digits makes Python's
html.unescaperaise, which stops the capture too.Invariants
Only a verified release, concept, source type and value domain may enter. Every verified source must admit a value, apart from the API's documented missing sentinels.
A domain on which sources disagree enters only under an exact, cited, settled ruling.
One input person-month yields one output row, in input order. A quote never joins two physical records, and a carriage return never splits one: the reader yields one row per LF-delimited data line, or refuses. The reader refuses a malformed layout.
Person identifiers stay strings, stable within a panel across months, waves and releases.
Source codes and weights pass through unchanged. The reader does no household or joint allocation and no annualization.
The corrected 2018–2021
TSSSAMTrequires a file downloaded on or after Census's 2025-07-24 correction.Replicate joins need verified, unique, complete keys and matching base weights.
We use each release's own metadata. The frozen tables reproduce the hashed evidence without network access.
No stored page shows a form
record_bearing_noterefuses.The guard still makes every reading the round-8 guard (
085a33b9) made, with the same result, and only adds readings to them, so it admits no page that guard refuses.tests/income_resources/fixtures/capture_user_notes_085a33b9.py.txt, with a test that pins its sha256). One draws pages from the parts of the round-9 review's forms. One draws lists of invented tokens, those of the differential property plus record tokens (adjacency marks, digit runs of each rule's length, comments, preformatted, noscript and table blocks, quoted values). The third builds a record from an identifier or none, a separator (each adjacency mark, a tab, a line end, or:), a value of 1, 3, 9 or 14 digits, plain or as decimal or hexadecimal references, and a wrapper that puts it where one reading or rule reads it._identifier_columnon each table. The browser readings and the way the guard joins and reads its readings have no counterpart there, so only the verdict covers them.The guard reads a page in time linear in its length: a test reads 20 invented pages of 100 kB to 3 MB, one in each form that the earlier guard or a slower helper read in quadratic time, in under 5 s of CPU time each. The guard took at most 2.08 s on the first 18 under Python 3.13 and 2.19 s under 3.14.7, both on the 3 MB page, and under 1 s on the other two under 3.13.
Each guard rule, and each limit on what the identifier rules read, has a minimal invented page and a twin that differs only in what it reads (49 pairs): disabling the rule admits its page, and dropping the limit refuses its twin. Invented record and definition pages pin the exemptions, the bounds on link-target removal, and each path that only one of the readings takes, for the forms the reviews found.
Each mutant in these sets fails a test, apart from those named as changing no result:
16ea8c94, and at seed 0 atd7442ef5, and ported, at955db507and atd576600f;7ae8edbf, and ported, at seed 0 at955db507and atd576600f;955db507, and T12 in seeds 0 and 7 at076e4310and, ported, at seed 0 atd576600f;d576600f, and SF1, SF2 and RN3 in seeds 0 and 7 atbc408371.Q1-Q7, G82-G89, T1, T3, T10-T15, SF1-SF4, SF6 and SV1 each fail the timing test on their own page. X12r (casefold for lower) and N14 (an end tag with no
>ends nothing) give the head's result on every page: the browser readings' names are ASCII, which casefold and lower fold alike, and the first text reading reads any text after the last>as it stands. PT7, plaintext added to the browser scan of the source, gave the head's verdict on every test page and on 520,000 random invented pages, but one page tells them apart: the head's scan reads plaintext contents as tags, so it refuses<plaintext><script-x><a PNUM href="." 101>, which holds no record, and PT7 admits that page, as085a33b9does. C1a-src (the browser source alone with\b) differs from the head: the definition page<script-x>x</script\x0b><a href="/notes/pnum-101.html">Person number</a>tells it apart. Atd576600f, SF2 passed the timing test in both seeds, SF1 passed it at seed 0, and RN3 failed only at seed 0, through a property.bc408371answers all three, as the Round 11 entry says.Each ruling member's PDF citations, with a page or without, match its dictionary entry's pages one for one, each as
{year}_dictionary.pdf#page={page}.Each invariant has a Hypothesis property or an example test; until round 10, the rule that the guard admits no page
085a33b9's guard refuses had neither. The domain rule and Census's own crosswalks give differential tests.Open questions
Each of these refuses the affected concepts;
refused_concepts.jsonandsource_rulings.jsonlist every case.ESSSMNYN, 2018–2020): it has no verified codes. Annual receipt and amounts remain.ESSI_BRSN, 2021–2022: the category order conflicts.TDIS6AMTandEDIS8MNYNconflict.TSSI_ERSNandEBOATOWNER3lack value codes, and the 2021 interview address identifier has an inverted printed range.Tests
Counted by collection over the three test modules:
All 598 pass locally with two workers at
0f016a81,b9f66c46and25057f4d, and so do 12 of the 13 birth-evidence seal tests. The other, the reachability test's track-U assertion, needs modules this sparse clone leaves out; the D2, CE1, D4 and SSI0 blocks before it pass. CI runs that test and the U2 isolation tests. At0f016a81, CI run 41358633577 reported 19,847 unit tests against a manifest count of 19,664 and 4,686 artifact tests against 4,271; the other three tiers matched. At9e4849f9, after the recount, CI passes, the tier test included: run 41623422531's four pytest shards report 30,005 passed, 1,116 skipped and 1 xfailed. At25057f4d, after the second recount, CI passes, the tier test included: run 42204606713's four pytest shards report 32,287 passed, 1,116 skipped and 1 xfailed.Review
Round 1 stopped before it finished, for a reason unrelated to the code.
Round 2 (fresh, at
1f51b60a): REVISE, with one high and two medium findings.Fix (
eb77fc19):QUOTE_NONE, with a minimized regression and a quote property;The regenerated concept, definition, release, replicate, correction and variable-to-note tables match
1f51b60a's. The note table keeps all 101 entries: the eight exclusions have an empty body path and the statusexcluded_record_bearing. The evidence pins lose the eight bodies and change only forsource_rulings.jsonanduser_notes_manifest.json.Round 3 (delta, at
eb77fc19): REVISE, with two medium and two low findings.THEQ_BUSruling misdescribed the dictionary's printed range.Fix (
7521c6d8):_check_layoutstrips one LF, then one CR, and refuses any other carriage return. Tests add the review's minimized regression, a CRLF file and a carriage return in the quote property's alphabet;THEQ_BUSreason now says the dictionary prints a malformed upper bound and a lower bound that differs from the API's. The fix regenerates the pin ofsource_rulings.jsonand changes no other table;Round 4 (delta, at
7521c6d8): APPROVE, with seven low findings and four notes.<br>CSV text and div grids; those stay admitted and out of scope.)Fix (
04a2b89a):.pdfcitation, and each damage case must fail at its own check;THEQ_BUSreason, the reader's docstring and the notes. Only thesource_rulings.jsonpin changes in the registry.17 of the 129 evidence tests fail against
7521c6d8's guard, and the tests catch all 16 mutants. Every stored note still passes. (Round 5 corrected four claims in this fix's message: the eight twins covered five rules and three readings, not every rule; the 16 mutants had two for the window width and none for the digit-below rule or the row-header and definition-table exemptions; onlypageless_pdfpasses generation under the parent check, whilepageless_other_release_pdfstops on a file missing from the invented folder; and 14 of the 16 invented record pages, not all, carried the invented SSUID. The heading correction also needs "that is not a year".)Merge (
ffc4d485):origin/masterat1ec57a5d(D1a, PSID income and wealth readers and field registry (D1a) #575). The birth-evidence check keeps D1a's exclusions and reachability assertion, then D2's.Round 5 (delta, at
ffc4d485): APPROVE, with five low findings and five notes.Fix (
c1a3c7b6):<or>between an identifier name and a value admitted the page. The window there now stops only at a period, as the round-3 rule meant ("within 40 characters of the same sentence"); the source reading still stops at tags. A twin pins it, 18 pairs in all.With
ffc4d485's guard, 9 of the 153 evidence tests fail, the same 9 in each of three Hypothesis seeds. The tests catch all 32 guard mutants in seeds 0 and 7, each of the 18 twins isolates its rule or limit, and every stored note still passes. (Round 6 corrected two claims in this fix: the 18 twins did not cover the heading-cell rule, each mark that stops the source window alone, unquoted href and src link targets, or adjacency in the text alone; and only this body, not the docstring, put the other L5 forms out of scope. The parent already admitted two of the "now admitted" definition pages,tracking_number_in_link_targetandrow_header_outside_definition_table.)Merge (
60b67f82):origin/masteratd8302233(SM1, SM1: differential mortality by lifetime earnings, education and race (normalized within age-sex-year cells) #570). It has no conflicts; git auto-merged the birth-evidence check and its script, which both branches changed.Round 6 (delta, at
60b67f82): APPROVE, with three low findings and four notes.srcassignment from the source reading; four wording corrections; the guard now refusesPNUM > 100.Fix (
c8dfe4f1):!or/, so a comparison in a script no longer hides asrcassignment;With
c1a3c7b6's guard, 2 of the 165 evidence tests fail, the same 2 in each of three Hypothesis seeds: the two that pin this fix's code changes. The tests catch all 44 guard mutants in seeds 0 and 7, each of the 26 twins isolates its rule or limit, and every stored note still passes. (Round 7 corrected two claims in this fix: a minified comparison, a CDATA marker ora</bin a script still hid asrcassignment, and the tests pinned the bounds on link-target removal only against a<followed by a space or digit.)Merge (
695798ed):origin/masterat0f69bbb2(OP1, OP1: open-population harness around the sealed loop #566, and its report fix, Fix review r10's report findings for OP1 #589). It has no conflicts; git auto-merged the birth-evidence check and its script, which both branches changed.Round 7 (delta, at
695798ed): APPROVE, with four low findings and four notes.<followed by a letter,/or!in a script still opened a "tag" whose href and src values the guard removed, so a minified comparison, a CDATA marker ora</bhid asrcassignment.Fix (
6e96c64d):With
695798ed's guard, 26 of the 201 evidence tests fail, the same 26 in each of three Hypothesis seeds: the ones that pin this fix's code changes. The tests catch all 67 guard mutants in seeds 0 and 7; this fix's own checks found four of them unpinned, and record pages now pin them. Each of the 33 twins isolates its rule or limit, the guard admits no page the parent guard refuses over the test pages, the review's probes and round-6 forms, and 2 × 100,000 random invented pages (round 8 found one that it admits:<a href="<script src="PNUM=101">), and every stored note still passes.Merge (
085a33b9):origin/masterat172f690f(Held-out data registry: round 7's follow-ups (unset event path, record ids, zero push boundary) #580 and the commits before it). It has no conflicts and changes no D2 path.Round 8 (delta, at
085a33b9): APPROVE, with four low findings and five notes.<scriptinside a quoted value, so the guard admitted<a href="<script src="PNUM=101">, which the parent refused.text/templatescripts, style strings, a raw<in visible text, textarea and title contents and an unquoted attribute value admitted record forms that no list named.Fix (
c501f04d), under one added rule, that the guard may admit no page085a33b9's guard refuses:>; the guard skips a script or style opening that no end tag of its name follows; comment and noscript removal stop at the last end tag; and the table rules read each row and column once. A differential property checks each helper against its plain pattern, and a timing test reads seven 200 to 600 kB pages, one in each form that took quadratic time before;<a href="<script src="PNUM=101">; the earlier reading stays, so the guard admits no page that reading refused;PNUM < 101,PNUM <- 101andPNUM: <101>in visible text, the review's textarea and title forms and an xmp form; it reads template literals in scripts and quoted strings in styles alone;text/templatemarkup, an unquoted attribute value, a value inside a tag, and attribute values in end tags, declarations or after bracketed names) out of scope, with a script string after a lone quote mark in a template literal; it names the newly refused definition and index forms and the href and src asymmetry among the pages the rules refuse;(?i)reads with a long s or a dotted or dotless i: the text reading raised on<SCRİPT>x</script>, and the script-string reading admitted a page the parent refuses. Both now match round 8's on every such spelling, on Python 3.10 to 3.14;With
085a33b9's guard, 26 of the 171 guard tests fail, the same 26 in each of three Hypothesis seeds: the ones that pin this fix's code changes (13 record pages, 5 twins, the 7 long pages and the differential property). The tests catch all 105 guard mutants, the review's ten among them: 104 in seeds 0 and 7 atc501f04d, and G89, which gives the same results in quadratic time, in both seeds at16ea8c94. That commit enlarges the timing test's row to 60,000 identifier cells (780 kB), and correctsc501f04d's message, which said the timing test alone pinned 8 quadratic mutants; it pinned 7. G82 to G88 still fail it in seed 0. Each of the 38 twins isolates its rule or limit. Over the test pages, both reviews' probes and 1,200,000 random invented pages, the guard admits no page the parent guard refuses, and every stored note still passes. (Round 9 corrected six claims in these commits: the differential property left out the attribute pattern and the table rules; O1, O3 and O5, ported to the split alone, survive; both guards refuse F6, the<b>form of F3, but085a33b9admits F3; round 7's fix had 8 pages, not 7; the 458 tests include the 12 birth-evidence tests; and16ea8c94also rewrote the timing test's comment.)Round 9 (delta, at
16ea8c94): APPROVE, with four low findings and six notes.085a33b9's guard refuses, and mutants that break it, of the split alone and of template literals, passed every invented page._finditer's reliance on(?s); the exact test command outlasts one shell call.Fix (
7ae8edbf, andd7442ef5for one passage of the notes), under the same rule:085a33b9's guard sits in the test tree as text, out of collection and out of the tier classifier's reach, and a Hypothesis property asserts that the guard refuses every page the copy refuses. It draws pages from the parts of the review's forms with invented tokens between them; its explicit examples and four record pages reproduce the review's X1, X3, X5 and X9. The differential property also checks the attribute pattern and the table rules;</and its name followed by whitespace,/or>;shown()compares names in lower case. They now refuse E1, E2, E4, U1, U4 and L1-L4, and record pages hold them. The ASCII flags cover only those parts, since a global one would also change\b;16ea8c94. Of 400,000 random invented pages, the guard admits 91 that16ea8c94refuses, each of which085a33b9admits too, where16ea8c94departed from a browser: it read a<SCRİPT>or<scrıpt>element's contents as raw text, ended a script at</scrİpt>, or took<ſfor a tag;-->, which this fix's checks found; they name D8 and F2 among the pages the rules refuse, and_finditer's docstring names its reliance on(?s).With
085a33b9's guard, 25 of the 38 new or changed tests fail, the same 25 in each of three Hypothesis seeds: 18 record pages, the six long pages and the differential property, which calls_finditer. The other 13 pass: the four record pages of forms that guard refuses itself, the seven definition pages, which pin mutants that refuse more, the rule property, which holds for the guard it names, and the fixture's pin. Of this round's 35 mutants, 33 fail a test in seeds 0 and 7, and the other two change no result; all of round 9's 105, rerun at seed 0 atd7442ef5, fail a test. Each of the 38 twins isolates its rule or limit. Over the test pages, the probes of rounds 6 to 9 and 400,000 random invented pages, the guard admits no page the parent guard refuses, and it refuses none of the 101 stored captures. (Round 10 corrected three claims in7ae8edbf's message: the guard refuses 25 of the round-9 reviewer's 34 record probes, up from 16, not 26 up from 17;<ſcript>stays text because the ASCII-scoped name never capturesſ, so casefold and lower agree on every name, not because lower keeps it apart; and the claim that plain token lists found none of the four forms in 3,000 pages holds for one list alone, since a 24-token list of the forms' chunks found X1, X3 and X5 first after 306, 101 and 526 pages.)Round 10 (delta, at
d7442ef5): APPROVE, with five low findings and five notes. The rule held over 105,000 pages of a tokenizer-edge grammar, and085a33b9refuses none of the 91 pages that16ea8c94refused and the head admits.\bafter a browser element's name departs from a browser, and accounts for one of the 91 pages.7ae8edbf's message and the token-list claim; no third pair of readings for the 91 pages; timing-test robustness (no change); S5 and other contrived forms unnamed; the notes-only commit holds (no change).Fix (
955db507), under the same rule:/or>, so<script-x>,<script.x>,<scripts>and the other forms the review listed open no script or style. Record pages hold seven forms, one for each mark another check of a name's end would pass;>, and iframe, noembed, noframes, noscript and template contents hidden. The reading that keeps comments still reads noscript contents, so<noscript>PNUM <b>101</b></noscript>stays refused. The source reading needs no such change: a script a browser would not open there hides no text from it, and reading those elements as raw text would read their tags' link targets. Record pages hold the review's six pages and 13 more, and the view also refuses the review's<!-->,<!--->,<![CDATA[-->,<!- -->and noembed forms;#,[,'and(before a digit and a noscript block. By itself, the property catches RB3, RB4 and RB7 in seeds 0 and 7; every RB mutant changes guard test pages;076e4310adds a sixteenth page, 200,000 closed scripts that each hold a string (4 MB). The host pass at955db507showed that T12 passed the timing test, because no page held scripts with strings in them, though the draft of this body said it failed. The guard takes 1.2 s on the new page and T12 15.7 s. That commit's message calls 1.2 s a tenth of 15.7 s; it falls short of a tenth, at about a thirteenth;-->in a quoted attribute value.Over the test pages, the probes of rounds 6 to 9 and 400,000 random invented pages, the guard admits no page the parent guard refuses. It admits 171 of those pages that
d7442ef5refuses, all of which085a33b9admits; html5lib shows a record on 9, each a named form. Over the round-10 review's grammar seeds 2 to 4, it admits 217 more pages thatd7442ef5refuses;085a33b9refuses none of them, and html5lib shows a record on 5, each a named form. Over those seeds, the record forms it admits fall from 611 to 330. It refuses none of the 101 stored captures, and each of the 42 twins isolates its rule or limit. With085a33b9's guard, 47 of the 58 new or changed tests fail, the same 47 in each of three Hypothesis seeds (the timing part at076e4310, the rest at955db507). The 58 count the fixture's pin, which neither commit changed. The other eleven pin what that guard already does: five record pages, two definition pages, three long pages and the fixture's pin. Of this round's 50 mutants, 48 fail a test in seeds 0 and 7 at955db507, T12 fails its new page in seeds 0 and 7 at076e4310, and C1a-src passes every test. Of the 140 ported mutants, 138 fail a test at seed 0, and X12r and N14 give the head's result. (Round 11 corrected three claims in this entry and the commits: the entry and the commits did not name every record form that stays admitted; a page tells C1a-src apart from the head; and 1.2 s comes to about a thirteenth of 15.7 s, not an eighth.)Round 11 (delta, at
076e4310): APPROVE, with six low findings and four notes. The rule held on every page the reviewer tried, among them 88,000 pages of a new grammar and 60,000 drawn pages._identifier_columnleft out of the rule's comparison, seeds 2 to 4's 217 departures); the 4 MB page cut the timing margin to about 1.55×; X12r and N14 give the head's result on every page and C1a-src does not;076e4310holds (no change).Fix (
d576600f), under the same rule:<b-->form among them, so that out-of-scope clause goes. Record pages hold four of them;<?instruction as a comment up to the next>, drop a NUL from the text and show one in title, textarea, xmp and plaintext contents as U+FFFD, and show xmp contents undecoded, as html5lib does outside svg and math. These close the review's NUL,<?, plaintext and xmp forms, and the clauses that named some of them go;</template>stay admitted, since closing them needs a reading that tracks the script escape states or template nesting; the docstring, the notes and this body name them;<!-- 12345678901234 -->,<img alt="PNUM\t7">and<script>PNUM\n7</script>, so RN4 and RN6 fail them. A third rule property builds records from their parts, with RN4's and RN6's forms as examples, and the rule's shared check also compares the tables and preformatted blocks and_identifier_column;Over the test pages, rounds 10 and 11's probes, 300,000 token-set pages, 100,000 pages of round 10's review grammar and 100,000 of round 11's, the guard admits no page the parent guard refuses. It admits 55 of those pages that
076e4310refuses, all of which085a33b9admits; html5lib shows a record on one, a plaintext opening inside math, a named form. That count covers the builder's sets; round 12's grammar finds 14 more, listed under round 12. Over the round-11 review's seeds 21 to 23, it admits 353 record forms in 3,189 hits, against the review's 526 in 3,385, and a classifier that puts each form in one bucket, by the named cause whose removal ends the hit, explains all of them: a raw>in a quoted value 249, a value split by a tag 59, double-escaped scripts 23, template ends 18, svg or math 4. It refuses none of the 101 stored captures, and each of the 47 twins isolates its rule or limit. With085a33b9's guard, 53 of the 64 new or changed tests fail, the same 53 in each of three Hypothesis seeds. Of this round's 45 mutants, 41 fail a test in seeds 0 and 7, and of the 190 ported mutants, 188 fail a test at seed 0; X12r and N14 give the head's result. PT7 gives the head's verdict on the builder's test and random pages; round 12 gives a definition page that tells them apart. SF1, SF2 and RN3 led to the next fix.Fix after the host pass (
bc408371), tests only:SSUID in 1899againstSSUID in 1900pins that floor, andSSUID in 2100againstSSUID in 2099pins the ceiling.SF1, SF2 and RN3 each fail in seeds 0 and 7 at
bc408371.Round 12 (delta, at
bc408371): approved, with no high or medium finding, four low findings and six notes. No page that085a33b9's guard refuses gets past the head, over the test pages, 412,000 pages of the reviewer's grammar and every probe. The head refuses none of the 101 stored captures, all 49 twins isolate, and the parent check reproduces. Load stopped 16 of the 20 chosen builder mutants in the review; the builder's host logs show 42 of 45 caught at each of seeds 0 and 7.A review's exit rule now applies. A finding that only invented inputs reach, with zero effect on pinned inputs, stays as a stated limit. A regression, a falsified claim, a changed record on a pinned input, or a misread real rule still gets a fix or a narrowed claim.
0f016a81narrows the claims round 12 falsified, in text only: the guard's and the test module's syntax trees matchbc408371's, docstrings aside. This body narrows the same claims.Stated limits, one line for each form:
!or?, exempting an exact identifier in a definition table's first row, and requiring a digit after an identifier in a preformatted block (RR4, RR5 and RR22).SCRIPT,STYLE,TABLE,PRE,ELEMENT,ROWandCELLread withfinditer, and the mark regex without its lookbehind. Each ran past 20 s on its own page under 3 MB, where the head takes under 0.6 s.<p>PNUM <template><!--</template>-->.</template> 101</p>.076e4310refused: 14 pages of the reviewer's grammar, all plaintext inside svg or math, and each sits in a named clause, and085a33b9admits them all.<template><e</template>Ssuid<noscript>.</noscript><?>1.Merge turn (
b9f66c46,9e4849f9):b9f66c46merges master97003ac2and with it Federal SSI interface and source-to-input contract (SSI0) #573 (SSI0) and Aggregate-table captures and readers, part 1 (D4) #574 (D4). Each had added a block to the birth-evidence exclusions, their expected tuple and the reachability test, where D2 adds its own. The merge keeps master's blocks and puts D2's after them, so the exclusions and the expected tuple list the same 221 paths in the same order. Both sides add the same emptytests/income_resources/__init__.py.9e4849f9recounts the tiers on97003ac2: master's 30,508 tests plus D2's 183 unit and 415 artifact make unit 23,836, artifact 4,942, integration_psid 1,471, reproduction_legacy 520 and oracle_policyengine 337, 31,106 in all.From
0f016a81to9e4849f9, 339 paths changed: the two tier files, the two birth-evidence files and 335 other paths that master changed since172f690f. All 335 match master's blobs, and none of D2's other paths moved.Round 13 (delta, at
9e4849f9): approved, with no high or medium finding, four low findings and two notes, all on this body's wording. The reviewer replayedresolve.pyand the merge proof to the same bytes and found no path outside the four merge exceptions that differs from both parents. The two Python files0f016a81changed matchbc408371's syntax trees, docstrings aside. The reviewer's own collection gives 183 unit and 415 artifact tests. With host load at 147, the reviewer skipped the other three tiers, where the host collections add none and CI counts them all.!or?limit described RR4's mutation as the head's rule; the head's window ends only at a period.0f016a81narrowed.Body update (no commit; the head stays
9e4849f9): this body takes the review's wording for all four lows and drops the reviewer's model from the round 12 entry. The folder's.gitattributesreads* -text, so "every file" stands.Merge turn on
02897ede(2ca74c50,25057f4d):2ca74c50merges master02897edeand with it Coverage-rule registry (CE1) #583 (CE1), which added a block to the birth-evidence exclusions, their expected tuple and the reachability test, where D2 adds its own. The merge keeps master's blocks and puts D2's after them, so the exclusions and the expected tuple list the same 222 paths in the same order.25057f4drecounts the tiers on02897ede: master's 32,790 tests plus D2's 183 unit and 415 artifact make unit 23,919, artifact 7,141, integration_psid 1,471, reproduction_legacy 520 and oracle_policyengine 337, 33,388 in all.From
9e4849f9to25057f4d, 272 paths changed: the two tier files, the two birth-evidence files and 268 other paths that master changed since97003ac2. All 268 match master's blobs, and none of D2's other paths moved. Each birth-evidence file holds master's text plus the lines D2 inserted from97003ac2to9e4849f9and nothing else, and runningresolve.pyon a freshgit merge-treereproduces both byte for byte.The eight removed bodies remain in this branch's earlier commits. A squash merge keeps them out of master's history.
Status
0482dc31and5bdd595bhold the later attempts' edits.1f51b60alists the two reader modules among the birth-evidence check's post-review exclusions;dac0d5f9,ffc4d485,60b67f82,695798ed,085a33b9,b9f66c46and2ca74c50merge master, and9e4849f9and25057f4drecount the tiers.2ca74c50or25057f4d. The coordinator accepted the merge proof above in place of a delta review under four conditions, and reran it at25057f4d.Data
We downloaded no SIPP microdata, opened none and computed no statistic from it, because we will hold a SIPP release out for the SSI gate. Tests use invented records and committed metadata.
axiom: n/a: survey-file readers and metadata registry for the microsim; no PolicyEngine country-model or RuleSpec encoding changed
🤖 Generated with Claude Code