<feed xmlns='http://www.w3.org/2005/Atom'>
<title>rulesets/claude-templates, 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-13T18:23:18+00:00</updated>
<entry>
<title>feat(workflows): add inbox-zero for routing the roam inbox by project</title>
<updated>2026-06-13T18:23:18+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-13T18:23:18+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=651b65e25c2dd13a5a371f1de91e17a41d906a84'/>
<id>urn:sha1:651b65e25c2dd13a5a371f1de91e17a41d906a84</id>
<content type='text'>
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 &lt;project&gt;: 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.
</content>
</entry>
<entry>
<title>feat(workflows): skeptical review gate for inbox change proposals</title>
<updated>2026-06-13T01:04:05+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-13T01:04:05+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=19829305721a327d07b6fe5b6dfba5bf34c8ed37'/>
<id>urn:sha1:19829305721a327d07b6fe5b6dfba5bf34c8ed37</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>feat(workflows): SUPERSEDED/CANCELLED decision states + old-model gate</title>
<updated>2026-06-13T00:33:12+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-13T00:33:12+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=22edacfd03de68eabd96d9aaa98a4dd5693535a6'/>
<id>urn:sha1:22edacfd03de68eabd96d9aaa98a4dd5693535a6</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>feat(workflows): spec decisions become org TODO/DONE tasks</title>
<updated>2026-06-13T00:15:15+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-13T00:15:15+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=7c052535f371c67956947a5afe711c71350feaf4'/>
<id>urn:sha1:7c052535f371c67956947a5afe711c71350feaf4</id>
<content type='text'>
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.
</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>chore: delete the page-signal pager wrapper</title>
<updated>2026-06-12T20:26:22+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-12T20:26:22+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=13256aad033f84c0854f2d562685ea808a5ec619'/>
<id>urn:sha1:13256aad033f84c0854f2d562685ea808a5ec619</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>fix(todo-cleanup): keep --archive-done silent on a real-mode no-op</title>
<updated>2026-06-12T20:26:22+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-12T20:26:22+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=21ab10ef9e2fff9b4726695036e95e33937e1fa9'/>
<id>urn:sha1:21ab10ef9e2fff9b4726695036e95e33937e1fa9</id>
<content type='text'>
The wrap runs --archive-done twice (wrap-it-up, then open-tasks.org Phase A). The first pass archives and reports. The second finds nothing and used to print "0 subtree(s) moved", which reads as alarming next to the first pass's diff. Now a real-mode run that moves nothing and skips nothing says nothing. Check mode still previews "0 would move", and a missing-section skip still reports, since those are conditions the caller needs.
</content>
</entry>
<entry>
<title>docs(task-audit): add tag-vocabulary enforcement and verify-then-close</title>
<updated>2026-06-12T12:30:57+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-12T12:30:57+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=fbeef0c83b15eb7a82cdb8c2b999e232e4f997b6'/>
<id>urn:sha1:fbeef0c83b15eb7a82cdb8c2b999e232e4f997b6</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>fix(scripts): lint-org pre-registers runtime org link types</title>
<updated>2026-06-12T07:28:43+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-12T07:28:43+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=1dba35cc182691390d80c789502b174292b14777'/>
<id>urn:sha1:1dba35cc182691390d80c789502b174292b14777</id>
<content type='text'>
mu4e registers its link type in a live Emacs, so batch org-lint parsed [[mu4e:msgid:...]] links as fuzzy heading refs and flagged "Unknown fuzzy location" on links that work interactively. lint-org now registers each type in lo-runtime-link-types as a no-op before linting. org-link-set-parameters merges rather than replaces, so a genuinely loaded mu4e keeps its real parameters.
</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>
</feed>
