<feed xmlns='http://www.w3.org/2005/Atom'>
<title>rulesets/.ai/workflows/triage-intake.org, branch main</title>
<subtitle>Claude Code skills, rules, and language bundles
</subtitle>
<id>https://git.cjennings.net/rulesets/atom?h=main</id>
<link rel='self' href='https://git.cjennings.net/rulesets/atom?h=main'/>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/'/>
<updated>2026-06-24T03:06:46+00:00</updated>
<entry>
<title>feat(inbox): consolidate three inbox workflows into one engine</title>
<updated>2026-06-24T03:06:46+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-24T03:06:46+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=24ca58d764dbcc2bad57a914a10e9e9b89a3f66e'/>
<id>urn:sha1:24ca58d764dbcc2bad57a914a10e9e9b89a3f66e</id>
<content type='text'>
I merged process-inbox, monitor-inbox, and inbox-zero into one inbox.org engine. A shared core (value gate, skeptical review, disposition ladder, reply discipline, capture-guard, priority-scheme check) holds the logic that used to be duplicated and cross-referenced across the three files. Each mode (process, monitor, roam) references the core by name instead of restating it.

Every trigger phrase still works, now routing to a mode, so there's nothing to relearn. I added the interactive auto inbox zero mode: ask for an interval, run roam mode on /loop, acknowledge-only on an empty cycle, surface a find to a queue gated on a yes. The fully-unattended /schedule pass stays vNext, tracked separately.

I repointed every live caller (INDEX, protocols, startup Phase C, wrap-up Step 3, triage-intake, broadcast) at inbox.org and its modes, then deleted the three old files. triage-intake and no-approvals stay separate by design. The value gate, dispositions, capture-guard, and reply discipline all behave as before.

Built from the Ready spec. Workflow-integrity and sync-check pass on both the canonical and mirror trees, the stale-reference grep is clean, and the full suite is green.

Claude-Session: https://claude.ai/code/session_017PtX1nt1rtYVATuzmzBS4f
</content>
</entry>
<entry>
<title>feat(kb): wire consult + contribute KB prompts into the workflows</title>
<updated>2026-06-21T03:28:37+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-21T03:28:37+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=76e55591e2a66e8ef42ee6e4535882545ee3d33b'/>
<id>urn:sha1:76e55591e2a66e8ef42ee6e4535882545ee3d33b</id>
<content type='text'>
Recent session receipts read "promoted 0 / consulted no" across the board: the wrap-up KB-promotion check existed but fired too late, and nothing surfaced existing lessons to read. This adds the spec's four light prompts plus the read-side step it was missing. Startup gets two Phase C nudges (gated on the roam clone): a consult line listing project-relevant node titles, and a contribute line pointing at the best-practices node. Triage-intake and inbox-zero get a conditional end-of-flow capture reminder that fires only on real signal. Wrap-up gets an early reflection prompt at the top of Step 1 that feeds the existing receipt, so learnings are captured while fresh instead of reconstructed after the Summary. Ratifies the spec's five decisions and adds D6 (the read-side surfacing).
</content>
</entry>
<entry>
<title>feat(triage): add a per-sweep timestamp to auto mode output</title>
<updated>2026-06-15T23:35:29+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-15T23:35:29+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=1898a0d85d7da0bf05b4337a11fd1b823b5827fe'/>
<id>urn:sha1:1898a0d85d7da0bf05b4337a11fd1b823b5827fe</id>
<content type='text'>
Auto-mode sweeps now end with the date, time, and timezone on their own final line, so an away reader gauges each summary's freshness at a glance without computing it. The stamp prints on every sweep, including a quiet "no changes" one — there the stamp is the proof the loop ran.

Same-day addendum to the work-project auto-mode proposal.
</content>
</entry>
<entry>
<title>feat(triage): add auto mode for unattended monitoring</title>
<updated>2026-06-15T19:41:00+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-15T19:41:00+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=561e481c492dc0e160158b8df5c62abbd3530d6b'/>
<id>urn:sha1:561e481c492dc0e160158b8df5c62abbd3530d6b</id>
<content type='text'>
Add an auto mode to the triage-intake engine: a self-running variant for when Craig is away but wants tight awareness. It runs the standard sweep on a short interval (default 20 min) as an in-session loop, accumulates findings instead of mutating state, and gates the mutations behind "close the triage" (flush the batch, keep looping) and "stop the triage" (flush, then stop).

A sweep advances nothing — no sentinel write, no todos, no mail actions, no commit. The scan window grows from the last close to the next, so nothing between sweeps is dropped, and the sentinel still means "everything before this timestamp has been scanned" — it just advances once per close. Each sweep reports deltas plus a running "responses awaiting your acknowledgment" list, the primitive an away user needs that a delta-only sweep loses.

The unacked list is durable in .ai/triage-intake-unacked.org so it survives a crash, a clear, or a restart — the away-from-desk case the mode exists for. Delivery is an in-session loop so MCP auth is inherited; a detached cron schedule stays out of scope and belongs to the morning-ops orchestrator, which can reuse this accumulate behavior as its triage limb.

Source proposal from the work project, design decisions ratified 2026-06-15.
</content>
</entry>
<entry>
<title>chore: drop the Signal triage-intake plugin</title>
<updated>2026-06-12T20:49:56+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-12T20:49:56+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=d8c38b0ac4d4b8885fe96230a234761187bd3f58'/>
<id>urn:sha1:d8c38b0ac4d4b8885fe96230a234761187bd3f58</id>
<content type='text'>
Remove the triage-intake Signal source plugin and de-list Signal from the engine's plugin enumeration. I'm rebuilding the Signal client (signel + signal-cli) from scratch, so the plugin would scan against an unstable client. The signal MCP server and its README setup stay. Re-add the plugin when the client is stable.
</content>
</entry>
<entry>
<title>feat(triage): deltas-only sweep summaries and silent telegram dev groups</title>
<updated>2026-06-11T23:22:12+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-11T23:22:12+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=647bc6119a19b9d8dc1d1860e6b253c1390b1e9b'/>
<id>urn:sha1:647bc6119a19b9d8dc1d1860e6b253c1390b1e9b</id>
<content type='text'>
A sweep now reports only what changed: a new invite, a moved or cancelled event, a message needing attention. Unchanged sources get no block. An all-quiet sweep renders as one line. Scan failures keep their loud banner and the suggested-actions line stays when actions are queued.

Telegram dev-community group traffic (zed, GNU Emacs, Kitty) is dropped from sweep reports entirely unless Craig asks. Real DMs from known contacts still surface as Action.
</content>
</entry>
<entry>
<title>feat(triage-intake): loud scan-failure rule + messenger plugin rework</title>
<updated>2026-06-10T20:27:28+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-10T20:27:28+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=403f8b891d04780a99859ed7ef64efcc0f4f82f2'/>
<id>urn:sha1:403f8b891d04780a99859ed7ef64efcc0f4f82f2</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>feat(triage-intake): add Telegram source plugin</title>
<updated>2026-06-09T19:15:48+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-09T19:15:48+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=75ab07df65351f9c96738cd7efe5edacc523ac80'/>
<id>urn:sha1:75ab07df65351f9c96738cd7efe5edacc523ac80</id>
<content type='text'>
I added a Telegram source plugin so the triage-intake sweep covers Telegram alongside Signal, cmail, Gmail, calendar, and PRs. Telegram is personal messaging, so it's a general plugin that syncs to every project.

Unlike signal-cli, Telegram has no headless CLI here, so the plugin drives telega.el inside the running Emacs daemon over emacsclient. It records whether telega was already live and shuts it down only if the scan started it, leaving an active session alone. Two sharp edges are documented in the plugin: the tdlib server can SIGSEGV on the initial sync, where docker mode is the fix, and the scan reads the cached telega--chats hash so a dead server still reports unread state instead of going blank.

I also added Telegram to the engine's general-plugin list.
</content>
</entry>
<entry>
<title>feat(triage-intake): add Signal source plugin</title>
<updated>2026-06-08T23:22:26+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-08T23:22:26+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=627f521a2e1cc6830dc26a97251772084b708db4'/>
<id>urn:sha1:627f521a2e1cc6830dc26a97251772084b708db4</id>
<content type='text'>
I added a Signal source plugin so the triage-intake sweep covers Signal alongside cmail, Gmail, calendar, and PRs. Signal is personal messaging, so it's a general plugin that syncs to every project.

It needs no wrapper script, unlike cmail. signal-cli is already a full CLI, so the plugin drives receive and send directly. The scan filters signal-cli's JSON down to real messages and drops the sync, receipt, and typing noise. One sharp edge is documented in the plugin: signal-cli receive drains the server queue, so the triage gets one shot per message. Signal Desktop and the phone keep their own copies, so nothing's lost.

I also added Signal to the engine's general-plugin list.
</content>
</entry>
<entry>
<title>feat(daily-prep): store prep docs in daily-prep/ with a root symlink</title>
<updated>2026-06-01T13:29:25+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-01T13:29:25+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=225c60df3ffe4d2163d8d42975d4cb74fe5ada39'/>
<id>urn:sha1:225c60df3ffe4d2163d8d42975d4cb74fe5ada39</id>
<content type='text'>
Prep docs are now born in daily-prep/YYYY-MM-DD-daily-prep.org and never move. A stable symlink at the project root, daily-prep.org, points at the current day's file and is the only thing that changes day to day. I replaced the old model where the doc was born in inbox/, yesterday's lingered there, and older docs were moved into a daily-prep/ archive.

Consumers resolve the root symlink instead of reconstructing a dated filename or scanning inbox/: the standup lookback, next-day Phase 2, and the Emacs opener. Phase 8 becomes a symlink repoint rather than an archive move, and triage-intake's prep-doc anchor fallback now points at daily-prep/ only.
</content>
</entry>
</feed>
