Skip to content

0.69 verb set V: every one of the 111 registered apr verbs is receipted or refuses by name on Qwen3.5 #3597

Closed as not planned
1 of 1 issue completed

Description

@noahgift

owner: aprender-a7 (re-owned 2026-10-09 by clerk aprender-3e for cop aprender-13: no open children)
Every verb apr exposes is in V (passes on the blessed model with a receipt, both CUDA host classes), in V2 (passes or refuses by name), or is an explicit refusal carrying removed_by. Nothing silent. Operator ruling 2026-09-20: 0.69 is verbs that are true; 0.70 is verbs that are fast.

The universe is bound — use these numbers, do not re-derive them loosely

Measured on apr 0.68.2 (crates.io) 2026-09-20:

fact value
verbs in apr --help 112
commands in contracts/apr-cli-commands-v1.yaml (SSOT) 111
difference exactly one: clap's builtin help. Zero registry verbs missing.
of the 111: *-lint family 32
of the 111: everything else 79

So the denominator for "verbs not classified" is 111, and FALSIFY-CLI-001/002 is holding — the registry is trustworthy as the universe. Use the registry, not --help.

apr agent does not exist. The proposed refusal table lists "apr code / apr agent on Qwen 3.5". code is real; agent is not in the binary. Per the operator's own rule 2 read in the other direction, that is a list defect — drop agent rather than dogfood it.

The work

  1. Diff the registry against the V / V2 / refusal tables. Every one of the 111 lands in exactly one bucket. A verb in none is a list defect, filed before the cut.
  2. Dogfood the [U] rows at m=1 on the blessed model (Qwen3.5-4B-Q4_K_M.gguf, sha256 00fe7986…, a validated ladder rung), on intel + gx10: chat, code, tool-call round-trip through serve.
  3. Each becomes PASS with a receipt or a refusal with removed_by and a named exit code. No third outcome.
  4. Release-notes rows are generated from the receipts, not written as prose.

Known-RED going in — these are inputs, not discoveries

done_when

  1. 0 of the 111 registry verbs is unclassified. The *-lint family (32) may take one blanket disposition rather than 32 rows — propose it, do not assume it.
  2. Every V row has a receipt on both CUDA host classes (intel + gx10), or has been moved to a refusal with removed_by. Partial coverage is a refusal, not a pass.
  3. Every refusal states one line, an exit code, and removed_by. A refusal whose text names the wrong defect is a fail-open — today's The autonomous-merge arming gate has six assertions that are inert on jq 1.6 (the majority of the pool) — a zero-byte receipt is stopped by one unrelated line #3594 refuses an empty receipt while saying delta_sweep.status is '', which a test asserting only "it refused" would score as a pass.
  4. Backend: and other diagnostics go to stderr; Completed in … goes to stdout. Any receipt-capturing harness reads both, and says which stream each field came from.
  5. The classification is committed as data the release notes are generated from, not as prose in a PR body.

Blessed model, both host classes, m=1. Refs #3080, #3545, #3541, #3542, #3595, #3596.

Activity

  1. added this to the 0.69.0 milestone on Sep 20, 2026
  2. added
    P0Critical priority
    epicEpic — multi-story umbrella
    on Sep 20, 2026
  3. noahgift commented on Sep 20, 2026

    @noahgift
    MemberAuthor

    BLOCKED on #3605 for the refusal bucket. removed_by has no shape, no schema and no validator — 0 occurrences tree-wide on origin/main. Operator ruling 2026-09-20: no refusal is written anywhere until removed_by has a shape, settled as a pv contract (refusal-receipt-v1, or a field on parity-receipt-v1), decided by this lane at Phase 0 from Σ at HEAD.

    That inverts the order I assumed when minting this ticket. The interim removed_by: v0.70 I ruled earlier stands only until #3605 lands, and any refusal written under it gets re-checked before the cut.

    The V and V2 classification work is not blocked — only the refusal bucket is. Start there.

    Also added to this ticket's scope by the instrument lane's finding, for item 3: the computed but unexposed class has its first confirmed entry for free — PhaseTimings { prefill_ms, decode_ms } is measured on the CUDA path and consumed only by serve; apr run cannot reach it. Not missing, unreachable. That is a different defect from "not implemented" and nothing currently looks for it, so item 3's question for every verb is "does it expose what the codebase already computes?" alongside "does it work?"

  4. noahgift commented on Sep 21, 2026

    @noahgift
    MemberAuthor

    done_when 1 and the data form of 5 are done (PR #3642). done_when 2 is the row that decides 0.69, and it is a handoff.

    V  41    V2  69    refusal  1    unclassified  0        41 + 69 + 1 = 111
    

    Derived from contracts/apr-cli-commands-v1.yaml, not hand-listed; scripts/derive_verb_classification.py --check fails if the committed classification is not what the registry produces today, falsified both ways.

    The number that changes the budget: the dogfood denominator is 41, not 111

    requires_model in the registry is the discriminator, and it is a structural fact rather than a judgement:

    bucket rule n
    V requires_model: true — model-bound, so it can carry a receipt on the blessed model, and owes one on both host classes 41
    V2 requires_model: false — takes no model, so "receipted on Qwen3.5" is not a statement that can be made about it 69
    refusal explicit, with removed_by and now a measured exit code 1

    Most of the registry cannot be receipted on a model at all. Anyone sizing done_when 2 from the headline 111 would be budgeting nearly three times the work that exists.

    The *-lint blanket disposition, proposed as asked

    All 32 go to V2, because all 32 carry requires_model: false — not 31, not "mostly". That is a disposition from a property they share rather than an exemption because counting to 32 is tedious. If one ever gains requires_model: true it leaves V2 automatically and the check says so.

    The one refusal, now measured rather than cited

    bench, measured on apr 0.68.2 (e6f77c98c) against Qwen3.5-0.8B-Q4_K_M.gguf:

    • exit code 5, refusal on stderr
    • "Architecture 'qwen35' is the Qwen3.5 hybrid (Gated Delta Net, detected tensor blk.0.ssm_a) … Load it with apr run / apr chat, which dispatch this architecture to the hybrid forward."

    It names the right defect and the right alternative, so it is not the fail-open done_when 3 warns about. removed_by: v0.70.

    A quorum caught that my first revision quoted done_when 3 in a comment and shipped a refusal with no exit code — 3/3 unanimous. The script now refuses to emit the file at all when a refusal row is missing any of exit_code / line / removed_by / reason / stream / measured_on.


    HANDOFF — done_when 2 is compute-bound and needs both host classes

    41 V rows each need a receipt on intel AND gx10. done_when 2: "Partial coverage is a refusal, not a pass." Every V row is currently dogfood: U, which records that a receipt is owed and absent. A U is not a pass and nothing in #3642 infers one.

    This row is not analysis-bound, it is host-bound, and I do not have both classes. A session with intel + gx10 time can take it by selector — the denominator is 41, the blessed model is Qwen3.5-4B-Q4_K_M.gguf (sha256 00fe7986…, a validated ladder rung), m=1, and the classification file is the worklist: filter bucket: V.

    If nobody has host time before 2026-09-22 18:00Z, this issue slips at freeze on done_when 2 alone, and that is the honest reason to record — not a scope problem, a host-availability one. done_when 3 (refusal text quality) and done_when 4 (stream discipline) also remain open, though both are much smaller than 2.

  5. modified the milestones: 0.69.0, 0.70.0 on Sep 21, 2026
  6. noahgift commented on Sep 21, 2026

    @noahgift
    MemberAuthor

    slipped_from: 0.69.0

    §4.1 freeze (06x-release-schedule.md §1: "scope that is not on the platform rides the next train"). Operator, 2026-09-21, verbatim: "just by these optimization you should be able to release 0.69 today, ensure this happens". The 0.69 platform is #3669 plus the bump.

    Why this row rides 0.70: done_when 1+5 are in #3642, which is red and not on the platform. Per the 2026-09-21T00:22Z comment, done_when 2 "is the row that decides 0.69, and it is a handoff". It is not done at the freeze.

    — aprender-04 (cop)

  7. modified the milestones: 0.70.0, 0.69.1 on Sep 21, 2026
  8. noahgift commented on Sep 21, 2026

    @noahgift
    MemberAuthor

    Cop: moved to 0.69.1 and absorbed into #3745 (cells DERIVED from apr's clap surface, SHACL-enforced). Every command without a model arg owes one cell (runs, or refuses by name). The 111 come from the binary's surface, not a list.

  9. modified the milestones: 0.69.1, 0.70.0 on Sep 23, 2026
  10. 21 remaining items

  11. added
    P1High priority
    and removed
    P0Critical priority
    on Oct 14, 2026
  12. noahgift commented on Oct 14, 2026

    @noahgift
    MemberAuthor

    P0 to P1 (2026-10-14 P0 triage): P0 now means it blocks the next release or carries the operator's own words on it; this issue does neither, so it stays on the 0.71.0 milestone at P1. The operator quote in its history is a milestone-wide triage note, not words about this issue.

  13. noahgift commented on Oct 14, 2026

    @noahgift
    MemberAuthor

    merged into #5312 (master ticket for epic #3994; triage rule 7b, 2026-10-14). It is a checklist row there; reopen this issue when work on it starts or its PR opens.

  14. noahgift commented on Oct 14, 2026

    @noahgift
    MemberAuthor

    Moved: this sub-ticket is now a row in #5332 (Release receipts: every verb receipted, version-exact receipt keys, a working install.sh), split out of #5312 by theme.

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

    P1High priorityepicEpic — multi-story umbrella

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions