A blanket "no retargeting in the measuring commit" rule would have been
wrong. CB-WP-0002 moved AC-1 three times in exactly that shape and every
move was correct -- each time a new instrument disproved the old figure.
Four legitimate corrections would have been forbidden to catch one bad
retarget.
The test is mechanical rather than a statement of intent:
correction the target moves and the implementation does not; legal in
the same commit provided the instrument's output is there
retarget the same commit changes both the target and the code the
target measures; requires an ADR stating why the new target
binds on future work
Applied retroactively: AM-4a/AM-4b are UNRATIFIED. They were set after
seeing the measurement, in the commit that produced it, with the
implementation changing too -- a retarget by this test. make dep-weight
is currently enforcing a target no reviewed decision stands behind.
Recorded as an open item; ratifying or changing them is a maintainer
decision, not an implementer's.
Also: specs/InnerLoop.md split into InnerLoop.md (process) and
InnerLoopReference.md (rubric, template, rules, definition of done).
Not a stylistic choice -- `make loop-lint` failed on the commit that
pushed the file to 407 lines against its own ~400 limit. The gate added
this morning to make that rule executable caught its own author within
the hour, which is the cheapest possible demonstration that it works.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
7.1 KiB
The Inner Loop — Reference
Normative companion to InnerLoop.md, which holds the five steps, the tiers, and the chaos roll. Split from it on 2026-07-31 so both files stay under the loop's own whole-file loadability limit.
Everything here binds exactly as the process document does.
The four-dimension rubric
Every survey, ADR, and acceptance table is organized by these dimensions:
| Dimension | Question | Example measurable proxies |
|---|---|---|
| D1 Ease of specification | How simply can behavior be stated, tested, understood? | rules-to-scenario coverage %, spec lines per rule, time-to-first-correct-scenario for a fresh agent session |
| D2 Efficiency of implementation | How cheap to build and keep building? | source LOC, dependency count/weight, clean-build and incremental-build time, tokens-per-completed-task |
| D3 Speed of execution | How fast does it run? | benchmark wall-time vs baseline, events/sec, memory footprint, determinism overhead |
| D4 Optionality | How cleanly does it integrate, extend, get replaced? | public API surface size, count of leaked foreign types (must be 0), effort-to-swap measured by null/reference impl existence, WIT-expressibility |
Scoring is always relative to the step-1 baseline, never absolute:
better / parity / worse / unmeasured per proxy, with the number attached.
unmeasured is legal in a survey, illegal in an evidence file.
Survey template (research/CB-RES-NNNN-.md)
# CB-RES-NNNN: <capability>
capability: <canonical.capability.id>
status: draft | approved
## Candidates
Per candidate: origin, license, maturity, adoption; data model; mutation
mechanism; determinism/replay story; relevant performance (measured if
runnable locally, cited with source otherwise).
## Baselines (benchmark-to-beat)
| Dimension | Baseline holder | Metric | Value | Provenance |
(one row minimum per dimension; provenance = measured / cited / estimated)
## Verdict
Which candidate leads per dimension; what none of them do well
(the surpass opportunity); risks in the baselines themselves.
Implementation rules the first pass earned
These are cheap, and each exists because its absence cost something in
CB-WP-0001. See history/260731-inner-loop-retrospective.md.
- No silently-ignored input. A field that is parsed and then unused
is a defect, not a stub. Inputs are honoured or rejected with an
error — never dropped. (A scenario
setup.patchwas parsed and discarded; every scenario using it would have tested the wrong initial state while passing.) - Decisions get commands, not defaults. A rule that requires a participant's choice is implemented as a command carrying that choice. Until it is, nothing claims coverage of it — no tag, no scenario, no acceptance row. Inventing a default to make a rule "done" is the failure this prevents.
- Scaffolds are exercised or marked. A scaffold's green gates are not evidence. Any scaffold path no test reaches is marked as unexercised. (A compiling, fully-green scaffold shipped a state-hash that would panic on any state holding a relation.)
- Coverage gates that count tags say so. A gate comparing rule IDs
against
covers:lists proves no rule is unclaimed and no claimed rule is invented. It does not prove a scenario exercises what it names. Wherever such a number is reported, that limit is reported with it.
Agentic-efficiency requirements
The loop exists to be driven by agents. Therefore:
- Whole-file loadability — every loop artifact stays under ~400 lines; split before exceeding, link with relative paths.
- Structured over prose (guidance, not a requirement — nothing can check it) — tables and fenced blocks for anything a later step must parse (baselines, acceptance metrics, evidence rows).
- One command surface — all checks runnable through repo-root
commands (eventually
cb *; until then,make/cargoaliases declared in one place), each supporting deterministic, greppable output. - Self-contained tasks — a workplan task names its input artifacts and output artifacts; a fresh session must be able to execute it from the task text plus linked files alone.
- Evidence or it didn't happen — claims of "better" live in committed evidence files with numbers, never only in commit messages or chat.
Token discipline — per the global budget policy, a loop iteration that exceeds its budget without measurable progress is stopped and decomposed, not pushed through.DEAD POLICY. The 8k/10k per-task token budget was never referenced or enforced, and CB-WP-0001 T08 exceeded it by orders of magnitude with no signal. It implies a control that does not exist. Replacement in USD is CB-WP-0003 T05; until then this is documentation of a gap, not a rule.
6a. Live cost budget (replaces the above) — spend since the last
commit, soft $10.00, hard $22.00, checked by make cost-budget.
Calibrated on the 32 commit intervals of CB-WP-0001 (p50 $1.40, p90
$9.36, max $10.80), so both thresholds bind on future work rather than
ratifying past work. Contract: CostAccounting.md
§7 (CB-01, CB-02). It fires on the open remainder rather than per task
because per-task cost needs the commit that closes the task, and a
budget that can only report after the money is spent is the dead policy
this replaces.
Enforcement status. Rules above that a command can check are enforced
by make loop-lint; the full classification of every InnerLoop rule as
executable / checkable / decorative, with the failure class each catches,
is in history/260731-inner-loop-rule-audit.md. Rules marked guidance
or dead say so where they appear, so a reader can tell a requirement
from a preference without consulting the audit.
Definition of done — one loop pass
A capability has completed the loop when all of the following are committed:
- research/CB-RES-NNNN with approved status and full baseline table
- decisions/ADR-NNNN with per-dimension expected advantage
- specs/.md with acceptance-metrics table
- passing scenarios covering every numbered spec rule
- evidence/CB-EV-NNNN with final comparison vs baseline, no
unmeasured - every reported number produced by a harness with a positive control; any metric that could not be instrumented is recorded as uncomputable rather than estimated
- every unmet metric reported as unmet, with attribution and the options for resolving it — a missed target is an output of the loop, not a reason to move the target quietly
- cost recorded:
make costrun for the pass, its composition (not only its total) in the evidence file, and the per-task figures pushed to the hub. M-D2-CST is no longer allowed to beuncomputable— the instrument exists (CostAccounting.md) - retrospective note (may be one paragraph appended to the evidence file): what the loop itself should change