Some checks failed
ci / check (push) Failing after 3s
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
257 lines
11 KiB
Markdown
257 lines
11 KiB
Markdown
---
|
||
id: CB-WP-0012
|
||
kind: product
|
||
title: "Stage 1, second slice: the rendering port"
|
||
status: done
|
||
state_hub_workstream_id: "761f626f-9770-4e23-aaba-94574c41ff04"
|
||
---
|
||
|
||
# Purpose
|
||
|
||
Tier **L**, the declaration CB-WP-0011 deferred and owed.
|
||
|
||
```
|
||
structural tier L (INTENT stage 1 creates a new capability port)
|
||
chaos d4 = 1 → no override
|
||
declared tier L
|
||
```
|
||
|
||
Declaration 7 of 12 in the calibration window. The CHAOS gate earned its
|
||
first `caught` entry last pass by rolling this same declaration down to S;
|
||
this time it rolls nothing, so the pass runs at full weight — survey,
|
||
adversarial review, ADR, then code. The hard gate applies as stated: **no
|
||
implementation code for the render capability exists before ADR-0007 is
|
||
committed.**
|
||
|
||
## What this pass owes
|
||
|
||
INTENT stage 1 is *"Inspectable 2D table — card/token/hand/relationship-
|
||
graph visualization, drag-to-propose, debug inspector, hot-seat play."*
|
||
CB-WP-0011 shipped the debug inspector. This pass owes the other three,
|
||
and the port they hang from:
|
||
|
||
```
|
||
cb-render-api
|
||
├── cb-render-null
|
||
└── cb-render-??? <- the survey's question
|
||
```
|
||
|
||
**The leading constraint is AM-4a**: 246,250 lines of 250,000, measured —
|
||
**3,750 lines of headroom**. Every candidate implementation of a 2D table
|
||
is a five- or six-figure line count. This is the first capability in the
|
||
project whose obvious implementation costs more than the entire remaining
|
||
budget, so the survey's first duty is to establish whether that is a real
|
||
obstacle or an artifact of how AM-4a is instrumented.
|
||
|
||
## Task: survey the render port and its dependency cost
|
||
|
||
```task
|
||
id: CB-WP-0012-T01
|
||
status: done
|
||
priority: high
|
||
state_hub_task_id: "61515aae-c6ff-4c19-b4c8-017c81d29ef7"
|
||
```
|
||
|
||
Write `research/CB-RES-0006-render-port.md`.
|
||
|
||
**Measure, do not estimate.** The candidate line counts must come from
|
||
the same method `tools/dep-weight.py` uses — `cargo tree --edges normal`
|
||
over a real resolved graph, then counted `.rs` lines in vendored source —
|
||
so the numbers are comparable to the AM-4a figure rather than merely
|
||
adjacent. Last pass's correction was a hand-counted number; this pass has
|
||
no excuse for one.
|
||
|
||
**Measure the marginal cost, not the total.** What AM-4a charges is what a
|
||
candidate adds to a graph that already holds 23 crates. A candidate's
|
||
headline size overstates its cost by whatever it shares with the base.
|
||
|
||
Cover at minimum: an immediate-mode GUI (`egui`/`eframe`), a 2D game
|
||
framework (`macroquad`), the raw stage-2 stack (`wgpu` + `winit`), a CPU
|
||
rasterizer (`softbuffer` + `tiny-skia`), a terminal UI (`ratatui`), and at
|
||
least one option that is not a Rust toolkit at all.
|
||
|
||
**Ask whether the instrument is right.** If AM-4a's figure counts code
|
||
that never reaches a shipped binary, the headroom it reports is wrong, and
|
||
that has been true for every pass that has cited it. Check this before
|
||
recommending any budget change — a survey that argues for raising a target
|
||
it has not first audited is arguing in its own favour.
|
||
|
||
**Done 2026-08-02.** [CB-RES-0006](../research/CB-RES-0006-render-port.md).
|
||
Two findings, and they point opposite ways.
|
||
|
||
The cheapest candidate that opens a window (`macroquad`) costs a marginal
|
||
**480,501** lines — **128×** the headroom. `egui` + `eframe` costs
|
||
2,782,849. `ratatui`, the option one expects to be cheap, costs *more than
|
||
macroquad* (1,067,013) because `rustix` pulls `linux-raw-sys` at 479,901
|
||
lines.
|
||
|
||
And AM-4a is mis-instrumented: **36.2% of the shipped-runtime figure
|
||
(89,048 lines) is proc-macro crates** — `syn` alone is 66,916 — which run
|
||
in the compiler and never reach a binary. Real headroom is **92,798**, not
|
||
3,750. Every pass that cited 3,750, this workplan's own Purpose included,
|
||
cited a number wrong in the conservative direction.
|
||
|
||
The recommendation survives the correction: `macroquad` is still 5.2× over
|
||
at 92,798. That was the condition for proposing the correction at all, and
|
||
the correction is filed separately rather than bundled with the decision
|
||
it would unblock.
|
||
|
||
Recommended: `cb-render-api` + `cb-render-null` + **`cb-render-html`** —
|
||
emitted HTML/SVG/JS, marginal AM-4a cost **zero**, with `cb-render-wgpu`
|
||
left to stage 2 where it becomes the interface's second use.
|
||
|
||
## Task: adversarial review of the survey
|
||
|
||
```task
|
||
id: CB-WP-0012-T02
|
||
status: done
|
||
priority: high
|
||
state_hub_task_id: "5c36ed13-2a1a-467c-b359-5a0e84388173"
|
||
```
|
||
|
||
Step 2 of the inner loop, run against T01's recommendation rather than for
|
||
it. The review must name, at minimum:
|
||
|
||
- what the recommended option **cannot** do that a windowed toolkit can,
|
||
stated concretely rather than as a caveat;
|
||
- the failure mode of building the port around a single implementation
|
||
when the second-use rule exists precisely to stop that;
|
||
- whether the survey's dependency argument would survive if AM-4a's target
|
||
were simply wrong, i.e. whether the recommendation is load-bearing on a
|
||
number the same pass proposes to correct.
|
||
|
||
A review that ratifies the survey without producing a control the survey
|
||
lacked has not run.
|
||
|
||
**Done 2026-08-02.** [challenge](../history/260802-render-port-challenge.md),
|
||
[response](../history/260802-render-port-response.md). **Not approvable as
|
||
written** — four of six challenges conceded, and the survey's two main
|
||
arguments replaced.
|
||
|
||
- **C1**: the survey concluded the sub-100k region was empty without
|
||
measuring it. It is not empty. `tiny-skia` fits at 83,956; the real
|
||
windowed floor is `fltk` at **140,079 — 1.5×** corrected headroom, not
|
||
128×. "Two orders of magnitude" withdrawn.
|
||
- **C1b**, which the concession exposed: `wgpu` + `winit` is **1,741,979**
|
||
marginal lines against a 250,000 target. **AM-4a is incompatible with
|
||
INTENT stage 2** — 7× the whole target — and has been since both were
|
||
written. Raised for the maintainer, deliberately not decided here.
|
||
- **C2**: "marginal cost zero" was scored on an axis chosen to produce
|
||
zero, and the same move already flattered `sdl2`/`fltk`. One acquisition
|
||
rule now covers all three, and it *raises* two candidates' cost.
|
||
- **C3**: the survey contradicted itself on the second-use rule.
|
||
**`cb-render-api` and `cb-render-null` are withdrawn from this pass.**
|
||
- **C4/C5**: six controls adopted as binding on ADR-0007 — a loopback
|
||
token with a mutation-backed refusal test, JS barred from constructing
|
||
commands, and the coverage gate crossing the language boundary.
|
||
- **C6**: the candidate measurements did carry a positive control (empty
|
||
`unlocated` for all seven, verified). The C1 batch did **not** — it
|
||
copied the measurement function without the guards — and was re-measured
|
||
under them before being cited. The HTML row is relabelled *0 by
|
||
construction, not by measurement*.
|
||
|
||
**Fidelity note:** the review ran in the same session as the survey rather
|
||
than a separate one, per this environment's standing instruction not to
|
||
spawn agents unasked. It therefore inherits the author's sampling and is a
|
||
lower bound on what a separate reviewer would find.
|
||
|
||
**Note on tier:** this pass no longer creates a capability port, which was
|
||
its structural trigger for tier L. The declaration and its roll stand — a
|
||
tier that changes because review shrank the work would be a function of the
|
||
outcome. Recorded as the CHAOS window's second entry.
|
||
|
||
## Task: ADR-0007 — the render port
|
||
|
||
```task
|
||
id: CB-WP-0012-T03
|
||
status: done
|
||
priority: high
|
||
state_hub_task_id: "75b33156-cd04-440b-ab0e-02609484944a"
|
||
```
|
||
|
||
Record the decision, the rejected alternatives with their measured costs,
|
||
and the controls the implementation must carry. No implementation code
|
||
lands before this commits.
|
||
|
||
**Done 2026-08-02.**
|
||
[ADR-0007](../decisions/ADR-0007-render-html-not-a-port.md) — *render to
|
||
HTML, and do not declare the port yet.* Five decisions, eight rejected
|
||
alternatives with measured costs, six binding controls, and **two items
|
||
reserved for the maintainer**: AM-4a's 7× incompatibility with stage 2, and
|
||
whether the acquisition rule proposed by the pass that benefits from it is
|
||
the right rule.
|
||
|
||
The hard gate held: no render implementation code existed before this
|
||
commit.
|
||
|
||
## Task: the port and its first implementation
|
||
|
||
```task
|
||
id: CB-WP-0012-T04
|
||
status: done
|
||
priority: high
|
||
state_hub_task_id: "07dc04f0-8f0b-4285-8e1a-d5f9203a924b"
|
||
```
|
||
|
||
`cb-render-api` plus `cb-render-null` and the implementation ADR-0007
|
||
chooses, delivering visualization, drag-to-propose and hot-seat play.
|
||
|
||
**K13 binds here.** The renderer consumes a `Project`ion and can never
|
||
feed back into validation; a drag that proposes a move must go through the
|
||
same command path a CLI move takes. The inspector's coverage gate is the
|
||
precedent for the control this needs.
|
||
|
||
**Done 2026-08-02.** `crates/cb-render-html` (doc/input/serve) and
|
||
`tools/cb-play/src/hotseat.rs`, behind `cb-play --serve PORT`. Per
|
||
ADR-0007 D2 there is **no `cb-render-api` and no `cb-render-null`**.
|
||
|
||
Marginal AM-4a cost, measured rather than claimed: **0 new third-party
|
||
crates** (23 before, 23 after). AM-4a unmoved at 246,250.
|
||
|
||
Eight mutations, each red for its stated reason. Two results worth more
|
||
than the six that behaved:
|
||
|
||
| control | result |
|
||
|---|---|
|
||
| a field present in neither list | fired **for real on the first run** — `ground_choices.*.choice`, `ground_choices.*.problem`, and `players.*.blame_from`, the last being an **empty vector**, a leaf path a fully-populated fixture would never produce |
|
||
| `Sec-Fetch-Site` arm removed | **stayed green** — the `Origin` check caught it independently. Both had to go before the control bit; a control that passes for an unintended reason has not been demonstrated |
|
||
|
||
**Never executed: the emitted JavaScript.** 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 `SCRIPT`.
|
||
|
||
## Task: evidence
|
||
|
||
```task
|
||
id: CB-WP-0012-T05
|
||
status: done
|
||
priority: medium
|
||
state_hub_task_id: "7ef422c6-1c5e-4d55-8325-d171ef8db5ad"
|
||
```
|
||
|
||
`evidence/CB-EV-0010-render-port.md`. Carry the standing items: the
|
||
falsifiable prediction from CB-EV-0009 §4 that the trailing-3 meta share
|
||
drops to 0% this pass, SH-3 at 0.0% for a sixth pass, and whether tier L
|
||
at full weight produced anything the rolled-down pass would have missed —
|
||
the CHAOS window's second data point, and the first from a non-override.
|
||
|
||
**Done 2026-08-02.**
|
||
[CB-EV-0010](../evidence/CB-EV-0010-render-port.md).
|
||
|
||
- **Tier L deleted its own deliverable.** Review withdrew the port. A
|
||
tier-S pass has no step 2 and would have shipped it.
|
||
- **The prediction held: meta budget reads 0%**, published in advance and
|
||
unfalsified.
|
||
- **A correction, and 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 its conclusion stands. But this is the **second**
|
||
consecutive evidence file to report its own pass's cost low — a pass
|
||
cannot measure its own cost, and every evidence file quoting its own is
|
||
quoting a floor.
|
||
- **Priced tier comparison, first ever on one subject**: 0.123 $/response
|
||
at L against 0.099 at S — 24% more, for a pass that found errors of 25×
|
||
and 85×.
|
||
- **SH-3 at 0.0% for a sixth pass.** Oldest unargued number in the
|
||
project; owed a declaration of its own.
|
||
- **INTENT stage 1 stays open** — all four deliverables now exist, and
|
||
none of the browser half has ever been run.
|