diff options
| author | Craig Jennings <c@cjennings.net> | 2026-06-10 15:27:28 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-06-10 15:27:28 -0500 |
| commit | 403f8b891d04780a99859ed7ef64efcc0f4f82f2 (patch) | |
| tree | a903d67d46b2137eac1a95d23a4e517ec829ec80 /.ai/workflows/triage-intake.org | |
| parent | 34c694567b24c7b22b68acb6e4b9860885eefa76 (diff) | |
| download | rulesets-403f8b891d04780a99859ed7ef64efcc0f4f82f2.tar.gz rulesets-403f8b891d04780a99859ed7ef64efcc0f4f82f2.zip | |
feat(triage-intake): loud scan-failure rule + messenger plugin rework
The 2026-06-10 sweep shipped without Signal: a standalone signal-cli receive hung on the account lock while the signel daemon owned it, and the failure looked identical to a quiet source. The engine now renders any failed, hung, or skipped scan in a SCAN FAILED banner at the top of the summary. Quiet means the scan ran and found nothing.
The signal plugin now detects which path owns the account before scanning: when the signel daemon is live it queries chat buffers through Emacs, and the standalone draining receive runs foreground-only when it isn't. The telegram plugin gets an at-a-glance lifecycle (docker-mode launch, scan, send, shutdown only if the scan started the server) and treats a real DM from a work contact as Action.
Diffstat (limited to '.ai/workflows/triage-intake.org')
| -rw-r--r-- | .ai/workflows/triage-intake.org | 12 |
1 files changed, 12 insertions, 0 deletions
diff --git a/.ai/workflows/triage-intake.org b/.ai/workflows/triage-intake.org index 265b883..173f051 100644 --- a/.ai/workflows/triage-intake.org +++ b/.ai/workflows/triage-intake.org @@ -95,6 +95,14 @@ Per-source bias (a work email account leans keep for audit value; a personal acc One markdown summary surfaced inline to Craig. Order: +0. *Scan failures — first, loud, always.* Any loaded source whose scan failed, hung, was killed, or was skipped for an operational reason renders at the very top of the summary, before Top signals: + + #+begin_example + ⚠ SCAN FAILED: <source> — <reason, one line> — <what's now unknown> + #+end_example + + A failed scan is never folded into "quiet." Quiet means the scan ran and found nothing; a failure means the sweep is blind on that channel, and the reader must know which. The same applies to a precondition skip the user hasn't standing-approved (e.g. a messaging client that needs a temporary server spin-up): run the lifecycle or report the failure — don't silently narrow the sweep. + 1. *Top signals to act on* — bullet list of 3-7 items, ordered by urgency, *Action only*. Each bullet links to the source (permalink, thread URL, PR number). 2. *Per-source breakdown* — one short section per *loaded* source, in =ORDER=, using that plugin's =Render= shape: Action items detailed, FYI items as a short list, Noise as a tally only ("Noise: 12 trash candidates, 4 keep, 0 starred"). 3. *Suggested actions* — explicit list of state changes Craig could take this run (trash these N messages, mark-read these M, star this Action item, respond to this invite, merge PRs #X and #Y, etc.). @@ -278,6 +286,7 @@ Order matters: top-signals first because that's what Craig reads in 30 seconds b 6. *Using mtime instead of content for the sentinel.* Plain =touch= writes /now/ to mtime, stranding items posted between Phase A and end of run. =touch -d "@$PHASE_A_TS"= fixes the time but mtime is per-machine — git tracks content, not metadata, so the anchor doesn't survive a clone or cross-machine sync. Always write the epoch into the file's *content*. 7. *Running this alongside daily-prep.* Daily-prep already does this as Phase 3 — don't duplicate. 8. *Mixing Action and FYI in the top-signals list.* Top signals = Action only. FYI lives in the per-source detail. +9. *Reporting a failed or skipped scan as a quiet source.* A hung receive, a dead daemon, or a skipped spin-up looks identical to "no new messages" in the output unless it's flagged. The 2026-06-10 sweep shipped with Signal silently missing because the scan hung on an account lock. Failures lead the summary, in their own banner line. * History / Design Notes @@ -297,6 +306,9 @@ Gap-window bug: a run had Phase A fire at 13:35 and the sentinel set at 15:04, s **** 2026-05-13: Move the sentinel from mtime to content (cross-machine survivability) The sentinel is checked into git, but git tracks content, not mtime — so an mtime anchor is per-machine. Fix: write the captured epoch into the sentinel's content (=EPOCH ISO-8601=), read with =awk 'NR==1 {print $1}'=, mtime as back-compat fallback. +**** 2026-06-10: Loud failure surfacing (Phase C item 0 + Common Mistake 9) +Craig: "highlight any failures in daily triage loudly. I get important communication from all these channels." Trigger: the 2026-06-10 sweep shipped with Signal silently missing — a standalone receive hung on the account lock while the signel daemon owned it, and the failure looked identical to a quiet source. Failures now lead the summary in a ⚠ SCAN FAILED banner; the signal and telegram plugins' failure paths point at this rule. + **** 2026-05-26: Refactor into engine + source plugins Split the monolithic workflow into a source-agnostic engine (this file) and per-source plugins named =triage-intake.<source>.org=. The engine carries the anchor/sentinel logic, the four-bucket model, the Phase A-D orchestration, the todo.org persistence convention, and the exit criteria. Each source's scan/classify/render/action knowledge moved to its own plugin. General plugins (personal-gmail, personal-calendar, cmail, github-prs) live in =.ai/workflows/= and are template-synced; project-specific plugins (a work project's Linear, work Gmail, work Slack, enterprise PRs) live in the project's =.ai/project-workflows/= and are never synced. Phase 0 globs *both* directories — the loud requirement, because missing the project dir silently halves the sweep. Naming convention: first dot is the engine/plugin boundary, deeper dots reserved for sub-adapters. This removed all DeepSat/Linear specifics from the engine; they become work-project plugins. |
