Skip to content

test(streams): regression tests for review bugs + Stream DO test harness#1455

Merged
jonastemplestein merged 3 commits into
mainfrom
streams-review-stage0-tests
Jun 10, 2026
Merged

test(streams): regression tests for review bugs + Stream DO test harness#1455
jonastemplestein merged 3 commits into
mainfrom
streams-review-stage0-tests

Conversation

@jonastemplestein

@jonastemplestein jonastemplestein commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

What

Stage 0 of an in-depth adversarial review of packages/streams (full plan + all findings in tasks/streams-review-fixes.md). This PR is tests only — no behavior changes. It pins the bugs the review found and gives the package its first always-on Durable Object tests, so the follow-up fix PRs land on a safety net.

Why first

The ~1000-line Stream DO had zero always-on tests (append, idempotency, the pause gate, >512KB chunking, replay all lived only in example-app/e2e/*, skipped unless STREAM_STAGING_E2E=true). The review surfaced two CRITICAL data-loss/security bugs and several MAJORs; this PR documents them as failing tests before any fix touches the code.

The bug-pins (committed as it.fails ratchets)

The six tests below assert the correct behavior, which is currently violated — so they register as "expected fail" and keep pnpm test green. Each was proven to fail for the right reason (output in the table). When a fix lands, flip it.failsit.

Test Finding Proven failure today
T1 C1 swallowed-ingest desync (CRITICAL) {total: 7} — event lost, expected 12
T2 C2 writeState checkpoint ordering (CRITICAL) nothing persisted on retry
T3 C3 PublicStreamRpcTarget leaks protected methods (CRITICAL, security) prototype exposes writeCoreProcessorState
T4 M2 source field crashes append Unrecognized key: "source"
T5 M3 breaker token bucket on backwards clock -99996 tokens
T6 M4 breaker silent after replay trip 0 pauses

T7 (idempotency) and T8 (DO smoke: offsets, getEvents paging, >512KB chunk round-trip, subscribe replay) are coverage for already-correct behavior and pass now.

The Stream DO test harness (structural)

Adds vitest-pool-workers to packages/streams (mirroring packages/shared):

  • vitest.workers.config.ts + vitest.workers.jsonc (binds the Stream + StreamProcessorRunner DOs)
  • src/workers/test-entry.ts (minimal worker exporting the DOs)
  • node config excludes **/*.workers.test.ts; pnpm test runs both pools (test:node / test:workers)

Following cloudflare/agents and the workers-sdk rpc fixture, the DO tests use runInDurableObject(stub, (instance, state) => …) to call the instance directly and inspect state.storage — clean local throws (no RPC unhandled-rejection workaround), deterministic replay, and the chunking test asserts the event really spans multiple event_chunks rows. One test stays on the RPC stub to cover the production boundary.

Verification

node pool:    58 passed | 4 expected-fail
workers pool:  6 passed | 2 expected-fail
typecheck: clean   lint: clean

🤖 Generated with Claude Code


Note

Low Risk
Test-only changes and CI script updates; no production paths modified. Bug-pin tests document known failures without changing runtime behavior.

Overview
Stage 0 (tests only) for the packages/streams review: no runtime behavior changes. It adds the first always-on coverage for the Stream Durable Object and pins six known bugs as it.fails ratchets so pnpm test stays green until fixes land.

A vitest-pool-workers harness is introduced (vitest.workers.config.ts, vitest.workers.jsonc, src/workers/test-entry.ts), with @cloudflare/vitest-pool-workers as a dev dependency. Node Vitest excludes **/*.workers.test.ts; pnpm test runs both pools (test:node / test:workers).

Node (stream-review-regressions.test.ts): T1–T2 (ingest desync, checkpoint after writeState failure) and T5–T6 (circuit-breaker clock regression and post-replay flood) assert correct behavior via stubs/fakes.

Workerd (stream.workers.test.ts): T3–T4 are failing ratchets for RPC surface leak and source on append; T7–T8 pass now (idempotency, offsets, paging, >512KB chunking, subscribe replay), mostly via runInDurableObject with one RPC-stub smoke test.

tasks/streams-review-fixes.md marks Stage 0 complete and documents the harness pattern for later fix PRs.

Reviewed by Cursor Bugbot for commit 5c94b0e. Bugbot is set up for automated code reviews on this repo. Configure here.

jonastemplestein and others added 3 commits June 10, 2026 15:03
Stage 0 of the packages/streams review (tasks/streams-review-fixes.md).
Pins the bugs the review found and gives the package its first always-on
Durable Object tests.

Node tests (stream-review-regressions.test.ts), proven red:
- T1 (C1): a swallowed ingest failure permanently drops events — drives the
  real createStreamProcessorHost with a fake pump that mimics the Stream DO
  delivery path (cursor advances before delivery, result fire-and-forgotten).
- T2 (C2): a writeState failure advances the in-memory checkpoint, so the
  retried batch persists nothing.
- T5 (M3): the circuit-breaker token bucket drains on a backwards clock.
- T6 (M4): the breaker stays silent on a live flood after tripping during replay.

vitest-pool-workers harness (the structural gap — the package had zero
always-on DO tests): vitest.workers.config.ts + vitest.workers.jsonc +
src/workers/test-entry.ts. Node config excludes *.workers.test.ts; `pnpm test`
runs both pools.

Stream DO tests (stream.workers.test.ts):
- T3 (C3, red): PublicStreamRpcTarget proxies protected readCoreProcessorState
  / writeCoreProcessorState.
- T4 (M2, red): appending an event with a `source` field throws.
- T7, T8 (green coverage): idempotency-key dedupe + offset precondition,
  consecutive offsets, getEvents paging, >512KB chunk round-trip (asserted via
  direct event_chunks inspection), and subscribe replay.

The six bug-pins are committed as `it.fails` ratchets so `pnpm test` stays green
until the fixes land (flip `it.fails` -> `it` then). Following cloudflare/agents
and the workers-sdk rpc fixture, the DO tests use runInDurableObject for direct
instance + storage access (clean local throws, deterministic replay, direct SQL
inspection), keeping one stub-RPC test for the production boundary.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@jonastemplestein jonastemplestein merged commit 6257b82 into main Jun 10, 2026
11 checks passed
@jonastemplestein jonastemplestein deleted the streams-review-stage0-tests branch June 10, 2026 15:00
jonastemplestein added a commit that referenced this pull request Jun 10, 2026
… surface (C1/C2/C3) (#1458)

## What

**Stage 1** of the `packages/streams` review (plan in
`tasks/streams-review-fixes.md`). Fixes the three CRITICAL findings.
Flips the Stage 0 ratchets **T1, T1b, T2, T3** from `it.fails` → `it`.

**Stacked on #1455** (Stage 0 tests) — base is
`streams-review-stage0-tests`; retarget to `main` once that merges.

## C1 — a failed batch no longer drops events (data loss)

The delivery pump is fire-and-forget and advances its cursor before
delivery, so a swallowed ingest failure left a permanent gap in the
subscriber's state. Per the agreed approach (consumer resubscribes from
checkpoint):

- On ingest failure the host re-handshakes from the durable checkpoint;
the stream replays the batch (replay is idempotent).
- **Continued-delivery race:** because the pump keeps delivering during
recovery, a *later* batch's successful ingest would advance the
checkpoint past the gap. Each subscription is now tagged with a
`generation`, and ingest runs through a per-processor serial chain that
re-checks the generation **between** batches — batches from the
superseded connection are dropped, and the post-recovery replay is the
single source of truth.
- **Poison policy (owner's call):** after
`MAX_CONSECUTIVE_INGEST_FAILURES` (3), the host appends a
`stream/error-occurred` event and disconnects rather than hot-looping;
recovery is then up to the subscriber/processor.

Covered by **T1** (transient recovery under continued delivery) +
**T1b** (poison → error + disconnect).

> Note: the browser-mirror consumer (`stream-browser-store.ts`) has the
same swallow-and-wedge bug. Left for Stage 4 with the other
browser-runtime fixes (tracked in the task).

## C2 — checkpoint ordering (silent data loss on write failure)

`StreamProcessor.#ingest` advanced `#state`/`#checkpointOffset` *before*
`writeState`, so a failed durable write left the in-memory checkpoint
ahead and the retried batch silently no-oped. Now it persists the
snapshot **first**, then advances. (Inlined the single-use
`#saveSnapshot`.) Covered by **T2**.

## C3 — `PublicStreamRpcTarget` method leak (security)

`makeRpcTargetClass` copied every prototype method except a two-item
denylist, so the `protected` `readCoreProcessorState` /
`writeCoreProcessorState` were proxied onto the unauthenticated public
target — `writeCoreProcessorState` could inject an attacker-chosen
subscription callable that the DO later dispatches with full `env`.
Added an `include` allowlist; both Stream targets now allowlist the
explicit `StreamRpc` surface (`satisfies readonly (keyof StreamRpc)[]`
so it can't drift). Covered by **T3**.

## Verification

```
node pool:    61 passed | 2 expected-fail   (T5/T6 remain → Stage 3)
workers pool:  7 passed | 1 expected-fail   (T4 remains → Stage 3)
typecheck: clean   lint: clean
```

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **High Risk**
> Changes durable ingest/checkpoint behavior and closes a security hole
on unauthenticated Stream RPC; incorrect recovery or ordering could
still cause data loss or wedge delivery.
> 
> **Overview**
> **Stage 1** closes three CRITICAL streams review findings (C1/C2/C3)
and turns regression tests T1, T1b, T1c, T2, and T3 from `it.fails` into
passing `it`.
> 
> **C1 — failed batches no longer lose events (hosted path).**
`createStreamProcessorHost` no longer swallows ingest errors. On failure
it re-handshakes from the durable checkpoint so the stream replays the
batch. A **generation** gate plus a per-processor **ingest chain** drops
batches from superseded connections while recovery runs (avoids
advancing the checkpoint past a gap). After three consecutive failures
it appends `stream/error-occurred` and disconnects instead of
hot-looping. Regression coverage adds a replay-capable `fakeStream`, T1b
(poison), and T1c (recovery throw must not wedge the chain).
> 
> **C2 — checkpoint vs durable write.** `StreamProcessor.#ingest` now
**`await`s `writeState` before** updating in-memory `#state` /
`#checkpointOffset`, so a failed write leaves the batch retryable
instead of a silent no-op.
> 
> **C3 — public RPC surface.** `makeRpcTargetClass` gains an **`include`
allowlist**; `PublicStreamRpcTarget` / `StreamRpcTarget` only expose
explicit `StreamRpc` methods so protected `readCoreProcessorState` /
`writeCoreProcessorState` are not callable on the unauthenticated public
target.
> 
> Task doc and test headers are updated to mark C1/C2/C3 fixed on the
hosted path; browser mirror recovery remains Stage 4.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
e5aeaac. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

<!-- CLOUDFLARE_PREVIEW -->
## Environment Config Lease
<!-- CLOUDFLARE_PREVIEW_STATE -->
<!--
{
  "apps": {
    "os": {
      "appDisplayName": "OS",
      "appSlug": "os",
      "status": "tests-failed",
      "updatedAt": "2026-06-10T15:23:10.059Z",
      "headSha": "a9d4a4d8e14d664b1d5a8ba1a127e2a14c2ec686",
"message": "...(truncated)\nt.toBeNull();\n 397|
expect(error!.name).toBe(\"ItxError\");\n | ^\n 398|
expect(error!.code).toBe(\"NOT_FOUND\");\n 399|
expect(error!.details).toEqual({ projectIdOrSlug:
\"definitely-not-a-…\n\n⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯\n\n\n\n>
@iterate-com/os@0.0.1 e2e /home/runner/work/iterate/iterate/apps/os\n>
vitest --config e2e/vitest.config.ts -t 'OS preview
smoke'\n\n[vitest-artifacts] run root: /tmp/os-e2e-deTncv\n[vitest] run
slug: os-vitest-run-20260610-151920\n\n RUN v4.0.15
/home/runner/work/iterate/iterate/apps/os\n\nstdout |
e2e/vitest/preview-smoke.e2e.test.ts > OS preview smoke\nOS preview
smoke passed for https://os.iterate-preview-4.com/\n\n ✓
e2e/vitest/preview-smoke.e2e.test.ts (1 test) 6669ms\n ✓ OS preview
smoke 6668ms\n ↓ e2e/vitest/admin-project.e2e.test.ts (1 test | 1
skipped)\n ↓ e2e/vitest/agents.e2e.test.ts (9 tests | 9 skipped)\n ↓
e2e/vitest/codemode-mcp-provider-stack.e2e.test.ts (1 test | 1
skipped)\n ↓ e2e/vitest/codemode.e2e.test.ts (3 tests | 3 skipped)\n ↓
e2e/vitest/e2e-test-map.e2e.test.ts (13 tests | 13 skipped)\n\n Test
Files 1 passed | 5 skipped (6)\n Tests 1 passed | 27 skipped (28)\n
Start at 15:19:20\n Duration 7.99s (transform 210ms, setup 0ms, import
837ms, tests 6.67s, environment 1ms)\n\n\n> @iterate-com/os@0.0.1
e2e:itx /home/runner/work/iterate/iterate/apps/os\n> vitest run --config
src/itx/e2e/vitest.config.ts --project node\n\n[vitest-artifacts] run
root: /tmp/os-itx-e2e-DurFwM\n[vitest] run slug:
os-vitest-run-20260610-151929\n\n RUN v4.0.15
/home/runner/work/iterate/iterate/apps/os\n\n ❯ node
src/itx/e2e/itx.e2e.test.ts (10 tests | 1 failed | 1 skipped) 93401ms\n
✓ itx scripts run identically over Cap'n Web and /api/itx/run 11957ms\n
✓ the five-step capability flow: provide live, call, promote durable,
call from a script 11979ms\n ✓ platform bindings are dialable
capabilities (raw + wrapped) 11831ms\n ↓ the first-party McpClient cap
bridges a remote MCP server\n ✓ script executions leave a two-event
record on the /itx stream 13369ms\n ✓ worker caps hold a correctly
scoped itx of their own 9833ms\n ✓ members caps auto-proxy every public
method/getter at any depth 11350ms\n ✓ one dynamic worker cap calls
another's methods through its own itx 10597ms\n × kernel errors cross
capnweb as ItxError-shaped errors with codes 89ms\n ✓ revoked and
offline caps fail with instructive errors 10399ms\n ✓ node
src/itx/e2e/itx-fork.e2e.test.ts (3 tests) 52757ms\n ✓ fork: child caps
shadow the parent, misses delegate up the chain 15585ms\n ✓ fork narrows
access: a session cannot reach sibling projects 19542ms\n ✓ fork: child
worker caps run with the owning project's authority 15835ms\n ✓ node
src/itx/e2e/itx-egress.e2e.test.ts (3 tests) 37217ms\n ✓ itx.fetch
substitutes secrets through project egress (explicit door) 9642ms\n ✓
bare fetch() in a project itx script goes through egress (implicit door)
16508ms\n ✓ bare fetch() inside a worker cap goes through egress
(implicit door) 8802ms\n ✓ node src/itx/e2e/itx-http.e2e.test.ts (2
tests) 24080ms\n ✓ facet caps keep private durable state across
invocations 8799ms\n ✓ HTTP-exposed caps serve their own hostname:
admin, share URL, public 13750ms\n ✓ node
src/itx/e2e/itx-subscribe.e2e.test.ts (1 test) 12735ms\n ✓ subscribe
replays history, tails live appends, and unsubscribes 10991ms\n\n Test
Files 1 failed | 4 passed (5)\n Tests 1 failed | 17 passed | 1 skipped
(19)\n Start at 15:19:29\n Duration 220.79s (transform 79ms, setup 0ms,
import 184ms, tests 220.19s, environment 0ms)\n\n\n::error
file=/home/runner/work/iterate/iterate/apps/os/src/itx/e2e/itx.e2e.test.ts,title=[node]
src/itx/e2e/itx.e2e.test.ts > kernel errors cross capnweb as
ItxError-shaped errors with codes,line=397,column=23::AssertionError:
expected 'Error' to be 'ItxError' // Object.is equality%0A%0AExpected:
\"ItxError\"%0AReceived: \"Error\"%0A%0A ❯
src/itx/e2e/itx.e2e.test.ts:397:23%0A%0A\n ELIFECYCLE  Command failed
with exit code 1.",
      "publicUrl": "https://os.iterate-preview-4.com",
"runUrl": "https://github.com/iterate/iterate/actions/runs/27285949769",
      "shortSha": "a9d4a4d"
    }
  },
  "environmentConfigLease": {
    "dopplerConfig": "preview_4",
    "leasedUntil": 1781107858241,
    "leaseId": "eb6ab7de-ab6c-495c-aa8e-09ab779d1471",
    "slug": "preview-4",
    "type": "environment-config-lease"
  }
}
-->
<!-- /CLOUDFLARE_PREVIEW_STATE -->
Lease: `preview-4`
Doppler config: `preview_4`
Type: `environment-config-lease`
Leased until: 2026-06-10T16:10:58.241Z

### OS
Status: tests failed
Commit: `a9d4a4d`
Preview: https://os.iterate-preview-4.com
Summary: ❯ node src/itx/e2e/itx.e2e.test.ts (10 tests | 1 failed | 1
skipped) 93401ms
[Workflow
run](https://github.com/iterate/iterate/actions/runs/27285949769)
Updated: 2026-06-10T15:23:10.059Z

<details>
<summary>Failure details</summary>

<pre>...(truncated)
t.toBeNull();
    397|   expect(error!.name).toBe("ItxError");
       |                       ^
    398|   expect(error!.code).toBe("NOT_FOUND");
399| expect(error!.details).toEqual({ projectIdOrSlug:
"definitely-not-a-…

⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/1]⎯



&gt; @iterate-com/os@0.0.1 e2e /home/runner/work/iterate/iterate/apps/os
&gt; vitest --config e2e/vitest.config.ts -t 'OS preview smoke'

[vitest-artifacts] run root: /tmp/os-e2e-deTncv
[vitest] run slug: os-vitest-run-20260610-151920

 RUN  v4.0.15 /home/runner/work/iterate/iterate/apps/os

stdout | e2e/vitest/preview-smoke.e2e.test.ts &gt; OS preview smoke
OS preview smoke passed for https://os.iterate-preview-4.com/

 ✓ e2e/vitest/preview-smoke.e2e.test.ts (1 test) 6669ms
   ✓ OS preview smoke  6668ms
 ↓ e2e/vitest/admin-project.e2e.test.ts (1 test | 1 skipped)
 ↓ e2e/vitest/agents.e2e.test.ts (9 tests | 9 skipped)
↓ e2e/vitest/codemode-mcp-provider-stack.e2e.test.ts (1 test | 1
skipped)
 ↓ e2e/vitest/codemode.e2e.test.ts (3 tests | 3 skipped)
 ↓ e2e/vitest/e2e-test-map.e2e.test.ts (13 tests | 13 skipped)

 Test Files  1 passed | 5 skipped (6)
      Tests  1 passed | 27 skipped (28)
   Start at  15:19:20
Duration 7.99s (transform 210ms, setup 0ms, import 837ms, tests 6.67s,
environment 1ms)


&gt; @iterate-com/os@0.0.1 e2e:itx
/home/runner/work/iterate/iterate/apps/os
&gt; vitest run --config src/itx/e2e/vitest.config.ts --project node

[vitest-artifacts] run root: /tmp/os-itx-e2e-DurFwM
[vitest] run slug: os-vitest-run-20260610-151929

 RUN  v4.0.15 /home/runner/work/iterate/iterate/apps/os

❯ node src/itx/e2e/itx.e2e.test.ts (10 tests | 1 failed | 1 skipped)
93401ms
✓ itx scripts run identically over Cap'n Web and /api/itx/run 11957ms
✓ the five-step capability flow: provide live, call, promote durable,
call from a script 11979ms
✓ platform bindings are dialable capabilities (raw + wrapped) 11831ms
   ↓ the first-party McpClient cap bridges a remote MCP server
✓ script executions leave a two-event record on the /itx stream 13369ms
   ✓ worker caps hold a correctly scoped itx of their own  9833ms
✓ members caps auto-proxy every public method/getter at any depth
11350ms
✓ one dynamic worker cap calls another's methods through its own itx
10597ms
× kernel errors cross capnweb as ItxError-shaped errors with codes 89ms
   ✓ revoked and offline caps fail with instructive errors  10399ms
 ✓  node  src/itx/e2e/itx-fork.e2e.test.ts (3 tests) 52757ms
✓ fork: child caps shadow the parent, misses delegate up the chain
15585ms
✓ fork narrows access: a session cannot reach sibling projects 19542ms
✓ fork: child worker caps run with the owning project's authority
15835ms
 ✓  node  src/itx/e2e/itx-egress.e2e.test.ts (3 tests) 37217ms
✓ itx.fetch substitutes secrets through project egress (explicit door)
9642ms
✓ bare fetch() in a project itx script goes through egress (implicit
door) 16508ms
✓ bare fetch() inside a worker cap goes through egress (implicit door)
8802ms
 ✓  node  src/itx/e2e/itx-http.e2e.test.ts (2 tests) 24080ms
   ✓ facet caps keep private durable state across invocations  8799ms
✓ HTTP-exposed caps serve their own hostname: admin, share URL, public
13750ms
 ✓  node  src/itx/e2e/itx-subscribe.e2e.test.ts (1 test) 12735ms
✓ subscribe replays history, tails live appends, and unsubscribes
10991ms

 Test Files  1 failed | 4 passed (5)
      Tests  1 failed | 17 passed | 1 skipped (19)
   Start at  15:19:29
Duration 220.79s (transform 79ms, setup 0ms, import 184ms, tests
220.19s, environment 0ms)


::error
file=/home/runner/work/iterate/iterate/apps/os/src/itx/e2e/itx.e2e.test.ts,title=[node]
src/itx/e2e/itx.e2e.test.ts &gt; kernel errors cross capnweb as
ItxError-shaped errors with codes,line=397,column=23::AssertionError:
expected 'Error' to be 'ItxError' // Object.is equality%0A%0AExpected:
"ItxError"%0AReceived: "Error"%0A%0A ❯
src/itx/e2e/itx.e2e.test.ts:397:23%0A%0A
 ELIFECYCLE  Command failed with exit code 1.</pre>

</details>
<!-- /CLOUDFLARE_PREVIEW -->

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
jonastemplestein added a commit that referenced this pull request Jun 10, 2026
#1479)

## Streams review — Stages 4–7 (browser robustness, perf, dead code,
docs)

The final batch of the `packages/streams` adversarial review
(`tasks/streams-review-fixes.md`), bundled into one PR per request.
Stages 0/1/3 already shipped (#1455, #1458, #1459); **Stage 2 (lazy
init) was abandoned** — #1460's subscriber-presence model appends a
`subscriber-connected` fact on every `subscribe()`, which fundamentally
conflicts with "don't initialize storage until the first `append()`".
`created`/`woken` stay eager.

All findings were re-verified against current `main` after #1460/#1457
moved the codebase; items those PRs already fixed or made obsolete are
called out below.

### Stage 4 — browser-runtime correctness
- **C1-browser** — the server delivery pump is fire-and-forget for
inbound subscribers and never reports a failed `ingest`, so a browser
mirror that fails to apply a batch silently desyncs forever. The browser
now self-heals: `ingestWithSelfHeal` resubscribes from the persisted
checkpoint with bounded exponential backoff on ingest failure.
- **B1** — connection-epoch guard so a stale connection's late status
callback can't clobber the live connection.
- **B2** — `appendBatch`/`runtimeState` await connection readiness
(`whenStreamReady`) instead of throwing "disposed" during a transient
reconnect; only throw when actually disposed.
- **B3** — the `ROLLBACK` in `stream-db.worker.ts` `batch()` is now in
its own try/catch so it can't mask the original error (which
`withBusyRetry`/`isBusyError` need to see).
- **B4** — reconcile guards on stream incarnation (server `createdAt` +
a `mirror_meta` table): rebuild the mirror on incarnation change rather
than trusting the offset comparison after a `reset()`.
- **B5** — `AbortSignal` on the Web Lock request (released on disposal)
+ the request rejection is surfaced instead of `void`-swallowed.
- **B6** — query lifecycle: arm GC at query creation (not only on
unsubscribe), skip listenerless queries in `#onChange`, and
equality-check before notifying to avoid spurious `useSyncExternalStore`
churn.

### Stage 5 — performance
- **P1** — `browser-event-feed` O(n²) write amplification: coalesce to
one op per `local_index` (was a cumulative op per event, each
re-serializing the whole accumulated array).
- **P2** — bound group rows with `MAX_GROUP_EVENTS = 200` so one
dominant event type can't grow a single blob unboundedly.
- **P3** — drop the per-event full-state `stateSchema.parse` in core
`reduce`; state is validated only at the KV/recovery trust boundary now.
- **P4** — already fixed by #1460 (subscribe override forwards
`eventTypes`; filtering is server-side). No change.

### Stage 6 — dead code / elegance (~247 lines deleted)
- **E1** dead exports in `shared/stream-processors.ts`; **E2**
`waitForOpen`; **E3** unreachable circuit-breaker `paused` guard; **E5**
dead `waitForEvent`/`messageInbox.error` machinery in `subscription.ts`;
**E6** redundant circuit-breaker `consumes` entries.
- **E4 obsolete** (#1460 removed `processor-registered`; the shared
`circuit-breaker-types` is a live, separately-imported hierarchy, not
dead code). **E7 declined** — post-#1460 the subscribe override
genuinely needs to retain the client callback / wire `onRpcBroken`, so
folding it into the generic `makeRpcTargetClass` isn't worth it.

### Stage 7 — docs
- **D1** `design.md`: status banner, fixed 1-based offsets + core-event
examples, the callable subscriber spec, SQLite/512KB-chunking storage,
live-tail `replayAfterOffset` default, OPFS mirror; superseded banners
on the never-shipped `implementProcessor`/`connectStream` sections.
- **D2** `README.md`: real browser export
(`withStreamConnectionFromBrowser`), sync `Disposable`, `?path=` route
map; new "Append & subscription semantics" section (D5).
- **D3** ADR 0001 superseded with the shipped per-`(namespace, path,
slug)` singleton model.
- **D4** remaining comment drift (`beforeAppend`→`validateAppend`,
`afterAppendBatch`→`processEventBatch`).

### Testing
`pnpm typecheck`, `pnpm lint`, node (79) + workers (15) suites, and
example-app typecheck all green. Example-app Playwright e2e run locally
against a clean `vite dev` (real Stream DO via Miniflare): **26
passed**. `origin/main` merged in (no `packages/streams` overlap; the
new project-config stream-processor consumers don't touch any deleted
exports).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Medium Risk**
> Touches browser reconnect, mirror discard, and ingest self-heal paths
that affect live viewers and local SQLite mirrors; server stream DO
behavior is mostly unchanged aside from core reduce hot-path
optimization.
> 
> **Overview**
> Closes out **Stages 4–7** of the `packages/streams` adversarial
review: browser mirror reliability, feed/core hot-path perf, dead-code
removal, and doc alignment. Stage 2 (lazy stream init) stays
**abandoned** and is only noted in `tasks/streams-review-fixes.md`.
> 
> **Browser runtime** (`stream-browser-store.ts` and friends) is
reworked so the OPFS mirror can recover instead of silently drifting.
Inbound delivery is fire-and-forget, so failed `ingest` now triggers
**`ingestWithSelfHeal`** (resubscribe from the last checkpoint with
capped exponential backoff). Reconnects go through one
**`scheduleReconnect`** path with a **connection epoch** so stale
WebSocket callbacks cannot tear down the replacement connection.
**`appendBatch` / `runtimeState`** use **`callWhenReady`** /
**`whenStreamReady`** during transient reconnects instead of throwing
“disposed”. Mirror trust uses server **`createdAt`** as incarnation
identity via new **`mirror_meta`** helpers in
**`stream-browser-db.ts`**. Web Lock **`release()`** aborts pending lock
requests; the SQLite worker preserves the original batch error if
`ROLLBACK` fails; reactive queries GC earlier, skip unobserved
refreshes, and avoid notify when snapshots are unchanged.
> 
> **Performance:** `browser-event-feed` **`planFeedOps`** coalesces one
SQL op per group row and caps groups at **`MAX_GROUP_EVENTS` (200)**.
Core **`reduce`** no longer exit-parses the full `stateSchema` on every
appended event.
> 
> **Cleanup:** ~247 lines removed (unused `stream-processors` exports,
`waitForOpen`, dead subscription `waitForEvent` machinery, trimmed
circuit-breaker `consumes` and an unreachable guard). **Docs:** `README`
(real browser API, `?path=` routes, append/subscription semantics),
`design.md` and ADR 0001 marked superseded where they diverge from
shipped code.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
f52f305. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

<!-- CLOUDFLARE_PREVIEW -->
## Environment Config Lease
<!-- CLOUDFLARE_PREVIEW_STATE -->
<!--
{
  "apps": {
    "os": {
      "appDisplayName": "OS",
      "appSlug": "os",
      "status": "deployed",
      "updatedAt": "2026-06-10T22:02:58.860Z",
      "headSha": "f52f305a9f1ab43c9749f80e30bcd96705cbce59",
      "message": null,
      "publicUrl": "https://os.iterate-preview-3.com",
"runUrl": "https://github.com/iterate/iterate/actions/runs/27309066809",
      "shortSha": "f52f305"
    }
  },
  "environmentConfigLease": {
    "dopplerConfig": "preview_3",
    "leasedUntil": 1781132382486,
    "leaseId": "52648479-bd91-469d-91e5-a3338534feae",
    "slug": "preview-3",
    "type": "environment-config-lease"
  }
}
-->
<!-- /CLOUDFLARE_PREVIEW_STATE -->
Lease: `preview-3`
Doppler config: `preview_3`
Type: `environment-config-lease`
Leased until: 2026-06-10T22:59:42.486Z

### OS
Status: deployed
Commit: `f52f305`
Preview: https://os.iterate-preview-3.com
[Workflow
run](https://github.com/iterate/iterate/actions/runs/27309066809)
Updated: 2026-06-10T22:02:58.860Z
<!-- /CLOUDFLARE_PREVIEW -->

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
jonastemplestein added a commit that referenced this pull request Jun 11, 2026
The packages/streams adversarial review is fully shipped — Stages 0/1/3
(#1455/#1458/#1459), Stages 4–7 (#1479), Stage 2 deliberately abandoned.
This deletes the now-stale `tasks/streams-review-fixes.md` and removes
the dangling pointers to it from the regression-test comments (the
finding ids and the PRs in git history are the durable record).

Doc/comment-only; no code changes.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Documentation and comment-only changes; no runtime or test behavior
changes.
> 
> **Overview**
> Removes the completed **`tasks/streams-review-fixes.md`** tracking doc
now that the June 2026 `packages/streams` review work is shipped (Stages
0/1/3 via #1455/#1458/#1459, Stages 4–7 via #1479; Stage 2 abandoned).
> 
> Regression test file headers are updated so they no longer link to
that task file. Comments now cite **review finding ids (C*/M*)** and the
**merged PRs** as the durable record instead.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
7c33b86. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

<!-- CLOUDFLARE_PREVIEW -->
## Environment Config Lease
<!-- CLOUDFLARE_PREVIEW_STATE -->
<!--
{
  "apps": {
    "os": {
      "appDisplayName": "OS",
      "appSlug": "os",
      "status": "deployed",
      "updatedAt": "2026-06-11T09:38:48.453Z",
      "headSha": "7c33b86fa2d6f11b18ad8e99bc42c78940c8a623",
      "message": null,
      "publicUrl": "https://os.iterate-preview-2.com",
"runUrl": "https://github.com/iterate/iterate/actions/runs/27337613329",
      "shortSha": "7c33b86"
    }
  },
  "environmentConfigLease": {
    "dopplerConfig": "preview_2",
    "leasedUntil": 1781174051088,
    "leaseId": "82ae23a4-0588-41db-bf69-772ac5bb0d87",
    "slug": "preview-2",
    "type": "environment-config-lease"
  }
}
-->
<!-- /CLOUDFLARE_PREVIEW_STATE -->
Lease: `preview-2`
Doppler config: `preview_2`
Type: `environment-config-lease`
Leased until: 2026-06-11T10:34:11.088Z

### OS
Status: deployed
Commit: `7c33b86`
Preview: https://os.iterate-preview-2.com
[Workflow
run](https://github.com/iterate/iterate/actions/runs/27337613329)
Updated: 2026-06-11T09:38:48.453Z
<!-- /CLOUDFLARE_PREVIEW -->

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant