<feed xmlns='http://www.w3.org/2005/Atom'>
<title>rulesets/.ai/scripts/lint-org.el, 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-12T07:28:43+00:00</updated>
<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>fix(scripts): lint-org resolves wrap-org-table from its own directory</title>
<updated>2026-06-11T19:58:59+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-11T19:58:59+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=6f575e64b1e9f5d9332db73b1e6427d500f90f48'/>
<id>urn:sha1:6f575e64b1e9f5d9332db73b1e6427d500f90f48</id>
<content type='text'>
Consumers load lint-org with a bare -l and no load-path flag, so the new require of wrap-org-table failed everywhere outside make test's -L. lint-org now adds its own directory to load-path first. lint-org-cli.bats locks the bare-load contract for both scripts.
</content>
</entry>
<entry>
<title>feat(org): table standard as a rule, reflow helper, and lint check</title>
<updated>2026-06-11T19:25:55+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-11T19:25:55+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=8d790f371e54a8cc3e79a5ce72cd4dd5b3fa4513'/>
<id>urn:sha1:8d790f371e54a8cc3e79a5ce72cd4dd5b3fa4513</id>
<content type='text'>
Wide org tables overflow the page in exported PDF/docx, and hand-wrapping a cell into continuation rows is tedious and error-prone. The standard existed only as a work-project convention with nothing enforcing it.

claude-rules/org-tables.md carries the generalized standard: 120-column budget measured at render width (a link counts as its visible label and is never split), over-budget cells wrap onto continuation rows, and a rule sits under the header and every logical row.

wrap-org-table.el reflows a table to that shape mechanically. Columns shrink from natural width toward a floor of their widest atomic token, cells wrap link-safe, and rule-delimited continuation groups merge back into their logical row before re-wrapping, which makes the reflow idempotent. A table whose floors still exceed the budget reflows best-effort and stays flagged for restructuring.

lint-org.el gains an org-table-standard judgment check: width overruns and missing rules surface during the sweep with a pointer to the helper. Conformant wrapped tables don't false-flag, since the check reuses the helper's continuation-group reading. The check is judgment-only by design: reflowing is a visible layout change the sweep shouldn't make silently.
</content>
</entry>
<entry>
<title>feat(lint-org): reconcile follow-ups on write instead of appending</title>
<updated>2026-06-03T02:31:37+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-06-03T02:31:37+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=ac693a6b7fa7abe88f7778f8e793d5ddfd32f24e'/>
<id>urn:sha1:ac693a6b7fa7abe88f7778f8e793d5ddfd32f24e</id>
<content type='text'>
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.
</content>
</entry>
<entry>
<title>fix(lint-org): suppress verbatim-asterisk misplaced-heading false positives</title>
<updated>2026-05-30T22:20:24+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-30T22:20:24+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=1f79945dd4ab386a9ea4ac58fb2161c174a26bba'/>
<id>urn:sha1:1f79945dd4ab386a9ea4ac58fb2161c174a26bba</id>
<content type='text'>
org-lint reads an =** Foo= verbatim span in body prose as a possible misplaced heading, but verbatim markup is never a real heading. lint-org kept surfacing these as judgment items, so they recurred in lint-followups.org on every wrap and could never be acted on, since the todo.org content was already correct.

I added lo--verbatim-asterisk-at-line-p, which mirrors the markdown-bold detector: it checks the reported line and the one before it, since org-lint marks the blank line after the offender. A match is now suppressed silently, the same way the cj-comment false positives already are. I flipped the two tests that pinned the old judgment behavior, and confirmed todo.org lints clean (judgment=0). This resolves the checker-bug report I filed in the inbox earlier, which I removed.
</content>
</entry>
<entry>
<title>chore(ai): sync lint-org and wrap-it-up from claude-templates</title>
<updated>2026-05-16T16:59:40+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-16T16:59:40+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=70af2a019e7592089d33a0dde4a1af699175f7ef'/>
<id>urn:sha1:70af2a019e7592089d33a0dde4a1af699175f7ef</id>
<content type='text'>
Project .ai/ mirror catches up to two canonical updates already in claude-templates/:

- lint-org cj-comment block suppression (3fb4c80). The =#+begin_src cj: ...= annotation pattern triggered three lint categories (suspicious-language, empty-header-argument, wrong-header-argument) as false positives at todo.org:16 and todo.org:1291. lint-org.el now recognizes the opener and skips all three on those lines.

- LINT_ORG_FOLLOWUPS default flipped to =./inbox/lint-followups.org= (684891d). The previous hardcoded default routed every project's wrap-up findings into the work project's inbox.

Phase A startup rsync brought both into the project mirror this morning; bundled into one chore commit since neither delta is project-specific work.
</content>
</entry>
<entry>
<title>chore(ai): sync lint-org script and wrap-it-up from claude-templates</title>
<updated>2026-05-14T23:45:48+00:00</updated>
<author>
<name>Craig Jennings</name>
<email>c@cjennings.net</email>
</author>
<published>2026-05-14T23:45:48+00:00</published>
<link rel='alternate' type='text/html' href='https://git.cjennings.net/rulesets/commit/?id=f5b8688aed8ec698220a67c2dbfbcae22e7575f4'/>
<id>urn:sha1:f5b8688aed8ec698220a67c2dbfbcae22e7575f4</id>
<content type='text'>
Byte-identical pull of .ai/scripts/lint-org.el,
.ai/scripts/tests/test-lint-org.el, and the new Step 3 lint section in
.ai/workflows/wrap-it-up.org. Upstream: claude-templates 138f35f (feat)
and 4eba98c (docs).
</content>
</entry>
</feed>
