Skip to content

Streaming phase 3#611

Open
sroussey wants to merge 10 commits into
claude/relaxed-faraday-ql3olrfrom
claude/task-graph-streaming-phase3-yg5msj
Open

Streaming phase 3#611
sroussey wants to merge 10 commits into
claude/relaxed-faraday-ql3olrfrom
claude/task-graph-streaming-phase3-yg5msj

Conversation

@sroussey

@sroussey sroussey commented Jul 3, 2026

Copy link
Copy Markdown
Collaborator

No description provided.

claude added 10 commits July 3, 2026 00:59
… backings

Filesystem/in-memory streaming backings resolve a cache-miss synchronously via
an existence probe (openSync / Map lookup). Async stores (IndexedDB, SQL) cannot,
so widen getOutputStreamByRef to optionally return a Promise and await it in the
shared streamRefViaBacking helper. A dangling ref now resolves to undefined (a
miss) for async backings instead of a truthy Promise mistaken for a live stream.
Synchronous backings are unaffected (awaiting a non-Promise is identity).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QehfSG3zCtk6WPebaCuo8R
Persists a ref's bytes as ordered chunk rows keyed by [refKey, seq] with a
manifest row (existence witness + size + createdAt). Streaming writes never
accumulate; reads page the chunk store so memory stays bounded and each page
runs in its own short-lived transaction. A sibling instance over the same
dbName resolves refs (cross-instance read contract).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QehfSG3zCtk6WPebaCuo8R
A TaskOutputRepository whose JSON rows persist via IndexedDbTabularStorage and
whose streamed port payloads persist as chunked blobs (IdbBlobChunkStore),
referenced by CacheRef. Implements the full streaming surface
(saveOutputStream/saveOutputStreamPort/getOutputByRef/getOutputStreamByRef/
deleteOutputByRef) with async reads; supportsStreaming/Reads/Ports all true and
isDurable true. Round-trips every codec mode, keeps distinct ports at distinct
refs, prunes blobs with rows, resolves refs cross-instance, and converts a
dangling ref into a cache miss through streamRefViaBacking.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QehfSG3zCtk6WPebaCuo8R
The streaming-read contract now permits an async getOutputStreamByRef, so the
base-typed contract suites (deterministic CacheStreamOut and run-private
RunPrivateFsFolderStream) must await the reader before consuming it. Runtime is
identical for the synchronous FsFolder/in-memory backings (awaiting a non-Promise
is identity); the suites still assert the same bytes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QehfSG3zCtk6WPebaCuo8R
The column definitions and the ON CONFLICT clause already quote identifiers,
but the CREATE TABLE PRIMARY KEY clause did not — so a schema with a camelCase
primary-key column (e.g. TaskOutputSchema's taskType) created a quoted
"taskType" column while the PK clause referenced the folded tasktype, failing
with 'column "tasktype" named in key does not exist'. Quote the PK list
consistently; snake_case schemas are unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QehfSG3zCtk6WPebaCuo8R
TabularBlobChunkStore persists a ref's bytes as ordered (refKey, seq, bytes)
chunk rows plus a manifest row over any ITabularStorage, with keyset-paged
bounded-memory reads. TabularStreamingTaskOutputRepository is the shared base
(rows + blob store + <scheme>://<refKey> refs); Streaming{Postgres,Sqlite}
TaskOutputRepository are thin subclasses over bytea / BLOB chunk tables. Tested
with InMemory (store logic), in-process PGlite (Postgres), and better-sqlite3.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QehfSG3zCtk6WPebaCuo8R
Parity with the PostgresTabularStorage fix: the exec_sql bootstrap DDL quoted
the column definitions but not the PRIMARY KEY clause, so a camelCase-PK schema
created a quoted column while the PK referenced the folded lowercase name.
Only the local-dev/test exec_sql bootstrap path is affected (production tables
are owned by Supabase migrations); snake_case schemas are unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QehfSG3zCtk6WPebaCuo8R
StreamingSupabaseTaskOutputRepository is a thin TabularStreamingTaskOutputRepository
subclass over SupabaseTabularStorage (bytea chunk tables via TabularBlobChunkStore),
tested through the PGlite-backed Supabase mock. Two mock fixes make a camelCase
schema faithful to real PostgREST (which quotes identifiers): quote the ON CONFLICT
target in upsert, and map delete-chain neq(col, null) to IS NOT NULL so deleteAll
actually clears. No external Supabase required.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QehfSG3zCtk6WPebaCuo8R
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.

2 participants