Skip to content

feat(ladder): model gate universe = each host's measured Q4_K inventory; no Q4_K rung optional (#3712 row A) - #3721

Closed
noahgift wants to merge 2 commits into
mainfrom
PMAT-3712-ladder-universe-inventory
Closed

noahgift wants to merge 2 commits into
mainfrom
PMAT-3712-ladder-universe-inventory

Conversation

@noahgift

@noahgift noahgift commented Sep 21, 2026

Copy link
Copy Markdown
Contributor

#3712 row A: the model gate's universe is each host's measured Q4_K inventory; no Q4_K rung is optional

Operator 2026-09-21: "you must ensure all models Q4_K CUDA work; the end". The gate measured a hand-picked list with an escape hatch, and a fleet sweep found reds that were on no list. This PR is done_when 1 + 2 (the gate side). done_when 3 + 4 (T-1 on both hosts, and proof on a real train) belong to the release-tooling lane.

What changes

file change
contracts/model-capability-ladder-v1.yaml ladder.inventory {dirs, case-insensitive *q4_k*/*q4k* .gguf/.apr patterns, backends [cuda]}; MCL-INV-006/007; FALSIFY-MCL-011..014
scripts/model_ladder.sh measures ladder ∪ the host's inventory with one measure() (a rung and an inventory model cannot drift); receipt v2: inventory [{file, sha256, bytes}], file per row, apr_sha (full 40-hex)
scripts/check_model_ladder.sh FAIL: required not true on a Q4_K rung · Q4_K rung not claiming cuda · ladder without inventory · receipt not v2 / no inventory / EMPTY inventory · inventory model MISSING from the run (named) · inventory-only model not green on cuda (skip, fallback, rc≠0 = RED)
scripts/lib/model_ladder_cases/ 18 → 26 cases, each red for its own reason; fixtures migrated to v2
GPU lock (cop ruling) every apr call in model_ladder.sh goes through apr_locked = flock -E 75 -w ${MODEL_LADDER_LOCK_WAIT:-1800} /tmp/apr-gpu.lock choom -n 1000 --; a lock still held after the wait → ENV decline (exit 2) naming the holder pid from /proc/locks. The judge audits it statically in the REAL run and behaviourally in --self-test (FALSIFY-MCL-015)

Measured on this head

  • check_model_ladder.sh --self-test: 26 cases, 0 bad, and 3 self-mutants killed (q4k-required-false by red-q4k-required-false, q4k-without-cuda by red-q4k-rung-cpu-only, inventory-missing by red-inventory-model-missing). It gives the same result when run from /tmp. --case no-such-case gives rc 1.
  • Lock: a fake apr via --lock-probe sees lock=LOCKED oom=1000; a lock held by another pid declines with rc 2, holder: pid <N>. Four producer mutants are killed, each for its own reason: raw-apr-call (static audit), no-lock (UNLOCKED), no-choom (oom=0), unbounded (rc 124, no bounded decline).
  • The real contract: check_model_ladder.sh --version 0.70.0 prints FAIL rung qwen3-8b-q4km is a Q4_K rung with required: False plus the missing receipts, so T-2 is RED.
  • pv validate ok · pv lint contracts/ PASS (11 armed) · census and contracts.nt unchanged · cargo test -p aprender-contracts --lib 1684 passed / 0 failed · guard_tree --no-cargo 76 checks, 0 failed · shell-lint ratchet PASS · bashrs 0 errors.
  • Producer dry-run on lambda found an inventory of 18 Q4_K files, versus 8 ladder rungs.

Where the gate runs (a round-1 lane read its rc=1 as a PR red)

check_model_ladder.sh is declared only in Cargo.toml [package.metadata.dogfood] gates (line 612, the T-2 pre-publish dogfood). It is also listed in scripts/unwired_guards_baseline.txt (line 12): no PR workflow runs it, and guard_tree skips it (unwired-baseline). Its rc=1 on the real contract is therefore the release NO-GO the operator asked for, not a PR red. pv lint is a different tool that never runs this script, and it PASSES on this head.

Deliberately NOT here (cop ruling)

qwen3-8b-q4km stays required: false. Flipping it turns pv lint contracts/ red on every PR: the armed ladder-green shape reads the committed 0.68.2 lambda receipt (golden_output: Empty output). I measured rc 0 → 1 with only that flip, one PV-ONT-011 missingGreenHost: lambda. The gate refuses the key at T-2, so the release cannot ship on it. The flip folds into 0.69.1 alongside the qwen3-8b fix and a committed green lambda receipt. The widened bar (verb × thinking × context-rung cells) is row B, stacked on this one.

Refs #3712
keep-open: #3712 row A only. done_when 1's "no required: false" clause lands with the qwen3-8b fix in 0.69.1; done_when 2's cells go green through the model fixes; done_when 3 and 4 belong to the release-tooling lane; row B adds the verb × thinking × context cells.

🤖 Generated with Claude Code

…inventory; no Q4_K rung is optional

Operator 2026-09-21: "you must ensure all models Q4_K CUDA work; the end". The gate
measured a hand-picked list with an escape hatch (qwen3-8b-q4km required: false, red
on lambda at 0.68.2 and 0.69.0), and a full fleet sweep then found reds that were on
no list at all. This row is #3712's done_when 1 + 2 (the gate side).

- contract: `ladder.inventory` {dirs, case-insensitive *q4_k*/*q4k* .gguf/.apr
  patterns, backends [cuda]}; MCL-INV-006/007 and FALSIFY-MCL-011..014.
- model_ladder.sh: measures ladder ∪ the host's inventory with ONE measure()
  function (a rung and an inventory model cannot drift), and writes receipt v2:
  `inventory` [{file, sha256, bytes}], `file` per row, `apr_sha` (full 40-hex).
- check_model_ladder.sh FAILs on: `required` not true on a Q4_K rung, a Q4_K rung
  that does not claim cuda, a ladder with no inventory, a receipt that is not v2 /
  has no or an EMPTY inventory, an inventory model MISSING from the run (named), and
  an inventory-only model not green on cuda (skip, fallback and rc != 0 are RED).
- case table 18 -> 26, each red for its own reason; 3 self-mutants, each killed by
  its case; `--case` naming no case is RED; the root comes from the script path.

qwen3-8b-q4km stays `required: false` in the contract by cop ruling: flipping it
turns `pv lint contracts/` red on every PR (the armed ladder-green shape reads the
committed 0.68.2 lambda receipt, "Empty output"; measured rc 0 -> 1 with only that
flip). The gate now refuses the key at T-2, so the release cannot ship on it; the
flip folds into 0.69.1 with the qwen3-8b fix and a green lambda receipt.

Refs #3712

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@noahgift

Copy link
Copy Markdown
Contributor Author

quorum-review (AD-04): NOT agreed (auto_merge: checked=true was_armed=false disarmed=false)

{
 "ticket": "PMAT-3712",
 "head": "789e4124fe72bf1ea1d7c9714a0ede1570e2a8c1",
 "width": 3,
 "executor": "agy",
 "agreed": false,
 "auto_merge": {
  "checked": true,
  "was_armed": false,
  "disarmed": false,
  "note": "auto-merge not armed"
 },
 "lanes": [
  {
   "lane": 1,
   "verdict": "FAIL",
   "findings": 2
  },
  {
   "lane": 2,
   "verdict": "FAIL",
   "findings": 1
  },
  {
   "lane": 3,
   "verdict": "PASS",
   "findings": 3
  }
 ]
}

@github-actions

Copy link
Copy Markdown

§13.11 rung 1 — quorum shadow verdict

S13-SHADOW pr=3721 head=789e4124fe72bf1ea1d7c9714a0ede1570e2a8c1 verdict=REFUSE class=Q1 arm_rc=1

Shadow mode: this records a verdict and merges nothing. A refusal
to arm is not a block (§13 adds zero rows to §7) — the pull request is
exactly as green as it was.

…o 1000, with a bounded wait

At 15:56:08Z interactive apr runs on gx10 drove the host into a global OOM and the
kernel killed CI containers (oom_score_adj 500), not apr (0): 18 kills in 10 s. Cop
ruling: the lock lives in model_ladder.sh, per apr call; T-1 wraps the script in
choom only (a second flock outside would deadlock on this one).

- model_ladder.sh: apr_locked = flock -E 75 -w ${MODEL_LADDER_LOCK_WAIT:-1800}
  /tmp/apr-gpu.lock choom -n 1000 -- "$APR"; the only GPU apr call site. A lock still
  held after the wait is an ENV decline (exit 2) naming the holder pid from /proc/locks
  (lslocks leaves PATH empty for files it cannot resolve), never a hang and never a
  model verdict. --lock-probe runs one call through it for the judge's table.
- check_model_ladder.sh: lock_audit (static; also in the REAL run, where a raw
  "$APR" <subcommand> call is RED) and lock_probe (a fake apr sees lock=LOCKED and
  oom=1000; a held lock declines naming the pid). Four producer mutants, each killed
  for its own reason: raw-apr-call, no-lock, no-choom, unbounded.
- contract: the precondition, and FALSIFY-MCL-015.
- fragment: where check_model_ladder.sh runs (dogfood only; unwired on PRs), which a
  round-1 lane misread as a PR red.

Refs #3712

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@noahgift

Copy link
Copy Markdown
Contributor Author

quorum-review (AD-04): three PASS — agreed (auto_merge: checked=true was_armed=false disarmed=false)

{
 "ticket": "PMAT-3712",
 "head": "6eee66bb07e86fe21971df3a4ed513e8064c22c0",
 "width": 3,
 "executor": "agy",
 "agreed": true,
 "auto_merge": {
  "checked": true,
  "was_armed": false,
  "disarmed": false,
  "note": "auto-merge not armed"
 },
 "lanes": [
  {
   "lane": 1,
   "verdict": "PASS",
   "findings": 0
  },
  {
   "lane": 2,
   "verdict": "PASS",
   "findings": 0
  },
  {
   "lane": 3,
   "verdict": "PASS",
   "findings": 0
  }
 ]
}

@noahgift

Copy link
Copy Markdown
Contributor Author

closed by triage (aprender-dd; cop aprender-cf approved): FOLDED, not abandoned. Per the release-process owner aprender-6c [8b6b78]'s ruling on #3712, this row was folded into the 0.69.1 squash batch #3772; its fold order lists it, and its cases are on main. The squash is why its head is not an ancestor of main. Branch kept.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant