fix(skills): scope the ten loosest descriptions - #66
Conversation
A coherence audit found two authoring generations in the language-skill
descriptions. Eighteen state their scope precisely — concrete triggers,
implicit-phrasing examples, and an explicit "Do NOT trigger for X (use
`Y`)" boundary. Twelve did not, and they were almost exactly the twelve
shortest: 254-427 rendered chars against 671-987 for the rest.
The gap is not cosmetic. The description is all a harness sees when
deciding whether to load a skill, so a description that names no boundary
competes for every request its keywords touch.
The sharpest case was Elixir and Erlang: 0.59 trigger overlap, the
highest in the fleet, with neither excluding the other. Both fired on
"OTP", "supervisor", "processes", "message passing", "let it crash" and
"BEAM concurrency" — different languages with different APIs
(gen_server vs GenServer), indistinguishable on any query that named the
runtime rather than the language. Gleam already declined both and warned
that generic BEAM advice "gets them wrong"; neither reciprocated.
Ten descriptions rewritten to the pattern the other eighteen use, with
triggers drawn from what each skill actually documents rather than
invented: Task.async_stream/3 and ExUnit for Elixir, gen_statem and ETS
and rebar3 for Erlang, errgroup and pprof for Go, comptime and
std.Thread.Pool for Zig, __close and the stylua/selene toolchain for Lua,
finalAttrs and nixfmt-rfc-style for Nix, `mut` and config.nu for Nu,
contracts and record merging for Nickel, Loop_Variant and Global/Depends
for Ada, parking_lot and spawn_blocking for Rust.
Two of the twelve are deliberately excluded:
* microsoft-rust-guidelines is *designed* to be universal — "MANDATORY
for ANY Rust action". A boundary clause would contradict its purpose.
* spacecraft-brand-guidelines belongs to the palette cluster, not the
language family; its scope question is palette authority and is
handled with that work.
Two skills needed a plane statement rather than a language boundary,
which is the honest fix for their overlap:
* spacecraft-rust-guidelines now says to load microsoft-rust-guidelines
FIRST as the mandatory base and that it stacks conditionally on top,
never as the front door — matching the precedence rules its own body
already carries but its description never surfaced.
* spacecraft-nu-guidelines now says it governs Nu code you author while
spacecraft-cli-shell owns whether a one-off command is syntactically
correct for the shell that runs it. Both legitimately claim Nushell;
they differ by plane, and neither said so.
A nickel/nix boundary was considered and checked before being written:
neither skill references the other anywhere, so the clause states a true
language boundary rather than a relationship inferred from nothing.
One regression caught by re-probing after the rewrite: dropping "message
passing" from both BEAM descriptions left the phrase matching no skill at
all. Narrowing too far is its own failure, so it was restored to both —
they now carry mutual exclusions, so triggering and self-resolving beats
not triggering.
The unqualified "write an OTP supervisor" query still reaches all three
BEAM skills, which is correct and unavoidable: nothing in that phrase
names a language. What changed is that each now tells the reader how to
resolve it instead of competing in silence.
All ten land between 699 and 936 rendered chars, none within the 40-char
warning margin of the §5.6 cap. Bundles rebuilt; inventory, frontmatter,
license, cross-reference and description-cap gates pass; drift sweep
clean.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5f12bab7b2
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| catch_unwind, false sharing, lock contention, or benchmarking a hot path. Load `microsoft-rust- | ||
| guidelines` FIRST — it is the mandatory base for any Rust work; this skill stacks on top of it |
There was a problem hiding this comment.
Keep the prerequisite skill ID unbroken
When YAML renders this folded scalar, the newline between microsoft-rust- and guidelines becomes a space, so agents see the nonexistent identifier microsoft-rust- guidelines. On Rust concurrency requests that rely on this explicit chain, the mandatory base skill cannot be resolved; keep the identifier together on one line or wrap before it.
AGENTS.md reference: AGENTS.md:L478-L480
Useful? React with 👍 / 👎.
A coherence audit found two authoring generations in the language-skill descriptions. Eighteen state their scope precisely — concrete triggers, implicit-phrasing examples, and an explicit
Do NOT trigger for X (use Y)boundary. Twelve did not, and they were almost exactly the twelve shortest:The gap isn't cosmetic. The description is all a harness sees when deciding whether to load a skill, so one that names no boundary competes for every request its keywords touch.
The sharpest case
elixir↔erlanghad 0.59 trigger overlap — the highest in the fleet — with neither excluding the other. Both fired onOTP,supervisor,processes,message passing,let it crash,BEAM concurrency: different languages with different APIs (gen_servervsGenServer), indistinguishable on any query naming the runtime rather than the language.gleamalready declined both and warned that generic BEAM advice "gets them wrong" for its typed OTP. Neither reciprocated.What changed
Ten descriptions rewritten to the pattern the other eighteen use, with triggers drawn from what each skill actually documents rather than invented —
Task.async_stream/3and ExUnit for Elixir,gen_statem/ETS/rebar3 for Erlang,errgroup/pprof for Go,comptime/std.Thread.Poolfor Zig,__closeand the stylua/selene toolchain for Lua,finalAttrs/nixfmt-rfc-stylefor Nix,mut/config.nufor Nu, contracts and record merging for Nickel,Loop_Variant/Global/Dependsfor Ada,parking_lot/spawn_blockingfor Rust.Two deliberately excluded
microsoft-rust-guidelinesis designed to be universal — "MANDATORY for ANY Rust action". A boundary clause would contradict its purpose.spacecraft-brand-guidelinesbelongs to the palette cluster, not the language family. Its scope question is palette authority, handled with that work.Two needed a plane statement, not a language boundary
spacecraft-rust-guidelinesnow says to loadmicrosoft-rust-guidelinesfirst as the mandatory base, and that it stacks conditionally on top, never as the front door — surfacing precedence rules its own body already carried but its description never exposed.spacecraft-nu-guidelinesnow says it governs Nu code you author, whilespacecraft-cli-shellowns whether a one-off command is syntactically correct for the shell that runs it. Both legitimately claim Nushell; they differ by plane, and neither said so.One boundary checked before writing
A
nickel/nixclause was considered and verified first — neither skill references the other anywhere in the tree, so the clause states a true language boundary rather than a relationship inferred from nothing.A regression I caught by re-probing
Dropping
message passingfrom both BEAM descriptions left that phrase matching no skill at all. Narrowing too far is its own failure, so it was restored to both — they now carry mutual exclusions, so triggering-and-self-resolving beats not triggering.What is deliberately not fixed
The unqualified query
"write an OTP supervisor"still reaches all three BEAM skills. That is correct and unavoidable — nothing in that phrase names a language. What changed is that each skill now tells the reader how to resolve it instead of competing in silence:Verification
Bundles rebuilt for all ten in the same commit. No skill body changed — descriptions only.
🤖 Generated with Claude Code