Provenance: the maintainer reported 'after some time i get an empty page
back. I guess the game crashes or ends but that is unclear as the ui
disappears.' Reproduced by driving a real game to completion over HTTP:
move 5 accepted, then GET / -> Connection refused. The game ENDED
normally, 5 rounds and 30 commands, and its whole result -- coalitions,
scores, winners, hash -- went to the terminal. next_choice only accepts
connections inside a human decision point, so when play() returns the
listener dies and the post-ok reload is refused. A crash and a win
render identically: nothing. Same class as CB-WP-0016's silent drop.
Also carries the chaos rate change CB-EV-0015 owed to the next
declaration (d4 -> d8, second window of 12), which is what makes this
structurally M. Rolled at the old d4=3, no override, because a rate
changes when the decision lands and not retroactively.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Provenance (tier M, structural S, chaos d4=4 -> OVERRIDE drawn M):
the maintainer could drag after CB-WP-0016 but could not tell what was
pickable, held, or droppable. Underneath that, the page was WRONG about
which moves exist: 9 legal commands rendered as 5 cards each claiming
all three target kinds, from a const string in the emitter. Investigate
is legal on problems 2 and 3 but not 1; Solve on 1 but not 2 or 3. The
live page now says 'Solve onto problem 1'.
ADR-0010 restates control 5, which this work would otherwise have
outgrown in silence: every game fact the page acts on must arrive from
Rust as data; the script may read, match and render it, never compute,
infer, filter or default one. The survey's real finding is that the
permitted and forbidden designs are indistinguishable from outside, so
the vocabulary grep is demoted to a cheap first line and two behavioural
properties become the controls -- the highlighted set EQUALS the set
Rust emitted, and anything the page marks legal must resolve. Both
mutation-proven; the derive-legality mutation produces a plausible
highlight (seat-0,1,2 where only seat-1 is legal) and is caught.
Visible now: .pick resting shadow, .held on the grabbed element, .dropok
on every legal target including BOTH drawings of a seat, and a ghost
following the pointer. Nothing perceptual is verified and ADR-0010 D5
says so.
The DOM stub now models classList/querySelectorAll/createElement and
builds its node set from the real emitted page. Trap recorded: QuickJS
fixes its stack limit at Context creation relative to that frame, so a
helper returning a Context makes every later eval report
'SyntaxError: stack overflow'.
CHAOS WINDOW CLOSED, 12 declarations, 2 overrides, one each way. Both
changed the outcome, so the retirement condition is not met. Verdict:
keep, and recommend d4 -> d8 with a second window of 12 -- that is a
change to the loop's own constraints and is owed to the next declaration
as tier-M work, not made here.
CB-EV-0014 corrected: it quoted CB-WP-0015 at $15.14/136 and called it
the first settled figure quoted. Now $22.70/166. The number had been
read during CB-WP-0015 itself, so there are two defects -- the boundary,
and quoting from memory instead of re-running the instrument.
make all exits 0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Provenance: the maintainer ran stage 1's check after CB-WP-0016, could
drag, and reported that the UI gives no way to tell what can be picked
up, what is being dragged, or where it may be dropped. Combined with the
prior finding that the page hides which moves are legal -- measured, 9
legal commands rendered as 5 cards each claiming all three target kinds,
with Investigate legal on problems 2 and 3 but not 1 -- highlighting drop
targets is not decoration, it is the first time the page tells the truth.
Structural tier S: presentation work inside an existing capability.
CHAOS ROLLED 4 -> OVERRIDE, drawn tier M. Second override in twelve
declarations and it rolls the opposite way from the first (CB-WP-0011 was
L rolled down to S), so the calibration window closes with one of each,
which is the minimum that makes its evaluation possible.
Declaration 12 of 12 -- the window closes here and T04 owes the verdict.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Provenance (tier S, one paragraph in lieu of survey and ADR): the human
check that kept INTENT stage 1 open was run and the drag was broken.
Root cause, worth more than the instance: drop targets were ids, and an
id must be unique, so exactly one element could ever be seat-0. The
relationship-graph circle took it and the seat card that every action
card's own text points at -- 'drag Attack onto a seat' -- silently had
none. A seat is drawn twice and both drawings are the seat; the document
model could not express that.
Drop keys are now data-drop. Any number of elements may carry the same
key, so a seat is droppable on its card and on its graph node. Measured
on a live server: seat-0/1/2 each appear twice, id survives only on
cb-status which is the one element the script looks up, and
down=action-attack&up=seat-1 returns ok.
Second defect: a drop on nothing returned without posting and without
touching the status line, so a broken target was indistinguishable from
a working page. resolve already refuses rather than defaulting, which is
right; refusing SILENTLY is not. The page now reports the raw fact --
'took action-attack, let go over nothing droppable' -- which names
elements, not moves, so ADR-0007 control 5 holds.
And the honest part: the general check added here -- every offered
affordance names a key that exists, driven through Policy::choose over
four real bot games -- does NOT catch the reported defect. seat-0 did
exist, on the graph circle. It is kept because a wholly absent target is
a real class, and paired with a targeted regression test that does catch
it. Three mutations, each red for its stated reason, including the
reported defect reintroduced; only the targeted test fires on that one.
A cb-play assertion matched id="action-ground" as a substring while
describing itself as checking the page; rewritten through drop_keys.
make all exits 0. Stage 1 stays open: verified by tests, mutation and a
live server, not by a human dragging.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Provenance (tier S, one paragraph in lieu of survey and ADR): the human
check CB-EV-0012 kept stage 1 open on was run by the maintainer and
found the drag broken. Diagnosed against the live server first:
down=action-attack&up=seat-1 returns ok, so socket, guard, resolve and
dispatch are correct. seat-{n} ids exist only on the SVG circles in the
relationship graph; player_card emits the visible seat cards with no id,
so the target every action card names is inert. jsrun feeds element ids
straight in and never hit-tests, which is why every test passed.
Structural tier S: a defect fix inside an existing capability, and the
check it adds is a product test rather than a control gate. Chaos d4=3,
no override. Declaration 11 of 12.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The rule adopted in CB-EV-0012 -- quote the previous pass's final cost,
never your own -- was applied here for the first time and did not hold.
This file opened quoting CB-WP-0014 at $7.47/34, which is what
make status reported then; by the close it read $8.56/48. A pass's
window runs to the next pass's first commit, so the previous pass is
not final until the pass after it starts. The rule fixed the wrong
boundary. Recorded as owed rather than changed silently.
Also: CB-EV-0009's prediction now has a point on each side. CB-WP-0014
opened above the SH-1 hard line at 0.220 $/response; CB-WP-0015 opened
below it, after a compaction, at 0.111. Both on the predicted side, and
the second is the control the last report said was missing -- but n=2,
different tiers and subjects, and the compaction that supplied the
control is also what makes the passes differ.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Provenance (tier S, one paragraph in lieu of survey and ADR): the two
clauses mutation-check has reported inert since CB-WP-0005. AM-7's
scaling ratio was held up by a test literally named
replay_100k_events_is_linear_and_fast that computed both throughputs,
printed both, and never divided one by the other. AM-8's N=10 was held
up by a runner that does two.
Both are now red. AM-7 3/3, AM-8 2/2, M-D1-MUT 10/14, and ADR-0005's
>=10-of-14 prediction MET for the first time. Neither was closed by
amending the question away, which was the live risk: the denominator is
unchanged and the four unenforced rows are the four already
unenforceable.
AM-7 needed three estimators. Best-of-N per leg then divide (AM-6's,
correct for a floor on one number) gave 0.581-1.085 on an unchanged
binary; legs back-to-back gave medians 0.931-1.004; legs interleaved at
fold granularity give 0.987/0.991/0.989, and 0.989 under 8-way CPU
contention while absolute throughput fell 4x. The INDETERMINATE guard
demanded unanimity and failed a good measurement over one sample
0.001 under the floor; it now requires a two-thirds majority. The
control that matters: AM-6's constant-cost mutation halves throughput
and leaves this ratio at 0.999x green, so AM-7 is not a second AM-6.
AM-8 kept N=10 because the measurement said so. Perturbing the RNG only
from its fourth construction on: --runs 2 PASSES, --runs 10 fails. A
late-onset divergence is deterministic, not flaky, so it is a control
rather than a coin flip. Ten runs live on one scenario (make am8, ~2s)
rather than all 25 (47s a build). GameKernel 5b records it.
The full run also found AM-4a's own mutation stale since ADR-0008 D3
moved the target 250,000 -> 161,000 in CB-WP-0013 -- reported
HARNESS-BROKEN, no score published. The build-free half of that check
is now a --self-test assertion, so make all catches the next one.
mutation-check clauses may now carry their own verify and mutation, and
then the enforced flag is measured rather than declared; a declaration
disagreeing with its measurement is refused.
make all exits 0.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Provenance (tier S, one paragraph in lieu of survey and ADR): the two
clauses tools/mutation-check.py has reported inert since CB-WP-0005 —
AM-7's scaling ratio (nothing relates the two throughput numbers
Criterion prints) and AM-8's N=10 (the runner does two). They are the
last two PARTIAL rows in the acceptance table. Structural tier S:
acceptance rows measure the product, and bench-test is in gates.toml's
not_control_gates list, so the M trigger about the loop's own
constraints does not fire. Chaos d4=2, no override. Declaration 10 of 12.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
CB-EV-0012. Stage 1, deliverable by deliverable:
relationship-graph visualization emitted and gated, NEVER SEEN
drag-to-propose evidenced end to end
debug inspector evidenced (CB-WP-0011)
hot-seat play evidenced here
Hot-seat was the one closest to being claimed on the strength of the code
path existing. SeatPolicy hands every human seat a handle on one shared
Server, so turn-taking "obviously" worked — and nothing drove more than
one seat until now. The property that matters is not that two turns
happen but that the same tab, asked twice, shows two different hands.
Mutating the projection to serve P1's view to every seat turns it red.
The stage stays open on ONE named blocker rather than a vague
reservation: no browser is available to this loop, so the visualization
is evidenced only as correctly emitted. Everything testable from here has
been tested. What remains is `cb-play --serve 0`, open the URL, confirm
the table reads and a drag works. INTENT carries that note now.
The self-quoting rule from CB-EV-0011 §4 is ADOPTED: an evidence file
quotes the previous pass's final cost and never its own. CB-WP-0013
reported itself at $5.78/34 mid-flight; final is $8.26/47, under by 43%.
Four for four, always low.
Meta budget 29% [OVER] soft 25%, driven by CB-WP-0013 in a trailing three
with two cheap product passes; it was an instrument repair, which
ADR-0006 D2 exempts.
SH-1 at 347,720 [HARD] against a 300,000 ceiling. Compaction is the
remedy and this session cannot do it for itself. CB-EV-0009's standing
prediction is now live and testable for the first time in three passes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ADR-0009: embed quick-js; node is refused. Measured marginal cost against
the dev-toolchain graph, under the positive control:
boa_engine 896,410
rquickjs 69,985
quick-js 11,434
node 0 <- and that zero is the problem
ADR-0007 D3's acquisition rule biting its author. CI runs on rust:1.97,
which has no node, so the test would make our build fetch a JS runtime of
tens of millions of unaudited lines while scoring zero on the only
instrument that governs dependencies. A browser is exempt because a
developer has one regardless of us; a CI-installed runtime is not.
The loop is now closed: the real server serves the real page, QuickJS
runs that page's own scripts, the gesture goes over a real socket, and
the seat's Choice comes back. Before this, every link was tested and the
chain was not — a page whose JavaScript sent something else entirely
would have passed everything.
Three controls, each red for its stated reason: the JS posting a command
name instead of ids, the gesture not being delivered (EXPECT-VACUOUS),
and the token stripped from the endpoint.
A wrong assertion worth keeping: the first draft required the body not to
contain "attack". It legitimately does — action-attack is the id of an
element a finger landed on. An element may name an action; that is not
the page deciding. The real test is the shape: exactly two fields, down
and up, carrying two ids and nothing derived from them.
AND the ADR's own cost argument was wrong. It claimed 35% of AM-4b's
headroom; after landing AM-4b did not move at all. It measures
games-ground --edges normal — one package, no dev edges. Measured, the
workspace including dev edges is 725,258 lines against AM-4b's 317,021:
408,237 uncounted, MORE THAN THE TARGET ITSELF (criterion, clap,
ciborium, quick-js). The decision stands on the acquisition rule; the
affordability argument is withdrawn. Third defect in the AM-4 family.
Also fixed structurally rather than by raising a limit: `make status` had
grown past its 40-line readability gate as workplans accumulated. Closed
workplans now collapse to one line, so the report is fixed-size.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Declaration 9 of 12. Structural tier M (adds an external dependency to
the toolchain); d4 = 2, no override.
CB-EV-0010 §4 recorded that the emitted JavaScript has never run, and
that sentence is the only thing keeping INTENT stage 1 open. It was
carried for a pass on the assumption that executing it was not possible
here. node v24.11.1 is on this machine. The assumption was never
checked — the same shape as every other finding of the last three
passes: a claim carried because nobody ran the command that settles it.
Executing it does not prove the table looks right; that needs a
rendering engine and a human eye. It proves the contract ADR-0007
control 5 rests on — that the page reports raw pointer facts and
nothing else — which is currently asserted by grepping the script for
game vocabulary. Grepping for absent words is a weak proxy for "this
code cannot construct a command".
T01 is a real dependency decision, priced under ADR-0007 D3's
acquisition rule so that "it's only a dev tool" is not an automatic
pass. CI runs on rust:1.97, which has no node, so the test either
forces an install or skips — and a test that skips silently is the
harness-does-nothing class this project has found five times.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
CB-EV-0011. Three instruments were wrong; the pass found the third
defect itself and committed the fourth.
The rule this pass should leave behind: an evidence file quotes the
PREVIOUS pass's final cost, not its own. Three for three, all low by a
strikingly consistent ~2/3:
CB-WP-0009 $6.73 reported -> $11.31 final
CB-WP-0011 $4.23 reported -> $7.02 final
CB-WP-0012 $8.82 reported -> $14.52 final
And this time it changed a conclusion. CB-EV-0010 reported the first
priced tier comparison as "0.123 at L against 0.099 at S — 24% more".
The final figures are 0.150 against 0.099 — 51% more. Tier L costs twice
what that comparison claimed. It still deleted a port that would have
been rewritten and found errors of 25x and 85x, so it still looks worth
it, but the price doubled and the file that made the argument could not
have known.
Also closed rather than deferred again: cb-play's "third mode" never
arrived. --serve is a play flag selecting which Policy fills a human
seat; the binary still has two modes, and CB-EV-0010 §6 was wrong.
Carried for two passes, resolved, stopped.
Recorded as a near-miss: an instrument reading that looked impossible
(53 tool calls in 53 responses) turned out to be correct. One
independent re-derivation before writing anything stopped a false
accusation — in the pass whose whole subject is instruments reporting
things that are not so.
gate-review: 0 due, 0 silent, 0 drifted. Every gate in the registry has
a caught entry for the first time.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ADR-0008, tier M (survey and ADR merged).
D1 — SH-3 retired as a gate, kept as a diagnostic. Investigating it
found a third defect, deeper than the two this pass was declared on.
Re-deriving batching from the raw transcripts, independently of cb-cost:
CB-WP-0011 pass 54 with tools 0 batched 0.0%
gap -> next decl 16 with tools 6 batched 37.5%
CB-WP-0012 pass 86 with tools 0 batched 0.0%
gap -> next decl 10 with tools 1 batched 10.0%
CB-WP-0013 so far 10 with tools 0 batched 0.0%
Zero batched turns in 150 in-pass responses; 37.5% in one gap, above the
20% floor. Batching needs two calls whose inputs are known at once —
orientation work. Implementation consumes each step's result before the
next. SH-3's window is since the last commit, which during a pass is
always implementation. The metric could not read above ~0% in the window
it was gated on. A floor the window structurally excludes is not a
target.
This pass's own declaration was also wrong: it claimed batching "has got
worse" (7.8-8.6% vs 1.1-6.3%). Differently-placed windows, not different
behaviour. Withdrawn — the same class of error, in the pass written to
correct it.
Not retargeting to match the measurement: the floor was not moved to 6%,
the gate was removed on an argument about what the quantity is worth.
The number is still reported; only the verdict is gone.
D2/D3 — AM-4a counts --edges normal,no-proc-macro: 157,202, not 246,250.
The target moves down with it, 250,000 -> 161,000, so the correction
hands back essentially nothing (headroom 3,750 -> 3,798). Three controls:
the exclusion drops exactly the five expected crates, only removes and
never adds, and is not a no-op.
The DFD gate then caught the follow-on it exists for — three historical
documents carrying live fact tags for a number that had changed. Not
rewritten; untagged, with a supersession banner.
AM-4b is deliberately not corrected: its proc-macro share is unmeasured.
gate-review now reads 0 due, 0 silent, 0 drifted — GATE-REVIEW earns its
first caught entry by forcing SH-3's re-justification, and the registry
has no silent gates left.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The metric six evidence files reported as 0.0% was never measured.
--shape-budget windows since the last commit, and it is read while
writing the evidence file — right after a commit, when the window holds
one or two responses. SH-1/SH-2 are location statistics and survive n=2.
SH-3 is a rate: at n=2 its only possible values are 0%, 50%, 100%.
cb-cost.py gains sh3_line(), which below a minimum sample prints
"insufficient sample" and no verdict. The floor is derived: if the true
rate were exactly the 20% target, P(zero batched in n) = 0.8^n, and at
n=14 that is 4.4% — so "0 batched in 14" rules out a target-meeting rate
at ~95%. Below that the tool has nothing to say and now says so.
The window was kept rather than split. SH-3 could have been given a
per-pass window, but the budget's purpose is the open remainder since
the last commit, and giving one of three metrics a different window
makes "the window" ambiguous in a tool three specs cite.
Four controls, three mutations, each red for its stated reason —
including the one the evidence files actually hit, where a refusal is
printed as a measured zero.
SessionShape.md §4 carries the correction with the real per-pass figures
(1.1%-6.3%), beside the eighth trusted-arithmetic instance. This is the
ninth, and the second in this same metric. It also shows what the frozen
0.0% hid: against the pinned 7.8%-8.6%, batching has got worse, and six
passes reported a breach that was moving underneath them.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Declaration 8 of 12. Structural tier M (changes how the loop constrains
its own operation — a budget instrument and a gate floor); d4 = 3, no
override. Meta budget reads 0% of the trailing three, so this is in
budget without the ADR-0006 D2 repair exemption.
The SH-3 half is larger than CB-WP-0012 filed it as. "SH-3 has read
0.0% for six consecutive passes" is an artifact: --shape-budget measures
the window since the last commit, and it is read while writing the
evidence file, immediately after a commit, when that window holds one or
two responses. SH-1 and SH-2 are location statistics and survive n=2;
SH-3 is a rate, and at n=2 its only possible values are 0%, 50%, 100%.
Measured over real per-pass windows it is 1.1%-6.3%, not 0.0%. Which
exposes what the artifact hid: the pinned historical rate is 7.8%-8.6%,
so batching has got WORSE, and a metric stuck at a constant could not
have shown it.
That is the ninth recorded instance of the trusted-arithmetic class, and
the second one in this same metric — SessionShape.md §4 already records
"0 of 330 tool calls were batched" as the eighth.
Also owed: AM-4a counts proc-macro crates that never reach a binary
(89,048 lines, 36.2%). The task is explicit that the target must move
down with the instrument, or the pass must argue why 89,048 lines of
unearned headroom are legitimate.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
CB-EV-0010. The pass's own verdict on the tier it ran at.
Full-weight review withdrew the capability port the declaration was made
to build. A tier-S pass has no step 2 and would have shipped it, and
stage 2 would have found it unimplementable — which is what CommitWindow
is already on record in this repo for doing.
Two corrections of the survey's own numbers, compounding:
AM-4a headroom 3,750 claimed -> 92,798 measured (25x)
cheapest windowed 480,501 claimed -> 140,079 measured (3.4x)
headline ratio 128x -> 1.5x (85x)
The prediction from CB-EV-0009 §4 held: meta budget reads 0%, published
in advance and unfalsified.
A correction that is now a pattern: CB-EV-0009 reported CB-WP-0011 at
45 responses / $4.23 / 0.094; final is 71 / $7.02 / 0.099. Still the
cheapest pass, so the conclusion stands. But that is the second
consecutive evidence file to report its own pass's cost low — a pass
cannot measure its own cost, and one quoting its own is quoting a floor.
First priced tier comparison on a single subject: 0.123 $/response at L
against 0.099 at S — 24% more, for a pass that found the two errors
above. On one data point, step 2 is cheap.
Not shipped, and said plainly: the emitted JavaScript has never been
executed. The socket loop is tested end to end with synthetic HTTP and
the page is asserted against as a parsed document, but no browser engine
has run it. INTENT stage 1 therefore stays open even though all four of
its named deliverables now exist.
SH-3 reads 0.0% for a sixth consecutive pass and remains the oldest
unargued number in the project.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Delivers ADR-0007 Decision 1: visualization, drag-to-propose and hot-seat
play, at a measured marginal AM-4a cost of zero.
games-ground shipped: 23 third-party crates
cb-render-html: 23 third-party crates
new crates introduced: 0
Measured, not asserted — the survey's own lesson. AM-4a is unmoved at
246,250; own source is 7,636 -> 9,652.
What shipped:
crates/cb-render-html doc.rs (HTML/SVG emission, incl. the relationship
graph), input.rs (pointer facts -> commands),
serve.rs (Guard, Request, loopback bind)
tools/cb-play hotseat.rs + `--serve PORT`
Per ADR-0007 Decision 2 there is NO cb-render-api and NO cb-render-null.
The renderer targets the existing Project trait; the port waits for
stage 2's wgpu implementation to be its second use.
The six controls, all live, all mutation-checked (8 mutations, each red
for its stated reason):
1-3 token / Origin+Sec-Fetch-Site / explicit 127.0.0.1 bind
4 a token-less request is refused, in the unit AND over a real socket
5 JS may not construct commands — the page reports pointer facts, Rust
resolves them against the legal list the aggregate already offered,
and a test asserts the emitted script contains no game vocabulary
6 the coverage gate crosses the language boundary: it walks the
serialized view for leaf paths and requires each token to appear in
the PARSED emitted document, with a test that the parse really is a
parse (script/style contents must not count as rendered)
The gate fired on its author again, on its first run: ground_choices.*.
choice, ground_choices.*.problem and players.*.blame_from were in neither
list. The last is the one worth keeping — an EMPTY vector is a leaf path
of its own, and it now renders as an explicit absence.
Also, a mutation that did not go red: removing the Sec-Fetch-Site arm
alone left the cross-site test green, because the Origin check caught it
independently. Both had to be removed before the control bit. Recorded
because a control that passes for a reason you did not intend has not
been demonstrated.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Five decisions:
1. cb-render-html emits HTML/SVG/JS; the browser draws it. Rejected on
measured marginal cost: egui+eframe 2,782,849; wgpu+winit 1,741,979;
ratatui 1,067,013; macroquad 480,501; sdl2 191,973; fltk 140,079.
The reason is allocation, not affordability — fltk is only 1.5x the
corrected headroom, but wgpu is 12x fltk, unavoidable, and named by
INTENT for stage 2. Stage 1 should not buy windowing stage 2 discards.
2. No cb-render-api and no cb-render-null. A port designed against one
document-emitting implementation acquires a document's shape and
stage 2 rewrites it. INTENT's second-use rule beats the blueprint's
port pattern on timing. cb-render-html ships against Project.
3. AM-4 counts third-party code the project causes to be ACQUIRED, not
runtimes the user already has. Browsers are not counted; sdl2 and
fltk are counted at MORE than their Rust bindings. The rule costs
more than it saves, which is the only reason to trust it here.
4. AM-4a's proc-macro defect (89,048 lines, 36.2%) is filed separately,
not bundled with the request it unblocks.
5. Six controls bind the implementation, including a mutation-backed
test that a token-less loopback request is refused, a bar on JS
constructing commands, and a coverage gate asserting over the parsed
emitted document rather than the Rust that emits it.
Reserved for the maintainer: AM-4a exceeds INTENT stage 2 by 7x and
cannot survive it; and whether decision 3's rule is the right one.
The hard gate held — no render implementation code before this commit.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Four of six challenges conceded; the survey's two main arguments are
replaced rather than clarified.
C1 The survey concluded the sub-100k region was empty without ever
measuring it. It is not empty: tiny-skia fits at 83,956, and the
real windowed floor is fltk at 140,079 — 1.5x corrected headroom,
not 128x. "Two orders of magnitude" is withdrawn.
C1b Following that concession: wgpu+winit is 1,741,979 marginal lines
against a 250,000 target. AM-4a is incompatible with INTENT stage 2
by 7x, and has been since both were written. Raised for the
maintainer; deliberately not decided by this pass.
C2 "Marginal cost zero" was scored on an axis chosen to produce zero,
and the same relocation already flattered sdl2 and fltk in the
survey's own table. One acquisition rule now covers all three, and
it raises two candidates' cost rather than lowering the winner's.
C3 The survey contradicted itself on the second-use rule. cb-render-api
and cb-render-null are withdrawn; cb-render-html ships against the
existing Project trait, and the port waits for stage 2's second use.
C6 The candidate measurements did carry a positive control. The C1
batch did not — it copied dep-weight.py's measurement function
without its guards — and was re-measured under them before being
cited. Figures reproduced unchanged. The HTML row is relabelled
0 by construction, not by measurement.
C4/C5 become six controls binding on ADR-0007.
The recommendation stands. The reasoning that reached it does not.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Measured with dep-weight.py's own method so the numbers subtract.
Marginal cost against the 23-crate base graph, not headline size:
egui+eframe 2,782,849 742x headroom
wgpu+winit 1,741,979 465x
softbuffer+tiny-skia 1,147,081 306x
ratatui+crossterm 1,067,013 285x
macroquad 480,501 128x
HTML/SVG emission 0 0x
ratatui costing more than macroquad is the surprise: rustix pulls
linux-raw-sys at 479,901 lines.
Separately, AM-4a counts proc-macro crates that never reach a binary:
89,048 lines, 36.2% of the shipped-runtime figure, syn alone 66,916.
Real headroom is 92,798, not the 3,750 this repo has been citing.
The recommendation is unchanged by that correction — macroquad is 5.2x
over even at 92,798 — which is the only condition under which a survey
may propose correcting a number in its own favour. The metric fix is
filed separately, not bundled with the decision it unblocks.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Declaration 7 of 12. Structural tier L (INTENT stage 1 creates a
capability port); d4 = 1, so no override — the pass runs at full
weight, which is the tier CB-WP-0011's roll deleted.
The leading constraint is AM-4a's 3,750 lines of headroom against
candidate implementations that are all five to six figures. T01 is
required to measure rather than estimate, and to audit the instrument
before recommending any change to the target it reports.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
CB-EV-0009. Tier S did not produce a worse outcome than tier L would
have. The roll deleted a survey that would have opened on 2D toolkit
selection; the decomposition it forced instead found that the existing
text renderer was showing 24 of 41 view fields. The structural trigger
fires on a property of the plan, not of the code, so nothing in the
tier derivation could have said the port was the wrong first question.
Recorded honestly in both directions: the pass also made an interface
change with no review, which is the cost side. One favourable fire is
not a calibration; the window stays open to 2026-09-30.
Corrects a number this pass asserted: the T01 commit message says
'42 of 43, up from 24'. Measured by splicing the old renderer back in,
it is 41 of 42 with 1 declared omitted, up from 24 -- and 16 fields
were genuinely absent, not 17, because outcome.winners was rendered in
a different format. Both original figures were counted by hand.
CHAOS gains its first caught entry. Cheapest pass per response yet
recorded (0.094 vs a previous best of 0.123).
Renders the table after every step of a .cbreplay bundle or a scenario
YAML, from any seat's projection or a spectator's. This is the first
thing in the project that answers 'what did the table look like when it
went wrong?' without adding a dbg! and re-running.
INTERFACE CHANGE (flagged per InnerLoop chaos limits -- this is a
tier-S pass that touched a runtime crate): cb-game-runtime gains
replay::open, extracted out of replay::replay. Dev-only, behind the
scenarios feature, no type changed. The point of the extraction is that
the inspector and the replay gate share one bundle reader, controls
included, so the inspector cannot show a state a replay never reached.
Three M-D1-MUT controls, each red for its stated reason. The
load-bearing one asserts one rendered table per step: without it, a
walk that rendered nothing would still report a matching hash.
The renderer moves out of the play loop into inspect.rs and grows from
24 to 42 of the 43 leaf paths a populated GroundView carries. What it
had been dropping was the whole DARVO state machine, the whole GROUND
practice, the scoring mode, Focus tokens, the discard pile, per-seat
protection, and every part of the outcome except the headline.
The load-bearing half is every_view_field_is_classified, which walks
the serialized view for leaf paths and requires each to be listed as
rendered (with a token the output must contain) or omitted (with a
reason). Paths rather than keys: 'problem' occurs under a DARVO target,
a GROUND choice and a Selection, and a key-set walk would let one of
the three vouch for the other two.
Four M-D1-MUT controls, each red for its stated reason. The
unclassified-field control fired for real on the first run --
players.*.hand, a field the gate's own author had missed.
Provenance (tier S, structural L, chaos d4=4 -> S). First fire of the
chaos mechanism in six declarations. The structural trigger was L
(stage 1 creates a rendering port); the roll overrode it to S, which
has no ADR. Rather than lawyer the hard 'no code before ADR' gate in
either direction, the declaration is split: this packet takes the part
of stage 1 that creates no port and adds no dependency, and the port
half keeps its own declaration and its own roll.
AM-4a supports that ordering independently -- 3,750 lines of headroom
against a 250,000 target means any toolkit choice needs the survey the
roll just deleted.
Finding acted on: cb-play's render() drops ~a third of GroundView,
including the whole DARVO and GROUND-practice state.
Two passes have now had the opportunity to give this type a second
consumer and declined: CB-WP-0008's bots and CLI drive GROUND's inline
commit/reveal, and this pass reviewed it and changed nothing.
The date is not moved and the type is not deleted early. The stated
condition is a second game, and no second game has been attempted, so
the test has not run — only the opportunity has passed. Deleting on a
test that was never run and extending a date because it is inconvenient
are the same error in opposite directions.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
COMMON PROBLEM was the only scoring mode with no scenario — implemented
since CB-WP-0001, referenced by nothing, and would not have failed if
deleted. Five players, where the threshold is reachable at all: every
Problem claimed for a total of 10 against 9, and the winner is decided
by Blame rather than by claimed value — P4 claimed the highest Problem
and loses to P3 because two Blame tokens sit in front of them.
No defect was found on the first execution of that path, which is worth
saying plainly rather than implying the scenario was hard-won.
The assertions were mutation-checked three ways instead of trusted,
because a dot-path expectation that silently fails to resolve would
report PASS: a wrong personal score, a wrong mastery, and removing the
Blame from the fixture each turn it red.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Both remaining tasks were overtaken and are cancelled with pointers. T05's
control loop was answered by CB-EV-0008 §1 and §4, which measured the
windowed metric and the budget firing on real passes. T06 asked whether
there is a fourth way a number can fail to bind; there is, and CB-EV-0007
§3 recorded it — the meta budget, aggregated over a window that could not
move it, two tasks after the same defect was fixed for session shape. The
tier-taxonomy gap T06 also carried was closed by ADR-0006 D5.
A workplan left in_progress makes `make status` name a stale next task,
which it had been doing for two passes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Tier S (structural S; chaos d4=1, no override; declaration 5 of 12).
Three items carried out of the last two passes: CB-WP-0007 left at 2/6
with both remaining tasks overtaken, GR-E03 with no scenario at all, and
CommitWindow's second failed second-use. CB-EV-0008 §4 also says the next
pass should be product, and this is how the meta share comes back down.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The windowed budget is confirmed for the failure it was written against
and not for the general claim: a single-pass window reads 0% for
CB-WP-0008 against 50% lifetime, but the trailing-3 window reads 45%
against 50%, inside the refutation band. The prediction was written
before the window size was chosen and did not say which comparison it
meant. Both readings are on record and whether 3 is the right window is
carried as open.
gate-review's first run: 9 gates, 0 due, 2 silent. The silent two are the
chaos roll and gate-review itself, both with dates. A registry where
everything looked productive would have been one written to look good.
D4 holds per pass, not per task: three of four tasks shipped a command,
and the two that did not are the spec change that makes the commands
normative and the evidence file that checks them.
Cost is the honest part. This pass cashed out three commands and ran at
$0.177/response — cheaper than every previous meta pass (0.228, 0.298,
0.362) and still 1.4x the product pass at 0.123. Partial support for D4,
not vindication. Context breached both shape targets because the pass ran
on an already-long session; reported, not gated.
Meta reads 45% of the trailing three against a soft 25%. Nothing was
displaced, but the number is over the line and the next pass should be
product.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
D2 the two exemptions — repairing the instrument that reports a breach
is always in budget, and the maintainer may authorize above-line work in
the workplan frontmatter. v1.5 had neither, and the first thing it did
was forbid fixing the budget's own defect.
D4 loop work cashes out into something runnable in the pass that invents
it, with the measured basis and the refutation condition stated.
D5 the tier table now triggers at M for changes to the loop's own
operation, closing the gap CB-RES-0005 §6 opened and this pass's own ADR
had to declare around.
The file went from 399 lines to 386: the chaos-roll calibration
rationale and the v1.0-v1.3 change log moved to InnerLoopReference.md.
Loadability is a gate too, and growing the file to fit a rule about
gates would have been the joke writing itself.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ADR-0006 D3. Nine standing control gates now say what they check, what
they have caught with pointers, when their keep-or-kill argument is due,
and what would retire them. make gate-review reports what is overdue and
what has caught nothing; it never fails the build, for CB-RES-0005 §4's
reason.
Drift is checked in both directions and both are pinned by self-tests: a
dependency of `make all` that is neither a registered control gate nor
listed in not_control_gates is a loop-lint finding, so a new gate cannot
acquire permanence without a review date, and an entry naming a target
the Makefile lacks is a finding too.
First run: 0 due, 2 silent. The silent two are the chaos roll, whose
12-declaration window exists precisely to find out, and gate-review
itself, which is not exempt from its own rule — if it has retired,
tightened or forced the re-justification of nothing by 2026-12-31 it is
a ritual and goes.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ADR-0006 D1. cb-cost gains pass_costs, which buckets responses into
workplan windows in a single read of the transcripts — calling collect()
once per boundary would re-read every transcript per window, and status
is supposed to stay cheap enough that nobody replaces it with ls.
make status now reports the share over a trailing three passes with the
per-pass breakdown, keeps the lifetime figure labelled NOT the metric,
and prints the D2 exemption so the next reader does not re-derive the
standoff where the budget blocked its own repair. One pass would be a
coin flip: a meta pass reads 100%, a product pass 0%. Three is the
smallest window where the ratio means something and still moves.
First reading: 36% over the last three passes against 49% lifetime,
with CB-WP-0008 at 0%.
The first run reported $0.00 for every window. Transcript stamps are
UTC Z and git prints a local offset, so the string comparison put every
response before the first boundary. Both the fix and a self-test for it
are in; reverting the conversion turns four checks red.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
CB-EV-0007 found three defects in how gates are designed rather than in
any one gate: the meta budget cannot see the pass it governs, it blocks
its own repair, and nothing retires any gate.
D1 budgets measure their own window. D2 a soft breach is a signal, and
repairing the instrument that reports a breach is always in budget — a
gate must never block its own remedy, which is the trap CB-RES-0005 §4
named for session shape and that got built anyway two tasks later. D3
every gate declares what would retire it and a date to argue it on. D4
loop work cashes out into something runnable in the pass that invents
it, from the measured finding that cost per response tracks distance
from a runnable check. D5 the tier table finally covers changes to the
loop's own operation — CB-RES-0005 §6 said a second instance should
trigger it, and this ADR is the second.
The workplan is meta and above the budget line on recorded maintainer
authorization, which is D2's first use.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The DFD gate caught this, not review: adding scenarios in T03 left
gr_scenarios stale at 21 and `make all` went red on the next run. That
is the gate doing exactly its job, one pass after it was built.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Stage 0's ten items are met. Three qualifications are recorded rather
than hidden behind checkmarks: GR-E01's threshold is unreachable below
five seats with the placeholder fixture, GR-A13 admits a SOLVE that
resolves to nothing, and GR-E03 has no scenario at all — implemented,
unreferenced, and would not fail if deleted.
The second-consumer verdict INTENT was waiting for: every abstraction
with a consumer fits, and the one with none is still unused. Bots and
the CLI drove Aggregate, Project, parse_command and the replay bundles
unchanged. CommitWindow had its best chance at a second user and did not
get one; its delete-by date stands.
The retrospective answers with the curve: 0.123, 0.228, 0.362, 0.298,
0.123 dollars per response across the last five passes. Neither
"meta is expensive" nor "compaction did it" survives the data. What does:
cost per response tracks how far the work is from a runnable check. The
meta passes that shipped a command were cheap; the ones that argued about
what a number means were not.
The meta budget reads 61% OVER on a pass that is 100% product, because
it aggregates over every task ever closed — the same defect CB-RES-0005
found in SH-1/SH-2 and that CB-WP-0007 T01 fixed for session shape. Not
fixed here: v1.5 forbids opening meta work above the line, so the
budget's first real act was to stop me from improving the budget.
Also fixes a doc comment that claimed DARVO was unimplemented for weeks
after it shipped. facts-check gates duplicated numbers; nothing gates a
prose claim about code.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
GR-O01 states 2-6 players; every scenario in the corpus was 3-player.
Now all five counts play to GameEnded under both policies and reproduce
at the same seed, with scenarios at both boundaries and the CLI
transcript run at 2p, 3p and 6p.
Nothing broke — the rules are seat-count-generic. What the boundaries
exposed is arithmetic: with the standard preset's placeholder Problem
values (value = priority), the best total any game can reach is 3 at 2p,
6 at 3-4p, 10 at 5-6p, against GR-E01 thresholds of 5, 7 and 9. Group
success is unreachable below five seats regardless of play, and no
scenario noticed because none had played to scoring with everything
claimed.
GR-S01 calls the fixture a stand-in for scenario Problem data, so this
is evidence the stand-in is not neutral, not that GR-E01 is wrong. It is
pinned by a passing scenario, an arithmetic test, and a provisional
marker owned by ground-game so it ages in `make coverage`. The test
states its own delete-by: it is expected to fail when Problem values
become real data, and that failure is the signal to delete it.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A human seat is a Policy like any bot, so the CLI adds no second driver:
HumanPolicy renders the projection, lists the legal commands and reads an
index or `pass`. `make play` runs it; `--all-bots` watches one.
K13's Project trait gains its first implementor after six passes with
none. Hidden: other seats' face-down selections until Reveal, hands and
deck (counts only), a face-down Problem's suit and value, and the seed —
not secret content, but a seat holding it can compute the deck.
A played session becomes an artifact: --record writes it as a scenario
the runner executes, --replay writes a .cbreplay bundle. record.rs is the
inverse of parse_command and its warrant is a round-trip test over every
command shape.
The acceptance test for the projection passed vacuously twice. First it
asserted the text contained "face-down", which every render does because
of Problems. Counted, it then reported zero inspected entries: seats are
asked in order, so a human at P1 is prompted before anyone has selected.
Seated at P3 it inspects ten entries and dies when the projection is
mutated to reveal everything. Counting what the harness examined caught
both, which is the second time that remedy has worked where a stronger
predicate would not have.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A Policy trait, a seeded random policy and a greedy one with a stated
heuristic, a legal-command generator that filters candidates through
validate, and a driver that runs a 3-player all-bot game to GameEnded.
Same-seed runs are hash-identical (K8), and a different policy seed
produces a different game — without that second assertion the first is
satisfied by a bot that ignores its RNG.
Every failure is loud, because the one a bot driver must not have is the
silent one: no legal move, passing where an action is required, an
out-of-range index (not clamped), a rejected command, and a stall guard.
What the second consumer found, none of it fixed here:
- GR-A13 admits SOLVE against an already-claimed Problem and resolution
then does nothing — the action is silently wasted. The policy avoids
it; the rule is left for a ruling.
- The 3-player standard fixture cannot reach GR-E01's threshold of 7:
three Problems valued 1,2,3 cap the total at 6. No scenario noticed
because none plays to scoring.
- K13's Project trait still has zero implementors. T02 is its first.
Mutation-checked by hand. The first mutation was a no-op and survived;
removing the Resolve call outright turned three tests red for the stated
reason. Third instance of the weak-mutation class.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>