Kernel: a machine user's approval is measured from the act that read the description, and one nothing anchors holds an edit (#195)
Part of #195, on the Factory Builder's ruling of 2026-11-07. It closes the requirement #550 left on it. A machine user's approval is now measured from the start of the approving act's Run that read the description, not from the moment the approval lands. So an edit made in the act's last seconds, between its read and its approval, holds the item. The record is NNNN until it is given a number at enqueue.
#195 closes when #196's shims land, the approve.yml shim among them, as ruled.
What changes
| File | Change |
|---|---|
kernel/derive.py | approval_anchor dates each approval in one of three ways. An act's approval: when the latest issue-approval Run on its content was made, by made_at, its dispatch, which a re-run keeps. A browser's approval (decision 0046), where a record of the item started no later than it: its own time. Otherwise before every time, so any edit holds: with no such record, beside a re-run act with no dispatch read, or with a record whose time cannot be read. description_anchor takes the records by name only, and derive always passes them |
tests/test_decide.py | test_an_approval_is_anchored_at_the_act_that_read_the_description, which also holds that derive gives the records, an empty list included, and that nothing else calls the anchor. One existing case gets a record before its 12:05 approval, so it keeps testing what it meant |
tools/mutants.py | Twenty mutants under "Issue 195", and three of 0135's repointed at the lines they mutate now, each killed by the test its row names |
docs/decisions/NNNN-⦠| The record, which amends 0135's anchor and 0140's first "does not see" clause; its rows name their mutants as 0154 asks |
Why an approval with no record holds, not falls back
Records expire oldest first, and an act's Run is made before its approval, so it is not gone while a record made before it stays. With no record that old, the approval may be an act's whose Run has expired, and falling back to the approval's own time would reopen the gap. The record names the residuals. An item whose oldest retained record postdates a browser's approval holds on any edit, which fails safe. Two pass an edit unseen: an act's Run a person deletes by hand, and a Run made while the act ran, whose record's start is when it was made (P-44), once the act's Run is past retention. #609 takes up the second, and #608 teaches the simulator's world the Run anchor (a protected edit).
Not changed
facts/1 and the held-out cases: run records already carry started_at. The simulator's sim/world.py and tests/test_simulator.py (protected) are also unchanged. description_anchor with no records given keeps the world's reading, since the world's act records its Run in the approval's own second, and derive always gives the records.
Protected paths
None.
Reviews
| Round | Head | Reader | Read, and what changed |
|---|---|---|---|
| 1 | 8107a3c | Claude, with security | A re-run moved the act's start past its approval: fixed in 0d131e3 (timed by dispatch) |
| 1 | 8107a3c | Codex | The same re-run case: fixed in 0d131e3, and a re-run with no dispatch read holds in 5951e4e |
| 1 | 8107a3c | Astra, as Muse's stand-in (Muse: not run, quota) | The latest act untested; a record after the act but before the approval: fixed in 0d131e3 (test, and the lane in the record) |
| 1 | 8107a3c | Argon | The latest act untested: fixed in 0d131e3 |
| 1 | 72e8d34 | The Builder | Guard the runs=None default: keyword-only, and tests that derive gives the records and nothing else leans on it |
| 2 | 5951e4e | Claude | An impossible date raised; the lane does not stop a dispatch: fixed in eaaaf2d |
| 2 | 5951e4e | Argon | A finer test pair: in #609 |
| 3 | eaaaf2d | Claude | A record's start is when it was made, even while it waits (P-44): the record names it as a residual (5d9f8a8), #609 |
| 3 | 5d9f8a8 | Argon | An unreadable start beside a readable dispatch passed, against the rule that an unreadable fact holds: fixed in 590d44d |
| ā | 5d9f8a8 | verify | The simulator's seed 69: a later first-attempt act with no dispatch was taken for a re-run: fixed in 590d44d |
| 4 | 590d44d | Claude, Argon | No blocker; a non-text start test, in #609; a wording row, fixed in b6d3b6f |
Verify
make verify on an export of 590d44d (b6d3b6f differs only in the record's wording), the record numbered in the export only: 1658 tests, OK, the simulator among them. Each Issue 195 mutant is killed by the test its Boundary row names. Muse's read is owed after 2026-11-09 (not run, quota); Astra read in its place.
š¤ Generated with Claude Code