Some checks failed
ci / check (push) Failing after 4s
The two AM-4 budgets had the SAME scope -- one package, no dev edges -- while claiming to bound different things. AM-4b now measures the workspace with dev edges: 57 crates / 725,258 lines where it read 29 / 317,021, having been blind to 28 crates and 408,237 lines, more source than its own target. Target 745,000, ~2.7% of room -- the same margin ADR-0008 D3 gave AM-4a, applied to a number that grew because the instrument was repaired, not because anything was added. The target moved to fit the measurement. T02: proc-macros are COUNTED here and excluded from AM-4a, on purpose. AM-4a asks what ships and a proc-macro never ships. AM-4b asks what is acquired, and ADR-0007 D3's acquisition rule counts what the build fetches -- 'it does not ship' is no answer to 'we downloaded it'. When the rules disagree, the question each budget asks decides. Measured share 109,585 lines / 15.1% against AM-4a's 36.2%, so ADR-0008 D2's refusal to borrow the ratio was right by more than a factor of two. Caught by this project's own earlier work twice: the mutation find-string went stale and --self-test reported it BUILD-FREE (the check CB-WP-0015 added after AM-4a's rotted for two passes), then the DFD gate caught facts.toml carrying the old numbers. CB-EV-0001 and ADR-0004 carried live fact: tags on historical readings. A dated record asserting a CURRENT value is a category error, so those occurrences are marked as-measured instead of retro-edited, and ADR-0004 gains a supersession note. make all exits 0. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
301 lines
12 KiB
Markdown
301 lines
12 KiB
Markdown
---
|
|
id: CB-WP-0019
|
|
kind: meta
|
|
title: "Budgets: what the meta budget is for, AM-4b's scope, and the self-quoting rule"
|
|
status: todo
|
|
state_hub_workstream_id: "ecf35aae-8549-4338-9e13-21dcf14c1130"
|
|
---
|
|
|
|
# Purpose
|
|
|
|
```
|
|
structural tier M (changes how the loop constrains its own operation:
|
|
a budget's scope and target, and a reporting rule)
|
|
chaos d8 = 5 → no override
|
|
declared tier M
|
|
```
|
|
|
|
Declaration 2 of chaos window 2, and **the first roll at d8**.
|
|
|
|
**Meta budget is 0%** over the trailing three, all product. ADR-0006 D2
|
|
exempts instrument repair anyway, and this is the repair four evidence
|
|
files have listed as owed.
|
|
|
|
## Two numbers that have been owed for five passes
|
|
|
|
Both were measured before this declaration, so the work is scoped against
|
|
facts rather than an intention to find them.
|
|
|
|
**AM-4b's scope**, owed since CB-EV-0012 §3:
|
|
|
|
| | crates | lines |
|
|
|---|---:|---:|
|
|
| AM-4b as instrumented (`games-ground`, `--edges normal`) | 29 | 317,021 |
|
|
| the whole workspace, dev edges included | 57 | 725,258 |
|
|
| **uncounted** | **28** | **408,237** |
|
|
|
|
**The dev-toolchain budget is blind to more source than its own target
|
|
of 350,000.** `criterion`, `clap`, `ciborium`, `quick-js` and now
|
|
`cb-game-runtime`'s dev graph are all invisible to it.
|
|
|
|
**AM-4b's proc-macro share**, owed since ADR-0008 D2: **109,585 lines,
|
|
15.1%** of the real graph.
|
|
|
|
That 15.1% is worth stating plainly, because it **vindicates a decision
|
|
made for the right reason**. ADR-0008 D2 refused to correct AM-4b using
|
|
AM-4a's measured 36.2%, saying *"correcting a second instrument on the
|
|
strength of the first one's ratio is the error this change exists to
|
|
fix."* The shares are 36.2% and 15.1%. Borrowing would have been wrong by
|
|
a factor of more than two.
|
|
|
|
## Task: give AM-4b a scope, and a target that matches it
|
|
|
|
```task
|
|
id: CB-WP-0019-T01
|
|
status: done
|
|
priority: high
|
|
state_hub_task_id: "b6b209c5-ecd7-4685-aa96-d0bc4d9c0df1"
|
|
```
|
|
|
|
Decide what AM-4b is **for**, then instrument that.
|
|
|
|
The two honest candidates, and the choice needs an argument rather than a
|
|
default:
|
|
|
|
- **Widen it** to the whole workspace with dev edges — everything a
|
|
contributor's `cargo test` acquires. Then the target must move with the
|
|
instrument, exactly as ADR-0008 D3 moved AM-4a's, and **the target moves
|
|
to fit the measurement, not the measurement to fit the target.**
|
|
- **Narrow the claim** to what it actually measures and rename it, if
|
|
"one package's non-dev graph" is the thing worth bounding.
|
|
|
|
Whichever wins, **do not repeat ADR-0008 D3's generosity by reflex.** That
|
|
decision gave back a small rounding-up because a target with 1.5% of room
|
|
fails on a patch release; a target set 130% above the current reading
|
|
would not be a budget at all.
|
|
|
|
**Controls:**
|
|
- the mutation must still go red — AM-4b's row is currently enforced and
|
|
must stay so;
|
|
- a test that the configuration measures what its name says: if it claims
|
|
dev edges, a dev-only dependency must move the number. `quick-js` is the
|
|
case to use, because it is dev-only and it is what exposed this.
|
|
|
|
**Done 2026-08-03.** **Widened.** AM-4b now asks *what a contributor
|
|
acquires* — `--workspace --edges normal,dev` — and reads **57 crates /
|
|
725,258** where it read 29 / 317,021.
|
|
|
|
The two budgets had the **same scope** while claiming to bound different
|
|
things, which is the whole defect. They now differ by construction:
|
|
AM-4a is `-p games-ground --no-default-features`, AM-4b is the workspace
|
|
with dev edges. `GameKernel.md` §5c states which question each asks.
|
|
|
|
**Target 745,000**, ~2.7% of room — the same margin ADR-0008 D3 gave
|
|
AM-4a, applied to a number that grew because the instrument was repaired
|
|
rather than because anything was added. **The target moved to fit the
|
|
measurement.**
|
|
|
|
Controls: `quick-js` must be visible to AM-4b and invisible to AM-4a, both
|
|
asserted — it is the dev-only crate that exposed the blindness in
|
|
CB-WP-0014, when it landed and the number did not move.
|
|
|
|
**And the pass was caught by its own earlier work, twice.** Changing the
|
|
target invalidated AM-4b's mutation find-string; `mutation-check
|
|
--self-test` reported it **build-free**, which is the check CB-WP-0015
|
|
added after AM-4a's mutation rotted unnoticed for two passes. Second
|
|
catch, first that cost nothing. Then the DFD gate caught `facts.toml`
|
|
carrying the stale 317,021/350,000.
|
|
|
|
## Task: the proc-macro share, decided not just measured
|
|
|
|
```task
|
|
id: CB-WP-0019-T02
|
|
status: done
|
|
priority: high
|
|
state_hub_task_id: "6a90d069-d300-42ff-9bf6-e793f60bcf5a"
|
|
```
|
|
|
|
15.1% is measured. What is owed is the **decision**: does the dev budget
|
|
exclude proc-macro crates as the shipped one does?
|
|
|
|
The shipped case was easy — a proc-macro never reaches a shipped binary,
|
|
so counting it in "what a game ships" was simply wrong. **The dev case is
|
|
not the same question.** A proc-macro *is* acquired, *is* compiled, *is*
|
|
unaudited third-party source on a contributor's machine, and the
|
|
acquisition rule (ADR-0007 D3) counts what the build causes to be fetched.
|
|
|
|
So the arguments point opposite ways and the answer is not inherited.
|
|
Decide it, and say which of the two rules governs when they disagree.
|
|
|
|
**Whatever is decided, ADR-0008 D2's note that AM-4b's share is unmeasured
|
|
must stop being true in the source.**
|
|
|
|
**Done 2026-08-03. Counted, not excluded — the opposite of AM-4a, on
|
|
purpose.**
|
|
|
|
AM-4a excludes proc-macros because they run in the compiler and never
|
|
reach a shipped binary; counting them in *"what a game ships"* was simply
|
|
false. AM-4b **counts** them, because ADR-0007 D3's acquisition rule
|
|
counts what the build causes to be **fetched**, and a proc-macro is
|
|
fetched, compiled and unaudited on a contributor's machine like anything
|
|
else. *"It does not ship"* is no answer to *"we downloaded it"*.
|
|
|
|
**The rule for when they disagree: the question each budget asks decides.**
|
|
That is what ADR-0008 D2 left open.
|
|
|
|
Measured share: **109,585 lines, 15.1%**, against AM-4a's 36.2% — so
|
|
ADR-0008 D2's refusal to borrow the ratio was right by more than a factor
|
|
of two. The `unmeasured` note is gone from `dep-weight.py` and the spec.
|
|
|
|
## Task: write the self-quoting rule down
|
|
|
|
```task
|
|
id: CB-WP-0019-T03
|
|
status: todo
|
|
priority: high
|
|
state_hub_task_id: "b473ab42-8fd9-47b1-8fd4-b181c75440be"
|
|
```
|
|
|
|
Six passes, six under-reports, both halves of the defect diagnosed, and
|
|
the rule still lives only in evidence files:
|
|
|
|
| pass | reported mid-flight | settled | under by |
|
|
|---|---|---|---|
|
|
| CB-WP-0009 | $6.73 | $11.31 | 40% |
|
|
| CB-WP-0011 | $4.23 | $7.02 | 40% |
|
|
| CB-WP-0012 | $8.82 | $14.52 | 39% |
|
|
| CB-WP-0013 | $5.78 | $8.26 | 30% |
|
|
| CB-WP-0015 | $15.14 | $22.70 | 33% |
|
|
| CB-WP-0017 | $5.19 | $9.48 | 45% |
|
|
|
|
**Six for six, always low, never by less than 30%.** That is not noise;
|
|
it is a systematic bias with two identified causes (CB-EV-0013 §5,
|
|
CB-EV-0015 §6):
|
|
|
|
1. a pass's window runs to the **next** pass's first commit, so the
|
|
previous pass is not final until the one after it starts;
|
|
2. **a figure read earlier in a session is an in-flight figure regardless
|
|
of whose name is on it** — quoting from memory defeats the rule even
|
|
when the boundary is right.
|
|
|
|
Put it in `specs/InnerLoop.md` as a rule with both halves, and make
|
|
`loop-lint` check what it can. A rule that lives only in prose has been
|
|
re-derived three times already.
|
|
|
|
**The honest question to answer while writing it:** is the right rule
|
|
"quote two passes back", or "re-run the instrument at quote time", or
|
|
both? T03 of CB-WP-0018 used the second and it worked. Say which is load
|
|
bearing.
|
|
|
|
## Task: say what the meta budget is *for*, and set it at 80/20
|
|
|
|
```task
|
|
id: CB-WP-0019-T05
|
|
status: done
|
|
priority: high
|
|
state_hub_task_id: "a17f949c-ac86-4e7e-8a8a-8159e2d4ad45"
|
|
```
|
|
|
|
The maintainer, 2026-08-03:
|
|
|
|
> *"we should establish a rule for what the budget is for. The main budget
|
|
> should be spent on the task at hand while some of the budget should be
|
|
> spent on control, review and improvement of the process we use to propell
|
|
> us forward. We can make that 80/20 to start with and allow for increasing
|
|
> or lowering the meta budget based on the phase or task at hand."*
|
|
|
|
META-25 has a threshold and **no stated purpose** — which is why it has
|
|
been argued about as a number three times. Write the purpose first; the
|
|
number follows from it.
|
|
|
|
### The window and the ratio have to be chosen together
|
|
|
|
The budget is measured over a **trailing 3-pass window**. One meta pass
|
|
among three, at the same cost as its neighbours, is already **33%**. So a
|
|
20% soft line over three passes does not mean *"one pass in five is
|
|
meta"* — it means *"one in five **and** at half the cost of a product
|
|
pass"*, which pushes meta work toward being rushed rather than rare.
|
|
|
|
| window | what a 20% line requires of a meta pass |
|
|
|---|---|
|
|
| trailing 3 | costs **half** a product pass |
|
|
| **trailing 5** | costs **the same** as a product pass |
|
|
|
|
**80/20 over a trailing 5-pass window is the literal reading of the
|
|
instruction:** one pass in five, at normal cost. Adopt that, and say in the
|
|
spec that the ratio and the window are a pair — changing one without the
|
|
other changes what the rule means.
|
|
|
|
### The phase dial, and why it must not be a dial
|
|
|
|
*"increasing or lowering based on the phase or task at hand"* is right —
|
|
stage 0 and a stabilisation phase should not carry the same ratio. But a
|
|
threshold anyone may move is not a threshold, and this project has a
|
|
standing rule that a limit is fixed structurally rather than raised
|
|
(four loadability breaches, `make status`'s 40 lines).
|
|
|
|
So the phase setting must be **declared, argued, and expiring**, in the
|
|
same shape `gates.toml` already uses: a value, a reason, a `review_by`
|
|
after which it reverts to 20 unless re-argued. Raising it silently to pass
|
|
a breach is the failure this shape exists to prevent.
|
|
|
|
**Controls:** `status.py`'s self-test must cover the new window and ratio,
|
|
and must fail if a phase override has no reason or no expiry.
|
|
|
|
**Done 2026-08-03.** InnerLoop **v1.7**.
|
|
|
|
**The purpose is written first, and the number follows from it:** *most
|
|
spend on the task at hand; some on control, review and improving the
|
|
process that carries the work forward.* `make status` now prints it above
|
|
the figure, because a threshold with no stated purpose is what let this
|
|
number be argued three times.
|
|
|
|
**Soft 20% over a trailing 5**, and the self-test enforces that they are a
|
|
**pair**: `META_SOFT_PCT == 100 / TRAILING_PASSES`. Moving the ratio to 25
|
|
without moving the window turns it red — *"25% over 5 passes; one meta
|
|
pass at parity reads 20%"*. That invariant is the rule's whole content;
|
|
without it the two numbers drift and "80/20" quietly means something else.
|
|
|
|
**The phase setting is declared, argued and expiring**, in `gates.toml`
|
|
beside the gate it governs. Verified live: with a setting present the line
|
|
moves to 35%, prints its reason, and announces *"reverts to 20% on that
|
|
date unless re-argued"*. A setting with **no reason** or **no expiry** is
|
|
refused by `--self-test`, not honoured — so the line cannot be raised
|
|
quietly to pass a breach.
|
|
|
|
**Measured effect of the change**, which is the point of adopting it
|
|
rather than asserting it: the last five passes read **7%** against the new
|
|
20% line. The old rule read 0% over three. Neither is a breach; the new
|
|
one is measuring a window in which a meta pass can actually appear.
|
|
|
|
`InnerLoop.md` crossed the 400-line loadability limit three times while
|
|
this was written, and was fixed structurally each time — the meta-budget
|
|
arithmetic, the cost-per-response basis, and the two review case studies
|
|
moved to `InnerLoopReference.md`. **The limit was not raised**, per the
|
|
standing precedent it exists to enforce.
|
|
|
|
## Task: evidence
|
|
|
|
```task
|
|
id: CB-WP-0019-T04
|
|
status: todo
|
|
priority: high
|
|
state_hub_task_id: "b499acb2-b728-4db9-9714-c235fb6c6363"
|
|
```
|
|
|
|
`evidence/CB-EV-0017-*.md`.
|
|
|
|
- **The AM-4 family, closed or not.** Four defects found across five
|
|
passes, none by looking for them. State whether any remain and whether
|
|
the family is now trustworthy — and if a fifth is plausible, say where.
|
|
- **What five passes of being "owed" cost.** These two numbers were
|
|
carried as open items in four consecutive evidence files. Either the
|
|
carrying was cheap and correct, or it was a way of not doing the work;
|
|
say which, with the cost.
|
|
- **Quote CB-WP-0018's cost by re-running the instrument.** Under the rule
|
|
T03 writes down.
|
|
- **The meta budget's new shape**, and what it would have said about the
|
|
last five passes had it been in force. If 80/20 over trailing-5 would
|
|
have failed passes that were plainly right to run, say so — that is the
|
|
ratio being wrong, not the passes.
|
|
- **Chaos: declaration 2 of 12 in window 2, first roll at d8.**
|