@vibe-agent-toolkit/agent-skills 0.1.41-rc.7 → 0.1.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/dist/content-type-routing.d.ts +18 -1
  2. package/dist/content-type-routing.d.ts.map +1 -1
  3. package/dist/content-type-routing.js +17 -0
  4. package/dist/content-type-routing.js.map +1 -1
  5. package/dist/evidence/build-evidence.d.ts +38 -0
  6. package/dist/evidence/build-evidence.d.ts.map +1 -0
  7. package/dist/evidence/build-evidence.js +60 -0
  8. package/dist/evidence/build-evidence.js.map +1 -0
  9. package/dist/evidence/index.d.ts +1 -0
  10. package/dist/evidence/index.d.ts.map +1 -1
  11. package/dist/evidence/index.js +1 -0
  12. package/dist/evidence/index.js.map +1 -1
  13. package/dist/files-config.d.ts +225 -31
  14. package/dist/files-config.d.ts.map +1 -1
  15. package/dist/files-config.js +445 -123
  16. package/dist/files-config.js.map +1 -1
  17. package/dist/index.d.ts +8 -6
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +10 -4
  20. package/dist/index.js.map +1 -1
  21. package/dist/post-build-checks.d.ts +10 -1
  22. package/dist/post-build-checks.d.ts.map +1 -1
  23. package/dist/post-build-checks.js +55 -6
  24. package/dist/post-build-checks.js.map +1 -1
  25. package/dist/schemas/index.d.ts +3 -2
  26. package/dist/schemas/index.d.ts.map +1 -1
  27. package/dist/schemas/index.js +2 -2
  28. package/dist/schemas/index.js.map +1 -1
  29. package/dist/schemas/installed-plugins-registry.d.ts +137 -63
  30. package/dist/schemas/installed-plugins-registry.d.ts.map +1 -1
  31. package/dist/schemas/installed-plugins-registry.js +94 -6
  32. package/dist/schemas/installed-plugins-registry.js.map +1 -1
  33. package/dist/schemas/known-marketplaces-registry.d.ts +165 -100
  34. package/dist/schemas/known-marketplaces-registry.d.ts.map +1 -1
  35. package/dist/schemas/known-marketplaces-registry.js +108 -21
  36. package/dist/schemas/known-marketplaces-registry.js.map +1 -1
  37. package/dist/schemas/registry-drift.d.ts +53 -0
  38. package/dist/schemas/registry-drift.d.ts.map +1 -0
  39. package/dist/schemas/registry-drift.js +50 -0
  40. package/dist/schemas/registry-drift.js.map +1 -0
  41. package/dist/skill-packager.d.ts +75 -5
  42. package/dist/skill-packager.d.ts.map +1 -1
  43. package/dist/skill-packager.js +304 -50
  44. package/dist/skill-packager.js.map +1 -1
  45. package/dist/skill-source/git-clone.d.ts.map +1 -1
  46. package/dist/skill-source/git-clone.js +32 -11
  47. package/dist/skill-source/git-clone.js.map +1 -1
  48. package/dist/skill-test/eval-inputs.js +2 -2
  49. package/dist/skill-test/eval-inputs.js.map +1 -1
  50. package/dist/skill-test/eval-lint.js +2 -2
  51. package/dist/skill-test/eval-lint.js.map +1 -1
  52. package/dist/skill-test/grader-prompt.js +2 -2
  53. package/dist/skill-test/grader-prompt.js.map +1 -1
  54. package/dist/test-input.d.ts +59 -24
  55. package/dist/test-input.d.ts.map +1 -1
  56. package/dist/test-input.js +77 -16
  57. package/dist/test-input.js.map +1 -1
  58. package/dist/validators/agent-instruction-presence.d.ts +41 -0
  59. package/dist/validators/agent-instruction-presence.d.ts.map +1 -0
  60. package/dist/validators/agent-instruction-presence.js +79 -0
  61. package/dist/validators/agent-instruction-presence.js.map +1 -0
  62. package/dist/validators/bundled-resource-link-detection.d.ts +20 -3
  63. package/dist/validators/bundled-resource-link-detection.d.ts.map +1 -1
  64. package/dist/validators/bundled-resource-link-detection.js +78 -34
  65. package/dist/validators/bundled-resource-link-detection.js.map +1 -1
  66. package/dist/validators/compat-detectors.d.ts +9 -4
  67. package/dist/validators/compat-detectors.d.ts.map +1 -1
  68. package/dist/validators/compat-detectors.js +18 -30
  69. package/dist/validators/compat-detectors.js.map +1 -1
  70. package/dist/validators/index.d.ts +1 -0
  71. package/dist/validators/index.d.ts.map +1 -1
  72. package/dist/validators/index.js +1 -0
  73. package/dist/validators/index.js.map +1 -1
  74. package/dist/validators/packaging-validator.d.ts +68 -10
  75. package/dist/validators/packaging-validator.d.ts.map +1 -1
  76. package/dist/validators/packaging-validator.js +51 -10
  77. package/dist/validators/packaging-validator.js.map +1 -1
  78. package/dist/validators/registry-validator.d.ts.map +1 -1
  79. package/dist/validators/registry-validator.js +28 -7
  80. package/dist/validators/registry-validator.js.map +1 -1
  81. package/dist/validators/rule-engine/rule-context.d.ts +4 -2
  82. package/dist/validators/rule-engine/rule-context.d.ts.map +1 -1
  83. package/dist/validators/rule-engine/rule-context.js.map +1 -1
  84. package/dist/validators/rule-engine/rule-engine.d.ts.map +1 -1
  85. package/dist/validators/rule-engine/rule-engine.js +15 -3
  86. package/dist/validators/rule-engine/rule-engine.js.map +1 -1
  87. package/dist/validators/skill-validator.d.ts.map +1 -1
  88. package/dist/validators/skill-validator.js +16 -10
  89. package/dist/validators/skill-validator.js.map +1 -1
  90. package/dist/validators/source-only-codes.d.ts.map +1 -1
  91. package/dist/validators/source-only-codes.js +1 -0
  92. package/dist/validators/source-only-codes.js.map +1 -1
  93. package/dist/validators/validation-rules.d.ts +135 -17
  94. package/dist/validators/validation-rules.d.ts.map +1 -1
  95. package/dist/validators/validation-rules.js +192 -38
  96. package/dist/validators/validation-rules.js.map +1 -1
  97. package/dist/validators/walker-to-issues.d.ts.map +1 -1
  98. package/dist/validators/walker-to-issues.js +20 -7
  99. package/dist/validators/walker-to-issues.js.map +1 -1
  100. package/dist/walk-link-graph.d.ts +10 -1
  101. package/dist/walk-link-graph.d.ts.map +1 -1
  102. package/dist/walk-link-graph.js +124 -39
  103. package/dist/walk-link-graph.js.map +1 -1
  104. package/package.json +5 -5
@@ -15,6 +15,13 @@
15
15
  * — because "we stopped shipping it" and "the executor can't read it" must not
16
16
  * be the same guarantee.)
17
17
  *
18
+ * The rule is PROJECT-WIDE, not per-skill: a file that ANY skill declares as its eval
19
+ * suite is test input, and never ships in ANY skill's bundle. Skill A's docs are free
20
+ * to cite skill B's suite as a worked example — that citation is a reference, not a
21
+ * reason to package B's answer key inside A. The invariant "the executor's filesystem
22
+ * contains no answer key" therefore covers every declared suite in the project, not
23
+ * only the subject's own.
24
+ *
18
25
  * This module is the ONE definition of where a skill's test input lives, shared by
19
26
  * every packaging lane, so no lane can answer the question differently.
20
27
  */
@@ -34,8 +41,14 @@ function hasConventionalSuite(skillDir) {
34
41
  // eslint-disable-next-line security/detect-non-literal-fs-filename -- skillDir is VAT's own resolved skill directory
35
42
  return existsSync(safePath.resolve(skillDir, DEFAULT_EVALS_SUBPATH));
36
43
  }
44
+ /** True when `candidate` is inside (or equal to) `dir`. Both are absolute. */
45
+ function isInside(candidate, dir) {
46
+ const c = safePath.resolve(candidate);
47
+ const d = safePath.resolve(dir);
48
+ return c === d || c.startsWith(`${d}/`);
49
+ }
37
50
  /**
38
- * Absolute directories holding a skill's declared test input.
51
+ * Absolute directories holding ONE skill's declared test input.
39
52
  *
40
53
  * The unit is the DIRECTORY containing the suite file (it also holds the suite's
41
54
  * `fixtures/`), except when the suite sits at the skill root — where the "directory"
@@ -56,7 +69,7 @@ function hasConventionalSuite(skillDir) {
56
69
  * root `evals/` holding no `evals.json`. Guessing from the name alone would silently
57
70
  * drop an author's unrelated directory out of their own bundle.
58
71
  */
59
- export function resolveTestInputDirs(config, skillDir) {
72
+ function declaredTestInputDirs(config, skillDir) {
60
73
  if (config.test === undefined && !hasConventionalSuite(skillDir))
61
74
  return [];
62
75
  const subpath = config.test?.evals ?? DEFAULT_EVALS_SUBPATH;
@@ -67,6 +80,55 @@ export function resolveTestInputDirs(config, skillDir) {
67
80
  return [];
68
81
  return [safePath.resolve(skillDir, parent)];
69
82
  }
83
+ /**
84
+ * Absolute directories holding declared test input, from the point of view of the
85
+ * skill being packaged: its OWN suite, plus EVERY other suite the project declares.
86
+ *
87
+ * The cross-skill half is not defensive breadth — it is the same rule applied to the
88
+ * same kind of file. A doc citing another skill's eval suite as a worked example is an
89
+ * entirely reasonable doc, and the link walker follows those citations. Keyed only to
90
+ * the subject, this function called another skill's answer key "ordinary content", so
91
+ * the walker bundled it — with no exclusion and no `PACKAGED_TEST_INPUT` receipt,
92
+ * because nothing under the subject's config named that path.
93
+ *
94
+ * Observed ACTIVE on a 90-skill adopter (2026-07-30, `vat skills build`): a built
95
+ * bundle contained a file byte-identical to a DIFFERENT skill's real eval suite,
96
+ * carried under that bundle's own subtree. The answer key shipped. A basename
97
+ * collision between two such suites does not save anyone — a FILENAME_COLLISION is
98
+ * REPORTED, not thrown, and the copy still happens.
99
+ *
100
+ * Nothing else in the pipeline sees it. `LINK_TO_SKILL_DEFINITION` covers only another
101
+ * skill's SKILL.md. And the two mechanisms in THIS module that exist to catch a
102
+ * shipped suite — the `PACKAGED_TEST_INPUT` receipt and the `checkPackagedTestInput`
103
+ * backstop — are both fed the dirs this function returns, so while those dirs were the
104
+ * subject's alone, both were structurally blind to another skill's suite. That is why
105
+ * the fix has to be a project-level INPUT here rather than another check downstream.
106
+ *
107
+ * `projectSkills` may include the skill being packaged; dirs are deduplicated, and the
108
+ * subject's own come first. It is REQUIRED, with no default: a defaulted parameter made
109
+ * every pre-existing caller silently keep the per-skill behaviour, so the rule above
110
+ * was written down and shipped as a no-op. A lane that genuinely cannot enumerate the
111
+ * project's skills passes `[]` at the call site, where the narrowing is visible and has
112
+ * to be justified in a comment — it can no longer happen by omission.
113
+ *
114
+ * SCOPE OF THE CROSS-SKILL HALF — another skill's suite dir travels to this build only
115
+ * when it lies INSIDE that skill's own directory. A `test.evals` pointing at a SHARED
116
+ * directory already strips that whole directory from the declaring skill's bundle
117
+ * (issue #166); honouring it project-wide would turn one skill's over-broad
118
+ * declaration into a project-wide strip of a directory no single skill owns. The
119
+ * declaring skill's own build is unchanged — the `config`/`skillDir` pair above is
120
+ * still taken at face value — so this narrows nothing that worked before.
121
+ */
122
+ export function resolveTestInputDirs(config, skillDir, projectSkills) {
123
+ const dirs = new Set(declaredTestInputDirs(config, skillDir));
124
+ for (const skill of projectSkills) {
125
+ for (const dir of declaredTestInputDirs(skill.config, skill.skillDir)) {
126
+ if (isInside(dir, skill.skillDir))
127
+ dirs.add(dir);
128
+ }
129
+ }
130
+ return [...dirs];
131
+ }
70
132
  /**
71
133
  * The test-input dirs VAT actually excludes links for: those inside the project
72
134
  * root. A dir outside it yields no exclude rule — the walker already refuses to
@@ -103,12 +165,6 @@ export function testInputExcludeRules(testInputDirs, projectRoot) {
103
165
  }
104
166
  return patterns.length === 0 ? [] : [{ patterns }];
105
167
  }
106
- /** True when `candidate` is inside (or equal to) `dir`. Both are absolute. */
107
- function isInside(candidate, dir) {
108
- const c = safePath.resolve(candidate);
109
- const d = safePath.resolve(dir);
110
- return c === d || c.startsWith(`${d}/`);
111
- }
112
168
  /**
113
169
  * Split `files:` entries into those that may be packaged and those that point into
114
170
  * declared test input and therefore must not be.
@@ -139,8 +195,8 @@ export function partitionTestInputFileEntries(filesConfig, projectRoot, testInpu
139
195
  return { kept, dropped };
140
196
  }
141
197
  /**
142
- * The `files:` entries that will ACTUALLY be packaged for a skill, derived from the
143
- * skill's own config: {@link resolveTestInputDirs} + the `kept` half of
198
+ * The `files:` entries that will ACTUALLY be packaged for a skill:
199
+ * {@link resolveTestInputDirs} + the `kept` half of
144
200
  * {@link partitionTestInputFileEntries}.
145
201
  *
146
202
  * Every lane that models "which `dest` paths will exist after the build" must build
@@ -151,16 +207,20 @@ export function partitionTestInputFileEntries(filesConfig, projectRoot, testInpu
151
207
  * and fails. Same input, opposite verdicts, in two commands that are supposed to
152
208
  * agree. The packager is the authority on what ships; this is how the read-only
153
209
  * lanes borrow its answer instead of guessing.
210
+ *
211
+ * `projectSkills` is forwarded to {@link resolveTestInputDirs}, so a `files:` entry
212
+ * pointing at ANOTHER skill's declared suite is dropped here too. Required for the
213
+ * same reason it is required there — see that function's note on the no-op default.
154
214
  */
155
- export function packagedFileEntries(config, skillDir, projectRoot) {
156
- return partitionTestInputFileEntries(config.files ?? [], projectRoot, resolveTestInputDirs(config, skillDir)).kept;
215
+ export function packagedFileEntries(config, skillDir, projectRoot, projectSkills) {
216
+ return partitionTestInputFileEntries(config.files ?? [], projectRoot, resolveTestInputDirs(config, skillDir, projectSkills)).kept;
157
217
  }
158
218
  /** A `PACKAGED_TEST_INPUT` receipt per dropped `files:` entry — a warning, not a failure. */
159
219
  export function testInputFileEntryIssues(dropped) {
160
220
  return dropped.map((entry) => materializeIssue('PACKAGED_TEST_INPUT', {
161
221
  location: toForwardSlash(entry.dest),
162
222
  message: `files: entry "${toForwardSlash(entry.source)} -> ${toForwardSlash(entry.dest)}" points into ` +
163
- `this skill's declared test input (test.evals) and was NOT packaged — test input, ` +
223
+ `declared test input (some skill's test.evals) and was NOT packaged — test input, ` +
164
224
  `including the expected_output answer key, never ships to consumers.`,
165
225
  }));
166
226
  }
@@ -200,9 +260,10 @@ export function testInputLinkIssues(excluded, testInputDirs, projectRoot, locati
200
260
  seen.add(location);
201
261
  issues.push(materializeIssue('PACKAGED_TEST_INPUT', {
202
262
  location,
203
- message: `Link "${ref.linkHref ?? location}" points into this skill's declared test input ` +
204
- `(test.evals). The target is NOT packaged — test input, including the expected_output ` +
205
- `answer key, never ships to consumers — so the link is removed from the packaged output.`,
263
+ message: `Link "${ref.linkHref ?? location}" points into declared test input (some skill's ` +
264
+ `test.evals — its own or another skill's). The target is NOT packaged — test input, ` +
265
+ `including the expected_output answer key, never ships to consumers — so the link is ` +
266
+ `removed from the packaged output.`,
206
267
  }));
207
268
  }
208
269
  return issues;
@@ -1 +1 @@
1
- {"version":3,"file":"test-input.js","sourceRoot":"","sources":["../src/test-input.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"test-input.js","sourceRoot":"","sources":["../src/test-input.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Presence-side detection for repo-internal agent-instruction files.
3
+ *
4
+ * `LINK_TO_AGENT_INSTRUCTION_FILE` catches the *reference* — a packaged doc
5
+ * linking a `CLAUDE.md` — and the walker then keeps that file out of the
6
+ * bundle. It cannot catch the other half: a file that arrives in the
7
+ * distributed artifact without any link at all. The plugin lane tree-copies its
8
+ * `source:` directory verbatim, so a `CLAUDE.md` sitting beside `plugin.json`
9
+ * ships to every consumer, and the orphan check does not object because plugin
10
+ * artifacts are exempt from skill reachability rules by design.
11
+ *
12
+ * This detector reads the built tree directly, so it is blind to how the file
13
+ * got there. That is the point: link-following, `files:` globs, and verbatim
14
+ * tree-copies are three routes into a bundle, and only the first is visible to
15
+ * the walker.
16
+ */
17
+ import { type ValidationIssue } from '@vibe-agent-toolkit/agent-schema';
18
+ /**
19
+ * Report every repo-internal agent-instruction file present in a distributed
20
+ * tree.
21
+ *
22
+ * @param rootDir Absolute path to the tree to scan (a packaged skill output
23
+ * directory, or a plugin directory about to be published).
24
+ * @param locationRoot Anchor base for reported locations. Pass the run's stated
25
+ * root, not `rootDir`, when the two differ — a location the reader cannot
26
+ * open is worse than no location.
27
+ * @param declaredDests Skill-output-relative dests named by EXPLICIT (non-glob)
28
+ * `files:` entries — {@link explicitFilesConfigDests}. Such a dest is NOT
29
+ * reported: naming a file in config is an unambiguous instruction to ship it,
30
+ * and this finding's remediation is "remove the file", i.e. undo what the
31
+ * config sanctioned. Callers that cannot know the config (an installed
32
+ * third-party bundle, a plugin tree with no `files:` block) pass `[]` — the
33
+ * honest answer, since intent is genuinely unknowable there.
34
+ *
35
+ * REQUIRED, not defaulted: every caller must state its answer, or a lane that
36
+ * silently inherits `[]` re-opens the contradiction for the population it
37
+ * governs. Matching is EXACT membership, never a prefix test — a directory-ish
38
+ * dest must not launder its whole subtree (see {@link explicitFilesConfigDests}).
39
+ */
40
+ export declare function detectPackagedAgentInstructionFiles(rootDir: string, locationRoot: string, declaredDests: readonly string[]): ValidationIssue[];
41
+ //# sourceMappingURL=agent-instruction-presence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-instruction-presence.d.ts","sourceRoot":"","sources":["../../src/validators/agent-instruction-presence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAcxE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,mCAAmC,CACjD,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,SAAS,MAAM,EAAE,GAC/B,eAAe,EAAE,CA8BnB"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Presence-side detection for repo-internal agent-instruction files.
3
+ *
4
+ * `LINK_TO_AGENT_INSTRUCTION_FILE` catches the *reference* — a packaged doc
5
+ * linking a `CLAUDE.md` — and the walker then keeps that file out of the
6
+ * bundle. It cannot catch the other half: a file that arrives in the
7
+ * distributed artifact without any link at all. The plugin lane tree-copies its
8
+ * `source:` directory verbatim, so a `CLAUDE.md` sitting beside `plugin.json`
9
+ * ships to every consumer, and the orphan check does not object because plugin
10
+ * artifacts are exempt from skill reachability rules by design.
11
+ *
12
+ * This detector reads the built tree directly, so it is blind to how the file
13
+ * got there. That is the point: link-following, `files:` globs, and verbatim
14
+ * tree-copies are three routes into a bundle, and only the first is visible to
15
+ * the walker.
16
+ */
17
+ import { existsSync } from 'node:fs';
18
+ import { crawlDirectorySync, issueLocation, safePath } from '@vibe-agent-toolkit/utils';
19
+ import { normalizeRelPath } from '../files-config.js';
20
+ import { materializeIssue } from './rule-engine/index.js';
21
+ import { AGENT_INSTRUCTION_FILE_PATTERNS, toAnyDepthGlobs } from './validation-rules.js';
22
+ /**
23
+ * Match each basename at the tree root AND at any depth — the root is the case
24
+ * that matters most (a `CLAUDE.md` beside `plugin.json` is the observed defect).
25
+ */
26
+ const INCLUDE_GLOBS = toAnyDepthGlobs(AGENT_INSTRUCTION_FILE_PATTERNS);
27
+ /**
28
+ * Report every repo-internal agent-instruction file present in a distributed
29
+ * tree.
30
+ *
31
+ * @param rootDir Absolute path to the tree to scan (a packaged skill output
32
+ * directory, or a plugin directory about to be published).
33
+ * @param locationRoot Anchor base for reported locations. Pass the run's stated
34
+ * root, not `rootDir`, when the two differ — a location the reader cannot
35
+ * open is worse than no location.
36
+ * @param declaredDests Skill-output-relative dests named by EXPLICIT (non-glob)
37
+ * `files:` entries — {@link explicitFilesConfigDests}. Such a dest is NOT
38
+ * reported: naming a file in config is an unambiguous instruction to ship it,
39
+ * and this finding's remediation is "remove the file", i.e. undo what the
40
+ * config sanctioned. Callers that cannot know the config (an installed
41
+ * third-party bundle, a plugin tree with no `files:` block) pass `[]` — the
42
+ * honest answer, since intent is genuinely unknowable there.
43
+ *
44
+ * REQUIRED, not defaulted: every caller must state its answer, or a lane that
45
+ * silently inherits `[]` re-opens the contradiction for the population it
46
+ * governs. Matching is EXACT membership, never a prefix test — a directory-ish
47
+ * dest must not launder its whole subtree (see {@link explicitFilesConfigDests}).
48
+ */
49
+ export function detectPackagedAgentInstructionFiles(rootDir, locationRoot, declaredDests) {
50
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- rootDir is a validated build-output path
51
+ if (!existsSync(rootDir))
52
+ return [];
53
+ const declared = new Set(declaredDests.map((d) => normalizeRelPath(d)));
54
+ // `respectGitignore: false` and an empty `exclude` are both load-bearing: the
55
+ // subject is BUILT output, which normally lives under a gitignored `dist/`
56
+ // that the crawler's defaults would skip entirely — the scan would pass by
57
+ // scanning nothing.
58
+ const files = crawlDirectorySync({
59
+ baseDir: rootDir,
60
+ include: INCLUDE_GLOBS,
61
+ exclude: [],
62
+ absolute: true,
63
+ filesOnly: true,
64
+ respectGitignore: false,
65
+ });
66
+ const issues = [];
67
+ for (const file of files) {
68
+ // The declaration is expressed relative to the SCANNED tree (a `files:` dest is
69
+ // skill-output-relative), while the reported location is relative to
70
+ // `locationRoot` — the two roots differ whenever a batching caller anchors
71
+ // elsewhere, so the exemption test must use rootDir and never the location.
72
+ if (declared.has(normalizeRelPath(safePath.relative(rootDir, file))))
73
+ continue;
74
+ const location = issueLocation(file, locationRoot);
75
+ issues.push(materializeIssue('PACKAGED_AGENT_INSTRUCTION_FILE', { location, detail: location }));
76
+ }
77
+ return issues;
78
+ }
79
+ //# sourceMappingURL=agent-instruction-presence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-instruction-presence.js","sourceRoot":"","sources":["../../src/validators/agent-instruction-presence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAGrC,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAExF,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,+BAA+B,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAEzF;;;GAGG;AACH,MAAM,aAAa,GAAG,eAAe,CAAC,+BAA+B,CAAC,CAAC;AAEvE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,mCAAmC,CACjD,OAAe,EACf,YAAoB,EACpB,aAAgC;IAEhC,+GAA+G;IAC/G,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,EAAE,CAAC;IAEpC,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAExE,8EAA8E;IAC9E,2EAA2E;IAC3E,2EAA2E;IAC3E,oBAAoB;IACpB,MAAM,KAAK,GAAG,kBAAkB,CAAC;QAC/B,OAAO,EAAE,OAAO;QAChB,OAAO,EAAE,aAAa;QACtB,OAAO,EAAE,EAAE;QACX,QAAQ,EAAE,IAAI;QACd,SAAS,EAAE,IAAI;QACf,gBAAgB,EAAE,KAAK;KACxB,CAAC,CAAC;IAEH,MAAM,MAAM,GAAsB,EAAE,CAAC;IACrC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,gFAAgF;QAChF,qEAAqE;QACrE,2EAA2E;QAC3E,4EAA4E;QAC5E,IAAI,QAAQ,CAAC,GAAG,CAAC,gBAAgB,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;YAAE,SAAS;QAC/E,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;QACnD,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,iCAAiC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;IACnG,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -2,13 +2,30 @@
2
2
  * Bundled-resource link detector.
3
3
  *
4
4
  * Emits SKILL_REFERENCES_BUT_NO_LINKS at info severity when a skill
5
- * directory contains scripts/, references/, or assets/ subdirectories
6
- * but neither SKILL.md's body nor any transitively linked file points
7
- * into them via a markdown link.
5
+ * directory contains a bundled subdirectory (the content-type routing
6
+ * categories plus the claude-web `references/` layout) holding files that
7
+ * neither SKILL.md's body nor any transitively linked file points at.
8
8
  *
9
9
  * Plugin-dev's "Mistake 4: Missing Resource References" — bundled assets
10
10
  * the body never links to are dead weight in the install. The author
11
11
  * intended progressive disclosure but forgot to wire up the references.
12
+ *
13
+ * Two properties are load-bearing:
14
+ *
15
+ * 1. **The vocabulary is derived, never re-listed.** A hardcoded list drifts
16
+ * from `content-type-routing.ts` — which routes `.md` and every unknown
17
+ * extension to `resources/` — and a subdirectory missing from the list
18
+ * makes the detector structurally unable to fire on it.
19
+ *
20
+ * 2. **Coverage is per file, not per directory.** A single live mention must
21
+ * not mask dead siblings: the real `command-development` skill ships 7
22
+ * files under `references/` and mentions only 2 of them, and a
23
+ * directory-granular check reported nothing at all.
24
+ *
25
+ * A file counts as referenced when its skill-relative path appears anywhere
26
+ * in the body — markdown link target, inline code span, or bare prose alike —
27
+ * or when link traversal reached it. Fenced code blocks are deliberately NOT
28
+ * parsed out: that approach was tried and rejected as too fragile.
12
29
  */
13
30
  import { type ValidationIssue } from '@vibe-agent-toolkit/agent-schema';
14
31
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"bundled-resource-link-detection.d.ts","sourceRoot":"","sources":["../../src/validators/bundled-resource-link-detection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAsDvF;;;;;GAKG;AACH,wBAAgB,iCAAiC,CAC/C,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,YAAY,EAAE,MAAM,GACnB,eAAe,EAAE,CAuBnB"}
1
+ {"version":3,"file":"bundled-resource-link-detection.d.ts","sourceRoot":"","sources":["../../src/validators/bundled-resource-link-detection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAOH,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,kCAAkC,CAAC;AA4EvF;;;;;GAKG;AACH,wBAAgB,iCAAiC,CAC/C,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,YAAY,EAAE,MAAM,GACnB,eAAe,EAAE,CAgCnB"}
@@ -2,20 +2,50 @@
2
2
  * Bundled-resource link detector.
3
3
  *
4
4
  * Emits SKILL_REFERENCES_BUT_NO_LINKS at info severity when a skill
5
- * directory contains scripts/, references/, or assets/ subdirectories
6
- * but neither SKILL.md's body nor any transitively linked file points
7
- * into them via a markdown link.
5
+ * directory contains a bundled subdirectory (the content-type routing
6
+ * categories plus the claude-web `references/` layout) holding files that
7
+ * neither SKILL.md's body nor any transitively linked file points at.
8
8
  *
9
9
  * Plugin-dev's "Mistake 4: Missing Resource References" — bundled assets
10
10
  * the body never links to are dead weight in the install. The author
11
11
  * intended progressive disclosure but forgot to wire up the references.
12
+ *
13
+ * Two properties are load-bearing:
14
+ *
15
+ * 1. **The vocabulary is derived, never re-listed.** A hardcoded list drifts
16
+ * from `content-type-routing.ts` — which routes `.md` and every unknown
17
+ * extension to `resources/` — and a subdirectory missing from the list
18
+ * makes the detector structurally unable to fire on it.
19
+ *
20
+ * 2. **Coverage is per file, not per directory.** A single live mention must
21
+ * not mask dead siblings: the real `command-development` skill ships 7
22
+ * files under `references/` and mentions only 2 of them, and a
23
+ * directory-granular check reported nothing at all.
24
+ *
25
+ * A file counts as referenced when its skill-relative path appears anywhere
26
+ * in the body — markdown link target, inline code span, or bare prose alike —
27
+ * or when link traversal reached it. Fenced code blocks are deliberately NOT
28
+ * parsed out: that approach was tried and rejected as too fragile.
12
29
  */
13
30
  /* eslint-disable security/detect-non-literal-fs-filename -- skill paths validated upstream */
14
31
  import { existsSync, readFileSync, readdirSync } from 'node:fs';
15
32
  import { dirname } from 'node:path';
16
33
  import { CODE_REGISTRY } from '@vibe-agent-toolkit/agent-schema';
17
34
  import { issueLocation, safePath } from '@vibe-agent-toolkit/utils';
18
- const BUNDLED_SUBDIRS = ['scripts', 'references', 'assets'];
35
+ import { CLAUDE_WEB_REFERENCES_SUBDIR, TARGET_SUBDIR_CATEGORIES } from '../content-type-routing.js';
36
+ /**
37
+ * Subdirectories a packaged skill may bundle resources into.
38
+ *
39
+ * Derived from the content-type routing categories (the single source of
40
+ * truth for extension→subdirectory mapping) plus the claude-web-specific
41
+ * `references/` layout name. De-duplicated so promoting `references` to a
42
+ * routing category later cannot produce a doubled finding.
43
+ */
44
+ const BUNDLED_SUBDIRS = [
45
+ ...new Set([...TARGET_SUBDIR_CATEGORIES, CLAUDE_WEB_REFERENCES_SUBDIR]),
46
+ ];
47
+ /** How many dead file names the message spells out before summarising. */
48
+ const MAX_LISTED_FILES = 5;
19
49
  /** Read SKILL.md content (best-effort) — empty string if unreadable. */
20
50
  function readSkillContent(skillPath) {
21
51
  try {
@@ -25,40 +55,51 @@ function readSkillContent(skillPath) {
25
55
  return '';
26
56
  }
27
57
  }
28
- /** Subdirectory exists AND contains at least one file (recursive). */
29
- function isNonEmptyDir(dir) {
58
+ /**
59
+ * Every file under `dir`, recursively, as paths relative to `baseDir`
60
+ * (forward-slash normalised by safePath). Empty when `dir` is absent,
61
+ * unreadable, or contains no files.
62
+ */
63
+ function listFilesRelative(dir, baseDir) {
30
64
  if (!existsSync(dir))
31
- return false;
65
+ return [];
66
+ const found = [];
32
67
  try {
33
- const entries = readdirSync(dir, { withFileTypes: true });
34
- for (const entry of entries) {
35
- if (entry.isFile())
36
- return true;
37
- if (entry.isDirectory() && isNonEmptyDir(safePath.join(dir, entry.name))) {
38
- return true;
68
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
69
+ const child = safePath.join(dir, entry.name);
70
+ if (entry.isFile()) {
71
+ found.push(safePath.relative(baseDir, child));
72
+ }
73
+ else if (entry.isDirectory()) {
74
+ found.push(...listFilesRelative(child, baseDir));
39
75
  }
40
76
  }
41
77
  }
42
78
  catch {
43
- return false;
79
+ return [];
44
80
  }
45
- return false;
81
+ return found;
46
82
  }
47
- /** Body or linked file references the subdir via path containing `<sub>/`. */
48
- function bodyMentionsSubdir(body, sub) {
49
- // Lightweight check: the sub-dir name occurs as part of a markdown
50
- // path, e.g. `(scripts/cli.mjs)` or `[x](references/detail.md)`. We
51
- // accept any occurrence of `<sub>/` since false negatives (a real
52
- // link the heuristic misses) are worse than false positives at info.
53
- return body.includes(`${sub}/`);
83
+ /**
84
+ * Body points at this file.
85
+ *
86
+ * Substring match on the skill-relative path, so `[x](references/a.md)`,
87
+ * `(./references/a.md)`, `` `references/a.md` `` and a bare prose
88
+ * `references/a.md` all count. Deliberately liberal: at info severity a
89
+ * missed finding beats a wrong one.
90
+ */
91
+ function bodyMentionsFile(body, relPath) {
92
+ return body.includes(relPath);
93
+ }
94
+ /** Link traversal reached this exact file. */
95
+ function linkedFilesCoverFile(linkedFiles, absPath) {
96
+ return linkedFiles.has(safePath.resolve(absPath));
54
97
  }
55
- /** Linked file path is inside the subdir. */
56
- function linkedFilesCoverSubdir(linkedFiles, skillDir, sub) {
57
- const subDir = safePath.join(skillDir, sub);
58
- return linkedFiles.some((f) => {
59
- const rel = safePath.relative(subDir, f);
60
- return !rel.startsWith('..') && rel.length > 0;
61
- });
98
+ /** Human-readable file list, truncated so the message stays scannable. */
99
+ function summariseFiles(relPaths) {
100
+ const shown = relPaths.slice(0, MAX_LISTED_FILES).join(', ');
101
+ const hidden = relPaths.length - MAX_LISTED_FILES;
102
+ return hidden > 0 ? `${shown} (and ${hidden} more)` : shown;
62
103
  }
63
104
  /**
64
105
  * @param skillPath Absolute path to SKILL.md
@@ -70,19 +111,22 @@ export function detectBundledResourceWithoutLinks(skillPath, skillDir, linkedFil
70
111
  const issues = [];
71
112
  const body = readSkillContent(skillPath);
72
113
  const baseDir = skillDir.length > 0 ? skillDir : dirname(skillPath);
114
+ const linked = new Set(linkedFiles.map((f) => safePath.resolve(f)));
73
115
  for (const sub of BUNDLED_SUBDIRS) {
74
116
  const subPath = safePath.join(baseDir, sub);
75
- if (!isNonEmptyDir(subPath))
76
- continue;
77
- if (bodyMentionsSubdir(body, sub))
117
+ const bundled = listFilesRelative(subPath, baseDir);
118
+ if (bundled.length === 0)
78
119
  continue;
79
- if (linkedFilesCoverSubdir(linkedFiles, baseDir, sub))
120
+ const unreferenced = bundled.filter((rel) => !bodyMentionsFile(body, rel) && !linkedFilesCoverFile(linked, safePath.join(baseDir, rel)));
121
+ if (unreferenced.length === 0)
80
122
  continue;
81
123
  const entry = CODE_REGISTRY.SKILL_REFERENCES_BUT_NO_LINKS;
82
124
  issues.push({
83
125
  severity: entry.defaultSeverity,
84
126
  code: 'SKILL_REFERENCES_BUT_NO_LINKS',
85
- message: `Skill directory contains "${sub}/" but no markdown link from SKILL.md or linked files points into it.`,
127
+ message: `Skill directory contains "${sub}/" with ${unreferenced.length} of ${bundled.length} ` +
128
+ `file(s) that nothing in SKILL.md or its linked files points at: ` +
129
+ `${summariseFiles(unreferenced)}.`,
86
130
  location: issueLocation(subPath, locationRoot),
87
131
  fix: entry.fix,
88
132
  reference: entry.reference,
@@ -1 +1 @@
1
- {"version":3,"file":"bundled-resource-link-detection.js","sourceRoot":"","sources":["../../src/validators/bundled-resource-link-detection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bundled-resource-link-detection.js","sourceRoot":"","sources":["../../src/validators/bundled-resource-link-detection.ts"],"names":[],"mappings":"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"}
@@ -15,14 +15,19 @@ export interface DetectorOutput {
15
15
  evidence: EvidenceRecord[];
16
16
  observations: Observation[];
17
17
  }
18
- export declare function collectLocalShellEvidence(content: string, filePath: string): EvidenceRecord[];
19
- export declare function collectExternalCLIEvidence(content: string, filePath: string): EvidenceRecord[];
20
- export declare function collectBrowserAuthEvidence(content: string, filePath: string): EvidenceRecord[];
18
+ export declare function collectLocalShellEvidence(content: string, filePath: string, locationRoot: string): EvidenceRecord[];
19
+ export declare function collectExternalCLIEvidence(content: string, filePath: string, locationRoot: string): EvidenceRecord[];
20
+ export declare function collectBrowserAuthEvidence(content: string, filePath: string, locationRoot: string): EvidenceRecord[];
21
21
  export declare function deriveObservations(evidence: readonly EvidenceRecord[]): Observation[];
22
22
  /**
23
23
  * Convert a capability Observation into a ValidationIssue using the
24
24
  * default severity, fix, and reference from CODE_REGISTRY.
25
25
  */
26
26
  export declare function observationToIssue(obs: Observation, location: string): ValidationIssue;
27
- export declare function runCompatDetectors(content: string, filePath: string): DetectorOutput;
27
+ /**
28
+ * @param locationRoot - The ONE base every emitted evidence `location.file` is
29
+ * expressed relative to. Required, so a producer cannot emit an absolute
30
+ * location by omission.
31
+ */
32
+ export declare function runCompatDetectors(content: string, filePath: string, locationRoot: string): DetectorOutput;
28
33
  //# sourceMappingURL=compat-detectors.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"compat-detectors.d.ts","sourceRoot":"","sources":["../../src/validators/compat-detectors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAiC,KAAK,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAEvG,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AA8BxE,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,YAAY,EAAE,WAAW,EAAE,CAAC;CAC7B;AAoED,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,cAAc,EAAE,CA+C7F;AASD,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,cAAc,EAAE,CA4B9F;AAED,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,cAAc,EAAE,CAe9F;AAQD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,SAAS,cAAc,EAAE,GAAG,WAAW,EAAE,CAKrF;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,GAAG,eAAe,CAWtF;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,cAAc,CAQpF"}
1
+ {"version":3,"file":"compat-detectors.d.ts","sourceRoot":"","sources":["../../src/validators/compat-detectors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAiC,KAAK,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAEvG,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AA2BxE,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,YAAY,EAAE,WAAW,EAAE,CAAC;CAC7B;AA6CD,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,GACnB,cAAc,EAAE,CAkDlB;AASD,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,GACnB,cAAc,EAAE,CA6BlB;AAED,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,GACnB,cAAc,EAAE,CAgBlB;AAQD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,SAAS,cAAc,EAAE,GAAG,WAAW,EAAE,CAKrF;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,GAAG,eAAe,CAWtF;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,GACnB,cAAc,CAQhB"}