@vibe-agent-toolkit/agent-skills 0.1.42 → 0.2.0-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 (322) hide show
  1. package/README.md +5 -5
  2. package/dist/builder.d.ts.map +1 -1
  3. package/dist/builder.js +7 -17
  4. package/dist/builder.js.map +1 -1
  5. package/dist/content-type-routing.d.ts +32 -0
  6. package/dist/content-type-routing.d.ts.map +1 -1
  7. package/dist/content-type-routing.js +23 -0
  8. package/dist/content-type-routing.js.map +1 -1
  9. package/dist/files-config.d.ts +34 -1
  10. package/dist/files-config.d.ts.map +1 -1
  11. package/dist/files-config.js +277 -39
  12. package/dist/files-config.js.map +1 -1
  13. package/dist/fs-attribution.d.ts +45 -0
  14. package/dist/fs-attribution.d.ts.map +1 -0
  15. package/dist/fs-attribution.js +57 -0
  16. package/dist/fs-attribution.js.map +1 -0
  17. package/dist/import.d.ts.map +1 -1
  18. package/dist/import.js +0 -4
  19. package/dist/import.js.map +1 -1
  20. package/dist/index.d.ts +13 -8
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +25 -7
  23. package/dist/index.js.map +1 -1
  24. package/dist/inventory/detectors/declared-but-missing.d.ts +1 -1
  25. package/dist/inventory/detectors/declared-but-missing.d.ts.map +1 -1
  26. package/dist/inventory/detectors/marketplace-source-missing.d.ts +1 -1
  27. package/dist/inventory/detectors/marketplace-source-missing.d.ts.map +1 -1
  28. package/dist/inventory/detectors/present-but-undeclared.d.ts +1 -1
  29. package/dist/inventory/detectors/present-but-undeclared.d.ts.map +1 -1
  30. package/dist/inventory/detectors/reference-target-missing.d.ts +1 -1
  31. package/dist/inventory/detectors/reference-target-missing.d.ts.map +1 -1
  32. package/dist/inventory/index.d.ts +1 -1
  33. package/dist/inventory/index.d.ts.map +1 -1
  34. package/dist/inventory/index.js +1 -1
  35. package/dist/inventory/index.js.map +1 -1
  36. package/dist/inventory/serialize.d.ts +4 -4
  37. package/dist/inventory/serialize.d.ts.map +1 -1
  38. package/dist/inventory/serialize.js +6 -6
  39. package/dist/inventory/serialize.js.map +1 -1
  40. package/dist/inventory/types.d.ts +8 -0
  41. package/dist/inventory/types.d.ts.map +1 -1
  42. package/dist/inventory/types.js.map +1 -1
  43. package/dist/link-graph-members.d.ts +18 -0
  44. package/dist/link-graph-members.d.ts.map +1 -0
  45. package/dist/link-graph-members.js +18 -0
  46. package/dist/link-graph-members.js.map +1 -0
  47. package/dist/parsers/frontmatter-parser.d.ts.map +1 -1
  48. package/dist/parsers/frontmatter-parser.js +30 -6
  49. package/dist/parsers/frontmatter-parser.js.map +1 -1
  50. package/dist/plugin-distribution-layout.d.ts +70 -6
  51. package/dist/plugin-distribution-layout.d.ts.map +1 -1
  52. package/dist/plugin-distribution-layout.js +84 -11
  53. package/dist/plugin-distribution-layout.js.map +1 -1
  54. package/dist/post-build-checks.d.ts +38 -1
  55. package/dist/post-build-checks.d.ts.map +1 -1
  56. package/dist/post-build-checks.js +68 -17
  57. package/dist/post-build-checks.js.map +1 -1
  58. package/dist/projection/skill-extent.d.ts +247 -0
  59. package/dist/projection/skill-extent.d.ts.map +1 -0
  60. package/dist/projection/skill-extent.js +560 -0
  61. package/dist/projection/skill-extent.js.map +1 -0
  62. package/dist/schemas/agent-skill-frontmatter.js +1 -1
  63. package/dist/schemas/agent-skill-frontmatter.js.map +1 -1
  64. package/dist/schemas/allowed-tools.d.ts +31 -0
  65. package/dist/schemas/allowed-tools.d.ts.map +1 -0
  66. package/dist/schemas/allowed-tools.js +88 -0
  67. package/dist/schemas/allowed-tools.js.map +1 -0
  68. package/dist/schemas/index.d.ts +1 -0
  69. package/dist/schemas/index.d.ts.map +1 -1
  70. package/dist/schemas/index.js +1 -0
  71. package/dist/schemas/index.js.map +1 -1
  72. package/dist/schemas/installed-plugins-registry.d.ts.map +1 -1
  73. package/dist/schemas/installed-plugins-registry.js +7 -1
  74. package/dist/schemas/installed-plugins-registry.js.map +1 -1
  75. package/dist/schemas/marketplace-manifest.d.ts.map +1 -1
  76. package/dist/schemas/marketplace-manifest.js +17 -6
  77. package/dist/schemas/marketplace-manifest.js.map +1 -1
  78. package/dist/skill-identity.d.ts +18 -3
  79. package/dist/skill-identity.d.ts.map +1 -1
  80. package/dist/skill-identity.js +25 -6
  81. package/dist/skill-identity.js.map +1 -1
  82. package/dist/skill-packager.d.ts +144 -20
  83. package/dist/skill-packager.d.ts.map +1 -1
  84. package/dist/skill-packager.js +447 -105
  85. package/dist/skill-packager.js.map +1 -1
  86. package/dist/skill-source/content-hash.d.ts.map +1 -1
  87. package/dist/skill-source/content-hash.js +21 -10
  88. package/dist/skill-source/content-hash.js.map +1 -1
  89. package/dist/skill-source/fetch-cache.d.ts.map +1 -1
  90. package/dist/skill-source/fetch-cache.js +0 -5
  91. package/dist/skill-source/fetch-cache.js.map +1 -1
  92. package/dist/skill-source/git-clone.d.ts +1 -1
  93. package/dist/skill-source/git-clone.d.ts.map +1 -1
  94. package/dist/skill-source/git-clone.js +10 -10
  95. package/dist/skill-source/git-clone.js.map +1 -1
  96. package/dist/skill-source/sources/url-source.d.ts.map +1 -1
  97. package/dist/skill-source/sources/url-source.js +2 -2
  98. package/dist/skill-source/sources/url-source.js.map +1 -1
  99. package/dist/skill-source/stage.d.ts.map +1 -1
  100. package/dist/skill-source/stage.js +0 -6
  101. package/dist/skill-source/stage.js.map +1 -1
  102. package/dist/skill-test/baseline-delta.d.ts +1575 -0
  103. package/dist/skill-test/baseline-delta.d.ts.map +1 -0
  104. package/dist/skill-test/baseline-delta.js +272 -0
  105. package/dist/skill-test/baseline-delta.js.map +1 -0
  106. package/dist/skill-test/baseline-integrity.d.ts +944 -0
  107. package/dist/skill-test/baseline-integrity.d.ts.map +1 -0
  108. package/dist/skill-test/baseline-integrity.js +3090 -0
  109. package/dist/skill-test/baseline-integrity.js.map +1 -0
  110. package/dist/skill-test/build-hook.d.ts +3 -2
  111. package/dist/skill-test/build-hook.d.ts.map +1 -1
  112. package/dist/skill-test/build-hook.js +4 -5
  113. package/dist/skill-test/build-hook.js.map +1 -1
  114. package/dist/skill-test/configure-writer.js +1 -1
  115. package/dist/skill-test/configure-writer.js.map +1 -1
  116. package/dist/skill-test/declared-env.d.ts +5 -4
  117. package/dist/skill-test/declared-env.d.ts.map +1 -1
  118. package/dist/skill-test/declared-env.js +8 -9
  119. package/dist/skill-test/declared-env.js.map +1 -1
  120. package/dist/skill-test/eval-executor.d.ts +21 -5
  121. package/dist/skill-test/eval-executor.d.ts.map +1 -1
  122. package/dist/skill-test/eval-executor.js +6 -6
  123. package/dist/skill-test/eval-executor.js.map +1 -1
  124. package/dist/skill-test/eval-fragment.d.ts +106 -28
  125. package/dist/skill-test/eval-fragment.d.ts.map +1 -1
  126. package/dist/skill-test/eval-fragment.js +78 -16
  127. package/dist/skill-test/eval-fragment.js.map +1 -1
  128. package/dist/skill-test/eval-grader.d.ts +65 -7
  129. package/dist/skill-test/eval-grader.d.ts.map +1 -1
  130. package/dist/skill-test/eval-grader.js +263 -64
  131. package/dist/skill-test/eval-grader.js.map +1 -1
  132. package/dist/skill-test/eval-inputs.d.ts +110 -8
  133. package/dist/skill-test/eval-inputs.d.ts.map +1 -1
  134. package/dist/skill-test/eval-inputs.js +177 -22
  135. package/dist/skill-test/eval-inputs.js.map +1 -1
  136. package/dist/skill-test/eval-lint.d.ts +17 -4
  137. package/dist/skill-test/eval-lint.d.ts.map +1 -1
  138. package/dist/skill-test/eval-lint.js +22 -9
  139. package/dist/skill-test/eval-lint.js.map +1 -1
  140. package/dist/skill-test/eval-suite-isolation.d.ts.map +1 -1
  141. package/dist/skill-test/eval-suite-isolation.js +8 -5
  142. package/dist/skill-test/eval-suite-isolation.js.map +1 -1
  143. package/dist/skill-test/evals-template.d.ts +1 -1
  144. package/dist/skill-test/evals-template.d.ts.map +1 -1
  145. package/dist/skill-test/evals-template.js +1 -3
  146. package/dist/skill-test/evals-template.js.map +1 -1
  147. package/dist/skill-test/executor-prompt.d.ts +15 -7
  148. package/dist/skill-test/executor-prompt.d.ts.map +1 -1
  149. package/dist/skill-test/executor-prompt.js +10 -7
  150. package/dist/skill-test/executor-prompt.js.map +1 -1
  151. package/dist/skill-test/failure-reason.d.ts +113 -0
  152. package/dist/skill-test/failure-reason.d.ts.map +1 -0
  153. package/dist/skill-test/failure-reason.js +124 -0
  154. package/dist/skill-test/failure-reason.js.map +1 -0
  155. package/dist/skill-test/fragment-merge.d.ts +3 -20
  156. package/dist/skill-test/fragment-merge.d.ts.map +1 -1
  157. package/dist/skill-test/fragment-merge.js +67 -8
  158. package/dist/skill-test/fragment-merge.js.map +1 -1
  159. package/dist/skill-test/grader-prompt.d.ts +29 -9
  160. package/dist/skill-test/grader-prompt.d.ts.map +1 -1
  161. package/dist/skill-test/grader-prompt.js +264 -68
  162. package/dist/skill-test/grader-prompt.js.map +1 -1
  163. package/dist/skill-test/grader-text.d.ts +145 -0
  164. package/dist/skill-test/grader-text.d.ts.map +1 -0
  165. package/dist/skill-test/grader-text.js +410 -0
  166. package/dist/skill-test/grader-text.js.map +1 -0
  167. package/dist/skill-test/grading-adapter.d.ts +38 -2
  168. package/dist/skill-test/grading-adapter.d.ts.map +1 -1
  169. package/dist/skill-test/grading-adapter.js +57 -9
  170. package/dist/skill-test/grading-adapter.js.map +1 -1
  171. package/dist/skill-test/grading-schema.d.ts +160 -5
  172. package/dist/skill-test/grading-schema.d.ts.map +1 -1
  173. package/dist/skill-test/grading-schema.js +66 -7
  174. package/dist/skill-test/grading-schema.js.map +1 -1
  175. package/dist/skill-test/harness-location.d.ts +3 -2
  176. package/dist/skill-test/harness-location.d.ts.map +1 -1
  177. package/dist/skill-test/harness-location.js +5 -16
  178. package/dist/skill-test/harness-location.js.map +1 -1
  179. package/dist/skill-test/index.d.ts +2 -2
  180. package/dist/skill-test/index.d.ts.map +1 -1
  181. package/dist/skill-test/index.js +2 -2
  182. package/dist/skill-test/index.js.map +1 -1
  183. package/dist/skill-test/lock.d.ts +58 -1
  184. package/dist/skill-test/lock.d.ts.map +1 -1
  185. package/dist/skill-test/lock.js +78 -6
  186. package/dist/skill-test/lock.js.map +1 -1
  187. package/dist/skill-test/pipeline.d.ts +19 -1
  188. package/dist/skill-test/pipeline.d.ts.map +1 -1
  189. package/dist/skill-test/pipeline.js +21 -10
  190. package/dist/skill-test/pipeline.js.map +1 -1
  191. package/dist/skill-test/preflight.d.ts +1 -1
  192. package/dist/skill-test/preflight.d.ts.map +1 -1
  193. package/dist/skill-test/preflight.js +59 -16
  194. package/dist/skill-test/preflight.js.map +1 -1
  195. package/dist/skill-test/prompt-invariants.d.ts +4 -2
  196. package/dist/skill-test/prompt-invariants.d.ts.map +1 -1
  197. package/dist/skill-test/prompt-invariants.js +5 -4
  198. package/dist/skill-test/prompt-invariants.js.map +1 -1
  199. package/dist/skill-test/run-harness.d.ts +665 -85
  200. package/dist/skill-test/run-harness.d.ts.map +1 -1
  201. package/dist/skill-test/run-harness.js +1522 -237
  202. package/dist/skill-test/run-harness.js.map +1 -1
  203. package/dist/skill-test/staging.d.ts +20 -8
  204. package/dist/skill-test/staging.d.ts.map +1 -1
  205. package/dist/skill-test/staging.js +25 -18
  206. package/dist/skill-test/staging.js.map +1 -1
  207. package/dist/skill-test/tier-plan.d.ts +1 -1
  208. package/dist/skill-test/tier-plan.js +1 -1
  209. package/dist/skill-test/tool-eval-schema.d.ts +6 -6
  210. package/dist/skill-test/tool-eval-schema.js +2 -2
  211. package/dist/skill-test/vendor-manifest.d.ts +2 -1
  212. package/dist/skill-test/vendor-manifest.d.ts.map +1 -1
  213. package/dist/skill-test/vendor-manifest.js +10 -10
  214. package/dist/skill-test/vendor-manifest.js.map +1 -1
  215. package/dist/test-input.d.ts +59 -8
  216. package/dist/test-input.d.ts.map +1 -1
  217. package/dist/test-input.js +64 -19
  218. package/dist/test-input.js.map +1 -1
  219. package/dist/validators/agent-instruction-presence.d.ts +1 -1
  220. package/dist/validators/agent-instruction-presence.d.ts.map +1 -1
  221. package/dist/validators/agent-instruction-presence.js +45 -2
  222. package/dist/validators/agent-instruction-presence.js.map +1 -1
  223. package/dist/validators/bundled-resource-link-detection.d.ts +6 -4
  224. package/dist/validators/bundled-resource-link-detection.d.ts.map +1 -1
  225. package/dist/validators/bundled-resource-link-detection.js +39 -39
  226. package/dist/validators/bundled-resource-link-detection.js.map +1 -1
  227. package/dist/validators/compat-detectors.d.ts +18 -1
  228. package/dist/validators/compat-detectors.d.ts.map +1 -1
  229. package/dist/validators/compat-detectors.js +47 -20
  230. package/dist/validators/compat-detectors.js.map +1 -1
  231. package/dist/validators/cross-skill-dependency-detection.d.ts +1 -1
  232. package/dist/validators/cross-skill-dependency-detection.d.ts.map +1 -1
  233. package/dist/validators/cross-skill-dependency-detection.js +1 -1
  234. package/dist/validators/cross-skill-dependency-detection.js.map +1 -1
  235. package/dist/validators/description-style-detection.d.ts +1 -1
  236. package/dist/validators/description-style-detection.d.ts.map +1 -1
  237. package/dist/validators/description-style-detection.js +1 -1
  238. package/dist/validators/description-style-detection.js.map +1 -1
  239. package/dist/validators/format-detection.d.ts +3 -0
  240. package/dist/validators/format-detection.d.ts.map +1 -1
  241. package/dist/validators/format-detection.js +41 -26
  242. package/dist/validators/format-detection.js.map +1 -1
  243. package/dist/validators/frontmatter-validation.d.ts +1 -1
  244. package/dist/validators/frontmatter-validation.d.ts.map +1 -1
  245. package/dist/validators/frontmatter-validation.js +2 -2
  246. package/dist/validators/frontmatter-validation.js.map +1 -1
  247. package/dist/validators/imperative-body-detection.d.ts +1 -1
  248. package/dist/validators/imperative-body-detection.d.ts.map +1 -1
  249. package/dist/validators/imperative-body-detection.js +1 -1
  250. package/dist/validators/imperative-body-detection.js.map +1 -1
  251. package/dist/validators/index.d.ts +1 -1
  252. package/dist/validators/index.d.ts.map +1 -1
  253. package/dist/validators/kebab-case-detection.d.ts +1 -1
  254. package/dist/validators/kebab-case-detection.d.ts.map +1 -1
  255. package/dist/validators/kebab-case-detection.js +1 -1
  256. package/dist/validators/kebab-case-detection.js.map +1 -1
  257. package/dist/validators/marketplace-validator.d.ts.map +1 -1
  258. package/dist/validators/marketplace-validator.js +7 -2
  259. package/dist/validators/marketplace-validator.js.map +1 -1
  260. package/dist/validators/mcp-tool-qualification.d.ts +158 -0
  261. package/dist/validators/mcp-tool-qualification.d.ts.map +1 -0
  262. package/dist/validators/mcp-tool-qualification.js +467 -0
  263. package/dist/validators/mcp-tool-qualification.js.map +1 -0
  264. package/dist/validators/packaged-size-limit.d.ts +296 -0
  265. package/dist/validators/packaged-size-limit.d.ts.map +1 -0
  266. package/dist/validators/packaged-size-limit.js +492 -0
  267. package/dist/validators/packaged-size-limit.js.map +1 -0
  268. package/dist/validators/packaging-validator.d.ts +149 -10
  269. package/dist/validators/packaging-validator.d.ts.map +1 -1
  270. package/dist/validators/packaging-validator.js +371 -55
  271. package/dist/validators/packaging-validator.js.map +1 -1
  272. package/dist/validators/plugin-hosted-shape.d.ts +4 -2
  273. package/dist/validators/plugin-hosted-shape.d.ts.map +1 -1
  274. package/dist/validators/plugin-hosted-shape.js +6 -7
  275. package/dist/validators/plugin-hosted-shape.js.map +1 -1
  276. package/dist/validators/plugin-recommended-fields.d.ts +1 -1
  277. package/dist/validators/plugin-recommended-fields.d.ts.map +1 -1
  278. package/dist/validators/plugin-recommended-fields.js +1 -1
  279. package/dist/validators/plugin-recommended-fields.js.map +1 -1
  280. package/dist/validators/referenced-path-missing.d.ts +211 -0
  281. package/dist/validators/referenced-path-missing.d.ts.map +1 -0
  282. package/dist/validators/referenced-path-missing.js +378 -0
  283. package/dist/validators/referenced-path-missing.js.map +1 -0
  284. package/dist/validators/registry-validator.d.ts.map +1 -1
  285. package/dist/validators/registry-validator.js +1 -2
  286. package/dist/validators/registry-validator.js.map +1 -1
  287. package/dist/validators/rule-engine/index.d.ts +1 -1
  288. package/dist/validators/rule-engine/rule-context.d.ts +20 -3
  289. package/dist/validators/rule-engine/rule-context.d.ts.map +1 -1
  290. package/dist/validators/rule-engine/rule-context.js +3 -1
  291. package/dist/validators/rule-engine/rule-context.js.map +1 -1
  292. package/dist/validators/rule-engine/rule-engine.d.ts +2 -2
  293. package/dist/validators/rule-engine/rule-engine.d.ts.map +1 -1
  294. package/dist/validators/rule-engine/rule-engine.js +52 -13
  295. package/dist/validators/rule-engine/rule-engine.js.map +1 -1
  296. package/dist/validators/skill-validator.d.ts.map +1 -1
  297. package/dist/validators/skill-validator.js +91 -54
  298. package/dist/validators/skill-validator.js.map +1 -1
  299. package/dist/validators/source-only-codes.js +1 -1
  300. package/dist/validators/source-only-codes.js.map +1 -1
  301. package/dist/validators/types.d.ts +21 -1
  302. package/dist/validators/types.d.ts.map +1 -1
  303. package/dist/validators/unified-validator.d.ts.map +1 -1
  304. package/dist/validators/unified-validator.js +4 -5
  305. package/dist/validators/unified-validator.js.map +1 -1
  306. package/dist/validators/validation-rules.d.ts +4 -4
  307. package/dist/validators/validation-rules.d.ts.map +1 -1
  308. package/dist/validators/validation-rules.js +9 -38
  309. package/dist/validators/validation-rules.js.map +1 -1
  310. package/dist/validators/walker-to-issues.d.ts +9 -3
  311. package/dist/validators/walker-to-issues.d.ts.map +1 -1
  312. package/dist/validators/walker-to-issues.js +64 -19
  313. package/dist/validators/walker-to-issues.js.map +1 -1
  314. package/dist/walk-link-graph.d.ts +64 -5
  315. package/dist/walk-link-graph.d.ts.map +1 -1
  316. package/dist/walk-link-graph.js +376 -92
  317. package/dist/walk-link-graph.js.map +1 -1
  318. package/package.json +14 -22
  319. package/dist/skill-test/exit-codes.d.ts +0 -97
  320. package/dist/skill-test/exit-codes.d.ts.map +0 -1
  321. package/dist/skill-test/exit-codes.js +0 -141
  322. package/dist/skill-test/exit-codes.js.map +0 -1
@@ -0,0 +1,560 @@
1
+ /**
2
+ * The **skill** extent, expressed as the generic closure primitive plus a
3
+ * declaration — zones.md §7.3's adequacy test, run for real.
4
+ *
5
+ * §7.3 requires that *a built-in extent must be expressible the way a
6
+ * config-declared one would be*. A skill bundle is the hardest case VAT has,
7
+ * because a privileged walker (`walk-link-graph.ts`) already computes it, so
8
+ * this module is the falsification: it translates a `SkillPackagingConfig` into
9
+ * an {@link ExtentDeclaration} and hands it to `ClosureExtentContributor`. There
10
+ * is deliberately **no bespoke walker here**. A second walker that passed its
11
+ * own tests would prove nothing about the primitive — it would only prove that
12
+ * the skill contributor can stay privileged, which is the outcome §17 risk 3
13
+ * asks about.
14
+ *
15
+ * ## What the primitive expresses, measured against the shipped walker
16
+ *
17
+ * The equality experiment lives in `test/projection-skill-extent.test.ts`, and
18
+ * its result is that **membership** agrees exactly on a corpus whose every link
19
+ * target is an ordinary reachable file, and — since the primitive gained a
20
+ * labelled `refusals` cascade plus `admitPaths` — on three of the cascade
21
+ * discriminators that used to diverge, and now on their REASONS as well. What
22
+ * remains is listed below. Stated here rather than in a report, because a reader
23
+ * reaching for this translation needs the boundary, not the anecdote:
24
+ *
25
+ * | Walker feature | Verdict |
26
+ * |---|---|
27
+ * | `linkFollowDepth` *membership* | **expressible** — same union, same off-by-one (`depth < maxDepth`) |
28
+ * | `depth-exceeded` *the REASON* | **expressible** — and it moved out of the not-expressible list once the primitive stopped guarding ENUMERATION on `maxDepth` and started guarding only ADMISSION. A member at the bound now has its references resolved and judged, and one the budget alone turns away becomes a `CLOSURE_DEPTH_EXCEEDED` condition carrying the same provenance a refusal does. This is the one verdict a DECLARATION states directly rather than through a `refusals` rule, so it carries no label and `matchedPattern` is null — which is exactly what the walker's own row says (`makeExclusion` attaches `matchedRule` only for `pattern-matched`) |
29
+ * | `excludeReferencesFromBundle` *membership* | **expressible** — first-match-wins and any-match select the same file set; carried as ONE refusal rule per declared rule, in declared order, which selects the same set the flat union did |
30
+ * | `excludeReferencesFromBundle` *WHICH rule matched* | **expressible** — one refusal rule apiece means the primitive's first-match-wins scan is `excludeMatchers.find(...)`'s scan, and the winner's first pattern lands in `realization_conditions.matchedPattern`, the column `packaging-validator.ts` reads as `matchedRule.patterns[0]` |
31
+ * | `excludeReferencesFromBundle` *`template` payload* | **expressible** — carried verbatim in `ExtentRefusalRule.payload` (opaque to the primitive) and reported as `realization_conditions.matchedPayload`, beside the rule's declared index. ⚠️ Never MEASURED against the walker: no shipped config declares a `template`, so the corpus shadow synthesizes one to compare the two arms |
32
+ * | `excludeNavigationFiles` | **expressible** — a refusal rule over `NAVIGATION_FILE_PATTERNS`, gated on the knob exactly as `classifyExclusion` gates its branch |
33
+ * | `agent-instruction-file` *membership* | **expressible** — a refusal rule over `AGENT_INSTRUCTION_FILE_PATTERNS`, unconditionally, and the explicit-`files:` escape hatch becomes `admitPaths` (see {@link declaredAgentInstructionSources}) |
34
+ * | `directory-target` *membership* | **expressible** — a refusal rule over `kinds: ['directory']`, which reads `resources.kind`; a path glob cannot express it, because a directory's path is shaped like a file's |
35
+ * | the REASON of those four exclusions | **expressible** — each refusal rule carries a `label`, and the first-match-wins order is `classifyExclusion`'s own branch order, so the refusal reports `SKILL_REFUSED_DIRECTORY_TARGET` where the walker reports `directory-target`. Pinned by the corpus shadow's reason-mismatch bucket, not asserted here |
36
+ * | `deferredArtifacts` (`files:`) | **not expressible** — its three-way classification is keyed on filesystem existence and on gitignore, and the closure does no I/O by construction. Only the ONE fact `admitPaths` needs — which sources are explicit, non-glob agent-instruction files — is a pure function of the config, which is why that much survives the translation |
37
+ * | `gitignored` | **expressible, CONDITIONALLY** — a COLUMN match, not an oracle: `resource_realizations.gitignored` is a first-class boolean the registry crawl fills, and `ExtentRefusalRule.flags` reads boolean columns. Carried as `{ gitignored: true, exists: true }` — a CONJUNCTION, because `classifyGitignored` is existence-gated — and emitted only when the population has a `GitTracker`, since without one the column is `false` on every row. ⚠️ Two bounds: the WALKER needs no tracker (it spawns `git check-ignore`), so the arms diverge in the no-tracker state; and `classifyGitignoredTarget` turns a gitignored `files:` DEST into a `deferred` verdict rather than a refusal, which no declaration can say (`admitPaths` would make it a member) |
38
+ * | `skill-definition` | **expressible**, as two halves that were always two verdicts under one `if`. The cross-skill half is an ordinary `basenames: ['SKILL.md']` rule, sitting between the agent-instruction rule and the globs exactly where `classifyExclusion` puts it. The self-link half is the walker's `{ kind: 'skipped' }`, and it is not a rule: the PRIMITIVE now skips a reference resolving to `closureFrom`, because the root is a member by declaration in any closure — see `closure-extent.ts`'s `hopFor`. ⚠️ The walker compares the basename with `===`; `basenames` folds case, so `Skill.md` diverges — see {@link SKILL_DEFINITION_BASENAME} |
39
+ * | `outside-project` | **expressible as a REASON, not as a full row** — and it never needed an oracle: `relativize` states every path against the root, and one the root does not contain comes back `..`-prefixed. It was a LABELLING gap, not a knowledge gap; the closure knew, and reported `CLOSURE_REFERENCE_UNRESOLVED`, which is true and useless. It is now `CLOSURE_REFERENCE_OUTSIDE_ROOT`, naming the same target the walker's row names. ⚠️ `targetExists` stays null: the walker `stat`s the escaping path, a projection populated from one root observes nothing outside it |
40
+ * | `missing-target` | **not expressible** — and NOT for the reason the column suggests. `exists` is a real column and `flags` reads it, but no rule can ever fire on it here: a path that is not on disk is never ENUMERATED, so it has no realization for a candidate to be, and the reference resolves to nothing long before the cascade runs. The producer is structurally blind, so the matcher is dead. The fact is still reported — as `CLOSURE_REFERENCE_UNRESOLVED` — but that code conflates "absent" with "present and not enumerated by any contributor", and only a filesystem probe separates them |
41
+ * | routable vs non-routable | **expressible**, and it closed the way the earlier note said it would have to — by adding the VERDICT, not a matcher. `traverseGlobs: LINK_GRAPH_MEMBER_GLOBS` is the walker's door rule itself — it traverses registry members, and the registry is that glob (NOT `parserKindForPath`, which also calls `.txt` and `README` markdown) — and the primitive admits a non-matching target as a LEAF: a member, not charged against `maxDepth`, never traversed through. The gap was not academic. It was measured on the repo-root corpus the moment a skill first linked a document that links assets: at `linkFollowDepth: 2` the packager bundled two files the closure refused as `depth-exceeded`, because a leaf is free on one arm and costs a hop on the other |
42
+ * | `unreadable-target` | **not expressible** — the one genuine oracle left. It is `existsSync` true AND `statSync` throwing anyway, a read outcome no column records: `contentState: 'unreadable'` is a *different* fact (a BYTE read that threw) and is demand-driven besides, so a path nobody asked to hash reads `deferred` whether or not it is stattable |
43
+ * | a refusal's PROVENANCE (`sourcePath`, `sourceLine`, `linkHref`, `targetExists`, `matchedRule`) | **expressible** — `realization_conditions` gained the six columns (projection schema v4), the closure fills them at the refusal site, and every one of the five is compared field by field against the walker's own row by the corpus shadow's provenance bucket |
44
+ *
45
+ * Read the membership, reason and provenance rows together: the primitive now
46
+ * selects the same files for those causes, names the same cause, and carries the
47
+ * same `sourcePath`/`sourceLine`/`linkHref`/`targetExists`/matched-rule
48
+ * provenance the walker attaches to a refusal.
49
+ *
50
+ * ## The residue is TWO reasons, not six — and one of them is not an oracle problem
51
+ *
52
+ * The count above used to be six, and four of those six were stale. Three had
53
+ * gained the machinery to express them (`gitignored` became a boolean column of
54
+ * the realization row; `outside-project` was always path math the closure was
55
+ * already doing; `skill-definition` needed one basename rule plus a self-link
56
+ * rule the primitive owes every closure), and one — `missing-target` — was
57
+ * inexpressible for a completely different reason than "no oracle": its matcher
58
+ * exists and can never fire, because the producer never emits the row it would
59
+ * match.
60
+ *
61
+ * What is left is `unreadable-target`, a genuine filesystem read outcome, and
62
+ * routability, which needs a new VERDICT in the primitive rather than a new
63
+ * matcher. Both are stated above with the evidence for the claim, because a
64
+ * boundary list that is never re-derived is how four verdicts stayed wrong for
65
+ * three increments.
66
+ *
67
+ * ⚠️ **Neither new verdict is measured against the walker on the real corpus,
68
+ * and they are not equally unmeasured elsewhere. Stated per verdict, because an
69
+ * aggregate "verified" would be false for one of them.**
70
+ *
71
+ * - **`skill-definition` IS measured against the walker, at FIXTURE scale.**
72
+ * `projection-skill-extent.test.ts` builds a corpus containing a sibling
73
+ * `skills/tool-b/SKILL.md`, and that divergence — named there, as a
74
+ * one-element equality — closes when this rule lands.
75
+ * - **`gitignored` is reasoned, not measured against the walker anywhere.** The
76
+ * `flags` conjunction it is made of has its own falsifying case in
77
+ * `projection-closure-extent.test.ts` (including the `exists: false` control
78
+ * that separates AND from OR), but no fixture yet links a skill to a gitignored
79
+ * file with both arms running, so no two-arm comparison has ever exercised it.
80
+ *
81
+ * Neither is reachable on the REAL corpus, and that is asserted rather than
82
+ * assumed: the corpus shadow was green with both verdicts unexpressed, which is
83
+ * possible only if no declared skill links to a gitignored file or to another
84
+ * skill's SKILL.md, and both populations are now pinned at zero there. The day a
85
+ * link appears the test fails and the reader learns the corpus grew teeth
86
+ * ([[fixtures-that-cannot-distinguish]]).
87
+ *
88
+ * The `excludeNavigationFiles` row is the one worth reading twice, because the
89
+ * shape of its extension is the argument for why a rule needs a basename matcher
90
+ * and not a cleverer glob: `isNavigationBasename` matches a **case-insensitive
91
+ * basename set** (`README.md`, `index.md`, …), while `patterns` is picomatch
92
+ * over a root-relative path. A brace alternation over `README` / `readme` /
93
+ * `Readme` enumerates spellings a case-insensitive filesystem generates freely,
94
+ * so the approximation silently under-matches exactly where the walker's comment
95
+ * says it must not (`Claude.md` is loaded as instructions on APFS just as
96
+ * `CLAUDE.md` is). The honest extension was a declared basename set, and it is
97
+ * what `ExtentRefusalRule.basenames` is.
98
+ *
99
+ * ## `closureFrom` is stated in projection coordinates
100
+ *
101
+ * {@link skillExtentDeclaration} takes the SKILL.md path **relative to the
102
+ * corpus root**, the way `resource_realizations.path` spells it, because that is
103
+ * the only coordinate system `closureFrom` is resolved in. The packager works in
104
+ * absolute paths; converting is the caller's job precisely because the caller is
105
+ * the one holding the root.
106
+ */
107
+ import { basename } from 'node:path';
108
+ import { ClosureExtentContributor, ExtentDeclarationSchema, } from '@vibe-agent-toolkit/resources';
109
+ import { isGlob, safePath } from '@vibe-agent-toolkit/utils';
110
+ import { LINK_GRAPH_MEMBER_GLOBS } from '../link-graph-members.js';
111
+ import { AGENT_INSTRUCTION_FILE_PATTERNS, NAVIGATION_FILE_PATTERNS, isAgentInstructionBasename, } from '../validators/validation-rules.js';
112
+ /**
113
+ * `zone_provenance.contributorId` prefix for a skill extent.
114
+ *
115
+ * **Per-skill, not fixed.** The plan specced a bare `builtin:skill`, which was
116
+ * written before anyone asked how many skills a corpus has:
117
+ * `ContributorRegistry.register` refuses a duplicate id, so a fixed id caps a
118
+ * population at **one** skill extent — and this repo alone ships thirteen. The
119
+ * extent ids were already distinct (the skill name is the within-root
120
+ * discriminator); only the contributor key space collided. Nothing schema-level
121
+ * objects: `zone_provenance.contributorId` is an open string.
122
+ */
123
+ export const SKILL_EXTENT_CONTRIBUTOR_ID_PREFIX = 'builtin:skill';
124
+ /**
125
+ * The `zone_provenance.contributorId` for one skill's extent.
126
+ *
127
+ * @param skillName - The skill's name
128
+ * @returns The contributor id, unique per skill
129
+ */
130
+ export function skillExtentContributorId(skillName) {
131
+ return `${SKILL_EXTENT_CONTRIBUTOR_ID_PREFIX}:${skillName}`;
132
+ }
133
+ /** The `resolution_contexts.kind` a skill extent has. */
134
+ export const SKILL_EXTENT_KIND = 'skill';
135
+ /**
136
+ * The hop budget a skill bundle gets when its config declares none.
137
+ *
138
+ * Two shipped sites spell this `?? 2` — `skill-packager.ts:580` and
139
+ * `packaging-validator.ts:484` — so the translation must default the same way or
140
+ * a config-less skill would project a different extent from the one it packages.
141
+ */
142
+ const DEFAULT_LINK_FOLLOW_DEPTH = 2;
143
+ /**
144
+ * The `resources.kind` a directory entity carries.
145
+ *
146
+ * Verified against the producers rather than assumed: both base contributors
147
+ * spell it the same way — `filesystem-extent.ts` and `git-extent.ts` each emit
148
+ * `kind: realization.isDirectory ? 'directory' : 'file'` — and
149
+ * `projection-filesystem-extent.test.ts` pins it ("kinds a directory row
150
+ * 'directory' and a file row 'file'"). That is what makes `excludeKinds` able to
151
+ * stand in for the walker's `classifyPathKind`, whose `directory-target` branch
152
+ * is the FIRST thing it refuses after the deferred check.
153
+ */
154
+ const DIRECTORY_KIND = 'directory';
155
+ /**
156
+ * The walker's default for `excludeNavigationFiles` when the config declares
157
+ * none — `skill-packager.ts:582` spells it `options.excludeNavigationFiles ?? true`.
158
+ */
159
+ const DEFAULT_EXCLUDE_NAVIGATION_FILES = true;
160
+ /**
161
+ * The refusal labels this translation supplies — **one per branch of the walker's
162
+ * exclusion cascade that a declaration can express**, and that property rather
163
+ * than a count is the definition: every `SKILL_REFUSED_*` constant below is a
164
+ * member, so adding a branch adds a member without falsifying this line. (The
165
+ * branches come from three classifiers, not one: `classifyExclusion`,
166
+ * `classifyPathKind` and `classifyGitignored` — each label's own doc line names
167
+ * which.)
168
+ *
169
+ * SCREAMING_SNAKE because they land in `realization_conditions.code`, whose two
170
+ * existing members (`CLOSURE_REFERENCE_UNRESOLVED`, `CLOSURE_ROOT_ABSENT`) set
171
+ * that convention. Prefixed `SKILL_REFUSED_` because that column is an OPEN
172
+ * vocabulary shared by every contributor in a population: a bare
173
+ * `DIRECTORY_TARGET` would not say whose cascade decided it.
174
+ *
175
+ * The walker reason each one stands for is in its own doc line, and that mapping
176
+ * is asserted end-to-end by the corpus shadow's reason-mismatch bucket rather
177
+ * than trusted — see `projection-skill-extent-corpus.integration.test.ts`.
178
+ */
179
+ /** `classifyPathKind`'s `directory-target`. */
180
+ export const SKILL_REFUSED_DIRECTORY_TARGET = 'SKILL_REFUSED_DIRECTORY_TARGET';
181
+ /** `classifyExclusion`'s `navigation-file`. */
182
+ export const SKILL_REFUSED_NAVIGATION_FILE = 'SKILL_REFUSED_NAVIGATION_FILE';
183
+ /** `classifyExclusion`'s `agent-instruction-file`. */
184
+ export const SKILL_REFUSED_AGENT_INSTRUCTION_FILE = 'SKILL_REFUSED_AGENT_INSTRUCTION_FILE';
185
+ /** `classifyExclusion`'s `pattern-matched`, from `excludeReferencesFromBundle`. */
186
+ export const SKILL_REFUSED_PATTERN_MATCHED = 'SKILL_REFUSED_PATTERN_MATCHED';
187
+ /**
188
+ * `classifyExclusion`'s `skill-definition` — ANOTHER skill's SKILL.md.
189
+ *
190
+ * Only the cross-skill half. The walker's branch is two verdicts wearing one
191
+ * `if`: a link to a *sibling's* SKILL.md is this refusal, and a link back to the
192
+ * walk's OWN `skillRootPath` is `{ kind: 'skipped' }` — recorded nowhere. The
193
+ * declaration expresses the first as an ordinary basename rule; the second is
194
+ * not a rule at all, and it is the primitive that supplies it, because a
195
+ * reference to `closureFrom` is a self-link in any closure and not a fact about
196
+ * skills (see `closure-extent.ts`'s `hopFor`).
197
+ */
198
+ export const SKILL_REFUSED_SKILL_DEFINITION = 'SKILL_REFUSED_SKILL_DEFINITION';
199
+ /** `classifyGitignored`'s `gitignored`, existence-gated exactly as that branch is. */
200
+ export const SKILL_REFUSED_GITIGNORED = 'SKILL_REFUSED_GITIGNORED';
201
+ /**
202
+ * The basename that makes a markdown file a skill DEFINITION rather than a
203
+ * resource — the whole content of `classifyExclusion`'s SKILL.md branch.
204
+ *
205
+ * ⚠️ The walker compares it with `===`, so `Skill.md` on a case-insensitive
206
+ * filesystem is a skill definition Claude Code loads and the walker bundles.
207
+ * `ExtentRefusalRule.basenames` folds case, deliberately and for the reason its
208
+ * schema states, so the declaration refuses the spelling the walker admits. That
209
+ * is a difference in the WALKER's favour on no real corpus: this repository
210
+ * declares fourteen skills and every one of them spells the file `SKILL.md`. It
211
+ * is recorded here rather than papered over with a case-sensitive matcher
212
+ * variant, which would be a primitive feature added to reproduce an
213
+ * inconsistency — the walker's own navigation and agent-instruction branches
214
+ * fold case, and its comment says why they must.
215
+ */
216
+ const SKILL_DEFINITION_BASENAME = 'SKILL.md';
217
+ /**
218
+ * The realization columns {@link SKILL_REFUSED_GITIGNORED} refuses on.
219
+ *
220
+ * A CONJUNCTION, and both halves are load-bearing: `classifyGitignored` returns
221
+ * early on `!facts.exists` because neither ignore oracle can be trusted about a
222
+ * path that is not there (a `GitTracker`'s active set holds only existing paths,
223
+ * so every typo'd link would read as "absent, therefore ignored"). Read
224
+ * disjunctively, `{ gitignored: true, exists: true }` would refuse every existing
225
+ * file in the corpus. Spelled as one object so the conjunction is visible at the
226
+ * site that depends on it — the same shape, for the same reason, as
227
+ * `inventory-extent.ts`'s `GITIGNORED_FLAGS`.
228
+ */
229
+ const GITIGNORED_FLAGS = { gitignored: true, exists: true };
230
+ /**
231
+ * This skill's refusal cascade, **in `classifyExclusion`'s own branch order**.
232
+ *
233
+ * ⚠️ The order is load-bearing now that a refusal carries a label: the primitive
234
+ * is first-match-wins, so a directory that also matches an
235
+ * `excludeReferencesFromBundle` pattern must be attributed to `directory-target`
236
+ * — which is what the walker does, and which the previous flat encoding got
237
+ * backwards (its glob matcher ran before its kind matcher, harmlessly, because
238
+ * no verdict carried a reason to get wrong).
239
+ *
240
+ * The six rules, and why each sits where it does:
241
+ *
242
+ * 1. **kinds `['directory']`** — `classifyPathKind` is the FIRST thing
243
+ * `classifyExclusion` consults after the deferred check, and no knob gates it.
244
+ * 2. **navigation basenames** — gated on `excludeNavigationFiles`, because
245
+ * `classifyExclusion`'s navigation branch is. Omitted entirely rather than
246
+ * emitted empty when the knob is off, so the declaration says "this branch
247
+ * does not run" rather than "it runs and catches nothing".
248
+ * 3. **agent-instruction basenames** — unconditional, and that is not an
249
+ * oversight: `refusesAgentInstructionFile` is deliberately NOT gated on
250
+ * `excludeNavigationFiles`, because that knob is about content granularity
251
+ * while these files are about distributability. Sitting AFTER navigation is
252
+ * what makes a `files:`-declared `README.md` report `navigation-file` — see
253
+ * {@link declaredAgentInstructionSources} for the other half of that rule.
254
+ * 4. **the `SKILL.md` basename** — `classifyExclusion`'s cross-skill branch,
255
+ * which sits exactly here: after the agent-instruction check and BEFORE the
256
+ * glob rules, so a sibling's SKILL.md that also matches a declared
257
+ * `excludeReferencesFromBundle` pattern reports `skill-definition`. Its other
258
+ * half — a link back to this skill's OWN SKILL.md — is not a rule and cannot
259
+ * be: the walker records nothing at all for it, and the primitive supplies
260
+ * that silence for every closure by skipping a reference to `closureFrom`.
261
+ * 5. **one rule per `excludeReferencesFromBundle` rule**, in declared order —
262
+ * see below.
263
+ * 6. **`gitignored ∧ exists`** — LAST, matching `classifyGitignored`'s position
264
+ * at the end of the cascade, and present only when the population can answer
265
+ * the question at all. `resource_realizations.gitignored` is filled by
266
+ * `FilesystemExtentContributor` only when the population was given a
267
+ * `GitTracker` (`realizations.ts` writes `false` on every row otherwise), so a
268
+ * rule emitted without one would CLAIM a branch it cannot run — the same
269
+ * dishonesty rule 2 avoids by omitting itself rather than emitting empty.
270
+ *
271
+ * ⚠️ **The gitignore rule is where the two arms stop being symmetric in the
272
+ * no-tracker state, and that is a fact about the WALKER.**
273
+ * `walkLinkGraph`'s branch needs no tracker: with none it spawns `git
274
+ * check-ignore` per target (`readGitignored`), so it refuses ignored targets
275
+ * anyway. The closure's only gitignore input is a column a tracker-less
276
+ * population never fills, so the two agree in that state only on a corpus with
277
+ * no gitignored link target.
278
+ *
279
+ * ## Why the exclude rules are ONE RULE EACH and not one flattened rule
280
+ *
281
+ * They used to flatten into a single refusal rule holding every rule's patterns,
282
+ * which selected the same files and reported the same label but could not say
283
+ * WHICH declared rule caught a file — so `LinkResolution.matchedRule`, which
284
+ * `packaging-validator.ts:1182` reads `patterns[0]` off, had no counterpart.
285
+ *
286
+ * Expanding them restores it **without touching the reported reason**: every
287
+ * expanded rule carries the SAME {@link SKILL_REFUSED_PATTERN_MATCHED} label, so
288
+ * `realization_conditions.code` is unchanged, while the primitive's
289
+ * first-match-wins scan over them is exactly `excludeMatchers.find(...)`'s scan
290
+ * over `options.excludeRules` — same order, same winner. A label is a REASON and
291
+ * reasons are shared; identity rides on the rule's position and its `payload`.
292
+ *
293
+ * ⚠️ They all stay in the glob branch's position, AFTER the basename rules: the
294
+ * expansion widens one cascade step into N, it does not reorder the cascade. And
295
+ * a config declaring no rules now contributes NO rule rather than one empty one —
296
+ * an empty pattern list never matched anything, and "one rule per declared rule"
297
+ * is a shape a reader can check against the config, which "always exactly one"
298
+ * was not.
299
+ *
300
+ * Each expanded rule's `payload` carries what the primitive has no column for:
301
+ * the rule's INDEX in the declared array (identity, when two rules share a first
302
+ * pattern) and its `template` (the walker's own `ExcludeRule.template`, which no
303
+ * `realization_conditions` column could hold without teaching the closure about
304
+ * skill packaging).
305
+ *
306
+ * Basename lists are imported from `validation-rules.ts`, never re-spelled: that
307
+ * module is explicit that ONE canonical spelling per name is the whole design,
308
+ * and a second copy here would be the enumeration it warns against.
309
+ *
310
+ * @param config - The skill's packaging block
311
+ * @param hasGitTracker - Whether the population was given a usable git oracle
312
+ * @returns The ordered refusal rules
313
+ */
314
+ function skillRefusals(config, hasGitTracker) {
315
+ const excludeNavigation = config.excludeNavigationFiles ?? DEFAULT_EXCLUDE_NAVIGATION_FILES;
316
+ return [
317
+ // `flags: {}` on every rule but the last: the empty record is the schema
318
+ // default and never matches, so spelling it declares "this rule refuses on
319
+ // no column" rather than leaving a reader to infer it from an absent key.
320
+ // Only the gitignore rule reads a column, and it reads two.
321
+ {
322
+ label: SKILL_REFUSED_DIRECTORY_TARGET,
323
+ patterns: [],
324
+ basenames: [],
325
+ kinds: [DIRECTORY_KIND],
326
+ flags: {},
327
+ payload: null,
328
+ },
329
+ ...(excludeNavigation
330
+ ? [{
331
+ label: SKILL_REFUSED_NAVIGATION_FILE,
332
+ patterns: [],
333
+ basenames: [...NAVIGATION_FILE_PATTERNS],
334
+ kinds: [],
335
+ flags: {},
336
+ payload: null,
337
+ }]
338
+ : []),
339
+ {
340
+ label: SKILL_REFUSED_AGENT_INSTRUCTION_FILE,
341
+ patterns: [],
342
+ basenames: [...AGENT_INSTRUCTION_FILE_PATTERNS],
343
+ kinds: [],
344
+ flags: {},
345
+ payload: null,
346
+ },
347
+ {
348
+ label: SKILL_REFUSED_SKILL_DEFINITION,
349
+ patterns: [],
350
+ basenames: [SKILL_DEFINITION_BASENAME],
351
+ kinds: [],
352
+ flags: {},
353
+ payload: null,
354
+ },
355
+ // `payload: null` above, a payload here: the first four rules ARE the
356
+ // walker's own branches, which carry no rule object for a consumer to read
357
+ // back (`makeExclusion` sets `matchedRule` only for `pattern-matched`).
358
+ ...(config.excludeReferencesFromBundle?.rules ?? []).map((rule, index) => ({
359
+ label: SKILL_REFUSED_PATTERN_MATCHED,
360
+ patterns: [...rule.patterns],
361
+ basenames: [],
362
+ kinds: [],
363
+ flags: {},
364
+ payload: excludeRulePayload(rule, index),
365
+ })),
366
+ ...(hasGitTracker
367
+ ? [{
368
+ label: SKILL_REFUSED_GITIGNORED,
369
+ patterns: [],
370
+ basenames: [],
371
+ kinds: [],
372
+ flags: { ...GITIGNORED_FLAGS },
373
+ payload: null,
374
+ }]
375
+ : []),
376
+ ];
377
+ }
378
+ /**
379
+ * One `excludeReferencesFromBundle` rule's identity, as opaque payload.
380
+ *
381
+ * `template` is the field the old flat encoding lost outright — the skill
382
+ * extent's own boundary table used to record it as "not expressible", and it is
383
+ * expressible now precisely because the payload is a channel the primitive never
384
+ * reads. `ruleIndex` is what distinguishes two rules that share a first pattern,
385
+ * which `matchedPattern` alone cannot.
386
+ *
387
+ * `template: null` rather than an omitted key, because the row this lands in is
388
+ * read as data: a consumer asking "did this rule declare a template" must not
389
+ * have to distinguish an absent key from a null one.
390
+ *
391
+ * @param rule - One declared exclude rule
392
+ * @param index - Its 0-based position in the declared array — first-match-wins order
393
+ * @returns The rule's payload, JSON-shaped
394
+ */
395
+ function excludeRulePayload(rule, index) {
396
+ return { ruleIndex: index, template: rule.template ?? null };
397
+ }
398
+ /**
399
+ * A `files:` source stated in projection coordinates — root-relative and
400
+ * forward-slashed, the way `resource_realizations.path` spells it.
401
+ *
402
+ * Mirrors `DeferredArtifacts.from`'s source normalization
403
+ * (`relative(projectRoot, resolve(join(projectRoot, source)))`), which strips a
404
+ * leading `./` and roots an absolute-looking source UNDER the project root. In
405
+ * projection coordinates the project root is the empty prefix, so that
406
+ * expression reduces to a normalizing join plus the leading-separator strip.
407
+ *
408
+ * @param source - A `files:` entry's `source`, authored relative to the project root
409
+ * @returns The same path, root-relative and forward-slashed
410
+ */
411
+ function rootRelativeSource(source) {
412
+ const joined = safePath.join(source);
413
+ return joined.startsWith('/') ? joined.slice(1) : joined;
414
+ }
415
+ /**
416
+ * The `files:`-declared agent-instruction files this skill's closure must admit
417
+ * despite {@link skillExcludeBasenames} refusing their basenames.
418
+ *
419
+ * ⚠️ **The asymmetry here is the walker's cascade ORDER, and it stays in this
420
+ * translation even though the primitive now has a cascade of its own.**
421
+ * `walk-link-graph.ts`'s `classifyExclusion` refuses `navigation-file` BEFORE it
422
+ * reaches the agent-instruction branch, and only the agent-instruction branch
423
+ * carries the explicit-`files:` escape hatch. A `files:`-declared `README.md`
424
+ * linked from a SKILL.md is therefore STILL excluded by the walker, as
425
+ * `navigation-file` — the hatch never gets a chance to run. {@link skillRefusals}
426
+ * reproduces the ORDER, so the reported reason is right; it cannot reproduce the
427
+ * hatch's POSITION, because `admitPaths` outranks the whole cascade rather than
428
+ * sitting inside one branch of it. So the positional fact is discharged HERE, by
429
+ * narrowing which declarations earn `admitPaths` at all — a per-branch escape
430
+ * hatch is a primitive feature nothing else has asked for.
431
+ *
432
+ * "Explicit" is EXACT membership in `DeferredArtifacts.sourcePaths`, which is
433
+ * why a GLOB source earns nothing: `DeferredArtifacts.from` registers a glob by
434
+ * its STATIC BASE (a directory), so a glob's matches are only ever prefix
435
+ * CHILDREN of what is in the set and the walker's exact-equality test refuses
436
+ * them. `refusesAgentInstructionFile` states the reasoning in full: naming a
437
+ * file is an unambiguous instruction to ship it, a glob is a net that never
438
+ * named the file it caught.
439
+ *
440
+ * ⚠️ **One narrowing the walker applies and this cannot.** Both walker lanes
441
+ * build their `DeferredArtifacts` from `partitionTestInputFileEntries(...).kept`
442
+ * (`skill-packager.ts:593`, `packaging-validator.ts:523`), so a `files:` entry
443
+ * whose source lives under a declared `test.evals` suite is dropped before it can
444
+ * earn the hatch. Reproducing that needs `resolveTestInputDirs`, which probes the
445
+ * filesystem and needs the project's whole skill list — neither of which a
446
+ * config→declaration translation has, by construction. A `test.evals`-resident
447
+ * `CLAUDE.md` declared in `files:` would therefore be admitted here and refused
448
+ * by the walker. Unreachable on the real corpus today: the corpus shadow test
449
+ * ("omitting the packager-only walk inputs changes no membership") measures the
450
+ * `test.evals` overlap across all fourteen declared skills and finds it empty.
451
+ *
452
+ * @param config - The skill's packaging block
453
+ * @returns Root-relative paths that outrank every refusal matcher
454
+ */
455
+ function declaredAgentInstructionSources(config) {
456
+ const admitted = [];
457
+ for (const entry of config.files ?? []) {
458
+ if (isGlob(entry.source))
459
+ continue;
460
+ const source = rootRelativeSource(entry.source);
461
+ if (isAgentInstructionBasename(basename(source)))
462
+ admitted.push(source);
463
+ }
464
+ return admitted;
465
+ }
466
+ /**
467
+ * Translate a skill's packaging config into a closure-extent declaration.
468
+ *
469
+ * This is the whole of the skill extent's behaviour: everything else is the
470
+ * generic contributor. `linkFollowDepth` becomes `maxDepth` unchanged (same
471
+ * `number | 'full'` union, same meaning of a hop), and {@link skillRefusals}
472
+ * becomes the cascade — one rule per `classifyExclusion` branch this translation
473
+ * can express, in that function's own order.
474
+ *
475
+ * ⚠️ This paragraph used to say the `excludeReferencesFromBundle` rules
476
+ * "flatten into ONE labelled refusal rule". They have not since the increment
477
+ * that restored `matchedRule`: they expand to one rule EACH, in declared order,
478
+ * which is what lets `realization_conditions.matchedPattern` name WHICH rule
479
+ * caught a file. The `template` it also said the primitive had "nowhere to put"
480
+ * rides in that rule's opaque `payload`.
481
+ *
482
+ * `follow` is left to the schema default (the three markdown forms), matching
483
+ * the walker: it processes only `isLocalFileLink` links off the markdown AST, so
484
+ * an `@`-prefixed or bare token is not an edge on either side.
485
+ *
486
+ * @param config - The skill's `skills.config.<name>` packaging block
487
+ * @param skillPath - The SKILL.md path **relative to the corpus root**, forward-slashed
488
+ * @param hasGitTracker - Whether the population this declaration will run in was
489
+ * given a usable git oracle. Not "should gitignored files be refused": the
490
+ * column that rule reads is unfilled without one, so declaring it anyway would
491
+ * claim a branch that cannot run. REQUIRED rather than defaulted, because a
492
+ * defaulted `false` would let a caller that does have a tracker silently ship a
493
+ * declaration missing the last rule of the cascade — a no-op wearing a fix
494
+ * @returns The declaration, schema-parsed so every default is materialized
495
+ * @throws When the resulting declaration is not schema-valid — e.g. an empty `skillPath`
496
+ */
497
+ export function skillExtentDeclaration(config, skillPath, hasGitTracker) {
498
+ return ExtentDeclarationSchema.parse({
499
+ kind: SKILL_EXTENT_KIND,
500
+ closureFrom: skillPath,
501
+ maxDepth: config.linkFollowDepth ?? DEFAULT_LINK_FOLLOW_DEPTH,
502
+ traverseGlobs: [...LINK_GRAPH_MEMBER_GLOBS],
503
+ refusals: skillRefusals(config, hasGitTracker),
504
+ admitPaths: declaredAgentInstructionSources(config),
505
+ });
506
+ }
507
+ /**
508
+ * The skill extent — `ClosureExtentContributor` under a fixed id and kind.
509
+ *
510
+ * Delegation rather than inheritance, and the thinness is the finding: if this
511
+ * class needed to *do* anything, the closure primitive would have been
512
+ * inadequate and the skill contributor would have stayed privileged. It owns
513
+ * only the two things the registry reads before `contribute` runs — a stable
514
+ * `id` for `zone_provenance`, and the `kind` `ContributorRegistry.forKind`
515
+ * partitions on.
516
+ *
517
+ * **One instance per skill**, keyed by {@link skillExtentContributorId}. A fixed
518
+ * id would cap a population at one skill extent, because
519
+ * `ContributorRegistry.register` refuses a duplicate — see that function.
520
+ */
521
+ export class SkillExtentContributor {
522
+ id;
523
+ kind = SKILL_EXTENT_KIND;
524
+ stratum = 'closure';
525
+ /** The generic primitive this contributor is nothing but a naming of. */
526
+ #closure;
527
+ /**
528
+ * Delegated, never restated: this contributor's `contribute` is the
529
+ * delegate's, so whether it reads blob-keyed tables is the delegate's answer
530
+ * and a hard-coded `true` here would be a second copy free to drift.
531
+ */
532
+ get readsBlobs() {
533
+ return this.#closure.readsBlobs;
534
+ }
535
+ /**
536
+ * @param skillName - The skill's name. Discriminates both the contributor id
537
+ * and, through the delegate, the extent's within-root context id — one
538
+ * source for both, so the two cannot drift apart.
539
+ */
540
+ constructor(skillName) {
541
+ this.id = skillExtentContributorId(skillName);
542
+ this.#closure = new ClosureExtentContributor(skillName, SKILL_EXTENT_KIND);
543
+ }
544
+ /**
545
+ * Produce the skill extent by running the closure primitive.
546
+ *
547
+ * Not `async`: the delegate's promise is returned directly, so there is no
548
+ * second microtask and no place for this method to add behaviour.
549
+ *
550
+ * @param base - Everything merged so far — the realizations a reference can
551
+ * resolve to, and the `blob_references` rows that are the edges
552
+ * @param parameters - A {@link skillExtentDeclaration} result, arriving as
553
+ * config data exactly as a user-declared extent would
554
+ * @returns The extent's context, members, realizations and conditions
555
+ */
556
+ contribute(base, parameters) {
557
+ return this.#closure.contribute(base, parameters);
558
+ }
559
+ }
560
+ //# sourceMappingURL=skill-extent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-extent.js","sourceRoot":"","sources":["../../src/projection/skill-extent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyGG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAErC,OAAO,EACL,wBAAwB,EACxB,uBAAuB,GASxB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAE7D,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EACL,+BAA+B,EAC/B,wBAAwB,EACxB,0BAA0B,GAC3B,MAAM,mCAAmC,CAAC;AAE3C;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,kCAAkC,GAAG,eAAe,CAAC;AAElE;;;;;GAKG;AACH,MAAM,UAAU,wBAAwB,CAAC,SAAiB;IACxD,OAAO,GAAG,kCAAkC,IAAI,SAAS,EAAE,CAAC;AAC9D,CAAC;AAED,yDAAyD;AACzD,MAAM,CAAC,MAAM,iBAAiB,GAAG,OAAO,CAAC;AAEzC;;;;;;GAMG;AACH,MAAM,yBAAyB,GAAG,CAAC,CAAC;AAEpC;;;;;;;;;;GAUG;AACH,MAAM,cAAc,GAAG,WAAW,CAAC;AAEnC;;;GAGG;AACH,MAAM,gCAAgC,GAAG,IAAI,CAAC;AAa9C;;;;;;;;;;;;;;;;;;GAkBG;AACH,+CAA+C;AAC/C,MAAM,CAAC,MAAM,8BAA8B,GAAG,gCAAgC,CAAC;AAE/E,+CAA+C;AAC/C,MAAM,CAAC,MAAM,6BAA6B,GAAG,+BAA+B,CAAC;AAE7E,sDAAsD;AACtD,MAAM,CAAC,MAAM,oCAAoC,GAAG,sCAAsC,CAAC;AAE3F,mFAAmF;AACnF,MAAM,CAAC,MAAM,6BAA6B,GAAG,+BAA+B,CAAC;AAE7E;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,8BAA8B,GAAG,gCAAgC,CAAC;AAE/E,sFAAsF;AACtF,MAAM,CAAC,MAAM,wBAAwB,GAAG,0BAA0B,CAAC;AAEnE;;;;;;;;;;;;;;GAcG;AACH,MAAM,yBAAyB,GAAG,UAAU,CAAC;AAE7C;;;;;;;;;;;GAWG;AACH,MAAM,gBAAgB,GAAsC,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AAE/F;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmFG;AACH,SAAS,aAAa,CAAC,MAA4B,EAAE,aAAsB;IACzE,MAAM,iBAAiB,GAAG,MAAM,CAAC,sBAAsB,IAAI,gCAAgC,CAAC;IAC5F,OAAO;QACL,yEAAyE;QACzE,2EAA2E;QAC3E,0EAA0E;QAC1E,4DAA4D;QAC5D;YACE,KAAK,EAAE,8BAA8B;YACrC,QAAQ,EAAE,EAAE;YACZ,SAAS,EAAE,EAAE;YACb,KAAK,EAAE,CAAC,cAAc,CAAC;YACvB,KAAK,EAAE,EAAE;YACT,OAAO,EAAE,IAAI;SACd;QACD,GAAG,CAAC,iBAAiB;YACnB,CAAC,CAAC,CAAC;oBACD,KAAK,EAAE,6BAA6B;oBACpC,QAAQ,EAAE,EAAE;oBACZ,SAAS,EAAE,CAAC,GAAG,wBAAwB,CAAC;oBACxC,KAAK,EAAE,EAAE;oBACT,KAAK,EAAE,EAAE;oBACT,OAAO,EAAE,IAAI;iBACd,CAAC;YACF,CAAC,CAAC,EAAE,CAAC;QACP;YACE,KAAK,EAAE,oCAAoC;YAC3C,QAAQ,EAAE,EAAE;YACZ,SAAS,EAAE,CAAC,GAAG,+BAA+B,CAAC;YAC/C,KAAK,EAAE,EAAE;YACT,KAAK,EAAE,EAAE;YACT,OAAO,EAAE,IAAI;SACd;QACD;YACE,KAAK,EAAE,8BAA8B;YACrC,QAAQ,EAAE,EAAE;YACZ,SAAS,EAAE,CAAC,yBAAyB,CAAC;YACtC,KAAK,EAAE,EAAE;YACT,KAAK,EAAE,EAAE;YACT,OAAO,EAAE,IAAI;SACd;QACD,sEAAsE;QACtE,2EAA2E;QAC3E,wEAAwE;QACxE,GAAG,CAAC,MAAM,CAAC,2BAA2B,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;YACzE,KAAK,EAAE,6BAA6B;YACpC,QAAQ,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC;YAC5B,SAAS,EAAE,EAAE;YACb,KAAK,EAAE,EAAE;YACT,KAAK,EAAE,EAAE;YACT,OAAO,EAAE,kBAAkB,CAAC,IAAI,EAAE,KAAK,CAAC;SACzC,CAAC,CAAC;QACH,GAAG,CAAC,aAAa;YACf,CAAC,CAAC,CAAC;oBACD,KAAK,EAAE,wBAAwB;oBAC/B,QAAQ,EAAE,EAAE;oBACZ,SAAS,EAAE,EAAE;oBACb,KAAK,EAAE,EAAE;oBACT,KAAK,EAAE,EAAE,GAAG,gBAAgB,EAAE;oBAC9B,OAAO,EAAE,IAAI;iBACd,CAAC;YACF,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,SAAS,kBAAkB,CAAC,IAAyB,EAAE,KAAa;IAClE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,IAAI,EAAE,CAAC;AAC/D,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,SAAS,kBAAkB,CAAC,MAAc;IACxC,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACrC,OAAO,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;AAC3D,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,SAAS,+BAA+B,CAAC,MAA4B;IACnE,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;QACvC,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;YAAE,SAAS;QACnC,MAAM,MAAM,GAAG,kBAAkB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAChD,IAAI,0BAA0B,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,MAAM,UAAU,sBAAsB,CACpC,MAA4B,EAC5B,SAAiB,EACjB,aAAsB;IAEtB,OAAO,uBAAuB,CAAC,KAAK,CAAC;QACnC,IAAI,EAAE,iBAAiB;QACvB,WAAW,EAAE,SAAS;QACtB,QAAQ,EAAE,MAAM,CAAC,eAAe,IAAI,yBAAyB;QAC7D,aAAa,EAAE,CAAC,GAAG,uBAAuB,CAAC;QAC3C,QAAQ,EAAE,aAAa,CAAC,MAAM,EAAE,aAAa,CAAC;QAC9C,UAAU,EAAE,+BAA+B,CAAC,MAAM,CAAC;KACpD,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,sBAAsB;IACxB,EAAE,CAAS;IAEX,IAAI,GAAW,iBAAiB,CAAC;IAEjC,OAAO,GAAuB,SAAS,CAAC;IAEjD,yEAAyE;IAChE,QAAQ,CAA2B;IAE5C;;;;OAIG;IACH,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;IAClC,CAAC;IAED;;;;OAIG;IACH,YAAY,SAAiB;QAC3B,IAAI,CAAC,EAAE,GAAG,wBAAwB,CAAC,SAAS,CAAC,CAAC;QAC9C,IAAI,CAAC,QAAQ,GAAG,IAAI,wBAAwB,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;IAC7E,CAAC;IAED;;;;;;;;;;;OAWG;IACH,UAAU,CAAC,IAAoB,EAAE,UAAqB;QACpD,OAAO,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IACpD,CAAC;CACF"}
@@ -1,4 +1,4 @@
1
- import { SKILL_NAME_REGEX, SKILL_NAME_REGEX_MESSAGE } from '@vibe-agent-toolkit/agent-schema';
1
+ import { SKILL_NAME_REGEX, SKILL_NAME_REGEX_MESSAGE } from '@vibe-agent-toolkit/schema';
2
2
  import { z } from 'zod';
3
3
  import { zodToJsonSchema } from 'zod-to-json-schema';
4
4
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"agent-skill-frontmatter.js","sourceRoot":"","sources":["../../src/schemas/agent-skill-frontmatter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent-skill-frontmatter.js","sourceRoot":"","sources":["../../src/schemas/agent-skill-frontmatter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * The declarations an `allowed-tools:` frontmatter VALUE carries.
3
+ *
4
+ * Claude Code documents the field as space-separated (`Bash(git add:*)
5
+ * Bash(git status:*)`), `AgentSkillFrontmatterSchema` says the same, many
6
+ * authors write commas, and a YAML sequence (flow or block) is accepted by
7
+ * every reader. This is the ONE place that turns any of those into a list —
8
+ * the settings-compat checker and the compat detectors both read through it,
9
+ * so a spelling cannot be visible to one and invisible to the other.
10
+ */
11
+ /**
12
+ * Split the STRING form of `allowed-tools:` into declarations.
13
+ *
14
+ * Commas and whitespace are both separators, but only at parenthesis depth
15
+ * zero — `Bash(rm -rf /)` is one declaration, and the whitespace inside its
16
+ * parentheses is part of the command pattern the matcher is handed. A `(` or
17
+ * `)` inside a quoted argument — `Bash(git commit -m "a) b")` — is part of the
18
+ * argument, not of the depth: the split used to count it, and the declaration
19
+ * ended at the quoted paren, handing the matcher `Bash(git commit -m "a)` and
20
+ * two stray tokens. Consecutive separators and edge padding produce no empty
21
+ * declaration.
22
+ */
23
+ export declare function splitAllowedToolsList(value: string): string[];
24
+ /**
25
+ * The declarations an `allowed-tools:` VALUE carries, whatever YAML shape the
26
+ * author gave it: a block or flow sequence (each string item, trimmed), or a
27
+ * scalar (split per {@link splitAllowedToolsList}). Anything else — absent,
28
+ * `null`, a mapping — declares nothing.
29
+ */
30
+ export declare function allowedToolsOf(value: unknown): string[] | undefined;
31
+ //# sourceMappingURL=allowed-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"allowed-tools.d.ts","sourceRoot":"","sources":["../../src/schemas/allowed-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAe7D;AA4BD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,GAAG,SAAS,CAanE"}