Block Memory Session Convergence — Requirements
Status: v1 draft, pre-red-team · 2026-07-20
Epic: block-memory-session-convergence (Phase 1.1)
Parent contract: Autri Block Memory Phase 1, locked in autri/.kiro/specs/block-memory/. This document is a visible amendment contract; it does not silently rewrite the locked Phase-1 requirements, design, tasks, or immutable block history.
North-star fit: B3 (knowledge layer inside existing AI tools), B4 (one secure substrate), and B7 (dependable session continuity).
Problem and outcome
Phase 1 converges work at session start: every new session_start consumes project frontier heads, including open work, and stale open owners can become reconciled. A reconciled session cannot later append or end. That topology conflicts with resumable sessions.
Phase 1.1 moves convergence to the terminal boundary. A session starts from the last integrated project state without advancing it; open work remains isolated and resumable; a successful end atomically integrates the session branch with the latest integrated state. Explicit abandonment is distinct from dormancy and end.
Grounded current state
- Implementation baseline: origin/feat/block-memory-history-backfill at 4333f8c, a descendant of origin/main at a5e8d18.
- Persisted session statuses are active, ended, and reconciled. There is no project integration pointer.
- Start and end serialize against project mutations; append serializes the session head. Live authorization is rechecked after lock waits.
- Start currently parents from every selected project leaf and may reconcile stale active owners. End currently writes a one-parent session_end and does not converge project work.
- The explorer is principal-fenced and payload-lazy, but its generic HEAD label conflates session heads, counts are derived from visible nodes, and active paths pulse indefinitely.
- History import has produced 138 ended sessions and 690 immutable blocks in the autri-platform project. Each episode is a five-block chain. Import and rollback have append-only audit journals.
- Claude Code has native SessionStart and SessionEnd events. Codex and Kiro expose start-like identity but no true session-end event; their Stop events are turn-scoped.
- Dev Memory confirms that the A → parallel B/C → D test was deliberately added to prove convergence. Phase 1.1 must replace its next-start merge expectation with terminal-driven convergence.
Global constraints
- C-1 — Critical-path precedence. Core lifecycle, migration, and recovery contracts land before harness adapters or explorer presentation changes depend on them.
- C-2 — Compound, do not duplicate. Extend the existing authorization, idempotency, project serialization, capture spool, admin, and kill-switch mechanisms. Do not create a parallel lifecycle or recovery plane.
- C-3 — Immutable history. Existing blocks, parent edges, payloads, summaries, provenance, and chronology are never rewritten to manufacture the new topology.
- C-4 — Principal and tenant fence. Phase 1.1 must not create cross-principal ancestry, bootstrap disclosure, or explorer disclosure. Multi-user shared memory remains behind the D-7/D-8 revisit tripwire.
- C-5 — Vended-account compatibility. The contract must work identically in shared and dedicated Autri deployments without global singleton state or account-specific identifiers.
- C-6 — Flagship inert. Schema may deploy ahead of behavior, but old and new lifecycle writers may not run concurrently against a partially migrated project. The existing memory-tools kill switch remains the mutation fence.
- C-7 — Check ownership. Every acceptance criterion names an AI-mechanized check (🤖) or a human judgment/prod witness (🧑). Mechanized checks close before human UAT.
- C-8 — Existing security ordering. Live credential authorization and canonical ownership checks precede replay visibility and state diagnostics, including after a caller waits for project serialization.
Requirements
S-1 — Open, dormant, ended, and abandoned lifecycle
Priority: must
User story: As a developer working across long or interrupted AI sessions, I want inactivity to be non-terminal so that I can safely resume unfinished work.
Acceptance criteria
- WHEN a session is created and has not ended or been explicitly abandoned, THE SYSTEM SHALL treat it as open and eligible for authorized append, resume, and end operations. 🤖
- WHEN an open session crosses the configured inactivity threshold, THE SYSTEM SHALL present it as dormant while preserving its open, resumable semantics. Dormancy SHALL be derived from activity time, not persisted as an implicit terminal transition. 🤖
- WHEN a different session starts, THE SYSTEM SHALL NOT end, reconcile, abandon, or otherwise terminalize any open or dormant session. 🤖
- WHEN an imported historical session or already-ended live session is read, THE SYSTEM SHALL keep it terminal and SHALL NOT reclassify it as active merely because it was recently inserted or backfilled. 🤖
- WHEN a legacy reconciled row is encountered, THE SYSTEM SHALL preserve it as a read-only legacy terminal state unless a separately audited migration explicitly maps it; Phase 1.1 runtime SHALL NOT create new reconciled sessions. 🤖
S-2 — Stable identity and resume semantics
Priority: must
User story: As a harness adapter, I want one stable project-scoped memory session per native session identity so that resumes and compactions continue the correct branch.
Acceptance criteria
- WHEN the same canonical principal, project, and harness-prefixed native session reference starts or lazily appends while its memory session is open, THE SYSTEM SHALL return and continue that exact session without creating a new branch. 🤖
- WHEN resume, clear, compact, or turn-scoped stop events occur within the same native session, THE SYSTEM SHALL NOT mint or terminate a memory session solely because of that event. 🤖
- WHEN a native reference points only to terminal sessions, THE SYSTEM SHALL create a successor only through an explicit start or lazy-start path and SHALL make the successor relationship observable. 🤖
- WHEN an adapter resolves a repo or linked worktree, THE SYSTEM SHALL attach only through the canonical main-worktree root that exactly matches an enrolled capture root; unknown, symlink-confused, or crafted roots SHALL fail closed without writes. 🤖
S-3 — Explicit abandonment
Priority: must
User story: As an operator, I want a deliberate way to abandon work that will never complete so that stale branches are honest without being silently merged or left open forever.
Acceptance criteria
- WHEN an authorized caller explicitly abandons an open session, THE SYSTEM SHALL record immutable terminal evidence including the actor, time, and optional reason; mark the session abandoned; and reject fresh append/end mutations afterward. 🤖
- WHEN a session is abandoned, THE SYSTEM SHALL preserve its branch and SHALL NOT advance the project integration state or imply that its work was accepted. 🤖
- WHEN abandonment races with append or end, THE SYSTEM SHALL serialize the outcomes so exactly one fresh terminal/mutation path wins and the loser receives a typed, principal-visible result. 🤖
- WHEN no explicit abandonment command occurs, THE SYSTEM SHALL never infer abandonment from age, inactivity, process death, or another session starting. 🤖
I-1 — Canonical integration state
Priority: must
User story: As a developer starting new work, I want one canonical integrated state for my project so that every new branch begins from accepted history rather than unrelated in-progress work.
Acceptance criteria
- WHEN a nonempty enrolled project is available for session work, THE SYSTEM SHALL identify exactly one canonical integration head that belongs to the same project and is authorized for the same canonical principal. 🤖
- WHEN an empty project accepts its first concurrent-capable session work, THE SYSTEM SHALL establish exactly one stable project baseline from which initial sessions can branch; it SHALL NOT adopt one session’s mutable work as another session’s base merely because that session started first. 🤖
- WHEN the integration state is absent, cross-project, cross-principal, deleted, or ambiguous, THE SYSTEM SHALL fail closed before creating or advancing session work and SHALL emit an operator-visible diagnostic. 🤖
- WHEN integration state changes, THE SYSTEM SHALL preserve a monotonic ancestry path: the new head descends from the prior integration head and from the branch being integrated. 🤖
I-2 — Start branches without convergence
Priority: must
User story: As a developer beginning parallel work, I want my session to branch from integrated history without touching anyone’s unfinished branch so that sessions remain independently resumable.
Acceptance criteria
- WHEN a new session starts in a nonempty project, THE SYSTEM SHALL parent its initial branch only from the canonical integration baseline defined by I-1 and SHALL NOT select parents from the project’s raw DAG leaves. 🤖
- WHEN a new session starts, THE SYSTEM SHALL NOT advance the canonical integration head. 🤖
- WHEN other open, dormant, ended-but-not-yet-observed, abandoned, or legacy-reconciled branches exist, THE SYSTEM SHALL leave their session states and current heads unchanged. 🤖
- WHEN start is retried for an already-open native scope, THE SYSTEM SHALL return the existing branch and SHALL NOT recompute convergence or the project baseline. 🤖
I-3 — Terminal-driven convergence
Priority: must
User story: As a developer completing a session, I want end to merge my branch with the latest integrated work so that parallel sessions converge without losing either contribution.
Acceptance criteria
- WHEN an open session ends successfully, THE SYSTEM SHALL atomically create terminal integration evidence descended from both the session branch tip and the canonical integration head observed under serialization, advance the canonical integration head to that evidence, and mark the session ended. 🤖
- WHEN the session branch already descends from the current integration head, THE SYSTEM SHALL preserve the same ancestry invariant without inventing duplicate work or dropping the session branch. 🤖
- WHEN two sessions end concurrently from the same starting baseline, THE SYSTEM SHALL serialize their commits so the final integration head descends from both branches; ordering SHALL follow committed serialization rather than caller timestamps. 🤖
- WHEN any write, parent validation, embedding-debt enqueue, accounting, idempotency, or integration-head update fails, THE SYSTEM SHALL roll back the entire end operation and leave the session open at its prior head. 🤖
- WHEN end succeeds, no later session start SHALL be required to make the completed branch part of canonical integrated history. 🤖
I-4 — Bootstrap and branch isolation
Priority: must
User story: As an AI assistant, I want bootstrap context to contain accepted history and my own resumable work, but not other unfinished sessions, so that I do not act on unintegrated changes.
Acceptance criteria
- WHEN a new session starts, THE SYSTEM SHALL build bootstrap from canonical integrated history and SHALL exclude blocks belonging only to other open, dormant, or abandoned branches. 🤖
- WHEN an existing open or dormant session resumes, THE SYSTEM SHALL include its own unintegrated branch context plus the integration baseline from which it branched, without silently rebasing or merging it. 🤖
- WHEN integrated history exceeds the bootstrap token budget, THE SYSTEM SHALL preserve the existing bounded, deterministic omission behavior and SHALL identify omitted context honestly. 🤖
- WHEN Phase-2 merge-LLM analysis is absent, THE SYSTEM SHALL still produce deterministic Phase-1.1 bootstrap and SHALL NOT describe deferred analysis as “no conflict.” 🤖
I-5 — Authorization, replay, and terminal ordering
Priority: must
User story: As a security-conscious operator, I want lifecycle retries to remain safe without leaking state so that convergence does not weaken Phase-1 authorization guarantees.
Acceptance criteria
- WHEN a lifecycle caller waits for project serialization, THE SYSTEM SHALL reauthorize the presented credential and canonical principal after the wait and before reading replay or session diagnostics. 🤖
- WHEN an end or abandon request repeats the same retained idempotency key and payload digest, THE SYSTEM SHALL replay the original result even though the session is now terminal. 🤖
- WHEN the same key is reused with a different digest, THE SYSTEM SHALL return a typed idempotency conflict without topology changes. 🤖
- WHEN a fresh key targets a terminal session, THE SYSTEM SHALL return the appropriate terminal result only to the owning principal; unauthorized callers receive the existing absent-shaped response. 🤖
- WHEN an idempotency record has expired, THE SYSTEM SHALL preserve the documented TTL-bounded semantics and SHALL NOT claim permanent exactly-once behavior. 🤖
M-1 — Additive migration and immutable-history preservation
Priority: must
User story: As the owner of the existing Dev Memory corpus, I want Phase 1.1 to add convergence metadata without rewriting history so that the 138-session record remains auditable.
Acceptance criteria
- WHEN the Phase-1.1 migration runs on the known autri-platform history project, THE SYSTEM SHALL initialize canonical integration state from the unique eligible terminal history head while preserving all 690 block IDs, block fields, payload hashes, created/occurred timestamps, parent edges, and import journals byte-for-byte or value-for-value. 🤖
- WHEN a project is empty, THE SYSTEM SHALL initialize it into the valid empty/baseline state defined by I-1 without creating contradictory genesis records. 🤖
- WHEN a project has open sessions, multiple ambiguous candidate integration heads, cross-principal ancestry, or an invalid topology, THE SYSTEM SHALL fail closed and produce a non-secret diagnostic; the production rollout SHALL require zero open sessions unless a separately tested deterministic classification is approved. 🤖
- WHEN legacy ended, abandoned, or reconciled metadata is migrated, THE SYSTEM SHALL change only the fields explicitly named by the migration contract and SHALL record before/after counts for operator review. 🤖
- WHEN migration verification compares the pre/post snapshots, any block or edge mutation SHALL fail the gate before lifecycle tools are enabled. 🤖
M-2 — History import, rollback, purge, and destruction compatibility
Priority: must
User story: As an operator, I want history administration to understand integration state so that import recovery and deletion remain safe after Phase 1.1.
Acceptance criteria
- WHEN a multi-invocation history import is incomplete, THE SYSTEM SHALL keep the project unavailable to live session writers and SHALL NOT expose a partial import tail as canonical integrated state. 🤖
- WHEN a history import completes, THE SYSTEM SHALL initialize or advance canonical integration state to the imported terminal tail only if the existing empty/history-only, zero-open-session, single-frontier contract still holds. 🤖
- WHEN history rollback is requested, THE SYSTEM SHALL refuse it if any non-import block or canonical integration descendant depends on the imported run; otherwise it SHALL update/clear integration metadata consistently while preserving immutable rollback journals. 🤖
- WHEN a project is purged or destroyed, THE SYSTEM SHALL remove or invalidate its integration metadata in the same serialized administrative operation and SHALL preserve the existing audit/destruction evidence contract. 🤖
- WHEN app and in-VPC admin copies of history logic are built, THE SYSTEM SHALL have a deterministic parity check that prevents integration-aware behavior from drifting across repositories. 🤖
A-1 — Claude Code adapter continuity
Priority: must
User story: As a Claude Code user, I want native session hooks to preserve capture and convergence automatically so that the established working path remains reliable.
Acceptance criteria
- WHEN Claude SessionStart fires for startup, resume, clear, or compact, THE ADAPTER SHALL preserve the existing source-aware behavior, stable claude-code native reference, canonical-root attachment, and drain-before-start ordering. 🤖
- WHEN Claude SessionEnd fires, THE ADAPTER SHALL durably spool the transcript reference and return within its hook deadline without performing unbounded semantic or network work in the native hook. 🤖
- WHEN the capture runner completes a project partition, THE ADAPTER SHALL append authored facts idempotently and invoke the terminal integration path with a stable per-session end key. 🤖
- WHEN one project partition succeeds and another fails, THE ADAPTER SHALL preserve completed siblings and retry only unfinished partitions without regenerating an immutable manifest. 🤖
A-2 — Codex and Kiro explicit finalization
Priority: must
User story: As a Codex or Kiro user, I want session continuity despite the lack of a true native end hook so that turn boundaries never corrupt lifecycle state.
Acceptance criteria
- WHEN Codex or Kiro emits a turn-scoped Stop event, THE ADAPTER SHALL NOT end or abandon the Block Memory session. 🤖
- WHEN /hl:stop is explicitly invoked in Codex or Kiro, THE METHODOLOGY ADAPTER SHALL act as the authoritative semantic-capture/finalization command for every authorized open project session belonging to that native reference, using stable per-session keys. 🤖
- WHEN /hl:stop is omitted, interrupted, or fails, THE SYSTEM SHALL remain correct: the session stays open/dormant, durable pending capture is preserved, and the next start/finalization path can recover without duplicate authored facts. 🤖
- WHEN Codex or Kiro resumes the same stable native reference, THE ADAPTER SHALL continue the same open session across turns; unstable or missing transcript paths SHALL be treated as versioned adapter inputs, not trusted lifecycle identity. 🤖
- WHEN Kiro session-layout or AgentSpawn behavior changes across supported versions, THE ADAPTER SHALL fail visibly or use a proven versioned fixture; it SHALL NOT guess an end boundary. 🤖
A-3 — Deadline and spool recovery
Priority: must
User story: As a developer starting a new session after a failed capture, I want recovery to finish safely without blocking forever so that continuity is durable and startup remains usable.
Acceptance criteria
- WHEN prior capture work exists, THE ADAPTER SHALL attempt bounded drain before building new bootstrap, preserving visible capture_pending, retry, and dead-letter states. 🤖
- WHEN capture authoring or append exceeds its deadline, THE SYSTEM SHALL keep the source session open/dormant and SHALL NOT advance integration or mark it ended. 🤖
- WHEN the next start drains a pending source successfully, THE SYSTEM SHALL complete its terminal integration before exposing the new session’s bootstrap, or SHALL report a bounded pending state without claiming the source is integrated. 🤖
- WHEN a process dies between manifest persistence, append, and end, THE SYSTEM SHALL recover from immutable manifest/progress state and idempotency records without regenerating facts or duplicating blocks. 🤖
U-1 — Truthful explorer lifecycle semantics
Priority: must
User story: As a user inspecting the memory DAG, I want integrated, open, dormant, ended, and abandoned work labeled honestly so that the visualization matches the lifecycle contract.
Acceptance criteria
- WHEN the explorer renders a project, THE SYSTEM SHALL visually distinguish the canonical integration head from per-session current heads; the generic HEAD label/control SHALL NOT conflate them. 🤖
- WHEN an open session is recent, THE SYSTEM MAY pulse its unintegrated branch; WHEN it becomes dormant, THE SYSTEM SHALL stop the pulse without changing terminal state. Recency SHALL use semantic/event activity time, not history-import insertion time. 🤖
- WHEN the explorer shows counts for open, recent, dormant, ended, or abandoned sessions, THE SYSTEM SHALL derive them from authoritative project/session data rather than only the currently visible block window. 🤖
- WHEN a branch is abandoned or legacy-reconciled, THE SYSTEM SHALL label it as non-integrated terminal history and SHALL NOT present it as accepted canonical work. 🤖
- WHEN Dan exercises project switching, integration-head navigation, resume/dormancy, and abandonment in the deployed explorer, the labels and controls SHALL be understandable without reading the implementation spec. 🧑
U-2 — Bounded-window truthfulness and scale seam
Priority: should
User story: As a user inspecting a large memory project, I want important heads and missing ancestry represented honestly so that a block cap never invents a false graph.
Acceptance criteria
- WHEN the ordinary bounded graph window omits older blocks, THE SYSTEM SHALL still include or explicitly represent the canonical integration head and every authorized open/dormant session tip. 🤖
- WHEN an edge or ancestor is outside the loaded window, THE SYSTEM SHALL show an off-window/truncated ancestry indicator rather than treating the child as a true root. 🤖
- WHEN the graph limit is configured, THE SYSTEM SHALL expose one authoritative value in code, documentation, and truncation UI; Phase 1.1 SHALL resolve the current 600-versus-1,000 disagreement. 🤖
- WHEN future viewport/cursor loading is added, THE Phase-1.1 data contract SHALL provide stable ordering/cursor and anchor seams; implementing the full large-DAG loader is not required by this epic. 🤖
U-3 — Read isolation and lazy payload preservation
Priority: must
User story: As a memory owner, I want convergence metadata to remain summary-safe and principal-fenced so that the new graph state does not leak payloads or another principal’s work.
Acceptance criteria
- WHEN graph summaries, counts, heads, or edges are read, THE SYSTEM SHALL enforce the existing canonical-principal fence and SHALL NOT expose another principal’s branch through project-global integration metadata. 🤖
- WHEN the initial graph payload is loaded, THE SYSTEM SHALL continue excluding full block payloads. 🤖
- WHEN a block is selected, THE SYSTEM SHALL lazy-load the full payload through the existing audited, no-store, ownership-checked drill-down path and fall back honestly on failure. 🤖
O-1 — Observability, rollout, and rollback safety
Priority: must
User story: As an operator, I want a reversible rollout with topology evidence so that Phase 1.1 cannot silently corrupt or partially activate production memory.
Acceptance criteria
- WHEN Phase 1.1 is rolled out, THE OPERATOR SHALL disable lifecycle tools, capture a topology/integrity baseline, apply the additive migration locally through the existing in-VPC path, deploy compatible writers/readers, run mechanized preflight, and only then re-enable tools. 🤖
- WHEN rollout or runtime detects missing/ambiguous integration state, cross-principal ancestry, failed convergence, open-session migration, or admin parity drift, THE SYSTEM SHALL emit a bounded non-secret metric/log and at least one actionable alarm or preflight failure. 🤖
- WHEN rollback is required after the schema exists, THE OPERATOR SHALL disable lifecycle tools before deploying any previous writer. A previous Phase-1 writer SHALL NOT be treated as behaviorally compatible merely because the newer schema is additive. 🤖
- WHEN the production flag is re-enabled, THE SYSTEM SHALL verify the expected lifecycle tool surface, zero topology-integrity errors, and successful terminal convergence before normal use resumes. 🤖
- WHEN the production ceremony reaches flag-on, Dan SHALL witness one resume, one parallel convergence, and one pending-capture recovery flow in the real environment. 🧑
- WHEN deployments or migrations run, they SHALL run from the local operator path; GitHub Actions remains CI-only. 🧑
V-1 — Deterministic lifecycle and race verification
Priority: must
User story: As an engineer shipping concurrency-sensitive memory behavior, I want deterministic race tests so that a green suite proves the topology rather than only individual functions.
Acceptance criteria
- WHEN the mechanized suite runs, it SHALL cover: concurrent first starts on an empty project; start/start on a nonempty project; append/end; end/end from the same baseline; resume after dormancy; abandon versus append; abandon versus end; same-key terminal replay; cross-principal denial; and imported-tail bootstrap. 🤖
- WHEN two parallel branches B and C end in either order, the suite SHALL prove that the final integration head descends from both, each session terminates exactly once, and no later D start is required for convergence. 🤖
- WHEN a new D session starts after B/C convergence, the suite SHALL prove D branches from the integrated head, receives both completed sentinels, and excludes any still-open E branch. 🤖
- WHEN a migration fixture containing imported history runs, the suite SHALL prove before/after block and edge identity, hash, chronology, journal, and ancestry equality. 🤖
- WHEN more open branches exist than an ordinary graph window contains, the suite SHALL prove authoritative counts and required head anchors remain truthful. 🤖
V-2 — Full-stack and deployed acceptance
Priority: must
User story: As the product owner, I want the actual hooks, spool, MCP server, database, explorer, and production lock path exercised together so that Phase 1.1 is proven at its seams.
Acceptance criteria
- WHEN the reusable local full-stack E2E runs, it SHALL use real hook/adapter mechanics, the real MCP lifecycle surface, and real PostgreSQL/pgvector to prove normal finalization, delayed recovery, parallel terminal convergence, resume, abandonment, no duplicates, and no cross-project/principal edges. 🤖
- WHEN Codex/Kiro fixtures run, multiple turn-scoped Stops SHALL leave the session open, while explicit /hl:stop SHALL finalize every authorized project partition for the native reference. 🤖
- WHEN the deployed preflight runs, it SHALL verify schema/integration metadata, IAM/VPC/RDS/TLS reachability, tool flag state, canonical principal ownership, and current production topology before mutations are enabled. 🤖
- WHEN production UAT completes, Dan SHALL approve the explorer’s integration/session-head semantics and confirm that resumed dormant work remains endable. 🧑
Out of scope for Phase 1.1
- Phase-2 merge-LLM conflict analysis or memory_poll_events.
- Multi-user shared memory, external memory exposure, or relaxing the D-7/D-8 tripwire.
- A restricted runtime database role; this remains a platform-register initiative.
- Full viewport/cursor loading for arbitrarily large DAGs; only the truthful bounded-window contract and compatibility seam are included.
- Rewriting the 690 imported blocks, their edges, or historical chronology.
- Replacing next.md or decisions.md with Block Memory.
- New content-detection, client-specific capture, or credential subsystems.
- Implementation during this spec session.
External clocks
No third-party approval or lead-time clock blocks specification. Production rollout still requires a Dan-witnessed local deployment ceremony and should be scheduled as an explicit change window.
Open questions for human refinement
| ID | Question | Draft recommendation |
|---|---|---|
| Q-1 | Is canonical integration state physically per project or per project-plus-principal? | Preserve the BM-4 “project integration head” product model, but fail closed unless all ancestry belongs to the same canonical principal; shared multi-principal memory remains out of scope. |
| Q-2 | How is the empty-project baseline represented? | Require one stable project baseline/root before concurrent work; choose the concrete block/schema representation in design. |
| Q-3 | What inactivity threshold drives “recent” versus “dormant”? | Make it configurable and presentation-only; do not reuse import insertion time or make correctness depend on the value. |
| Q-4 | What is the explicit abandon surface? | One authenticated, idempotent lifecycle operation with optional reason; no integration-head advancement. |
| Q-5 | Does Phase 1.1 ship full cursor loading? | No. Ship truthful head anchors, off-window indicators, and a stable cursor seam; defer the full viewport loader. |
Amendments
| Date | Requirement(s) | Change | Why | Approved by |
|---|---|---|---|---|
| — | — | No post-lock amendments yet. | — | — |