@vibe-agent-toolkit/agent-skills 0.2.0-rc.5 → 0.2.0-rc.7
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.
- package/dist/content-type-routing.d.ts +32 -0
- package/dist/content-type-routing.d.ts.map +1 -1
- package/dist/content-type-routing.js +23 -0
- package/dist/content-type-routing.js.map +1 -1
- package/dist/index.d.ts +7 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -3
- package/dist/index.js.map +1 -1
- package/dist/parsers/frontmatter-parser.d.ts.map +1 -1
- package/dist/parsers/frontmatter-parser.js +30 -6
- package/dist/parsers/frontmatter-parser.js.map +1 -1
- package/dist/plugin-distribution-layout.d.ts.map +1 -1
- package/dist/plugin-distribution-layout.js +13 -0
- package/dist/plugin-distribution-layout.js.map +1 -1
- package/dist/post-build-checks.d.ts +37 -0
- package/dist/post-build-checks.d.ts.map +1 -1
- package/dist/post-build-checks.js +40 -0
- package/dist/post-build-checks.js.map +1 -1
- package/dist/schemas/allowed-tools.d.ts +31 -0
- package/dist/schemas/allowed-tools.d.ts.map +1 -0
- package/dist/schemas/allowed-tools.js +88 -0
- package/dist/schemas/allowed-tools.js.map +1 -0
- package/dist/schemas/index.d.ts +1 -0
- package/dist/schemas/index.d.ts.map +1 -1
- package/dist/schemas/index.js +1 -0
- package/dist/schemas/index.js.map +1 -1
- package/dist/schemas/marketplace-manifest.d.ts.map +1 -1
- package/dist/schemas/marketplace-manifest.js +17 -6
- package/dist/schemas/marketplace-manifest.js.map +1 -1
- package/dist/skill-identity.d.ts +10 -0
- package/dist/skill-identity.d.ts.map +1 -1
- package/dist/skill-identity.js +12 -0
- package/dist/skill-identity.js.map +1 -1
- package/dist/skill-packager.d.ts +85 -13
- package/dist/skill-packager.d.ts.map +1 -1
- package/dist/skill-packager.js +178 -32
- package/dist/skill-packager.js.map +1 -1
- package/dist/skill-test/eval-fragment.d.ts +31 -29
- package/dist/skill-test/eval-fragment.d.ts.map +1 -1
- package/dist/skill-test/eval-fragment.js +5 -3
- package/dist/skill-test/eval-fragment.js.map +1 -1
- package/dist/skill-test/eval-grader.d.ts +8 -2
- package/dist/skill-test/eval-grader.d.ts.map +1 -1
- package/dist/skill-test/eval-grader.js +3 -6
- package/dist/skill-test/eval-grader.js.map +1 -1
- package/dist/validators/agent-instruction-presence.d.ts.map +1 -1
- package/dist/validators/agent-instruction-presence.js +44 -1
- package/dist/validators/agent-instruction-presence.js.map +1 -1
- package/dist/validators/compat-detectors.d.ts +17 -0
- package/dist/validators/compat-detectors.d.ts.map +1 -1
- package/dist/validators/compat-detectors.js +46 -19
- package/dist/validators/compat-detectors.js.map +1 -1
- package/dist/validators/marketplace-validator.d.ts.map +1 -1
- package/dist/validators/marketplace-validator.js +6 -0
- package/dist/validators/marketplace-validator.js.map +1 -1
- package/dist/validators/mcp-tool-qualification.d.ts +158 -0
- package/dist/validators/mcp-tool-qualification.d.ts.map +1 -0
- package/dist/validators/mcp-tool-qualification.js +467 -0
- package/dist/validators/mcp-tool-qualification.js.map +1 -0
- package/dist/validators/packaged-size-limit.d.ts +296 -0
- package/dist/validators/packaged-size-limit.d.ts.map +1 -0
- package/dist/validators/packaged-size-limit.js +494 -0
- package/dist/validators/packaged-size-limit.js.map +1 -0
- package/dist/validators/packaging-validator.d.ts +41 -2
- package/dist/validators/packaging-validator.d.ts.map +1 -1
- package/dist/validators/packaging-validator.js +159 -15
- package/dist/validators/packaging-validator.js.map +1 -1
- package/dist/validators/referenced-path-missing.d.ts +211 -0
- package/dist/validators/referenced-path-missing.d.ts.map +1 -0
- package/dist/validators/referenced-path-missing.js +379 -0
- package/dist/validators/referenced-path-missing.js.map +1 -0
- package/dist/validators/skill-validator.d.ts.map +1 -1
- package/dist/validators/skill-validator.js +29 -0
- package/dist/validators/skill-validator.js.map +1 -1
- package/dist/validators/types.d.ts +14 -0
- package/dist/validators/types.d.ts.map +1 -1
- package/dist/walk-link-graph.js +26 -7
- package/dist/walk-link-graph.js.map +1 -1
- package/package.json +7 -7
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"allowed-tools.js","sourceRoot":"","sources":["../../src/schemas/allowed-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAa;IACjD,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAC9B,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACtB,IAAI,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC,IAAI,KAAK,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;YACzD,OAAO,IAAI,IAAI,CAAC;YAChB,SAAS;QACX,CAAC;QACD,IAAI,OAAO,KAAK,EAAE;YAAE,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC/C,OAAO,GAAG,EAAE,CAAC;IACf,CAAC;IACD,IAAI,OAAO,KAAK,EAAE;QAAE,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC/C,OAAO,YAAY,CAAC;AACtB,CAAC;AAED;;;GAGG;AACH,MAAM,OAAO;IACH,KAAK,GAAG,CAAC,CAAC;IACV,KAAK,CAAwB;IAErC,gFAAgF;IAChF,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;IACxB,CAAC;IAED,OAAO,CAAC,IAAY;QAClB,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YAC7B,IAAI,IAAI,KAAK,IAAI,CAAC,KAAK;gBAAE,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;QAClD,CAAC;aAAM,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YAC5D,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QACpB,CAAC;aAAM,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;YACxB,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC;QAClB,CAAC;aAAM,IAAI,IAAI,KAAK,GAAG,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC;YAC1C,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,YAAY,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;QAClD,OAAO,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5D,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,YAAY,GAAG,KAAK;aACvB,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC;aAC1D,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;aAC1B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC;QACjC,OAAO,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC;IAC5D,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
package/dist/schemas/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Schema exports for agent-skills package
|
|
3
3
|
*/
|
|
4
4
|
export { AgentSkillFrontmatterJsonSchema, AgentSkillFrontmatterSchema, VATAgentSkillFrontmatterSchema, type AgentSkillFrontmatter, type VATAgentSkillFrontmatter, } from './agent-skill-frontmatter.js';
|
|
5
|
+
export { allowedToolsOf, splitAllowedToolsList } from './allowed-tools.js';
|
|
5
6
|
export { detectInstalledPluginsRegistryDrift, InstalledPluginsRegistryJsonSchema, InstalledPluginsRegistrySchema, KNOWN_INSTALLATION_SCOPES, type InstalledPluginsRegistry, type PluginInstallation, } from './installed-plugins-registry.js';
|
|
6
7
|
export { detectKnownMarketplacesRegistryDrift, KNOWN_MARKETPLACE_SOURCE_KINDS, KnownMarketplacesRegistryJsonSchema, KnownMarketplacesRegistrySchema, type KnownMarketplacesRegistry, type MarketplaceEntry, type MarketplaceSource, } from './known-marketplaces-registry.js';
|
|
7
8
|
export type { RegistryShapeDrift } from './registry-drift.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/schemas/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,+BAA+B,EAC/B,2BAA2B,EAC3B,8BAA8B,EAC9B,KAAK,qBAAqB,EAC1B,KAAK,wBAAwB,GAC9B,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACL,mCAAmC,EACnC,kCAAkC,EAClC,8BAA8B,EAC9B,yBAAyB,EACzB,KAAK,wBAAwB,EAC7B,KAAK,kBAAkB,GACxB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EACL,oCAAoC,EACpC,8BAA8B,EAC9B,mCAAmC,EACnC,+BAA+B,EAC/B,KAAK,yBAAyB,EAC9B,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,GACvB,MAAM,kCAAkC,CAAC;AAE1C,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAE9D,OAAO,EACL,6BAA6B,EAC7B,yBAAyB,EACzB,KAAK,mBAAmB,GACzB,MAAM,2BAA2B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/schemas/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,+BAA+B,EAC/B,2BAA2B,EAC3B,8BAA8B,EAC9B,KAAK,qBAAqB,EAC1B,KAAK,wBAAwB,GAC9B,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAE3E,OAAO,EACL,mCAAmC,EACnC,kCAAkC,EAClC,8BAA8B,EAC9B,yBAAyB,EACzB,KAAK,wBAAwB,EAC7B,KAAK,kBAAkB,GACxB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EACL,oCAAoC,EACpC,8BAA8B,EAC9B,mCAAmC,EACnC,+BAA+B,EAC/B,KAAK,yBAAyB,EAC9B,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,GACvB,MAAM,kCAAkC,CAAC;AAE1C,YAAY,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAE9D,OAAO,EACL,6BAA6B,EAC7B,yBAAyB,EACzB,KAAK,mBAAmB,GACzB,MAAM,2BAA2B,CAAC"}
|
package/dist/schemas/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Schema exports for agent-skills package
|
|
3
3
|
*/
|
|
4
4
|
export { AgentSkillFrontmatterJsonSchema, AgentSkillFrontmatterSchema, VATAgentSkillFrontmatterSchema, } from './agent-skill-frontmatter.js';
|
|
5
|
+
export { allowedToolsOf, splitAllowedToolsList } from './allowed-tools.js';
|
|
5
6
|
export { detectInstalledPluginsRegistryDrift, InstalledPluginsRegistryJsonSchema, InstalledPluginsRegistrySchema, KNOWN_INSTALLATION_SCOPES, } from './installed-plugins-registry.js';
|
|
6
7
|
export { detectKnownMarketplacesRegistryDrift, KNOWN_MARKETPLACE_SOURCE_KINDS, KnownMarketplacesRegistryJsonSchema, KnownMarketplacesRegistrySchema, } from './known-marketplaces-registry.js';
|
|
7
8
|
export { MarketplaceManifestJsonSchema, MarketplaceManifestSchema, } from './marketplace-manifest.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/schemas/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,+BAA+B,EAC/B,2BAA2B,EAC3B,8BAA8B,GAG/B,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EACL,mCAAmC,EACnC,kCAAkC,EAClC,8BAA8B,EAC9B,yBAAyB,GAG1B,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EACL,oCAAoC,EACpC,8BAA8B,EAC9B,mCAAmC,EACnC,+BAA+B,GAIhC,MAAM,kCAAkC,CAAC;AAI1C,OAAO,EACL,6BAA6B,EAC7B,yBAAyB,GAE1B,MAAM,2BAA2B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/schemas/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,+BAA+B,EAC/B,2BAA2B,EAC3B,8BAA8B,GAG/B,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAE3E,OAAO,EACL,mCAAmC,EACnC,kCAAkC,EAClC,8BAA8B,EAC9B,yBAAyB,GAG1B,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EACL,oCAAoC,EACpC,8BAA8B,EAC9B,mCAAmC,EACnC,+BAA+B,GAIhC,MAAM,kCAAkC,CAAC;AAI1C,OAAO,EACL,6BAA6B,EAC7B,yBAAyB,GAE1B,MAAM,2BAA2B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"marketplace-manifest.d.ts","sourceRoot":"","sources":["../../src/schemas/marketplace-manifest.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"marketplace-manifest.d.ts","sourceRoot":"","sources":["../../src/schemas/marketplace-manifest.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAwExB,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCA0B0C,CAAC;AAEjF,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE5E;;;GAGG;AACH,eAAO,MAAM,6BAA6B;;;;;CAMzC,CAAC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { hasParentTraversalSegment, isAbsoluteAnyPlatform } from '@vibe-agent-toolkit/utils';
|
|
1
2
|
import { z } from 'zod';
|
|
2
3
|
import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
3
4
|
/**
|
|
@@ -26,17 +27,27 @@ const OwnerSchema = z
|
|
|
26
27
|
* We validate the discriminant (`source` field on objects) but use
|
|
27
28
|
* .passthrough() for provider-specific fields (repo, url, package, etc.).
|
|
28
29
|
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
30
|
+
* A string `source` is a path the consumer resolves against the marketplace
|
|
31
|
+
* root and WALKS, so this refine is the first containment gate. It refuses
|
|
32
|
+
* every spelling that leaves the root on some platform: an absolute path
|
|
33
|
+
* (POSIX root, drive letter, UNC) and a `..` segment behind EITHER separator.
|
|
34
|
+
* Claude Code's installer rejects a source that resolves outside the
|
|
35
|
+
* marketplace directory, so such an entry cannot ship either way.
|
|
36
|
+
*
|
|
37
|
+
* 🪤 The check used to split on `/` alone — `plugins\..\..\x` passed it and
|
|
38
|
+
* `path.resolve` walked it out of the root on every platform; `/etc` passed it
|
|
39
|
+
* outright — and the consumer entered whatever it named.
|
|
31
40
|
*/
|
|
32
41
|
const PluginSourceSchema = z.union([
|
|
33
42
|
z
|
|
34
43
|
.string()
|
|
35
44
|
.min(1)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
message:
|
|
39
|
-
|
|
45
|
+
.refine((s) => !isAbsoluteAnyPlatform(s) && !hasParentTraversalSegment(s), (s) => ({
|
|
46
|
+
// Names the value: the reader's next move is to fix THIS entry.
|
|
47
|
+
message: `source path "${s}" must be relative to the marketplace directory and stay inside it`
|
|
48
|
+
+ ' (no absolute path, no `..` segment) — Claude Code rejects a plugin source that'
|
|
49
|
+
+ ' resolves outside the marketplace, so this entry cannot be installed',
|
|
50
|
+
})),
|
|
40
51
|
z.object({ source: z.string() }).passthrough(),
|
|
41
52
|
]);
|
|
42
53
|
const MarketplacePluginEntrySchema = z
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"marketplace-manifest.js","sourceRoot":"","sources":["../../src/schemas/marketplace-manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD;;;;;;;;;;;;;;GAcG;AAEH,MAAM,WAAW,GAAG,CAAC;KACnB,MAAM,CAAC;IACP,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,wBAAwB,CAAC;IACjD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE;CACpC,CAAC;KACD,WAAW,EAAE,CAAC;AAEhB
|
|
1
|
+
{"version":3,"file":"marketplace-manifest.js","sourceRoot":"","sources":["../../src/schemas/marketplace-manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAC7F,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD;;;;;;;;;;;;;;GAcG;AAEH,MAAM,WAAW,GAAG,CAAC;KACnB,MAAM,CAAC;IACP,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,wBAAwB,CAAC;IACjD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE;CACpC,CAAC;KACD,WAAW,EAAE,CAAC;AAEhB;;;;;;;;;;;;;;;GAeG;AACH,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC;IAClC,CAAC;SACC,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,CAAC;SACN,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAClF,gEAAgE;QAChE,OAAO,EACN,gBAAgB,CAAC,oEAAoE;cACnF,iFAAiF;cACjF,sEAAsE;KACzE,CAAC,CAAC;IACJ,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,WAAW,EAAE;CAC9C,CAAC,CAAC;AAEH,MAAM,4BAA4B,GAAG,CAAC;KACpC,MAAM,CAAC;IACP,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,yBAAyB,CAAC;IAClD,MAAM,EAAE,kBAAkB,CAAC,QAAQ,CAAC,gDAAgD,CAAC;IACrF,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,MAAM,EAAE,CAAC;SACP,MAAM,CAAC;QACP,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QACvB,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,QAAQ,EAAE;KACpC,CAAC;SACD,WAAW,EAAE;SACb,QAAQ,EAAE;CACZ,CAAC;KACD,WAAW,EAAE,CAAC;AAEhB,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC;KACxC,MAAM,CAAC;IACP,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;IAEhE,IAAI,EAAE,CAAC;SACL,MAAM,EAAE;SACR,GAAG,CAAC,CAAC,EAAE,8BAA8B,CAAC;SACtC,QAAQ,CAAC,wBAAwB,CAAC;IAEpC,WAAW,EAAE,CAAC;SACZ,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,+CAA+C,CAAC;IAE3D,OAAO,EAAE,CAAC;SACR,MAAM,EAAE;SACR,QAAQ,EAAE;SACV,QAAQ,CAAC,8BAA8B,CAAC;IAE1C,KAAK,EAAE,WAAW,CAAC,QAAQ,CAAC,+BAA+B,CAAC;IAE5D,OAAO,EAAE,CAAC;SACR,KAAK,CAAC,4BAA4B,CAAC;SACnC,QAAQ,CAAC,+CAA+C,CAAC;CAC3D,CAAC;KACD,WAAW,EAAE;KACb,QAAQ,CAAC,oEAAoE,CAAC,CAAC;AAIjF;;;GAGG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,eAAe,CAC3D,yBAAyB,EACzB;IACC,IAAI,EAAE,qBAAqB;IAC3B,YAAY,EAAE,MAAM;CACpB,CACD,CAAC"}
|
package/dist/skill-identity.d.ts
CHANGED
|
@@ -18,4 +18,14 @@
|
|
|
18
18
|
* some fallback (typically the directory leaf) applies.
|
|
19
19
|
*/
|
|
20
20
|
export declare function readDeclaredSkillName(skillMdPath: string): string | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* The same answer, for a SKILL.md whose BYTES a caller already holds and whose
|
|
23
|
+
* path may not exist on disk at all — an entry read out of a ZIP's central
|
|
24
|
+
* directory being the case this was split out for.
|
|
25
|
+
*
|
|
26
|
+
* Deliberately the same function as the path-taking reader above rather than a
|
|
27
|
+
* second parse beside it: two spellings of "what name does this declare" is
|
|
28
|
+
* exactly how one lane starts answering differently from another.
|
|
29
|
+
*/
|
|
30
|
+
export declare function declaredSkillNameIn(content: string): string | undefined;
|
|
21
31
|
//# sourceMappingURL=skill-identity.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-identity.d.ts","sourceRoot":"","sources":["../src/skill-identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"skill-identity.d.ts","sourceRoot":"","sources":["../src/skill-identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAS7E;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CASvE"}
|
package/dist/skill-identity.js
CHANGED
|
@@ -28,6 +28,18 @@ export function readDeclaredSkillName(skillMdPath) {
|
|
|
28
28
|
catch {
|
|
29
29
|
return undefined;
|
|
30
30
|
}
|
|
31
|
+
return declaredSkillNameIn(content);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The same answer, for a SKILL.md whose BYTES a caller already holds and whose
|
|
35
|
+
* path may not exist on disk at all — an entry read out of a ZIP's central
|
|
36
|
+
* directory being the case this was split out for.
|
|
37
|
+
*
|
|
38
|
+
* Deliberately the same function as the path-taking reader above rather than a
|
|
39
|
+
* second parse beside it: two spellings of "what name does this declare" is
|
|
40
|
+
* exactly how one lane starts answering differently from another.
|
|
41
|
+
*/
|
|
42
|
+
export function declaredSkillNameIn(content) {
|
|
31
43
|
const parsed = parseFrontmatter(content);
|
|
32
44
|
if (!parsed.success)
|
|
33
45
|
return undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-identity.js","sourceRoot":"","sources":["../src/skill-identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAEnE;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,WAAmB;IACvD,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,iGAAiG;QACjG,OAAO,GAAG,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;
|
|
1
|
+
{"version":3,"file":"skill-identity.js","sourceRoot":"","sources":["../src/skill-identity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AAEnE;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CAAC,WAAmB;IACvD,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,iGAAiG;QACjG,OAAO,GAAG,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,mBAAmB,CAAC,OAAO,CAAC,CAAC;AACtC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAe;IACjD,MAAM,MAAM,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACzC,IAAI,CAAC,MAAM,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IAEtC,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IAC5C,IAAI,OAAO,QAAQ,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAEnD,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;IAChC,OAAO,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;AAC9C,CAAC"}
|
package/dist/skill-packager.d.ts
CHANGED
|
@@ -14,9 +14,10 @@
|
|
|
14
14
|
* Uses ResourceRegistry + transformContent() from @vibe-agent-toolkit/resources
|
|
15
15
|
* for link resolution and rewriting (replacing the previous inline regex approach).
|
|
16
16
|
*/
|
|
17
|
-
import { ResourceRegistry, type ResourcePopulationSource } from '@vibe-agent-toolkit/resources';
|
|
17
|
+
import { ResourceRegistry, type ResourceLink, type ResourcePopulationSource } from '@vibe-agent-toolkit/resources';
|
|
18
18
|
import { type AllowUsageLedger, type ValidationConfig, type ValidationIssue } from '@vibe-agent-toolkit/schema';
|
|
19
19
|
import { type GitTracker } from '@vibe-agent-toolkit/utils/git';
|
|
20
|
+
import { type PackagingTarget } from './content-type-routing.js';
|
|
20
21
|
import { type SkillFileEntry } from './files-config.js';
|
|
21
22
|
import { type ConventionalSuiteProbe, type DeclaredEvalSuite } from './test-input.js';
|
|
22
23
|
import { type PackagingValidationResult, type SkillPackagingConfig } from './validators/packaging-validator.js';
|
|
@@ -24,12 +25,6 @@ import { type PackagingValidationResult, type SkillPackagingConfig } from './val
|
|
|
24
25
|
* Resource naming strategy type
|
|
25
26
|
*/
|
|
26
27
|
export type ResourceNamingStrategy = 'basename' | 'resource-id' | 'preserve-path';
|
|
27
|
-
/**
|
|
28
|
-
* Packaging target: determines ZIP directory structure
|
|
29
|
-
* - 'claude-code': Standard VAT format with resources/ subdirectory (default)
|
|
30
|
-
* - 'claude-web': Claude.ai web upload format with references/, scripts/, assets/ subdirectories
|
|
31
|
-
*/
|
|
32
|
-
export type PackagingTarget = 'claude-code' | 'claude-web';
|
|
33
28
|
export interface PackageSkillOptions {
|
|
34
29
|
/**
|
|
35
30
|
* Output directory for packaged skill
|
|
@@ -111,8 +106,10 @@ export interface PackageSkillOptions {
|
|
|
111
106
|
/**
|
|
112
107
|
* Packaging target — controls the ZIP directory structure produced.
|
|
113
108
|
*
|
|
114
|
-
* - 'claude-code' (default): Standard VAT layout
|
|
115
|
-
*
|
|
109
|
+
* - 'claude-code' (default): Standard VAT layout, routed by extension into
|
|
110
|
+
* resources/, scripts/, templates/, assets/
|
|
111
|
+
* - 'claude-web': Claude.ai web upload layout — every resource flattened into
|
|
112
|
+
* references/, extensions ignored (see `PackagingTarget`)
|
|
116
113
|
*
|
|
117
114
|
* Default: 'claude-code'
|
|
118
115
|
*/
|
|
@@ -390,12 +387,87 @@ export declare function createProjectRegistry(projectRoot: string, options?: Pro
|
|
|
390
387
|
*/
|
|
391
388
|
export declare function synthesizeAssetId(assetPath: string): string;
|
|
392
389
|
/**
|
|
393
|
-
*
|
|
390
|
+
* Copy a single file, optionally rewriting markdown links using transformContent().
|
|
391
|
+
*
|
|
392
|
+
* For markdown files with rewriteLinks enabled:
|
|
393
|
+
* 1. Reads the source file
|
|
394
|
+
* 2. Finds the corresponding resource in the "from" registry
|
|
395
|
+
* 3. Calls transformContent() with the resource's links, unified rules, and "to" registry
|
|
396
|
+
* 4. Writes the result
|
|
397
|
+
*
|
|
398
|
+
* All link rewriting (bundled, excluded, inline, reference-style definitions)
|
|
399
|
+
* is handled by a single transformContent() call with ordered rules.
|
|
400
|
+
*
|
|
401
|
+
* For non-markdown files, performs a plain binary copy.
|
|
402
|
+
*/
|
|
403
|
+
/**
|
|
404
|
+
* Re-base a resource's link spans onto the frontmatter-stripped body.
|
|
405
|
+
*
|
|
406
|
+
* ## 🚨 Why this exists: the span rewrite was INERT here, and could mis-splice
|
|
407
|
+
*
|
|
408
|
+
* `transformContent` identifies each link by its parsed `[startOffset,
|
|
409
|
+
* endOffset)` span rather than by replaying a regex and correlating on href —
|
|
410
|
+
* which is the whole point, because the two grammars disagree about what the
|
|
411
|
+
* href IS. Its docstring states the precondition outright: *links must come from
|
|
412
|
+
* the same bytes as content*.
|
|
413
|
+
*
|
|
414
|
+
* This call site violated it. `resource.links` are parsed from the WHOLE FILE,
|
|
415
|
+
* and `editor.body` has the frontmatter block removed — so every offset was off
|
|
416
|
+
* by the frontmatter's length. Measured on a four-line skill: span `[45, 77)`
|
|
417
|
+
* against a body shifted by 40, where `body.slice(45, 81)` is `"ails.\n"`. Every
|
|
418
|
+
* splice declined and every link fell back to the pre-fix regex path, so the
|
|
419
|
+
* headline defect (`[](url)` silently not rewritten) was still
|
|
420
|
+
* shipping. Worse, a stale span can land on a *different*, structurally valid
|
|
421
|
+
* link and rewrite ITS href to the first link's target.
|
|
422
|
+
*
|
|
423
|
+
* ## The re-base is VERIFIED, not assumed
|
|
424
|
+
*
|
|
425
|
+
* Subtracting `content.length - body.length` is correct if and only if `body` is
|
|
426
|
+
* a literal SUFFIX of `content` — that is exactly the statement "every body index
|
|
427
|
+
* `i` is content index `i + offset`". `String.endsWith` decides it outright, so
|
|
428
|
+
* the arithmetic is checked rather than argued, and a body that is not a suffix
|
|
429
|
+
* comes back with its spans REMOVED instead of with coordinates nothing verified.
|
|
430
|
+
* `openFrontmatter` does yield a suffix today, across CRLF, a commented block, an
|
|
431
|
+
* absent block and empty input; the check is what keeps that a fact rather than a
|
|
432
|
+
* comment that outlives the code it describes.
|
|
433
|
+
*
|
|
434
|
+
* ⛔ **This used to claim `splicableFrom` as its backstop, and that claim was
|
|
435
|
+
* false.** The words were: "`splicableFrom` refuses any span whose destination is
|
|
436
|
+
* not exactly the parser's href, so a misalignment that survives this degrades to
|
|
437
|
+
* *no rewrite* rather than to a wrong one." It does not. That comparison is keyed
|
|
438
|
+
* on the HREF, which two links in one document routinely share, so a stale span
|
|
439
|
+
* landing on a same-href neighbour passes it and the neighbour is rewritten
|
|
440
|
+
* through the first link's metadata. Constructed and pinned in
|
|
441
|
+
* `packages/resources/test/content-transform.test.ts` › *two links sharing an
|
|
442
|
+
* href defeat the destination comparison*, where a tuned frontmatter length makes
|
|
443
|
+
* two labels swap places. A mitigation keyed on a value the two candidates have
|
|
444
|
+
* in common cannot be a guarantee, and a guard resting on one is resting on
|
|
445
|
+
* nothing.
|
|
446
|
+
*
|
|
447
|
+
* 🔑 What holds instead, in full, because the precondition has two halves:
|
|
448
|
+
*
|
|
449
|
+
* 1. *The spans address `content`* — discharged by the reader, not by this
|
|
450
|
+
* function. `resource.links` and `content` must come from the same decode of
|
|
451
|
+
* the same file, which is why the caller's read is pinned to
|
|
452
|
+
* `readTextContent` with a 🚨 of its own. A second reader is the one way this
|
|
453
|
+
* half fails, and it fails invisibly.
|
|
454
|
+
* 2. *The subtraction maps `content` onto `body`* — discharged here, by
|
|
455
|
+
* `endsWith`.
|
|
456
|
+
*
|
|
457
|
+
* `splicableFrom`'s destination check remains a useful mitigation for the
|
|
458
|
+
* residue. It is not counted on, and nothing here degrades gracefully because of
|
|
459
|
+
* it.
|
|
394
460
|
*
|
|
395
|
-
*
|
|
396
|
-
*
|
|
461
|
+
* @param content - The file as read, which the links were parsed from
|
|
462
|
+
* @param body - The frontmatter-stripped body the rewrite will run over
|
|
463
|
+
* @param links - The resource's links, carrying whole-file offsets
|
|
464
|
+
* @param onUnverifiable - Called when `body` is not a suffix of `content`, so the
|
|
465
|
+
* caller can say which file lost its span-driven rewrite. Never called on the
|
|
466
|
+
* normal path.
|
|
467
|
+
* @returns The same links with offsets stated against `body`, or with no offsets
|
|
468
|
+
* at all when the re-base could not be verified
|
|
397
469
|
*/
|
|
398
|
-
export declare function
|
|
470
|
+
export declare function bodyRelativeLinks(content: string, body: string, links: readonly ResourceLink[], onUnverifiable: () => void): ResourceLink[];
|
|
399
471
|
/**
|
|
400
472
|
* Extract H1 title from markdown content
|
|
401
473
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skill-packager.d.ts","sourceRoot":"","sources":["../src/skill-packager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAMH,OAAO,EAGL,gBAAgB,
|
|
1
|
+
{"version":3,"file":"skill-packager.d.ts","sourceRoot":"","sources":["../src/skill-packager.ts"],"names":[],"mappings":"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"}
|
package/dist/skill-packager.js
CHANGED
|
@@ -20,12 +20,14 @@ import { basename, dirname } from 'node:path';
|
|
|
20
20
|
import { DeferredArtifacts, DuplicateResourceIdError, ResourceRegistry, loadConfig, openFrontmatter, resolveLocalHref, rewriteFrontmatterUriReferencesFromSchema, rewriteHtmlLinks, transformContent, parseFileCached, } from '@vibe-agent-toolkit/resources';
|
|
21
21
|
import { allowUnusedIssues, createAllowUsageLedger, runValidationFramework, } from '@vibe-agent-toolkit/schema';
|
|
22
22
|
import { findProjectRoot, isGlob, issueLocation, resolveAssetReference, toForwardSlash, safePath, } from '@vibe-agent-toolkit/utils';
|
|
23
|
-
import {
|
|
23
|
+
import { readTextContent } from '@vibe-agent-toolkit/utils/fs';
|
|
24
|
+
import { getResourceSubdirForFile } from './content-type-routing.js';
|
|
24
25
|
import { applyFilesConfig, buildArtifactHint, droppedGlobMatchesToIssues, explicitFilesConfigDests, globEntryDest, skippedGlobMatchesToIssues, } from './files-config.js';
|
|
25
26
|
import { READ_REMEDY, withFsAttribution } from './fs-attribution.js';
|
|
26
|
-
import { checkBrokenPackagedLinks, checkUnreferencedFiles } from './post-build-checks.js';
|
|
27
|
+
import { checkBrokenPackagedLinks, checkMissingReferencedPaths, checkUnreferencedFiles } from './post-build-checks.js';
|
|
27
28
|
import { checkPackagedTestInput, partitionTestInputFileEntries, resolveTestInputDirs, testInputExcludeRules, testInputFileEntryIssues, testInputLinkIssues, } from './test-input.js';
|
|
28
29
|
import { detectPackagedAgentInstructionFiles } from './validators/agent-instruction-presence.js';
|
|
30
|
+
import { checkPackagedSizeLimit } from './validators/packaged-size-limit.js';
|
|
29
31
|
import { validateSkillForPackaging } from './validators/packaging-validator.js';
|
|
30
32
|
import { materializeIssue } from './validators/rule-engine/index.js';
|
|
31
33
|
import { deferredAssetsToIssues, walkerExclusionsToIssues } from './validators/walker-to-issues.js';
|
|
@@ -40,18 +42,20 @@ const WRITE_ACTION = 'written into the bundle';
|
|
|
40
42
|
* `{{link.rawText}}`, not `{{link.text}}`, for the same two reasons the rewrite
|
|
41
43
|
* branch uses it (see `bundledLinkTemplate`):
|
|
42
44
|
*
|
|
43
|
-
* - **
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* one phrase for an unrelated one in shipped prose; the rewrite branch never
|
|
48
|
-
* exposed it because it re-emits `rawText`.
|
|
45
|
+
* - **Per-occurrence identity.** `link.text` is a property of the parsed link,
|
|
46
|
+
* and two occurrences sharing an href are two links whose text may differ.
|
|
47
|
+
* `rawText` is always the text of the occurrence actually being replaced, so
|
|
48
|
+
* it cannot swap one phrase for an unrelated one in shipped prose.
|
|
49
49
|
* - **Formatting.** `rawText` keeps the inline markup the author wrote, so
|
|
50
50
|
* ``[`foo.yaml`](…)`` strips to ``` `foo.yaml` ``` rather than bare `foo.yaml`.
|
|
51
51
|
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
52
|
+
* > This used to explain the first reason as a defence against `transformContent`
|
|
53
|
+
* > keying parsed links by href and letting the FIRST occurrence win. That
|
|
54
|
+
* > correlation is gone: `transformContent` now splices each parsed link at its
|
|
55
|
+
* > own `[startOffset, endOffset)` span, so there is no shared-href map to collide
|
|
56
|
+
* > in for any link the parser located. `rawText` remains correct and remains the
|
|
57
|
+
* > right choice — the reasoning above no longer depends on a collision that the
|
|
58
|
+
* > rewriter can still have.
|
|
55
59
|
*/
|
|
56
60
|
const DEFAULT_STRIP_TEMPLATE = '{{link.rawText}}';
|
|
57
61
|
/**
|
|
@@ -461,6 +465,30 @@ export async function packageSkill(skillPath, options = {}) {
|
|
|
461
465
|
...collisionIssues,
|
|
462
466
|
...await checkUnreferencedFiles(outputPath, filesConfigDests),
|
|
463
467
|
...await checkBrokenPackagedLinks(outputPath, droppedGlobDests),
|
|
468
|
+
// The inverse of checkUnreferencedFiles: paths the docs NAME that the bundle
|
|
469
|
+
// does not contain. Built phase only — a `files:` dest exists here and not in
|
|
470
|
+
// the source tree, so the same check at source phase flags every injected
|
|
471
|
+
// script.
|
|
472
|
+
//
|
|
473
|
+
// SKILL-LOCAL, and this is the ONLY caller. The packager knows its own output
|
|
474
|
+
// directory, not the plugin the skill will be installed into, so there is no
|
|
475
|
+
// wider root to give it — the sibling-search parameter that measured 1.9%
|
|
476
|
+
// instead of 3.8% was deleted for having no caller. The shipped rate is 3.8%.
|
|
477
|
+
...await checkMissingReferencedPaths(outputPath, target),
|
|
478
|
+
// The only byte measurement in the pipeline. Built phase for the same reason
|
|
479
|
+
// as its neighbour above: a `files:` entry materializes files here that the
|
|
480
|
+
// source tree does not have, so the bytes that ship are only knowable now.
|
|
481
|
+
//
|
|
482
|
+
// ⚠️ Runs before step 14, so it does not weigh what `generatePackageArtifacts`
|
|
483
|
+
// adds. Measured, so the residue is not a guess: the `zip` and `npm` formats
|
|
484
|
+
// write to `<outputPath>.zip` / `.tgz`, OUTSIDE the bundle and outside the
|
|
485
|
+
// upload; only the `npm` format's synthetic package.json and the `marketplace`
|
|
486
|
+
// format's manifest land inside, and both are a few hundred bytes. The order
|
|
487
|
+
// is not free to change — checkUnreferencedFiles two lines up would flag that
|
|
488
|
+
// same synthetic package.json — so the under-count is stated rather than
|
|
489
|
+
// fixed. If an artifact step ever writes something LARGE into outputPath, this
|
|
490
|
+
// call has to move after it and the framework run with it.
|
|
491
|
+
...checkPackagedSizeLimit(outputPath),
|
|
464
492
|
// A receipt for every file a glob matched and the never-package list refused.
|
|
465
493
|
// Reported as an issue, not written to stderr: a file vanishing from a bundle
|
|
466
494
|
// has to be visible in `issueCounts`, or CI reads a clean report for a build
|
|
@@ -619,7 +647,7 @@ function withRunAllowUnused(framework, ledger) {
|
|
|
619
647
|
*/
|
|
620
648
|
async function runPostBuildValidation(outputPath, validation, allowLedger) {
|
|
621
649
|
const builtSkillPath = safePath.join(outputPath, 'SKILL.md');
|
|
622
|
-
return validateSkillForPackaging(builtSkillPath, validation ? { validation } : undefined, 'built', { allowLedger });
|
|
650
|
+
return validateSkillForPackaging(builtSkillPath, validation ? { validation } : undefined, 'built', { allowLedger, unreadable: 'refuse' });
|
|
623
651
|
}
|
|
624
652
|
/**
|
|
625
653
|
* Assemble the final PackageSkillResult from intermediate data.
|
|
@@ -694,6 +722,9 @@ export async function createProjectRegistry(projectRoot, options = {}) {
|
|
|
694
722
|
const registry = await ResourceRegistry.fromCrawl({
|
|
695
723
|
baseDir: projectRoot,
|
|
696
724
|
include: ['**/*.md'],
|
|
725
|
+
// A build must not ship a shorter bundle: a directory this crawl cannot
|
|
726
|
+
// list refuses the run by name — see `RegistryUnreadablePolicy`.
|
|
727
|
+
unreadable: 'refuse',
|
|
697
728
|
...(options.populationSource !== undefined && { populationSource: options.populationSource }),
|
|
698
729
|
}, config === undefined ? undefined : { config });
|
|
699
730
|
registry.resolveLinks();
|
|
@@ -1096,21 +1127,6 @@ function stampDeferredDestResolvedId(resources, absDestTarget, id) {
|
|
|
1096
1127
|
}
|
|
1097
1128
|
return linked;
|
|
1098
1129
|
}
|
|
1099
|
-
// ============================================================================
|
|
1100
|
-
// Path Map Building
|
|
1101
|
-
// ============================================================================
|
|
1102
|
-
/**
|
|
1103
|
-
* Determine the resource subdirectory for a file.
|
|
1104
|
-
*
|
|
1105
|
-
* For claude-web target: uses the existing references directory.
|
|
1106
|
-
* For claude-code target: uses content-type routing based on file extension.
|
|
1107
|
-
*/
|
|
1108
|
-
export function getResourceSubdirForFile(filePath, target) {
|
|
1109
|
-
if (target === 'claude-web') {
|
|
1110
|
-
return CLAUDE_WEB_REFERENCES_SUBDIR;
|
|
1111
|
-
}
|
|
1112
|
-
return getTargetSubdir(filePath);
|
|
1113
|
-
}
|
|
1114
1130
|
/**
|
|
1115
1131
|
* The FILENAME_COLLISION finding for one pair of sources that package to one dest.
|
|
1116
1132
|
*
|
|
@@ -1295,6 +1311,106 @@ async function copyAndRewriteFiles(skillPath, bundledFiles, ctx) {
|
|
|
1295
1311
|
*
|
|
1296
1312
|
* For non-markdown files, performs a plain binary copy.
|
|
1297
1313
|
*/
|
|
1314
|
+
/**
|
|
1315
|
+
* Re-base a resource's link spans onto the frontmatter-stripped body.
|
|
1316
|
+
*
|
|
1317
|
+
* ## 🚨 Why this exists: the span rewrite was INERT here, and could mis-splice
|
|
1318
|
+
*
|
|
1319
|
+
* `transformContent` identifies each link by its parsed `[startOffset,
|
|
1320
|
+
* endOffset)` span rather than by replaying a regex and correlating on href —
|
|
1321
|
+
* which is the whole point, because the two grammars disagree about what the
|
|
1322
|
+
* href IS. Its docstring states the precondition outright: *links must come from
|
|
1323
|
+
* the same bytes as content*.
|
|
1324
|
+
*
|
|
1325
|
+
* This call site violated it. `resource.links` are parsed from the WHOLE FILE,
|
|
1326
|
+
* and `editor.body` has the frontmatter block removed — so every offset was off
|
|
1327
|
+
* by the frontmatter's length. Measured on a four-line skill: span `[45, 77)`
|
|
1328
|
+
* against a body shifted by 40, where `body.slice(45, 81)` is `"ails.\n"`. Every
|
|
1329
|
+
* splice declined and every link fell back to the pre-fix regex path, so the
|
|
1330
|
+
* headline defect (`[](url)` silently not rewritten) was still
|
|
1331
|
+
* shipping. Worse, a stale span can land on a *different*, structurally valid
|
|
1332
|
+
* link and rewrite ITS href to the first link's target.
|
|
1333
|
+
*
|
|
1334
|
+
* ## The re-base is VERIFIED, not assumed
|
|
1335
|
+
*
|
|
1336
|
+
* Subtracting `content.length - body.length` is correct if and only if `body` is
|
|
1337
|
+
* a literal SUFFIX of `content` — that is exactly the statement "every body index
|
|
1338
|
+
* `i` is content index `i + offset`". `String.endsWith` decides it outright, so
|
|
1339
|
+
* the arithmetic is checked rather than argued, and a body that is not a suffix
|
|
1340
|
+
* comes back with its spans REMOVED instead of with coordinates nothing verified.
|
|
1341
|
+
* `openFrontmatter` does yield a suffix today, across CRLF, a commented block, an
|
|
1342
|
+
* absent block and empty input; the check is what keeps that a fact rather than a
|
|
1343
|
+
* comment that outlives the code it describes.
|
|
1344
|
+
*
|
|
1345
|
+
* ⛔ **This used to claim `splicableFrom` as its backstop, and that claim was
|
|
1346
|
+
* false.** The words were: "`splicableFrom` refuses any span whose destination is
|
|
1347
|
+
* not exactly the parser's href, so a misalignment that survives this degrades to
|
|
1348
|
+
* *no rewrite* rather than to a wrong one." It does not. That comparison is keyed
|
|
1349
|
+
* on the HREF, which two links in one document routinely share, so a stale span
|
|
1350
|
+
* landing on a same-href neighbour passes it and the neighbour is rewritten
|
|
1351
|
+
* through the first link's metadata. Constructed and pinned in
|
|
1352
|
+
* `packages/resources/test/content-transform.test.ts` › *two links sharing an
|
|
1353
|
+
* href defeat the destination comparison*, where a tuned frontmatter length makes
|
|
1354
|
+
* two labels swap places. A mitigation keyed on a value the two candidates have
|
|
1355
|
+
* in common cannot be a guarantee, and a guard resting on one is resting on
|
|
1356
|
+
* nothing.
|
|
1357
|
+
*
|
|
1358
|
+
* 🔑 What holds instead, in full, because the precondition has two halves:
|
|
1359
|
+
*
|
|
1360
|
+
* 1. *The spans address `content`* — discharged by the reader, not by this
|
|
1361
|
+
* function. `resource.links` and `content` must come from the same decode of
|
|
1362
|
+
* the same file, which is why the caller's read is pinned to
|
|
1363
|
+
* `readTextContent` with a 🚨 of its own. A second reader is the one way this
|
|
1364
|
+
* half fails, and it fails invisibly.
|
|
1365
|
+
* 2. *The subtraction maps `content` onto `body`* — discharged here, by
|
|
1366
|
+
* `endsWith`.
|
|
1367
|
+
*
|
|
1368
|
+
* `splicableFrom`'s destination check remains a useful mitigation for the
|
|
1369
|
+
* residue. It is not counted on, and nothing here degrades gracefully because of
|
|
1370
|
+
* it.
|
|
1371
|
+
*
|
|
1372
|
+
* @param content - The file as read, which the links were parsed from
|
|
1373
|
+
* @param body - The frontmatter-stripped body the rewrite will run over
|
|
1374
|
+
* @param links - The resource's links, carrying whole-file offsets
|
|
1375
|
+
* @param onUnverifiable - Called when `body` is not a suffix of `content`, so the
|
|
1376
|
+
* caller can say which file lost its span-driven rewrite. Never called on the
|
|
1377
|
+
* normal path.
|
|
1378
|
+
* @returns The same links with offsets stated against `body`, or with no offsets
|
|
1379
|
+
* at all when the re-base could not be verified
|
|
1380
|
+
*/
|
|
1381
|
+
export function bodyRelativeLinks(content, body, links, onUnverifiable) {
|
|
1382
|
+
if (!content.endsWith(body)) {
|
|
1383
|
+
onUnverifiable();
|
|
1384
|
+
return links.map(withoutSpan);
|
|
1385
|
+
}
|
|
1386
|
+
const offset = content.length - body.length;
|
|
1387
|
+
if (offset === 0)
|
|
1388
|
+
return [...links];
|
|
1389
|
+
return links.map((link) => ({
|
|
1390
|
+
...link,
|
|
1391
|
+
...(link.startOffset === undefined ? {} : { startOffset: link.startOffset - offset }),
|
|
1392
|
+
...(link.endOffset === undefined ? {} : { endOffset: link.endOffset - offset }),
|
|
1393
|
+
}));
|
|
1394
|
+
}
|
|
1395
|
+
/**
|
|
1396
|
+
* The link with its coordinates dropped and everything else kept.
|
|
1397
|
+
*
|
|
1398
|
+
* ⚠️ Dropping them is the point, and returning the link unchanged would be the
|
|
1399
|
+
* bug: an unrebased whole-file span still ADDRESSES the body's bytes, just the
|
|
1400
|
+
* wrong ones, so `splicableFrom` would happily splice at it. Without a span the
|
|
1401
|
+
* link is `UNRECOGNISED`, which routes it to the pre-span regex replay — the
|
|
1402
|
+
* behaviour this call site had before spans existed. A documented degrade, not a
|
|
1403
|
+
* silent one; the caller warns.
|
|
1404
|
+
*
|
|
1405
|
+
* @param link - A link whose offsets could not be re-based
|
|
1406
|
+
* @returns The same link with no `startOffset` and no `endOffset` key
|
|
1407
|
+
*/
|
|
1408
|
+
function withoutSpan(link) {
|
|
1409
|
+
const stripped = { ...link };
|
|
1410
|
+
delete stripped.startOffset;
|
|
1411
|
+
delete stripped.endOffset;
|
|
1412
|
+
return stripped;
|
|
1413
|
+
}
|
|
1298
1414
|
async function copyAndRewriteFile(sourcePath, targetPath, ctx) {
|
|
1299
1415
|
// Through the SAME attribution point as the `files:` lanes. This is the default
|
|
1300
1416
|
// path for every ordinary markdown-linked file in a build — the most-travelled
|
|
@@ -1316,10 +1432,34 @@ async function copyAndRewriteFile(sourcePath, targetPath, ctx) {
|
|
|
1316
1432
|
await withFsAttribution(subject, () => copyFile(sourcePath, targetPath));
|
|
1317
1433
|
return;
|
|
1318
1434
|
}
|
|
1319
|
-
// Read source file
|
|
1320
|
-
|
|
1321
|
-
//
|
|
1322
|
-
|
|
1435
|
+
// Read source file.
|
|
1436
|
+
//
|
|
1437
|
+
// 🚨 `readTextContent`, never `readFile(path, 'utf-8')` — and here the reason
|
|
1438
|
+
// is sharper than the general one `link-parser.ts:149` gives. THE LINKS WERE
|
|
1439
|
+
// PARSED FROM THIS FILE BY THAT READER, and `bodyRelativeLinks` below
|
|
1440
|
+
// re-bases their offsets by differencing two string lengths. Two different
|
|
1441
|
+
// readers make that subtraction meaningless: `readTextContent` strips a BOM
|
|
1442
|
+
// and decodes UTF-16/32, so on a BOM-bearing file `readFile` returned a
|
|
1443
|
+
// string one character longer, `OPENING_FENCE` (`/^---\r?\n/`) then failed to
|
|
1444
|
+
// match, `openFrontmatter` reported no frontmatter, the offset came out 0,
|
|
1445
|
+
// and every span stayed whole-file — silently reverting the fix this call
|
|
1446
|
+
// site exists to deliver.
|
|
1447
|
+
//
|
|
1448
|
+
// ⛔ This comment used to add "it failed CLOSED rather than corrupting, only
|
|
1449
|
+
// because `splicableFrom` compares the destination to the href." That is not
|
|
1450
|
+
// a guarantee and must not be read as one: the destination check is keyed on
|
|
1451
|
+
// the href, which two links in one document routinely share, so a stale span
|
|
1452
|
+
// landing on a same-href neighbour passes it (constructed in
|
|
1453
|
+
// `content-transform.test.ts` › *two links sharing an href defeat the
|
|
1454
|
+
// destination comparison*). The BOM shift also survives
|
|
1455
|
+
// `bodyRelativeLinks`'s own `endsWith` check, because a body equal to the
|
|
1456
|
+
// content IS a suffix of it — nothing downstream can see that the links came
|
|
1457
|
+
// from a different decode. **One reader is the only thing standing between
|
|
1458
|
+
// this lane and a wrong rewrite.** Do not swap it.
|
|
1459
|
+
//
|
|
1460
|
+
// It also stops a UTF-16 source being written back as mojibake, which the
|
|
1461
|
+
// `utf-8` read did on the copy as well as the rewrite.
|
|
1462
|
+
const { text: content } = await withFsAttribution(subject, () => readTextContent(sourcePath),
|
|
1323
1463
|
// Not "copied": the read is the step that failed, and this lane reads before
|
|
1324
1464
|
// it rewrites, so naming the copy would point past the actual failure.
|
|
1325
1465
|
'read for link rewriting', READ_REMEDY);
|
|
@@ -1362,7 +1502,13 @@ async function copyAndRewriteFile(sourcePath, targetPath, ctx) {
|
|
|
1362
1502
|
// for the existing rule/template body-link rewrite contract (unchanged).
|
|
1363
1503
|
const editor = openFrontmatter(content);
|
|
1364
1504
|
// Body rewrite (existing behavior, unchanged contract).
|
|
1365
|
-
|
|
1505
|
+
const rebased = bodyRelativeLinks(content, editor.body, resource.links, () => {
|
|
1506
|
+
ctx.warn(`Rewrote links in '${sourcePath}' without parsed spans: the frontmatter-stripped body is not a ` +
|
|
1507
|
+
`suffix of the file as read, so the offsets the parser reported cannot be moved onto it. ` +
|
|
1508
|
+
`Links are matched by href instead, which is the pre-span behaviour — a link the two grammars ` +
|
|
1509
|
+
`disagree about (an image inside a link, most often) may go unrewritten.`);
|
|
1510
|
+
});
|
|
1511
|
+
editor.body = transformContent(editor.body, rebased, {
|
|
1366
1512
|
linkRewriteRules: ctx.rewriteRules,
|
|
1367
1513
|
resourceRegistry: ctx.toRegistry,
|
|
1368
1514
|
sourceFilePath: targetPath, // Output path so relativePath is computed from output location
|