Kernel: a change to the Factory's own rules or a Lens's inputs is reviewed by a model Lens
Closes #113.
A pull request that changes the Factory's own rules, or the inputs of a deterministic Lens, now converges only once every model Lens has reviewed its current head, whatever its class. The machine user then approves it, as it does every item. Before this, a Dependabot update to .github/workflows/verify.yml was judged by that Lens alone. Per the Maintainer's ruling on #113, no person is needed. The rulings are in the issue's comments, and decision 0020 records them.
What changes
- Facts:
- New
changed_paths, one{path, previous}record per changed file, andcomplete.changed_paths. - A list read short defers (
facts_incomplete). - A list that is malformed, or whose number of records is not exactly
diff.files, holds for the Maintainer (paths_unreadable).
- New
- One list:
config/hooks.json. Itsprotectedentries and a newlens_inputsare read by both the session hooks and the Kernel'sprotected_paths, and a test pins the two matchers to each other.- Lens inputs:
Makefile(in any case),GNUmakefile, every file or link at the repo root (*), a root package's__init__and bytecode (*/__init__.*,__pycache__/,*/__pycache__/), the root packages whole, the check folders,kernel/,.gitleaks.tomland.gitleaksignore. - Empty or malformed list: the Kernel defers (
protected_paths_unreadable). - Where the list comes from: decision 0020 says it is built from the base, never the head. This waits on
controller/.
- Lens inputs:
- Kernel:
required_model_lenses()no longer excusesmodel_not_required_forwhen the change touches the list. A queued item on the list leaves the queue when its head has no model review. - Simulator:
- Three actors make such changes: a Role, Dependabot and the Maintainer.
- It asserts I-45 at approval, enqueue and merge.
- One seed in ten is a dependency update; every other seed replays as on
main.
- Records:
- New decision 0020, which decides 0018's workflow-file row differently: no person.
- I-45 is added to the design. §3.3, §4.6 and §4.9 now say what 0020 decided.
Verified on a git archive export at a534a0f: make verify passes (501 tests); python3 -m tools.mutants kills 348 of 348; check_decisions is clean.
Reviewed by
- A fresh-context Claude review and a security pass. Their findings were fixed in 799f8ee:
- an empty path list marked complete;
- the list must come from the base;
- the missing Lens inputs;
- design-doc drift;
- 0018's Check cell.
- The 400k-pair fuzz of the two matchers found no disagreement.
- AGY, Gemini 4 Argon (799f8ee): two majors and four minors, all real and fixed in 7b5f160. The majors: the matcher's overlap check had no test or mutant, and a malformed pattern failed open.
- CodeRabbit: rename names could fill the path count, so
changed_pathsis now one{path, previous}record per file and must equaldiff.files. Fixed in 7b5f160. - AGY, Gemini 3.8 Flash High (7b5f160; Argon was out of credits): no findings.
- Muse Wonder (
muse-wonder-1.0, 7b5f160) and Codex: one blocker. A root-level package such asunittest/__init__.pyshadowed the stdlib inside verify, so a dependency update converged unreviewed. Fixed in 95c7584. Codex's three other threads were already fixed in 7b5f160. - AGY, Gemini 4 Argon (95c7584, d29be3f, a534a0f): no findings. Muse could not re-read after 7b5f160 (its subscription quota was used up).
- Codex (95c7584, 4e98ba5): two more gaps of the same class. Files inside an existing root package were closed in d29be3f, with a test that every root package is listed whole. A root symlink with no suffix was closed in a534a0f by making every root file or link an input.
- CI:
verifypassed the 30-minute job timeout, which #136 raised to 40. Sharding is #112.
Left out: reading the fact from GitHub (adapters), the ruleset half (#62), the harness refusing such a push, and running each deterministic Lens from the base's inputs (next).
🤖 Generated with Claude Code