teal-sea / zeta-labstate of record · compiled 14 Aug 2026 · revision 9ebdea0 · source

Library · hunts/r_414eed/RESULTS.md

Hunt r-414eed — results

1,822 words · 185 lines · source

Question. Does scripts/make_context.py --check catch its declared smallest mutant, and where does its sensitivity stop?

Answer. It catches it, and it catches every one of the seventeen in-scope mutants tried. The guard's ledger entry can move from fired=None to fired=True. Its scope, previously "undetermined until demonstrated", is now mapped: four blind regions and one narrow miss, all listed below.

Reproduce: python3 hunts/r_414eed/probe.py (~50 s, standard library only — no .venv and no zeta import needed, because the guard itself needs neither). Raw data: results.json.

Controls

Both ran, both held, and without them no row below would mean anything.

controlwhat it rules outoutcome
the unmutated sandbox is run through the guard firsta "catch" produced by the copy rather than by the mutantexit 0, CONTEXT.md is up to date.
after every mutant the undo is checked with a second guard runrow n+1 inheriting row n's mutationquiet after all 24

The repository under test was never written to: every mutation is applied to a throwaway copy under /tmp.

The table

diff is how many lines of the regenerated CONTEXT.md move. token is whether the mutant's own new name appears among them — the difference between the guard seeing the symbol and the guard merely noticing that a file changed length.

In scope — the guard should fire

idmutantfireddifftoken
M01the ledger's declared mutant: public function appended to zeta/core.py, __all__ untouchedyes2no
M02public function appended to zeta/core.py, added to __all__yes3yes
M03public function appended to zeta/adele.py (declares no __all__)yes3yes
M04public function added to ontology/domains/zeta_domain.pyyes3yes
M05public class added to harness/guards.pyyes3yes
M06public function added to dossier/status.pyyes3yes
M07public function renamed in place (xixi_renamed)yes2yes
M08public signature gains a keyword-only argument, in placeyes2yes
M09public docstring's first line changed, in placeyes2yes
M10a whole new module zeta/mutant_module.pyyes6yes
M11an upper-case module constant addedyes6yes
M12a new document docs/mutant-probe.mdyes1yes
M13a document's H1 title changed in placeyes2yes
M14a new script scripts/99_mutant.pyyes1yes
M15a test function added to an existing tests/test_*.pyyes4yes
M16CONTEXT.md hand-edited, tree untouchedyes0n/a
B08one blank line appended to zeta/core.py — no symbol at allyes2n/a

17 / 17.

Boundary probes — where the guard is silent

idmutantfiredis that right?
B01public function added to meta/ledger.pynoscope: meta/ is not indexed
B02public function added to compiler/semantics.pynoscope: compiler/ is not indexed
B03a document added under docs/doors/noscope: doc_index globs docs/*.md, not docs/**/*.md
B04a test file added as tests/mutant_helper.pynoscope: test_counts globs test_*.py
B05a private function appended to zeta/core.pyyesmy prediction was wrong, not the guard — see below
B06private helper promoted to public in place, not added to __all__nothe one genuine miss
B07public docstring changed below its first linenoby design: only the first line is indexed

What the numbers say, in order of how much they matter

1. The guard has power, and the ledger entry is now answerable. The declared smallest mutant (M01) fires. So do sixteen siblings spanning every category the entry's guards_against names: added symbols, renames, new docs, new scripts, new modules, changed signatures. Proposed amendment to harness/departments/guard_ledger.py in HANDBACK.json; this hunt does not apply it.

2. M01 fires for the wrong reason, and that matters. CONTEXT.md prints a per-module line count (*NNN lines*), so any edit that changes a file's length makes the artifact stale. B08 isolates this: appending a single blank line, with no symbol of any kind, fires the guard. M01's token never reaches CONTEXT.md at all — module_api filters by __all__ when a module declares one, and twenty-three of the zeta/ modules do. The guard caught M01 by accounting, not by comprehension.

3. Hence B06, the one genuine miss. Renaming zeta/core.py's private _num to pubnum in place adds a public symbol, changes no file's length, and leaves the name out of __all__ — so the regenerated CONTEXT.md is byte-identical and the guard says "up to date". This is the ledger's declared mutant with the line-count tell removed, and it slips through. It is narrow (it needs a length-neutral edit in an __all__-declaring module) but it is exactly the shape of a real promote-a-helper-to-public commit that then adds the export in a later edit.

4. B05 was my expectation being wrong, not a false alarm. I predicted a private function would be ignored; it fires, because it lengthens the file. The guard's real invariant is not "the public API index is current" but "CONTEXT.md is a byte-exact function of the tree", which is strictly broader. That is the more useful way to describe it in the ledger, and it is why B08 belongs in the in-scope table rather than the boundary one.

5. Four blind regions, none of them accidental-looking, none of them documented. meta/ and compiler/ are real packages with real public functions and no presence in the index at all; docs/doors/ is a directory the repository's own front matter treats as first-class; tests/*.py that are not test_*.py are invisible. Whether any of these should be indexed is a design call this hunt does not make. What it can say is that the ledger's known_misses=() is currently understating the scope, and now has candidates to hold.

What I chose, and why

A copy of the tree rather than the tree itself. Mutating the live checkout would have been simpler, but a guard test that leaves the repository dirty on an interrupt is indistinguishable from an ordinary work-in-progress edit, and this branch is unsupervised. The sandbox also made control 2 (undo re-checked after every mutant) cheap, which is what lets twenty-four rows share one baseline.

Exit code and diff, not exit code alone. CI only sees the exit code. Had I recorded only that, the honest summary would have been "17/17, guard is strong", and finding 3 — the actual miss — would not exist. The extra measurement cost one subprocess per mutant.

Twenty-four mutants rather than one. The brief asked for the declared mutant. One mutant answers fired; it cannot answer scope, and scope is the other field the ledger entry leaves blank.

What I could not settle

Loose threads

The three above are what I noticed and did not chase. One candidate I did check and can rule out: the ledger's known_misses field is not generally empty — all five records that carry an outcome populate it, so the blank on this guard is because nobody had run a mutant, not because the field is decorative.