Skip to content

Persistence v0.1: durable state ports, receipts, D1/DO reference #16

Description

@tim8es

Mission

Implement MindRail's first durable persistence boundary and Cloudflare reference mapping on branch feature/persistence-v0-1.

Base SHA: 87fbfcf2ed738071f648a3b94bfff1df1f235dba.

Before editing read AGENTS.md, ADR-0001/0003/0004/0005, docs/architecture/02_CLOUDFLARE_RUNTIME_PERSISTENCE.md, Domain Contracts, current runtime, roadmap, security docs, and docs/CURRENT_STATE.md. Current repository state wins over this issue.

Goal

Move toward a runtime that can survive process restart without making Cloudflare part of canonical domain/protocol semantics.

Implement vendor-neutral persistence ports first, then a Cloudflare D1 + Workspace Durable Object reference adapter consistent with the accepted persistence design.

Do not replace the in-memory control plane wholesale or duplicate lifecycle authority. Persistence must implement/serve the accepted runtime semantics, not define new ones.

Required storage model

Durable truth must cover at least the currently implemented/accepted concepts needed by v0.1:

  • Workspace
  • Goal
  • Task
  • Agent
  • Session
  • Lease
  • Checkpoint
  • PermissionRequest / PermissionDecision storage hooks (even if policy PR lands later, design ports so these records fit without redesign)
  • AuditEvent
  • per-Task fencing counter / allocation state
  • idempotency command receipt

Command receipt invariant

The unique logical key is exactly:

(workspaceId, commandId)

Persist atomically with an admitted mutation:

  • command discriminator;
  • canonical semantic request fingerprint;
  • immutable bounded terminal result/error snapshot.

Do not key by operation + idempotency key. Do not persist only a reference to mutable current state for replay.

Pre-admission structural/auth failures must not reserve a receipt.

Correctness requirements

Preserve ADR-0004/0005 semantics:

  • optimistic revisions;
  • exactly one effective active Lease per Task;
  • monotonic fencing on every new ownership grant;
  • stale fence cannot mutate authoritative state;
  • running Task can outlive Session/Lease and be recovered;
  • Goal-level ordering prevents CreateTask racing automatic Goal success/cancel into inconsistency;
  • same-Session duplicate claim returns current Lease without new fence;
  • session/lease expiry uses authoritative server time;
  • canonical domain admission occurs before durable commit;
  • append-only records remain append-only;
  • no full event sourcing.

Ports

Create small explicit persistence interfaces under a new owned module (src/persistence/* or equivalent). Prefer transaction-oriented semantic methods over generic put(table, json) / arbitrary CRUD abstractions.

The core layer must not import Cloudflare D1/DO types.

Where an atomic operation spans multiple records, expose a transaction boundary that can correctly implement the semantic unit rather than pretending independent writes are safe.

D1 / Durable Objects reference

Follow the accepted architecture: Workspace Durable Object coordinates Workspace-scoped mutation ordering; D1 is durable canonical operational storage. Durable Object memory is never the only source of truth and restart must not lose authority state.

Implement the smallest reference adapter that proves:

  • schema/migrations and required indexes;
  • command receipt uniqueness;
  • atomic revision update guards;
  • atomic Lease/fence allocation;
  • Workspace/Goal serialization boundary needed for Goal-level operations;
  • restart/read-back reconstruction;
  • lease/session expiry recovery queries;
  • pending human permission query support;
  • append-only checkpoint/audit writes.

Avoid queues/sharding/custom consensus unless an executed correctness test proves they are required.

SQL/index expectations

At minimum support efficient reads for:

  • Tasks by Goal;
  • claimable/recoverable Tasks;
  • active/effective Lease by Task;
  • Leases by expiry;
  • Sessions by liveness/lastSeenAt where required;
  • permission requests awaiting human decision;
  • audit events by Workspace/time;
  • command receipts by (workspace_id, command_id).

Use bounded serialized snapshots only where required by protocol replay; do not add unrestricted metadata JSON bags.

Testing

Mandatory TDD. Prefer deterministic adapter/contract tests that can run in repository CI. If real Cloudflare runtime tests cannot execute in available CI, label them explicitly unexecuted and provide runnable test harness/config; never call them PASS.

At minimum prove with executed tests:

  1. state survives adapter re-instantiation/restart simulation;
  2. duplicate admitted command returns stored immutable response and does not duplicate mutation;
  3. same commandId/different fingerprint conflicts;
  4. two competing claims cannot both obtain effective ownership;
  5. fencing strictly increases after release/expiry/session-loss recovery;
  6. stale expected revision update loses deterministically;
  7. stale fence cannot checkpoint/complete;
  8. Task/Lease/receipt commit is atomic under injected failure where applicable;
  9. Goal completion and concurrent Task creation serialize consistently;
  10. cross-workspace references fail;
  11. canonical-invalid records are never durably written;
  12. checkpoint/audit append order and immutability are preserved.

Run fresh:

  • pnpm install --frozen-lockfile
  • pnpm check
  • pnpm test:coverage
  • any additional persistence integration tests that actually execute;
  • permanent Quality on final PR head.

Scope boundaries

Do NOT:

  • change canonical JSON schemas to fit D1;
  • leak Cloudflare types into domain/protocol packages;
  • introduce event sourcing;
  • introduce a generic repository/ORM abstraction that erases semantic concurrency boundaries;
  • implement HTTP/MCP;
  • implement Permission policy evaluation;
  • implement GitHub adapter;
  • add auth/billing/account/team concepts;
  • claim production Cloudflare verification unless it actually ran against the relevant runtime.

Ownership / parallel safety

Primary ownership:

  • new src/persistence/* / Cloudflare adapter modules;
  • migrations/SQL/config specific to persistence;
  • persistence tests;
  • narrowly related docs.

Avoid large edits to src/runtime/in-memory-control-plane.ts and src/runtime/protocol*.ts; Runtime Surface is changing them in parallel. If a small integration seam is required, isolate it and document expected integration conflict rather than refactoring the runtime.

Definition of done

Open a non-draft PR from feature/persistence-v0-1 to main with:

  • exact storage/transaction model;
  • migrations;
  • executed adapter/contract tests;
  • explicit Cloudflare verification status;
  • final Quality run;
  • failure/restart limitations;
  • no temporary workflow files.

Do not merge it yourself unless acting as integration owner.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions