Skip to content

phase2: the inventory's disposition verdict runs in no gate, and the committed phase2-inventory.txt is stale (#1758) #1804

Open

Description

@InauguralPhysicist

Found by the #1758 R1.1 round-2 blind critic (PR #1776), 2026-10-15, on branch phase2-numbers at cdfb128. Both files below exist only on that branch.

Design 2.5 and 2.7 (R1.1, row 2) say a slot classifier with no reviewed disposition is caught because "the inventory fails on an unreviewed entry". The inventory does fail. But no gate runs that verdict:

  • tools/phase2_check.sh --through R1.1 runs tokens, int-source, slot-test, corpus-diff and smi-trap. None of them runs tools/phase2_inventory.py's verdict.
  • The slot test's runner calls phase2_inventory.py --slot-population, which returns (line 832) before the disposition check (line 943). It lists only function entries whose first parameter is an EigsSlot.
  • No workflow, precheck row or suite section runs the full inventory.

Reproduce

Append a new classifier to a copy of src/vm.c:

int critic_new_reader(Value *v) {
    EigsSlot s = slot_from_heap(v);
    return slot_is_bool(s) ? 1 : (slot_is_null(s) ? 2 : 0);
}

Results on the copy:

  • python3 tools/phase2_inventory.py --no-write exits 1:
    FAIL: slot classifier `vm.c:critic_new_reader` has no disposition row
    slot classifiers: D1=56 D2=19 D3=25 T=67 dispositions=99 missing=1 stale=0
    phase2-inventory: FAIL
    
  • --slot-population still prints slot-population: entries=33, so the slot test is unchanged.
  • The token gate (tokens: rounds<=R1.1 tokens=5 files=89 hits=0) and the int-source check both pass.

So phase2_check.sh --through R1.1 (and R1.2, whose 464 forced sites are where new classifiers appear) passes with an unreviewed classifier.

The committed generated file is stale too. docs/design/phase2-inventory.txt says "generated by tools/phase2_inventory.py; do not edit", but at cdfb128 it differs from a fresh --out in 753 lines:

  • examined=1818 (fresh: 1826);
  • dispositions=98 (fresh: 99);
  • NUM_CMP, INT_BINOP_R, CASE(NEG) and CASE(BNOT) are still recorded guarded (fresh: unwired, the R1.1 fix round's change);
  • #define SLOT_SMI_TRAP is missing.

phase2_check.py's plan checks read their ## Numeric arms from that committed file.

Done when

  • phase2_check.sh --through R1.1 and --through R1.2 run the inventory's verdict as a mechanical gate, and it fails on phase2-inventory: FAIL. The planted critic_new_reader above turns that gate red and names the function.
  • At the branch head, docs/design/phase2-inventory.txt equals a fresh tools/phase2_inventory.py --out byte for byte, and the same gate fails when they differ. Alternatively, the file is no longer committed and the plan checks derive the numeric arms themselves.

Activity

  1. added 2 commits that reference this issue on Oct 15, 2026
    348ab6a
    2a20ace
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:gatesSubsystem: gatesfound-by:criticInstrument that surfaced it: critickind:gate-defectA gate, check or claim that measures less than it says

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions