Daeseon Yoo
Back to project
·Tech retro·3 min

Hardening operating-memory and growing a connector action spine

A week of parallel work that tightened the GraphStore operating-memory contract and grew a provider-neutral action SDK — the spine that future connector packs will execute through, without adding any real provider calls.

DalkkakAI's wedge is business memory, not coding help. This week's parallel packets pushed on the two load-bearing layers underneath that wedge: the GraphStore that is the operating memory, and the action SDK that future connector packs will run through. The honest headline: the memory contract got harder, the action spine got real shape, and nothing started calling a real provider.

One contract for the whole graph

The biggest correctness win was unifying how edges enter the store. Two branches had independently bolted an "edges" feature onto GraphStore, so the merge (apps/desktop/src-tauri/src/capture.rs) collapsed them onto a single API — append_edge / has_edge / read_edges_all, backed by one edge_seen dedup map. The memory engine's callers in memory.rs were renamed (read_all_edgesread_edges_all) so the RAG read path and the WorkItem write path now touch edges through the same function, not two parallel ones that could drift.

What matters is that append_edge enforces the same provenance contract as nodes: a confirmed record must carry evidence, schema_version is validated (a v2 record is rejected with unsupported schema_version), and secret-looking tokens (sk-ant-, ghp_, …) are redacted before anything is written. Edges aren't a second-class side channel anymore; they obey the integrity rules the nodes always did. JSONL stays the single canonical log.

The SQLite sidecar is honestly still a plan

apps/desktop/src-tauri/src/graph_index.rs reads like production but is deliberately inert (#![allow(dead_code)], no Tauri command registered, no SQLite crate added). It contains a JSONL node/edge parser, a normalizer, and a full GRAPH_INDEX_SCHEMA_SQL string — graph_nodes/graph_edges/graph_evidence tables, startup/type/domain/created_at indexes, and an FTS5 virtual table for future full-text search. The framing is the point: this SQLite/FTS index is a derived, rebuildable projection over the JSONL log, never an authority. Until parity tests against read_all()/read_edges_all() exist, it stays a sidecar.

A spine, not a faucet

packages/action-sdk/src/index.ts is where the connector packs will eventually plug in, and it grew the contracts that make "did this action actually happen?" answerable. AR01 added an ActionLifecycleState machine, an ActionRuntimeContract (permission scope, risk, approval requirement, rollback requirement, required evidence fields, receipt shape), a ProviderNeutralExecutionPlan, and a shaped ConnectorActionExecutionReceipt stamped schemaVersion: action-receipt.v1. The rule the whole thing exists to enforce: a claim of external mutation only clears externalMutationBlocked if it carries a real receipt with matching run identity, dryRun=false, an approval receipt, required evidence, and a rollback plan when one is required. A mock or fixture receipt is valid for planning and can never masquerade as provider execution — there's even a guard that fails business-output copy like "sent successfully" when the metadata says mock.

AR02 then turned the screws: sandbox vocabulary (execution_blocked, rollback_required, …), execution-capability and rollback-capability records, and provider rate-limit/backoff plus network-partition state. High-risk or external-apply plans stay blocked unless approval, execution capability, supported rollback, clear backoff, and a dispatchable network all line up. The local MCP server mirrors all of this read-only — it exposes the gates, it does not pull the trigger.

What's still owed

Everything provider-real. No Gmail/Stripe/social/CRM/browser adapter executes; the SQLite importer isn't wired; rollback is modeled, not performed. Verification was the SDK/MCP test suites and scripts/verify-local.sh (Rust tests green, action-sdk and local-mcp tests green) — AR02's desktop run was blocked by unrelated dirty worktree state, logged rather than papered over. The spine is in place; the muscles come next.