Filed out-of-scope from #7358 (widening check-skills-paths's scan root). Unassigned.
What
scripts/check-shell-escape-residue.mjs declares:
exportconstSCAN_ROOTS=Object.freeze([{spec: 'AGENTS.md',kind: 'file',minFiles: 1},{spec: 'CLAUDE.md',kind: 'file',minFiles: 1},{spec: 'skills',kind: 'dir',minFiles: 5},{spec: 'content/docs',kind: 'dir',minFiles: 100},]);skills is a directory root, so before #7251 it covered skills/objectui/guides/console-development.md and skills/objectui/rules/no-touch-zones.md. #7251 moved both to .claude/skills/objectui-contributor/, which no row reaches. Same move, same class as #7358, a different gate.
Measured on main@0614b6df1
Its own verdict line today:
check-shell-escape-residue: OK (4/4 root(s) resolved -- AGENTS.md: 1 file(s), 15 fence(s);
CLAUDE.md: 1 file(s), 2 fence(s); skills: 16 file(s), 196 fence(s);
content/docs: 185 file(s), 1071 fence(s); ...)
Fenced blocks now outside every root:
| file | fenced blocks | was under skills before #7251 |
|---|
.claude/skills/objectui-contributor/guides/console-development.md | 9 | yes |
.claude/skills/objectui-contributor/rules/no-touch-zones.md | 9 | yes |
.claude/skills/verify/SKILL.md | 2 | no — never covered |
.claude/skills/objectui-contributor/SKILL.md | 0 | no — never covered |
So 18 fenced blocks left the surface in the move, and 2 more have never been on it.
Why the floor did not catch it
The skills row carries minFiles: 5 and the tree still holds 16 files, so the floor stayed satisfied while two files walked off. That is the same whole-surface-floor blindness #7358 found in check-skills-paths, where a checked floor of 20 was cleared by the 27 assertions still under skills while 55 sat unscanned. #7358's fix judges emptiness per root for exactly this reason; a minFiles row here is already per-root, but a per-root floor only measures the roots that are declared, never the tree that left.
Not a duplicate of
Suggested shape, not prescribed
Add a .claude/skills dir row with its own minFiles, then clear whatever the widened surface reports — the discipline this repo's other scan-surface widenings follow (#3479 / #3490 / #3545, and #7358's own measurement table). Whether .claude/** belongs on this gate at all is the decision to make first: these files are contributor-facing rather than published, and the residue class this gate exists to catch is machine-produced shell escaping, which is just as likely in a guide an agent writes.
Filed out-of-scope from #7358 (widening
check-skills-paths's scan root). Unassigned.What
scripts/check-shell-escape-residue.mjsdeclares:skillsis a directory root, so before #7251 it coveredskills/objectui/guides/console-development.mdandskills/objectui/rules/no-touch-zones.md. #7251 moved both to.claude/skills/objectui-contributor/, which no row reaches. Same move, same class as #7358, a different gate.Measured on
main@0614b6df1Its own verdict line today:
Fenced blocks now outside every root:
skillsbefore #7251.claude/skills/objectui-contributor/guides/console-development.md.claude/skills/objectui-contributor/rules/no-touch-zones.md.claude/skills/verify/SKILL.md.claude/skills/objectui-contributor/SKILL.mdSo 18 fenced blocks left the surface in the move, and 2 more have never been on it.
Why the floor did not catch it
The
skillsrow carriesminFiles: 5and the tree still holds 16 files, so the floor stayed satisfied while two files walked off. That is the same whole-surface-floor blindness #7358 found incheck-skills-paths, where acheckedfloor of 20 was cleared by the 27 assertions still underskillswhile 55 sat unscanned. #7358's fix judges emptiness per root for exactly this reason; aminFilesrow here is already per-root, but a per-root floor only measures the roots that are declared, never the tree that left.Not a duplicate of
skills/— widen SCAN_ROOT to cover.claude/skills#7358 — the same move, butcheck-skills-paths; that one is being fixed and does not touch this gate.skills/objectui/— 123 TypeScript fences and 63 JSON fences are checked by nothing #7359 — no gate reads inside fences underskills/objectui/; this one is about which files have fences read at all..mdxunder content/docs — 40.mdguides are uncovered with no UNGATED_DOCS entry, contradicting its own "covered by default" rule #5174 —check-doc-snippet-typescollecting only.mdx; same class, different gate and different cause.Suggested shape, not prescribed
Add a
.claude/skillsdir row with its ownminFiles, then clear whatever the widened surface reports — the discipline this repo's other scan-surface widenings follow (#3479 / #3490 / #3545, and #7358's own measurement table). Whether.claude/**belongs on this gate at all is the decision to make first: these files are contributor-facing rather than published, and the residue class this gate exists to catch is machine-produced shell escaping, which is just as likely in a guide an agent writes.