refactor(state): Effect-native kernel internals behind the unchanged API (wave 3.5 stage 1) - #154
Merged
Merged
Conversation
…API (wave 3.5 stage 1) - sqlite driver: connection owned by a Layer + per-store scoped runtime; BEGIN IMMEDIATE / COMMIT / ROLLBACK as Effect.acquireUseRelease with rollback-on-failed-commit; SqliteConnection as a Context.Service - typed AgentStateError error channel end to end; sqlite/system throws map to the existing corrupt/unavailable codes, unexpected throws stay defects and still roll the transaction back - memory driver: same stateEffect channel; store close is the scope finalizer - driver close now settles pending opens with store-closed before resolving (new race tests pin it for both drivers) - packaging test additionally proves root/plugin entries ship no effect bytes - host-artifacts example test: allow the optional react peer that #151 added (pre-existing failure on main; hard deps stay banned) - agent-patterns/effect-scope.md: document the transaction idiom the rewrite settled on (dogfood feedback)
🦋 Changeset detectedLatest commit: 180e708 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
ScriptedAlchemy
added a commit
that referenced
this pull request
Sep 1, 2026
agent-bundle's test helpers import @agent-bundle/runtime; CI was typechecking that package before runtime dist existed, which is why main's post-#154 Verify jobs fail in ~30s.
ScriptedAlchemy
added a commit
that referenced
this pull request
Sep 1, 2026
agent-bundle's test helpers import @agent-bundle/runtime; CI was typechecking that package before runtime dist existed, which is why main's post-#154 Verify jobs fail in ~30s.
ScriptedAlchemy
added a commit
that referenced
this pull request
Sep 1, 2026
… 3.5 stage 2) (#156) * refactor(runtime): Effect-native dispatcher and stream pipeline (wave 3.5 stage 2) Rewrite the #145 Flight decode and bound-event pipeline on Effect Streams and fibers while keeping dispatch() and stream() byte-compatible. Refs #152. * fix(build): emit runtime types before agent-bundle declaration emit agent-bundle's test helpers import @agent-bundle/runtime; CI was typechecking that package before runtime dist existed, which is why main's post-#154 Verify jobs fail in ~30s. * docs(runtime): record the verified locked-stream teardown mechanism in comments The maxEvents hang was not a blocking-interrupt deadlock: the acquireRelease finalizer called cancel() on the Flight readable while the Flight client held its reader, the locked-stream rejection became an Effect.promise defect during scope close, and the event stream's exit never surfaced. Document that at the scopedAbortSignal fix site and correct the boundary cancel() comment.
5 tasks
ScriptedAlchemy
added a commit
that referenced
this pull request
Sep 1, 2026
…head verification, replay across migrations (#171) Codex review follow-ups on the state kernel and drivers, re-verified against the Effect-native internals from #154: - Both drivers consult the idempotency key before running the reducer (#142/#149 P1): a committed key replays its stored result even when the reducer would now fail against the current head. Payload validation and canonicalization moved ahead of the key lookup; the reducer runs only on the append path. - Committed results replay across migrations (#142 P1): every journal record stores its post-commit state (event rows too, in the sqlite driver's existing nullable column), and migrations run the same chain over the stored results, so replay no longer depends on exact-revision history that migrations rebase. Legacy event rows without a stored state fall back to journal replay. - The sqlite driver verifies storage on open (#149 P1): journal continuity via expectConsistentJournal (a deleted intermediate row fails closed) and the materialized head against journal replay (a schema-valid hand-edited head fails closed); with a pending migration the head is checked against the last stored post-commit state instead. - sanitizedFileName hashes the complete definition id (sha-256) instead of hex-encoding its first six bytes (#149 P2), so ids sharing a sanitized prefix get isolated database files. - isJsonSafe rejects sparse arrays (#142 P2): holes no longer canonicalize like dense arrays under permissive schemas. The conformance suite pins the corrected semantics for both drivers: replay-before-reduce, replay across migrations, and prefix-colliding id isolation; sqlite corruption tests cover the two new fail-closed opens.
This was referenced Sep 1, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Wave 3.5 stage 1: the #98 state kernel becomes the exemplar Effect migration. Internals are Effect v4; the public API (
defineState,dispatch,read,changes,reset, the typedAgentStateErrorcodes, Promise shapes) is byte-for-byte unchanged, enforced by the untouched conformance suite.DatabaseSyncconnection lives in aLayerbehind a per-store scoped runtime (makeScopedEffectRuntimefrom the stage-0 boundary);store.close()disposes the runtime and the connection closes as the scope finalizer.BEGIN IMMEDIATE/COMMIT/ROLLBACKis oneEffect.acquireUseRelease: rollback on failure, and a failed COMMIT still rolls back before re-raising so the connection never holds a transaction open.Effect.Effect<A, AgentStateError>; sqlite/system throws map to the existingcorrupt/unavailable/busy→unavailablecodes; unexpected throws stay Effect defects (with the transaction still rolled back — new test pins the defect passing throughrejects.toBe(defect)with revision 0 preserved). The Promise edge goes through the stage-0 boundary module only; the boundary lint rule keeps it that way.close()now settles pendingopen()s withstore-closedbefore resolving, and repeated closes share one settlement. New race tests pin this for both drivers.from "effect"/Effect.runPromisebytes, so stateless projects ship zero effect cost.examples/rsc-agent-runtimehost-artifacts.test.tsfailed on pristinemainbecause feat(test): route-unit consumer test harness (#103 stage 1) #151 addedreactas an optional peer ofagent-bundle. The assertion now bans hard deps but allows peers explicitly marked optional inpeerDependenciesMeta.agent-patterns/effect-scope.mdgains the transaction idiom (acquireUseRelease+ rollback-on-failed-commit) the rewrite settled on.Parity bar (all unchanged suites, all green)
state-sqlite-cross-process.test.ts)examples/rsc-agent-runtime: 168 passed / 6 skipped / 0 failedpnpm eval:spot: green