test: share one skill-structure lint across the four plugin suites - #714
Merged
Conversation
The lint existed four times and test-utils.ts was byte-identical in three plugins, so parser fixes never propagated: only feed's copy folded YAML block scalars, meaning a `description: >-` in any dev/fitness/forge skill would have failed lint as "too short". tests/lib/skill-lint.ts now owns the shared checks with feed's parser, and lintSkills returns failures rather than exiting, so the console-runner suites and feed's bun:test both consume it without touching forge's shared-runner constraint. Per-plugin files keep only their expectations and genuinely plugin-specific checks. The four plugin workflows plus the cross-plugin one now trigger on tests/lib/**, which previously matched no path filter at all.
The shared lint's frontmatter parser stopped folding a block scalar at the first blank line, silently truncating a multi-paragraph description to its first paragraph — latent for today's skills, but this parser now backs four plugin suites. tsconfig also excluded tests/, so the module's own test file was never type-checked.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The skill-structure lint existed in four copies and
tests/test-utils.tswas byte-identical (md51ffd9c8f9149eb75ff6f86b886f5e4f2) in dev, fitness, and forge. Because the copies drifted independently, parser improvements never propagated: only feed's version folded YAML block scalars, so adescription: >-in any dev/fitness/forge skill would have been read as the literal>-and failed lint as "description too short". This extracts the shared checks into one repo-root module and adopts feed's parser as the shared one.Monorepo dev tooling only — never shipped to operators, which is why it may live at the repo root and cross plugin boundaries (same territory as
tests/cross-plugin/). No CHANGELOG entries: root-scope and test-only changes aren't something an operator experiences.Changes
tests/lib/skill-lint.ts—parseFrontmatter(dev's{raw, fields, body}shape + feed's block-scalar folding),makeReporter(moved verbatim from the deleted copies), andlintSkills(pluginRoot, skills).lintSkillsis pure: it returns failure messages and never prints or exits, so both the console-reporter suites (dev/fitness/forge, which run each lint as its ownbunprocess) and feed'sbun testconsume it without touching forge's shared-runner constraint.${CLAUDE_PLUGIN_ROOT}/scripts/dangling-reference check, fitness its CLAUDE-APPEND trim guard, forge its PHP-floor assertion; feed's first loop now callslintSkillsand its local parser is gone.test-utils.tscopies deleted, with all five importers repointed.tests/lib/**added to the path filters oftest-dev,test-fitness,test-forge,test-feed, andtest-cross-plugin; previously an edit to shared test code matched no filter and ran in zero suites. The cross-plugin job also runstests/lib/.Side effect worth noting: feed's per-skill checks previously asserted only
name/description; routing throughlintSkillsalso applies the gate-count and internal-link checks to its skills. That's an expansion of what CI enforces for that plugin, consistent with the other three.Test plan
All run and green on the rebased branch:
bash tests/run-all.shinclaude-code-dev-hermit(13 passed),claude-code-fitness-hermit(129 passed),laravel-forge-hermit(13 passed, incl. PHP suite) — exit 0 eachbun testinfeed-hermit— 54 passedbun test tests/lib/ tests/cross-plugin/— 110 passedbunx tsc --noEmitfrom repo root (strict) — exit 0dev-prexpectation from 5 gates to 4 fails withdev-pr: expected 4 Gate headers, found 5; reverted and green