<feed xmlns='http://www.w3.org/2005/Atom'>
<title>rulesets/claude-templates/.ai/workflows, 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-28T16:40:27+00:00</updated>
<entry>
<title>feat(workflows): add code-quality sweep workflow</title>
<updated>2026-06-28T16:40:27+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-28T16:40:27+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=96dfa6394a76994d713ee56c07009d3296de4fda'/>
<id>urn:sha1:96dfa6394a76994d713ee56c07009d3296de4fda</id>
<content type='text'>
A thin orchestrator that runs the behavior-preserving quality passes over a scope of existing code in order: /refactor, then readability-audit, then it surfaces the :refactor: tasks readability filed and any deferred /refactor findings. It leaves /simplify out, since that works the current diff rather than existing code.
</content>
</entry>
<entry>
<title>feat(workflows): add suspend and readability-audit workflows</title>
<updated>2026-06-28T16:24:59+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-28T16:24:59+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=797c4267022699527a5e7c51f67be52e6fac1409'/>
<id>urn:sha1:797c4267022699527a5e7c51f67be52e6fac1409</id>
<content type='text'>
suspend is a capture-only mid-session pause for an abrupt departure: it writes a resume-weighted entry and leaves the session anchor in place, so the next startup resumes from it. It's the capture half. Startup is the resume half. I registered it with its trigger phrases.

readability-audit is a language-agnostic pass over comments, file headers, names, and organization. The cheap comment and name fixes land inline. Structural findings get filed as :refactor: tasks. It feeds /refactor rather than duplicating it.
</content>
</entry>
<entry>
<title>refactor(tasks): use a :blocker: tag, not a :BLOCKS: property</title>
<updated>2026-06-24T11:09:21+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-24T11:09:21+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=9709638f1d50193bd4636205a142a2277f92e4f4'/>
<id>urn:sha1:9709638f1d50193bd4636205a142a2277f92e4f4</id>
<content type='text'>
:BLOCKS: rulesets: was a malformed org tag, and the property form (:BLOCKED_BY: / :BLOCKS: carrying &lt;project&gt;: &lt;what&gt;) was more structure than the dependency needs. The blocking side now carries a plain :blocker: tag, mirroring :blocked: on the waiting side, with the which-project detail in the task body rather than a property. open-tasks.org reads the body for the blocking/requesting project; the scheme, the todo-format convention, and the inbox blocking-dependency handoff all move to the two-tag form. No property anywhere.
</content>
</entry>
<entry>
<title>feat(tasks): make cross-project dependencies bidirectional</title>
<updated>2026-06-24T11:00:48+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-24T11:00:48+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=06b6cbcf086729414ff9a533b1f031fb41c4088b'/>
<id>urn:sha1:06b6cbcf086729414ff9a533b1f031fb41c4088b</id>
<content type='text'>
The :blocked: tag only marked the waiting side, so a blocker could stay unaware it was holding up another project: the dependency was visible to the one project that couldn't act on it and invisible to the one that could. This closes that gap. Setting :blocked: now requires a reciprocal inbox-send to the blocker, which files the work with a :BLOCKS: &lt;project&gt;: &lt;what&gt; property on its side. open-tasks.org surfaces :BLOCKS: tasks first, since clearing one unblocks another project (the highest-leverage pick), the mirror of pulling :blocked: tasks out of the cascade. Inbox process mode recognizes the blocking-dependency handoff shape, and the convention documents the resolution flow (drop :BLOCKS:, notify the waiter, who lifts :blocked:).

This works for any project pair, since the convention (todo-format.md) and the surfacing (open-tasks.org) live in the shared rule and workflow layer, not in one project.

Claude-Session: https://claude.ai/code/session_017PtX1nt1rtYVATuzmzBS4f
</content>
</entry>
<entry>
<title>feat(task-audit): consolidate related tasks into a merge or parent</title>
<updated>2026-06-24T10:34:50+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-24T10:34:50+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=bcfce0e3d48c8ec0214a1ce560764b1f552b1fb4'/>
<id>urn:sha1:bcfce0e3d48c8ec0214a1ce560764b1f552b1fb4</id>
<content type='text'>
Reconciliation keeps each task honest on its own, but a single effort fragmented across several tasks (the agent-agnostic work, say) is hard to see and finish as a whole. Adds Phase C.5: read the open-task set, spot semantic clusters by judgment rather than a brittle keyword match, and propose per cluster either a merge (fold same-work members into one) or a parent-with-children grouping (related-but-distinct members). Proposes, never applies, until Craig picks; broader than Phase C's exact-duplicate fold.

Claude-Session: https://claude.ai/code/session_017PtX1nt1rtYVATuzmzBS4f
</content>
</entry>
<entry>
<title>feat(tasks): surface cross-project dependencies in what's-next</title>
<updated>2026-06-24T10:34:50+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-24T10:34:50+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=4d2f83de2fff3eecaaa96c86301a221d1fe8d708'/>
<id>urn:sha1:4d2f83de2fff3eecaaa96c86301a221d1fe8d708</id>
<content type='text'>
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: &lt;project&gt;: &lt;what&gt; 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
</content>
</entry>
<entry>
<title>feat(inbox): poll-and-retry the capture-guard instead of bouncing</title>
<updated>2026-06-24T09:36:29+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-24T09:36:29+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=1eaec823a9174bb74596a5b008917cdddfc21e6d'/>
<id>urn:sha1:1eaec823a9174bb74596a5b008917cdddfc21e6d</id>
<content type='text'>
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
</content>
</entry>
<entry>
<title>feat(wrap): end the valediction with a "session wrapped." signoff</title>
<updated>2026-06-24T04:42:15+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-24T04:42:15+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=d5cc37c739f91d0806b96180e6f4ddaf028da513'/>
<id>urn:sha1:d5cc37c739f91d0806b96180e6f4ddaf028da513</id>
<content type='text'>
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
</content>
</entry>
<entry>
<title>fix(inbox): stop pulling the roam repo during triage</title>
<updated>2026-06-24T04:07:13+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-24T04:07:13+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=f83d4bbe6772c472f10efb0e298116abd6f97922'/>
<id>urn:sha1:f83d4bbe6772c472f10efb0e298116abd6f97922</id>
<content type='text'>
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
</content>
</entry>
<entry>
<title>feat(wrap): add session teardown and shutdown to wrap-it-up</title>
<updated>2026-06-24T03:34:18+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-24T03:34:18+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=f87f59cc9eb1dd492be5b55870271d67245c1fdd'/>
<id>urn:sha1:f87f59cc9eb1dd492be5b55870271d67245c1fdd</id>
<content type='text'>
A bare "wrap it up" now tears the session down after the valediction: it kills the ai-term buffer and the aiv-&lt;project&gt; 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
</content>
</entry>
</feed>
