aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/design/2026-05-28-generic-agent-runtime-spec.org60
-rw-r--r--todo.org3
2 files changed, 61 insertions, 2 deletions
diff --git a/docs/design/2026-05-28-generic-agent-runtime-spec.org b/docs/design/2026-05-28-generic-agent-runtime-spec.org
index 5e547e0..bd9d60b 100644
--- a/docs/design/2026-05-28-generic-agent-runtime-spec.org
+++ b/docs/design/2026-05-28-generic-agent-runtime-spec.org
@@ -422,6 +422,56 @@ silently (both read, both write, last write wins). The contract, by tier:
cross-agent form already specced above (=machine.project.agent-id=), or
just gets reported to Craig.
+*** Data-integrity rules — 2026-06-11 second pass
+
+The scoped-edit discipline covers helper-vs-primary edits on /different/
+headings. Four loss/corruption windows remain, each with a rule. They matter
+doubly in the consolidated home project, where a single =todo.org= carries
+every personal task and corruption has maximal blast radius.
+
+1. /Primary file-wide passes vs a live helper./ =todo-cleanup.el=,
+ =lint-org.el=, and =wrap-org-table.el= rewrite whole files; run while a
+ helper is mid-edit, they clobber the helper's just-written change (last
+ write wins, silently). Rule: before any file-wide pass, the primary checks
+ =session-context.d/= for live helper files. If any exist, it pauses the
+ pass and asks Craig (or skips hygiene for that wrap). A crashed helper's
+ stale file would block hygiene forever, so staleness is surfaced as a
+ judgment call — the file's own content and timestamps show whether the
+ helper is really gone — never silently skipped past and never silently
+ honored indefinitely.
+2. /A new primary starting while a helper runs./ The previous primary may
+ wrap and exit while a helper keeps working; the next =ai= launch becomes
+ primary and runs full startup. The existing guards already do the right
+ thing — the helper's uncommitted edits make the tree dirty, and Phase A.0
+ skips pulls on a dirty tree. Rule: startup additionally surfaces live
+ =session-context.d/= files as active agents (already in the
+ session-context contract above), so the new primary knows /why/ the tree
+ is dirty instead of treating it as leftover mess to resolve.
+3. /Write-ahead edit journal./ The helper logs each intended shared-file
+ edit — file, heading, one-line intent — to its own session-context file
+ /before/ applying it. The Session Log discipline already requires logging
+ state-mutating turns; this tightens it to log-before-write for shared
+ files specifically. After a crash, the journal shows which edits landed,
+ and nothing about the shared file has to be reconstructed from memory.
+4. /The memory dir./ =MEMORY.md= is a shared read-modify-write index with no
+ heading anchors — the same lost-update shape as =todo.org= with none of
+ the scoped-edit protection. Rule: helpers don't write memory at all.
+ Candidate memories go into the helper's session log; the primary (or its
+ wrap-up promotion check) writes them.
+
+Backstop, independent of all four: every file-wide pass snapshots its target
+to =/tmp= before modifying. =lint-org.el= and =wrap-org-table.el= already do;
+=todo-cleanup.el= — the pass that moves whole subtrees — does not, and gets
+brought up to the invariant in Phase 1.5. Beyond that, the primary's normal
+commit cadence keeps git the recovery layer: a corrupted =todo.org= is one
+checkout away from its last committed state, which is exactly why all git
+mutation stays primary-only and frequent.
+
+One small collision nit: =inbox-send= filenames carry minute-resolution
+timestamps (=YYYY-MM-DD-HHMM-from-<project>-<slug>=). A helper and primary
+sending to the same target in the same minute with the same slug would
+collide; helper-originated sends include the agent id in the slug.
+
*** Helper startup and wrap-up
Helper startup is deliberately light: resolve the context path, read
@@ -504,9 +554,17 @@ Independent of the phases 2-6 go/no-go; same-runtime only.
- Bats tests: id assignment and sanitization through the launcher, helper vs
primary path resolution, two simultaneous context files (extends the
existing =session-context-path= suite).
+- Data-integrity items (the second-pass rules): the live-helper gate before
+ any file-wide hygiene pass (with stale-file surfacing); =todo-cleanup.el=
+ brought up to the backup-to-=/tmp= invariant the other two passes already
+ meet; log-before-write journaling for helper shared-file edits in
+ protocols.org; memory writes primary-only (helpers log candidates); agent
+ id in helper-originated =inbox-send= slugs.
- Manual validation: Craig runs a real helper session against a live primary
— a task lookup, one scoped =todo.org= edit, wrap-up — and the primary's
- next commit picks up the helper's edit cleanly.
+ next commit picks up the helper's edit cleanly. Then the corruption drill:
+ with the helper mid-task, the primary attempts a wrap-up and the hygiene
+ gate visibly pauses on the live helper.
** Phase 2: Introduce runtime manifests and generic install commands
diff --git a/todo.org b/todo.org
index bb1c2cb..caabb7e 100644
--- a/todo.org
+++ b/todo.org
@@ -50,7 +50,8 @@ Implement Phase 1.5 of the generic-agent-runtime spec ([[file:docs/design/2026-0
- =ai --helper= flag: live-anchor detection, auto AI_AGENT_ID + AI_HELPER export, tmux window naming, warn-and-run-normal when no primary is live.
- Shared-file read/write contract into protocols.org (helper: scoped single-heading org edits only; file-wide passes, inbox processing, and all git mutation stay primary-only); helper branches in startup.org (light path, no pulls/rsync) and wrap-it-up.org (archive own file, skip hygiene + commit).
- Bats: launcher id assignment/sanitization, helper-vs-primary resolution, two simultaneous context files.
-- Manual validation with Craig: live helper against a live primary — lookup, one scoped todo.org edit, wrap-up, primary commits the helper's edit cleanly.
+- Data-integrity items (spec second pass, 2026-06-11): live-helper gate before any file-wide hygiene pass (todo-cleanup/lint-org/wrap-org-table check session-context.d/, pause + ask on live files, surface stale ones); todo-cleanup.el brought up to the backup-to-/tmp invariant (lint-org and wrap-org-table already conform — verified); log-before-write journaling for helper shared-file edits; memory writes primary-only (MEMORY.md has no heading anchors — helpers log candidates instead); agent id in helper-originated inbox-send slugs (minute-resolution filenames can collide).
+- Manual validation with Craig: live helper against a live primary — lookup, one scoped todo.org edit, wrap-up, primary commits the helper's edit cleanly. Then the corruption drill: primary attempts wrap-up while the helper is mid-task and the hygiene gate visibly pauses.
Independent of the spec's phases 2-6 (runtime-neutral refactor), which stay gated on their own go/no-go.