aboutsummaryrefslogtreecommitdiff
path: root/.ai/workflows
Commit message (Collapse)AuthorAgeFilesLines
* feat(tasks): surface cross-project dependencies in what's-nextCraig Jennings2026-06-241-1/+15
| | | | | | A task can be blocked by work owed by another project, and today it keeps getting recommended as "next" even though it can't move, while the blocker sits at low priority over there and the dependency stalls silently. Adds a :blocked: tag plus a :BLOCKED_BY: <project>: <what> property (todo-format.md) to mark the dependency, and teaches open-tasks.org Next Mode to pull :blocked: tasks out of the cascade pick and surface them in a dedicated "Blocked on other projects" section that names each blocker and offers an inbox-send nudge. Distinct from VERIFY, which waits on Craig rather than another project. Claude-Session: https://claude.ai/code/session_017PtX1nt1rtYVATuzmzBS4f
* feat(inbox): poll-and-retry the capture-guard instead of bouncingCraig Jennings2026-06-241-5/+14
| | | | | | | | | | When a roam edit hits a live org-capture, the guard used to bounce the caller right away (surface to the user, or skip the cycle) even though the capture is usually a few seconds of mid-finalize that clears on its own. capture-guard gets a --wait poll mode: it re-checks every ~10s up to a budget (default 30s, each sleep capped so a short --wait never overshoots), returns the instant the capture clears, and reports blocked only at the deadline. The no-capture common case still returns instantly without sleeping. Roam mode now uses --wait on every write, and the per-caller fallback fires only after the wait: an interactive run surfaces, the auto /loop defers to the next cycle (the loop cadence is the retry), wrap-up skips and self-heals. Surfaced live this session: a transient capture blocked a roam reconcile and had cleared a minute later. Covered by three new bats cases (instant-when-safe, timeout-when-blocked, target-after-flag). Claude-Session: https://claude.ai/code/session_017PtX1nt1rtYVATuzmzBS4f
* feat(wrap): end the valediction with a "session wrapped." signoffCraig Jennings2026-06-241-1/+5
| | | | | | The wrap-up valediction now always ends with "session wrapped." on its own line — a consistent, unmistakable end-of-session marker, since it's the last user-facing output before Step 6's silent teardown. Craig's request via the roam inbox. Claude-Session: https://claude.ai/code/session_017PtX1nt1rtYVATuzmzBS4f
* fix(inbox): stop pulling the roam repo during triageCraig Jennings2026-06-242-11/+18
| | | | | | | | | | The roam repo's working tree is dirty most of the time (Craig captures into it constantly, and roam-sync only commits every 15 minutes), so roam mode's pull --ff-only failed on nearly every run and blocked triage. The auto inbox zero loop hit it every cycle. Roam mode now never pulls. The scan reads the working-tree file directly, since that's already the latest local state, and the rare write removes the claimed items in place and then triggers roam-sync to commit and push. roam-sync already commits-first-then-rebases, so it handles the dirty tree, and the ownership partition (only this project touches its own prefixed lines) means its rebase can't conflict on the edit. Trade-off: the roam-repo commit carries roam-sync's generic auto-sync message instead of a descriptive one. The provenance for routed tasks lives in the project's todo.org and session log anyway. Claude-Session: https://claude.ai/code/session_017PtX1nt1rtYVATuzmzBS4f
* feat(wrap): add session teardown and shutdown to wrap-it-upCraig Jennings2026-06-232-2/+56
| | | | | | | | | | | | A bare "wrap it up" now tears the session down after the valediction: it kills the ai-term buffer and the aiv-<project> tmux session (which takes claude with it) and restores geometry. "wrap it up with summary" or "and summarize" keeps the buffer. "wrap it up and shutdown" gates on this being the only live ai-term session, then powers the machine off through an abort-able Emacs countdown. Teardown can't run inline because it kills the session claude runs in, so the valediction would never flush. Step 6 instead drops a basename-keyed sentinel after commit+push is verified, and a new Stop hook (ai-wrap-teardown.sh) does the teardown when the response ends, by which point the valediction has rendered. The hook is a no-op on every normal stop because the sentinel only exists after a teardown wrap. The runtime lives in .emacs.d/modules/ai-term.el (cj/ai-term-quit, cj/ai-term-live-count, cj/ai-term-shutdown-countdown), and the rulesets side calls it via emacsclient. I routed that companion to .emacs.d, so the feature is end-to-end once it lands. The hook has 8 bats tests. The live teardown and shutdown paths are a manual checklist in todo.org. Built from the proposal. I went with both summary qualifiers, the Emacs-timer countdown, and the live-count gate. Claude-Session: https://claude.ai/code/session_017PtX1nt1rtYVATuzmzBS4f
* feat(inbox): consolidate three inbox workflows into one engineCraig Jennings2026-06-2310-481/+502
| | | | | | | | | | | | 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
* feat(inbox-zero): sweep empty roam entries on triageCraig Jennings2026-06-231-7/+8
| | | | | | An aborted org-capture can leave a heading with no title and no body (just stars and maybe a TODO keyword). Those belong to nobody and were piling up in the shared roam inbox. inbox-zero now buckets them as empty in Phase B and removes them in Phase D in the same edit as the claimed items. An empties-only run still enters Phase D and commits, so the sweep runs on every triage, not only when this project owns something. A heading with any title or body is never touched.
* feat(inbox-zero): guard roam-inbox writes against live org-captureCraig Jennings2026-06-231-3/+8
| | | | | | | | | | Editing the roam inbox on disk while Emacs has an indirect org-capture buffer cloned from it reverts the base buffer under the capture: the capture can't finalize with C-c C-c, and a freshly-typed item can be lost. inbox-zero Phase D edits that file, which Craig captures into constantly, so the collision recurs every session. I added a capture-guard helper that asks the running daemon whether any CAPTURE buffer's base buffer visits a given file (file-equal-p, so symlinks and path spelling don't matter), exiting non-zero with the names when so. No reachable Emacs or no capture means exit 0, so it never blocks a write that was safe. Phase D calls it before the pull, not only before the remove, because the ff-only pull also rewrites the file on disk and would wedge a capture the same way. On a collision an on-demand run stops and asks Craig to finalize or abort. The wrap-up sub-step skips the roam reconcile without blocking the wrap, since the items are already filed and the next run reclaims them. emacs.md gains the inverse of the reload rule: don't yank a file out from under the daemon's live buffers.
* refactor: fold spec review findings into the spec itselfCraig Jennings2026-06-214-100/+73
| | | | | | | | The spec-review/spec-response pair wrote findings to a sibling <spec>-review.org file that spec-response deleted once processed. The deletion left the iteration-history Artifacts line dangling and dropped the verbatim review. Keeping the file instead collided with spec-response's file discovery and its "no review files remain" done-condition. Findings now live in the spec under a * Review findings section as TODO tasks with a [/] cookie, the same shape * Decisions already uses. The reviewer records findings there. The responder completes each in place (accept and modify finish DONE, reject finishes CANCELLED with the reason), and the readiness rubric gates on the cookie. A scope-expanding response re-runs the rubric and files any new obligation as a finding or decision before claiming Ready, because resolving every finding can still introduce unreviewed assumptions. Also folds in two reviewer-practice principles: keep review and response roles explicit, and cite the source for external-dependency facts in a finding. Updates spec-create.org and the workflow INDEX so the trio describes one convention.
* chore: sync inbox-zero.org mirror from canonicalCraig Jennings2026-06-211-10/+22
| | | | The canonical and mirror copies of inbox-zero.org were committed out of sync; the mirror lagged the canonical's two-inbox revision. Bring the mirror up to match.
* feat(kb): wire consult + contribute KB prompts into the workflowsCraig Jennings2026-06-204-0/+26
| | | | 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).
* docs: level-2 VERIFY completes task-shaped, not as a dated headerCraig Jennings2026-06-201-1/+1
| | | | The old rule dated a resolved VERIFY at every depth, including the top level. A level-2 dated header carries no keyword, so todo-cleanup's --archive-done can never archive it and task-review drops it from selection. Now a top-level VERIFY closes like any other top-level task (DONE/CANCELLED + CLOSED:), and dated rewrites are reserved for level 3 and deeper. Updated the rule and the three places that encoded the old behavior: todo-format.md, respond-to-cj-comments.md, and process-inbox.org. Also repaired two pre-existing level-2 dated headers.
* refactor: remove unused cross-agent-comms subsystemCraig Jennings2026-06-164-346/+8
| | | | Nothing used the cross-agent message system (send/recv/watch/status/discover/halt/resume over the inbox/from-agents/ file-IPC protocol). Every cross-project handoff goes through inbox-send instead. I removed the scripts, READMEs, workflow, tests, INDEX entry, the three startup.org wirings, and the legacy bin symlinks, then repointed helper-mode's escalation to inbox-send and noted the removal in the generic-agent-runtime spec.
* feat(triage): add a per-sweep timestamp to auto mode outputCraig Jennings2026-06-151-2/+7
| | | | | | 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.
* feat(triage): add auto mode for unattended monitoringCraig Jennings2026-06-151-0/+78
| | | | | | | | | | 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.
* feat(inbox): define monitor-inbox as a 15-min loop with clean-tree gatesCraig Jennings2026-06-153-25/+58
| | | | | | | | | | Redefine "monitor the inbox" as the explicit behavior Craig wants: run one process-inbox pass now, then loop process-inbox every 15 minutes. The 15-minute loop was previously an opt-in background recipe; it's now the defined meaning of the phrase. Gate the workflow at both ends on a clean worktree and a green full-suite run. Starting on a dirty tree lets the per-item auto-commit sweep up unrelated changes; starting on a red suite hides whether the monitor broke anything. On a dirty tree, offer to commit in discrete batches; on a red suite, offer to investigate — never start until both are satisfied, and leave the tree clean and green when the loop stops. Add the no-approvals execute criteria: an accepted item self-applies only when agreed (passed the value gate and Skeptical Review), quick (under ~15 min including verification), and solo (no decision needed from Craig). All three commit and push at the end of the item; miss any and it files or, for shared-asset and convention changes, parks. Broaden the Skeptical Review to run on every arriving task and file, not only shared-asset proposals — a core right/complete/simpler pass on everything, with the cross-project battery added for changes that sync to consuming projects.
* feat(ai): add helper-mode workflow contractCraig Jennings2026-06-152-0/+102
| | | | | | | | helper-mode.org is the canonical home of the helper-instance rules: a second Claude alongside a live primary in the same project. It defines the four read/write tiers (always-safe reads and own-context writes, safe-by-discipline scoped single-heading edits, primary-only file-wide passes and all git mutation, escalation), the four data-integrity windows, the light startup, and the helper wrap-up (archive own context file, skip commit, with the git ban lifting only for an orphaned helper that ends up alone). protocols.org gets a one-paragraph pointer, and INDEX.org gets a triggerless catalog entry like startup.org, so the no-trigger workflow clears the integrity check without a special case. The contract is the canonical home. The routing that sends a session here (ai --helper, startup's roster branch, the wrap-up helper branch) ships behind the feature's drill gate and isn't live yet. Until then a session adopts it by an explicit "you are a helper" instruction.
* docs(ai): require an epoch on the tail of helper-agent idsCraig Jennings2026-06-141-1/+1
| | | | | | A helper agent's session-context file is .ai/session-context.d/<id>.org. A bare, reused id like "codex" makes the next run resolve to the previous run's leftover anchor, which it then mistakes for a crash to recover or clobbers. That bit on 2026-06-13: a codex run left codex.org for the next session to clean up. The fix is a convention, not a resolver change. The spawner appends an epoch on the tail (host.project.runtime.<epoch>) so each run gets a fresh anchor. The epoch can't be minted inside session-context-path, since that resolver runs many times per session and must return the same path each call. I documented it in protocols.org, the wrap-up recommended-shape note, and the resolver header.
* feat(workflows): add inbox-zero for routing the roam inbox by projectCraig Jennings2026-06-134-0/+111
| | | | | | | | The global roam inbox (~/org/roam/inbox.org) is one shared capture file every project can see, and nothing routed its items to the project that owns them. inbox-zero claims the items prefixed for the current project, files them into that project's todo.org per the process-inbox discipline, and removes them from the shared inbox. Foreign-prefixed and unowned items stay. Every scan reports the total item count plus how many appear related to this project. This v1 is single-destination: it routes by explicit <project>: prefix only. The domain-aware mode that would guess every item's owner and empty the whole inbox in one run is deferred until the multi-project need is concrete. Wired into both session ends so each project touches the inbox twice a session: startup surfaces a read-only count and offer, wrap-up Step 3 sweeps the claimed set before the cleanup scripts so imported tasks ride the wrap commit. INDEX carries the trigger phrases.
* feat(workflows): skeptical review gate for inbox change proposalsCraig Jennings2026-06-122-2/+47
| | | | | | | | The value gate asks whether to take an inbox item, never whether the proposed change is right. process-inbox gains a Skeptical Review for proposals that change shared assets: a written question battery (fit for all consumers, conflicts elsewhere, effect on common activities, enhancement, simplification, plus at least three change-specific questions), ending in a summary and recommendation Craig approves before the change lands. In a no-approvals session, behavior-changing proposals park instead of self-applying: prepared diff in working/, a [#B] VERIFY carrying the decision package, a reply to the sender. Wording-only fixes proceed, logged. monitor-inbox's act-vs-file rule and protocols.org's act-now line gain the matching exception so all three statements of the rule agree. protocols.org's tables picked up the org-table-standard reflow in the same pass. The motivating case is today's spec-decisions handoff. I applied it as-is, and the after-the-fact review surfaced a lost state and a vacuous gate pass the battery would have caught up front.
* feat(workflows): SUPERSEDED/CANCELLED decision states + old-model gateCraig Jennings2026-06-122-4/+10
| | | | | | A superseded decision now flips to SUPERSEDED (linking its replacement) and a moot one to CANCELLED. Both are done-class via a #+TODO: header the spec template auto-adds, so the [/] cookie counts them resolved and neither blocks implementation-ready. The TODO/DONE pair alone had lost the old State: field's superseded value. spec-review's gate and Ready rubric now read "no decision is still TODO", and a spec still on the retired State: field model fails the gate item until converted. The gate as first written would have vacuously passed old specs, which have no decision tasks at all.
* feat(workflows): spec decisions become org TODO/DONE tasksCraig Jennings2026-06-123-15/+31
| | | | | | Each spec decision is now an org TODO task that flips to DONE when the decision-maker agrees, with a [/] cookie on the Decisions heading and a Discussion child for disputes. This replaces the inline State: proposed | accepted | superseded field. spec-response folds settled decisions by flipping them to DONE. spec-review's readiness gate and Ready rubric require the cookie to read complete. A spec can't move past draft to implementation-ready while any decision is still TODO. From the .emacs.d handoff 2026-06-12.
* chore: drop the Signal triage-intake pluginCraig Jennings2026-06-122-118/+2
| | | | 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.
* chore: delete the page-signal pager wrapperCraig Jennings2026-06-123-90/+1
| | | | Remove the page-signal CLI wrapper, its workflow, and the references in INDEX.org, broadcast.org, and mcp/README.org. The signal MCP server stays. It's the two-way path and a separate capability. The pager number had deregistered and the send-only wrapper isn't worth re-registering.
* docs(task-audit): add tag-vocabulary enforcement and verify-then-closeCraig Jennings2026-06-121-0/+14
| | | | Two Phase C behaviors, both surfaced auditing an Emacs-config todo.org. Enforce a project's declared closed tag set (strip tags outside it) where the legend marks the set exhaustive, leaving open-vocabulary projects untouched. For a task whose code shipped but awaits a manual or visual check, file that check under the project's manual-testing parent (dedup first) and close the implementation task, rather than letting "done but unverified" linger half-open.
* feat(triage): deltas-only sweep summaries and silent telegram dev groupsCraig Jennings2026-06-112-11/+37
| | | | | | 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.
* feat(workflows): session-harvest monthly promotion-mining passCraig Jennings2026-06-112-0/+106
| | | | | | session-harvest runs a monthly pass over recent session summaries across every AI project and proposes promotion candidates in four lanes: patterns catalog, KB facts, rule refinements, workflow learnings. Capture already happens continuously. This adds the batched review cadence that turns it into curated promotion. The window filter reads each session filename's date prefix instead of mtime. Clones and syncs reset mtime, which let 2025 sessions pass a recency filter. The run also aggregates the KB receipt lines from session summaries, so it doubles as the 30-day KB metrics readout.
* fix(triage): correct telegram mark-read verbs and crash guidanceCraig Jennings2026-06-111-12/+43
| | | | The documented mark-read verb telega-chat--mark-read never existed in telega. I replaced it with the verified telega--viewMessages form (plus mentions and reactions), noted that telega-chat-toggle-read toggles and needs an unread guard, and added the delete-join-notice sweep Craig approved (first run deleted 41 chats). The SEGFAULT gotcha now reflects reality: the dockerized server crashes spontaneously (memory corruption, 11 coredumps since 2026-06-09), the verbs were never the trigger, so action batches check the server first and treat a death as retryable.
* fix(install): link default hooks in make installCraig Jennings2026-06-111-2/+2
| | | | | | session-clear-resume.sh shipped 2026-06-02 with its settings.json entry, but make install didn't cover hooks and nothing re-ran install-hooks, so the symlink only existed on machines that had linked it by hand. Everywhere else the hook errored silently on every /clear. make install now links DEFAULT_HOOKS alongside skills, rules, config, and bin scripts, so the startup workflow's install step propagates new hooks machine-wide. Opt-in hooks stay manual. scripts/tests/install-hooks-link.bats covers the new section. The SessionStart-on-clear todo task closes with this: the hook feature already existed, and the gap was distribution.
* feat(workflows): rewrite daily-prep to the strict three-section templateCraig Jennings2026-06-112-420/+239
| | | | | | | | From the template spec Craig wrote 2026-06-10 plus four refinements from his review of the first new-format prep. The doc is now exactly Heads-Up, Day's Priorities, and Meetings / Focus Blocks. Two run modes replace full-prep and standup-only: Create ends with a mandatory priorities review gate (disagreement there signals todo.org staleness), and Update refreshes a day when the world moves. Both run a triage-intake first when none ran in the last hour. It retires the separate Standup Briefs and Upcoming Deadlines sections, the Anchor Tasks handoff, and the thin-link convention. Priorities entries now mirror their todo.org task heading and carry links and context in the body. Briefs nest under the standup they're reported in, with Blockers: None explicit. Meetings carry what to contribute and get, likely questions with answers, linked prep docs, and day-before prep blocks for unanswered questions. Focus blocks are linked menus, created the day before and marked free. The spec and the decisions handoff land in docs/design/.
* feat(workflows): transcript processing gains classification, extraction, ↵Craig Jennings2026-06-101-31/+42
| | | | | | exit gate Three changes from today's work session, closing the defect where the workflow could end at file hygiene with nothing landing in durable homes. Every recording is classified before transcription (this project / named other project / personal — unmatchable files ask Craig, never default), and cross-project files route per cross-project.md: labeled transcript plus an outcome note via inbox-send, recording to the owning project's meetings dir, nothing in local assets. A new mandatory Step 11 extracts action items to todo.org with owners and decisions to knowledge.org. The validation checklist becomes a hard exit gate: Step 13 (delete sources, the irreversible step) must not run until classification, extraction, and durable-home writes all hold.
* fix(triage-intake): Signal is Emacs-only — remove the standalone receive pathCraig Jennings2026-06-101-45/+32
| | | | Craig's ruling, correcting this morning's plugin: signel and standalone signal-cli share the same account config and device queue, so a standalone drain steals messages the Emacs client would otherwise show him. Step 0 now starts signel via cj/signel--ensure-started when it's down and leaves it running (a live signel is the steady state, so no teardown). signal-cli survives only for queue-untouching reads like listAccounts; the SCAN FAILED rule covers signel failing to start.
* feat(workflows): wrap-up promotes to the KB and records the usage receiptCraig Jennings2026-06-101-0/+13
| | | | Phase 3 of the agent KB spec. Step 1 of wrap-it-up gains a promotion check against knowledge-base.md's inclusion criteria, and every Summary now ends with a "KB: promoted N / consulted yes-no" line — the single grep-able input to the spec's 30-day success-metrics checkpoint. The validation checklist enforces the line.
* feat(kb): roam-sync script + timer units, old roam path repointedCraig Jennings2026-06-101-2/+2
| | | | Phase 0 of the agent KB spec: the org-roam KB now lives at ~/org/roam as a git repo on cjennings.net. roam-sync.sh (bats-tested: commit, rebase, push, conflict-abort) runs from a 15-minute systemd user timer; canonical unit files live in scripts/systemd/. Live references to the old ~/sync/org/roam path (the task-list pointer, the journal workflow, the notes template) repoint to ~/org/roam, and a transition symlink at the old location covers stragglers.
* feat(triage-intake): loud scan-failure rule + messenger plugin reworkCraig Jennings2026-06-103-25/+128
| | | | | | 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.
* feat(workflows): daily-prep carries execution links and join linksCraig Jennings2026-06-101-1/+16
| | | | | | A Day's Priorities entry now carries the URL the task is done through (payment portal, doc, PR, form), not just the thin link to its todo.org home. When that URL is missing from the todo.org body, the prep build finds it and adds it to both. Meeting lines in Meetings / Work Blocks get an org link to the join URL from the calendar event's conference data, so joining is one click from the prep doc. Both rules came out of working the 2026-06-10 prep doc, where paying an invoice meant a Gmail dig for the payment URL first.
* feat(voice): expand skill to 45 patterns with attestation receipts and ↵Craig Jennings2026-06-101-2/+2
| | | | | | | | | | | | artifact budgets Two patterns kept failing in practice despite being documented (#40 praise asymmetry and the #38 terse cut), so I made the walk verifiable and closed the content gap behind tangled review text. The high-recurrence set (#13, #37, #38, #40, #42) now gets per-pattern attestation receipts. The anti-AI audit runs after the terse pass so the audited text is the text that ships. Short personal-mode artifacts get a compact output format, and a write-back step puts the voiced text in the file the publish flow posts from. Four patterns are new: #42 finding stems (one claim per sentence in review findings), #43 single-sentence paragraph cadence, #44 parenthetical asides, #45 declarative register marker. #37 exempts verdict formulas. #40 covers verification narration. #13 and #33 carry the self-discipline framing. A per-artifact budgets table makes terse a checkable budget instead of an adjective. The profile gains paired entries with the approved worked examples, and commits.md plus no-approvals.org drop hardcoded pattern counts so the next addition doesn't re-drift them.
* feat(workflows): promote meeting-prep to a general templateCraig Jennings2026-06-104-3/+179
| | | | | | Meeting-prep was project-only. I generalized its project-specific references (transcript-home path, issue tracker, knowledge file, worked-example doc) to neutral terms and moved it into claude-templates so any project's .ai/ picks it up. The pre-wire supporting doc travels beside it as meeting-prep.pre-wire.org. I added the workflow entry and trigger phrases to INDEX.org. I flipped daily-prep's two conditional meeting-prep references, and its trailing changelog claim, to direct links now that the workflow ships as a template.
* docs(task-review): sharpen the :solo: tag definitionCraig Jennings2026-06-101-2/+10
| | | | | | Craig clarified what :solo: means. The old third gate ("the outcome is verifiable locally, no ... confirmation that the result is right") read literally disqualified every task, since Craig spot-checks everything regardless of the tag. It conflated "Craig will also check" with "only Craig can check." The three gates are now buildable, verifiable by Claude, and no upfront decision. The fix is decoupling Craig's routine spot-check from the determination: a task Claude builds and verifies itself, leaving a manual-testing reminder for the residual human-in-the-loop confirmation, is solo. The disqualifier is having no verification path of Claude's own, a result only judgeable by Craig's eyes. task-audit.org Phase C already defers here for the definition, so this is the one edit site.
* feat(daily-prep): add 5-day look-ahead, daily big-ball, and decline gateCraig Jennings2026-06-101-4/+18
| | | | I folded in three additions from the Manager Tools prep research. Phase A now fetches the prep day plus the next 5 days, and a new Phase 1 sub-section scans that window for meetings that need prep, scheduling traps, and focus blocks to protect. It's a scan-and-flag pass that feeds Heads-up and Anchor Tasks, not a new prep-doc section. Phase 3 sub-step 3a pulls one important-but-not-urgent task per day for a 15-minute chunk, so strategic work lands in small daily pieces instead of getting displaced by the urgent. Phase 1 item 5 reframes "attend" as "contribute" and adds a send-regrets gate for meetings with no objective. The look-ahead's meeting-prep references stay conditional ("where the project has one") since meeting-prep is project-only for now.
* docs(create-workflow): document the supporting-document conventionCraig Jennings2026-06-102-1/+9
| | | | A workflow that outgrows its inline content stores the overflow in a sibling <workflow>.<suffix>.org, linked inline. This reuses the engine.plugin dot-glob, so the drift-check and discovery glob already treat the file as owned rather than an orphan. It also travels with the workflow on promotion. I extended the INDEX drift-check note to name supporting docs alongside source plugins.
* docs(spec-review): check generated config resolves where consumedCraig Jennings2026-06-101-1/+1
| | | | A generated config gets read in a different namespace than the one that wrote it. Build host, chroot, image runtime, target system, container, and VM are distinct, so a path valid where the config is generated can be absent where it's read. I added the check to the Architecture & maintainability dimension.
* feat(workflows): generalize broadcast into announcement + situational modesCraig Jennings2026-06-093-141/+187
| | | | cross-project-broadcast handled tooling and rule announcements but had no shape for the situational case: a life or work event I want every project's agent to know, said once so none is missing context when I next talk to them. I renamed it to broadcast (helper and test alongside) and split it into two modes over the same fan-out plumbing. Announcement keeps the rigid capability template. Situational carries a general-not-comprehensive summary plus a fixed receiving-agent contract: record it in notes.org, hold it time-boxed or standing, apply on the project's own judgment, ask follow-ups at startup. The broadcasting agent does no per-project relevance analysis. Each receiving agent decides what the event means for its own work.
* feat(workflows): add spec-create, the author leg of the spec trioCraig Jennings2026-06-092-0/+199
| | | | spec-create is the front of the spec-create → spec-review → spec-response trio: the author writes a short design spec before non-trivial code, shaped to pass spec-review's readiness gate. It runs a when-to-spec proportionality gate first, then problem-first framing, design with forced alternatives and inline mini-ADR decisions, implementation phases with acceptance criteria and a readiness-dimensions menu, a terseness pass, and a hand-off self-check against the review rubric.
* feat(triage-intake): add Telegram source pluginCraig Jennings2026-06-092-1/+199
| | | | | | | | 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.
* feat(triage-intake): add Signal source pluginCraig Jennings2026-06-082-1/+69
| | | | | | | | 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.
* feat(workflows): promote reusable spec-review checks from emacs-d review passesCraig Jennings2026-06-061-12/+67
| | | | | | I folded the reusable, product-neutral checks from two emacs-d review passes into the canonical spec-review.org, so they survive the startup rsync and reach every project instead of living only in a downstream copy. The additions cover package-readiness and Makefile scope, actionable error strings, observability and diagnostics, long-running performance and failure-mode research, defcustom surface, a documentation plan, architecture weak-point mitigation, simplicity controls, extension/plugin developer experience, comparable-product sentiment, terminal-state discovery, CLI-wrapper value, and rollout/rollback, plus three reviewer principles and a generalizable-question harvesting rule. The promotion is a pure superset. Every change adds or expands a generic check, nothing regresses. Project-specific findings stayed in the source spec. The handoff that asked for this is preserved under docs/design.
* feat(workflows): build implementation tasks on Ready in spec-responseCraig Jennings2026-06-061-0/+19
| | | | | | I added Phase 6 to spec-response: once the author confirms a spec is Ready, file the full implementation-task breakdown in todo.org rather than leave a Ready spec nobody can act on. The phase creates one task per implementation phase, runs a completeness pass against every acceptance criterion and principle rule, marks :solo: only where the agent can build and verify end to end, collects the rest under a Manual-testing task, and defers outward-facing publish steps until the user confirms. This is the author-side complement to spec-review's Phase 6, which emits the drop-in task block. Review produces the block, response files the work.
* feat(startup): run make install in Phase A.0 to link new skillsCraig Jennings2026-06-051-0/+19
| | | | | | | | A skill added to rulesets and pushed reached each machine's files on the next pull, but not its ~/.claude symlink. make install only links what isn't already linked, and a git pull doesn't run it. So a new skill stayed silently uninstalled until someone re-ran make install by hand. The flush skill sat in that gap from 2026-06-02 until a manual install today. I added a make install step right after the Phase A.0 rulesets pull, the step that brings the skill's files in. It's idempotent: skips already-linked targets, links only what's new, and only writes symlinks under ~/.claude and ~/.local/bin. A grep keeps the all-skip case to one quiet line. Link, relink, and WARN lines get surfaced, and a new Phase C bullet handles them: a skill the harness already picked up mid-session is noted as available, one it didn't gets a restart prompt, a non-symlink collision goes to the user. Now "add a skill, commit, push" is enough to reach every machine on the next session. The step also covers a newly-added rule or script, since make install links those too. The canonical template and the .ai/ mirror both carry the change.
* feat(lint-org): reconcile follow-ups on write instead of appendingCraig Jennings2026-06-021-1/+1
| | | | | | | | | | Every run appended a fresh dated "lint-org follow-ups" section with line-number-keyed entries, so the follow-ups file grew an unbounded pile of near-duplicate sections, kept entries whose finding had since resolved, and broke whenever the target file's line numbers shifted. Running an audit against a large todo.org surfaced exactly that drift: dead-link flags pointing at docs that now exist, and three stacked dated runs for one file. Now lint-org rewrites the current file's section from the current run. Findings that no longer reproduce simply are not re-emitted, re-runs dedupe to one section, and entries key on checker plus message with the line as a trailing annotation, so a finding survives line shifts as the same entry. Other files' sections are left intact, and the strip step tolerates the old dated-header shape so existing follow-ups files migrate on first run. This changes the follow-ups file from an append-only log to the current outstanding findings per file. task-audit's Phase C link-hygiene step now also reaps a matching dead-link entry when it fixes or verifies the link, scoped strictly to dead-link entries, so the audit and the follow-ups file stop drifting between lint runs. Five follow-ups tests cover record-by-content, dedupe across runs, drop-on-resolve, and preserve-other-files. Mirrors synced.