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

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 (47) hide show
  1. package/dist/files-config.d.ts +54 -0
  2. package/dist/files-config.d.ts.map +1 -1
  3. package/dist/files-config.js +200 -18
  4. package/dist/files-config.js.map +1 -1
  5. package/dist/index.d.ts +1 -0
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +1 -0
  8. package/dist/index.js.map +1 -1
  9. package/dist/plugin-distribution-layout.d.ts +60 -0
  10. package/dist/plugin-distribution-layout.d.ts.map +1 -0
  11. package/dist/plugin-distribution-layout.js +83 -0
  12. package/dist/plugin-distribution-layout.js.map +1 -0
  13. package/dist/skill-packager.d.ts +31 -0
  14. package/dist/skill-packager.d.ts.map +1 -1
  15. package/dist/skill-packager.js +109 -32
  16. package/dist/skill-packager.js.map +1 -1
  17. package/dist/skill-source/git-clone.d.ts +2 -2
  18. package/dist/skill-source/git-clone.d.ts.map +1 -1
  19. package/dist/skill-source/git-clone.js +29 -9
  20. package/dist/skill-source/git-clone.js.map +1 -1
  21. package/dist/skill-source/sources/url-source.d.ts.map +1 -1
  22. package/dist/skill-source/sources/url-source.js +23 -8
  23. package/dist/skill-source/sources/url-source.js.map +1 -1
  24. package/dist/skill-source/sources/workspace-source.d.ts.map +1 -1
  25. package/dist/skill-source/sources/workspace-source.js +16 -8
  26. package/dist/skill-source/sources/workspace-source.js.map +1 -1
  27. package/dist/skill-source/stage.js +6 -2
  28. package/dist/skill-source/stage.js.map +1 -1
  29. package/dist/skill-test/harness-location.d.ts +13 -3
  30. package/dist/skill-test/harness-location.d.ts.map +1 -1
  31. package/dist/skill-test/harness-location.js +72 -16
  32. package/dist/skill-test/harness-location.js.map +1 -1
  33. package/dist/skill-test/preflight.d.ts.map +1 -1
  34. package/dist/skill-test/preflight.js +1 -2
  35. package/dist/skill-test/preflight.js.map +1 -1
  36. package/dist/skill-test/run-harness.d.ts +59 -11
  37. package/dist/skill-test/run-harness.d.ts.map +1 -1
  38. package/dist/skill-test/run-harness.js +25 -19
  39. package/dist/skill-test/run-harness.js.map +1 -1
  40. package/dist/skill-test/vendor-manifest.d.ts +3 -3
  41. package/dist/skill-test/vendor-manifest.d.ts.map +1 -1
  42. package/dist/skill-test/vendor-manifest.js +13 -3
  43. package/dist/skill-test/vendor-manifest.js.map +1 -1
  44. package/dist/walk-link-graph.d.ts.map +1 -1
  45. package/dist/walk-link-graph.js +26 -1
  46. package/dist/walk-link-graph.js.map +1 -1
  47. package/package.json +6 -5
@@ -31,6 +31,12 @@ export declare function mergeFilesConfig(defaults: SkillFileEntry[] | undefined,
31
31
  * Returns the matching entry and whether it matched on source or dest.
32
32
  * Source matches take priority over dest matches.
33
33
  *
34
+ * For GLOB entries (`isGlob(entry.source)`), matching is by directory prefix:
35
+ * - source match: link is equal to or under the glob's static base
36
+ * - dest match: link is equal to or under entry.dest
37
+ *
38
+ * Single-file entries still match EXACTLY (unchanged).
39
+ *
34
40
  * @param linkTarget - Resolved link target path (relative to project root)
35
41
  * @param files - Merged files config entries
36
42
  * @returns Match result or null if no match
@@ -106,6 +112,44 @@ export interface ApplyFilesConfigOptions {
106
112
  */
107
113
  bundledFiles?: string[];
108
114
  }
115
+ /**
116
+ * Verify that each (absSource, absDest) pair has byte-identical content.
117
+ *
118
+ * Throws with a message naming the offending dest path on any mismatch or
119
+ * missing dest. Intended to be called after a copy operation to assert the
120
+ * copy was faithful. Exported so it can be tested directly without running a
121
+ * full applyFilesConfig round-trip.
122
+ */
123
+ export declare function verifyFilesIntegrity(pairs: {
124
+ absSource: string;
125
+ absDest: string;
126
+ }[]): void;
127
+ /**
128
+ * Verify that the on-disk contents of a glob entry's dest subtree EXACTLY match
129
+ * the set of rel paths the copy step intended to write — no missing, no extra.
130
+ *
131
+ * Why a SET comparison and not just `verifyFilesIntegrity`'s byte check:
132
+ * `verifyFilesIntegrity` hashes the (absSource, absDest) pairs that the SAME copy
133
+ * code computed. If the rebase/glob-mapping logic maps a match to the WRONG dest,
134
+ * that wrong dest rides along in the pair, so `hash(absSource) === hash(absDest)`
135
+ * still passes and the bug slips through. Enumerating the dest subtree and
136
+ * diffing against the expected rel set is what catches a misrouted rebase, a
137
+ * stale leftover, or a dropped file.
138
+ *
139
+ * SAFETY ASSUMPTION (why this can't false-positive): a glob entry OWNS its dest
140
+ * directory (`skillOutputDir/<entry.dest>`) and the build wipes the skill output
141
+ * dir before copying (skill-packager.ts removes `resolvedOutput` recursively
142
+ * before any copy). Nothing else writes into this subtree, so any EXTRA file is a
143
+ * genuine bug, not a co-tenant. This scoping is what makes the set check safe
144
+ * here even though a project-wide "no extra files" check would not be.
145
+ *
146
+ * @param destDir Absolute path to the glob entry's dest subtree.
147
+ * @param expectedRel Forward-slash rel paths (relative to `destDir`) the copy
148
+ * step wrote for THIS entry.
149
+ * @param source The entry's `source` (for error messages only).
150
+ * @throws if the actual subtree omits an expected file or contains an extra one.
151
+ */
152
+ export declare function verifyDestSet(destDir: string, expectedRel: string[], source: string): Promise<void>;
109
153
  /**
110
154
  * Copy each `files:` entry's `source` → `dest` into the skill output directory.
111
155
  *
@@ -117,6 +161,16 @@ export interface ApplyFilesConfigOptions {
117
161
  * packager does (`resolve(join(projectRoot, source))`, so an absolute-looking
118
162
  * source roots UNDER the project). Returns the dest paths actually copied.
119
163
  *
164
+ * Glob entries (`source` containing `*`, `?`, or `[`) expand late-bound at
165
+ * copy time: all matched files are rebased under `dest` preserving their
166
+ * path relative to the glob's static base. Zero matches → error.
167
+ *
168
+ * When `integrity: true` is set on an entry, `verifyFilesIntegrity` is called
169
+ * after copying to assert byte-identical content. For GLOB entries it ALSO runs
170
+ * `verifyDestSet` to assert the dest subtree contains exactly the copied rels
171
+ * (no missing, no extra) — catching a misrouted rebase the byte check misses.
172
+ * Single-file entries get only the byte check (dest is a file, not a subtree).
173
+ *
120
174
  * @throws if a declared `source` does not exist — a declared build artifact must
121
175
  * be present at copy time (callers that defer existence validate it upstream).
122
176
  */
@@ -1 +1 @@
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"}
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;AAYpE,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;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,cAAc,EAAE,GACtB,gBAAgB,GAAG,IAAI,CAiCzB;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,CAqBf;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;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAAE,GAC9C,IAAI,CAgBN;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,aAAa,CACjC,OAAO,EAAE,MAAM,EACf,WAAW,EAAE,MAAM,EAAE,EACrB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAyBf;AAiGD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,uBAAuB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAyCvF"}
@@ -7,10 +7,11 @@
7
7
  * - Computing deferred paths for validation
8
8
  * - Copying declared build artifacts into a skill output dir (every build path)
9
9
  */
10
- import { existsSync } from 'node:fs';
10
+ import { existsSync, statSync } from 'node:fs';
11
11
  import { copyFile, mkdir } from 'node:fs/promises';
12
12
  import { dirname } from 'node:path';
13
- import { toForwardSlash, safePath } from '@vibe-agent-toolkit/utils';
13
+ import { fileContentHash, globMagicRemainder, hasParentTraversalSegment, isGlob, safePath, staticGlobBase, toForwardSlash, } from '@vibe-agent-toolkit/utils';
14
+ import { glob } from 'glob';
14
15
  /**
15
16
  * Normalize a path for comparison: strip leading ./ and normalize slashes.
16
17
  */
@@ -74,21 +75,43 @@ export function mergeFilesConfig(defaults, perSkill) {
74
75
  * Returns the matching entry and whether it matched on source or dest.
75
76
  * Source matches take priority over dest matches.
76
77
  *
78
+ * For GLOB entries (`isGlob(entry.source)`), matching is by directory prefix:
79
+ * - source match: link is equal to or under the glob's static base
80
+ * - dest match: link is equal to or under entry.dest
81
+ *
82
+ * Single-file entries still match EXACTLY (unchanged).
83
+ *
77
84
  * @param linkTarget - Resolved link target path (relative to project root)
78
85
  * @param files - Merged files config entries
79
86
  * @returns Match result or null if no match
80
87
  */
81
88
  export function matchLinkToFiles(linkTarget, files) {
82
89
  const normalized = normalizePath(linkTarget);
83
- // Source match has priority
90
+ /** True when `candidate` equals `normalized` or is a path-prefix of it. */
91
+ function isPrefixMatch(candidate) {
92
+ return normalized === candidate || normalized.startsWith(candidate + '/');
93
+ }
94
+ // Source match has priority (checked before dest across all entries)
84
95
  for (const entry of files) {
85
- if (normalizePath(entry.source) === normalized) {
96
+ if (isGlob(entry.source)) {
97
+ const base = normalizePath(staticGlobBase(entry.source));
98
+ if (isPrefixMatch(base)) {
99
+ return { match: 'source', entry };
100
+ }
101
+ }
102
+ else if (normalizePath(entry.source) === normalized) {
86
103
  return { match: 'source', entry };
87
104
  }
88
105
  }
89
106
  // Then check dest match
90
107
  for (const entry of files) {
91
- if (normalizePath(entry.dest) === normalized) {
108
+ if (isGlob(entry.source)) {
109
+ const destBase = normalizePath(entry.dest);
110
+ if (isPrefixMatch(destBase)) {
111
+ return { match: 'dest', entry };
112
+ }
113
+ }
114
+ else if (normalizePath(entry.dest) === normalized) {
92
115
  return { match: 'dest', entry };
93
116
  }
94
117
  }
@@ -127,13 +150,153 @@ export function computeDeferredPaths(files, opts) {
127
150
  for (const entry of files) {
128
151
  // dest is authored relative to skillDir (skill-packager: resolve(skillDir, dest))
129
152
  destPaths.add(toForwardSlash(safePath.relative(opts.projectRoot, safePath.resolve(opts.skillDir, entry.dest))));
130
- // source is authored relative to projectRoot. Mirror skill-packager exactly:
153
+ // source is authored relative to projectRoot. For GLOB entries, register the
154
+ // static base (e.g. 'dist/packs' for 'dist/packs/**/*') so that prefix
155
+ // matching in checkDeferred() can defer links under the glob's expansion tree
156
+ // without executing the glob at validate time (late-bound, pattern-derived).
157
+ // For single-file entries, mirror skill-packager exactly:
131
158
  // resolve(join(projectRoot, source)) so absolute-looking sources root under
132
159
  // projectRoot rather than escaping it.
133
- sourcePaths.add(toForwardSlash(safePath.relative(opts.projectRoot, safePath.resolve(safePath.join(opts.projectRoot, entry.source)))));
160
+ const effectiveSource = isGlob(entry.source) ? staticGlobBase(entry.source) : entry.source;
161
+ sourcePaths.add(toForwardSlash(safePath.relative(opts.projectRoot, safePath.resolve(safePath.join(opts.projectRoot, effectiveSource)))));
134
162
  }
135
163
  return { destPaths, sourcePaths };
136
164
  }
165
+ /**
166
+ * Verify that each (absSource, absDest) pair has byte-identical content.
167
+ *
168
+ * Throws with a message naming the offending dest path on any mismatch or
169
+ * missing dest. Intended to be called after a copy operation to assert the
170
+ * copy was faithful. Exported so it can be tested directly without running a
171
+ * full applyFilesConfig round-trip.
172
+ */
173
+ export function verifyFilesIntegrity(pairs) {
174
+ for (const { absSource, absDest } of pairs) {
175
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- paths from validated config
176
+ if (!existsSync(absDest)) {
177
+ throw new Error(`files: integrity check failed — dest file missing: ${toForwardSlash(absDest)}`);
178
+ }
179
+ const srcHash = fileContentHash(absSource);
180
+ const dstHash = fileContentHash(absDest);
181
+ if (srcHash !== dstHash) {
182
+ throw new Error(`files: integrity check failed — content mismatch at dest: ${toForwardSlash(absDest)}`);
183
+ }
184
+ }
185
+ }
186
+ /**
187
+ * Verify that the on-disk contents of a glob entry's dest subtree EXACTLY match
188
+ * the set of rel paths the copy step intended to write — no missing, no extra.
189
+ *
190
+ * Why a SET comparison and not just `verifyFilesIntegrity`'s byte check:
191
+ * `verifyFilesIntegrity` hashes the (absSource, absDest) pairs that the SAME copy
192
+ * code computed. If the rebase/glob-mapping logic maps a match to the WRONG dest,
193
+ * that wrong dest rides along in the pair, so `hash(absSource) === hash(absDest)`
194
+ * still passes and the bug slips through. Enumerating the dest subtree and
195
+ * diffing against the expected rel set is what catches a misrouted rebase, a
196
+ * stale leftover, or a dropped file.
197
+ *
198
+ * SAFETY ASSUMPTION (why this can't false-positive): a glob entry OWNS its dest
199
+ * directory (`skillOutputDir/<entry.dest>`) and the build wipes the skill output
200
+ * dir before copying (skill-packager.ts removes `resolvedOutput` recursively
201
+ * before any copy). Nothing else writes into this subtree, so any EXTRA file is a
202
+ * genuine bug, not a co-tenant. This scoping is what makes the set check safe
203
+ * here even though a project-wide "no extra files" check would not be.
204
+ *
205
+ * @param destDir Absolute path to the glob entry's dest subtree.
206
+ * @param expectedRel Forward-slash rel paths (relative to `destDir`) the copy
207
+ * step wrote for THIS entry.
208
+ * @param source The entry's `source` (for error messages only).
209
+ * @throws if the actual subtree omits an expected file or contains an extra one.
210
+ */
211
+ export async function verifyDestSet(destDir, expectedRel, source) {
212
+ // dot: true to stay symmetric with the copy glob (M10) — both sides must see
213
+ // hidden files, otherwise a dropped dot-file is invisible to integrity.
214
+ const actual = (await glob('**/*', { cwd: destDir, nodir: true, dot: true }))
215
+ .map((m) => toForwardSlash(m))
216
+ .sort((a, b) => a.localeCompare(b));
217
+ const expected = [...expectedRel].sort((a, b) => a.localeCompare(b));
218
+ const expectedSet = new Set(expected);
219
+ const actualSet = new Set(actual);
220
+ for (const rel of actual) {
221
+ if (!expectedSet.has(rel)) {
222
+ throw new Error(`files: integrity check for '${source}' found unexpected file '${rel}' under dest '${toForwardSlash(destDir)}'`);
223
+ }
224
+ }
225
+ for (const rel of expected) {
226
+ if (!actualSet.has(rel)) {
227
+ throw new Error(`files: integrity check for '${source}' missing expected file '${rel}' under dest '${toForwardSlash(destDir)}'`);
228
+ }
229
+ }
230
+ }
231
+ /**
232
+ * Copy a single (non-glob) files entry into the skill output dir.
233
+ *
234
+ * Returns `[destPath]` (the single entry.dest string) on success.
235
+ * Throws on missing source or if source is a directory.
236
+ */
237
+ async function copyNonGlobEntry(entry, absoluteSource, skillOutputDir) {
238
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- source path from validated config
239
+ if (!existsSync(absoluteSource)) {
240
+ throw new Error(`files: source '${entry.source}' does not exist (resolved to ${absoluteSource}).`);
241
+ }
242
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- source path from validated config
243
+ if (statSync(absoluteSource).isDirectory()) {
244
+ throw new Error(`files: source '${entry.source}' is a directory; use a glob like '${entry.source}/**/*' to copy its contents.`);
245
+ }
246
+ // joinUnderRoot rejects a dest that escapes the skill output dir (absolute /
247
+ // drive-letter / '..'), defense-in-depth beyond the schema refine.
248
+ const absoluteDest = safePath.joinUnderRoot(skillOutputDir, entry.dest);
249
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- dest path from validated config
250
+ await mkdir(dirname(absoluteDest), { recursive: true });
251
+ await copyFile(absoluteSource, absoluteDest);
252
+ return { relDest: entry.dest, absSource: absoluteSource, absDest: absoluteDest };
253
+ }
254
+ /**
255
+ * Expand a glob entry, copy all matched files, and return copied rel-dest paths
256
+ * plus source/dest pairs for optional integrity verification.
257
+ */
258
+ async function copyGlobEntry(entry, projectRoot, skillOutputDir, bundledFileSet) {
259
+ const base = staticGlobBase(entry.source);
260
+ const remainder = globMagicRemainder(entry.source);
261
+ // H2: the static base may legitimately contain leading '..' (the deliberate
262
+ // sibling-base monorepo feature), but the MAGIC REMAINDER must never contain a
263
+ // '..' segment — `glob` honors it and climbs above absoluteBase. Reject it.
264
+ if (hasParentTraversalSegment(remainder)) {
265
+ throw new Error(`files: source '${entry.source}' (glob) has a '..' segment in its glob portion ('${remainder}'); ` +
266
+ `parent-directory traversal is not allowed after the static base.`);
267
+ }
268
+ const absoluteBase = safePath.resolve(safePath.join(projectRoot, base));
269
+ // dot: true so hidden files under the source subtree are included — keeps the
270
+ // package symmetric with verifyDestSet (M10: silent dot-file drop).
271
+ const rawMatches = await glob(remainder, { cwd: absoluteBase, nodir: true, dot: true });
272
+ const matches = rawMatches.map((m) => toForwardSlash(m)).sort((a, b) => a.localeCompare(b));
273
+ if (matches.length === 0) {
274
+ throw new Error(`files: source '${entry.source}' (glob) matched no files under ${absoluteBase} — has your build run?`);
275
+ }
276
+ const copied = [];
277
+ const pairs = [];
278
+ // rels are dest-subtree-relative (relative to skillOutputDir/<entry.dest>),
279
+ // which equals the matched `rel` for files actually copied — the expected set
280
+ // verifyDestSet diffs the on-disk subtree against.
281
+ const rels = [];
282
+ for (const rel of matches) {
283
+ // joinUnderRoot asserts each matched file stays under absoluteBase (read) and
284
+ // that the rebased dest stays under the skill output dir (write) — H1/H2
285
+ // defense-in-depth against a traversal that slipped past earlier guards.
286
+ const absSource = safePath.joinUnderRoot(absoluteBase, rel);
287
+ if (bundledFileSet.has(toForwardSlash(absSource)))
288
+ continue;
289
+ const relDest = toForwardSlash(safePath.join(entry.dest, rel));
290
+ const absDest = safePath.joinUnderRoot(skillOutputDir, entry.dest, rel);
291
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- dest path from validated config
292
+ await mkdir(dirname(absDest), { recursive: true });
293
+ await copyFile(absSource, absDest);
294
+ copied.push(relDest);
295
+ pairs.push({ absSource, absDest });
296
+ rels.push(toForwardSlash(rel));
297
+ }
298
+ return { copied, pairs, rels };
299
+ }
137
300
  /**
138
301
  * Copy each `files:` entry's `source` → `dest` into the skill output directory.
139
302
  *
@@ -145,6 +308,16 @@ export function computeDeferredPaths(files, opts) {
145
308
  * packager does (`resolve(join(projectRoot, source))`, so an absolute-looking
146
309
  * source roots UNDER the project). Returns the dest paths actually copied.
147
310
  *
311
+ * Glob entries (`source` containing `*`, `?`, or `[`) expand late-bound at
312
+ * copy time: all matched files are rebased under `dest` preserving their
313
+ * path relative to the glob's static base. Zero matches → error.
314
+ *
315
+ * When `integrity: true` is set on an entry, `verifyFilesIntegrity` is called
316
+ * after copying to assert byte-identical content. For GLOB entries it ALSO runs
317
+ * `verifyDestSet` to assert the dest subtree contains exactly the copied rels
318
+ * (no missing, no extra) — catching a misrouted rebase the byte check misses.
319
+ * Single-file entries get only the byte check (dest is a file, not a subtree).
320
+ *
148
321
  * @throws if a declared `source` does not exist — a declared build artifact must
149
322
  * be present at copy time (callers that defer existence validate it upstream).
150
323
  */
@@ -152,18 +325,27 @@ export async function applyFilesConfig(opts) {
152
325
  const bundledFileSet = new Set((opts.bundledFiles ?? []).map((f) => toForwardSlash(f)));
153
326
  const copied = [];
154
327
  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}).`);
328
+ if (isGlob(fileEntry.source)) {
329
+ const { copied: entryCopied, pairs, rels } = await copyGlobEntry(fileEntry, opts.projectRoot, opts.skillOutputDir, bundledFileSet);
330
+ if (fileEntry.integrity === true) {
331
+ verifyFilesIntegrity(pairs);
332
+ // Scoped set check: the glob entry owns its dest subtree and the build
333
+ // wiped the output dir first, so the on-disk subtree must equal exactly
334
+ // the rels we copied catches a misrouted rebase the pair-hash misses.
335
+ await verifyDestSet(safePath.joinUnderRoot(opts.skillOutputDir, fileEntry.dest), rels, fileEntry.source);
336
+ }
337
+ copied.push(...entryCopied);
338
+ }
339
+ else {
340
+ const absoluteSource = safePath.resolve(safePath.join(opts.projectRoot, fileEntry.source));
341
+ if (bundledFileSet.has(toForwardSlash(absoluteSource)))
342
+ continue;
343
+ const { relDest, absSource, absDest } = await copyNonGlobEntry(fileEntry, absoluteSource, opts.skillOutputDir);
344
+ if (fileEntry.integrity === true) {
345
+ verifyFilesIntegrity([{ absSource, absDest }]);
346
+ }
347
+ copied.push(relDest);
162
348
  }
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);
167
349
  }
168
350
  return copied;
169
351
  }
@@ -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
@@ -32,4 +32,5 @@ export type { DeriveObservationsOptions, DerivationSubject } from './evidence/in
32
32
  export type { AnyInventory, BaseInventory, ComponentRef, DeclaredList, HookRef, InstallInventory, LspRef, MarketplaceInventory, McpRef, ParseError as InventoryParseError, PluginInventory, PluginRef, ResolvedReference, SkillInventory, } from './inventory/index.js';
33
33
  export { isInstallInventory, isMarketplaceInventory, isPluginInventory, isSkillInventory, serializeInventory, serializeInventoryShallow, INVENTORY_SCHEMA_VERSION, detectDeclaredButMissing, detectMarketplacePluginSourceMissing, detectPresentButUndeclared, detectReferenceTargetMissing, } from './inventory/index.js';
34
34
  export * from './skill-test/index.js';
35
+ export { computeTreeCopiedSkillLocations, getPluginOutputDir, getPluginSourceDir, listPluginSourceSkillDirs, type DistributedSkillLocation, } from './plugin-distribution-layout.js';
35
36
  //# 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
@@ -29,4 +29,5 @@ export { resolveSkillSource } from './skill-source/resolve-skill-source.js';
29
29
  export { PATTERN_REGISTRY, getPatternDefinition, assertPatternRegistered, deriveObservationsFromEvidence, } from './evidence/index.js';
30
30
  export { isInstallInventory, isMarketplaceInventory, isPluginInventory, isSkillInventory, serializeInventory, serializeInventoryShallow, INVENTORY_SCHEMA_VERSION, detectDeclaredButMissing, detectMarketplacePluginSourceMissing, detectPresentButUndeclared, detectReferenceTargetMissing, } from './inventory/index.js';
31
31
  export * from './skill-test/index.js';
32
+ export { computeTreeCopiedSkillLocations, getPluginOutputDir, getPluginSourceDir, listPluginSourceSkillDirs, } from './plugin-distribution-layout.js';
32
33
  //# 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,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"}
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;AAEtC,OAAO,EACL,+BAA+B,EAC/B,kBAAkB,EAClB,kBAAkB,EAClB,yBAAyB,GAE1B,MAAM,iCAAiC,CAAC"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Plugin distribution layout helpers.
3
+ *
4
+ * Shared primitives for locating where `vat build --only claude` places
5
+ * tree-copied plugin skills in the output tree, and where it reads them from.
6
+ *
7
+ * Consumed by `vat build`, `vat verify`, and consistency-check so the path
8
+ * conventions can never drift between those commands.
9
+ */
10
+ import type { ProjectConfig } from '@vibe-agent-toolkit/resources';
11
+ /**
12
+ * Absolute path to the built plugin output directory.
13
+ *
14
+ * Shape: `<configDir>/dist/.claude/plugins/marketplaces/<mp>/plugins/<name>/`
15
+ *
16
+ * Extracted verbatim from build.ts lines 577–580 so that build can later adopt
17
+ * this helper with zero behavior change.
18
+ */
19
+ export declare function getPluginOutputDir(configDir: string, marketplaceName: string, pluginName: string): string;
20
+ /**
21
+ * Absolute path to the plugin source directory.
22
+ *
23
+ * Resolves to `<configDir>/<plugin.source>` when the plugin declares a custom
24
+ * source, otherwise `<configDir>/plugins/<plugin.name>`.
25
+ *
26
+ * Extracted verbatim from build.ts lines 581–584.
27
+ */
28
+ export declare function getPluginSourceDir(configDir: string, plugin: {
29
+ name: string;
30
+ source?: string | undefined;
31
+ }): string;
32
+ /**
33
+ * Names of immediate skill subdirectories under `<pluginSourceDir>/skills/`.
34
+ *
35
+ * Returns `[]` when the `skills/` directory does not exist (pool-only plugin).
36
+ * Non-directory entries (files, symlinks, …) are silently skipped.
37
+ *
38
+ * Mirrors `listSubdirectories` in install.ts.
39
+ */
40
+ export declare function listPluginSourceSkillDirs(pluginSourceDir: string): string[];
41
+ /** Location of a single skill shipped via source tree-copy. */
42
+ export interface DistributedSkillLocation {
43
+ /** Name of the marketplace this skill ships through. */
44
+ marketplaceName: string;
45
+ /** Name of the plugin that contains this skill. */
46
+ pluginName: string;
47
+ /** Directory name under the plugin's `skills/` source dir (also the skill fs path segment). */
48
+ skillDirName: string;
49
+ /** Absolute output path where `vat build` places the skill: `getPluginOutputDir(...)/skills/<skillDirName>`. */
50
+ skillOutputDir: string;
51
+ }
52
+ /**
53
+ * Every skill shipped via source tree-copy across all marketplaces in the
54
+ * config, paired with the output directory where `vat build` places it.
55
+ *
56
+ * Pool-only plugins — those whose source `skills/` directory is absent on disk
57
+ * — contribute nothing to the result.
58
+ */
59
+ export declare function computeTreeCopiedSkillLocations(config: ProjectConfig, configDir: string): DistributedSkillLocation[];
60
+ //# sourceMappingURL=plugin-distribution-layout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-distribution-layout.d.ts","sourceRoot":"","sources":["../src/plugin-distribution-layout.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAGnE;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,MAAM,EACvB,UAAU,EAAE,MAAM,GACjB,MAAM,CAWR;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,GACpD,MAAM,CAKR;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,EAAE,CAQ3E;AAED,+DAA+D;AAC/D,MAAM,WAAW,wBAAwB;IACvC,wDAAwD;IACxD,eAAe,EAAE,MAAM,CAAC;IACxB,mDAAmD;IACnD,UAAU,EAAE,MAAM,CAAC;IACnB,+FAA+F;IAC/F,YAAY,EAAE,MAAM,CAAC;IACrB,gHAAgH;IAChH,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;GAMG;AACH,wBAAgB,+BAA+B,CAC7C,MAAM,EAAE,aAAa,EACrB,SAAS,EAAE,MAAM,GAChB,wBAAwB,EAAE,CAyB5B"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Plugin distribution layout helpers.
3
+ *
4
+ * Shared primitives for locating where `vat build --only claude` places
5
+ * tree-copied plugin skills in the output tree, and where it reads them from.
6
+ *
7
+ * Consumed by `vat build`, `vat verify`, and consistency-check so the path
8
+ * conventions can never drift between those commands.
9
+ */
10
+ import { existsSync, readdirSync } from 'node:fs';
11
+ import { safePath } from '@vibe-agent-toolkit/utils';
12
+ /**
13
+ * Absolute path to the built plugin output directory.
14
+ *
15
+ * Shape: `<configDir>/dist/.claude/plugins/marketplaces/<mp>/plugins/<name>/`
16
+ *
17
+ * Extracted verbatim from build.ts lines 577–580 so that build can later adopt
18
+ * this helper with zero behavior change.
19
+ */
20
+ export function getPluginOutputDir(configDir, marketplaceName, pluginName) {
21
+ return safePath.join(configDir, 'dist', '.claude', 'plugins', 'marketplaces', marketplaceName, 'plugins', pluginName);
22
+ }
23
+ /**
24
+ * Absolute path to the plugin source directory.
25
+ *
26
+ * Resolves to `<configDir>/<plugin.source>` when the plugin declares a custom
27
+ * source, otherwise `<configDir>/plugins/<plugin.name>`.
28
+ *
29
+ * Extracted verbatim from build.ts lines 581–584.
30
+ */
31
+ export function getPluginSourceDir(configDir, plugin) {
32
+ return safePath.join(configDir, plugin.source ?? safePath.join('plugins', plugin.name));
33
+ }
34
+ /**
35
+ * Names of immediate skill subdirectories under `<pluginSourceDir>/skills/`.
36
+ *
37
+ * Returns `[]` when the `skills/` directory does not exist (pool-only plugin).
38
+ * Non-directory entries (files, symlinks, …) are silently skipped.
39
+ *
40
+ * Mirrors `listSubdirectories` in install.ts.
41
+ */
42
+ export function listPluginSourceSkillDirs(pluginSourceDir) {
43
+ const skillsDir = safePath.join(pluginSourceDir, 'skills');
44
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- caller validates pluginSourceDir
45
+ if (!existsSync(skillsDir))
46
+ return [];
47
+ // eslint-disable-next-line security/detect-non-literal-fs-filename -- caller validates pluginSourceDir
48
+ return readdirSync(skillsDir, { withFileTypes: true })
49
+ .filter(d => d.isDirectory())
50
+ .map(d => d.name);
51
+ }
52
+ /**
53
+ * Every skill shipped via source tree-copy across all marketplaces in the
54
+ * config, paired with the output directory where `vat build` places it.
55
+ *
56
+ * Pool-only plugins — those whose source `skills/` directory is absent on disk
57
+ * — contribute nothing to the result.
58
+ */
59
+ export function computeTreeCopiedSkillLocations(config, configDir) {
60
+ const locations = [];
61
+ const marketplaces = config.claude?.marketplaces;
62
+ if (!marketplaces)
63
+ return locations;
64
+ for (const [marketplaceName, marketplace] of Object.entries(marketplaces)) {
65
+ for (const plugin of marketplace.plugins) {
66
+ const pluginSourceDir = getPluginSourceDir(configDir, plugin);
67
+ const skillDirNames = listPluginSourceSkillDirs(pluginSourceDir);
68
+ if (skillDirNames.length === 0)
69
+ continue;
70
+ const pluginOutputDir = getPluginOutputDir(configDir, marketplaceName, plugin.name);
71
+ for (const skillDirName of skillDirNames) {
72
+ locations.push({
73
+ marketplaceName,
74
+ pluginName: plugin.name,
75
+ skillDirName,
76
+ skillOutputDir: safePath.join(pluginOutputDir, 'skills', skillDirName),
77
+ });
78
+ }
79
+ }
80
+ }
81
+ return locations;
82
+ }
83
+ //# sourceMappingURL=plugin-distribution-layout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-distribution-layout.js","sourceRoot":"","sources":["../src/plugin-distribution-layout.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAGlD,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAErD;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAChC,SAAiB,EACjB,eAAuB,EACvB,UAAkB;IAElB,OAAO,QAAQ,CAAC,IAAI,CAClB,SAAS,EACT,MAAM,EACN,SAAS,EACT,SAAS,EACT,cAAc,EACd,eAAe,EACf,SAAS,EACT,UAAU,CACX,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAChC,SAAiB,EACjB,MAAqD;IAErD,OAAO,QAAQ,CAAC,IAAI,CAClB,SAAS,EACT,MAAM,CAAC,MAAM,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,CACvD,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,yBAAyB,CAAC,eAAuB;IAC/D,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;IAC3D,uGAAuG;IACvG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,EAAE,CAAC;IACtC,uGAAuG;IACvG,OAAO,WAAW,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;SACnD,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;SAC5B,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC;AAcD;;;;;;GAMG;AACH,MAAM,UAAU,+BAA+B,CAC7C,MAAqB,EACrB,SAAiB;IAEjB,MAAM,SAAS,GAA+B,EAAE,CAAC;IAEjD,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC;IACjD,IAAI,CAAC,YAAY;QAAE,OAAO,SAAS,CAAC;IAEpC,KAAK,MAAM,CAAC,eAAe,EAAE,WAAW,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;QAC1E,KAAK,MAAM,MAAM,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;YACzC,MAAM,eAAe,GAAG,kBAAkB,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YAC9D,MAAM,aAAa,GAAG,yBAAyB,CAAC,eAAe,CAAC,CAAC;YACjE,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC;gBAAE,SAAS;YAEzC,MAAM,eAAe,GAAG,kBAAkB,CAAC,SAAS,EAAE,eAAe,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;YACpF,KAAK,MAAM,YAAY,IAAI,aAAa,EAAE,CAAC;gBACzC,SAAS,CAAC,IAAI,CAAC;oBACb,eAAe;oBACf,UAAU,EAAE,MAAM,CAAC,IAAI;oBACvB,YAAY;oBACZ,cAAc,EAAE,QAAQ,CAAC,IAAI,CAAC,eAAe,EAAE,QAAQ,EAAE,YAAY,CAAC;iBACvE,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
@@ -223,6 +223,20 @@ export declare function packageSkills(skills: SkillBuildSpec[], projectRoot: str
223
223
  * ```
224
224
  */
225
225
  export declare function packageSkill(skillPath: string, options?: PackageSkillOptions): Promise<PackageSkillResult>;
226
+ /**
227
+ * Generate a synthetic resource ID for a non-markdown asset that collides with an
228
+ * existing markdown resource. Uses the absolute asset path prefixed with `asset::`
229
+ * to guarantee uniqueness — this id is used only for skill-packager internal
230
+ * lookups (output registry + link rewriting), not for user-facing output.
231
+ */
232
+ export declare function synthesizeAssetId(assetPath: string): string;
233
+ /**
234
+ * Determine the resource subdirectory for a file.
235
+ *
236
+ * For claude-web target: uses the existing references directory.
237
+ * For claude-code target: uses content-type routing based on file extension.
238
+ */
239
+ export declare function getResourceSubdirForFile(filePath: string, target: PackagingTarget): string;
226
240
  /**
227
241
  * Extract H1 title from markdown content
228
242
  *
@@ -230,6 +244,23 @@ export declare function packageSkill(skillPath: string, options?: PackageSkillOp
230
244
  * @returns The H1 title text, or undefined if not found
231
245
  */
232
246
  export declare function extractH1Title(content: string): string | undefined;
247
+ /**
248
+ * Find the common ancestor directory of all file paths
249
+ *
250
+ * @param filePaths - Array of absolute file paths
251
+ * @returns Common ancestor directory path
252
+ */
253
+ export declare function findCommonAncestor(filePaths: string[]): string;
254
+ /**
255
+ * Generate target path based on naming strategy
256
+ *
257
+ * @param filePath - Absolute path to the source file
258
+ * @param basePath - Base path to calculate relative path from
259
+ * @param strategy - Naming strategy to use
260
+ * @param stripPrefix - Path prefix to remove before applying strategy (works for all strategies)
261
+ * @returns Target path (relative) for the packaged resource
262
+ */
263
+ export declare function generateTargetPath(filePath: string, basePath: string, strategy?: ResourceNamingStrategy, stripPrefix?: string): string;
233
264
  /**
234
265
  * Thrown when a claude-web ZIP exceeds the 8MB Claude.ai upload limit.
235
266
  * The CLI catches this and exits with code 1.