Repository navigation
feat(coding-agent): list a large skill catalog one line per skill - #4456
Conversation
|
Measured on a real session (omo 5.1.48 install; "after" = the same tree with this PR's
-6,465 input tokens per request (run 1 totals) on a 101-skill catalog. Correction to the issue text: the "cliff" claim does not hold for this library. Measured with 98 skills, the catalog stays compact because its full render exceeds the existing 48 KiB cap. The 16 KiB description trigger only changes catalogs whose full render fits under 48 KiB (roughly 50-100 skills with ~300-character descriptions), which would otherwise list every full description. Method: same fixed empty cwd, |
…atalog A cut now keeps the description's trigger sentence (Use when/for, MUST USE, Triggers:, Korean triggers) and fills the remaining room with the text around it, at 160 characters; a catalog that still overflows the 48 KiB cap tries 100-character lines before dropping descriptions. The names-only header no longer promises a when-to-use part, and settings.md documents the real thresholds and format. Refs #4449, follow-up #4518.
Removing the lead fill makes the 'what it does, then Use when' case fail. Refs #4449.
…talog-lines # Conflicts: # packages/coding-agent/test/suite/regressions/3483-prompt-goldens.json
Fixes #4449
What
A large skill catalog is listed one line per skill instead of a five-line XML block:
<root>/<name>/SKILL.md(100 of 101 skills on a real catalog), else the path under the root, so every skill stays resolvable through the existing<skill_roots>table; one header line states the rule.Use when/for/whenever ...,MUST USE ...,USE ONLY WHEN,This skill should be used when,Triggers: ...,Korean triggers: ...,Triggers - ...): a cut keeps that sentence whole (or its start, when it alone is longer than the line) and fills the remaining room with the leading what-it-does text, then the text after it, cut at word boundaries. Multi-line descriptions are flattened first, so a trigger on a later line still counts. A catalog whose 160-character lines overflow the 48 KiB cap tries 100-character lines before dropping descriptions.- name [location](no: when to use it). Small catalogs render exactly as before.<available_skills>wrapper and the catalog marker sentence are kept, so the Claude-subscription prompt extractor still finds the block.Measured: when-to-use clause survival vs tokens (review FIX_FIRST at 7da8afe)
Real libraries on a dev machine:
~/.agents/skills(71 skills, 65 with a trigger clause) and the same plus the omo plugin skills (97 skills, 89 with a clause). Tokens are an o200k estimate (js-tiktoken) of the whole rendered skills section. "Whole" = the full trigger sentence appears in the line; "start" = its first 40 characters appear.mainrenders the 71-skill set in full XML (below its thresholds) and the 97-skill set with a 160-character head cut (over the 48 KiB cap). The previous head of this PR (100-character head cut) kept the whole clause for 4 skills.Candidate rules, whole-clause survival / tokens (71-skill set · 97-skill set):
The bar was the 160-character baseline: a clause survives whenever it fits in 160 characters (39/65 and 62/89 clauses are that short). Trigger-first at 160 meets it exactly at the lowest cost of any rule that does; 140 falls to 33/65. A head cut never comes close at any cap.
Tests
test/suite/regressions/4449-compact-skill-catalog-lines.test.ts: onmainboth original cases fail (expected false to be truefor the 16 KiB trigger,expected [] to have a length of 98for the line form). The new table-driven casekeeps the when-to-use clause: $shapecovers 11 description shapes (Use when / Use for / Use this whenever / MUST USE first / USE ONLY WHEN / This skill should be used when / Triggers: / Korean triggers / Triggers - Korean list / trigger on a later line / clause longer than the line). Against the previous head 7da8afe, 11 of 13 cases failed (RED); all 13 pass now (GREEN). It also resolves every listed line back to the skill's file through the roots table. The short-trigger case also asserts that the lead fill survives (the line starts withOperates the deployment toolchain); replacing the lead fill with""makes that case fail.3460-context-file-size-cap.test.tsfor the line form and the new byte threshold. Its 400-skill case also covers the 100-character fallback tier.3483-prompt-goldens.json: onlyprompts.compactchanged, and only between</skill_roots>and</available_skills>. The fixture's two-line descriptions are now flattened ("... verify behavior. Keep the full description."); every other key is byte-identical.docs/settings.mdnow states the real thresholds (16 KiB, 160 characters), the one-line format, and the trigger-sentence rule.git diff --check origin/main...HEAD,bun run check, those tests, andnode scripts/check-pr-changelog.mjs.Follow-up
Run/Load/Call ... for/before/if) can pick imperative prose over the real when-to-use sentence (review LOW 1; 0 misfires on real libraries, synthetic repro in the issue).rewriteSkillsLocations(Anthropic subscription lane) has not rewritten any location since the roots-table aliases landed. It is pre-existing and out of scope here.