diff options
| -rw-r--r-- | .ai/workflows/inbox.org | 4 | ||||
| -rw-r--r-- | .ai/workflows/triage-intake.org | 8 | ||||
| -rw-r--r-- | claude-templates/.ai/workflows/inbox.org | 4 | ||||
| -rw-r--r-- | claude-templates/.ai/workflows/triage-intake.org | 8 | ||||
| -rw-r--r-- | docs/specs/2026-07-20-silent-until-signal-monitors-spec.org | 3 | ||||
| -rw-r--r-- | todo.org | 14 |
6 files changed, 28 insertions, 13 deletions
diff --git a/.ai/workflows/inbox.org b/.ai/workflows/inbox.org index 123e6df..fc8091b 100644 --- a/.ai/workflows/inbox.org +++ b/.ai/workflows/inbox.org @@ -482,14 +482,14 @@ 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), read-only — no =git pull=. The capture-guard still gates any write: use =capture-guard --wait= (core §5) so a transient capture clears itself; if it's still open after the wait, *defer this cycle's roam reconcile to the next cycle* rather than surfacing — the loop cadence is the retry, and the filed items get swept next time. 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. +2. *Nothing found* → no inbox summary. One heartbeat line: =inbox zero at HH:MM: nothing= (HH:MM local, from =date=) — the silent-until-signal policy, see =docs/specs/2026-07-20-silent-until-signal-monitors-spec.org=. Nothing else. Keeping a quiet inbox quiet is the whole point. 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* → chain into =work-the-backlog.org= as an explicit second step after routing completes: pass it the eligibility query over the queued items (status =TODO= + =:solo:= per the scheme header, priority-ordered), =file-only= mode, paging off, cap 1. The highest-priority eligible candidate runs; the rest wait for the next tick or a later yes. - *No* → they stay queued for a later go. This mode never implements anything itself — routing ends here, and the execution loop lives in =work-the-backlog.org=, its one home. 4. *Cross-cycle dedup.* Subsequent cycles add only *newly-found* items to the same displayed queue, never re-surfacing what's already there. Dedup against the queue (the =TaskCreate= list), not against what's already been implemented — a find that was queued-but-not-yet-run must not reappear, and one already filed into =todo.org= is dropped by roam Phase C's status check. -A find is always surfaced and filed; execution happens only through the =work-the-backlog.org= chain and waits for Craig's yes. A quiet inbox produces only the timestamped acknowledgement. =auto inbox zero= is inherently in-session because its chain step waits for that yes. +A find is always surfaced and filed; execution happens only through the =work-the-backlog.org= chain and waits for Craig's yes. A quiet inbox produces only the =inbox zero at HH:MM: nothing= heartbeat. =auto inbox zero= is inherently in-session because its chain step waits for that yes. ** Fully-unattended pass (=/schedule=) — vNext, not v1 diff --git a/.ai/workflows/triage-intake.org b/.ai/workflows/triage-intake.org index d476ac3..4f7c7b8 100644 --- a/.ai/workflows/triage-intake.org +++ b/.ai/workflows/triage-intake.org @@ -220,11 +220,13 @@ Each sweep runs Phase 0 (load *both* plugin dirs — the loud requirement still - DOES update an active daily-prep in Update mode and re-open it on change (per =daily-prep.org=). - DOES report, deltas-only, with loud scan-failure banners (Phase C rules unchanged). -** End-of-sweep output — three sections +** End-of-sweep output — three sections, or one heartbeat -1. *Deltas* — what changed since the *previous sweep* (the standard Phase C summary scoped to the inter-sweep delta; one line if nothing: "HH:MM sweep: no changes"). +*Silent-until-signal (see =docs/specs/2026-07-20-silent-until-signal-monitors-spec.org=).* An *empty sweep* — no deltas since the previous sweep and no change to the awaiting-acknowledgment list — collapses to a single heartbeat line and nothing else: =triage intake at HH:MM: nothing= (HH:MM local, from =date=). Detection still runs in full (Phase 0 plus the A-D scan, against the session's inherited MCP auth); only the output collapses, so a long unattended run stops filling the session with identical "no changes" blocks. A sweep with real deltas or an unacked-list change prints the full three sections below. + +1. *Deltas* — what changed since the *previous sweep* (the standard Phase C summary scoped to the inter-sweep delta). 2. *Responses awaiting your acknowledgment* — every Slack reply, email, or message directed at Craig that he hasn't acknowledged or had the agent answer. A *running list carried forward across sweeps* until Craig acks each item or closes the triage. An away user's first need is "who's waiting to hear back from me," which a delta-only sweep loses the moment it scrolls past. -3. *Timestamp* — the current date, time, and timezone on the sweep's own final line, so an away reader sees how fresh the summary is without computing it. Print it on *every* sweep, including a quiet "no changes" one — on a quiet sweep the stamp is the proof the loop ran. Generate it with: +3. *Timestamp* — the current date, time, and timezone on the sweep's own final line, so an away reader sees how fresh the summary is without computing it. Print it on every sweep that prints these three sections. On an *empty* sweep there is no separate timestamp line — the heartbeat (=triage intake at HH:MM: nothing=) is itself the freshness stamp and the proof the loop ran. Generate it with: #+begin_src bash date "+%A %Y-%m-%d %H:%M:%S %Z (%z)" diff --git a/claude-templates/.ai/workflows/inbox.org b/claude-templates/.ai/workflows/inbox.org index 123e6df..fc8091b 100644 --- a/claude-templates/.ai/workflows/inbox.org +++ b/claude-templates/.ai/workflows/inbox.org @@ -482,14 +482,14 @@ 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), read-only — no =git pull=. The capture-guard still gates any write: use =capture-guard --wait= (core §5) so a transient capture clears itself; if it's still open after the wait, *defer this cycle's roam reconcile to the next cycle* rather than surfacing — the loop cadence is the retry, and the filed items get swept next time. 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. +2. *Nothing found* → no inbox summary. One heartbeat line: =inbox zero at HH:MM: nothing= (HH:MM local, from =date=) — the silent-until-signal policy, see =docs/specs/2026-07-20-silent-until-signal-monitors-spec.org=. Nothing else. Keeping a quiet inbox quiet is the whole point. 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* → chain into =work-the-backlog.org= as an explicit second step after routing completes: pass it the eligibility query over the queued items (status =TODO= + =:solo:= per the scheme header, priority-ordered), =file-only= mode, paging off, cap 1. The highest-priority eligible candidate runs; the rest wait for the next tick or a later yes. - *No* → they stay queued for a later go. This mode never implements anything itself — routing ends here, and the execution loop lives in =work-the-backlog.org=, its one home. 4. *Cross-cycle dedup.* Subsequent cycles add only *newly-found* items to the same displayed queue, never re-surfacing what's already there. Dedup against the queue (the =TaskCreate= list), not against what's already been implemented — a find that was queued-but-not-yet-run must not reappear, and one already filed into =todo.org= is dropped by roam Phase C's status check. -A find is always surfaced and filed; execution happens only through the =work-the-backlog.org= chain and waits for Craig's yes. A quiet inbox produces only the timestamped acknowledgement. =auto inbox zero= is inherently in-session because its chain step waits for that yes. +A find is always surfaced and filed; execution happens only through the =work-the-backlog.org= chain and waits for Craig's yes. A quiet inbox produces only the =inbox zero at HH:MM: nothing= heartbeat. =auto inbox zero= is inherently in-session because its chain step waits for that yes. ** Fully-unattended pass (=/schedule=) — vNext, not v1 diff --git a/claude-templates/.ai/workflows/triage-intake.org b/claude-templates/.ai/workflows/triage-intake.org index d476ac3..4f7c7b8 100644 --- a/claude-templates/.ai/workflows/triage-intake.org +++ b/claude-templates/.ai/workflows/triage-intake.org @@ -220,11 +220,13 @@ Each sweep runs Phase 0 (load *both* plugin dirs — the loud requirement still - DOES update an active daily-prep in Update mode and re-open it on change (per =daily-prep.org=). - DOES report, deltas-only, with loud scan-failure banners (Phase C rules unchanged). -** End-of-sweep output — three sections +** End-of-sweep output — three sections, or one heartbeat -1. *Deltas* — what changed since the *previous sweep* (the standard Phase C summary scoped to the inter-sweep delta; one line if nothing: "HH:MM sweep: no changes"). +*Silent-until-signal (see =docs/specs/2026-07-20-silent-until-signal-monitors-spec.org=).* An *empty sweep* — no deltas since the previous sweep and no change to the awaiting-acknowledgment list — collapses to a single heartbeat line and nothing else: =triage intake at HH:MM: nothing= (HH:MM local, from =date=). Detection still runs in full (Phase 0 plus the A-D scan, against the session's inherited MCP auth); only the output collapses, so a long unattended run stops filling the session with identical "no changes" blocks. A sweep with real deltas or an unacked-list change prints the full three sections below. + +1. *Deltas* — what changed since the *previous sweep* (the standard Phase C summary scoped to the inter-sweep delta). 2. *Responses awaiting your acknowledgment* — every Slack reply, email, or message directed at Craig that he hasn't acknowledged or had the agent answer. A *running list carried forward across sweeps* until Craig acks each item or closes the triage. An away user's first need is "who's waiting to hear back from me," which a delta-only sweep loses the moment it scrolls past. -3. *Timestamp* — the current date, time, and timezone on the sweep's own final line, so an away reader sees how fresh the summary is without computing it. Print it on *every* sweep, including a quiet "no changes" one — on a quiet sweep the stamp is the proof the loop ran. Generate it with: +3. *Timestamp* — the current date, time, and timezone on the sweep's own final line, so an away reader sees how fresh the summary is without computing it. Print it on every sweep that prints these three sections. On an *empty* sweep there is no separate timestamp line — the heartbeat (=triage intake at HH:MM: nothing=) is itself the freshness stamp and the proof the loop ran. Generate it with: #+begin_src bash date "+%A %Y-%m-%d %H:%M:%S %Z (%z)" diff --git a/docs/specs/2026-07-20-silent-until-signal-monitors-spec.org b/docs/specs/2026-07-20-silent-until-signal-monitors-spec.org index 210c1e9..c15d10f 100644 --- a/docs/specs/2026-07-20-silent-until-signal-monitors-spec.org +++ b/docs/specs/2026-07-20-silent-until-signal-monitors-spec.org @@ -4,10 +4,11 @@ #+TODO: TODO | DONE #+TODO: DRAFT READY DOING | IMPLEMENTED SUPERSEDED CANCELLED -* DRAFT silent-until-signal monitor loops +* IMPLEMENTED silent-until-signal monitor loops :PROPERTIES: :ID: af592bd6-d3e6-47e2-8804-2a287b4d9303 :END: +- 2026-07-20 Mon @ 13:34:53 -0500 — READY (Craig approved after his read) → building Phases 2-5 immediately → IMPLEMENTED. Phase 2 (auto triage-intake heartbeat), Phase 3 (auto inbox-zero heartbeat), Phase 4 (shared-policy home: the spec is the single definition, each workflow states its own heartbeat and references it), Phase 5 (manual-testing checklist). All phases shipped. - 2026-07-20 Mon @ 12:30:00 -0500 — Phase 1 (sentry quiet-fire heartbeat) implemented ahead of the full READY gate, at Craig's direction — a quiet sentry fire now collapses to =sentry at HH:MM: nothing=, and the "no silent skip" discipline is reconciled (the heartbeat is the explicit "nothing" record). Phases 2-5 (triage, inbox, shared-policy home, verification) still pending Craig's deep read. Spec stays DRAFT. - 2026-07-20 Mon @ 12:14:20 -0500 — drafted during the morning session. Design decisions resolved live with Craig off the .emacs.d proposal and the sentry live-trial evidence. DRAFT pending his deep read. @@ -65,6 +65,15 @@ What we're verifying: the morning teardown reviews and merges cleanly, nothing r - Squash-merge what's wanted, delete the branch, revert any stale Emacs buffers. - Confirm main was never pushed to during the night and the approval queue was walked. Expected: the night's work is reviewable as one branch, merges by choice, and main stayed clean throughout. +*** Silent-until-signal — empty fire heartbeats, real item full turn +What we're verifying: an in-session monitor fire collapses to a one-line heartbeat when nothing changed, and still does the full turn on a real item. Covers sentry, auto triage-intake, and auto inbox-zero (spec: docs/specs/2026-07-20-silent-until-signal-monitors-spec.org). +- Run a sentry fire with nothing pending. Expected: one line, =sentry at HH:MM: nothing=, no per-pass digest block, tree clean. +- Run a sentry fire after planting an inbox handoff. Expected: the full per-pass digest block, the handoff processed or queued. +- Start "auto triage-intake" and let an empty sweep run. Expected: one line, =triage intake at HH:MM: nothing=, no three-section output. +- Plant a real change in a triage source, let the next sweep run. Expected: the full three-section output (deltas / unacked / timestamp). +- Start "auto inbox zero" with an empty roam inbox, let a cycle run. Expected: one line, =inbox zero at HH:MM: nothing=. +- Add a roam inbox item, let the next cycle run. Expected: the item summarized, filed, and queued. +Expected: every empty fire is a single labelled heartbeat; every fire with real work does its full turn unchanged. ** DONE [#B] working/ tracked-from-creation + gitignored temp/ :feature: CLOSED: [2026-07-20 Mon] @@ -183,8 +192,9 @@ From the sentry live trial (2026-07-20): triage-intake self-activates in every p Awaiting Craig's deep read of the spec (DRAFT → READY gate). Two decisions still open in the spec (declaration format details, whether interactive adopts the same gate). On READY, spec-response decomposes the 5 phases into build tasks. Supersedes Fire 1's triage-probe approval-queue item, which was the narrower probe-only framing. -** TODO [#B] Silent-until-signal for in-session monitor loops :feature:spec: -Spec: [[file:docs/specs/2026-07-20-silent-until-signal-monitors-spec.org][docs/specs/2026-07-20-silent-until-signal-monitors-spec.org]] (DRAFT, ID af592bd6-d3e6-47e2-8804-2a287b4d9303). Decisions resolved live with Craig 2026-07-20; awaiting his deep read for DRAFT → READY. +** DONE [#B] Silent-until-signal for in-session monitor loops :feature:spec: +CLOSED: [2026-07-20 Mon] +Spec: [[file:docs/specs/2026-07-20-silent-until-signal-monitors-spec.org][docs/specs/2026-07-20-silent-until-signal-monitors-spec.org]] (IMPLEMENTED, ID af592bd6-d3e6-47e2-8804-2a287b4d9303). Craig approved without changes 2026-07-20; all 5 phases shipped that day. Sentry, auto triage-intake, and auto inbox-zero all collapse an empty fire to =<workflow> at HH:MM: nothing=; a manual-testing entry covers the live-loop verification. Craig-approved proposal from .emacs.d (2026-07-20), demonstrated by the sentry live trial (fires 3-8 were walls of no-op lines). Reframed live from a watcher *mechanism* to a *policy*: an in-session monitor fire detects first, and on an empty check collapses to one labelled heartbeat line (=<workflow> at HH:MM: nothing=) instead of a full turn; only a real item earns the full surface-and-judge turn. Keeping detection in-session dissolves the MCP-auth split (triage's Gmail/Slack/Linear need session auth), so it applies uniformly to sentry, auto triage-intake, and auto inbox-zero. No external watcher, no new seen-list. Five build phases in the spec. Phase 1 (sentry quiet-fire heartbeat) shipped 2026-07-20 ahead of the full READY gate at Craig's direction — a quiet fire now collapses to =sentry at HH:MM: nothing=. Phases 2-4 (auto triage-intake, auto inbox-zero, shared-policy home) + Phase 5 verification pending Craig's spec read. Overlaps the sentry cluster ([[file:todo.org::*Sentry vNext passes][Sentry vNext passes]], [[file:todo.org::*Triage source activation][Triage source activation]]). |
