Repository navigation
Federal SSI interface and source-to-input contract (SSI0) - #573
Merged
Merged
Conversation
Plain-request captures of the SSI legal sources, the certified PolicyEngine release metadata and the PyPI records of every installed distribution, each with URL, retrieval time, size and SHA-256 in its manifest. A folder-level .gitattributes stores the bytes as fetched. Built by a Subfleet build lane in a standalone clone; committed by the coordinating session. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The static inventory of federal SSI variables, parameters and inputs in the certified PolicyEngine release, and contract ssi0-v1 mapping each of its 41 engine inputs and 12 context rows to PSID, SIPP and Microcosm sources. Both are reproduced by the scripts added here; unmapped inputs refuse. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Typed records, input validation, the runner that admits or refuses each case with counted accounting, and a separate-interpreter worker that calls only the public PolicyEngine interfaces of the pinned release. Unit tests use invented records; the oracle tests run only when POPULACE_DYNAMICS_PE_US_PYTHON_SSI0 names the pinned interpreter. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
The pin hashed each primary distribution's whole RECORD, whose console-script entries carry the interpreter's own path in their shebangs, so the same release installed anywhere but the build's temporary path was refused. Hash only the entries inside site-packages, in both the child check and the pin script, and record the new digests (identical for the build's interpreter and ~/.venvs/policyengine-py-6.10.2). Two properties: the digest ignores entries outside site-packages and changes with any package entry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
black and ruff read every .py file in the repository, so the pinned copy of policyengine-us 2.2.1's ssi_if_takes_up.py failed the lint job. Rename the capture to .py.txt and update the two capture manifests and the captured-sources table. Its bytes, size and SHA-256 are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The SSI interface is opt-in, and nothing in the historical projection imports it. List its twelve source files, the package data included, as post-review exclusions in the birth-evidence script and its expected tuple, and assert that none of its modules is reachable from the birth-evidence reducer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A pooled worker calculation that failed copied its error to every request in the pool. So one invalid case refused every valid case pooled with it (review round 2). The worker now reruns each case alone after a pooled failure, through the same path a batch of three or fewer uses, and only a case that fails alone reports an error. The inventory now reads each enum variable's member names from the pinned source, and the contract row for immigration_status carries them. The contract admits an enum input only when it names a member. An invalid name therefore refuses its own case as INPUT_CONTRACT_GAP before any calculation instead of reaching the engine and counting as RULES_ENGINE_GAP. Invariants, each with a property test on invented data: - a case's outcome does not depend on which other cases share its batch; - an enum input is admitted exactly when it names a pinned member; - an enum input whose members cannot be read refuses the inventory. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review round 3 approved 48a7198 with one low finding: that commit's message said every listed invariant had a property test, but the inventory's refusal of an enum input with unreadable members had only one fixed example. Two Hypothesis properties now cover the extraction: - generated member lists round-trip from an invented enum class; - an enum input whose possible_values names an absent class, an empty enum or a class that is not an Enum always refuses the inventory. Each fails when the extraction lowercases its names or the refusal is removed. Test-only; no source or generated file changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 25, 2026
The inventory read an enum input's members from every plain assignment in a same-named Enum class. Three gaps let it disagree with Python: - annotated, tuple, private and _sunder_ targets, non-literal values and nested classes were dropped or admitted without regard to Enum's own rules; - the first class definition won, whatever else the module bound to that name; - the default was never checked against the members. None affects the pinned release: its three enum classes use plain string assignments, their defaults are members, and the regenerated inventory, contract and decision table are byte-identical. enum_members now returns None, so the inventory refuses the input, unless the module binds the name once, the class subclasses Enum alone with no decorators or keywords, and its body holds only a leading docstring, pass, methods and assignments of a string or integer literal, or an earlier member, to public names, each named once. An enum whose default names another class or no member stays unresolved. Invariants and tests: - Whatever the reader admits, Python's Enum defines identically (a Hypothesis differential over invented class bodies against enum.Enum). With the old reader it finds `INVENTED_A: str = "invented_a"` read as no members, and `_INVENTED_A = 0` admitted. - The admitted forms with at least one member are always read. - Refused forms, second bindings, other bases, decorators, keywords and the name mro are never read. - A default outside its own class's members refuses the inventory. - Oracle: each committed enum record, in both the input and variable lists, matches its class executed from the pinned source under the pinned release's own Enum, and the source hash matches. Dropping one member from either list fails it. Tests: 100 passed and 9 skipped (lane, seal, U2); the 9 oracle tests pass on the pinned interpreter. Unit 83 (12 new), oracle 9 (1 new). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The round-4 review found that the reader's claim, that Python's Enum defines whatever it admits the same way, failed for plain static forms: - methods were skipped as non-members, but a decorator can make one a member and an __init__ hook can drop members; - the binding count read only top-level statements, so a class in an if block, a walrus, a match capture, a global declaration in a function or class, a guarded or aliased import, or a star import after the class rebound the name unseen; - the variable's own body was never checked, so a second binding of possible_values, or a rebinding of the class inside the body, changed the class the engine sees; - an alias passed into the contract, although the engine's Enum.encode looks names up by iterating the class, which yields canonical names only; - Enum was matched by spelling, so a module-local Enum could change membership. Writing the fix turned up a further gap: module code could reach the variable itself, through an attribute store such as invented_status.possible_values = Other, a decorator, or a rebinding of the variable's name. None of these affects the pinned release. Its three enum modules import only the model API, their classes hold plain string assignments, and the regenerated inventory is byte-identical. The reader now: - counts every binding site of a name in any scope: assignments of each kind, imports, definitions, parameters, except and match captures, type parameters, del, global and nonlocal declarations, and attribute stores. The class must be the only one, a top-level class defined before its variable; - requires the variable to be its name's only binding, to subclass Variable alone with no decorators or keywords, and to bind value_type, possible_values and default_value once each by plain assignment, with no attribute store to those names in the module; - refuses a module that imports anything but the model API's star import before the class, binds Enum, names exec, eval, compile, globals, locals, vars, getattr, setattr, delattr or a frame's f_globals, f_locals or f_builtins, or names anything with a leading underscore, such as a function's __globals__; - allows the class to be read outside its body only as possible_values, the default, a member or encode; - refuses methods, aliases, equal values and chained targets in the class body. Reflection past these names, and code in other modules, is beyond a read of one module. The oracle now loads the engine's country model and reads each enum variable's class from it, so such code in the pinned release would show there. Invariants and tests: - Whatever the reader admits, Python gives the variable the same members, with no aliases, and the same default. A Hypothesis differential runs 400 invented modules against Python, each with at most one refused form among admitted ones. Of 2,000 drawn examples, 819 are read and compared. - Each refused form is refused on its own. For each one marked observable, Python's answer also changes, so the refusal matters. These include (lambda: None).__globals__[...] and a generator frame's f_globals. - binding_sites agrees with CPython's symbol table on each construct that the language reference lists as binding a name, with global declarations, at module level and nested in a function and a class, and on eight forms that only read the name. Attribute stores count although the symbol table does not track them. - The five forms that put one member list in the input record while the variable held another now refuse the inventory end to end, each against a control that reads. - The oracle checks each loaded class's source path and hash, its base (policyengine_core's Enum), its members against its canonical names, and the default. Dropping TPS from the inventory, or changing the default, fails it. The unreadable-members test now passes a member of the intended class as the default, so each defect alone causes the refusal. An empty class has no member to name, so either check refuses it. Correction: b8d9a68's message gave "9 skipped (lane, seal, U2)". All 9 were SSI0 oracle tests, skipped where the pinned interpreter is absent. Verification: the 196 SSI tests (187 unit, 9 oracle) pass with the pinned interpreter. 85 of the 126 inventory tests fail against the parent reader, with its top-level count standing in for binding_sites, among them the differential and all five end-to-end cases. All 35 mutants of the reader's refusal clauses are caught. Regenerating against the pinned release, compared with 2.18.0, gives a byte-identical inventory. black and ruff pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
M1, identifiers outside Name and Attribute. static_module scanned only
Name ids and attribute names, so a match class pattern's keyword, such
as case object(__globals__=...), reached a function's globals unseen.
It now scans every string field of every node outside literals: pattern
keywords, def and class names and keyword argument names. A literal
such as label = "_invented exec" stays admitted.
M2, Variable by spelling. The module may now bind neither Enum nor
Variable. Writing the fix found more routes to what the engine reads:
policyengine_core's Variable constructor calls self.set to read
value_type, possible_values and default_value, so a body method or an
assignment named set could override it, and an override can remove its
own name before the engine checks for unknown attributes. The
variable's body may now hold only a leading docstring, single
assignments to the names that constructor reads (ENGINE_ATTRIBUTES),
and formula functions without decorators. Every attribute store in the
module refuses, including stores through Variable, a member or an
alias.
M3, coding cookies. Every parse reads bytes, so source is decoded as
Python decodes it, PEP 263 cookie included.
L1. A store through a member, such as Enum.MEMBER.index = 0, refuses,
and the oracle checks that every pinned enum's indices equal its member
positions.
L2. value_type must be one plain assignment of a primitive type or
Enum, with no attribute store, or the inventory refuses ("Unresolved
value_type").
L3. Head forms for a star import from another module and a relative
model API import now fail without the import clauses.
N1. The method test is renamed and now calls the reader.
N2 stays a stated limit: reflection through module attributes the model
API exports is not read statically. The oracle, which loads the pinned
engine, covers the pinned release.
New oracle tests, on the pinned interpreter:
- invented modules load in the pinned engine with the members the
reader reads, for each admitted form and for all of them together.
A set override and a member store load without error but change what
the engine gives, which is why the reader refuses them;
- ENGINE_ATTRIBUTES equals the names the pinned constructor reads,
through set or by popping them.
Invariants:
- The inventory reads an enum input's members only from a module whose
own code cannot change them; whatever it reads, Python and the pinned
engine give the same members, with no aliases, and the same default.
- Each variable's value_type is one plain primitive or Enum assignment,
or the inventory refuses.
- Source is decoded as Python decodes it.
- ENGINE_ATTRIBUTES equals the attributes the pinned Variable reads.
- Each pinned enum's indices are its member positions.
Corrections to 08fdaaf's message:
- "names anything with a leading underscore" was false for names held
outside Name and Attribute nodes (M1). It holds now.
- "subclasses Variable alone" matched Variable by spelling (M2). The
module may no longer bind it.
- "85 of the 126 inventory tests fail against the parent reader" held
only with the parent's enum_members call adapted. With only
binding_sites shimmed, 45 failed.
- "Of 2,000 drawn examples, 819 are read" is not reproducible, because
Hypothesis draws differ between runs. The review got 746 to 769.
- "All 35 mutants are caught" could not be checked, because the set was
not kept.
Results at this commit:
- 20 of the 150 inventory tests fail against 08fdaaf's reader, with no
shim.
- The differential reads 745 of 2,000 examples over seeds 0 to 4, from
133 to 164 per 400-example run.
- 56 mutants of the reader's clauses, now kept with the lane's build
records: 53 are caught. The 3 survivors are equivalent: a named model
API import must bind Enum, Variable or the enum's name, which the
binding checks refuse; an empty class fails the default-member check;
a leading-underscore member name fails the identifier scan.
- The regenerated inventory is byte-identical with inventory.json.
- With the pinned interpreter, 222 SSI tests pass: contract 20, runner
41, inventory 150, engine oracle 8 and dataset oracle 3. By tier,
unit 211 and oracle_policyengine 11.
- black and ruff are clean.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
M1, value_type by spelling. parse_variables matched a primitive
value_type by its name, so a module that rebinds the name, as
float = Enum does, gave the engine an Enum input that the inventory
recorded as a float with no members. The inventory now refuses a
value_type whose name the module binds anywhere ("Unresolved
value_type"), and the same rule covers the names an entity and a
definition period are spelled by ("Unresolved entity", "Unresolved
definition_period"). Tests add a rebinding of each primitive type, an
entity and a period bound in the module, and a value_type spelled by a
name the module never binds, such as one a star import of the model API
could bind to Enum. A new oracle test checks each inventoried variable's
value_type, default, entity and period against what the pinned engine
gives it.
L1, the single-target clause. A refused form chains an engine attribute
with another name (label = invented_note = "note"), and another binds
set beside a reference (reference = set = invented_set) after an
admitted helper that overrides set. The engine oracle now loads that
pair, which changes the members the engine gives without an error.
L2, clauses without a failing test. Refused forms add a delete through a
member (del InventedEnum.MEMBER.index), an underscore keyword argument
name and an underscore parameter name. Two tests put the SSI helper
roots and the core primitive defaults under a utf-7 coding cookie, so a
parse that reads text instead of bytes misses a helper's dependency or
reads the wrong defaults. validate_core_defaults now also refuses a
module that binds VALUE_TYPES twice, since Python keeps the last.
L3, the reflection limit. The script's header now says the static read
does not follow reflection through objects that the model API exports,
and that only the pinned-engine oracle tests cover that, for the pinned
release: they compare each inventoried variable's value_type, default,
entity and period, and each enum input's members, with what the engine
loads.
Corrections:
- b682dcd's L2 line and its value_type invariant were false for a
module that rebinds a primitive name (M1). They hold now.
- b682dcd gave the three surviving mutants' S3 reason as "a named model
API import must bind Enum, Variable or the enum's name". It need not:
a named import of YEAR binds none. The mutant is equivalent because a
named model-API import binds a name to an object the model API exports,
as its star import does, since the pinned model_api has no __all__.
Binding Enum, Variable, the enum's name or a value_type's name is
refused either way, and an underscore name fails the scan.
- The PR body said round 5's M2 forms changed what the engine reads. For
class Variable(Variable, metaclass=...), the pinned loader registers
the local Variable class itself and fails loudly. Refusing the form is
still right.
Invariants:
- Each variable's value_type is one plain assignment of a primitive type
or Enum, by a name its module never binds, or the inventory refuses.
- The entity and period are spelled by names the module never binds.
- The core defaults come from one plain VALUE_TYPES table.
- For the pinned release, each inventoried variable's value_type,
default, entity and period equal what the engine gives.
Results at this commit:
- 7 of the 165 inventory tests fail against b682dcd's reader.
- 65 mutants of the reader's clauses, kept with the lane's build records:
62 are caught. The 3 survivors are the known equivalents (S3 above; an
empty class fails the default-member check; a leading-underscore
member name fails the identifier scan).
- The regenerated inventory is byte-identical with inventory.json.
- With the pinned interpreter, 238 SSI tests pass: contract 20, runner
unit 41, dataset engine 3, engine 9, inventory 165. Tiers: unit 226,
oracle_policyengine 12.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # scripts/first_estimates_birth_evidence.py # tests/estimates/test_birth_evidence_artifact.py
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
M1 needed the reader to decide inputs by the engine's rule. The reader now records which naming attributes each class binds, and reads a variable that is not a boundary as an input exactly when it has no formula and sets neither adds nor subtracts, as is_input_variable does; a defined_for or a label plays no part. The inventory still follows an input's dependencies, so a defined_for gate resolves and has a record. Reader tests cover the review's three forms, the label route and four more. The attribute oracle child, which already builds the country system, now compares each pinned record's input status with is_input_variable, and a new core-harness oracle, which builds none, does so for every invented form. M2 needed a body literal to count by its source alone. The reader drops set(records) from the names a literal may match. It also pushes dependencies in sorted order, reads a dependency's file even when a class of that name was already read, and refuses a variable name read from two files, as the engine does: a search for other order-dependent output found that the record took whichever file the walk read last. A new test reads three invented layouts, the review's among them, under four hash seeds in child processes and in process, and gets one output for each. A probe in the round's evidence finds that f92719c's reader gives two or more outputs for each layout over seeds 0 to 7. M3 needed dotted names to resolve as get_parameter resolves them. The new parameter_child walks exact os.listdir names from parameters/, so case counts on this volume, and refuses an empty part, an absent name, a name two entries give and a key inside a YAML node. parameter_file admits only a .yaml file that the engine builds as a dated Parameter, and raises a ValueError otherwise, never a KeyError (N1). Every string adds or subtracts and every list item with a period goes through it. A naming attribute that names its own variable, directly or through a parameter's list, now refuses, and the self-name test is inverted; a formula's lagged read of its own variable stays no dependency. A formula's parameter prefix that names neither a file nor a folder now refuses: in both releases all 38 prefixes name a file, so no record changes. Reader tests cover 30 refused and 6 admitted naming forms, the review's six among them. The core-harness oracle shows the engine raising on the review's five raising forms and on the self-names, refusing to load three more, and reading the key inside a YAML node and every form the header lists as a safe-direction refusal. L1 needed the claim that every parameter the engine reads is on the record narrowed: the tracer records only a formula's reads. The header and the trace test say so, and the attribute oracle compares each pinned record with the adds, subtracts and defined_for the engine holds, and with the names a string's parameter lists on any date. L2 needed the reform to show that it took. TRACE_CHILD returns the individual FBR from each simulation's tree, and the trace test asserts that the reformed value is INVENTED_POLICY's 1000 and that the plain one differs, which an empty reform fails. L3 needed the header to name what the trace test leaves out. It now lists the four differences from calculate_household. compile_reform passes no reform for a case without overrides, so the comment that the runner always passes one now says it passes one whenever a case has an override. L4 needed tests for four routes. list_item_outside_gov kills B3, defined_for_names_a_parameter kills B7, string_lists_a_class_of_another_stem kills B10, and gate_of_another_stem_beside_adds and gate_beside_adds kill B19. L5 needed the trace targets pinned to the roots. The trace test asserts that the target count equals federal_ssi_variable_count, which removing the root filter fails. N2's safe-direction refusals are listed in the header's first limit, with a built parameter such as gov.abolitions.<name>. N3 and N6: the first limit now names list items with a period as parameters, the self-name refusal, the union of a parameter's lists over all dates, and literals that equal a class of the same module. N5: a comment at unread says when it can fail on a correct record. The claim sweep compared every rule the header states for every input with the engine's code. Five rules differed in forms the engine refuses to load, and the reader now refuses each: a variable with more than one computation mode, in any class a read module defines; a defined_for that names an Enum or str variable; a variable name in two files; a parameter file that repeats a key; and a .yml file in the federal SSI parameter tree, which the table would leave out. The engine also refuses a variable with no label, which the reader does not check; the header states that limit, and the core harness gives its invented variables labels. A static oracle checks the core constants the reader mirrors: the parameter suffixes, the skipped names, the dated-key pattern and the numeric value types. Checks: contract 20, runner unit 41 and inventory 723 passed, through safe-pytest at two workers. The four new engine tests that build no country system passed: the three core-harness tests and the static constants test. Regeneration with -I gives the same inventory.json bytes (sha256 93f6efbf...), and the full records of 2.2.1 and 2.18.0 under this reader equal those under f92719c's. Collection gives unit 784 and oracle_policyengine 27 over the five SSI modules, plus the moved test. black -l 79, ruff and git diff --check are clean. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
O3 and P14 were real test gaps: the reader refuses each layout and the mutant admits it. B9 is equivalent on both pinned releases, but the reader still refuses a boundary's literal adds that name itself or an absent parameter, and these tests pin that. Z1 only changed the exception type, so its test pins the reader's own ValueError, for a list and for an empty file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Text only: the abstract syntax trees of both files, docstrings aside, match 208b4d4's. The reader's docstrings now say that a bare expected string refuses while a mapping marked expected joins the union, that index.yml and reference.yml load as no parameter, that a self-name refuses on any date, and which other forms the engine refuses to load. A test comment now says the engine raises on the two cases it heads. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both tier files take master's blobs; the next commit recounts them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Master's counts plus SSI0's modules: unit 19,504 + 790, oracle 308 + 28. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both tier files take master's blobs; the next commit recounts them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Master's counts plus SSI0's modules: unit 19,664 + 790, oracle 308 + 28. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Round 15's two medium findings, each a claim that went too far. Neither changes a record or a runtime path. The reader's sentence on the .yml refusal named the stems index and reference, but the pinned core also skips __pycache__ as a file. The docstring now names all three. SSI's three income lists start on 1975-01-01 in both releases, and prepare accepts 1974, so the future-only list limit reaches pinned sources and not only invented modules. On the pinned route an earlier year never reaches them: invented cases in every year from 1972 to 2021, plus 1000 and 1900, end in a counted RULES_ENGINE_GAP from the worker, and 2022 gives the first result. The new oracle test holds seven of those years and 2022. The runner's docstring now says such a year refuses from the worker, not before any calculation. The test adds one to oracle_policyengine (337), 27,053 in all. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
marked this pull request as ready for review
November 2, 2026 14:40
Contributor
Author
|
The Microcosm Dynamics coordinator merged this PR at
|
MaxGhenis
added a commit
that referenced
this pull request
Nov 2, 2026
Master brings SSI0 (#573), which touches no Track B file. The tier files take master's counts plus this branch's new tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis
added a commit
that referenced
this pull request
Nov 2, 2026
Master brings SSI0 (#573), which touches no Track B file. The tier files take master's counts plus this branch's new tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Nov 2, 2026
Merged
MaxGhenis
added a commit
that referenced
this pull request
Nov 3, 2026
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>
MaxGhenis
added a commit
that referenced
this pull request
Nov 3, 2026
Master's #573 (SSI0) and #574 (D4) each added a block to the birth-evidence exclusions, their expected tuple and the reachability test, where CE1 adds its own. Keep master's blocks and put CE1's after them in all three places. D4's block already lists src/populace_dynamics/income_resources/__init__.py, which both sides add as the same blob, so CE1's exclusion blocks keep only coverage_rules.py. The merge takes master's tier files, and the next commit recounts them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Nov 3, 2026
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.
This is milestone SSI0 of the income-and-resources design (#559: §3.3 and the SSI0 row of the milestone table). The third review round approved
48a71983. Later rounds hardened how the inventory reads each variable. The eleventh approved691111f0with three low findings and four notes;4150b7d4answers them, andf92719cerecounts the tiers. The twelfth, a delta review off92719ce, asked for revision, with three medium findings;cba389abandcb728630answer it, and208b4d49recounts the tiers. The thirteenth approved208b4d49with three low findings and seven notes;146c3723narrows the claims it falsified, and56bbcde8carries the latest merge of master and tier recount. The fifteenth, a delta review of56bbcde8, asked for revision, with two medium findings;c865dce1answers them. The sixteenth, a delta review ofc865dce1, approved it with no finding.What it adds
An annual federal SSI interface to the PolicyEngine release that the latest
policyengine(6.10.2) certifies:policyengine-us2.2.1 andpolicyengine-core3.33.3. It ships with a complete source-to-input contract, published before any SSI computation.src/populace_dynamics/income_resources/ssi/):policyengineinterfaces. It never importspolicyengine_usinternals.pin.jsonrecords the three primary versions, wheel hashes and RECORD hashes;environment_wheels.jsonrecords all 89 installed distributions;docs/analysis/ssi0/requirements-macos-arm64-py313.txtis the hash-locked environment;2dee2fc4fixes this and adds two properties.inventory.json): 52 federal SSI variables, an 86-variable closure, 41 inputs and 24 parameters. It was regenerated byte for byte byscripts/income_resources/inventory_ssi.pyand compared with PE-US 2.18.0. Both releases have the same active chain, inputs and parameters.input_contract.json, versionssi0-v1): each of the 41 engine inputs and 12 context rows gets one decision per starting population (PSID, SIPP, Microcosm's frame). The decision is a source, an opted-in assumption with an audit ID, or a refusal.scripts/build_ssi_input_contract.pyreproduces it together with the review table indocs/analysis/ssi0/input_decisions.md.docs/analysis/ssi0/captured_sources.md). Each capture folder has a.gitattributeswith* -text.Refusals (
RULES_ENGINE_GAP)prepareaccepts any four-digit year, and the worker raises on each year before 2022, so such a case ends in a counted refusal with no result. 2022 gives the first result.Invariants
scripts/income_resources/inventory_ssi.py):.ymlfile in the parameter tree refuses: the engine loads one as a parameter, unless its stem isindex,referenceor__pycache__, and the table would leave it out.__init__.py, so a file whose name merely ends in__init__.pyis a variables file. A folder whose path has a glob character (*,?or[) refuses, since the walk globs the whole path and its glob of that folder can read another folder's files. For the pinned release, an oracle test checks the reader's file index against the country system's own walk, file for file and in order. A dependency whose stem names more than one file refuses, and so does a variable name read from two files, which the engine refuses to register twice. Every dependency reaches another inventoried variable or an explicit input.addsnorsubtracts, as the engine'sis_input_variablehas it; adefined_foror a label plays no part. So the contract supplies every variable the engine holds as an input and, boundaries apart, none that the engine calculates. The inventory still follows an input's dependencies, so each resolves.policyengine_us.variables., andSimulationfrompolicyengine_core.simulations. This covers variable modules, followed modules, and the package inits their imports run.VariablenorEnum, in any form. The reader trusts each spelling to name what the model API's star import binds only because no module it reads binds it. So a base spelledVariablemarks every variable class in the module, and a class onEnumis a core Enum, never a variable.addsorsubtracts, anduprating, as the engine'scheck_computation_modesrequires. So no variable class overrides aVariablemethod. Otherwise the inventory refuses.PathFinder.find_specin the reader's own interpreter, with its path hooks and suffixes; no meta path finder is asked. Namespace folders pass. Every other step must be.pysource loaded bySourceFileLoader, read from that origin; anything else refuses. The reader also refuses when its interpreter would match file names without regard to case, asPYTHONCASEOKmakes it on a case-insensitive platform without-Ior-E. The documented command runs it with-I.value_type, entity and period is one plain assignment, of a name its module never binds.float(v) == v; or a member of its statically read enum class. The inventory reads an enum input's members only from a module whose own code cannot change them, and no member takes the name of the class'sencodemethod, which formulas and the engine call.adds,subtractsanddefined_for, which name the variables the engine reads for it, are each a string literal or, for the first two, a list or tuple of them. A boundary keeps any value, since the reader bypasses its dependencies; in both releases the one such value issocial_security's computedadds.defined_for, and a list item without a period, names a variable, whatever file defines it, so a name the file index misses refuses as unresolved. Adefined_formust name a variable of a numeric type, as the engine requires when it registers the variable.addsorsubtracts, and a list item with a period, names a parameter, which the reader resolves as the engine'sget_parameterdoes. It splits the name on periods; an empty part refuses; each part must be the exact child name, case included, of one entry of the parameter folder before it; the name must end at a.yamlfile that the engine builds as a datedParameter; and anything else refuses with aValueError. A string's parameter must list variable names on every date, and the record holds their union over all dates, where the engine reads the list at the start of the period and skips a date marked expected. A mapping markedexpected: truethat holds a list joins that union. A name that names its own variable, directly or through a parameter's list on any date, refuses: the engine's calculation of a variable that names itself at the period never ends, and the other dates refuse in the safe direction. A formula's parameter prefix resolves by the same exact names to a.yamlfile or a folder, or refuses. The resolution also refuses, in the safe direction, a key inside a YAML node, a folder or a.ymlfile that a string names, a file of dated keys withoutvalues, a bareexpectedstring, and a parameter the engine builds rather than loads. Every parameter file the reader reads has distinct keys, as the engine's YAML loader requires.value_type, entity, period and default value against what the engine loads; the type of the engine's default against the type the engine's conversion gives the record's default (an int, bool included, becomes a float only as the explicit default of a float variable); each enum variable's members; whether the engine holds the record to be an input; and that theadds,subtractsanddefined_forthe engine holds, and the names a string's parameter lists on any date, are on the record. The engine holds one float for an explicit40and40.0of a float variable, so a test that runs no engine also compares each record's default, by value and type, with the literal the pinned source binds, or with the core type default where it binds none. A core-harness oracle, which builds no country system, loads each invented naming, input-rule and load-time form in the pinnedpolicyengine_coreand shows that it raises, refuses to load or reads as the reader's record or refusal says.federal_ssi_variable_count. It runs once with no reform and once under the reform of all seven overrides the runner admits, and the reformed tree holds the reform's individual FBR. The engine reads exactly the listed variables and seven names of its own input route.system.pymoves the values ofemployment_income,self_employment_incomeandsstb_self_employment_incometo their_before_lsrvariables. Theaddsofemployment_incomesums its_before_lsrvariable and a behavioral response, and that response readslabor_supply_behavioral_response. Every listed name is read. Every formula edge from a record that is neither an input nor a boundary is in the record's dependencies, apart from a variable reading itself. Every parameter the tracer records is on the record or agov.abolitions.<name>gate, which the engine reads before it calculates each variable that has one. The tracer records only a formula's reads, so a parameter thataddsorsubtractsnames does not show there; the attribute oracle above compares those. Under the reform a recorded parameter may also sit undergov.simulation.labor_supply_responses., which the behavioral response reads before it gives 0. The test asserts that the response stays 0 on both traces and that no admitted override sits under that prefix.adds,subtractsanddefined_forname, as above; the first argument of an entity accessor call; and the string literals of its body and of the federal SSI helpers it calls that equal the stem of a file whose name has no leading underscore or the name of a variable class in the same module, by the source alone. A formula's read of its own variable, which may be at another period, is no dependency. A formula that reaches a variable through a function or constant its module binds, through a parameter's values, or through a name it builds reads a variable the record does not list, and so does one that passes a literal to anything but an accessor when the class of that name sits in a file of another stem. A literal no code reads, such as a label that equals a file's stem, adds a dependency the engine does not read. The reader bypasses a boundary's dependencies, so a literaldefined_foron a boundary, which the engine applies when it runs the boundary'sadds, stays unread, and so does its type. The reader follows an input's dependencies, though the engine reads none of them for a value the contract supplies. The safe-direction refusals above hold in neither release. The trace test checks the pinned release's records over invented households. It buildspolicyengine_us'sSimulationitself, where the runner'scalculate_householdcallscompile_reform(which gives no reform for a case without overrides, and each scalar override from 1 January of the year), passes spm settings, builds one marital unit of every person, and calculates at the year, where the test calculates MONTH targets at2026-01only. Those differences, a code path the households don't reach, the dataset route's simulation and any other release stay outside that test. In both releases the only names a closure variable's body loads from its module are its enum classes,Simulationand_apply_ssi_exclusions, an SSI helper imported under its own name.policyengine_us/variablesoutside the closure, and such a module can change what the engine loads; the reader does not read those modules, and only the pinned-engine oracle covers them.parameters/, and one it cannot load stops it, while the reader reads only the files it lists or resolves. Nor does the reader check every rule the engine applies as it loads a variable: it admits a variable class with no label, a formula name the engine cannot parse, a class bound a second time at module level and ametadata.yamlin a parameter folder that a name passes through, each of which stops the engine. A release the engine does not load gives no record to compare, and only the pinned-engine oracle shows that the pinned release loads.importlib.util.cache_from_sourcenames, in__pycache__or undersys.pycache_prefixwhen that is set. It runs a timestamp file whose recorded modification time and size match the source's, and never compares that file's code with the source. It runs a hash-based file unless it compares the file's recorded hash with the source's and they differ, and it compares them, under--check-hash-based-pycs, for a file marked checked in the default mode, for every file underalways, and for none undernever. The reader reads only source, so only the pinned-engine oracle covers cached bytecode too.Tests
POPULACE_DYNAMICS_PE_US_PYTHON_SSI0names the pinned interpreter (fallback~/.venvs/policyengine-py-6.10.2/bin/python), and the name contains the classifier's oracle substring;c865dce1, each module whole;tests/income_resources/test_ssi_static_offset.py(1 test) holds the static-offset differential, moved out oftest_ssi_engine.pyso that the engine checks import nothing from the estimates package. It importsestimates/adjusted_poverty.pyinside the test body. CI collects it and skips it, because CI has no SSI0 interpreter. It ran on the pinned interpreter at765c4879,2864d622,ff70470a,691111f0,f92719ceand208b4d49, each time in a throwaway clone with output kept off-screen: 1 passed. It does not run in CI.ssi_invented.INVENTED_POLICY(FBRs, exclusions, earned-income share and resource limits); the five Social Security amounts and the 25% cut share are invented; the income year is 2026, as in the other invented cases; the two-cent tolerance followstest_ssi_engine's federal invariants; and every expected offset is the pinned engine's own result for an invented case. Its only constants that also appear inadjusted_poverty.pyare the integers 0, 1 and 2 and thefukey passed to_ssi_response.tests/estimates/test_birth_evidence_artifact.pygives 12 passed and 1 failed in this branch's sparse checkout, intest_post_review_exclusions_are_unreachable_from_birth_evidence. CI's full checkout runs that module, and its Tests run atf92719cepassed.cb728630, each mutant run over the whole inventory module:mutants_r14.py), one or more for each rule or guard the round adds, with round 12's B3, B7, B9, B10, B14 and B19 ported to this round's loop. Atcba389ab, O3, P14, Z1 and B9 survived. O3 and P14 showed test gaps, Z1 changed only the exception type, and B9 changed no record of either release but admitted a boundary'saddsthat names itself or an absent parameter.cb728630adds a test for each, and all 37 fail at that head;test_engine_trace_reads_only_what_the_inventory_lists;r13p, 12 mutants) all fail, and so do the other 4;PYTHONCASEOKis set, even under-Eor-I, and so only over-refuses;module_importsalready refuses a class that is not a top-level statement subclassingVariableorEnumalone; G2: with no glob character in the folder's path, a match named__init__.pyis the joined path);cb728630, 58 of the 729 inventory tests fail againstf92719ce's reader, the same 58 in each of Hypothesis seeds 0, 1 and 2. They sit in 17 of this round's 20 new test functions, and no older function fails.18082859: unit +790 (20,454), oracle_policyengine +29 (337), with artifact 4,271, integration_psid 1,471 and reproduction_legacy 520, 27,053 in all. CI's tier-policy test passes on those counts. The recount takes the static-offset test from its source, as one unparametrized function.Since the build
2dee2fc4makes the installation RECORD digest skip entries outside site-packages.14febfdbmergesorigin/masteratfe5ab5abcleanly.d037e91arenames the pinned copy of policyengine-us 2.2.1'sssi_if_takes_up.pyto.py.txt, because black and ruff read every.pyfile and the lint job failed on it. Its bytes, size and SHA-256 are unchanged, and both capture manifests and the captured-sources table name the new file.bde9d3ddkeeps the birth-evidence seal. The twelve new files undersrc/populace_dynamics/income_resources/are listed inPOST_REVIEW_SOURCE_EXCLUSIONSand in the test's expected tuple, and a new assertion checks that none of the SSI modules is reachable from the birth-evidence reducer.black and ruff are clean. The seal, U2-isolation and lane tests pass locally (83 passed, with the oracle tests on the pinned interpreter).
tests/test_tier_policy.pyis expected to fail until the tier-count slot.The independent review at
bde9d3dd(GPT-6.1 Sol, round 2) found one medium problem and asked for revision. When a pooled calculation failed, the worker copied its error to every case in the pool, so one invalid case refused every valid case pooled with it.48a71983fixes it:immigration_statuscarries them, so an invalid name refuses its own case asINPUT_CONTRACT_GAPbefore dispatch;At
48a71983, lane, seal and U2-isolation tests give 86 passed, with the 8 oracle tests skipped. The 8 oracle tests pass on the pinned interpreter. black and ruff are clean.The round-3 delta review (GPT-6.1 Sol, at
48a71983) approves, with no high or medium finding. Its probe ran the worker's parent and child control flow over 162 batches, with the failing case at every position for sizes 1 to 11 and at the first, middle and last positions for sizes 12 to 16. Each batch left exactly one refusal and kept the valid outcomes, case IDs, order and accounting.Its one low finding:
48a71983's message says every listed invariant has a property test, but the inventory's refusal of an enum input whose members it cannot read had only a fixed example.fdd85c6eadds two Hypothesis properties totests/income_resources/test_ssi_inventory.py: invented enum members round-trip from source, and an enum input whose class is absent, empty or not an enum refuses the inventory. It changes no other file.At
fdd85c6e, lane, seal and U2-isolation tests give 88 passed, with the 8 oracle tests skipped. black and ruff are clean.b8d9a68acloses three ways the enum reader could disagree with Python: unsupported assignment forms in the class body, other bindings of the class's name, and a default outside the class's members. None affected the pinned release; the regenerated inventory, contract and decision table were byte-identical.The round-4 delta review (an Opus 5.5 reviewer, at
b8d9a68a) asked for revision, with two medium findings:__init__hook can drop members;ifblock, a walrus, a match capture, aglobaldeclaration in a function or class, a guarded or aliased import, a star import after the class, or a second binding ofpossible_valuesin the variable's body could each change the class while the reader recorded the original members.Its low findings: an alias passed the contract although
Enum.encodeaccepts only canonical names;Enumwas matched by spelling; and one refusal test passed only because of the default check.08fdaaf1fixes these, and a further gap found while writing the fix: module code could reach the variable itself, by an attribute store such asinvented_status.possible_values = Other, a decorator, or a rebinding of the variable's name.value_type,possible_valuesanddefault_valueonce each, by plain assignment.Enum, uses a reflective builtin or frame attribute, or names anything with a leading underscore (which covers a function's__globals__). Round 5 showed this held only forNameandAttributenodes; see below.possible_values, the default, a member orencode.Tests at
08fdaaf1:(lambda: None).__globals__[...]and a generator frame'sf_globals;binding_sitesagainst CPython's symbol table for each construct the language reference lists as binding a name;Results at
08fdaaf1: 85 of the 126 inventory tests fail against the parent reader (round 5 found this holds only with the parent'senum_memberscall adapted; with onlybinding_sitesshimmed, 45 fail). All 35 mutants of the reader's refusal clauses were caught (the set was not kept, so this could not be checked). The oracle fails when TPS is dropped from the inventory or the default is changed. The regenerated inventory is byte-identical, and the 196 SSI tests pass with the pinned interpreter. black and ruff are clean.Correction:
b8d9a68a's message gave "9 skipped (lane, seal, U2)". All 9 were SSI0 oracle tests, skipped where the pinned interpreter is absent.The round-5 delta review (an Opus 5.5 reviewer, at
08fdaaf1) asked for revision, with three medium findings, each a module the reader read differently from Python and the pinned engine:matchclass pattern's keyword, such ascase object(__globals__=...), reached a function's globals, because the scan read onlyNameids and attribute names;Variablewas matched by spelling, so a localVariablewith a metaclass, or a rebinding, could change what the engine reads. (Round 6 corrected this account: for the metaclass form, the pinned loader registers the localVariableclass itself and fails loudly. Refusing the form is still right.);Its low findings: a store through a member changed encoding indices unchecked; a
value_typethat was not a plain= Enumskipped the member check; two import clauses had no test that failed without them. Its notes: one test name overclaimed, and reflection through module attributes the model API exports is a boundary of the stated limit.b682dcd2fixes these:EnumnorVariable, and every attribute store refuses;Variable's constructor readsvalue_type,possible_valuesanddefault_valuethroughself.set, which a body method or an assignment namedsetcould override. The variable's body may now hold only a leading docstring, single assignments to the names that constructor reads, and formula functions without decorators;value_typemust be one plain assignment of a primitive type orEnum, or the inventory refuses (round 6 found this did not hold for a module that rebinds a primitive name;b1d0d029closes it);b1d0d029states it in the script's header).New oracle tests: invented modules load in the pinned engine with the members the reader reads, and a set override and a member store change what the engine gives; the constructor's attribute names equal the reader's allow-list; every pinned enum's indices are its member positions.
Results at
b682dcd2:08fdaaf1's reader, with no shim;The round-6 delta review (an Opus 5.5 reviewer, at
b682dcd2) asked for revision, with one medium finding:value_typewas read by the spelling of a primitive name, so a module that bindsfloat = Enumgave the engine an Enum input that the inventory recorded as a float with no members.Its low findings: the single-target clause had no failing test, though a chained
setbinding beside an override changes the engine's members; four other clauses (deletes, keyword and parameter names, byte parsing of helper roots and core defaults) had none either; and the script's header did not state the reflection limit. Its notes: the S3 equivalence reason was imprecise, and this body overstated round 5's M2.b1d0d029fixes these:value_type, entity or period spelled by a name the module binds refuses the inventory, with tests for each primitive, an entity and a period (round 7 noted that the model-API alias test listed here is refused by the older known-name clause, not by this rule);setbinding, a delete through a member and underscore keyword and parameter names; the engine oracle loads the chainedsetpair beside an admitted override;VALUE_TYPEStwice refuses;value_type, default, entity and period with the pinned engine's.The corrected S3 reason: a named model-API import binds a name to an object the model API exports, as its star import does, since the pinned
model_apihas no__all__. BindingEnum,Variable, the enum's name, avalue_type's name or an entity's or period's name is refused either way (round 7 added the last), and an underscore name fails the scan.Results at
b1d0d029:b682dcd2's reader;81a6db61mergesorigin/masterat1ec57a5d(D1a, PSID income and wealth readers and field registry (D1a) #575). The birth-evidence check keeps D1a's exclusions and reachability assertion, then SSI0's; its 13 tests pass.The round-7 delta review (an Opus 5.5 reviewer, at
81a6db61) asked for revision, with two medium findings that share one cause: the reader checked a variable's body and module only when itsvalue_typewas spelledEnum.value_typeis spelled as a primitive could still be an Enum input in the engine, through asetoverride,setattr,globals()or__builtins__;entitieslist or aglobals()store changed what the engine loads.Its low findings: the spelling and
VALUE_TYPEStests exercised one binding form each; and the attribute oracle compared entities through a name conversion that is wrong forSPMUnit, and defaults (likevalidate_core_defaults) by==alone, so1passed forTrue. Its three notes correct earlier text: N1 and N2 are marked above, and N3 (under mutant D2 the core-defaults parse refuses as "not one plain table" rather than reading wrong defaults) is in the commit.04e12f58fixes these:Variable, no keywords or decorators, and a body of a leading docstring, single assignments to namesVariable's constructor reads, and undecorated formulas, with each attribute the reader records bound at most once by plain assignment;value_type, entity and period are each a name the module never binds, and a default is a literal of the variable's primitive type or a member of its enum class;policyengine_us/variablesthat it imports, with the package__init__files the import runs, may import only the model API's star import and named imports from modules underpolicyengine_us.variablesorpolicyengine_core, at top level; may define classes only at top level, onVariableorEnum; may store no attribute; and may name no reflective builtin, frame attribute or dunder name. Imported variables modules are followed in turn;float,PersonandYEAR, and a secondVALUE_TYPESbinding by assignment, annotation,|=, match capture, import alias or parameter refuses, each against Python's answer;policyengine_us.model_api, and compares defaults by type as well as value;validate_core_defaultscompares by type too (round 8 found the oracle compared defaults by==and bool-ness only;a2b3952bmakes it compare types);test_ssi_static_offset.py, as the Tests section describes.New tests: each route the review traced (and more), end to end against a control package, with Python's answer for each; a Hypothesis differential of the static read against Python over admitted forms of an invented module; literal defaults by type; each refused form of module code in a variable module, a module it imports and the package
__init__that import runs; string literals that spell reflective or dunder names, admitted in all three; a variable name bound again, and a variable class with type parameters; followed imports, package inits and import cycles; and an oracle test that loads every route in the pinned engine and shows each changes what the engine loads.Results at
04e12f58:81a6db61's reader, in each of three Hypothesis seeds;0f756216mergesorigin/masteratd8302233(SM1, SM1: differential mortality by lifetime earnings, education and race (normalized within age-sex-year cells) #570) without conflicts: master adds SM1's modules to the birth-evidence reducer's exclusions and to the seal tests, beside SSI0's. At the merge, the SSI tests and the birth-evidence tests pass locally (465 passed, the 12 oracle tests on the pinned interpreter among them). The one failure is the seal reachability test, which needs modules this sparse clone leaves out; CI runs it.765c4879recounts the tiers on that master.The round-8 delta review (an Opus 5.5 reviewer, at
765c4879) asked for revision, with five medium findings. In each, the reader admitted a release while the pinned engine loaded a different default,value_type, entity or period, or refused to load:policyengine_coreimport and an item store or method call on itsVALUE_TYPEStable;__init__has only bytecode;__init__.pyfiles, which the engine's directory walk skips, and kept the last of two files with the same stem;Its low findings: four of its mutants (N1, N2, N6, N8) survived with no witness test, and "compares defaults by type as well as value" was false for the oracle. Its notes corrected wording in a docstring, the moved test,
04e12f58's message and this body.a2b3952bfixes these:|=changes the table with no call or store); the core imports are an allowlist,Simulationonly;PathFinder.find_spec, and anything but.pysource loaded bySourceFileLoaderrefuses. Namespace steps are admitted, since they run no code and both pinned releases' followed paths use them;OverflowErrorincluded;04e12f58's "Python's float default is shown for each" did not cover the import-alias case, which was not executed, and this body's "for every invented module the reader admits" holds over the Hypothesis domain.New tests: the review's repros, each reaching the core table two ways; 15 import-time and 8 import forms refused, with 5 forms that stay admitted; shadow, sourceless, extension, submodule-name, cannot-resolve, case-mismatch and import-cache tests, checked against a fresh interpreter's
find_specwhere that applies (the extension, step-past-module and case-mismatch tests do not call it); the walk's file-index cases; exact and inexact int defaults, with a Hypothesis property; and two oracle tests: the core-table changes change what the pinned engine loads, and the file index equals the pinned engine's own walk.Results at
a2b3952b: the regenerated inventory is byte-identical; the SSI tests pass (contract 20, runner unit 41, inventory 486, and with the pinned interpreter engine 11 and dataset engine 3); the mutant and parent-check counts are in the Tests section; black and ruff are clean.While writing the fix, the builder found that Python's source loader can run a module's cached bytecode instead of its source, which the reader never reads. Refusing any module with cached bytecode would refuse the installed releases, so
60b8ca24states this limit in the reader's header, in the sentence in the Invariants section. The regenerated inventory is byte-identical.2864d622mergesorigin/masterat0f69bbb2(OP1, OP1: open-population harness around the sealed loop #566, and its report fix, Fix review r10's report findings for OP1 #589). Git auto-merged the birth-evidence reducer and its test, which both branches changed: the merge keeps master's OP1 lines and SSI0's exclusions and reachability block.tests/tier_counts.jsonandtests/README-tiers.mdconflicted and now read master's counts plus SSI0's 562 tests. At the merge, the SSI tests pass as above, and the birth-evidence tests give 12 passed and 1 failed: the seal reachability test, which needs modules this sparse clone leaves out; CI runs it.The round-9 delta review (at
2864d622) asked for revision, with one medium finding. M1: a module the closure imports could define aVariableclass that overridesVariable.set. The reader checked such a class only for its bases, keywords and decorators, while the engine's walk builds it and runs the override; in the review's repro the engine gaveemployment_incomea default of 7 where the reader recorded 0. Its low findings:__init__.pyby name, while the engine leaves out only the path it joins for the folder's own init, so a folder name with a glob character class (invented_a[b]/) split them;PYTHONCASEOKwithout-Icould make it read a different file from the one the engine imports.Its notes asked for an exact cached-bytecode sentence (N1), "where that applies" on this body's
find_specclaim (N2), and an oracle test of its ten import-time forms without a call (N3).67e52e52fixes these:check_modulerefuses any module it reads, followed modules and package inits included, that defines a variable class with type parameters or a bodyplain_variable_bodyrefuses;module_importsalready refuses a class that is not a top-level statement, so a class inside a module-levelif,tryorwithrefuses there first;variable_filesleaves out only the match equal toos.path.join(directory, "__init__.py"), as the engine does, and refuses a folder whose path has a glob character;value_type, following the pinnedVariable.set, and a new test that runs no engine compares each record's default and its origin with the pinned source;importlib._bootstrap_external._relax_case()holds, and the documented command passes-I; the header says resolution uses the reader's own path hooks and suffixes and asks no meta path finder;SourceLoader.get_codein CPython 3.13, and its oracle sentence says what is compared;ssi_federal_living_arrangement.py(one plain variable class) and_apply_ssi_exclusions.py(no classes), no folder undervariables/has a glob character, and no file name ends in__init__.pywithout being one.New tests: the review's repro end to end, with six kinds of variable class that is not plain in a followed module and in a package init, each against a plain control, and an oracle test in which the engine's walk gives 7 with the override and the recorded default without it;
tryandwithclass forms; theinvented_a[b]layout and a package below a folder namedinvented[x], which refuse, and an SSI file namedinvented__init__.py, which stays a root; oracle tests for the engine's walk ofinvented_a[b]/, forinvented__init__.pyin the invented walk, and forvariable_filesagainst the pinned release's own walk, in order; witnesses for MY3 and MY7 as refused forms and as core-table changes, and an async helper as an admitted form, with each admitted form tested alone; the pinned-source default test; a child process withPYTHONCASEOK=1and no-Ion the review's case layout, which refuses; and an oracle test that loads each admitted form and each of the ten forms without a call, one at a time and together, as the reader records them. Like round 8's, the import tests are checked against a fresh interpreter'sfind_specwhere that applies.Results at
67e52e52: the regenerated inventory, run with-I, is byte-identical (sha25693f6efbf…); the SSI tests pass (contract 20, runner unit 41, inventory 535, and with the pinned interpreter engine 16 and dataset engine 3); the mutant and parent-check counts are in the Tests section; black and ruff are clean.ff70470amergesorigin/masterata747bafa. Git flagged onlytests/README-tiers.mdandtests/tier_counts.json, which both branches changed; every other file master changed stands as master has it. The tier files carry the provisional counts in the Tests section.The round-10 delta review (at
ff70470a) asked for revision, with one medium finding. M1: in a module that bindsEnumtoVariable(by assignment, byimport … as Enum, or by importing a plain variable class asEnum), a class onEnumwas a variable class that no rule read, and the engine's walk ran itssetoverride, which gaveemployment_incomea default of 7. An SSI-tree class in that form went unrecorded. Its low findings:ff70470a.Its notes:
engine_default_typecatches no edit the old function missed;67e52e52's message gave a stale count of round 8's mutants;d06014b7fixes these:EnumnorVariable, in any formbinding_sitesreads (module_imports, throughbinds_model_api_spelling, whichstatic_moduleshares). So a class onEnumis a core Enum and never a variable, and every variable class has a base spelledVariable. The header says the reader trusts the two spellings only because no module it reads binds them;plain_variableandplain_variable_bodyadmit, enum members, the model API's names and the engine attributes) lists each with the check that stops a rebinding, or the reason a rebinding cannot change a record (trusted-names.mdin the round's evidence). Three had no check, and each now refuses:encode, which takes the class'sencodemethod;adds,subtractsordefined_forof a variable that is not a boundary, other than a string literal or a list or tuple of them. A name the module binds, a computed list, or an Enum member asdefined_forhid from the record's dependencies the variables the engine loads in these attributes;FORMULA_NAME_PREFIX;ef82f376tests it for the pinned release;[,?and*;67e52e52's message:engine_default_typealso caught. The test that resolves round 9's L3 istest_inventory_defaults_are_the_pinned_source_literals, which runs no engine (N1);New tests:
followed_assign,closure_assign,closure_import_alias,closure_intermediate) end to end, each against Python's answer, with controls without the binding;Enumand ofVariablein a variable module, each against a control that binds another name;Enum = Variableamong the refused module forms in a variable module, a followed module and a package init;adds;followed_assigngivesemployment_income7 while the reader refuses;Enumloads a member namedencodein order and loses itsencodemethod;adds,subtractsanddefined_fornaming variables the record would not list, and holds only the last of two formulas of one name.Results at
d06014b7:-I, is byte-identical (sha25693f6efbf…). None of the 87 modules the reader reads in either release bindsEnum,Variable,encode, a primitive type, or an entity or period the records name. (Formula parameters and locals bindperson,parameters,tax_unitandmarital_unit, and four modules import_apply_ssi_exclusionsunder its own name. The read uses these names only to add dependencies.d06014b7's message says "or another spelling the reader trusts", which is too broad for these.);ef82f376addstest_engine_trace_reads_only_what_the_inventory_lists, which the session that ran this round wrote after the build. The pinned engine runs with its full tracer over nine invented households, and the test checks the trace against the record, as the Invariants section says. Four controls show that each kind of gap fails it: a record removed, a dependency removed, an invented record no household reads, and the parameters removed. Over the nine households the engine read 93 variables and 76 parameters, of which only the seven route names and thegov.abolitions.gates sit outside the record, and two self-edges (ssi,ssi_countable_income) sit outside its dependencies. The header's first limit now says what the test covers and what stays outside it; the reader's code otherwise stands, byast.dump, asd06014b7left it. The commit's message corrects two statements ind06014b7's: "another spelling the reader trusts", and its count of the engine tests that finished.691111f0carries the provisional tier recount in the Tests section.Results at
691111f0: contract 20, runner unit 41, inventory 627, engine 20 and dataset engine 3 pass; the regenerated inventory is byte-identical; the moved test passes in its throwaway clone.The round-11 delta review (an Opus 5.5 reviewer, at
691111f0) approved it, with no high or medium finding. None of its findings changes a record in 2.2.1 or 2.18.0. Its low findings:labor_supply_behavioral_responsereads 13 elasticity parameters before it gives 0, and the dataset route's simulation also sits outside the test;adds,subtractsordefined_forgave only if a file's stem matched it, and it expanded a string only undergov., so a class in a file of another stem or in an underscore file read as an input.trusted-names.mdlisted neither check.Its notes:
addsorsubtractsnames, and of the literals only those equal to a file's stem, or an accessor call's first argument, count;defined_foron a boundary would mask its input unseen;4150b7d4fixes these:adds,subtractsordefined_forgives stays a dependency whatever file defines it, so a name the file index misses refuses as unresolved. A string names a parameter wherever it sits, one that names no parameter refuses, and a list item with a period names a parameter, as the engine reads them (L3);defined_foras unread (N2, N3);trusted-names.mdgains the two rows in this round's evidence.New tests: 16 in
test_ssi_inventory.py. A name the stem index misses refuses in eight layouts; a string names a parameter undergov.and elsewhere; one that names no parameter refuses; a list item with a period names a parameter;defined_forkeeps a dependency of any stem the index finds; and a name equal to its own variable stays no dependency.f92719cecarries the provisional tier recount in the Tests section.Results at
f92719ce:-I, gives the sameinventory.jsonbytes (sha25693f6efbf…), and neither release refuses;The round-12 delta review (at
f92719ce) asked for revision, with three medium findings. Each broke a claim the PR states for every input, in forms only invented modules reach; no record of either release changes under the fix.defined_foror a label equal to a file's stem made an engine input derived, and its default reached the calculation unrecorded, while anaddsof parameters only, or of a parameter that lists nothing, made an engine aggregate an input.-Icommand could give two inventories for one source.Its low findings:
addsorsubtracts;Its notes: N1, a file with no
valuesraisedKeyError; N2, the safe-direction refusals needed a sentence; N3 and N6, the first limit was inexact; N4, the birth-evidence log's expected failure; N5, whenunreadcan fail on a correct record.cba389abfixes these:defined_forgate resolves, and an oracle child compares each pinned record's input status withis_input_variable();get_parameterdoes, by exactos.listdirnames, to a.yamlfile of dated values, with aValueErrorfor anything else (M3, N1). A naming attribute that names its own variable refuses, a formula's lagged read of its own variable stays no dependency, and a formula prefix that names nothing refuses; in both releases all 38 record–prefix pairs, over 22 distinct prefixes in each release, name a.yamlfile;calculate_household.compile_reform({})returns None, so the runner passes a reform whenever a case has an override, not always (L3);federal_ssi_variable_count(L5);unreadsays when it can fail on a correct record (N5).claim-sweep.mdin the round's evidence). Five rules differed in forms the engine refuses to load, and the reader now refuses each: two computation modes in one variable; adefined_forthat names an Enum or str variable; a variable name in two files; a parameter file that repeats a key; and a.ymlfile in the SSI parameter tree. The engine also refuses a variable with no label, which the reader does not check: the header states that limit.trusted-names.mdgains four rows: the dotted-name mapping, the self-name,set(records), and dependency emptiness as the input rule.New tests:
test_ssi_inventory.py, a net 80 (81 added, the inverted test removed): the body-literal test, the input rule's 8 forms and an input's followed dependencies; 10defined_forgates; 30 refused and 6 admitted naming forms; the self-names and a lagged self-read; 5 formula prefixes; repeated keys and a.ymlfile; 4 mixed and 3 single computation modes, one in a followed module; a name in two files; and three layouts read under four hash seeds in child processes;test_ssi_inventory.py, 6 more fromcb728630, for the four mutants that survived atcba389ab: a class read from a stem file after another file, a formula prefix at a.ymlfile, a boundary's literaladdsthat names itself or an absent parameter, and a parameter file that holds a list or nothing;test_ssi_engine.py, 4 that build no country system: the core harness for the input rule, for the naming forms and for the load-time refusals, and a static check of the core constants the reader mirrors. The attribute oracle and the trace test gain the assertions above.Results at
cb728630:-I, gives the sameinventory.jsonbytes (sha25693f6efbf…), and every record of 2.2.1 and of 2.18.0 equals the recordf92719ce's reader gives;208b4d49(1 passed);The round-13 delta review (an Opus 5.5 reviewer, at
208b4d49) approved, with no high or medium finding. Both pinned releases keep byte-identical records, all 37 of round 14's mutants fail, and it found three low findings and seven notes. Invented modules reach each of them, and round 15 found that pinned lists also reach one, the future-only list below.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, and the next PR that moves the pinned release must recheck each limit below. 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.
146c3723narrows the claims round 13 falsified, in text only: both files' syntax trees match208b4d49's, docstrings aside. This body narrows the same claims.cba389ab's need this correction. The core harness shows the engine reading most of the header's safe-direction forms, and it raises onstring_folderandstring_node_fileas the test spells them. The table holds five load errors, where the message says three more.Stated limits, one line for each form:
.yml: the reader'srglobrefuses a.ymlfile below a subfolder of the SSI parameter tree, and no test covers that depth (mutant V3 survives).index.yml,reference.ymlor__pycache__.ymlin that tree: the reader refuses, though the engine loads none of them as a parameter.adds = Noneorsubtracts = None: the reader refuses, and the engine treats the variable as an input.scale[0]) or abaseline.name: the reader refuses, and the engine reads it.index,referenceor__pycache__: the reader resolves it as the engine does, and nothing pins that (mutant V2 survives).addsorsubtracts, a formula dated past the period, or a formula past itsend: the record marks the variable derived, asis_input_variabledoes, and the engine gives the default with nothing supplied.addswhose parameter starts after the period: the reader admits it, and the engine raisesTypeErrorat that period. Pinned lists have this form: in both releasesearned.yaml,unearned.yamlandcountable.yamlstart on 1975-01-01, andprepareaccepts 1974. The pinned route refuses every year before 2022 first, as the round-16 entry below shows, so no pinned case reaches that error.inventory.json.Master
6413d842merged with conflicts only intests/README-tiers.mdandtests/tier_counts.json, which take master's blobs and then this PR's recount: unit 20,294, artifact 4,271, integration_psid 1,471, reproduction_legacy 520, oracle_policyengine 336, 26,892 in all.Master
18082859(S0.1: source, exposure, access and power audit for SM2–SM4 and ED1–ED2 #588) merged the same way:7659cd08takes master's two tier files, and56bbcde8recounts them to unit 20,454, artifact 4,271, integration_psid 1,471, reproduction_legacy 520, oracle_policyengine 336, 27,052 in all.Results at
ace1f1c5. They stand at56bbcde8, sincegit diff --name-only ace1f1c5 56bbcde8names only S0.1: source, exposure, access and power audit for SM2–SM4 and ED1–ED2 #588's own files and the two tier files, none of which these runs read:-I, gives the sameinventory.jsonbytes (sha25693f6efbf…);ace1f1c5(1 passed);208b4d49's, docstrings aside.The round-15 delta review (GPT-6.1 Sol, at
56bbcde8) asked for revision, with two medium findings, both falsified claims. Neither is a regression, and regeneration gave the same records..ymlsentences left out the file stem__pycache__, which the pinned core also skips.ssi_earned_incomeuses the earned list andprepareaccepts 1974. A core harness over those bytes raisesTypeErrorfor 1974 and returns a value for 1975.c865dce1answers both and changes no runtime path:RULES_ENGINE_GAPfrom the worker, and 2022 gives the first result. The worker's error readsParameterNotFoundErrorto 2016 andSPMInputErrorfrom 2017 to 2021;test_years_before_2022_end_in_a_counted_refusalholds seven of those years and 2022;check_versionsrefuses any release but the pin, so the next PR that moves the pin must recheck this limit.Results at
c865dce1:-I, gives the sameinventory.jsonbytes (sha25693f6efbf…);c865dce1(1 passed);56bbcde8's, docstrings aside.The round-16 delta review (GPT-6.1 Sol, at
c865dce1) approved, with no finding:index,referenceand__pycache__, and the reader's docstring and this body name all three;inventory.jsonbytes, and its separate runs pass contract 20, runner unit 41 and inventory 729;The review's own probes through the real runner timed out on its lane, so it asked for one more run on the host. At
c865dce1(2026-11-02, 14:39Z), its probe with no policy overrides ran two invented cases. 1974 ends in a countedRULES_ENGINE_GAP(ParameterNotFoundError), and 2022 gives a result: 2 attempted, 1 accepted, 1 refused, denominator 2. The checkout stayed clean.Upstream, after the approval: SSI: retirement funds never count as resources, but POMS SI 01120.210 counts an owner's accessible lump sum policyengine-us#10446 files the retirement-fund gap, and its RuleSpec mirror is Encode SSI retirement-fund resources under POMS SI 01120.210 (PE-US #10446 parity) TheAxiomFoundation/rulespec-us#1910. Comments on SSI: deemed benefit is capped at the individual rate instead of the no-deeming amount, and couples are identified by tax roles policyengine-us#10138 and Encode the SSI spousal-deeming benefit limit (20 CFR 416.1163(d)-(f)) and SSI couple definitions (416.1801(c), 416.1806, 416.1160(d)) (PE-US #10138 parity) TheAxiomFoundation/rulespec-us#1706 confirm that the spousal-deeming cap gap is still on PE-US
mainand add two boundary cases.axiom: n/a: microsim-side interface, inventory and contract over the certified PolicyEngine release; no country-model or RuleSpec encoding changed (the retirement-fund gap goes upstream as a separate issue)
🤖 Generated with Claude Code