…rrier +483 br over a −546 ceiling; net −63); residue doc §3.1 "As measured" + §7b; plan §3 row R2
Measured before writing, per the step's rule, on step 1's head (frames
eager 35,250 / 11,654): the deletion ceiling (`stage` whole out) is
−1,645 / −546 on this head; the carrier AS THE STEP WOULD HAVE WRITTEN IT
— applied to an edited dist copy through the harness's bundler — is
+1,414 min / +483 br over it, net −231 / −63 (pages −29 / −37; non-SC
0 / 0). The rule was "carrier > +300 br → stop and report"; nothing of the
form reached source.
Two findings. (1) The §3.1 sketch (`pullcarrier`, +242) is unsound where
the budget was built: it deleted the content token, and `dynamic`
delivers a kept resolution only when its address differs — without the
token a same-address refetch never runs the follow's compute half or any
fill memo in the transaction (#3844's gap 1; C15 (a, b), the
optimistic-hold multi-flight arms). The token binding stays in any form:
227 min / 88 br. (2) The honest carrier is twice the sketch because the
handler's chunk buffer (≈ 200 min) is replayed through `host.apply` and
inherits every semantic the host has — version policy, the landing, L1,
per-id routing (nested regions and a flight's several roots stage for
free) — while a host-side staged set carries each itself (promote through
the store's own `write` + landing tail; the `write` / `settleWait` guards;
flight-path per-root staging 176 / 54; nested regions 152 / 53), and the
pull read needs a lane gate (the fill keyed by the mount's address
accessor, 106 / 29) that the push has by construction, so the read
(≈ 750 min) is not smaller than the push it replaces (≈ 700). The unsound
floor without flight / regions / gate is still +980 / +339.
frames-residue-pass.md: status line; §3.1 "As measured" (the sketch's
unsound point, the honest carrier as designed, the attribution table,
why the sketch was short by half, the conclusion); §2 row 1c and §4 row 3
corrected to the measured net; §5 item 3 marked stopped; §7b the step's
table and what it changes in the path (≈ 120 B of margin instead of
≈ 330 with C1 + claims). frames-savings-pass.md §3: row R2, the surface
the form would have added named. frames-consistency-contract.md: C15's
pin list gains arm (e), the gap #3844 named.
Co-authored-by: Cursor <cursoragent@cursor.com>
Draft — frames size pass, residue step 2: the
previewpull form, MEASURED AND STOPPED. Offsize/frames-residue-1(#3863) @fce81d2c0; retargets as the stack merges (→ #3862 → #3860 → #3849 →next). Ground truth:documentation/plans/frames-residue-pass.md§3.1 (the design) and §2 row 1c / §5 row 3; #3844's body ("the gap");frames-rulings.md1.6 / 2.3 / "Fix shape — seam 1"; principles §9.2.2 (A29). The step's standing rule was measure before writing — build the carrier on an edited dist first; if it exceeds +300 br over the deletion ceiling, stop and report the design. It does: +483 br. Nothing of the form reached source. This PR carries the measurement (docs) and one pin.Summary
Frames eager stays 35,250 min / 11,654 br — 1,654 B above ≤ 10.0 KB. The pull form was budgeted at −300 br net (a −542 deletion ceiling, a +242 carrier sketch). Measured on this head as the step would have written it, the honest carrier is +1,414 min / +483 br over a −546 ceiling → net −231 / −63 (pages −29 / −37; non-SC 0 / 0). Two findings:
pullcarrier(the measured +242) deleted the content token with the buffer and readhost.staged(address)off the bare address. Butdynamicdelivers a kept resolution only when its.addressdiffers from the last one delivered (web/src/index.tsresolveBinding/sameInstance): a refetch of the address a mount SHOWS resolves to the same object, the delivery is a same-value write, and neither the follow effect's compute half nor any fill memo runs in the transaction — the content lands at body end beside siblings the transaction holds. That is frames: A1b + A4 — stage/preview deletion, declared slot records, S-ref #3844's gap (1) restated; the sketch could not have kept C15 (a, b) or any multi-flight arm offrames-optimistic-holdgreen. The token binding stays in any form: 227 min / 88 br, the first thing the +242 did not count.host.applyand inherits every semantic the host already has — version policy, the landing, L1, per-id routing, so nested regions and a flight's several roots stage for free. A host-side staged set has to carry each of those itself (promotethrough the store's ownwrite+ landing tail, thewrite/settleWaitguards, flight-path per-root staging 176 / 54, nested regions promoted with the root 152 / 53), and the pull read needs a lane gate — the fill keyed by the mount's own address accessor, so a write-through recompute between a refetch's header and its commit (a live op on an adopted boundary, a reveal cascade, asettleWait) does not read the staged set outside the pass — 106 / 29, which the push has by construction. So the pull read (≈ 750 min) is not smaller than the push it replaces (≈ 700). The unsound floor without flight / regions / gate is still +980 / +339.Measured before written
frames/dist/client.js, throughscripts/size/bundle.mjs)fce81d2c0stagewhole out: the buffer, the token,stagedContent/contentAddress,FrameImpl#preview/host.preview, the token arms ofhandle/applyFlightResponse,followAddress→ a rebind effectpromotethroughwrite+ the shared landing tail (the lean form; sound)Pages (lean form): base 114,422 → 114,184 / 36,488 → 36,459 (−238 / −29); live 126,294 → 126,061 / 40,125 → 40,088 (−233 / −37). The four non-SC scenarios 0 / 0 on every row. Tooling:
.wt-logs/res2-edit.mjs(the cuts, exact-string replacements asserted to match once;node --checkon the result),res2-measure.mjs(the harness's own bundler with the copy in place of the dist). Built: none.The carrier as designed (what "+483" buys; the text measured is the text the source change would have produced). Handler:
showingdecides at the header as today; a staged response's chunks reach the host flagged (host.apply(chunk, true); the flight path flags by staged-root prefix, asregionOfdid); the token binding is minted intolatest; the call settles at body end. Host:apply(chunk, stage)writes a flagged chunk whose version is newer than the store's intostore.staged = { version, records }under the same policy-Awrite(one response's; once the store is at the version the rest writes through, as a committed entry did);settleArgsthrough the store's version-keyed waits,settleWaitre-applying only a record that is the store's current one;staged(id);promote(id, version)= the store's ownwrite+ the landing tailapplyalready runs (shown / open / the pending landing settled or rejected / frames applied as one write / L1 for the response's undelivered refs), the waits carried across the bump. Frame:#stagedRecord(occurrence)— the staged set's record, else the parent's when this store does not shadow the key (theinheritedrulepreviewhad);ctx.staged()resolves it through#resolveArgsunless it adds or renames a region (R.changed). Fill:liveSlotPropsreadsstaged() && ctx.staged() || args(),staged=host.staged(address)?.version === +versionparsed from the mount'sbinding()— the signaldynamicwrites in the transaction's pass, so the read is lane-correct. Follow: the effect half promotes the token's version, rebinds, then promotes each region store below (regions-tier.ts, replacingframes()).Public API changes
None — no source under
packages/*/srcchanged. For the record, the form would have removedFrameHost.preview/Frame.preview/stagedContent/contentAddress(approved 2026-10-06) and addedFrameHost.staged(id),FrameHost.promote(id, version?), a second parameter onFrameHost.apply(chunk, stage?), andSlotContext.staged()(all@experimental); a customFrameHostnot implementing them would lose atomic staging (today the handler's buffer gives it to any host). Named here so the trade is visible if the form is ever taken at −63.Pins
c15-staging-atomic(e), the gap frames: A1b + A4 — stage/preview deletion, declared slot records, S-ref #3844 named: a same-address refetch enters the transaction — with the body complete and the sibling held, the fill HAS derived the new arg (seenis["one", "two"]: the staged read happened in the transaction's pass) while the DOM still showsa0|v1|one, noframe:appliedfired and the frame's version is 1; the release lands the whole in one frame; the fill is not re-read at the commit. Any carrier of the staging — the push today or a pull — must keep both halves. Green on the push form (reproduced before any change, per the rule).frames-optimistic-hold×6,frames-morph-in-transition×3, hydrate + consistency 87 files / 446 passed / 16 expected fail / 2 skipped.Size
No change: frames eager 35,250 / 11,654 br (cap 11.67 KB), page base 114,422 / 36,488 (36.50), live 126,294 / 40,125 (40.14); vs
next@9d89df731as #3863's. No cap moved. The three pre-existing over-cap-by-noise warnings (signals floor, isPending, CSR) are +0 as on the base.Docs
frames-residue-pass.md: status line; §3.1 "As measured" (the sketch's unsound point, the honest carrier as designed, the attribution table, why the sketch was short by half, the conclusion); §2 row 1c and §4 row 3 corrected to the measured net; §5 item 3 marked stopped; §7b the step's table and what it changes in the path — the residue proper stalls ≈ 215 B higher than §4 says; crossing 10.0 still needs C1 and the claims chunk, with ≈ 120 B of margin instead of ≈ 330.frames-savings-pass.md§3: row R2.frames-consistency-contract.md: C15's pin list gains arm (e).Not done
stagedContent.record(token, id, occurrence)+ the host'ssettleArgsexposed + the same frame-side read and gate) — comes out ≈ 720 added for ≈ 710 deleted: not a step either.