diff --git a/decisions/ADR-0006-adaptive-control-gates.md b/decisions/ADR-0006-adaptive-control-gates.md new file mode 100644 index 0000000..163e14b --- /dev/null +++ b/decisions/ADR-0006-adaptive-control-gates.md @@ -0,0 +1,132 @@ +# ADR-0006 — control gates are experiments, and they measure their own window + +Status: **accepted** 2026-08-01 +Tier: M (structural S by the letter of InnerLoop's table — no capability +port, no canonical interface, no dependency — declared **M** because it +changes how the loop constrains its own operation. This is the *second* +recorded instance of that gap, after CB-RES-0005 §6, which said a second +instance should trigger the change. D5 is that change. Chaos d4=3, no +override; declaration 4 of 12.) + +Supersedes nothing. Amends InnerLoop v1.5 → **v1.6**. + +## Context + +Six passes of loop work produced five standing control mechanisms: the +cost budget (CB-01/CB-02), the session-shape budget (SH-1/2/3), the +mutation harness (M-D1-MUT), the DFD fact gate, and the meta budget +(v1.5). [CB-EV-0007](../evidence/CB-EV-0007-stage-0.md) measured what +they have been worth and found three defects in the *design of gates*, +not in any one gate: + +1. **The meta budget could not see the pass it governed.** It aggregates + over every attributed task ever closed, so CB-WP-0008 — 100% product — + read `61% OVER`. This is the identical defect CB-RES-0005 §1 found in + SH-1/SH-2 and CB-WP-0007 T01 fixed for session shape. It was + *reintroduced two tasks later, by the person who had just fixed it*. +2. **The budget blocked its own repair.** v1.5 forbids opening meta work + above the line; the fix for the budget is meta work; the budget was + over. CB-RES-0005 §4 rejected build-gating session shape for exactly + this shape — *"a gate that blocks the remedy when the metric breaches + is not a gate, it is a trap"* — and the trap was then built elsewhere. +3. **Gates accumulate and nothing retires them.** Five mechanisms, no + expiry, no review. Three artifacts in this repo *do* carry one — the + chaos roll's 12-declaration window, AM-4c's withdrawal, and + `CommitWindow`'s delete-by 2026-12-31 — and all three came from + individual argument rather than from a rule. + +The maintainer's instruction that opened this pass: *"experiment our way +to sensible, task- and context-specific control and review gates that +drive continuous and adaptive optimization."* These decisions are the +smallest step that makes gates experimental rather than permanent. + +## Decisions + +### D1 — A budget measures the window it governs + +Every budget reports the window it constrains, and names it in its own +output. Cumulative figures are retained and labelled **history**. + +The meta budget becomes **per-pass** (since the current workplan's first +commit), matching CB-01/CB-02's since-last-commit window and CB-RES-0005 +D1's windowed session shape. Provenance: `adapted:sre-error-budget`, the +same rolling-window shape already adopted once here. + +**Refuted if** the windowed figure and the cumulative figure stay within +20% of each other across two passes — in which case aggregation was not +the problem and the extra machinery should be deleted. + +### D2 — A soft breach is a signal; repairing the instrument is exempt + +Two changes to v1.5's meta budget: + +- **Instrument repair is always in-budget.** Work that fixes the + instrument reporting a breach may be opened regardless of the reading. + A gate must never block its own remedy. +- **The maintainer may authorize above-line work explicitly**, recorded + in the workplan's frontmatter (`authorized_above_budget: `). + This pass carries the first one. Undocumented above-line meta work + remains a violation the evidence file must report. + +The rest of v1.5 stands: soft, a started task may be finished, and a +breach is reported rather than enforced. + +### D3 — Every control gate declares a review trigger + +A gate without an expiry is a permanent tax justified once. Each entry in +`gates.toml` declares: what it checks, what it has **caught** (with +evidence pointers), a `review_by` date, and **what would retire it**. + +`make gate-review` reports gates past their review date and gates that +have caught nothing since they were added. It **reports**; it does not +fail the build, for CB-RES-0005 §4's reason. + +The trigger for actually retiring one is deliberately not automatic: +a gate that has caught nothing may be preventing rather than missing. +The report forces the argument to be made on a date, not never. + +**Refuted if** a review cycle passes with no gate either retired, +tightened, or explicitly re-justified — that would make it a ritual, and +this document's own D4 says rituals cash out or go. + +### D4 — Loop work cashes out into something runnable, in the same pass + +From CB-EV-0007 §5: cost per response across five passes was 0.123, +0.228, 0.362, 0.298, 0.123 dollars, and the pattern that survived the +data is that **cost tracks distance from a runnable check**. The passes +that shipped a command were cheap; the passes that argued about what a +number means were not. + +So: a `meta` pass must ship at least one executable check, command, or +gate. Findings that remain prose are recorded as findings and do **not** +count as delivery. + +**Refuted if** a prose-only meta pass demonstrably lowers cost per +response or catches a defect class no command could have. Stated because +it is the plausible counter-case: CB-WP-0003's conclusion that +class-by-class hardening does not converge was prose, and was correct. + +### D5 — The tier table covers changes to the loop's own operation + +CB-RES-0005 §6 recorded that InnerLoop's tier triggers are all *code* +properties ("new capability port", "canonical interface", "dependency"), +so a change to how the loop constrains itself scores **S** — one +paragraph in a commit message — however consequential. It declined to fix +this on one instance. This ADR is the second. + +New trigger, at **M or above**: *changes whether or how the loop +constrains its own operation* — budgets, gates, review requirements, tier +rules themselves. + +## Consequences + +- `make status` reports a per-pass meta share; cumulative moves to + history. Existing readings are not comparable to new ones, and the + first output says so. +- A new `gates.toml` and `make gate-review`; `loop-lint` gains a check + that every gate in the Makefile has an entry, so the registry cannot + silently fall behind the gates it describes. +- InnerLoop → **v1.6**. +- One more thing to maintain. That is the honest cost, and D3's own + review trigger applies to `gate-review` itself: if it has retired + nothing by 2026-12-31, it is a ritual and goes. diff --git a/workplans/CB-WP-0009-adaptive-gates.md b/workplans/CB-WP-0009-adaptive-gates.md new file mode 100644 index 0000000..5576967 --- /dev/null +++ b/workplans/CB-WP-0009-adaptive-gates.md @@ -0,0 +1,125 @@ +--- +id: CB-WP-0009 +kind: meta +title: "Make control gates experimental: window them, review them, cash them out" +status: proposed +authorized_above_budget: "maintainer, 2026-08-01 — 'improve our policies where it seems promising; we will experiment our way to sensible task- and context-specific control and review gates'. Meta read 59% at the time." +state_hub_workstream_id: "" +--- + +# Purpose + +[ADR-0006](../decisions/ADR-0006-adaptive-control-gates.md) (tier M, +survey merged into the ADR from [CB-EV-0007](../evidence/CB-EV-0007-stage-0.md) +§3 and §5; chaos d4=3, no override, declaration 4 of 12). + +Six passes produced five control mechanisms and no way to retire any of +them. CB-EV-0007 found three defects in how gates are *designed*: + +1. the meta budget cannot see the pass it governs — the same cumulative + defect CB-WP-0007 T01 had just fixed for session shape, reintroduced + two tasks later by the same hand; +2. it blocks its own repair, which is the trap CB-RES-0005 §4 named and + rejected for session shape and then got built anyway; +3. nothing retires a gate. + +This pass is **`kind: meta` and above the budget line**, on explicit +maintainer authorization recorded in the frontmatter — the first use of +ADR-0006 D2, and a deliberate exercise of it. + +Per **D4**, every task here ships something runnable. A task that ends in +prose has not delivered. + +## Task: the meta budget measures the pass it governs + +```task +id: CB-WP-0009-T01 +status: todo +priority: high +state_hub_task_id: "" +``` + +ADR-0006 **D1**. `make status` reports the meta share **for the current +pass** — the window since the active workplan's first commit — and keeps +the cumulative figure labelled *history*, exactly as `cb-cost`'s session +shape block does since CB-WP-0007 T01. + +The instrument-repair exemption (**D2**) is what makes this task legal to +open at 59%, so the task must also *state* the exemption where the budget +prints, or the next reader will re-derive the same standoff. + +**Predicted:** the windowed share for CB-WP-0008 reads at or near 0% — +it was a pure product pass — against 61% cumulative. +**Refuted if** the two land within 20% of each other, in which case D1 is +wrong and the machinery should be deleted rather than kept. + +## Task: `gates.toml` and `make gate-review` + +```task +id: CB-WP-0009-T02 +status: todo +priority: high +state_hub_task_id: "" +``` + +ADR-0006 **D3**. A registry of every standing control gate: what it +checks, what it has caught (with pointers), `review_by`, and **what would +retire it**. `make gate-review` reports what is overdue and what has +caught nothing. + +Seed it with the mechanisms that exist today — the cost budget, the +shape budget, mutation coverage, the DFD fact gate, the meta budget, the +chaos roll, the kernel spec→code gate, and `gate-review` itself, which is +not exempt from its own rule. + +**The positive control this needs:** a registry that silently drifts +behind the Makefile is worse than none, so `loop-lint` gains a check that +every gate target has an entry and every entry names a real target. Its +own self-test must fail when an entry is removed. + +## Task: InnerLoop v1.6 + +```task +id: CB-WP-0009-T03 +status: todo +priority: medium +state_hub_task_id: "" +``` + +Fold **D2**, **D4** and **D5** into `specs/InnerLoop.md`: + +- the breach-is-a-signal wording and the two exemptions (instrument + repair; recorded maintainer authorization); +- the cash-out rule, with its refutation condition; +- the tier trigger for changes to the loop's own operation, closing the + gap CB-RES-0005 §6 opened and this ADR's own tier declaration used. + +`InnerLoop.md` is at its 400-line loadability limit, so this task +**displaces** as much as it adds: the chaos-roll rationale and the v1.1 +→ v1.4 change log move to `InnerLoopReference.md`, leaving the rule and a +pointer. Loadability is itself a gate; growing the file to fit a rule +about gates would be the joke writing itself. + +## Task: control loop — did the changes fire? + +```task +id: CB-WP-0009-T04 +status: todo +priority: high +state_hub_task_id: "" +``` + +Commit `evidence/CB-EV-0008-adaptive-gates.md`. Four questions, all +answered from output, not argument: + +1. **Does the windowed meta share differ from cumulative?** Against + T01's prediction; refuted within 20%. +2. **What does `gate-review` say on its first run?** A registry where + every gate is current and every gate has caught something is a + registry that was written to look good — say which entries are + uncomfortable. +3. **Did D4 hold for this pass?** Three of four tasks here ship a + command; T03 is prose. State whether the rule survives its own first + pass or needs the exception written down. +4. **Cost**, against the 0.123–0.362 per-response range, and the meta + share this pass itself consumed — reported under the rule it wrote.