Skip to content

Route Store through agent-store substrate (dogfood the causal store)#59

Merged
hartsock merged 2 commits into
mainfrom
feat/agent-store-substrate
Jun 14, 2026
Merged

Route Store through agent-store substrate (dogfood the causal store)#59
hartsock merged 2 commits into
mainfrom
feat/agent-store-substrate

Conversation

@hartsock

@hartsock hartsock commented Jun 14, 2026

Copy link
Copy Markdown
Owner

Summary

modulex becomes the second consumer of agent-store (alongside newt-agent), dogfooding the shared causal-store substrate and making its storage backend a policy-driven config choice.

Substrate adoption:

  • Store holds an agent_store::SqliteBackend (via from_connection) instead of a bare rusqlite::Connection. All domain SQL is unchanged — it runs on backend.connection().
  • The engine generation counter is now agent_store::Generation. A one-time migration carries any pre-substrate meta.last_generation value into the substrate counter and drops the legacy row.

Policy-driven backend (flat knob):

  • [store] backend = "sqlite" | "postgres", defaulting to sqlite. StoreConfig flattens agent_store::StorePolicy; Store::open_with_policy routes construction by the policy.
  • postgres is reserved (Phase 2) and rejected with a clear error (the engine treats it as a soft "store unavailable" skip — never a silent fallback).
  • Lowers risk, enables direction changes later: the default is a no-op (today's behavior), and switching backends is a reviewed config edit, not a code change.

Depends on agent-store = "0.1" (crates.io, v0.1.2). No behavior change at the default.

Test plan

  • just check green: fmt + clippy -D warnings + tests (145 modulex-core lib + workspace).
  • Regression tests: legacy_generation_is_migrated_into_substrate (fails on old path), policy_rejects_reserved_postgres_backend (fail-loud), store_backend_is_a_flat_policy_knob (flatten parses via the real Config path).

risk:low — scoped to the store seam + a defaulted config knob, regression-tested, no CI/hook/pipeline changes. Left for human review/merge per repo policy.

WHAT: modulex's Store now holds an agent_store::SqliteBackend (via
from_connection) instead of a bare rusqlite Connection, and the engine
generation counter is agent_store::Generation. All domain SQL is unchanged,
running on backend.connection(). A one-time migration carries the pre-substrate
`meta.last_generation` string into the substrate counter and drops the legacy
row (single source of truth). Depends on agent-store 0.1.1 (crates.io).

WHY: dogfood the shared causal-store substrate (PG-readiness + shared causal
primitives) in a second consumer alongside newt-agent. No behavior change.

Regression test: legacy_generation_is_migrated_into_substrate — fails on the
old path (old code never dropped the legacy row). 143 modulex-core lib tests
green; `just check` clean (fmt + clippy -D warnings + tests).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@hartsock hartsock added the risk:low Scoped, tested, no CI/build changes label Jun 14, 2026
WHAT: `[store] backend = "sqlite" | "postgres"` — a flat knob defaulting to
sqlite. StoreConfig flattens agent_store::StorePolicy; Store::open_with_policy
routes construction by the policy: sqlite opens as before, postgres is reserved
(Phase 2) and rejected with a clear error (the engine treats that as a soft
"store unavailable" skip — never a silent fallback). Bumps the dep to
agent-store 0.1.2.

WHY: the backend a consumer opens should be a reviewed configuration choice,
not a hardcoded commitment — lowering risk (safe SQLite default, reversible)
and letting the fleet change direction (to Postgres, later) by editing config
instead of code.

Tests: store_backend_is_a_flat_policy_knob (flatten parses via the real Config
path), policy_rejects_reserved_postgres_backend (fail-loud, no silent fallback).
145 modulex-core lib tests green; `just check` clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@hartsock hartsock merged commit cb90c65 into main Jun 14, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:low Scoped, tested, no CI/build changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant