aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorCraig Jennings <c@cjennings.net>2026-06-10 18:01:27 -0500
committerCraig Jennings <c@cjennings.net>2026-06-10 18:01:27 -0500
commita059be8650080864505b3d9274c6b3555419b9b2 (patch)
treed078f5ebab6cec12f230fcc95cf37bcbce9b46dd /docs
parent4e6fd2d760469b09d7f235f19d722aaa03bce6db (diff)
downloadrulesets-a059be8650080864505b3d9274c6b3555419b9b2.tar.gz
rulesets-a059be8650080864505b3d9274c6b3555419b9b2.zip
docs(spec): move agent KB to git and fold in migration, metrics, upkeep
The KB leaves the ~/sync/org Syncthing share for its own git repo on cjennings.net (new decision D8). A systemd timer auto-syncs Craig's edits, agents pull before query and commit+push after write, machines replicate by clone (the work machine doesn't), and agent writes land under an agents/ subdirectory. Syncthing's no-history, no-gate, conflict-fork costs were the design's weakest accepted risks, and the phone constraint dissolved: mobile stays on on-demand doc drops to the ~/sync/phone share. The amendment also folds in inclusion criteria plus a guided per-project memory sweep (Phase 1.5), a Success metrics section with a 30-day checkpoint, the seed node redefined as the KB's own documentation, and monthly hygiene automation (Phase 4). Phases renumbered 0-4. Implementation stays held pending the go-ahead.
Diffstat (limited to 'docs')
-rw-r--r--docs/agent-knowledge-base-spec.org123
1 files changed, 94 insertions, 29 deletions
diff --git a/docs/agent-knowledge-base-spec.org b/docs/agent-knowledge-base-spec.org
index bdf7852..cf69c35 100644
--- a/docs/agent-knowledge-base-spec.org
+++ b/docs/agent-knowledge-base-spec.org
@@ -3,7 +3,7 @@
#+DATE: 2026-06-10
* Metadata
-| Status | ready — Codex review incorporated, D7 ratified keep, work-root denylist confirmed =~/projects/work= only (Craig, 2026-06-10); implementation awaiting Craig's go |
+| Status | ready — Codex review incorporated; D7 keep, denylist =~/projects/work= only, D8 transport = git all ratified (Craig, 2026-06-10); implementation awaiting Craig's go |
| Owner | Craig Jennings |
| Reviewer | Craig Jennings; Codex (2026-06-10) |
| Related | [[file:../todo.org][todo.org — "Check that memories are sync'd across machines via git"]] |
@@ -12,7 +12,7 @@ This spec supersedes the 2026-06-05 draft (formerly docs/design/2026-06-05-org-r
* Summary
-Agents adopt Craig's existing org-roam knowledge base (=~/sync/org/roam/=, ~490 org files, Syncthing-synced since 2023) as the shared, cross-project store for durable knowledge. Per-project harness memory stays as a fast capture layer; durable facts get promoted into the KB, which already syncs across machines. This replaces two abandoned designs (a dedicated git repo, a two-tier rules split) with a substrate that already exists.
+Agents adopt Craig's existing org-roam knowledge base (~490 org files, curated since 2023) as the shared, cross-project store for durable knowledge. The KB moves from Syncthing to git (D8): it relocates out of the =~/sync/org= share into its own repo with a cjennings.net remote, synced the way every other repo is. Per-project harness memory stays as a fast capture layer; durable facts get promoted into the KB. This replaces two abandoned designs (a dedicated memory repo, a two-tier rules split) with the substrate that already exists — now with git history and revertability on every write.
* Problem / Context
@@ -20,12 +20,12 @@ Per-project agent memory lives at =~/.claude/projects/<encoded-cwd>/memory/=, a
Two fixes were built or designed and dropped. A dedicated =claude-memory.git= repo was built then reversed because it pooled work-confidential and personal memory into one store. A two-tier split (general lessons to rules, project memory to each project's =.ai/=) left public-remote code projects' memory at-risk by design.
-The simplification: cross-machine sync is already solved for anything living in =~/sync/org/roam/=. The task stops being "build a memory-sync system" and becomes "point agents at the knowledge base that already syncs."
+The simplification: the knowledge base already exists and already syncs across machines. The task stops being "build a memory-sync system" and becomes "point agents at the existing KB." The 2026-06-10 transport revision (D8) moves that sync from Syncthing to git — history, revertability, and explicit per-machine replication, with the KB syncing like every other repo instead of through a second mechanism.
* Goals and Non-Goals
** Goals
-- Durable, cross-machine agent knowledge with no new sync mechanism.
+- Durable, cross-machine agent knowledge synced the same way as every other repo (git, cjennings.net remote).
- Agents query the KB before relying on remembered project facts, prior decisions, or reference material.
- Agent-written notes are distinguishable from Craig's, and index cleanly in his org-roam.
- The work/personal confidentiality boundary is explicit and enforced on the write side.
@@ -36,9 +36,9 @@ The simplification: cross-machine sync is already solved for anything living in
- No autonomy expansion. Free agent writes apply to the KB only — email, Linear comments, PRs, and every other public or external channel still require Craig's review and consent (D6).
** Scope tiers
-- v1: the pointer rule, the write schema, the boundary, one verified seed node.
-- Out of scope: migrating historical harness memory wholesale into the KB; auto-promotion.
-- vNext: promotion tooling (a wrap-up prompt or =/promote= pass), KB hygiene reports (orphan =:agent:= nodes).
+- v1: the transport migration (Phase 0), the pointer rule, the write schema, the boundary, the guided memory sweep (Phase 1.5), one verified seed node, the promotion cadence with usage instrumentation, and the monthly hygiene pass (Phase 4).
+- Out of scope: wholesale import of historical harness memory (the sweep is guided and approved, not bulk); auto-promotion.
+- vNext: a =/promote= command if the wrap-up prompt proves insufficient; an =:agent:inbox:= staging tag if free writes prove too noisy.
* Design
@@ -50,9 +50,9 @@ Conflict-file exclusion is part of the command contract, not a prose reminder â€
#+begin_src sh
# content/tag search
-rg --glob '*.org' --glob '!*sync-conflict*' '<query>' ~/sync/org/roam/
+rg --glob '*.org' --glob '!*sync-conflict*' '<query>' <kb-path>/
# follow an [[id:UUID]] link to its node
-rg --glob '*.org' --glob '!*sync-conflict*' ':ID:[[:space:]]+<uuid>' ~/sync/org/roam/
+rg --glob '*.org' --glob '!*sync-conflict*' ':ID:[[:space:]]+<uuid>' <kb-path>/
#+end_src
For a *writer* (personal-project agents only, per D5): create one node per fact, following roam conventions so the next =org-roam-db-sync= indexes it:
@@ -67,7 +67,28 @@ For a *writer* (personal-project agents only, per D5): create one node per fact,
<the fact, with [[id:...]] links to related nodes>
#+end_example
-Filename follows roam's timestamp-prefix convention (=YYYYMMDDHHMMSS-slug.org=). The =:agent:= filetag makes =rg '#\+filetags:.*:agent:'= a clean inventory of everything agents wrote, so Craig can review or prune at will.
+Filename follows roam's timestamp-prefix convention (=YYYYMMDDHHMMSS-slug.org=), under the =agents/= subdirectory (see Transport and layout below). The =:agent:= filetag makes =rg '#\+filetags:.*:agent:'= a clean inventory of everything agents wrote, so Craig can review or prune at will.
+
+** Transport and layout (D8)
+
+The KB is a git repo with a cjennings.net remote, not a Syncthing subtree. It relocates out of the =~/sync/org= share (that share's =.stfolder= root sits at =~/sync/org=) to a standalone path — proposed =~/org/roam=, final path set at migration — and =roam-dir= in Craig's =org-roam-config.el= follows it.
+
+- Craig's edits sync via a systemd user timer (the git-sync pattern: =pull --rebase=, commit, push every 15-30 minutes), preserving his zero-touch flow.
+- Agents need no new plumbing: pull before query, commit + push after write — the same session discipline as every other repo. Agent commits are attributable in history.
+- Per-machine replication is opt-in by clone. The work machine simply doesn't clone, which retires D5's replication exposure.
+- The phone needs no roam leg: Craig's on-demand pattern (an agent drops a doc into the separate =~/sync/phone= share, Syncthing pushes it to the phone) replaces syncing all of roam to mobile.
+- Agent writes land under the =agents/= subdirectory. org-roam scans recursively, so it's one database and one search surface with id-links intact, while the agent corpus stays physically corralled — hideable later with one =org-roam-file-exclude-regexp= line, and a future split is a =mv=. The =:agent:= filetag stays on every node regardless; the subdirectory is bulk management, the tag is identity.
+- Once migrated, the Syncthing =*.sync-conflict-*= file class disappears (git merges or conflicts loudly; it never forks silent copies). The query commands keep their exclusion globs through the transition; they're harmless afterward.
+
+** Inclusion criteria — what goes in, what stays out
+
+=knowledge-base.md= carries these as rules, so every project applies the same bar.
+
+In: durable facts with cross-project or cross-machine value — decisions and their why, environment and tooling gotchas, reference pointers (URLs, dashboards, key paths), lessons that transfer beyond the project that learned them.
+
+Out: anything the repo already records (code structure, git history, CLAUDE.md content), session state, task state (todo.org owns that), high-churn facts that will be stale in a month, secrets and credentials, and anything work-confidential (the D5 boundary).
+
+Existing knowledge migrates through a one-time guided sweep per project (Phase 1.5), not a wholesale import: the project's agent reads its harness-memory dir, classifies each fact against the criteria above (KB-worthy / stays local / stale-delete), and proposes the batch for Craig's approval. The memory frontmatter helps: =reference=-type and durable =feedback=-type memories are natural candidates; most =project=-type entries stay local.
** Project classification and write routing (v1)
@@ -91,6 +112,7 @@ A new =claude-rules/knowledge-base.md= rule (auto-installs via the Makefile RULE
- Good, because git gives history, review, and a deliberate sync step.
- Bad, because it pooled work-confidential and personal memory into one all-machines store — the reason it was built and then reversed (2026-05-23/24).
- Bad, because it added a new clone + symlink mechanism every machine must maintain.
+- Neutral, because the pooling objection is solved by D5's write boundary, not by avoiding git — D8 (2026-06-10) adopts git as the transport for the existing KB, keeping this alternative's history and revert benefits without its new-store cost.
** Two-tier split (rules file + per-project =.ai/memory/=)
- Good, because general lessons would load natively into every session via the rules layer.
@@ -98,9 +120,9 @@ A new =claude-rules/knowledge-base.md= rule (auto-installs via the Makefile RULE
- Neutral, because the promote-general-lessons instinct survives in this design as KB promotion.
** Org-roam KB (chosen)
-- Good, because sync already works (Syncthing, since 2023) — zero new infrastructure.
+- Good, because the substrate already exists and already syncs — no new store to build.
- Good, because the KB is already Craig's curated knowledge home; agent knowledge lands where he actually looks.
-- Bad, because Syncthing has no review gate (accepted in D6) and no history — a bad write propagates immediately.
+- Bad as originally specced on Syncthing — no review gate, no history, silent conflict forks. D8 moves the transport to git, which restores history and revert and softens the D6 risk to "revertable after push."
- Neutral, because agents read it as plain files; no org-roam tooling required or used.
* Decisions
@@ -108,7 +130,7 @@ A new =claude-rules/knowledge-base.md= rule (auto-installs via the Makefile RULE
** D1 — The KB is a queried substrate, accessed as files
- State: accepted (Craig, 2026-06-10)
- Context: an agent is a harness process, not an Emacs session; it cannot call org-roam's Elisp API or read its SQLite cache.
-- Decision: We will treat =~/sync/org/roam/= as a directory of plain org files — ripgrep for search, grep-for-=:ID:= to follow links.
+- Decision: We will treat the KB directory (pre-migration =~/sync/org/roam/=; post-Phase-0 the D8 git checkout) as a directory of plain org files — ripgrep for search, grep-for-=:ID:= to follow links.
- Consequences: easier — works in every runtime, no Emacs dependency; harder — no backlink graph or db-backed queries for agents (acceptable: ~490 tagged, linked text files grep well).
** D2 — Capture in harness memory, promote into the KB
@@ -133,13 +155,13 @@ A new =claude-rules/knowledge-base.md= rule (auto-installs via the Makefile RULE
- State: accepted (Craig, 2026-06-10: "Your recommendation C is the right one.")
- Context: the KB is personal and replicates to every Syncthing machine — Craig confirmed that includes a work machine. The leak risk is asymmetric and lives on the write side: a work agent writing confidential facts would pool them into the personal store.
- Decision: We will let any project read the shared KB; only personal projects write to it. Work agents write to work's own project tree, never the shared KB. Craig confirmed C handles the work-machine replication acceptably.
-- Consequences: easier — reading value lands everywhere, confidential work data stays physically out of the KB; harder — work knowledge has no shared home (status quo, unchanged), and the inverse risk (personal facts surfacing in work artifacts) remains governed by the existing content-scope rules in =commits.md=.
+- Consequences: easier — reading value lands everywhere, confidential work data stays physically out of the KB; harder — work knowledge has no shared home (status quo, unchanged), and the inverse risk (personal facts surfacing in work artifacts) remains governed by the existing content-scope rules in =commits.md=. Under D8, machine replication is opt-in by clone, so the work machine holds no KB copy at all unless deliberately cloned.
** D6 — Agent writes land freely in the KB, and only there
- State: accepted (Craig, 2026-06-10)
- Context: Syncthing has no git-style review gate; the alternative was a staging tag (=:agent:inbox:=) Craig promotes from.
- Decision: We will let agent writes land freely in the KB without a review gate. This autonomy is scoped to the KB alone — it is not permission to send email, comment on Linear tickets, or post to any public or external channel; those still require Craig's review and consent.
-- Consequences: easier — no promotion queue to tend, knowledge lands immediately; harder — a bad write syncs everywhere before anyone reviews it (mitigated by the =:agent:= inventory and Craig's normal roam curation).
+- Consequences: easier — no promotion queue to tend, knowledge lands immediately; harder — a bad write lands without pre-review (mitigated by the =:agent:= inventory, Craig's normal roam curation, and — under D8 — git history making every write attributable and revertable).
** D7 — Harness memory stays as the capture layer
- State: accepted (Craig, 2026-06-10: "keep")
@@ -147,18 +169,33 @@ A new =claude-rules/knowledge-base.md= rule (auto-installs via the Makefile RULE
- Decision: We will keep harness memory as the ephemeral capture layer. D2 stands as written, and Phase 3's promotion cadence is required, not optional — it's what keeps the capture layer from silting up.
- Consequences: easier — automatic recall keeps working, no harness behavior changes; harder — two stores and a promotion discipline (mitigated by Phase 3's mechanical wrap-up trigger).
+** D8 — Transport: git on cjennings.net, not Syncthing
+- State: accepted (Craig, 2026-06-10: "shape a looks good")
+- Context: the KB lived inside the =~/sync/org= Syncthing share — no history, no review gate, silent =*.sync-conflict-*= forks (63 at count), and share-level replication that pushed roam to a work machine whether wanted or not. The phone constraint dissolved on inspection: Craig's mobile pattern is on-demand (an agent drops a doc into the =~/sync/phone= share), not whole-roam sync, and he prefers it that way. The earlier dedicated-memory-repo design was rejected for pooling work and personal facts, which D5 now solves independent of transport.
+- Decision: We will move the KB out of the Syncthing share into its own git repo (proposed =~/org/roam=, cjennings.net remote). Craig's edits auto-sync via a systemd user timer; agents pull before query and commit + push after write; machines replicate by cloning, and the work machine doesn't clone.
+- Consequences: easier — per-fact history and blame, revertable and attributable agent writes, the conflict-file class disappears, explicit per-machine replication, one sync model everywhere; harder — a one-time migration (conflict-file cleanup, the move, the Emacs =roam-dir= update, a link sweep for the old path, timer setup) and staleness windows between timer runs where Syncthing was near-instant (mitigated by pull-at-session-start on both Craig's and agents' sides). D4's one-node-per-fact files make merge collisions rare by construction.
+
* Implementation phases
Not started — Craig has explicitly held implementation pending his go-ahead.
+** Phase 0 — Transport migration (D8)
+Resolve or delete the 63 =*.sync-conflict-*= files, move the directory out of the =~/sync/org= share to the new path, =git init= + =.gitignore= + initial commit + push to the cjennings.net remote, clone on the other personal machines (not the work machine), and set up the auto-sync timer. Update =roam-dir= in =org-roam-config.el= (handoff to the =.emacs.d= project) and sweep references to the old path (the =protocols.org= task-list pointer at =~/sync/org/roam/inbox.org=, among others) per the keep-links-current rule; a transition symlink at the old location covers stragglers. Verify: Syncthing no longer tracks the tree, org-roam indexes the new location, and an edit round-trips between two machines via the timer.
+
** Phase 1 — Pointer rule
-The work-root denylist is confirmed (=~/projects/work= only, Craig 2026-06-10). Write =claude-rules/knowledge-base.md=: path, the canonical query commands (conflict-file exclusion included), the D4 schema, the classification + write-routing rules, the refusal contract, and the D5/D6 boundary. =make install= links it machine-wide via the existing RULES glob — no Makefile change. Tree stays working throughout (pure addition).
+The work-root denylist is confirmed (=~/projects/work= only, Craig 2026-06-10). Write =claude-rules/knowledge-base.md=: the KB path (post-migration), the canonical query commands, the D4 schema with the =agents/= subdirectory, the pull-before-query / commit-and-push-after-write discipline, the inclusion criteria, the classification + write-routing rules, the refusal contract, and the D5/D6 boundary. =make install= links it machine-wide via the existing RULES glob — no Makefile change. Tree stays working throughout (pure addition).
+
+** Phase 1.5 — Guided memory migration (one-time, per project)
+A small =migrate-memories= pass each project runs once: read the project's harness-memory dir, classify each fact against the inclusion criteria (KB-worthy / stays local / stale-delete), propose the batch, and write approved facts as =agents/= nodes. Craig approves per project; no wholesale import.
** Phase 2 — Seed node + index verification
-Craig supplies or approves the durable fact; the implementer writes exactly one node under =~/sync/org/roam/= per the schema (a genuine durable fact, not a test stub). Craig runs =org-roam-db-sync= and confirms it indexes and displays cleanly. Rollback if the schema fails: delete that one timestamped =:agent:= file. This validates the schema end-to-end before agents write at volume.
+The seed node is the KB's own user-facing documentation: a "How the agent knowledge base works" node — what agents write, the =:agent:= tag, the inventory command, what Craig can prune. A genuine durable fact, it doubles as Craig's doc and validates the schema end-to-end: Craig confirms it indexes and displays (=org-roam-db-autosync-mode= is on, so no manual sync step). Rollback if the schema fails: delete or revert that one node.
+
+** Phase 3 — Promotion cadence + usage instrumentation
+Wire the promotion prompt into the wrap-up workflow (a "anything worth promoting to the KB?" check), and have wrap-up record one line in the session summary: "KB: promoted N / consulted yes-no." That single line makes usage measurable by grepping session archives — the input to the Success metrics checkpoint. Note the cadence in =knowledge-base.md=. Resolves D2's discipline risk with a mechanical trigger.
-** Phase 3 — Promotion cadence
-Wire the promotion prompt into the wrap-up workflow (a "anything worth promoting to the KB?" check), and note the cadence in =knowledge-base.md=. Resolves D2's discipline risk with a mechanical trigger.
+** Phase 4 — Maintenance automation
+A monthly agent-run hygiene pass: the =:agent:= inventory, orphan and duplicate detection, node-count trend — report dropped in the rulesets inbox, deletions proposed for approval (auto-cleanup allowed only for =:agent:=-tagged nodes). Extends the filed hygiene-reports task; under D8 there is no conflict-file purge left to schedule. Craig's recurring duty collapses to approving one short report a month.
* Acceptance criteria
@@ -169,27 +206,43 @@ Wire the promotion prompt into the wrap-up workflow (a "anything worth promoting
- [ ] A work-project agent, asked to store a durable fact, writes it to work's own tree, not the KB.
- [ ] An unknown-classification project, asked to store a durable fact, refuses the KB write and reports the redacted fact per the refusal contract rather than guessing.
- [ ] The documented query commands find a known note and exclude =*.sync-conflict-*= files.
+- [ ] The KB is a git repo with a cjennings.net remote; Syncthing no longer tracks it; the auto-sync timer round-trips Craig's edits between machines.
+- [ ] Agent writes land under =agents/= as attributable commits.
+- [ ] =knowledge-base.md= states the inclusion criteria and the pull / commit-push discipline.
+- [ ] The 30-day Success-metrics checkpoint is scheduled with its thresholds recorded.
+
+* Success metrics
+
+The acceptance criteria prove the mechanism; these prove the design. Measured from Phase 3's wrap-up instrumentation line and the =:agent:= inventory:
+
+- Usage: node count grows steadily, and promotions appear in wrap-up lines (most multi-session weeks promote at least one fact).
+- Recall wins: a KB query answers something that would otherwise be re-derived or re-asked. The decisive form is cross-project — a fact written in project A used in project B. Target: at least one cross-project win inside 30 days.
+- Boundary integrity: zero work-classified content in the KB, ever. Auditable via the inventory and the git log.
+- Hygiene: orphan and duplicate rate among =:agent:= nodes stays low enough that the monthly report is boring.
+
+30-day checkpoint: review the four together. Writes-but-no-recall-wins means agents aren't querying — strengthen the query trigger in =knowledge-base.md= rather than writing more. No writes at all means the promotion prompt isn't firing or the inclusion bar is set wrong. Either failure revises the rule, not the substrate.
* Readiness dimensions
- Data model & ownership: KB nodes are user-curated (Craig) or agent-authored (=:agent:= tag); agents never edit Craig's hand-authored nodes, only link to them. Harness memory stays agent-owned and ephemeral.
-- Errors, empty states & failure: a missing =~/sync/org/roam/= (machine without Syncthing) means the rule's query step finds nothing — agents proceed without the KB and say so rather than fabricate recall. No write occurs to a nonexistent path.
+- Errors, empty states & failure: a missing KB checkout (machine without the clone) means the rule's query step finds nothing — agents proceed without the KB and say so rather than fabricate recall. No write occurs to a nonexistent path.
- Security & privacy: D5/D6 are the whole story — work never writes; KB writes never extend to public channels. No credentials live in the KB.
-- Observability: =rg '#\+filetags:.*:agent:'= inventories all agent writes; roam's UI shows them tagged in Craig's normal browsing.
+- Observability: =rg '#\+filetags:.*:agent:'= inventories all agent writes; roam's UI shows them tagged in Craig's normal browsing; under D8 the git log is the per-write audit trail.
- Performance & scale: 484 files today; ripgrep over a few thousand org files is milliseconds. N/A as a concern.
- Reuse & lost opportunities: maximal — the entire design is reusing an existing synced, curated store instead of building one.
-- Architecture fit & weak points: mirrors the patterns.md pointer-rule shape; the existing Makefile RULES glob installs the new rule with no Makefile change. Weak point is Syncthing conflict files (=*.sync-conflict-*=, 63 today) — excluded by the canonical query commands, not left to prose.
+- Architecture fit & weak points: mirrors the patterns.md pointer-rule shape; the existing Makefile RULES glob installs the new rule with no Makefile change. The legacy weak point (Syncthing conflict files, 63 today) is retired by D8 at migration; the query commands keep their exclusion globs through the transition.
- Config surface: one path constant in =knowledge-base.md=. No knobs.
- Documentation plan: =knowledge-base.md= is the documentation; the spec records the why.
- Dev tooling: N/A because the interface is ripgrep and Write — no build, no tests beyond Phase 2's manual index check.
-- Rollout, compatibility & rollback: pure addition; rollback is deleting the rule file and (optionally) the =:agent:=-tagged nodes, which the tag makes a one-command sweep.
-- External APIs & deps: none — plain files. Verified: =~/sync/org/roam/= exists with ~490 org files plus 63 conflict files, Syncthing-synced (2026-06-05 ground-truth check; recount in the 2026-06-10 Codex review).
+- Rollout, compatibility & rollback: pure addition past Phase 0; rollback is deleting the rule file and (optionally) the =:agent:=-tagged nodes — a one-command sweep by tag, or a revert by commit under D8. Phase 0 itself is reversible until the Syncthing copy is retired.
+- External APIs & deps: git + the cjennings.net remote, the same dependency every other repo carries; otherwise plain files. Verified 2026-06-05/10: ~490 org files plus 63 conflict files at the pre-migration location inside the =~/sync/org= share; =org-roam-db-autosync-mode= is on in Craig's config.
* Risks, Rabbit Holes, and Drawbacks
-- Un-reviewed writes propagate instantly (D6 accepted this). Dodge: the =:agent:= inventory keeps cleanup cheap.
-- Promotion discipline may not stick (D2). Dodge: Phase 3 makes it a mechanical wrap-up step rather than a memory burden.
-- Syncthing conflict files could confuse queries. Dodge: exclusion is baked into the canonical commands.
+- Un-reviewed writes land without a gate (D6 accepted this). Dodge: under D8 every write is an attributable, revertable commit, and the =:agent:= inventory keeps cleanup cheap.
+- Promotion discipline may not stick (D2). Dodge: Phase 3 makes it a mechanical wrap-up step rather than a memory burden, and its instrumentation line makes a lapse visible at the 30-day checkpoint.
+- Staleness between machines in the gap between auto-sync timer runs (Syncthing was near-instant). Dodge: pull at session start on both Craig's and agents' sides; D4's per-fact files make collisions rare when concurrent edits do happen.
+- The Phase 0 move breaks references to the old path (the Emacs =roam-dir=, the =protocols.org= task-list pointer). Dodge: the migration includes a link sweep plus a transition symlink at the old location.
- An incomplete work-root denylist would let a work project classify as personal. Dodge: Craig confirmed the denylist (=~/projects/work= only, 2026-06-10), and the classification's safe default (unknown → refuse) covers anything outside the known parents.
* Testing / Verification
@@ -198,12 +251,14 @@ From the 2026-06-10 review, the verification surface for v1:
- =make install= links =knowledge-base.md= into =~/.claude/rules/=.
- In a personal repo, the documented =rg= command finds a known note.
-- In a work repo, a durable-storage request produces no write under =~/sync/org/roam/= and the refusal report names the fact.
+- In a work repo, a durable-storage request produces no write in the KB and the refusal report names the fact.
- In an unknown project, the agent refuses or asks rather than guessing.
- One approved seed node indexes via =org-roam-db-sync= and appears in the =rg '#\+filetags:.*:agent:'= inventory.
- A =*.sync-conflict-*= file containing a unique token is excluded by the documented query.
-The first, second, and last checks are agent-runnable; the org-roam display check and the work/unknown behavioral checks are Craig's manual validation (tracked in todo.org).
+- After Phase 0: an edit made on one machine appears on another within the timer interval, no new =*.sync-conflict-*= files appear, and the work machine has no clone.
+
+The first, second, and last checks are agent-runnable; the org-roam display check, the work/unknown behavioral checks, and the cross-machine round-trip are Craig's manual validation (tracked in todo.org).
* Review dispositions
@@ -239,3 +294,13 @@ Modified recommendations from the 2026-06-10 Codex review, with reasons. Everyth
- What: confirmed the work-root denylist is complete at =~/projects/work= alone; archangel is not work-scoped.
- Why: this was the single "ready with caveats" caveat. The spec is now ready. Implementation still awaits Craig's explicit go.
- Artifacts: this file (status flipped to ready); the denylist VERIFY in todo.org resolved to a dated entry.
+
+** 2026-06-10 Wed @ 17:57:08 -0500 — Craig Jennings + Claude — amendment: D8 git transport + five design folds
+- What: Craig's five design questions answered and ratified. New D8: the KB moves out of the =~/sync/org= Syncthing share into its own git repo on cjennings.net (Shape A — whole roam), with an =agents/= subdirectory for agent writes, a systemd auto-sync timer for Craig's edits, opt-in-by-clone replication (work machine doesn't clone), and the phone staying on the on-demand =~/sync/phone= pattern. Folded in: inclusion criteria + a Phase 1.5 guided memory migration, a Success metrics section with a 30-day checkpoint, the seed node redefined as the KB's own user-facing documentation, and Phase 4 maintenance automation. Phases renumbered 0-4.
+- Why: the original verification proved mechanism but not success; migration and maintenance were unspecified; and Syncthing's no-history / no-gate / conflict-fork costs were the design's weakest accepted risks — git removes them for the price of a one-time migration. The phone constraint that might have blocked Shape A dissolved: Craig's mobile pattern is on-demand doc drops, not whole-roam sync.
+- Artifacts: this file; todo.org phase tasks updated (Phase 0, 1.5, and 4 added). Implementation remains held pending Craig's go.
+
+** 2026-06-10 Wed @ 17:31:10 -0500 — Codex — reviewer
+- What changed or was recommended: re-ran the spec-review workflow after the caveat resolution. Rubric: ready. No new blocking or medium-priority findings; no review file written. Confirmed the implementation phases and test-surface tasks are already represented under the existing parent task in todo.org.
+- Why: the prior blockers are dispositioned, the work-root denylist is confirmed, the pointer-rule install path matches the current Makefile RULES glob, and v1's manual/agent-runnable verification surface is explicit.
+- Artifacts: this file; [[file:../todo.org][todo.org]] parent task "Check that memories are sync'd across machines via git".