aboutsummaryrefslogtreecommitdiff
path: root/claude-templates
diff options
context:
space:
mode:
Diffstat (limited to 'claude-templates')
-rw-r--r--claude-templates/.ai/workflows/inbox.org27
-rw-r--r--claude-templates/.ai/workflows/wrap-it-up.org2
2 files changed, 18 insertions, 11 deletions
diff --git a/claude-templates/.ai/workflows/inbox.org b/claude-templates/.ai/workflows/inbox.org
index 26bf008..67f0dde 100644
--- a/claude-templates/.ai/workflows/inbox.org
+++ b/claude-templates/.ai/workflows/inbox.org
@@ -137,10 +137,10 @@ Cross-project boundary: never act on a file under another project's =.ai/= scope
* Core §5 — Capture-guard before a roam write
-Before *any* read-modify-write of =~/org/roam/inbox.org=, run =.ai/scripts/capture-guard "$HOME/org/roam/inbox.org"=. This runs first because a =git pull= on the roam repo *also* rewrites the file on disk, and a fast-forward landing underneath a live capture wedges it just as a hand edit would.
+Before *any* read-modify-write of =~/org/roam/inbox.org=, run =.ai/scripts/capture-guard "$HOME/org/roam/inbox.org"=. This runs first because the Phase D edit rewrites the file on disk, and editing underneath a live capture wedges it just as a stray hand edit would.
- *Exit 0* → no live capture (or no reachable Emacs). Proceed.
-- *Exit 1* → an indirect org-capture buffer is cloned from the roam inbox (the script prints the offending buffer name). Editing or fast-forwarding the file underneath it would leave the capture pointing at stale state and unable to finalize with =C-c C-c= (see =emacs.md=). Behavior depends on the caller:
+- *Exit 1* → an indirect org-capture buffer is cloned from the roam inbox (the script prints the offending buffer name). Editing the file underneath it would leave the capture pointing at stale state and unable to finalize with =C-c C-c= (see =emacs.md=). Behavior depends on the caller:
- *On-demand / interactive run* → stop and surface: "You have a live org-capture session open against the roam inbox (=<buffer>=) — finalize it (=C-c C-c=) or abort it (=C-c C-k=) and I'll continue." Re-run the guard and resume once it returns clean.
- *Wrap-up sub-step* → don't block the wrap. Skip the roam reconcile for this run and surface one line: "Skipped roam-inbox reconcile — a live org-capture is open against it; claimed items stay and get caught next run." The items were already filed into =todo.org= in roam mode Phase C, so the next roam run's Phase C status-check drops the duplicates and its Phase D removes them — the skip self-heals.
@@ -395,12 +395,19 @@ Apply the core disposition discipline against the project's =todo.org=; don't re
** Phase D — Reconcile the shared roam inbox
-The roam inbox lives in a git repo (=~/org/roam=, auto-synced by the =roam-sync= timer). Edit it carefully:
+The roam inbox lives in a git repo (=~/org/roam=, auto-synced every 15 minutes by the =roam-sync= timer). Craig captures into it constantly, so its working tree is dirty most of the time — which is exactly why this mode never runs =git pull= itself. A pull on a dirty tree fails, and that would block triage on nearly every run. Instead, edit the file and hand the git work to =roam-sync=, which already commits-first-then-rebases and so handles the dirty tree correctly.
-1. *Guard against a live org-capture session* — run the capture-guard (core §5) before any read-modify-write. The guard runs first because the pull in step 2 also rewrites the file on disk. On exit 1 the caller-specific behavior (interactive stop-and-surface vs wrap-up skip-and-self-heal) is in core §5.
-2. *Pull first* (=git -C ~/org/roam pull --ff-only=). If it can't fast-forward (dirty tree, divergence), surface and stop. Don't auto-stash, auto-merge, or force. Resolve before removing items.
-3. *Remove the claimed items and the empty entries.* Never touch foreign or unowned (titled) items. Empty entries (Phase B's =empty= bucket) are removed on every triage regardless of who would own a titled version, since an aborted capture belongs to nobody. The claimed-item removal and the empty sweep happen in the same edit.
-4. *Commit the roam repo as its own commit* (separate from any project wrap commit). Subject by what changed: =chore(inbox): route <project> tasks to <project>/todo.org= when items were claimed, =chore(inbox): drop empty entries= when the run only swept empties, or both clauses when it did both. Push, or leave for the =roam-sync= timer. Surface a blocked push; don't force.
+1. *Guard against a live org-capture session* — run the capture-guard (core §5) before the edit. On exit 1 the caller-specific behavior (interactive stop-and-surface vs wrap-up skip-and-self-heal) is in core §5.
+2. *Remove the claimed items and the empty entries* from the working-tree file. Never touch foreign or unowned (titled) items. Empty entries (Phase B's =empty= bucket) are removed on every triage regardless of who would own a titled version, since an aborted capture belongs to nobody. The claimed-item removal and the empty sweep happen in the same edit.
+3. *Hand the commit + push to =roam-sync=.* Don't =git pull=, =git commit=, or =git push= here. Trigger the sync so the edit lands promptly rather than waiting up to 15 minutes for the next timer tick:
+
+ #+begin_src bash
+ systemctl --user start roam-sync.service
+ #+end_src
+
+ =roam-sync= commits the edit (under its generic auto-sync message), rebases onto the remote, and pushes. The removal is safe to land without a pull-first because only this project ever touches =<project>:=-prefixed lines (the ownership partition), so =roam-sync='s rebase can't conflict on the edit. Provenance for the routed tasks lives in the project's =todo.org= and session log, not the roam commit message. If =systemctl= isn't available, leave the edit for the next timer tick — it still lands.
+
+ Don't pull or stash the roam tree to "clean" it first: that fights =roam-sync= for ownership of the repo's git state. The edit-then-sync handoff is the whole point.
** Phase E — Surface
@@ -414,7 +421,7 @@ If triaging this batch surfaced a durable, cross-project fact (a reference point
- Project-local =inbox/= exists but has no pending handoffs → continue to roam scan.
- No =~/org/roam/inbox.org= after the local inbox check → report the local inbox disposition and stop.
- No claimed, no related-unowned, and no empty roam entries → report the total, stop.
-- Roam pull blocked → surface, stop before editing.
+- Live org-capture against the roam inbox (capture-guard exit 1) → surface (interactive) or skip-and-self-heal (wrap-up), per core §5.
** Caller integration
@@ -429,7 +436,7 @@ v1 handles the single-destination case via the prefix rule. The multi-project pa
1. *Domain-aware empty-it-all mode.* If rulesets held a description of each project's domain, one run could guess the owner of every item (prefixed or not) and empty the whole inbox at once, delivering each item to its owning project's =inbox/= via =inbox-send= (where that project's process-mode gate still decides whether to file it). Open: where the domain map lives, how confident a guess must be before auto-routing vs surfacing, and whether a low-confidence item stays put.
2. *Explicit per-project =:INBOX_PREFIX:= as the durable resolver*, replacing basename inference.
3. *Unowned-item lifecycle* once domain-aware routing exists (no item stays unrouted indefinitely).
-4. *Concurrent push contention* on the shared roam repo: the pull-before-edit + ff-only + surface-on-conflict floor may want a retry-once-after-pull.
+4. *Concurrent push contention* on the shared roam repo: triage now hands its commit + push to =roam-sync=, which already aborts-and-surfaces on a rebase conflict. If multi-machine contention ever makes that abort frequent, =roam-sync= may want a retry-once-after-rebase.
Take these up when the single-destination version is in use and the multi-project pain is concrete.
@@ -439,7 +446,7 @@ A recurring, *interactive* roam check. Trigger phrase: "auto inbox zero" (match
** Per cycle
-1. Run roam mode's scan (Phase A local check + Phase B roam scan). The capture-guard and pull-before-edit discipline (core §5, roam Phase D) still gate any write.
+1. Run roam mode's scan (Phase A local check + Phase B roam scan), read-only — no =git pull=. The capture-guard (core §5) still gates any write, and the rare write hands its git to =roam-sync= (roam Phase D).
2. *Nothing found* → no inbox summary. One acknowledgement line: =ran at HH:MM, nothing found=. Nothing else. The acknowledge-only-on-empty rule keeps a quiet inbox quiet.
3. *Items found* → summarize the found items, file them as tasks (roam Phase C), and *append them to a displayed queue* — the harness task list, via =TaskCreate= — so the queue accumulates across cycles. Then ask: "run this batch next?"
- *Yes* → launch into implementing the found items, each through the normal disposition ladder (core §3) + verify flow.
diff --git a/claude-templates/.ai/workflows/wrap-it-up.org b/claude-templates/.ai/workflows/wrap-it-up.org
index 6e89f5f..4b7910f 100644
--- a/claude-templates/.ai/workflows/wrap-it-up.org
+++ b/claude-templates/.ai/workflows/wrap-it-up.org
@@ -114,7 +114,7 @@ Before the cleanup scripts, sweep the roam global inbox (=~/org/roam/inbox.org=)
[ -f "$HOME/org/roam/inbox.org" ] && grep -cE '^\*\* ' "$HOME/org/roam/inbox.org" || true
#+end_src
-Skip-fast when nothing matches: if the roam clone isn't on this machine, or no item is prefixed for this project, this is a silent no-op. When claimed items exist, run roam mode's Phase B–C (file each into =todo.org=, then remove them from the shared inbox in a separate roam commit). Report the total count and how many appeared related to this project, per roam mode's scan-summary rule.
+Skip-fast when nothing matches: if the roam clone isn't on this machine, or no item is prefixed for this project, this is a silent no-op. When claimed items exist, run roam mode's Phase B–D (file each into =todo.org=, then remove them from the shared inbox and let =roam-sync= commit + push the edit). Report the total count and how many appeared related to this project, per roam mode's scan-summary rule.
*** Hygiene pass