<feed xmlns='http://www.w3.org/2005/Atom'>
<title>rulesets/voice, 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-07-28T01:52:02+00:00</updated>
<entry>
<title>docs: file rightsizing follow-up, fix the first-person referent</title>
<updated>2026-07-28T01:52:02+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-07-28T01:52:02+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=16756135ff2b70a47aded26e8ccf33dc249a9f17'/>
<id>urn:sha1:16756135ff2b70a47aded26e8ccf33dc249a9f17</id>
<content type='text'>
I filed the remaining rightsizing work as a DOING task, because what's left is decisions I haven't made rather than work to execute: whether verification.md's honesty core survives the over-verification warning, what to do with interaction.md now that it's the largest rule, whether to cut the TDD rationalization table, and which of my approval gates are preference versus guardrail. The three working docs are a commit behind the two splits, so they get reconciled first.

I also fixed the first-person rule I added earlier today. It said to write in the first person without saying whose voice that is, so it read as an agent narrating work on my behalf. The "I" is mine. I'm the author of record on every commit and review in these repos and they go out under my name, so the voice is me writing about my own work, and an agent never appears in the prose as a separate party. That lives in commits.md, which is symlinked machine-wide, so it covers every project from now on. Pattern #32 in the voice skill carried the same ambiguity and now matches.

I filed work's recurring-loop proposal with three findings, and work's reply corrected the weakest of them. I'd offered either a rare heartbeat or failure-breaks-silence, and both are needed: a failed subagent covers a scan-level failure, but only a heartbeat catches the scheduler dying, since then nothing spawns and there's no failure to report. CronCreate expires recurring jobs after seven days, so a fully silent loop is guaranteed to die quietly.

The session archive covers the day. Always-loaded rules went from about 57,800 tokens to 28,949, path-scoping and the de-duplication were both confirmed against a live session, and two bugs in my own tooling turned up, one of which had killed a work session mid-flight.
</content>
</entry>
<entry>
<title>refactor(rules): split commits.md into invariants plus a publish skill</title>
<updated>2026-07-27T18:58:35+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-07-27T18:58:35+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=931f364864441676eb250cecd074c4876012a1cd'/>
<id>urn:sha1:931f364864441676eb250cecd074c4876012a1cd</id>
<content type='text'>
commits.md was 12,800 tokens, larger than the next four rules combined, and it loaded in every session in every project whether or not anything was being published. Most of it is procedure that only applies when a commit or PR is in play.

I split it by blast radius rather than by size. What stays always-loaded is what must hold whether or not I'm publishing, and where a violation is permanent and reaches other people: author identity, the no-AI-attribution ban, the generated-document byline rule, and the public-artifact content-scope rules. That core is 1,027 words, about 2,342 tokens.

What moved into the publish skill is everything about how a message gets written, reviewed, approved, and published. The pre-flight reconcile, the code-review gate, the draft and voice and approval gate, conventional-commit format, Voice and Focus, PR description structure, the three review shapes, merge strategy, and the pre-commit checklist.

The failure modes are why the line falls there. If the skill doesn't load I don't know the publish flow and have to be told, which is visible and recoverable. I don't silently commit with AI attribution, because that guard never moved. Only the recoverable half is on the skill-triggering bet.

I verified the split by using it. The skill registered mid-session and I invoked it to publish this commit, and it loaded with the flow intact.

Content is conserved: 5,561 words in, 5,898 across both files, the difference being the frontmatter and the pointer I added to the core. I repointed five cross-references in voice, review-code, inbox.org, and no-approvals.org that named sections which moved.

One thing I left alone. The skill is a single 4,871-word file, and both posts argue a long skill should split internally rather than sit as one blob. It loads on demand now, which is the win worth taking today. Splitting it further is its own change.
</content>
</entry>
<entry>
<title>feat(voice): add recipient-priority ordering, calibrate the paragraph rule</title>
<updated>2026-07-24T04:27:33+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-07-24T04:27:33+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=37c6fe6c99ae713177a43cd2416fd8ba64356c72'/>
<id>urn:sha1:37c6fe6c99ae713177a43cd2416fd8ba64356c72</id>
<content type='text'>
Adds pattern #47: in a reply, lead with what matters most to the recipient, not the easiest answer or the order they wrote it. Correspondence-scoped, so it fires on email, Signal, and letters and nowhere else. It's the one pattern that doesn't carry into personal mode, since a commit or PR review isn't a reply to someone's news.

Recalibrates #43 in the same edit. "Shifts angle" now means shifts topic: break between topics, consolidate within one, up to a five-or-six-sentence ceiling. The never-merge line was being read at sentence granularity, which fragmented single topics across paragraphs. #43 and #47 are one rule seen from both sides, the break between topics and the order of them, not a rule in tension with its neighbor.

Both land in SKILL.md and the profile per the pairing rule, with the worked before/after in the profile. From a home session drafting a Signal reply; the design is Craig's.
</content>
</entry>
<entry>
<title>docs(voice): add comma-budget pattern (#46) to personal mode</title>
<updated>2026-07-21T04:27:19+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-07-21T04:27:19+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=2ea5d9a62ad8a28b26715b528ac8eb50a2677926'/>
<id>urn:sha1:2ea5d9a62ad8a28b26715b528ac8eb50a2677926</id>
<content type='text'>
Craig's directive from the 2026-07-20 archsetup session: no sentence in a publish artifact carries more than two commas, enforced in the /voice personal pass. The third comma almost always marks stacked clauses or an inline list doing a paragraph's work. It's a mechanical count the walk can enforce where "don't stack clauses" gets skipped.

Scoped to publish artifacts, so the personal-only set goes four to five. Added to the attestation high-recurrence set at birth: a comma count is cheap to receipt, and new discipline fails silently without one. The profile section carries the before/after from the Hyprland issue draft that prompted the rule.
</content>
</entry>
<entry>
<title>docs(review): drop praise from approve summaries, print inline text at the gate</title>
<updated>2026-07-11T06:56:07+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-07-11T06:56:07+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=99bd213002f2bd24192d15ff9ae69a0379b2f5be'/>
<id>urn:sha1:99bd213002f2bd24192d15ff9ae69a0379b2f5be</id>
<content type='text'>
An approve summary now carries no praise, not even a bare positive like "Clean." or "Solid fix." Lead with the substantive pointer (the design note pinned inline) and close with the verdict. This removes the bare-positive carve-out from review-code's Posted Summary Voice and from voice pattern #40, and updates the worked examples.

The review gate must also print the full prose of every inline comment, never a description of it. The exact words post under my name, so I have to see them before I approve. Made explicit in review-code Phase 5 and commits.md Shape 1.

From a DeepSat review session where I approved "One design note inline, not a blocker. Approving."
</content>
</entry>
<entry>
<title>feat(voice): expand skill to 45 patterns with attestation receipts and artifact budgets</title>
<updated>2026-06-10T15:12:22+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-10T15:12:22+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=571669583e634a90f9c96e7073d5e91658e1119c'/>
<id>urn:sha1:571669583e634a90f9c96e7073d5e91658e1119c</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>fix(voice): make the terse cut a mandatory final pass</title>
<updated>2026-06-05T05:15:31+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-05T05:15:31+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=4779ce8a64560e68b34311ced309013c50706d39'/>
<id>urn:sha1:4779ce8a64560e68b34311ced309013c50706d39</id>
<content type='text'>
Pattern #38 (omit needless words) was one of 41 walked mid-list, so it got glossed as a checkbox instead of the real "cut it in half" sweep. A commit message went out today needing two manual Orwell-walk requests before it read terse, even though /voice personal had run.

The rule already said to cut hard. The gap was position. Buried in the middle of the walk, #38 lost to the categorical detectors that come back clean while the text still runs a third too long.

I moved it to an explicit standalone last step in the SKILL.md Process, run after every other pattern and right before the draft is shown. Now the first draft the user sees is already terse, not terse only after they ask. Profile §38 gains an execution-position rule and a history entry. The commits.md publish gate points at #38 as the last pass.
</content>
</entry>
<entry>
<title>docs(voice): generalize §38 from padding list to omit-needless-words walk</title>
<updated>2026-06-02T18:50:39+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-02T18:50:39+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=a0c98c496635b37c7b60727f55a36ccea30af99e'/>
<id>urn:sha1:a0c98c496635b37c7b60727f55a36ccea30af99e</id>
<content type='text'>
§38 was a wordlist match against named padding ("worth noting", "obviously"). A PR-review comment cleared that list and still ran a third too long on ordinary verbosity the list never names: "is the same change that already merged via" for "landed on", restated subjects, throat-clearing lead-ins. So §38 becomes two passes. The named list runs first, then a real per-sentence sweep whose forcing test is to delete half the sentence and keep only what changes meaning. I renamed "Rhetorical Padding" to "Omit Needless Words" and added a generic-verbosity example pair that carries no padding word. I updated SKILL.md and voice-profile.org together per the pairing rule.
</content>
</entry>
<entry>
<title>docs(voice): Phase 2 corpus findings: email + PR registers added to voice-profile.org</title>
<updated>2026-05-29T23:25:27+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-29T23:25:27+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=7355d21d9a36716afbeeb7d63de58dff302f44c1'/>
<id>urn:sha1:7355d21d9a36716afbeeb7d63de58dff302f44c1</id>
<content type='text'>
Phase 2 of the writing voice corpus adds four sub-corpora to the
profile: personal email (1139 messages, 283k words), work email (22
messages, small sample), PR descriptions (9 PRs), and PR review
comments (3 comments, very small sample). Mu queries on local
maildirs and gh API calls on the cjennings github identity.
Signatures, quoted replies, and forwarded blocks stripped before
analysis. No corpus files written to disk.

The headline finding is the register split. Phase 1's commit-prose
signal does not generalize cleanly. Em-dashes and semicolons are
concentrated in commit prose (3.49 and 3.16 per 1000). Conversational
and PR prose run an order of magnitude lower (em-dash 0.28 in
personal email, 0.00 in PR review comments). Semicolon shows the
same shape (0.64 in personal email, 0.00 in PR comments). The
personal-mode rules on those still earn their place, but the basis
shifts. The rules mostly enforce what is already true for non-commit
registers.

Contractions invert the pattern: commits 3.57 per 1000, personal
email 38.52, PR review comments 50.78. The Phase 1 curiosity (I'm
and I'll surprisingly rare relative to standalone I in commits) is
resolved as a register effect. Personal email shows I'm at 6.04 per
1000 vs standalone I at 36.91, near natural English. Craig's voice
is heavily-contracted in conversational prose and uniquely suppresses
contractions in commit prose. The contraction rule is strongly
confirmed in the registers where contractions are most expected.

Updates land in:
- Top-level Corpus section: a new Phase 2 subsection with the four
  sub-corpora and a cross-register findings table.
- Curiosities (resolved by Phase 2) section: I'm/I'll rarity puzzle
  answered.
- §7 (AI vocabulary) Basis: cross-register watch-word measurements.
  Comprehensive is concentrated in commits. Leverage shows up
  modestly in personal email.
- §13 (em-dash) Basis: register split documented.
- §32 (first-person) Basis: standalone I rates across all five
  registers.
- §33 (semicolon) Basis: register split parallels em-dash.
- §34 (contractions) Basis: register inversion documented, Phase 1
  curiosity resolved.
- §38 (terse cut) Basis: single-sentence-paragraph rate across
  registers, highest in PR descriptions.

AI tells stay near zero across all five corpora. Leverage 18
occurrences in personal email is the only non-zero hit on the
watch-list outside commits.
</content>
</entry>
<entry>
<title>docs(voice): scrub prose em-dashes from voice-profile.org</title>
<updated>2026-05-29T23:03:44+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-29T23:03:44+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=1a795d6147ba15519e8cf934c1b764809f79567f'/>
<id>urn:sha1:1a795d6147ba15519e8cf934c1b764809f79567f</id>
<content type='text'>
This hygiene sweep covers the profile's prose sections (Problem,
Basis, History, Phase 1 findings, Phase 2 list) where em-dashes had
carried over from the original SKILL.md text. 21 prose em-dashes were
replaced with context-appropriate punctuation (periods, colons,
parentheses, or rewords).

Eight em-dashes are preserved as legitimate exceptions: the literal
symbol reference in §13 Rule, §13 Before example (shows source text
with em-dashes), §36 Before example (felt-experience tic), §38
heading "Terse Cut — Rhetorical Padding" (paired with SKILL.md
heading verbatim), §39 Before example (WARN output format), §40
example dialogue (shows what a kind correction reads like).

The profile now follows its own rule for prose voice. The known
follow-up flagged in 10d0bc1's commit message is closed.
</content>
</entry>
</feed>
