Skip to content

Commit bb0c043

Browse files
dzhelezovclaude
andcommitted
feat(realtime): RT-2 — isolated-cutover finality floor (INV-25, RG0 INERT)
The isolated single-chain historical→realtime cutover clamp (getHistoricalEventsIsolated) now passes floor = params.syncProgress .finalized.number to clampFinalizedToPortalHead, mirroring the multichain/omnichain cutover sites. Added to all 5 wiring patches (0.15.17–0.16.9), added block byte-identical; hunk headers rebalanced. CANDID: the floor is INERT defense-in-depth / doc-parity. RG0 proved the isolated path is already safe via the upstream break-before-adopt guard (delta <= finalityBlockCount ⇒ break, before the boundary assignment): a stale-LOW probe yields a negative delta and is never adopted regardless of the floor. Since floor equals the guard's compare value, the floor MASKS a guard mutation — so the test pins the guard INDEPENDENTLY of the floor rather than through the real path (which would be vacuous, per RG0): Pin A pins the shipped floor; Pin B pins the load-bearing guard. Mutation-verified: M1 (drop the floor line) fails Pin A only; M2 (weaken the guard <= → >=) fails Pin B only — the pins are independent. INVARIANTS.md: add INV-25. Plan: mark RT-2 landed in RG1 + the RT-G13 register disposition (PR number left as #NNN for the merge gate). Gates: scripts/sync-upstream.sh {0.16.6,0.15.17} --test → 361 passed each (cutover-guard 42 tests); biome check portal/ --diagnostic-level=error → 0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent fe1909c commit bb0c043

8 files changed

Lines changed: 127 additions & 19 deletions

File tree

.agents/plans/stream-realtime-production.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ and nowhere else; it is gated on the complete dossier, not on judgment.
3535
| Gate | Name | One-line exit criterion |
3636
|------|------|------------------------|
3737
| RG0 | Ground truth ratified | This plan merged; RT-G13 (cutover floor) verified true-bug-or-not with a written verdict. **MET** — plan merged ([#157](../../pull/157)); RT-G13 verified **INERT / NOT-A-BUG** (upstream guards isolated adoption — verdict in the RT-G13 register entry below), so RT-2 reclassifies to should-fix (defense / doc-parity). |
38-
| RG1 | Must-fix code landed | RT-1/RT-2/RT-3 merged: mutation-verified tests, committee review, both-version gates green |
38+
| RG1 | Must-fix code landed | RT-1/RT-2/RT-3 merged: mutation-verified tests, committee review, both-version gates green. RT-1 ([#161](../../pull/161)) + RT-3 ([#162](../../pull/162)) merged; **RT-2 landed** ([#163](../../pull/163)) — isolated-cutover finality `floor` shipped for parity across all 5 wiring patches (INV-25), test pins the load-bearing break-before-adopt guard INDEPENDENTLY of the inert floor (M1/M2 mutation-verified), both-version `--test` gates green (361 passed each). |
3939
| RG2 | Fail-loud audit complete | Fatal-injection suite + silent-gap fuzzer green in CI; no enumerated silent path survives |
4040
| RG3 | Realtime chaos passed | ≥200 kills across ≥6 timing classes, 100 % clean resumes, byte-identical digests. **MET (Phase A, [#158](../../pull/158))** — 238 kills / 7 timing-class sub-runs, 238/238 clean, byte-identical, 0 dup FINALIZED; K6-cutover + K2-spread non-vacuity self-certified. Numbers + candid mock-fidelity caveats in VALIDATION §5.11. |
4141
| RG4 | Multichain stream soak passed | ≥72 h multi-chain stream soak (incl. one fast chain + omnichain), crash drills clean, parity clean |
@@ -226,7 +226,7 @@ gates RG1), **should-fix** (lands during the campaign, doesn't gate the label by
226226
| RT-G10 | must-fix | RT-1 (progress watchdog) |
227227
| RT-G11 | must-fix | RT-1 (read idle bound → reconnect) |
228228
| RT-G12 | must-fix | RT-1 (poll decoupled from delivery) |
229-
| RT-G13 | verified INERT (RG0) → should-fix | RT-2 (floor for parity; test pins the upstream guard, not the floor) |
229+
| RT-G13 | verified INERT (RG0) → should-fix **LANDED (RT-2, [#163](../../pull/163))** | RT-2 (floor shipped for parity across all 5 wiring patches → INV-25; Pin A pins the floor, Pin B pins the upstream break-before-adopt guard, mutation-verified independent — M1 fails Pin A only, M2 fails Pin B only) |
230230
| RT-G14 | evidence | RG3 |
231231
| RT-G15 | evidence | RG3 K5 + RG2 seam test |
232232

@@ -280,6 +280,16 @@ mirroring the multichain site.
280280
cutover the boundary does not regress (fails with the floor removed); if RG0 verification shows
281281
upstream already guards adoption, the test instead pins the guard and the change is documentation-
282282
parity. Both-version gates; the patches for all pinned versions updated together.
283+
**Status — LANDED ([#163](../../pull/163)).** RG0 confirmed the isolated path is already INERT-safe
284+
(break-before-adopt guard), so RT-2 shipped the `floor` for cross-site parity + defense-in-depth (INV-25)
285+
across all 5 wiring patches (0.15.17–0.16.9, added `+` block byte-identical). Per RG0 the test does NOT
286+
assert the boundary through the real path (the floor equals the guard's compare value, so it MASKS a guard
287+
mutation → a behavioral test would be vacuous); instead `portal-cutover-guard.test.ts`
288+
"INV-25 / RT-2: isolated-cutover finality floor" pins the two protections INDEPENDENTLY at the grafted
289+
source — **Pin A** the shipped floor, **Pin B** the load-bearing break-before-adopt guard. Mutation-verified:
290+
M1 (drop the floor line) fails Pin A only; M2 (weaken the guard `<=``>=`) fails Pin B only — the pins are
291+
independent. Both-version `--test` gates green (0.16.6 + 0.15.17, 361 passed each; cutover-guard 42 tests);
292+
biome clean.
283293

284294
### RT-3 — RING_CAP headroom + eviction-path proof (RT-G2)
285295

portal/INVARIANTS.md

Lines changed: 6 additions & 2 deletions
Large diffs are not rendered by default.

portal/portal-cutover-guard.test.ts

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -803,3 +803,82 @@ describe('INV-18: wiring pins (grafted runtime/historical.ts)', () => {
803803
);
804804
});
805805
});
806+
807+
// ─────────────────── INV-25 / RT-2: isolated-cutover finality floor (grafted wiring pins) ───────────────────
808+
//
809+
// RT-2 lands the `floor` on the isolated single-chain cutover clamp so it mirrors the multichain/omnichain
810+
// sites (documentation-parity / defense-in-depth). CANDID DESIGN NOTE — the floor is INERT here:
811+
// `floor = params.syncProgress.finalized.number` is the SAME value the break-before-adopt guard just below
812+
// compares against, so it can only clamp a stale-LOW probe UP to exactly the previously-adopted boundary —
813+
// a no-op relative to that boundary. The LOAD-BEARING protection against a below-boundary adoption is the
814+
// upstream guard (`… <= params.chain.finalityBlockCount ⇒ break;`), which refuses to adopt a non-advancing
815+
// (stale-LOW ⇒ negative-delta) boundary at all. Because the floor MASKS a guard-weakening mutation (drop
816+
// the guard and the floor still prevents a below-boundary clamp OUTPUT), a behavioral test through the real
817+
// isolated path would be VACUOUS — so per RG0 the two protections are pinned INDEPENDENTLY at the source:
818+
// Pin A pins the SHIPPED floor (the parity change); Pin B pins the LOAD-BEARING guard.
819+
// Both read the grafted `runtime/historical.ts` (byte-identical across all pinned versions) and slice the
820+
// isolated function body [getHistoricalEventsIsolated, refetchHistoricalEvents) so a pin can never match the
821+
// multichain/omnichain clamp (which use `floor: hexToNumber( params.perChainSync.get(...)…`).
822+
823+
describe('INV-25 / RT-2: isolated-cutover finality floor', () => {
824+
const historical = readFileSync(
825+
join(__dirname, '..', 'runtime', 'historical.ts'),
826+
'utf8',
827+
);
828+
829+
// The function AFTER getHistoricalEventsIsolated is refetchHistoricalEvents (not getLocalSyncGenerator —
830+
// two refetch/generator helpers sit between them). Slicing to its start bounds the isolated body exactly.
831+
const isolatedStart = historical.indexOf('getHistoricalEventsIsolated');
832+
const isolatedEnd = historical.indexOf('refetchHistoricalEvents');
833+
const isolated = historical.slice(isolatedStart, isolatedEnd);
834+
835+
test('the slice bounds are sane (isolated body is non-empty and precedes refetchHistoricalEvents)', () => {
836+
expect(isolatedStart).toBeGreaterThan(-1);
837+
expect(isolatedEnd).toBeGreaterThan(isolatedStart);
838+
// The isolated body must contain its own cutover clamp — the site RT-2 edits.
839+
expect(isolated).toContain('clampFinalizedToPortalHead({');
840+
});
841+
842+
// ── Pin A: the SHIPPED parity change. The isolated cutover clamp now carries the finality floor.
843+
// Scoped to `isolated` so it cannot match the multichain/omnichain sites (whose floor reads from
844+
// `params.perChainSync.get(...)`, not `params.syncProgress` — the single-chain isolated form).
845+
// MUTATION RECIPE (M1): delete the `floor: hexToNumber(params.syncProgress.finalized.number),` line
846+
// from the isolated clamp in the wiring patch → this pin FAILS (Pin B still passes — they are
847+
// independent; the floor is inert so no behavioral test could catch its removal).
848+
test('Pin A (shipped parity): the isolated cutover clamp carries floor = hexToNumber(params.syncProgress.finalized.number)', () => {
849+
expect(isolated).toContain(
850+
'floor: hexToNumber(params.syncProgress.finalized.number),',
851+
);
852+
});
853+
854+
// ── Pin B: the LOAD-BEARING guard (RG0). The isolated path BREAKS-BEFORE-ADOPT on the finality-delta
855+
// guard; the boundary assignment `params.syncProgress.finalized =` sits AFTER that guarded break, so a
856+
// stale-LOW (non-advancing) probe is never adopted. This — NOT the inert floor above — is what prevents
857+
// a below-boundary adoption. Pinned independently precisely because the floor MASKS a guard mutation.
858+
// MUTATION RECIPE (M2): in the grafted historical.ts, alter the pinned guard text — e.g. rename
859+
// `finalityBlockCount` in that predicate, or remove the `break;` / move the boundary assignment before
860+
// the guard → this pin FAILS. (Editing the pinned source and showing the pin fails IS the accepted
861+
// "pin the guard" verification per the plan — the floor cannot be relied on to catch it.)
862+
test('Pin B (load-bearing guard, RG0): the isolated path breaks-before-adopt on the finality-delta guard', () => {
863+
// The break-before-adopt guard: a non-advancing (stale-LOW ⇒ negative) delta is `<= finalityBlockCount`,
864+
// so the loop breaks WITHOUT adopting the probed boundary.
865+
expect(isolated).toContain('params.chain.finalityBlockCount');
866+
expect(isolated).toContain('params.syncProgress.finalized.number) <=');
867+
868+
// The boundary assignment must sit AFTER the guarded break — never before it — so a stale-LOW probe
869+
// that trips the guard can never reach the adopt. Anchor on the guard PREDICATE itself (`… .number) <=`),
870+
// NOT the first `params.chain.finalityBlockCount` (that occurrence is the probe computation
871+
// `latest.number - finalityBlockCount`, not the guard), so the ordering assertion targets what it names.
872+
const guardAt = isolated.indexOf(
873+
'params.syncProgress.finalized.number) <=',
874+
);
875+
const breakAt = isolated.indexOf('break;', guardAt);
876+
const adoptAt = isolated.indexOf(
877+
'params.syncProgress.finalized = finalizedBlock;',
878+
);
879+
880+
expect(guardAt).toBeGreaterThan(-1);
881+
expect(breakAt).toBeGreaterThan(guardAt);
882+
expect(adoptAt).toBeGreaterThan(breakAt);
883+
});
884+
});

portal/wiring/0.15.17.patch

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ index 01b6288..8567db1 100644
532532
if (Date.now() - lastUnfinalizedRefetch < 30_000) {
533533
break;
534534
}
535-
@@ -826,6 +979,14 @@ export async function* getHistoricalEventsIsolated(params: {
535+
@@ -826,6 +979,17 @@ export async function* getHistoricalEventsIsolated(params: {
536536
],
537537
context,
538538
),
@@ -542,12 +542,15 @@ index 01b6288..8567db1 100644
542542
+ chain: params.chain,
543543
+ rpc,
544544
+ finalizedBlock: fb,
545+
+ // The previously adopted boundary is the in-run finality floor — a stale-LOW probe must not regress
546+
+ // it (RT-2; INERT given the isolated adopt-guard below, defense/parity per RG0).
547+
+ floor: hexToNumber(params.syncProgress.finalized.number),
545548
+ common: params.common,
546549
+ }),
547550
);
548551

549552
const finalizedBlockNumber = hexToNumber(finalizedBlock.number);
550-
@@ -1216,7 +1377,9 @@ export async function* getLocalSyncGenerator(params: {
553+
@@ -1216,7 +1380,9 @@ export async function* getLocalSyncGenerator(params: {
551554
return;
552555
} else if (params.isCatchup === false) {
553556
params.common.logger.info({
@@ -558,7 +561,7 @@ index 01b6288..8567db1 100644
558561
chain: params.chain.name,
559562
chain_id: params.chain.id,
560563
cached_block: hexToNumber(params.syncProgress.current.number),
561-
@@ -1227,14 +1390,18 @@ export async function* getLocalSyncGenerator(params: {
564+
@@ -1227,14 +1393,18 @@ export async function* getLocalSyncGenerator(params: {
562565
first = hexToNumber(params.syncProgress.current.number) + 1;
563566
} else {
564567
params.common.logger.info({

portal/wiring/0.16.6.patch

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ index 0bd78dc..48c2f24 100644
532532
if (Date.now() - lastUnfinalizedRefetch < 30_000) {
533533
break;
534534
}
535-
@@ -813,6 +966,14 @@ export async function* getHistoricalEventsIsolated(params: {
535+
@@ -813,6 +966,17 @@ export async function* getHistoricalEventsIsolated(params: {
536536
],
537537
context,
538538
),
@@ -542,12 +542,15 @@ index 0bd78dc..48c2f24 100644
542542
+ chain: params.chain,
543543
+ rpc,
544544
+ finalizedBlock: fb,
545+
+ // The previously adopted boundary is the in-run finality floor — a stale-LOW probe must not regress
546+
+ // it (RT-2; INERT given the isolated adopt-guard below, defense/parity per RG0).
547+
+ floor: hexToNumber(params.syncProgress.finalized.number),
545548
+ common: params.common,
546549
+ }),
547550
);
548551

549552
const finalizedBlockNumber = hexToNumber(finalizedBlock.number);
550-
@@ -1203,7 +1364,9 @@ export async function* getLocalSyncGenerator(params: {
553+
@@ -1203,7 +1367,9 @@ export async function* getLocalSyncGenerator(params: {
551554
return;
552555
} else if (params.isCatchup === false) {
553556
params.common.logger.info({
@@ -558,7 +561,7 @@ index 0bd78dc..48c2f24 100644
558561
chain: params.chain.name,
559562
chain_id: params.chain.id,
560563
cached_block: hexToNumber(params.syncProgress.current.number),
561-
@@ -1214,14 +1377,18 @@ export async function* getLocalSyncGenerator(params: {
564+
@@ -1214,14 +1380,18 @@ export async function* getLocalSyncGenerator(params: {
562565
first = hexToNumber(params.syncProgress.current.number) + 1;
563566
} else {
564567
params.common.logger.info({

portal/wiring/0.16.7.patch

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ index 0bd78dc..48c2f24 100644
532532
if (Date.now() - lastUnfinalizedRefetch < 30_000) {
533533
break;
534534
}
535-
@@ -813,6 +966,14 @@ export async function* getHistoricalEventsIsolated(params: {
535+
@@ -813,6 +966,17 @@ export async function* getHistoricalEventsIsolated(params: {
536536
],
537537
context,
538538
),
@@ -542,12 +542,15 @@ index 0bd78dc..48c2f24 100644
542542
+ chain: params.chain,
543543
+ rpc,
544544
+ finalizedBlock: fb,
545+
+ // The previously adopted boundary is the in-run finality floor — a stale-LOW probe must not regress
546+
+ // it (RT-2; INERT given the isolated adopt-guard below, defense/parity per RG0).
547+
+ floor: hexToNumber(params.syncProgress.finalized.number),
545548
+ common: params.common,
546549
+ }),
547550
);
548551

549552
const finalizedBlockNumber = hexToNumber(finalizedBlock.number);
550-
@@ -1203,7 +1364,9 @@ export async function* getLocalSyncGenerator(params: {
553+
@@ -1203,7 +1367,9 @@ export async function* getLocalSyncGenerator(params: {
551554
return;
552555
} else if (params.isCatchup === false) {
553556
params.common.logger.info({
@@ -558,7 +561,7 @@ index 0bd78dc..48c2f24 100644
558561
chain: params.chain.name,
559562
chain_id: params.chain.id,
560563
cached_block: hexToNumber(params.syncProgress.current.number),
561-
@@ -1214,14 +1377,18 @@ export async function* getLocalSyncGenerator(params: {
564+
@@ -1214,14 +1380,18 @@ export async function* getLocalSyncGenerator(params: {
562565
first = hexToNumber(params.syncProgress.current.number) + 1;
563566
} else {
564567
params.common.logger.info({

portal/wiring/0.16.8.patch

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ index 0bd78dc..48c2f24 100644
532532
if (Date.now() - lastUnfinalizedRefetch < 30_000) {
533533
break;
534534
}
535-
@@ -813,6 +966,14 @@ export async function* getHistoricalEventsIsolated(params: {
535+
@@ -813,6 +966,17 @@ export async function* getHistoricalEventsIsolated(params: {
536536
],
537537
context,
538538
),
@@ -542,12 +542,15 @@ index 0bd78dc..48c2f24 100644
542542
+ chain: params.chain,
543543
+ rpc,
544544
+ finalizedBlock: fb,
545+
+ // The previously adopted boundary is the in-run finality floor — a stale-LOW probe must not regress
546+
+ // it (RT-2; INERT given the isolated adopt-guard below, defense/parity per RG0).
547+
+ floor: hexToNumber(params.syncProgress.finalized.number),
545548
+ common: params.common,
546549
+ }),
547550
);
548551

549552
const finalizedBlockNumber = hexToNumber(finalizedBlock.number);
550-
@@ -1203,7 +1364,9 @@ export async function* getLocalSyncGenerator(params: {
553+
@@ -1203,7 +1367,9 @@ export async function* getLocalSyncGenerator(params: {
551554
return;
552555
} else if (params.isCatchup === false) {
553556
params.common.logger.info({
@@ -558,7 +561,7 @@ index 0bd78dc..48c2f24 100644
558561
chain: params.chain.name,
559562
chain_id: params.chain.id,
560563
cached_block: hexToNumber(params.syncProgress.current.number),
561-
@@ -1214,14 +1377,18 @@ export async function* getLocalSyncGenerator(params: {
564+
@@ -1214,14 +1380,18 @@ export async function* getLocalSyncGenerator(params: {
562565
first = hexToNumber(params.syncProgress.current.number) + 1;
563566
} else {
564567
params.common.logger.info({

portal/wiring/0.16.9.patch

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ index 0bd78dc..48c2f24 100644
532532
if (Date.now() - lastUnfinalizedRefetch < 30_000) {
533533
break;
534534
}
535-
@@ -813,6 +966,14 @@ export async function* getHistoricalEventsIsolated(params: {
535+
@@ -813,6 +966,17 @@ export async function* getHistoricalEventsIsolated(params: {
536536
],
537537
context,
538538
),
@@ -542,12 +542,15 @@ index 0bd78dc..48c2f24 100644
542542
+ chain: params.chain,
543543
+ rpc,
544544
+ finalizedBlock: fb,
545+
+ // The previously adopted boundary is the in-run finality floor — a stale-LOW probe must not regress
546+
+ // it (RT-2; INERT given the isolated adopt-guard below, defense/parity per RG0).
547+
+ floor: hexToNumber(params.syncProgress.finalized.number),
545548
+ common: params.common,
546549
+ }),
547550
);
548551

549552
const finalizedBlockNumber = hexToNumber(finalizedBlock.number);
550-
@@ -1203,7 +1364,9 @@ export async function* getLocalSyncGenerator(params: {
553+
@@ -1203,7 +1367,9 @@ export async function* getLocalSyncGenerator(params: {
551554
return;
552555
} else if (params.isCatchup === false) {
553556
params.common.logger.info({
@@ -558,7 +561,7 @@ index 0bd78dc..48c2f24 100644
558561
chain: params.chain.name,
559562
chain_id: params.chain.id,
560563
cached_block: hexToNumber(params.syncProgress.current.number),
561-
@@ -1214,14 +1377,18 @@ export async function* getLocalSyncGenerator(params: {
564+
@@ -1214,14 +1380,18 @@ export async function* getLocalSyncGenerator(params: {
562565
first = hexToNumber(params.syncProgress.current.number) + 1;
563566
} else {
564567
params.common.logger.info({

0 commit comments

Comments
 (0)