diff options
| -rw-r--r-- | .ai/workflows/triage-intake.org | 78 | ||||
| -rw-r--r-- | claude-templates/.ai/workflows/triage-intake.org | 78 | ||||
| -rw-r--r-- | docs/design/2026-06-15-auto-triage-intake-spec.org | 43 | ||||
| -rw-r--r-- | todo.org | 2 |
4 files changed, 201 insertions, 0 deletions
diff --git a/.ai/workflows/triage-intake.org b/.ai/workflows/triage-intake.org index b257f2d..7d1290f 100644 --- a/.ai/workflows/triage-intake.org +++ b/.ai/workflows/triage-intake.org @@ -168,6 +168,81 @@ If Craig has been silent for a while after Phase D and the surface looks closed- This rule prevents the failure mode where the workflow self-declares done and the next exchange has to relitigate what state things are in. +* Auto mode (unattended monitoring) + +Auto mode is a self-running variant of the engine for when Craig is away from the desk but wants tight awareness — a loop that runs the standard sweep on a short interval, *accumulates* findings rather than mutating state, and hands Craig a gated checkpoint to commit the batch. It composes two things: the *delivery* (a =/loop= in the live session) and the *behavior* (accumulate-don't-mutate sweeps with a checkpoint). The one-shot run above is unchanged; auto mode is an additional way to run the same Phase 0 / A-D engine. + +** Trigger and delivery + +- "auto triage" / "auto triage-intake" / "watch the desk" / "monitor the triage" — start auto mode. +- Default interval *20 minutes*; Craig sets it. + +Auto mode runs as a =/loop= in the *live session*, not a detached cron job: + +#+begin_src +/loop 20m run an auto-mode triage-intake sweep per triage-intake.org +#+end_src + +Running in the live session means MCP auth (Slack, Gmail, Linear) is inherited from the session — the headless-auth wall that blocks a detached cron run does not apply. A durable cross-session schedule is out of scope here; that belongs to the morning-ops orchestrator, which can later invoke auto mode's accumulate behavior as its triage limb. The close/stop commands below require a live session by design. + +** Preconditions and Close-out + +Auto mode borrows the inbox-monitor gates (=monitor-inbox.org=): do not start on a dirty worktree or a red test suite — a close's batch commit would otherwise sweep up unrelated changes — and leave the tree clean and green when the loop stops. Surface a blocker with inline numbered options per =interaction.md= and wait. + +** A sweep: accumulate, don't mutate + +Each sweep runs Phase 0 (load *both* plugin dirs — the loud requirement still holds) and Phases A-D's scan / classify / synthesize, but performs *none* of the normal run's mutations: + +- Does NOT advance the sentinel. The scan window grows from the last *close* until the next close: every sweep scans from the existing sentinel up to now, so nothing between sweeps is dropped. +- Does NOT write =todo.org= Action tasks — accumulates them for the close. +- Does NOT take mail actions (trash / mark-read / star). +- Does NOT commit. +- 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 — two sections + +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"). +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. + +** The unacked list — durable state + +The awaiting-acknowledgment list lives in =.ai/triage-intake-unacked.org=, so it survives a session crash, a =/clear=, or a restart — the away-from-desk case auto mode exists for. It's project-local state, tracked the same way as the sentinel (=.ai/last-triage-intake=), created on first need. + +Shape — one =** = heading per awaiting item: + +#+begin_example +#+TITLE: Triage Intake — Responses Awaiting Acknowledgment +# Maintained by triage-intake auto mode. One heading per item; acked items are removed. + +** Dana — 2pm reschedule invite +:PROPERTIES: +:SOURCE: personal-calendar +:LOCATOR: <event id or thread url — the dedupe key> +:SINCE: 2026-06-15 10:42 +:END: +She's waiting on a yes/no to the move. +#+end_example + +- *Add* — a sweep appends any new directed-at-Craig response not already listed, deduped on =LOCATOR=. +- *Carry forward* — every sweep re-renders the full list in its second section, whether or not it changed this sweep. +- *Ack* — "ack <item>" (e.g. "ack the Dana thread") removes that heading; "ack all" clears the list. +- *Close* — a close empties the list as part of processing (each item is either actioned or filed). + +** Close and stop — the checkpoint + +The mutations are gated behind two commands: + +- *"close the triage"* — run the full close: take the accumulated mail actions, add the accumulated Action items to =todo.org= as =:quick:reactive:= tasks (asking Craig the questions a normal Phase C/D would), empty the unacked list, then *advance the sentinel* — capture the close run's Phase A timestamp, do the mutations, write that timestamp to =.ai/last-triage-intake= exactly as a normal run does (per "Capture the Phase A timestamp") — and commit + push the batch. Then *keep looping* (next sweep on the normal interval). This is the "flush the batch and carry on" checkpoint. +- *"stop the triage"* — the same close processing, then *stop the loop* and revert to manual (on-demand) triage. + +A close is the only point auto mode advances the sentinel or commits. Between closes the engine state is untouched — that is what makes a 20-minute sweep cheap and non-destructive, and it preserves the engine invariant: the sentinel still means "everything before this timestamp has been scanned," it just advances once per close instead of once per run. + +** Why a separate mode + +The standard engine is one-shot and mutating — right for an at-the-desk "what's new?" glance, wrong for unattended polling: run every 20 minutes it would advance the sentinel past unprocessed items, spray reactive todos, take mail actions, and commit noise without review. Auto mode separates the cheap, frequent *watching* from the deliberate, gated *committing*, and adds the away-user's missing primitive — the running unacked-responses list. + + * Reference ** Source Plugin Contract @@ -314,6 +389,9 @@ Update the engine as the orchestration pattern evolves; update a plugin as its s *** Updates and Learnings +**** 2026-06-15: Auto mode (unattended monitoring) +Added a self-running mode for when Craig is away but wants tight awareness — a =/loop= in the live session running accumulate-don't-mutate sweeps with "close the triage" / "stop the triage" as the gated checkpoint. Born the morning Craig cleared his day for a family emergency and wanted the desk watched while in and out. Design decisions (work-project proposal, ratified by Craig 2026-06-15): the unacked-responses list is durable in =.ai/triage-intake-unacked.org= (survives a crash/clear, the away-from-desk case it exists for); the sentinel advances only at close, preserving the scanned-before invariant; delivery is an in-session loop so MCP auth is inherited (a detached cron schedule belongs to the morning-ops orchestrator, not here, because of the headless-auth wall); it stays a mode of this engine, distinct from but reusable by that orchestrator. + **** 2026-05-01: Initial creation Extracted from daily-prep's Phase 3 pattern as a standalone, lightweight, between-meetings sweep. diff --git a/claude-templates/.ai/workflows/triage-intake.org b/claude-templates/.ai/workflows/triage-intake.org index b257f2d..7d1290f 100644 --- a/claude-templates/.ai/workflows/triage-intake.org +++ b/claude-templates/.ai/workflows/triage-intake.org @@ -168,6 +168,81 @@ If Craig has been silent for a while after Phase D and the surface looks closed- This rule prevents the failure mode where the workflow self-declares done and the next exchange has to relitigate what state things are in. +* Auto mode (unattended monitoring) + +Auto mode is a self-running variant of the engine for when Craig is away from the desk but wants tight awareness — a loop that runs the standard sweep on a short interval, *accumulates* findings rather than mutating state, and hands Craig a gated checkpoint to commit the batch. It composes two things: the *delivery* (a =/loop= in the live session) and the *behavior* (accumulate-don't-mutate sweeps with a checkpoint). The one-shot run above is unchanged; auto mode is an additional way to run the same Phase 0 / A-D engine. + +** Trigger and delivery + +- "auto triage" / "auto triage-intake" / "watch the desk" / "monitor the triage" — start auto mode. +- Default interval *20 minutes*; Craig sets it. + +Auto mode runs as a =/loop= in the *live session*, not a detached cron job: + +#+begin_src +/loop 20m run an auto-mode triage-intake sweep per triage-intake.org +#+end_src + +Running in the live session means MCP auth (Slack, Gmail, Linear) is inherited from the session — the headless-auth wall that blocks a detached cron run does not apply. A durable cross-session schedule is out of scope here; that belongs to the morning-ops orchestrator, which can later invoke auto mode's accumulate behavior as its triage limb. The close/stop commands below require a live session by design. + +** Preconditions and Close-out + +Auto mode borrows the inbox-monitor gates (=monitor-inbox.org=): do not start on a dirty worktree or a red test suite — a close's batch commit would otherwise sweep up unrelated changes — and leave the tree clean and green when the loop stops. Surface a blocker with inline numbered options per =interaction.md= and wait. + +** A sweep: accumulate, don't mutate + +Each sweep runs Phase 0 (load *both* plugin dirs — the loud requirement still holds) and Phases A-D's scan / classify / synthesize, but performs *none* of the normal run's mutations: + +- Does NOT advance the sentinel. The scan window grows from the last *close* until the next close: every sweep scans from the existing sentinel up to now, so nothing between sweeps is dropped. +- Does NOT write =todo.org= Action tasks — accumulates them for the close. +- Does NOT take mail actions (trash / mark-read / star). +- Does NOT commit. +- 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 — two sections + +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"). +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. + +** The unacked list — durable state + +The awaiting-acknowledgment list lives in =.ai/triage-intake-unacked.org=, so it survives a session crash, a =/clear=, or a restart — the away-from-desk case auto mode exists for. It's project-local state, tracked the same way as the sentinel (=.ai/last-triage-intake=), created on first need. + +Shape — one =** = heading per awaiting item: + +#+begin_example +#+TITLE: Triage Intake — Responses Awaiting Acknowledgment +# Maintained by triage-intake auto mode. One heading per item; acked items are removed. + +** Dana — 2pm reschedule invite +:PROPERTIES: +:SOURCE: personal-calendar +:LOCATOR: <event id or thread url — the dedupe key> +:SINCE: 2026-06-15 10:42 +:END: +She's waiting on a yes/no to the move. +#+end_example + +- *Add* — a sweep appends any new directed-at-Craig response not already listed, deduped on =LOCATOR=. +- *Carry forward* — every sweep re-renders the full list in its second section, whether or not it changed this sweep. +- *Ack* — "ack <item>" (e.g. "ack the Dana thread") removes that heading; "ack all" clears the list. +- *Close* — a close empties the list as part of processing (each item is either actioned or filed). + +** Close and stop — the checkpoint + +The mutations are gated behind two commands: + +- *"close the triage"* — run the full close: take the accumulated mail actions, add the accumulated Action items to =todo.org= as =:quick:reactive:= tasks (asking Craig the questions a normal Phase C/D would), empty the unacked list, then *advance the sentinel* — capture the close run's Phase A timestamp, do the mutations, write that timestamp to =.ai/last-triage-intake= exactly as a normal run does (per "Capture the Phase A timestamp") — and commit + push the batch. Then *keep looping* (next sweep on the normal interval). This is the "flush the batch and carry on" checkpoint. +- *"stop the triage"* — the same close processing, then *stop the loop* and revert to manual (on-demand) triage. + +A close is the only point auto mode advances the sentinel or commits. Between closes the engine state is untouched — that is what makes a 20-minute sweep cheap and non-destructive, and it preserves the engine invariant: the sentinel still means "everything before this timestamp has been scanned," it just advances once per close instead of once per run. + +** Why a separate mode + +The standard engine is one-shot and mutating — right for an at-the-desk "what's new?" glance, wrong for unattended polling: run every 20 minutes it would advance the sentinel past unprocessed items, spray reactive todos, take mail actions, and commit noise without review. Auto mode separates the cheap, frequent *watching* from the deliberate, gated *committing*, and adds the away-user's missing primitive — the running unacked-responses list. + + * Reference ** Source Plugin Contract @@ -314,6 +389,9 @@ Update the engine as the orchestration pattern evolves; update a plugin as its s *** Updates and Learnings +**** 2026-06-15: Auto mode (unattended monitoring) +Added a self-running mode for when Craig is away but wants tight awareness — a =/loop= in the live session running accumulate-don't-mutate sweeps with "close the triage" / "stop the triage" as the gated checkpoint. Born the morning Craig cleared his day for a family emergency and wanted the desk watched while in and out. Design decisions (work-project proposal, ratified by Craig 2026-06-15): the unacked-responses list is durable in =.ai/triage-intake-unacked.org= (survives a crash/clear, the away-from-desk case it exists for); the sentinel advances only at close, preserving the scanned-before invariant; delivery is an in-session loop so MCP auth is inherited (a detached cron schedule belongs to the morning-ops orchestrator, not here, because of the headless-auth wall); it stays a mode of this engine, distinct from but reusable by that orchestrator. + **** 2026-05-01: Initial creation Extracted from daily-prep's Phase 3 pattern as a standalone, lightweight, between-meetings sweep. diff --git a/docs/design/2026-06-15-auto-triage-intake-spec.org b/docs/design/2026-06-15-auto-triage-intake-spec.org new file mode 100644 index 0000000..1c7cd94 --- /dev/null +++ b/docs/design/2026-06-15-auto-triage-intake-spec.org @@ -0,0 +1,43 @@ +#+TITLE: Proposed engine addition — Auto mode (auto triage-intake) +#+DATE: 2026-06-15 + +* What this adds + +A new *mode* of the triage-intake engine: *auto mode* (auto triage-intake). It's a self-running monitor for when Craig is away from the desk but wants tight awareness — a loop that runs the standard triage on a short interval, accumulates rather than mutating, and hands Craig a controlled checkpoint to commit the batch. + +Origin: 2026-06-15, the morning Craig had to clear his day for a family emergency and wanted the desk watched while he was in and out. He asked for 20-minute sweeps that summarize what's come in for him, with an explicit command to process and commit the batch. + +* The mode + +** Cadence +A loop (CronCreate / =/loop=) fires the triage on an interval — default *20 minutes*. Craig sets the interval. + +** Accumulate, don't mutate (the core difference from a normal run) +A normal triage run writes the sentinel, creates =:quick:reactive:= todos, takes mail actions on confirmation, and is a one-shot. An auto-mode *sweep* does none of the mutations: + +- Does NOT advance the sentinel — the scan window grows from the last *close* until the next close, so nothing is dropped between sweeps. +- Does NOT create todo.org tasks — accumulates them (in the session log) for the close. +- Does NOT take mail actions (trash / mark-read / star). +- Does NOT commit. +- DOES run the full plugin scan, DOES update an active daily-prep (Update mode) and re-open it on change, DOES report. + +** End-of-sweep output +Each sweep ends with two short sections: +1. *Deltas* — what changed since the last sweep (one line if nothing). +2. *Responses awaiting your acknowledgment* — every Slack reply, email, or message directed at the user that he hasn't explicitly acknowledged or had the agent answer. This is a *running list carried forward* across sweeps until the user acks each item or closes the triage. It exists because an away user's main need is "who's waiting to hear back from me," which a delta-only sweep loses the moment it scrolls past. + +** Close / stop commands (the checkpoint) +The mutations are gated behind two user commands: + +- *"close the triage"* — finish the mail + sentinel processing, add all accumulated todos (asking the user questions along the way), commit and push, then *keep looping* (next sweep on the normal interval). This is the "flush the batch and carry on" checkpoint. +- *"stop the triage"* — the same close processing, then *stop the loop* and revert to manual triage (run only when asked). + +* Why it's worth adding to the engine + +The standard engine is one-shot and mutating, which is right for an at-the-desk "what's new?" glance. It's wrong for unattended monitoring: running it every 20 minutes would spray reactive todos, advance the sentinel past unprocessed items, and commit noise without review. Auto mode separates the cheap, frequent *watching* from the deliberate, gated *committing* — and adds the away-user's missing primitive, the running unacknowledged-responses list. + +* Companion notes + +- The interval loop is the delivery mechanism (CronCreate session-only, or a durable schedule); the mode is the behavior. They compose. +- "Responses awaiting acknowledgment" tracking needs a small piece of state. In a session it can live in the session-context log; if the engine wants it durable across sessions, a tiny =.ai/triage-unacked.org= (or similar) is the natural home — flagged as a design choice for the rulesets side to decide. +- Deltas-only reporting (the 2026-06-11 ruling) and loud scan-failure surfacing both still apply inside each sweep. @@ -186,6 +186,8 @@ Expected: all four behave per the spec; any miss promotes to a bug task. (Agent- :END: A scheduled headless morning run chaining the existing pieces: startup checks, the triage-intake scan, a system health check — producing the prep doc plus a report and a notify ping, with all remediation propose-only. Staged adoption from the 2026-06-11 insights report's "Self-Healing Daily Ops Orchestrator": read-only first; promote individual routine remediations to auto only after each has a track record. Known blockers to design around: headless MCP auth (interactively-authenticated servers are absent in cron runs) and the consent boundary (triage Phase D, anything destructive). +The triage limb can reuse triage-intake's *auto mode* (added 2026-06-15, see [[file:.ai/workflows/triage-intake.org]]) — its accumulate-don't-mutate sweep is the propose-only behavior this orchestrator wants. Auto mode itself runs in-session (inherited MCP auth); the orchestrator is the durable headless schedule, so the headless-auth blocker above is the part still on this task to solve. + ** TODO [#C] Build =create-documentation= skill for high-quality project/product docs :feature: :PROPERTIES: :LAST_REVIEWED: 2026-06-12 |
