Repository navigation
Epic: nine gaps in the Kernel, found in review #29
Description
Nine places where the Kernel on main decides wrongly or cannot decide, found by a review of the pull request "Context for the Factory's authors: lessons, standards, decisions and the checks that hold them". Five are pinned there as tests marked @pending in tests/test_decide.py, class NotYetHeld. Those tests exist only once that pull request has merged.
This epic is separate from "Epic: slice 0, foundations. The repo holds the line, its context is tested, and the platform facts are recorded": none of these is a condition of slice 0's exit, and all are needed before the Kernel gates anything real in slice 1.
How a pinned gap is closed
- Take
@pendingoff its test. It now fails for real. - Write the rule in
kernel/. The test passes. - Add the rule's mutant to
tools/mutants.py. A rule that acts in two places gets a test and a mutant for each. - In every document that says
not held yetbeside that test, remove those words.make verifyfails until this is done, and says where.
A gap that is not pinned needs its boundary test written first.
The gaps
| Gap | State | Story |
|---|---|---|
| 1. A Pause does not stop approvals and merges | Pinned; ready to build | A Pause stops every act |
3. An unknown mergeable converges |
Pinned; ready to build | An unknown merge state defers |
| 4. A dependency update waits for a model review | Pinned; ready to build | A dependency update needs no model review |
| 2. A queued pull request that loses its approval stays queued | Pinned; needs a ruling | What takes a pull request out of the queue |
| 5. A writer's request for changes does not gate | Pinned; needs a ruling | A request for changes from a person with write access |
6. A neutral check is read as failed |
Needs a ruling | What each check conclusion means |
| 7. A Lens that never reports waits for ever | Needs a ruling | When waiting becomes the Maintainer's to see |
| 8. Nothing counts acts | Needs a ruling | How an act is recorded and bounded |
| 9. The Lifecycle check bounds only cycles made wholly by the Factory | Needs a ruling | Bounds in the Lifecycle data |
Two smaller ones are one more story: the facts have no completeness flag for the list of Runs, and the configuration may name no deterministic Lens.
Rules
- One story to a pull request, at most four acceptance criteria, the failing test first.
- A story that needs a ruling starts by asking the Maintainer, with choices, the recommended one first. Nothing is built before the answer.
- The Kernel does no I/O, keeps nothing between calls, and writes no number but 0 and 1: a limit is read from
config/defaults.json. - A new fact goes into
schemas/facts.schema.json,examples/facts.json,tests/support.pyandsim/world.pyin the same change, with a counter-example underexamples/invalid/. - A change to the Kernel is read once by a second model family before its pull request is opened.
What was verified, and by whom
Gaps 1, 2, 3, 4 and 6 were reproduced by calling decide(). Gap 5 is confirmed by its pinned test failing as expected. Gaps 7, 8 and 9 were reported by a reviewing agent that ran them and were not run a second time.
Activity
don-petry commentedon Oct 14, 2026
#29 Build order for the eleven sub-issues
#30, #31 and #32 go first, in that order. Then:
kernel/derive.pyand adds a map to the configuration. It produces the deferral that Kernel: when waiting becomes the Maintainer's to see #36 later makes visible.acts_since_writerandmax_acts_per_item. It comes after Kernel: a Pause stops every act, not only Runs #30, so every act already defers under a Pause.max_acts_per_itemamong them.These files are shared, so the stories that touch them must run one at a time. This is a source of merge conflicts, not a dependency:
tests/support.pyandsim/world.py: Kernel: two smaller gaps in what it is given #39, Kernel: what each check conclusion means #35, Kernel: a request for changes from a person with write access #34, Kernel: how an act is recorded and bounded #37, Kernel: when waiting becomes the Maintainer's to see #36, Kernel: what happens to a Finding that does not gate #55.kernel/derive.py: Kernel: an unknown merge state defers #31, Kernel: a dependency update needs no model review #32, Kernel: what each check conclusion means #35, Kernel: a request for changes from a person with write access #34, Kernel: what takes a pull request out of the merge queue #33, Kernel: what happens to a Finding that does not gate #55.kernel/decide.py: Kernel: a Pause stops every act, not only Runs #30, Kernel: how an act is recorded and bounded #37, Kernel: what takes a pull request out of the merge queue #33, Kernel: when waiting becomes the Maintainer's to see #36.lifecycle/pull_request.jsonandtools/check_lifecycle.py: Lifecycle check: bounds in the data for every cycle with no person in it #38, Kernel: what takes a pull request out of the merge queue #33, Kernel: when waiting becomes the Maintainer's to see #36.tools/mutants.py.don-petry commentedon Oct 16, 2026
Every story in this epic has merged. The last was "Kernel: every change of State that derive can make is declared" (#102). In order: #30, #31, #32, #39, #37, #38, #35, #34, #33 (#93), #36 (#94), #55 (#96), #60 (#98), #61 (#100), #81 (#102). Follow-ups filed from its reviews belong to the slice-0 epic: #95, #97, #99, #103.