Skip to content

Improve skill guidance on text generated by LLM models - #304

Merged
jserv merged 7 commits into
sysprog21:mainfrom
henrybear327:skills/reconcile-and-gate
Aug 17, 2026
Merged

Improve skill guidance on text generated by LLM models#304
jserv merged 7 commits into
sysprog21:mainfrom
henrybear327:skills/reconcile-and-gate

Conversation

@henrybear327

@henrybear327 henrybear327 commented Aug 16, 2026

Copy link
Copy Markdown
Collaborator

Improve the guidance for comment, skill, and documentation writing.


Summary by cubic

Gates skill references in the build and tightens prose rules across the repo. Old: skills could cite stale files and markdown allowed em dashes; new: check-skill-refs validates typeset paths/targets/sections in SKILL.md and references/*.md (including indented fenced blocks), and conventions ban U+2014 and the broader machine-written register across comments, docs, commits, and PRs.

  • scripts/check-skill-refs.py: resolves references/*.md beside the file and skill root before the tree, recognizes paths and make commands inside fenced blocks at any indentation (directory+extension required for paths), treats inline backticked spans with slashes as paths (not skills), rejects fd.c/h, uses is_file() to avoid directory false-positives, repoints targets to mk/verify.mk, checks references/*.md themselves, extends self-tests (synthetic skills, sibling refs, indented-fence cases), and trims duplicate comments/docstrings without changing behavior.

  • Build: mk/tests.mk adds check-skill-refs to make check and runs --self-test first; clones without .claude/skills exit 0 with a note. mk/help.mk replaces the banner em dash with a colon.

  • Conventions: .claude/skills/elfuse-conventions/SKILL.md centralizes style for all prose surfaces; bans U+2014 and machine-written register classes; clarifies per-clone working docs and exclusions.

  • Required action: run make check and fix any check-skill-refs findings. Stop using U+2014 and other banned register in comments, commit messages, docs, PR bodies, and reviews.

Written for commit 045b186. Summary will update on new commits.

Review in cubic

@henrybear327
henrybear327 requested a review from jserv August 16, 2026 21:15
@henrybear327 henrybear327 self-assigned this Aug 16, 2026
@henrybear327 henrybear327 changed the title Improve skill guidance on model text generation Improve skill guidance on text generated by LLM models Aug 16, 2026
cubic-dev-ai[bot]

This comment was marked as resolved.

A skill that splits its detail into references/ could not name any of
it. tree_paths() prunes .claude, so every backticked references/x.md
read as a stale pointer to a file sitting beside the skill that wrote
it. Resolution now tries the file's own directory and the skill root
before the tree, which also covers one skill citing another's SKILL.md.
Each candidate has to be a file: resolve() matches against tree_paths(),
which lists files only, and a bare existence test would let a directory
named like a reference satisfy a pointer here and nowhere else.

Three narrower gaps went with it. A path inside a fenced block carries
no backticks and was invisible, so a checklist could name a deleted
script; a fenced path is recognized when it carries a directory
component, which keeps build/elfuse and ./binary out of it. Fences count
at any indentation, since a fence inside a numbered step sits at that
step's content column and a column-0 anchor skipped those blocks whole.
The make-command pattern loses that anchor too, because finding the
block is not enough while the command inside it still has to start at
column 0. An inline span holding a slash is a path rather than a skill
name, so cmd/elfuse-container no longer reads as a skill that went
missing. And the references/ files are checked themselves, since a
citation rots there exactly as fast.

Each class has a self-test case, watched failing with its own fix
reverted: sibling resolution with the skill root removed from the
search, the indented-fence cases with either anchor restored, and the
directory case with the existence test back.
Splitting mk/analysis.mk into verify.mk, lint.mk, and format.mk left
check-skill-refs.py naming the old makefile twice, in the docstring and
above the target check it describes. Both are prose rather than a
typeset reference, so the script cannot report them, which is why they
outlived the rename the same script exists to catch. The skills
themselves were repointed when the split landed.
@henrybear327
henrybear327 force-pushed the skills/reconcile-and-gate branch from 9cb1020 to 4948c6e Compare August 16, 2026 21:40
The check existed and nothing called it, which is how the verify skill
came to name a makefile that had been split two commits earlier. It sits
beside check-syscall-coverage, the other gate that reads a file the
compiler never sees.

The target runs the checker twice, self-test first. Every case in that
self-test is a class of stale reference the script once shipped past,
and behind a flag the assertions run only when somebody remembers to
type it. The extra run costs 0.65s, against a target that builds and
runs the test matrix.

The module docstring gains what the mode does, since a reader meeting it
in the build has no reason to know the flag reads no skill file at all.
self_test() narrows to the one thing that account leaves out, where its
cases came from, and the case shape stays where it belongs, above the
list it describes.

A clone without .claude/skills exits 0 with a note, so this does not
make the build depend on files a clone may not carry. The self-test arm
holds there too: it builds its fixtures in a temporary directory and
reads the skills directory not at all, watched passing with SKILL_DIR
pointed at a name that does not exist.
Three statements described one contributor's checkout as though every
clone had it. The working docs were named individually and one of them
was declared to win wherever it and this file disagree, which resolves
to nothing on a clean checkout, where docs/ and these skills are all a
contributor gets. claudedocs/ was described as ignored through
.git/info/exclude, so a reader following it lands an untracked directory
in git status and reads that as correct.

Working docs are now described as a per-clone habit nobody else touches,
the conventions defer to none of them, and Layout says where a report
goes and which of the two exclusion mechanisms is the per-clone one.
The ASCII rule exempted markdown wholesale, so the character most
likely to mark prose as machine-written was permitted everywhere a
contributor actually writes prose: docs/ and these skill files are
markdown. It has been rejected on sight (PR#209). The rule now names
every surface, the stand-in, and the codepoint spelling that keeps the
grep for the character from matching the sentence forbidding it.

The em dash is only the sharpest tell in a wider register: inflation
words, empty pivots, coined vocabulary, trailing -ing glosses, negative
parallelism, rule-of-three padding, signposting, effort claims,
narrating the change rather than the thing, and invisible-character
artifacts date prose the same way. The catalogue is one line per class
and the only place a class is stated, so a per-surface section names
its own instance and nothing else. The invisible class gets its own
scan, because legitimate Unicode lives in docs/.

The one instance the tree carried goes with it: the make help banner
has printed an em dash since the initial import, and a colon is what
the gloss wanted.
Comments, docs/, commit bodies, and PR threads are the surfaces a
contributor writes prose on, and the rules for them arrived as two
commits that each rediscovered the same classes. The history ban was
written twice, once for comments and once for docs/; the ban on coined
nouns was written twice, once as "coined metaphors" and once as
"invented vocabulary"; figurative accounting was stated only under
commit messages although it binds a comment the same way. Two spellings
of one rule drift apart, and a reader cannot tell whether the
difference is deliberate.

The classes now live in Style, which already claimed every surface, and
each section carries only its own instance: the doorbell that does not
ring for comments, the rejected reply shapes and their citations for
pull requests, the diagram rule for commit messages. The checkability
list under commit messages loses two of its four entries that way, and
the two that remain read as a sentence, which is the shape the register
rules ask for.

Four classes no section covered come in with them, each one met in this
tree: signposting and prompt echo, a closing sentence that grades the
change instead of stating a fact, an effort claim standing in for a
result, and flattery in a review reply. They are drawn from the
sloptrim catalogue, https://github.com/seyedehsanhadi/sloptrim, which
the skill does not cite, because a skill has to stand on its own in a
fresh clone.

Two of that catalogue's classes are false alarms here and stay out.
Title Case headings are house style in docs/, and its sentence-length
and paragraph-rhythm statistics say nothing about a body wrapped at 72
columns.
@henrybear327
henrybear327 force-pushed the skills/reconcile-and-gate branch from 4948c6e to 87549e0 Compare August 16, 2026 21:56
The comments in check-skill-refs.py told most reasons twice: a decision
argued in a constant's comment and again at its call site, an example
spelled out after the rule it illustrates, and a module docstring
narrating how the sidecar.c reference was found on top of naming it.

Every fact survives. What goes is the second telling, the asides
addressed to the reader, and the discovery narrative that belongs in a
commit message rather than in a file somebody opens to change the code.
229 lines of comment and docstring become 169.

The register rules this branch states for comments and docs bind a
script under scripts/ the same way.

Verified: the docstring-stripped ASTs of the two revisions are equal, so
nothing outside comments moved, and the same comparison reports a
difference when a comparison operator in check_paths() is mutated.
@jserv
jserv merged commit 3541d18 into sysprog21:main Aug 17, 2026
18 of 19 checks passed
@henrybear327
henrybear327 deleted the skills/reconcile-and-gate branch August 17, 2026 04:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants