Skip to content
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
6067b9c
docs(state): ADR 0001 — state store lives in the worker process
guibeira Jul 6, 2026
a4d8c94
feat(state): scaffold state worker crate
guibeira Jul 6, 2026
265bea6
feat(state): worker config — kv/redis adapter oneOf, live gates, save…
guibeira Jul 6, 2026
6534f8c
feat(state): port update-op engine verbatim (merge/set/increment/appe…
guibeira Jul 6, 2026
80b28f6
feat(state): port BuiltinKvStore — identical on-disk format, save-loo…
guibeira Jul 6, 2026
0408ea4
feat(state): kv and redis adapters (state:<scope> hash parity, atomic…
guibeira Jul 6, 2026
0d0c8f5
feat(state): parity structs + trigger handler keyed by id (silent rep…
guibeira Jul 6, 2026
6a3a7c6
feat(state): event fan-out + six state::* functions (exact id/shape p…
guibeira Jul 6, 2026
e77acd5
feat(state): boot with builtin iii-state guard, trigger type + functi…
guibeira Jul 6, 2026
a91a275
feat(state): configuration integration — live gates, save-cadence ret…
guibeira Jul 6, 2026
a3a8603
feat(state): binary entry with seed config and manifest output
guibeira Jul 6, 2026
a2bbc7b
test(state): connect-or-skip e2e — ops/trigger/config parity
guibeira Jul 6, 2026
7e4c6f5
style(state): cargo fmt + clippy collapsible_if fixes
guibeira Jul 6, 2026
277fb38
feat(state): release tag, README, skills, parity checklist
guibeira Jul 6, 2026
119328b
docs(state): reword telemetry parity row for external readers
guibeira Jul 6, 2026
39d9668
docs(state): document trigger-metadata parity delta + fix stale porte…
guibeira Jul 6, 2026
a88d78a
test(state): port remaining save-loop/store-method tests from the bui…
guibeira Jul 6, 2026
ebd6176
fix(state): typed schemas for interface-collection gate
guibeira Jul 8, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/create-tag.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ on:
- slack
- telegram-bot
- shell
- state
- worktree
- storage
- web
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ on:
- 'slack/v*'
- 'telegram-bot/v*'
- 'shell/v*'
- 'state/v*'
- 'storage/v*'
- 'web/v*'
- 'worktree/v*'
Expand Down
51 changes: 51 additions & 0 deletions docs/adr/0001-state-worker-store-location.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# ADR 0001: State worker — store location

## Status
Accepted (2026-07-06).

## Context
The engine builtin `iii-state` is not just a trigger handler: it owns a key-value
store that lives in the engine process (`engine/src/builtins/kv.rs`,
`BuiltinKvStore`, in_memory or file_based with a background flush loop).
Migrating `iii-state` to a standalone worker forces a decision about where that
store lives. Coupling analysis on the engine found ZERO inbound engine-internal
consumers of `state::*` (everything reaches state over the function bus), so the
functions can move; the question is only the store.

## Options

### (a) Store lives in the worker process — RECOMMENDED
Port `BuiltinKvStore` (file_based/in_memory, identical on-disk format) into the
worker; `redis` adapter ported as-is for multi-instance/production.

- Durability: store dies with the WORKER process instead of the engine process.
`file_based` keeps the same crash window (unflushed writes within one
`save_interval_ms` cadence); `redis` is unchanged. An engine restart no longer
wipes in_memory state (the worker survives it); a worker restart now does.
- Latency: `state::get/set` change from in-process calls (µs) to engine⇄worker
WebSocket round-trips (ms). This is the price of every builtin migration but
state is the hottest path — MUST be benchmarked (see Acceptance criteria).
- No engine changes required; ships entirely from the workers repo.

### (b) Engine exposes the store as a service; worker is a thin façade
Engine keeps `BuiltinKvStore` behind new internal functions; the worker proxies.
- Keeps in-engine durability but ADDS a hop to every call, and requires an
engine-repo change — out of scope for the workers repo. Rejected unless (a)'s
benchmark fails the parity gate.

### (c) State remains a builtin
No migration. Rejected as the default: contradicts the registry-migration
program, but it is the fallback if the latency benchmark shows unacceptable
regression for real workloads (e.g. Motia per-step state reads).

## Decision
Option (a). Tasks 2–13 of the state-worker plan are written against it.

## Acceptance criteria
1. Durability profile documented in the worker README (parity table): what is
lost on worker crash per adapter (`kv in_memory`: everything; `kv
file_based`: ≤ one save_interval window; `redis`: nothing).
2. Latency delta acknowledged: `state::get/set` move from in-process calls
(µs) to engine⇄worker WS round-trips (low ms). The formal p50/p95
benchmark gate was waived by project decision on 2026-07-06; the README
parity table records the order-of-magnitude delta instead.
Loading
Loading