feat(state): #98 v1 node:sqlite workspace-durable driver + example migration (PR-2) - #149
Conversation
🦋 Changeset detectedLatest commit: 494f8fe 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. |
… migrates off its JSONL kernel (#98 v1, PR-2) The workspace-durable driver ships on node:sqlite (G3: zero new dependencies; the ExperimentalWarning is documented in the module and both READMEs): WAL with full synchronous durability, every commit in one BEGIN IMMEDIATE transaction, bounded busy-timeout cross-process serialization, explicit migrations on open, corruption fail-closed. It passes the same conformance suite as the memory driver plus the two cross-process acceptance proofs (two independent writers over one store; a SIGKILLed writer cannot leave successful-but-corrupt state), and lives behind its own ./state/sqlite subpath sharing one kernel runtime instance with ./state so error identity holds across entries. examples/rsc-agent-runtime retires its 781-line JSONL kernel and lock machinery: the example now declares schema/events/reducer via defineState and adapts the framework store to its provider-facing RuntimeKernel contract, with eventId/recordedAt derived from journal revisions and commit timestamps so whole-payload idempotency matches the retired kernel's semantic dedupe identity. Tests and pnpm eval:spot stay green, with the spot check now also proving cross-process idempotent replay.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c86690afab
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
c86690a to
494f8fe
Compare
…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.
…ots, workspace-free published manifest (#183) Three independent breakages kept hosted CI red on main: - scripts/run-examples-check.mjs launched npm_execpath through the current Node executable, but pnpm/setup on hosted runners exposes a native shim (bare command name), so `node pnpm` failed with MODULE_NOT_FOUND. The script now execs non-JavaScript entrypoints directly. - The sqlite migration (#149) made the example kernel return the durable prefix at the original commit revision on idempotent replays; the retired JSONL kernel returned the current head. Re-running a fixture after a reset therefore reported the pre-reset state version and failed the runtime playground e2e on every Node line. Replays now read the head again. - #151 added `"@agent-bundle/runtime": "workspace:*"` to the published agent-bundle devDependencies, tripping the release audit (npm refuses tarball manifests with workspace ranges). The optional peer is now satisfied through a pnpm-workspace override instead of a shipped range.
Summary
Wave 2 Lane B, PR 2 of 2 for the #98 v1 state kernel (follows #142; plan #107 §6, G3 recorded).
node:sqliteworkspace-durable driver behind the new@agent-bundle/runtime/state/sqlitesubpath (G3: zero new dependencies; ExperimentalWarning documented in the module and both READMEs). WAL journal mode withsynchronous = FULL; every commit is oneBEGIN IMMEDIATEtransaction (idempotency lookup, CAS, reducer, journal append, head update commit atomically); cross-process writers serialize on the database lock with a bounded busy timeout; explicit migrations run on open and rebase history; corruption fails closed with typed errors (SQLITE-level, head/journal mismatch, schema-invalid persisted state, unknown kernel format, foreign definition id).PRAGMA integrity_checkok, every retained revision replays, new commits accepted)../statenever loadsnode:sqlite, and./state/sqliteshares the./stateruntime chunk soinstanceof AgentStateErrorholds across subpaths (the sqlite lib externalizes the kernel to../state.jsinstead of re-bundling it). Package now declares"sideEffects": false.examples/rsc-agent-runtimeretires its 781-line JSONL kernel (state-file-core.ts, test support, lock fixtures,proper-lockfiledependency — net −1,996 lines). The example now declares schema/events/reducer viadefineStateand adapts the framework store to its unchanged provider-facingRuntimeKernel/RuntimeSnapshotcontract. The event payload is exactly the four caller-owned fields (the retired kernel's canonical dedupe identity);eventId/recordedAtare derived from journal revisions and commit timestamps, so native tool-id retries replay instead of conflicting. No wire-DTO changes.eval:spotstays green and now also proves cross-process idempotent replay (a second hook process replaying the sametool_use_idcommits nothing). Tests that pinned raw JSONL bytes now read through the kernel; stderr-sensitive tests tolerate exactly the documented sqlite ExperimentalWarning and nothing else.Test plan
pnpm --filter @agent-bundle/runtime test— 108 passed (18/18 conformance on sqlite incl. durable-only; cross-process two-writer + SIGKILL proofs; packaging boundaries)pnpm --filter @agent-bundle/rsc-agent-runtime-demo check— validate/build/typecheck green; tests 174 total, 0 failed (6 pre-existing skip-gated host opt-ins)pnpm eval:spot— greenpnpm lint,pnpm typecheck,pnpm check:runtime-topology— cleanFixes #98. Refs #107.