Reuse-leg protocol: K(scene′ | scene) across stacks
Owner, 2026-10-26. Plan this measures: HYPERFRAMES_SCORECARD_PLAN.md.
Extends: the competitor benchmark, tier-based token-cost study (2026-10-26).
The question this leg answers: once a T2 scene exists, what does a nearby scene cost per stack, counting everything the agent had to load, not just what it emitted?
Why it exists:
- The tier study measured blank-page build cost, K(scene | vocabulary).
- The PinePaper thesis is about the conditional, K(scene′ | scene): a stored design graph should make neighbours cheap, because the agent references structure instead of re-sending it.
- The existing edit leg is one data point against that on the current agent surface (full rebuild, 6,702 tok per attempt).
- This leg tests the claim properly, on every route, with one accounting rule that nobody can fudge.
Testers: read §3 before anything else. If you report only a diff, your row is discarded.
1. Baseline
The baseline is T2 MEDIUM exactly as shipped in the tier study:
batch-t2.json(26,807 B) for the native route;batch-t2.jsonfrom the PP-JS work dir for the custom-JS route;- each code route’s T2 source file.
Do not regenerate it. Neighbours are defined relative to this scene, so a regenerated baseline makes your numbers incomparable.
T2 composition (from the native RESULTS.md, the reference for what “the scene” contains):
| Layer | Items | Native keys | Notes |
|---|---|---|---|
| Title “SIGNAL / NOISE” | 1 | 2 | fade-in |
| Bars | 5 | 5×3 = 15 | values 40 / 65 / 52 / 80 / 71, growth ease-out, baseline y=900 |
| Bar labels | 5 | 5×2 = 10 | one per bar |
| Ring | 24 dots | 24×9 = 216 | centre (960, 430), radius 260, one revolution per 6 s, sampled at t = 0…8 s (1 s steps), hand-sampled on the native route |
| Sine polyline | 1 | 8 | draws on t=4→7 s |
| Total | 36 | 251 | 26,807 B / ~6,702 tok |
Canvas 1920×1080, 30 fps, 8.000 s, dark navy background. Same spec as the tier study.
2. Neighbours
Four neighbours, ordered by what kind of change they are. N1 is the existing edit leg and serves as the calibration row. A tester whose N1 numbers disagree with the study’s by more than the stated tolerance has a method problem, and their N2–N4 rows are suspect.
| ID | Change | Change class | What it isolates |
|---|---|---|---|
| N1 | Bar 3 value 52→88 (height 364→616); title → “SIGNAL / PROOF” | Item-level value edit | Calibration. Already measured: native 6,702/attempt, PP-JS 667, HF 43, Three 21, canvas 19 (diff-only basis). |
| N2 | 5 bars → 7 bars, values 40 / 65 / 52 / 80 / 71 / 33 / 58, with labels; bars re-spaced evenly across the same x-extent (260…1460, so step 200 instead of 300); stagger rule unchanged (growth ends 3.7 + 0.15·i, label fades 3.4 + 0.15·i) | Item-multiplying, non-pattern | Does adding instances of a hand-shaped layer cost per-instance or per-declaration? |
| N3 | Ring stays 24 dots; radius 260→360 px, period 6 s→4 s (centre unchanged) | Parameter edit on a pattern layer, count unchanged | The cleanest test of “declaration exists”: a stored orbit/ring node absorbs this in a handful of tokens. Enumerated keyframes re-sample all 216 keys. |
| N4 | Ring 24 dots → 32 dots, radius 360, period 4 s (i.e. applied on top of N3) | Pattern-multiplying | The tell. If “ring of 32” costs 288 keys, pattern nodes are not real on that route. |
Each neighbour is authored from the baseline, not from the previous neighbour. The exception is N4, which is defined on top of N3 and is authored from N3’s artifact. State this in every results row.
The reference route-5 batches for N2, N3 and N4 (batch-n2.json, batch-n3.json, batch-n4.json) were generated from
a script that reproduces batch-t2.json and batch-t2-edit.json byte-for-byte, so they define the neighbours exactly.
Native testers on route 5 should land within a few bytes of them; if they don’t, the scene they built is not the
neighbour.
3. Accounting rule (the whole leg depends on this)
Per neighbour, per route, report three numbers. All are in bytes, with est. tokens = bytes / 4, the same convention as the tier study.
-
C_read: every byte of baseline material the agent had in context in order to author the change. This includes:
- the baseline source file or batch JSON, if the agent opened it;
- the output of any readback tool call (
get_items,graph_query,query_relations,scene_graph, acatof the file, an IDE “open”); - any doc the agent fetched to recall the API.
If the agent could not have made the change without seeing it, it counts.
-
C_send: every byte the agent emitted to effect the change, including failed attempts and re-sends, exactly as the tier study counted.
-
C_total = C_read + C_send.
Rules:
- Fresh session per neighbour. The agent starts with nothing in context except the task text and a path to the baseline artifact: no prior chat, no memory of having built T2. If your harness cannot guarantee this, say so in the row and the row is marked unclean.
- A diff is not a payload. “12-byte file diff” is a fact about the file, not about what the agent needed. The tier-study edit leg reported diffs for the three code routes. Those numbers are reproduced here only as the N1 diff-only column, for continuity; the comparison column is C_total.
- Generator scripts remain scaffolding and are not counted. But if the agent had to read the generator to know how to change the scene, that read counts under C_read.
- Failed attempts count in C_send, as in the tier study. Report the successful-send figure alongside, as the study did for T2.
- Log the full agent transcript per neighbour: prompt, every tool call and result, every file read. The transcript is the evidence; the row is a summary of it. A row with no transcript is discarded.
What “normal” looks like under this rule. A code route that re-reads its 2.7 KB T2 source and emits a 77-byte edit has C_total ≈ 2,734 B ≈ 684 tok. That is roughly 100% of its own T2 build cost, not 19 tok. The native batch route at 6,702 tok still loses that comparison by ~10×: read-back narrows the gap, it does not close it. If a tester’s code-route C_total comes in under ~500 tok for N1, they almost certainly did not count the read.
4. Routes
Run every neighbour on every route that is runnable. Routes 5 and 6 have conditions.
| # | Route | How the neighbour is authored | Status today (1.6.23+d785d14) |
|---|---|---|---|
| 1 | Raw canvas | edit draw(t) source, recapture |
runnable |
| 2 | Three.js | edit source, recapture | runnable |
| 3 | HyperFrames | edit composition file, CLI render | runnable |
| 4 | PinePaper custom JS | edit script, re-send whole via execute_custom_code, re-export |
runnable |
| 5 | PinePaper native: batch | re-send full batch-t2.json with changes, fresh session |
runnable; the control (targets below) |
| 6 | PinePaper native: ontology doc | keep the JSON-LD doc as the external baseline; edit the doc per neighbour; re-run instantiate_ontology; count doc read + doc edit + full re-instantiation as sent |
runnable, with conditions (below) |
| 7 | PinePaper native: stored declaration | scene persisted with an unexpanded ring/orbit node and addressable ids; agent queries the node, patches a parameter or count, re-exports | not runnable today (below) |
Route 5, exact single-send targets from the reference batches:
| Neighbour | Bytes sent | Bytes changed |
|---|---|---|
| N1 | 26,807 B | 36 B (0.1%) |
| N2 | 28,509 B | 1,759 B (6.2%) |
| N3 | 26,777 B | 3,256 B (12.2%) |
| N4 | 33,669 B | 10,085 B (30.0%) |
Every neighbour re-sends ≥ 70% unchanged bytes; that unchanged fraction is the reuse the current surface cannot express.
Route 6 is document-level reuse, not scene-level. It gets its own row and must not be presented as the native reuse result. Note the id-recovery cost (registry diff) in C_read if the agent needed it.
Route 7 is not runnable today:
add_relationpersists live, but it binds two existing items and has no pattern semantics;apply_template/template_paramsexpand on write;template_cast/template_patchdo not exist in source.
The row is defined now so the table is ready when AR-2 (pattern nodes) and AR-4 (persistent semantic ids) land. Do not fake it with route 6.
Route 5 vs route 7 is the entire point of the leg. Route 6 is a useful intermediate: it shows how far a compact external declaration gets you when the engine still expands on write.
5. Verification per neighbour
Same discipline as the tier study: nothing is a pass until the file on disk proves it.
- ffprobe: 1920×1080, 30 fps, 8.000 s.
- Decode clean:
ffmpeg -v error -f null -. - Two frames viewed minimum, at the times below, with the stated assertion checked by eye and recorded.
| Neighbour | Frame times | Assertions |
|---|---|---|
| N1 | 3.0 s, 7.5 s | bar 3 tallest; label “88”; title reads “…/ PROOF”; other four bars unchanged |
| N2 | 3.0 s, 7.5 s | seven bars, evenly spaced, labels 40/65/52/80/71/33/58; ring and polyline unchanged |
| N3 | 2.0 s, 4.0 s | 24 dots; ring visibly larger (outer dot at x ≈ 1320, was 1220); the dot that starts at (1320, 430) is back there at t = 4.0 s (baseline returns at 6.0 s) |
| N4 | 2.0 s, 4.0 s | 32 dots counted on frame, same radius and period as N3 |
Claim and content-verify exports immediately. The tier study recorded a shared-exports race: name your output files per route and neighbour, and never trust filename or timestamp alone.
6. Results table
One row per route × neighbour. Columns:
route | neighbour | fresh-session? | C_read (B) | C_send (B, as-sent) | C_send (B, successful) | C_total (B) | est tok | diff-only (B, N1 only) | items touched | keys authored | failures | wall (s) | verified? | transcript path
Then two derived views the write-up will need:
- Reuse ratio per route: C_total(N) / C_build(T2) for each neighbour. A route whose neighbours cost ≈1.0× its own build has no reuse. Below ~0.3× means the route is amortising the baseline.
- Native ÷ best code at each neighbour, computed on C_total (not diff). Two rows: route 5 (batch) and, when it exists, route 7 (declaration).
7. Reading the result
Three outcomes were defined before running. Pick the one the data supports; do not blend them.
- A: thesis proven. Route 7’s C_total beats the best code route’s C_total on N2, N3 and N4, with read-back counted on both sides, and route 7’s reuse ratio is well under 0.3×. This is the result that flattens the T3 slope, and it is the marketing artifact.
- B: nodes not real yet. Route 7 beats code on N1 and N3 (parameter edits), but N4 scales with dot count (≥ ~200 keys or ≥ ~5 KB for 24→32). This is an engineering finding: the declaration is stored, but count is still expanded somewhere on the path. It is not a thesis finding.
- C: reconsider. Route 7 is runnable, declarations are stored and addressable by id, and native C_total still exceeds the best code route’s C_total on N2–N4. That would mean the graph’s compression is not recoverable by an agent at the protocol level. It is the only result in this leg that should change the product bet.
Until route 7 exists, the leg can only produce:
- the route-5 control (expected: no reuse, ≈1.0× ratio across all neighbours);
- the route-6 intermediate.
Report those as what they are. The tier study’s bottom line stands unchanged until a route-7 row exists.
8. Tester briefing (paste as-is)
You are extending the 2026-10-26 tier study with a reuse leg. Use the shipped T2 baseline, do not regenerate it. For each of the four neighbours in §2, start a fresh agent session with only the task and the baseline path, make the change, export, verify per §5, and record every byte the agent read and every byte it sent (§3). Report C_read, C_send and C_total — a file diff on its own is not an acceptable number and the row will be dropped. Attach the full transcript. Run N1 first; if your N1 C_send for your route is not within 15% of the tier study’s figure, stop and check your harness before continuing. Native testers: run route 5 (batch) as the control; run route 6 (ontology doc) as its own row; do not attempt route 7 unless the server build you have persists a pattern node — ask before claiming it does.
9. Known hazards (carried from the tier study)
- Native
agent_start_jobcan time out at 180 s under parallel load. Log zero-step attempts as failures, and count their payload if any was sent. execute_custom_codereports success on logical failure; frame verification is the only proof.- The title at spec position (200,130) clips to “IGNAL / …” on PinePaper routes, because text is centre-anchored. Keep the spec coordinate for comparability; note the clip, don’t fix it.
- H.264 exports are not byte-deterministic on PinePaper routes (ledger B31). Determinism is not part of this leg; don’t re-run it.
- The shared exports directory is raced by parallel agents; claim and verify immediately.
Note on route 7 readiness (2026-10-26)
The pattern node exists in the engine (FxTool #201, addPattern, stored unexpanded and evaluated per frame) and has an
MCP tool (mcp-server #18, pinepaper_pattern). That is not enough to claim route 7:
- its kinds are
phase_waveandstagger, with noringororbityet, so N3 and N4 cannot be expressed as a declaration; - there is no persistent scene-by-id across sessions (AR-4).
Per §8, ask before claiming route 7.