aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-11 19:53:38 -0500
committerCraig Jennings <c@cjennings.net>2026-06-11 19:53:38 -0500
commitb405fff94d6ddcdd5b2278f20c327c583aad487d (patch)
treefb0b27241322773e8c5aa4f65e1040f06362651a /docs
parentf4b856b9eacc5a7ce8af3a031d72e7b7d6840305 (diff)
downloadrulesets-b405fff94d6ddcdd5b2278f20c327c583aad487d.tar.gz
rulesets-b405fff94d6ddcdd5b2278f20c327c583aad487d.zip
docs(spec): data-integrity rules for helper instances
Four loss windows the scoped-edit discipline doesn't cover: a primary file-wide hygiene pass silently clobbering a helper's concurrent edit (gate on live session-context.d/ files before any such pass), a new primary misreading helper dirt as leftover mess (surface live helper files at startup), crash recovery for shared-file edits (helpers journal each edit before applying it), and MEMORY.md's anchor-less read-modify-write index (memory writes stay primary-only). Backstop: every file-wide pass snapshots to /tmp before modifying. lint-org and wrap-org-table already conform; todo-cleanup — the pass that moves whole subtrees — does not, and Phase 1.5 brings it up to the invariant.
Diffstat (limited to 'docs')
-rw-r--r--docs/design/2026-05-28-generic-agent-runtime-spec.org60
1 files changed, 59 insertions, 1 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