@vibe-agent-toolkit/agent-skills 0.1.39-rc.1 → 0.1.39-rc.10

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 (174) hide show
  1. package/dist/files-config.d.ts +83 -7
  2. package/dist/files-config.d.ts.map +1 -1
  3. package/dist/files-config.js +72 -12
  4. package/dist/files-config.js.map +1 -1
  5. package/dist/index.d.ts +5 -1
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +6 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/post-build-checks.d.ts +5 -5
  10. package/dist/post-build-checks.d.ts.map +1 -1
  11. package/dist/post-build-checks.js +119 -61
  12. package/dist/post-build-checks.js.map +1 -1
  13. package/dist/schemas/installed-plugins-registry.d.ts +6 -6
  14. package/dist/skill-packager.d.ts +1 -1
  15. package/dist/skill-packager.d.ts.map +1 -1
  16. package/dist/skill-packager.js +109 -31
  17. package/dist/skill-packager.js.map +1 -1
  18. package/dist/skill-source/content-hash.d.ts +13 -0
  19. package/dist/skill-source/content-hash.d.ts.map +1 -0
  20. package/dist/skill-source/content-hash.js +49 -0
  21. package/dist/skill-source/content-hash.js.map +1 -0
  22. package/dist/skill-source/fetch-cache.d.ts +26 -0
  23. package/dist/skill-source/fetch-cache.d.ts.map +1 -0
  24. package/dist/skill-source/fetch-cache.js +62 -0
  25. package/dist/skill-source/fetch-cache.js.map +1 -0
  26. package/dist/skill-source/git-clone.d.ts +21 -0
  27. package/dist/skill-source/git-clone.d.ts.map +1 -0
  28. package/dist/skill-source/git-clone.js +66 -0
  29. package/dist/skill-source/git-clone.js.map +1 -0
  30. package/dist/skill-source/resolve-skill-source.d.ts +12 -0
  31. package/dist/skill-source/resolve-skill-source.d.ts.map +1 -0
  32. package/dist/skill-source/resolve-skill-source.js +37 -0
  33. package/dist/skill-source/resolve-skill-source.js.map +1 -0
  34. package/dist/skill-source/sources/npm-source.d.ts +22 -0
  35. package/dist/skill-source/sources/npm-source.d.ts.map +1 -0
  36. package/dist/skill-source/sources/npm-source.js +48 -0
  37. package/dist/skill-source/sources/npm-source.js.map +1 -0
  38. package/dist/skill-source/sources/path-source.d.ts +10 -0
  39. package/dist/skill-source/sources/path-source.d.ts.map +1 -0
  40. package/dist/skill-source/sources/path-source.js +17 -0
  41. package/dist/skill-source/sources/path-source.js.map +1 -0
  42. package/dist/skill-source/sources/url-source.d.ts +14 -0
  43. package/dist/skill-source/sources/url-source.d.ts.map +1 -0
  44. package/dist/skill-source/sources/url-source.js +113 -0
  45. package/dist/skill-source/sources/url-source.js.map +1 -0
  46. package/dist/skill-source/sources/vendored-source.d.ts +8 -0
  47. package/dist/skill-source/sources/vendored-source.d.ts.map +1 -0
  48. package/dist/skill-source/sources/vendored-source.js +16 -0
  49. package/dist/skill-source/sources/vendored-source.js.map +1 -0
  50. package/dist/skill-source/sources/workspace-source.d.ts +17 -0
  51. package/dist/skill-source/sources/workspace-source.d.ts.map +1 -0
  52. package/dist/skill-source/sources/workspace-source.js +27 -0
  53. package/dist/skill-source/sources/workspace-source.js.map +1 -0
  54. package/dist/skill-source/stage.d.ts +21 -0
  55. package/dist/skill-source/stage.d.ts.map +1 -0
  56. package/dist/skill-source/stage.js +73 -0
  57. package/dist/skill-source/stage.js.map +1 -0
  58. package/dist/skill-source/types.d.ts +65 -0
  59. package/dist/skill-source/types.d.ts.map +1 -0
  60. package/dist/skill-source/types.js +11 -0
  61. package/dist/skill-source/types.js.map +1 -0
  62. package/dist/skill-test/build-hook.d.ts +58 -0
  63. package/dist/skill-test/build-hook.d.ts.map +1 -0
  64. package/dist/skill-test/build-hook.js +63 -0
  65. package/dist/skill-test/build-hook.js.map +1 -0
  66. package/dist/skill-test/configure-writer.d.ts +31 -0
  67. package/dist/skill-test/configure-writer.d.ts.map +1 -0
  68. package/dist/skill-test/configure-writer.js +39 -0
  69. package/dist/skill-test/configure-writer.js.map +1 -0
  70. package/dist/skill-test/declared-env.d.ts +72 -0
  71. package/dist/skill-test/declared-env.d.ts.map +1 -0
  72. package/dist/skill-test/declared-env.js +85 -0
  73. package/dist/skill-test/declared-env.js.map +1 -0
  74. package/dist/skill-test/evals-template.d.ts +22 -0
  75. package/dist/skill-test/evals-template.d.ts.map +1 -0
  76. package/dist/skill-test/evals-template.js +56 -0
  77. package/dist/skill-test/evals-template.js.map +1 -0
  78. package/dist/skill-test/exit-codes.d.ts +34 -0
  79. package/dist/skill-test/exit-codes.d.ts.map +1 -0
  80. package/dist/skill-test/exit-codes.js +59 -0
  81. package/dist/skill-test/exit-codes.js.map +1 -0
  82. package/dist/skill-test/experimenter-prompt.d.ts +20 -0
  83. package/dist/skill-test/experimenter-prompt.d.ts.map +1 -0
  84. package/dist/skill-test/experimenter-prompt.js +68 -0
  85. package/dist/skill-test/experimenter-prompt.js.map +1 -0
  86. package/dist/skill-test/friction-schema.d.ts +74 -0
  87. package/dist/skill-test/friction-schema.d.ts.map +1 -0
  88. package/dist/skill-test/friction-schema.js +28 -0
  89. package/dist/skill-test/friction-schema.js.map +1 -0
  90. package/dist/skill-test/grading-adapter.d.ts +22 -0
  91. package/dist/skill-test/grading-adapter.d.ts.map +1 -0
  92. package/dist/skill-test/grading-adapter.js +49 -0
  93. package/dist/skill-test/grading-adapter.js.map +1 -0
  94. package/dist/skill-test/grading-schema.d.ts +171 -0
  95. package/dist/skill-test/grading-schema.d.ts.map +1 -0
  96. package/dist/skill-test/grading-schema.js +65 -0
  97. package/dist/skill-test/grading-schema.js.map +1 -0
  98. package/dist/skill-test/harness-location.d.ts +40 -0
  99. package/dist/skill-test/harness-location.d.ts.map +1 -0
  100. package/dist/skill-test/harness-location.js +111 -0
  101. package/dist/skill-test/harness-location.js.map +1 -0
  102. package/dist/skill-test/index.d.ts +16 -0
  103. package/dist/skill-test/index.d.ts.map +1 -0
  104. package/dist/skill-test/index.js +16 -0
  105. package/dist/skill-test/index.js.map +1 -0
  106. package/dist/skill-test/lock.d.ts +16 -0
  107. package/dist/skill-test/lock.d.ts.map +1 -0
  108. package/dist/skill-test/lock.js +42 -0
  109. package/dist/skill-test/lock.js.map +1 -0
  110. package/dist/skill-test/manifest.d.ts +59 -0
  111. package/dist/skill-test/manifest.d.ts.map +1 -0
  112. package/dist/skill-test/manifest.js +34 -0
  113. package/dist/skill-test/manifest.js.map +1 -0
  114. package/dist/skill-test/plugin-env.d.ts +20 -0
  115. package/dist/skill-test/plugin-env.d.ts.map +1 -0
  116. package/dist/skill-test/plugin-env.js +24 -0
  117. package/dist/skill-test/plugin-env.js.map +1 -0
  118. package/dist/skill-test/plugin-layout.d.ts +41 -0
  119. package/dist/skill-test/plugin-layout.d.ts.map +1 -0
  120. package/dist/skill-test/plugin-layout.js +49 -0
  121. package/dist/skill-test/plugin-layout.js.map +1 -0
  122. package/dist/skill-test/preflight.d.ts +31 -0
  123. package/dist/skill-test/preflight.d.ts.map +1 -0
  124. package/dist/skill-test/preflight.js +67 -0
  125. package/dist/skill-test/preflight.js.map +1 -0
  126. package/dist/skill-test/run-harness.d.ts +102 -0
  127. package/dist/skill-test/run-harness.d.ts.map +1 -0
  128. package/dist/skill-test/run-harness.js +446 -0
  129. package/dist/skill-test/run-harness.js.map +1 -0
  130. package/dist/skill-test/staging.d.ts +76 -0
  131. package/dist/skill-test/staging.d.ts.map +1 -0
  132. package/dist/skill-test/staging.js +145 -0
  133. package/dist/skill-test/staging.js.map +1 -0
  134. package/dist/skill-test/vendor-manifest.d.ts +39 -0
  135. package/dist/skill-test/vendor-manifest.d.ts.map +1 -0
  136. package/dist/skill-test/vendor-manifest.js +121 -0
  137. package/dist/skill-test/vendor-manifest.js.map +1 -0
  138. package/dist/validators/packaging-validator.d.ts +7 -0
  139. package/dist/validators/packaging-validator.d.ts.map +1 -1
  140. package/dist/validators/packaging-validator.js +44 -21
  141. package/dist/validators/packaging-validator.js.map +1 -1
  142. package/dist/validators/rule-engine/index.d.ts +10 -0
  143. package/dist/validators/rule-engine/index.d.ts.map +1 -0
  144. package/dist/validators/rule-engine/index.js +3 -0
  145. package/dist/validators/rule-engine/index.js.map +1 -0
  146. package/dist/validators/rule-engine/rule-context.d.ts +107 -0
  147. package/dist/validators/rule-engine/rule-context.d.ts.map +1 -0
  148. package/dist/validators/rule-engine/rule-context.js +44 -0
  149. package/dist/validators/rule-engine/rule-context.js.map +1 -0
  150. package/dist/validators/rule-engine/rule-engine.d.ts +50 -0
  151. package/dist/validators/rule-engine/rule-engine.d.ts.map +1 -0
  152. package/dist/validators/rule-engine/rule-engine.js +117 -0
  153. package/dist/validators/rule-engine/rule-engine.js.map +1 -0
  154. package/dist/validators/skill-validator.js +2 -2
  155. package/dist/validators/skill-validator.js.map +1 -1
  156. package/dist/validators/validation-rules.js +2 -2
  157. package/dist/validators/validation-rules.js.map +1 -1
  158. package/dist/validators/walker-to-issues.d.ts +12 -0
  159. package/dist/validators/walker-to-issues.d.ts.map +1 -1
  160. package/dist/validators/walker-to-issues.js +59 -22
  161. package/dist/validators/walker-to-issues.js.map +1 -1
  162. package/dist/walk-link-graph.d.ts +10 -2
  163. package/dist/walk-link-graph.d.ts.map +1 -1
  164. package/dist/walk-link-graph.js +38 -14
  165. package/dist/walk-link-graph.js.map +1 -1
  166. package/package.json +6 -5
  167. package/schemas/friction-report.json +59 -0
  168. package/vendor/skill-creator/ATTRIBUTION.md +12 -0
  169. package/vendor/skill-creator/LICENSE.txt +202 -0
  170. package/vendor/skill-creator/SKILL.md +485 -0
  171. package/vendor/skill-creator/agents/grader.md +223 -0
  172. package/vendor/skill-creator/plugin.json +8 -0
  173. package/vendor/skill-creator/references/schemas.md +430 -0
  174. package/vendor/skill-creator/vendored.manifest.json +10 -0
@@ -5,6 +5,7 @@
5
5
  * - Merging defaults + per-skill entries (additive, per-skill wins on dest collision)
6
6
  * - Matching auto-discovered links to files entries
7
7
  * - Computing deferred paths for validation
8
+ * - Copying declared build artifacts into a skill output dir (every build path)
8
9
  */
9
10
  import type { SkillFileEntry } from '@vibe-agent-toolkit/resources';
10
11
  export type { SkillFileEntry } from '@vibe-agent-toolkit/resources';
@@ -36,13 +37,88 @@ export declare function mergeFilesConfig(defaults: SkillFileEntry[] | undefined,
36
37
  */
37
38
  export declare function matchLinkToFiles(linkTarget: string, files: SkillFileEntry[]): FilesMatchResult | null;
38
39
  /**
39
- * Compute the set of paths that should be treated as "deferred" during
40
- * source-time validation. These are paths from files config entries where
41
- * the file may not exist yet (build artifacts).
40
+ * Structured deferred path sets returned by {@link computeDeferredPaths}.
42
41
  *
43
- * Both source and dest paths are included because:
44
- * - source may be a build artifact that doesn't exist at validation time
45
- * - dest is the target location that won't exist until build time
42
+ * - `destPaths` files: dest paths that are always deferred (the target
43
+ * location won't exist until build time).
44
+ * - `sourcePaths` files: source paths that are deferred ONLY when the
45
+ * target does not yet exist on disk (i.e. genuine build artifacts). A
46
+ * source that already exists on disk and is gitignored is a leak and must
47
+ * NOT be deferred — let it fall through to the gitignore branch.
46
48
  */
47
- export declare function computeDeferredPaths(files: SkillFileEntry[]): Set<string>;
49
+ export interface DeferredPaths {
50
+ /** files: dest paths — always deferred (won't exist until build). */
51
+ destPaths: Set<string>;
52
+ /** files: source paths — deferred ONLY when the target does not yet exist (build artifact). */
53
+ sourcePaths: Set<string>;
54
+ }
55
+ /**
56
+ * Options for {@link computeDeferredPaths}.
57
+ *
58
+ * - `skillDir` — absolute path to the directory containing SKILL.md.
59
+ * `files:` dest values are authored relative to this dir.
60
+ * - `projectRoot` — absolute path to the project root (git / config root).
61
+ * `files:` source values are authored relative to this dir.
62
+ */
63
+ export interface ComputeDeferredPathsOpts {
64
+ skillDir: string;
65
+ projectRoot: string;
66
+ }
67
+ /**
68
+ * Compute the structured sets of paths that should be treated as "deferred"
69
+ * during source-time validation. These are paths from files config entries
70
+ * where the file may not exist yet (build artifacts).
71
+ *
72
+ * Both sets contain **project-root-relative, forward-slash** paths so they
73
+ * match the `rel` value computed in `checkDeferred()` inside walk-link-graph:
74
+ *
75
+ * ```ts
76
+ * const rel = toForwardSlash(safePath.relative(projectRoot, targetPath));
77
+ * ```
78
+ *
79
+ * - `dest` is authored relative to `skillDir` (mirroring `skill-packager.ts`
80
+ * `resolve(skillDir, entry.dest)`). We resolve it to an absolute path and
81
+ * then make it relative to `projectRoot`.
82
+ * - `source` is authored relative to `projectRoot`. We resolve it with the
83
+ * exact expression `skill-packager.ts` uses —
84
+ * `resolve(join(projectRoot, entry.source))` — so an absolute-looking source
85
+ * is rooted UNDER `projectRoot` identically to what the packager copies.
86
+ * (A bare `resolve(projectRoot, source)` would let a leading slash escape the
87
+ * root, yielding a `../`-prefixed path that never matches the walker's `rel`.)
88
+ * Resolving then re-relativising is a no-op for clean relative paths but
89
+ * correctly strips any leading `./`.
90
+ *
91
+ * - dest paths are always deferred (target won't exist until build)
92
+ * - source paths are deferred only when the target does not yet exist on disk
93
+ */
94
+ export declare function computeDeferredPaths(files: SkillFileEntry[], opts: ComputeDeferredPathsOpts): DeferredPaths;
95
+ /** Options for {@link applyFilesConfig}. */
96
+ export interface ApplyFilesConfigOptions {
97
+ /** Merged `files:` entries to copy. */
98
+ filesConfig: SkillFileEntry[];
99
+ /** Absolute project root; each `source` resolves relative to it. */
100
+ projectRoot: string;
101
+ /** Absolute skill output dir; each `dest` resolves relative to it. */
102
+ skillOutputDir: string;
103
+ /**
104
+ * Absolute source paths already materialized by link traversal — skipped so
105
+ * a linked-and-copied asset isn't copied twice. Defaults to none (copy all).
106
+ */
107
+ bundledFiles?: string[];
108
+ }
109
+ /**
110
+ * Copy each `files:` entry's `source` → `dest` into the skill output directory.
111
+ *
112
+ * This is the single copy primitive shared by every build path so that
113
+ * build-provided artifacts (a bundled engine, generated data, a catalog) are
114
+ * VAT-managed end-to-end: the shared-pool `vat skills build` packager and the
115
+ * Claude plugin marketplace build both call it, instead of the latter relying on
116
+ * an external inject script VAT can't see. `source` is resolved the same way the
117
+ * packager does (`resolve(join(projectRoot, source))`, so an absolute-looking
118
+ * source roots UNDER the project). Returns the dest paths actually copied.
119
+ *
120
+ * @throws if a declared `source` does not exist — a declared build artifact must
121
+ * be present at copy time (callers that defer existence validate it upstream).
122
+ */
123
+ export declare function applyFilesConfig(opts: ApplyFilesConfigOptions): Promise<string[]>;
48
124
  //# sourceMappingURL=files-config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"files-config.d.ts","sourceRoot":"","sources":["../src/files-config.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAGpE,YAAY,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAEpE,4DAA4D;AAC5D,MAAM,WAAW,gBAAgB;IAC/B,8CAA8C;IAC9C,KAAK,EAAE,QAAQ,GAAG,MAAM,CAAC;IACzB,+BAA+B;IAC/B,KAAK,EAAE,cAAc,CAAC;CACvB;AAaD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,cAAc,EAAE,GAAG,SAAS,EACtC,QAAQ,EAAE,cAAc,EAAE,GAAG,SAAS,GACrC,cAAc,EAAE,CA6ClB;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,cAAc,EAAE,GACtB,gBAAgB,GAAG,IAAI,CAkBzB;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,CAOzE"}
1
+ {"version":3,"file":"files-config.d.ts","sourceRoot":"","sources":["../src/files-config.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAGpE,YAAY,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAEpE,4DAA4D;AAC5D,MAAM,WAAW,gBAAgB;IAC/B,8CAA8C;IAC9C,KAAK,EAAE,QAAQ,GAAG,MAAM,CAAC;IACzB,+BAA+B;IAC/B,KAAK,EAAE,cAAc,CAAC;CACvB;AAaD;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,cAAc,EAAE,GAAG,SAAS,EACtC,QAAQ,EAAE,cAAc,EAAE,GAAG,SAAS,GACrC,cAAc,EAAE,CA6ClB;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,cAAc,EAAE,GACtB,gBAAgB,GAAG,IAAI,CAkBzB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,aAAa;IAC5B,qEAAqE;IACrE,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACvB,+FAA+F;IAC/F,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC1B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,cAAc,EAAE,EACvB,IAAI,EAAE,wBAAwB,GAC7B,aAAa,CAgBf;AAED,4CAA4C;AAC5C,MAAM,WAAW,uBAAuB;IACtC,uCAAuC;IACvC,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9B,oEAAoE;IACpE,WAAW,EAAE,MAAM,CAAC;IACpB,sEAAsE;IACtE,cAAc,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,uBAAuB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAmBvF"}
@@ -5,8 +5,12 @@
5
5
  * - Merging defaults + per-skill entries (additive, per-skill wins on dest collision)
6
6
  * - Matching auto-discovered links to files entries
7
7
  * - Computing deferred paths for validation
8
+ * - Copying declared build artifacts into a skill output dir (every build path)
8
9
  */
9
- import { toForwardSlash } from '@vibe-agent-toolkit/utils';
10
+ import { existsSync } from 'node:fs';
11
+ import { copyFile, mkdir } from 'node:fs/promises';
12
+ import { dirname } from 'node:path';
13
+ import { toForwardSlash, safePath } from '@vibe-agent-toolkit/utils';
10
14
  /**
11
15
  * Normalize a path for comparison: strip leading ./ and normalize slashes.
12
16
  */
@@ -91,20 +95,76 @@ export function matchLinkToFiles(linkTarget, files) {
91
95
  return null;
92
96
  }
93
97
  /**
94
- * Compute the set of paths that should be treated as "deferred" during
95
- * source-time validation. These are paths from files config entries where
96
- * the file may not exist yet (build artifacts).
98
+ * Compute the structured sets of paths that should be treated as "deferred"
99
+ * during source-time validation. These are paths from files config entries
100
+ * where the file may not exist yet (build artifacts).
97
101
  *
98
- * Both source and dest paths are included because:
99
- * - source may be a build artifact that doesn't exist at validation time
100
- * - dest is the target location that won't exist until build time
102
+ * Both sets contain **project-root-relative, forward-slash** paths so they
103
+ * match the `rel` value computed in `checkDeferred()` inside walk-link-graph:
104
+ *
105
+ * ```ts
106
+ * const rel = toForwardSlash(safePath.relative(projectRoot, targetPath));
107
+ * ```
108
+ *
109
+ * - `dest` is authored relative to `skillDir` (mirroring `skill-packager.ts`
110
+ * `resolve(skillDir, entry.dest)`). We resolve it to an absolute path and
111
+ * then make it relative to `projectRoot`.
112
+ * - `source` is authored relative to `projectRoot`. We resolve it with the
113
+ * exact expression `skill-packager.ts` uses —
114
+ * `resolve(join(projectRoot, entry.source))` — so an absolute-looking source
115
+ * is rooted UNDER `projectRoot` identically to what the packager copies.
116
+ * (A bare `resolve(projectRoot, source)` would let a leading slash escape the
117
+ * root, yielding a `../`-prefixed path that never matches the walker's `rel`.)
118
+ * Resolving then re-relativising is a no-op for clean relative paths but
119
+ * correctly strips any leading `./`.
120
+ *
121
+ * - dest paths are always deferred (target won't exist until build)
122
+ * - source paths are deferred only when the target does not yet exist on disk
101
123
  */
102
- export function computeDeferredPaths(files) {
103
- const paths = new Set();
124
+ export function computeDeferredPaths(files, opts) {
125
+ const destPaths = new Set();
126
+ const sourcePaths = new Set();
104
127
  for (const entry of files) {
105
- paths.add(normalizePath(entry.source));
106
- paths.add(normalizePath(entry.dest));
128
+ // dest is authored relative to skillDir (skill-packager: resolve(skillDir, dest))
129
+ destPaths.add(toForwardSlash(safePath.relative(opts.projectRoot, safePath.resolve(opts.skillDir, entry.dest))));
130
+ // source is authored relative to projectRoot. Mirror skill-packager exactly:
131
+ // resolve(join(projectRoot, source)) so absolute-looking sources root under
132
+ // projectRoot rather than escaping it.
133
+ sourcePaths.add(toForwardSlash(safePath.relative(opts.projectRoot, safePath.resolve(safePath.join(opts.projectRoot, entry.source)))));
134
+ }
135
+ return { destPaths, sourcePaths };
136
+ }
137
+ /**
138
+ * Copy each `files:` entry's `source` → `dest` into the skill output directory.
139
+ *
140
+ * This is the single copy primitive shared by every build path so that
141
+ * build-provided artifacts (a bundled engine, generated data, a catalog) are
142
+ * VAT-managed end-to-end: the shared-pool `vat skills build` packager and the
143
+ * Claude plugin marketplace build both call it, instead of the latter relying on
144
+ * an external inject script VAT can't see. `source` is resolved the same way the
145
+ * packager does (`resolve(join(projectRoot, source))`, so an absolute-looking
146
+ * source roots UNDER the project). Returns the dest paths actually copied.
147
+ *
148
+ * @throws if a declared `source` does not exist — a declared build artifact must
149
+ * be present at copy time (callers that defer existence validate it upstream).
150
+ */
151
+ export async function applyFilesConfig(opts) {
152
+ const bundledFileSet = new Set((opts.bundledFiles ?? []).map((f) => toForwardSlash(f)));
153
+ const copied = [];
154
+ for (const fileEntry of opts.filesConfig) {
155
+ const absoluteSource = safePath.resolve(safePath.join(opts.projectRoot, fileEntry.source));
156
+ if (bundledFileSet.has(toForwardSlash(absoluteSource)))
157
+ continue;
158
+ const absoluteDest = safePath.join(opts.skillOutputDir, fileEntry.dest);
159
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- source path from validated config
160
+ if (!existsSync(absoluteSource)) {
161
+ throw new Error(`files: source '${fileEntry.source}' does not exist (resolved to ${absoluteSource}).`);
162
+ }
163
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- dest path from validated config
164
+ await mkdir(dirname(absoluteDest), { recursive: true });
165
+ await copyFile(absoluteSource, absoluteDest);
166
+ copied.push(fileEntry.dest);
107
167
  }
108
- return paths;
168
+ return copied;
109
169
  }
110
170
  //# sourceMappingURL=files-config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"files-config.js","sourceRoot":"","sources":["../src/files-config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"files-config.js","sourceRoot":"","sources":["../src/files-config.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -6,7 +6,7 @@ export { buildAgentSkill, type BuildOptions, type BuildResult } from './builder.
6
6
  export { extractH1Title, packageSkill, packageSkills, ZipSizeLimitError, type PackageSkillOptions, type PackageSkillResult, type PackagingTarget, type SkillBuildSpec, type SkillMetadata, } from './skill-packager.js';
7
7
  export { walkLinkGraph, type ExcludeRule, type LinkGraphResult, type LinkResolution, type WalkableRegistry, type WalkLinkGraphOptions, } from './walk-link-graph.js';
8
8
  export { getTargetSubdir, CONTENT_TYPE_ROUTING_MAP, type TargetSubdirCategory, } from './content-type-routing.js';
9
- export { mergeFilesConfig, matchLinkToFiles, computeDeferredPaths, type FilesMatchResult, } from './files-config.js';
9
+ export { applyFilesConfig, mergeFilesConfig, matchLinkToFiles, computeDeferredPaths, type ApplyFilesConfigOptions, type ComputeDeferredPathsOpts, type DeferredPaths, type FilesMatchResult, } from './files-config.js';
10
10
  export { AgentSkillFrontmatterJsonSchema, AgentSkillFrontmatterSchema, VATAgentSkillFrontmatterSchema, type AgentSkillFrontmatter, type VATAgentSkillFrontmatter, } from './schemas/agent-skill-frontmatter.js';
11
11
  export { MarketplaceManifestJsonSchema, MarketplaceManifestSchema, type MarketplaceManifest } from './schemas/marketplace-manifest.js';
12
12
  export { PluginJsonSchema, type PluginJson } from './schemas/plugin-json.js';
@@ -23,9 +23,13 @@ export { crawlAndResolveRegistry, validateSkillForPackaging, type ExcludedRefere
23
23
  export { createIssue, NAVIGATION_FILE_PATTERNS, VALIDATION_RULES, VALIDATION_THRESHOLDS, type RuleCategory, type ValidationRule, type ValidationRuleCode, } from './validators/validation-rules.js';
24
24
  export type { ValidationResult, ValidateOptions, ResourceFormat, Surface, } from './validators/types.js';
25
25
  export { importSkillToAgent, type ImportOptions, type ImportResult, } from './import.js';
26
+ export { cloneGitSource, type GitCloneResult } from './skill-source/git-clone.js';
27
+ export { resolveSkillSource, type ResolveSkillSourceOptions } from './skill-source/resolve-skill-source.js';
28
+ export type { SkillSource, ResolvedSkillSource, ResolveSkillSourceContext, } from './skill-source/types.js';
26
29
  export type { EvidenceRecord, EvidenceSource, EvidenceConfidence, EvidenceLocation, PatternDefinition, Observation, } from './evidence/index.js';
27
30
  export { PATTERN_REGISTRY, getPatternDefinition, assertPatternRegistered, deriveObservationsFromEvidence, } from './evidence/index.js';
28
31
  export type { DeriveObservationsOptions, DerivationSubject } from './evidence/index.js';
29
32
  export type { AnyInventory, BaseInventory, ComponentRef, DeclaredList, HookRef, InstallInventory, LspRef, MarketplaceInventory, McpRef, ParseError as InventoryParseError, PluginInventory, PluginRef, ResolvedReference, SkillInventory, } from './inventory/index.js';
30
33
  export { isInstallInventory, isMarketplaceInventory, isPluginInventory, isSkillInventory, serializeInventory, serializeInventoryShallow, INVENTORY_SCHEMA_VERSION, detectDeclaredButMissing, detectMarketplacePluginSourceMissing, detectPresentButUndeclared, detectReferenceTargetMissing, } from './inventory/index.js';
34
+ export * from './skill-test/index.js';
31
35
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ export { buildAgentSkill } from './builder.js';
6
6
  export { extractH1Title, packageSkill, packageSkills, ZipSizeLimitError, } from './skill-packager.js';
7
7
  export { walkLinkGraph, } from './walk-link-graph.js';
8
8
  export { getTargetSubdir, CONTENT_TYPE_ROUTING_MAP, } from './content-type-routing.js';
9
- export { mergeFilesConfig, matchLinkToFiles, computeDeferredPaths, } from './files-config.js';
9
+ export { applyFilesConfig, mergeFilesConfig, matchLinkToFiles, computeDeferredPaths, } from './files-config.js';
10
10
  export { AgentSkillFrontmatterJsonSchema, AgentSkillFrontmatterSchema, VATAgentSkillFrontmatterSchema, } from './schemas/agent-skill-frontmatter.js';
11
11
  export { MarketplaceManifestJsonSchema, MarketplaceManifestSchema } from './schemas/marketplace-manifest.js';
12
12
  export { PluginJsonSchema } from './schemas/plugin-json.js';
@@ -22,6 +22,11 @@ export { detectResourceFormat, enumerateSurfaces } from './validators/format-det
22
22
  export { crawlAndResolveRegistry, validateSkillForPackaging, } from './validators/packaging-validator.js';
23
23
  export { createIssue, NAVIGATION_FILE_PATTERNS, VALIDATION_RULES, VALIDATION_THRESHOLDS, } from './validators/validation-rules.js';
24
24
  export { importSkillToAgent, } from './import.js';
25
+ // Skill source primitives
26
+ export { cloneGitSource } from './skill-source/git-clone.js';
27
+ // Unified skill-source resolution (spec §11c)
28
+ export { resolveSkillSource } from './skill-source/resolve-skill-source.js';
25
29
  export { PATTERN_REGISTRY, getPatternDefinition, assertPatternRegistered, deriveObservationsFromEvidence, } from './evidence/index.js';
26
30
  export { isInstallInventory, isMarketplaceInventory, isPluginInventory, isSkillInventory, serializeInventory, serializeInventoryShallow, INVENTORY_SCHEMA_VERSION, detectDeclaredButMissing, detectMarketplacePluginSourceMissing, detectPresentButUndeclared, detectReferenceTargetMissing, } from './inventory/index.js';
31
+ export * from './skill-test/index.js';
27
32
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,eAAe,EAAuC,MAAM,cAAc,CAAC;AAEpF,OAAO,EACL,cAAc,EACd,YAAY,EACZ,aAAa,EACb,iBAAiB,GAMlB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,aAAa,GAMd,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,eAAe,EACf,wBAAwB,GAEzB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,oBAAoB,GAErB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,+BAA+B,EAC/B,2BAA2B,EAC3B,8BAA8B,GAG/B,MAAM,sCAAsC,CAAC;AAE9C,OAAO,EAAE,6BAA6B,EAAE,yBAAyB,EAA4B,MAAM,mCAAmC,CAAC;AAEvI,OAAO,EAAE,gBAAgB,EAAmB,MAAM,0BAA0B,CAAC;AAE7E,OAAO,EACL,gBAAgB,GAEjB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACpG,OAAO,EAAE,wBAAwB,EAAyB,MAAM,sCAAsC,CAAC;AACvG,OAAO,EAAE,8BAA8B,EAAE,MAAM,2CAA2C,CAAC;AAC3F,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,GAEnB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,QAAQ,EAA+B,MAAM,mCAAmC,CAAC;AAC1F,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAC3F,OAAO,EACL,uBAAuB,EACvB,yBAAyB,GAK1B,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EACL,WAAW,EACX,wBAAwB,EACxB,gBAAgB,EAChB,qBAAqB,GAItB,MAAM,kCAAkC,CAAC;AAQ1C,OAAO,EACL,kBAAkB,GAGnB,MAAM,aAAa,CAAC;AAWrB,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,uBAAuB,EACvB,8BAA8B,GAC/B,MAAM,qBAAqB,CAAC;AAoB7B,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,yBAAyB,EACzB,wBAAwB,EACxB,wBAAwB,EACxB,oCAAoC,EACpC,0BAA0B,EAC1B,4BAA4B,GAC7B,MAAM,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,eAAe,EAAuC,MAAM,cAAc,CAAC;AAEpF,OAAO,EACL,cAAc,EACd,YAAY,EACZ,aAAa,EACb,iBAAiB,GAMlB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,aAAa,GAMd,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EACL,eAAe,EACf,wBAAwB,GAEzB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,oBAAoB,GAKrB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,+BAA+B,EAC/B,2BAA2B,EAC3B,8BAA8B,GAG/B,MAAM,sCAAsC,CAAC;AAE9C,OAAO,EAAE,6BAA6B,EAAE,yBAAyB,EAA4B,MAAM,mCAAmC,CAAC;AAEvI,OAAO,EAAE,gBAAgB,EAAmB,MAAM,0BAA0B,CAAC;AAE7E,OAAO,EACL,gBAAgB,GAEjB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACpG,OAAO,EAAE,wBAAwB,EAAyB,MAAM,sCAAsC,CAAC;AACvG,OAAO,EAAE,8BAA8B,EAAE,MAAM,2CAA2C,CAAC;AAC3F,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,GAEnB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;AAC5E,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,QAAQ,EAA+B,MAAM,mCAAmC,CAAC;AAC1F,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAC3F,OAAO,EACL,uBAAuB,EACvB,yBAAyB,GAK1B,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EACL,WAAW,EACX,wBAAwB,EACxB,gBAAgB,EAChB,qBAAqB,GAItB,MAAM,kCAAkC,CAAC;AAQ1C,OAAO,EACL,kBAAkB,GAGnB,MAAM,aAAa,CAAC;AAErB,0BAA0B;AAC1B,OAAO,EAAE,cAAc,EAAuB,MAAM,6BAA6B,CAAC;AAElF,8CAA8C;AAC9C,OAAO,EAAE,kBAAkB,EAAkC,MAAM,wCAAwC,CAAC;AAgB5G,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,uBAAuB,EACvB,8BAA8B,GAC/B,MAAM,qBAAqB,CAAC;AAoB7B,OAAO,EACL,kBAAkB,EAClB,sBAAsB,EACtB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,yBAAyB,EACzB,wBAAwB,EACxB,wBAAwB,EACxB,oCAAoC,EACpC,0BAA0B,EAC1B,4BAA4B,GAC7B,MAAM,sBAAsB,CAAC;AAE9B,cAAc,uBAAuB,CAAC"}
@@ -6,18 +6,18 @@
6
6
  */
7
7
  import { type ValidationIssue } from '@vibe-agent-toolkit/agent-schema';
8
8
  /**
9
- * Check that every file in the packaged output is referenced from some markdown file.
9
+ * Check that every file in the packaged output is referenced from some markdown or HTML file.
10
10
  *
11
11
  * Two-pass detection:
12
- * 1. Walk `[text](href)` link graph from SKILL.md (strict, transitive).
12
+ * 1. Walk formal link graph from SKILL.md (strict, transitive, covers .md and .html/.htm).
13
13
  * 2. For files not covered by pass 1, check whether their output-relative path
14
- * is mentioned anywhere in packaged markdown (code blocks, prose, etc.).
14
+ * is mentioned anywhere in packaged content files (markdown or HTML).
15
15
  * Authors often document CLI scripts via invocation examples rather than
16
- * markdown links, and that counts as documented.
16
+ * formal links, and that counts as documented.
17
17
  */
18
18
  export declare function checkUnreferencedFiles(outputDir: string): Promise<ValidationIssue[]>;
19
19
  /**
20
- * Check that every local file link in packaged markdown files resolves to a file
20
+ * Check that every local file link in packaged markdown and HTML files resolves to a file
21
21
  * that exists in the packaged output.
22
22
  */
23
23
  export declare function checkBrokenPackagedLinks(outputDir: string): Promise<ValidationIssue[]>;
@@ -1 +1 @@
1
- {"version":3,"file":"post-build-checks.d.ts","sourceRoot":"","sources":["../src/post-build-checks.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EAAiB,KAAK,eAAe,EAAE,MAAM,kCAAkC,CAAC;AA4JvF;;;;;;;;;GASG;AACH,wBAAsB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CA4B1F;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CA6B5F"}
1
+ {"version":3,"file":"post-build-checks.d.ts","sourceRoot":"","sources":["../src/post-build-checks.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,kCAAkC,CAAC;AA0OxE;;;;;;;;;GASG;AACH,wBAAsB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAmC1F;AAED;;;GAGG;AACH,wBAAsB,wBAAwB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAe5F"}
@@ -4,11 +4,12 @@
4
4
  * Run after packageSkill() completes — all files are copied, all links rewritten.
5
5
  * Detects unreferenced files and broken links in the packaged output.
6
6
  */
7
- import { existsSync, readdirSync } from 'node:fs';
7
+ import { existsSync, readdirSync, statSync } from 'node:fs';
8
8
  import { readFile } from 'node:fs/promises';
9
9
  import { dirname } from 'node:path';
10
- import { CODE_REGISTRY } from '@vibe-agent-toolkit/agent-schema';
10
+ import { parseHtml } from '@vibe-agent-toolkit/resources';
11
11
  import { safePath, toForwardSlash } from '@vibe-agent-toolkit/utils';
12
+ import { evaluate, makeRuleContext, materializeIssue } from './validators/rule-engine/index.js';
12
13
  /**
13
14
  * Regex matching markdown inline links: [text](href).
14
15
  * Negated character classes [^\]\\] and [^)] are non-backtracking by design.
@@ -76,38 +77,105 @@ function extractLocalLinks(content) {
76
77
  return links;
77
78
  }
78
79
  /**
79
- * Walk the markdown link graph starting at SKILL.md and return the set of
80
+ * Extract local file hrefs from a content file markdown or HTML.
81
+ *
82
+ * For markdown: regex-matches `[text](href)` links, skipping code blocks.
83
+ * For HTML/HTM: uses `parseHtml` (parse5-based) and returns `local_file` hrefs only.
84
+ * Fragments are stripped from all returned hrefs.
85
+ */
86
+ async function extractLocalHrefs(filePath) {
87
+ if (filePath.endsWith('.html') || filePath.endsWith('.htm')) {
88
+ const result = await parseHtml(filePath);
89
+ return result.links
90
+ .filter(link => link.type === 'local_file')
91
+ .map(link => {
92
+ const [withoutFragment] = link.href.split('#');
93
+ return withoutFragment ?? '';
94
+ })
95
+ .filter(href => href.length > 0);
96
+ }
97
+ // Markdown: read content and regex-match
98
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- filePath from walkDir
99
+ const content = await readFile(filePath, 'utf-8');
100
+ return extractLocalLinks(content);
101
+ }
102
+ /**
103
+ * Check hrefs from a content file against allFileSet and return PACKAGED_BROKEN_LINK
104
+ * issues for any that don't resolve to a file in the packaged output.
105
+ *
106
+ * Shared by markdown and HTML broken-link checks to eliminate duplicate resolve/emit logic.
107
+ */
108
+ function collectBrokenLinkIssues(sourceFile, hrefs, allFileSet, outputDir) {
109
+ const issues = [];
110
+ const relativeSourcePath = toForwardSlash(safePath.relative(outputDir, sourceFile));
111
+ for (const href of hrefs) {
112
+ const resolved = toForwardSlash(safePath.resolve(dirname(sourceFile), href));
113
+ if (!allFileSet.has(resolved)) {
114
+ // A navigational directory link (href ending in `/`, classified `local_directory`)
115
+ // is a valid target if the directory itself exists on disk — walkDir populates
116
+ // allFileSet with FILES only, so directory paths are never in the set.
117
+ // Note: a NO-SLASH link (`[Concepts](concepts)`, classified `local_file`) that
118
+ // happens to resolve to a directory is a different case — it matches the
119
+ // link-rewrite bundled-link rule (skill-packager.ts buildRewriteRules) and
120
+ // renders with an undefined `link.resource.*`. Fixing that is the
121
+ // link-rewrite engine's job, tracked under #129 (slice 3, built-path
122
+ // unification). The slash form (`concepts/`, `local_directory`) survives
123
+ // rewrite verbatim and is the realistic navigational case this guard covers.
124
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- resolved is a normalized path from a validated output directory
125
+ const isExistingDirectory = statSync(resolved, { throwIfNoEntry: false })?.isDirectory() === true;
126
+ if (isExistingDirectory) {
127
+ continue;
128
+ }
129
+ // Built-path edge extraction: a link whose target is absent from the
130
+ // packaged output. The engine resolves this to PACKAGED_BROKEN_LINK
131
+ // (a link-rewriter bug) rather than LINK_MISSING_TARGET via phase: 'built'.
132
+ const code = evaluate(makeRuleContext({ subject: 'edge', phase: 'built', existsAtSource: false }));
133
+ if (code !== null) {
134
+ issues.push(materializeIssue(code, {
135
+ location: relativeSourcePath,
136
+ detail: `link: ${href} from ${relativeSourcePath}`,
137
+ }));
138
+ }
139
+ }
140
+ }
141
+ return issues;
142
+ }
143
+ /**
144
+ * Walk the markdown and HTML link graph starting at SKILL.md and return the set of
80
145
  * referenced file paths (normalized to forward slashes).
81
146
  *
82
- * SKILL.md itself is always included as the root.
147
+ * SKILL.md itself is always included as the root. Traversal follows `.md`, `.html`,
148
+ * and `.htm` links transitively so an HTML file referenced only by another HTML file
149
+ * is not reported as unreferenced.
83
150
  */
84
151
  async function collectReferencedPaths(outputDir, allFileSet) {
85
152
  const referenced = new Set();
86
153
  const skillMdPath = safePath.join(outputDir, 'SKILL.md');
87
- const mdQueue = [skillMdPath];
154
+ const fileQueue = [skillMdPath];
88
155
  const visited = new Set();
89
156
  // SKILL.md itself is the root — always referenced
90
157
  referenced.add(toForwardSlash(skillMdPath));
91
- while (mdQueue.length > 0) {
92
- const mdFile = mdQueue.shift();
93
- if (!mdFile)
158
+ while (fileQueue.length > 0) {
159
+ const filePath = fileQueue.shift();
160
+ if (!filePath)
94
161
  break;
95
- const normalized = toForwardSlash(mdFile);
162
+ const normalized = toForwardSlash(filePath);
96
163
  if (visited.has(normalized))
97
164
  continue;
98
165
  visited.add(normalized);
99
- // eslint-disable-next-line security/detect-non-literal-fs-filename -- mdFile from walkDir output
100
- if (!existsSync(mdFile))
166
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- filePath from walkDir output
167
+ if (!existsSync(filePath))
101
168
  continue;
102
- // eslint-disable-next-line security/detect-non-literal-fs-filename -- mdFile validated above
103
- const content = await readFile(mdFile, 'utf-8');
104
- const links = extractLocalLinks(content);
105
- for (const href of links) {
106
- const resolved = toForwardSlash(safePath.resolve(dirname(mdFile), href));
169
+ const hrefs = await extractLocalHrefs(filePath);
170
+ for (const href of hrefs) {
171
+ const resolved = toForwardSlash(safePath.resolve(dirname(filePath), href));
107
172
  referenced.add(resolved);
108
- // If it's a markdown file in the output, traverse it transitively
109
- if (resolved.endsWith('.md') && allFileSet.has(resolved) && !visited.has(resolved)) {
110
- mdQueue.push(resolved);
173
+ // Traverse .md, .html, and .htm files transitively
174
+ const isTraversable = (resolved.endsWith('.md') || resolved.endsWith('.html') || resolved.endsWith('.htm')) &&
175
+ allFileSet.has(resolved) &&
176
+ !visited.has(resolved);
177
+ if (isTraversable) {
178
+ fileQueue.push(resolved);
111
179
  }
112
180
  }
113
181
  }
@@ -115,22 +183,22 @@ async function collectReferencedPaths(outputDir, allFileSet) {
115
183
  }
116
184
  /**
117
185
  * Record packaged files whose output-relative path appears anywhere in any
118
- * packaged markdown — inside code blocks (`` ```bash\nnode scripts/cli.mjs `` ``),
119
- * inline code spans, or prose — as "documented" references.
186
+ * packaged content file (markdown or HTML) — inside code blocks, inline code
187
+ * spans, or prose — as "documented" references.
120
188
  *
121
189
  * A file that a skill author chose to bundle but never documents is the real
122
190
  * problem this check exists to catch; documentation by code-block invocation
123
191
  * is still documentation. By contrast, `collectReferencedPaths` is intentionally
124
- * strict (only `[text](href)` links) because it also walks the transitive link
192
+ * strict (only formal link syntax) because it also walks the transitive link
125
193
  * graph, which would be unbounded if we followed substring hits.
126
194
  */
127
- async function addMentionReferences(outputDir, referenced, candidates, mdFiles) {
128
- if (candidates.length === 0 || mdFiles.length === 0) {
195
+ async function addMentionReferences(outputDir, referenced, candidates, contentFiles) {
196
+ if (candidates.length === 0 || contentFiles.length === 0) {
129
197
  return;
130
198
  }
131
199
  const contents = await Promise.all(
132
- // eslint-disable-next-line security/detect-non-literal-fs-filename -- mdFile from walkDir
133
- mdFiles.map(f => readFile(f, 'utf-8')));
200
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- contentFile from walkDir
201
+ contentFiles.map(f => readFile(f, 'utf-8')));
134
202
  const haystack = contents.join('\n');
135
203
  for (const candidate of candidates) {
136
204
  const relativePath = toForwardSlash(safePath.relative(outputDir, candidate));
@@ -140,68 +208,58 @@ async function addMentionReferences(outputDir, referenced, candidates, mdFiles)
140
208
  }
141
209
  }
142
210
  /**
143
- * Check that every file in the packaged output is referenced from some markdown file.
211
+ * Check that every file in the packaged output is referenced from some markdown or HTML file.
144
212
  *
145
213
  * Two-pass detection:
146
- * 1. Walk `[text](href)` link graph from SKILL.md (strict, transitive).
214
+ * 1. Walk formal link graph from SKILL.md (strict, transitive, covers .md and .html/.htm).
147
215
  * 2. For files not covered by pass 1, check whether their output-relative path
148
- * is mentioned anywhere in packaged markdown (code blocks, prose, etc.).
216
+ * is mentioned anywhere in packaged content files (markdown or HTML).
149
217
  * Authors often document CLI scripts via invocation examples rather than
150
- * markdown links, and that counts as documented.
218
+ * formal links, and that counts as documented.
151
219
  */
152
220
  export async function checkUnreferencedFiles(outputDir) {
153
221
  const allFiles = walkDir(outputDir);
154
222
  const allFileSet = new Set(allFiles.map(f => toForwardSlash(f)));
155
223
  const referenced = await collectReferencedPaths(outputDir, allFileSet);
156
- // Second pass: treat any path mention in packaged markdown as documentation.
224
+ // Second pass: treat any path mention in packaged content files as documentation.
157
225
  const candidates = allFiles.filter(f => !referenced.has(toForwardSlash(f)));
158
- const mdFiles = allFiles.filter(f => f.endsWith('.md'));
159
- await addMentionReferences(outputDir, referenced, candidates, mdFiles);
226
+ const contentFiles = allFiles.filter(f => f.endsWith('.md') || f.endsWith('.html') || f.endsWith('.htm'));
227
+ await addMentionReferences(outputDir, referenced, candidates, contentFiles);
160
228
  // Find unreferenced files
161
229
  const issues = [];
162
230
  for (const file of allFiles) {
163
231
  const normalized = toForwardSlash(file);
164
232
  if (!referenced.has(normalized)) {
165
233
  const relativePath = toForwardSlash(safePath.relative(outputDir, file));
166
- issues.push({
167
- severity: CODE_REGISTRY.PACKAGED_UNREFERENCED_FILE.defaultSeverity,
168
- code: 'PACKAGED_UNREFERENCED_FILE',
169
- message: `Packaged file not referenced from any markdown: ${relativePath}`,
170
- location: relativePath,
171
- fix: CODE_REGISTRY.PACKAGED_UNREFERENCED_FILE.fix,
172
- reference: CODE_REGISTRY.PACKAGED_UNREFERENCED_FILE.reference,
173
- });
234
+ // Built-path file extraction: a packaged file reachable by neither link
235
+ // nor mention nor files: declaration. The engine resolves this to
236
+ // PACKAGED_UNREFERENCED_FILE for a skill-bundled copy at the built phase.
237
+ const code = evaluate(makeRuleContext({
238
+ subject: 'file',
239
+ phase: 'built',
240
+ copyRole: 'skill-bundled',
241
+ reachableFromSkillMd: false,
242
+ referencedHow: 'none',
243
+ }));
244
+ if (code !== null) {
245
+ issues.push(materializeIssue(code, { location: relativePath, detail: relativePath }));
246
+ }
174
247
  }
175
248
  }
176
249
  return issues;
177
250
  }
178
251
  /**
179
- * Check that every local file link in packaged markdown files resolves to a file
252
+ * Check that every local file link in packaged markdown and HTML files resolves to a file
180
253
  * that exists in the packaged output.
181
254
  */
182
255
  export async function checkBrokenPackagedLinks(outputDir) {
183
256
  const allFiles = walkDir(outputDir);
184
- const mdFiles = allFiles.filter(f => f.endsWith('.md'));
257
+ const linkableFiles = allFiles.filter(f => f.endsWith('.md') || f.endsWith('.html') || f.endsWith('.htm'));
185
258
  const allFileSet = new Set(allFiles.map(f => toForwardSlash(f)));
186
259
  const issues = [];
187
- for (const mdFile of mdFiles) {
188
- // eslint-disable-next-line security/detect-non-literal-fs-filename -- mdFile from walkDir
189
- const content = await readFile(mdFile, 'utf-8');
190
- const links = extractLocalLinks(content);
191
- const relativeMdPath = toForwardSlash(safePath.relative(outputDir, mdFile));
192
- for (const href of links) {
193
- const resolved = toForwardSlash(safePath.resolve(dirname(mdFile), href));
194
- if (!allFileSet.has(resolved)) {
195
- issues.push({
196
- severity: CODE_REGISTRY.PACKAGED_BROKEN_LINK.defaultSeverity,
197
- code: 'PACKAGED_BROKEN_LINK',
198
- message: `Broken link in packaged output: ${href} (from ${relativeMdPath})`,
199
- location: relativeMdPath,
200
- fix: CODE_REGISTRY.PACKAGED_BROKEN_LINK.fix,
201
- reference: CODE_REGISTRY.PACKAGED_BROKEN_LINK.reference,
202
- });
203
- }
204
- }
260
+ for (const sourceFile of linkableFiles) {
261
+ const hrefs = await extractLocalHrefs(sourceFile);
262
+ issues.push(...collectBrokenLinkIssues(sourceFile, hrefs, allFileSet, outputDir));
205
263
  }
206
264
  return issues;
207
265
  }