@skill-graph/cli 0.5.6

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 (330) hide show
  1. package/CHANGELOG.md +247 -0
  2. package/LICENSE +200 -0
  3. package/NOTICE +62 -0
  4. package/README.md +398 -0
  5. package/SKILL_GRAPH.md +443 -0
  6. package/bin/skill-graph.js +374 -0
  7. package/docs/ADOPTION.md +117 -0
  8. package/docs/CONFORMANCE.md +66 -0
  9. package/docs/PRIMER.md +384 -0
  10. package/docs/QUICKSTART-30MIN.md +333 -0
  11. package/docs/ROUTING-METRICS.md +120 -0
  12. package/docs/SKILL-MD-FORMAT-COMPATIBILITY.md +127 -0
  13. package/docs/SKILL_AUDIT_CHECKLIST.md +199 -0
  14. package/docs/SKILL_AUDIT_LOOP.md +195 -0
  15. package/docs/SKILL_METADATA_PROTOCOL.md +609 -0
  16. package/docs/_archived/marketplace-publication-priority-2026-05-18.md +239 -0
  17. package/docs/adr/0001-predicate-set.md +69 -0
  18. package/docs/adr/0002-json-ld-context.md +82 -0
  19. package/docs/adr/0003-ontoclean-rigidity-tags.md +65 -0
  20. package/docs/adr/0004-persistent-identifiers.md +74 -0
  21. package/docs/adr/0005-freshness-consolidation.md +70 -0
  22. package/docs/adr/0006-revise-predicate-rename.md +105 -0
  23. package/docs/adr/0007-audit-loop-cadence.md +99 -0
  24. package/docs/adr/0008-skill-surface-split-and-curation-policy.md +93 -0
  25. package/docs/category-consumers.md +168 -0
  26. package/docs/concept-map.md +194 -0
  27. package/docs/diagrams/drift-states.mmd +21 -0
  28. package/docs/diagrams/manifest-pipeline.mmd +25 -0
  29. package/docs/diagrams/routing-harness.mmd +41 -0
  30. package/docs/diagrams/starter-graph.mmd +53 -0
  31. package/docs/field-decision-guide.md +315 -0
  32. package/docs/field-rationale.md +211 -0
  33. package/docs/field-reference.generated.md +624 -0
  34. package/docs/field-reference.md +1426 -0
  35. package/docs/glossary.md +190 -0
  36. package/docs/head-noun-glossary.md +63 -0
  37. package/docs/images/audit-phases.png +0 -0
  38. package/docs/images/drift-states.png +0 -0
  39. package/docs/images/graded-mode.png +0 -0
  40. package/docs/images/manifest-pipeline.png +0 -0
  41. package/docs/images/routing-harness.png +0 -0
  42. package/docs/images/skill-anatomy.png +0 -0
  43. package/docs/images/starter-graph.png +0 -0
  44. package/docs/images/system-model.png +0 -0
  45. package/docs/integrations/github-actions.md +155 -0
  46. package/docs/manifest-field-mapping.md +443 -0
  47. package/docs/marketplace-publication-queue.generated.md +240 -0
  48. package/docs/marketplace-release-agent-prompt.md +82 -0
  49. package/docs/marketplace-skill-candidate-list.md +272 -0
  50. package/docs/marketplace-syndication.md +222 -0
  51. package/docs/migration-sample-review.md +155 -0
  52. package/docs/migrations/v4-to-v5.md +168 -0
  53. package/docs/migrations/v5-to-v6.md +221 -0
  54. package/docs/name-exceptions.yaml +37 -0
  55. package/docs/plans/marketplace-p1-public-migration-plan.md +41 -0
  56. package/docs/plans/multi-root-workspace.md +148 -0
  57. package/docs/plans/scripts-roadmap.md +107 -0
  58. package/docs/plans/v4-schema-bump.md +160 -0
  59. package/docs/plans/wave-2-extraction.md +122 -0
  60. package/docs/positioning-vs-marketplaces.md +175 -0
  61. package/docs/proposals/skill-audit-loop-positioning.md +160 -0
  62. package/docs/quality-doctrine.md +138 -0
  63. package/docs/recommended-skills.md +150 -0
  64. package/docs/research/skill-comprehension-eval-research.md +1830 -0
  65. package/docs/research/skill-retrieval-evidence.md +66 -0
  66. package/docs/skill-metadata-protocol.md +471 -0
  67. package/docs/skills-sh-maintainer-cleanup-request.md +80 -0
  68. package/examples/audits/a11y/findings.md +52 -0
  69. package/examples/audits/a11y/scorecard.md +21 -0
  70. package/examples/audits/a11y/verdict.md +44 -0
  71. package/examples/audits/debugging/findings.md +59 -0
  72. package/examples/audits/debugging/scorecard.md +22 -0
  73. package/examples/audits/debugging/verdict.md +33 -0
  74. package/examples/audits/documentation/findings.md +59 -0
  75. package/examples/audits/documentation/scorecard.md +22 -0
  76. package/examples/audits/documentation/verdict.md +33 -0
  77. package/examples/evals/a11y.json +140 -0
  78. package/examples/evals/api-design.json +52 -0
  79. package/examples/evals/code-review.json +52 -0
  80. package/examples/evals/data-modeling.json +52 -0
  81. package/examples/evals/database-migration.json +52 -0
  82. package/examples/evals/debugging.json +118 -0
  83. package/examples/evals/dependency-architecture.json +52 -0
  84. package/examples/evals/design-system-architecture.json +52 -0
  85. package/examples/evals/error-tracking.json +52 -0
  86. package/examples/evals/event-contract-design.json +52 -0
  87. package/examples/evals/form-ux-architecture.json +52 -0
  88. package/examples/evals/framework-fit-analysis.json +52 -0
  89. package/examples/evals/graph-audit.json +139 -0
  90. package/examples/evals/information-architecture.json +52 -0
  91. package/examples/evals/interaction-feedback.json +52 -0
  92. package/examples/evals/interaction-patterns.json +52 -0
  93. package/examples/evals/layout-composition.json +52 -0
  94. package/examples/evals/lint-overlay.json +117 -0
  95. package/examples/evals/microcopy.json +52 -0
  96. package/examples/evals/observability-modeling.json +52 -0
  97. package/examples/evals/pattern-recognition.json +96 -0
  98. package/examples/evals/performance-engineering.json +52 -0
  99. package/examples/evals/refactor.json +128 -0
  100. package/examples/evals/semiotics.json +52 -0
  101. package/examples/evals/skill-infrastructure.json +96 -0
  102. package/examples/evals/skill-router.json +140 -0
  103. package/examples/evals/skill-router.routing.json +113 -0
  104. package/examples/evals/system-interface-contracts.json +52 -0
  105. package/examples/evals/task-analysis.json +52 -0
  106. package/examples/evals/testing-strategy.json +118 -0
  107. package/examples/evals/type-safety.json +249 -0
  108. package/examples/evals/visual-design-foundations.json +52 -0
  109. package/examples/evals/webhook-integration.json +52 -0
  110. package/examples/exports/a11y.skill-md.md +80 -0
  111. package/examples/exports/debugging.skill-md.md +80 -0
  112. package/examples/exports/refactor.skill-md.md +78 -0
  113. package/examples/exports/testing-strategy.skill-md.md +81 -0
  114. package/examples/projects/markdown-static-site/README.md +115 -0
  115. package/examples/projects/markdown-static-site/skills/content-source-router/SKILL.md +131 -0
  116. package/examples/projects/markdown-static-site/skills/image-optimization-pipeline-config/SKILL.md +132 -0
  117. package/examples/projects/markdown-static-site/skills/link-rot-detection/SKILL.md +103 -0
  118. package/examples/projects/markdown-static-site/skills/markdown-post-frontmatter-validation/SKILL.md +133 -0
  119. package/examples/projects/markdown-static-site/skills/migrate-posts-to-v2-frontmatter/SKILL.md +140 -0
  120. package/examples/projects/saas-stripe-postgres/README.md +208 -0
  121. package/examples/projects/saas-stripe-postgres/db/migrations/0004_canonicalize_orders.sql +37 -0
  122. package/examples/projects/saas-stripe-postgres/db/schema.sql +112 -0
  123. package/examples/projects/saas-stripe-postgres/skills/migrate-orders-to-canonical-schema/SKILL.md +149 -0
  124. package/examples/projects/saas-stripe-postgres/skills/nextjs-server-action-validation/SKILL.md +154 -0
  125. package/examples/projects/saas-stripe-postgres/skills/payment-provider-router/SKILL.md +153 -0
  126. package/examples/projects/saas-stripe-postgres/skills/postgres-rls-pattern/SKILL.md +163 -0
  127. package/examples/projects/saas-stripe-postgres/skills/stripe-webhook-signature-verification/SKILL.md +137 -0
  128. package/examples/protocol/skill-metadata-template.md +301 -0
  129. package/examples/protocol/skills.manifest.sample.json +13245 -0
  130. package/examples/skill-metadata-template.md +317 -0
  131. package/examples/skills.manifest.sample.json +13519 -0
  132. package/examples/tests/v3-1-skos-fixture/SKILL.md +93 -0
  133. package/marketplace/README.md +17 -0
  134. package/marketplace/skills/a11y/SKILL.md +66 -0
  135. package/marketplace/skills/acid-fundamentals/SKILL.md +106 -0
  136. package/marketplace/skills/agent-engineering/SKILL.md +386 -0
  137. package/marketplace/skills/agent-eval-design/SKILL.md +55 -0
  138. package/marketplace/skills/ai-native-development/SKILL.md +294 -0
  139. package/marketplace/skills/api-design/SKILL.md +60 -0
  140. package/marketplace/skills/architecture-decision-records/SKILL.md +55 -0
  141. package/marketplace/skills/background-jobs/SKILL.md +265 -0
  142. package/marketplace/skills/bounded-context-mapping/SKILL.md +55 -0
  143. package/marketplace/skills/cap-theorem-tradeoffs/SKILL.md +127 -0
  144. package/marketplace/skills/client-server-boundary/SKILL.md +187 -0
  145. package/marketplace/skills/code-review/SKILL.md +120 -0
  146. package/marketplace/skills/color-system-design/SKILL.md +43 -0
  147. package/marketplace/skills/component-architecture/SKILL.md +126 -0
  148. package/marketplace/skills/compression/SKILL.md +112 -0
  149. package/marketplace/skills/conceptual-modeling/SKILL.md +181 -0
  150. package/marketplace/skills/connection-pooling/SKILL.md +105 -0
  151. package/marketplace/skills/constraint-awareness/SKILL.md +287 -0
  152. package/marketplace/skills/content-monitor/SKILL.md +209 -0
  153. package/marketplace/skills/context-engineering/SKILL.md +320 -0
  154. package/marketplace/skills/context-graph/SKILL.md +174 -0
  155. package/marketplace/skills/context-management/SKILL.md +174 -0
  156. package/marketplace/skills/context-window/SKILL.md +239 -0
  157. package/marketplace/skills/contract-testing/SKILL.md +120 -0
  158. package/marketplace/skills/cron-scheduling/SKILL.md +223 -0
  159. package/marketplace/skills/dark-mode-implementation/SKILL.md +47 -0
  160. package/marketplace/skills/data-modeling/SKILL.md +59 -0
  161. package/marketplace/skills/data-modeling-fundamentals/SKILL.md +117 -0
  162. package/marketplace/skills/database-migration/SKILL.md +429 -0
  163. package/marketplace/skills/debugging/SKILL.md +67 -0
  164. package/marketplace/skills/dependency-architecture/SKILL.md +58 -0
  165. package/marketplace/skills/design-module-composition/SKILL.md +43 -0
  166. package/marketplace/skills/design-system-architecture/SKILL.md +61 -0
  167. package/marketplace/skills/design-thinking/SKILL.md +44 -0
  168. package/marketplace/skills/diagnosis/SKILL.md +296 -0
  169. package/marketplace/skills/diff-analysis/SKILL.md +188 -0
  170. package/marketplace/skills/e2e-test-design/SKILL.md +113 -0
  171. package/marketplace/skills/entity-relationship-modeling/SKILL.md +218 -0
  172. package/marketplace/skills/epistemic-grounding/SKILL.md +112 -0
  173. package/marketplace/skills/error-boundary/SKILL.md +235 -0
  174. package/marketplace/skills/error-tracking/SKILL.md +261 -0
  175. package/marketplace/skills/eval-driven-development/SKILL.md +147 -0
  176. package/marketplace/skills/evaluation/SKILL.md +113 -0
  177. package/marketplace/skills/event-contract-design/SKILL.md +60 -0
  178. package/marketplace/skills/event-storming/SKILL.md +56 -0
  179. package/marketplace/skills/form-ux-architecture/SKILL.md +60 -0
  180. package/marketplace/skills/framework-fit-analysis/SKILL.md +59 -0
  181. package/marketplace/skills/frontend-architecture/SKILL.md +43 -0
  182. package/marketplace/skills/generative-ui/SKILL.md +118 -0
  183. package/marketplace/skills/graph-audit/SKILL.md +81 -0
  184. package/marketplace/skills/guardrails/SKILL.md +118 -0
  185. package/marketplace/skills/hooks-patterns/SKILL.md +185 -0
  186. package/marketplace/skills/http-semantics/SKILL.md +136 -0
  187. package/marketplace/skills/ideation/SKILL.md +41 -0
  188. package/marketplace/skills/indexing-strategy/SKILL.md +108 -0
  189. package/marketplace/skills/information-architecture/SKILL.md +59 -0
  190. package/marketplace/skills/integration-test-design/SKILL.md +111 -0
  191. package/marketplace/skills/intent-recognition/SKILL.md +136 -0
  192. package/marketplace/skills/interaction-feedback/SKILL.md +59 -0
  193. package/marketplace/skills/interaction-patterns/SKILL.md +59 -0
  194. package/marketplace/skills/journey-mapping/SKILL.md +41 -0
  195. package/marketplace/skills/keywords/SKILL.md +213 -0
  196. package/marketplace/skills/knowledge-modeling/SKILL.md +232 -0
  197. package/marketplace/skills/layout-composition/SKILL.md +59 -0
  198. package/marketplace/skills/linguistics/SKILL.md +429 -0
  199. package/marketplace/skills/lint-overlay/SKILL.md +76 -0
  200. package/marketplace/skills/mental-models/SKILL.md +126 -0
  201. package/marketplace/skills/merge-queue/SKILL.md +94 -0
  202. package/marketplace/skills/methodology/SKILL.md +317 -0
  203. package/marketplace/skills/microcopy/SKILL.md +232 -0
  204. package/marketplace/skills/middleware-patterns/SKILL.md +363 -0
  205. package/marketplace/skills/mobile-responsive-ux/SKILL.md +287 -0
  206. package/marketplace/skills/mutation-testing/SKILL.md +112 -0
  207. package/marketplace/skills/naming-conventions/SKILL.md +112 -0
  208. package/marketplace/skills/observability-modeling/SKILL.md +59 -0
  209. package/marketplace/skills/ontology-modeling/SKILL.md +67 -0
  210. package/marketplace/skills/owasp-security/SKILL.md +153 -0
  211. package/marketplace/skills/pattern-recognition/SKILL.md +472 -0
  212. package/marketplace/skills/performance-budgets/SKILL.md +185 -0
  213. package/marketplace/skills/performance-engineering/SKILL.md +58 -0
  214. package/marketplace/skills/performance-testing/SKILL.md +125 -0
  215. package/marketplace/skills/printify/SKILL.md +42 -0
  216. package/marketplace/skills/prioritization/SKILL.md +118 -0
  217. package/marketplace/skills/problem-framing/SKILL.md +41 -0
  218. package/marketplace/skills/problem-locating-solving/SKILL.md +203 -0
  219. package/marketplace/skills/project-knowledge-extraction/SKILL.md +54 -0
  220. package/marketplace/skills/prompt-craft/SKILL.md +134 -0
  221. package/marketplace/skills/prompt-injection-defense/SKILL.md +132 -0
  222. package/marketplace/skills/property-based-testing/SKILL.md +100 -0
  223. package/marketplace/skills/prototyping/SKILL.md +43 -0
  224. package/marketplace/skills/query-optimization/SKILL.md +144 -0
  225. package/marketplace/skills/real-time-updates/SKILL.md +324 -0
  226. package/marketplace/skills/ref-patterns/SKILL.md +284 -0
  227. package/marketplace/skills/refactor/SKILL.md +65 -0
  228. package/marketplace/skills/rendering-models/SKILL.md +142 -0
  229. package/marketplace/skills/replication-patterns/SKILL.md +110 -0
  230. package/marketplace/skills/research-synthesis/SKILL.md +41 -0
  231. package/marketplace/skills/route-handler-design/SKILL.md +347 -0
  232. package/marketplace/skills/schema-evolution/SKILL.md +140 -0
  233. package/marketplace/skills/security-fundamentals/SKILL.md +139 -0
  234. package/marketplace/skills/semantic-center/SKILL.md +194 -0
  235. package/marketplace/skills/semantic-relations/SKILL.md +250 -0
  236. package/marketplace/skills/semantics/SKILL.md +366 -0
  237. package/marketplace/skills/semiotics/SKILL.md +230 -0
  238. package/marketplace/skills/seo-strategy/SKILL.md +260 -0
  239. package/marketplace/skills/server-actions-design/SKILL.md +243 -0
  240. package/marketplace/skills/server-components-design/SKILL.md +190 -0
  241. package/marketplace/skills/sharding-strategy/SKILL.md +123 -0
  242. package/marketplace/skills/shopify/SKILL.md +42 -0
  243. package/marketplace/skills/skill-infrastructure/SKILL.md +320 -0
  244. package/marketplace/skills/skill-router/SKILL.md +71 -0
  245. package/marketplace/skills/skill-scaffold/SKILL.md +105 -0
  246. package/marketplace/skills/snapshot-testing/SKILL.md +120 -0
  247. package/marketplace/skills/spec-driven-development/SKILL.md +148 -0
  248. package/marketplace/skills/state-machine-modeling/SKILL.md +56 -0
  249. package/marketplace/skills/state-management/SKILL.md +134 -0
  250. package/marketplace/skills/streaming-architecture/SKILL.md +194 -0
  251. package/marketplace/skills/summarization/SKILL.md +156 -0
  252. package/marketplace/skills/suspense-patterns/SKILL.md +265 -0
  253. package/marketplace/skills/system-interface-contracts/SKILL.md +59 -0
  254. package/marketplace/skills/task-analysis/SKILL.md +201 -0
  255. package/marketplace/skills/taxonomy-design/SKILL.md +66 -0
  256. package/marketplace/skills/test-coverage-strategy/SKILL.md +108 -0
  257. package/marketplace/skills/test-doubles-design/SKILL.md +98 -0
  258. package/marketplace/skills/test-driven-development/SKILL.md +96 -0
  259. package/marketplace/skills/testing-strategy/SKILL.md +67 -0
  260. package/marketplace/skills/theme-system-design/SKILL.md +43 -0
  261. package/marketplace/skills/tool-call-flow/SKILL.md +229 -0
  262. package/marketplace/skills/tool-call-strategy/SKILL.md +292 -0
  263. package/marketplace/skills/transaction-isolation/SKILL.md +98 -0
  264. package/marketplace/skills/type-safety/SKILL.md +177 -0
  265. package/marketplace/skills/typography-system/SKILL.md +43 -0
  266. package/marketplace/skills/usability-testing/SKILL.md +43 -0
  267. package/marketplace/skills/user-research/SKILL.md +43 -0
  268. package/marketplace/skills/vercel-composition-patterns/SKILL.md +157 -0
  269. package/marketplace/skills/version-control/SKILL.md +233 -0
  270. package/marketplace/skills/visual-design-foundations/SKILL.md +59 -0
  271. package/marketplace/skills/visual-hierarchy/SKILL.md +43 -0
  272. package/marketplace/skills/webhook-integration/SKILL.md +331 -0
  273. package/marketplace/skills/writing-humanizer/SKILL.md +380 -0
  274. package/package.json +67 -0
  275. package/schemas/manifest.schema.json +811 -0
  276. package/schemas/manifest.v2.schema.json +164 -0
  277. package/schemas/manifest.v3.schema.json +758 -0
  278. package/schemas/manifest.v4.schema.json +755 -0
  279. package/schemas/manifest.v5.schema.json +755 -0
  280. package/schemas/manifest.v6.schema.json +811 -0
  281. package/schemas/skill.context.jsonld +279 -0
  282. package/schemas/skill.schema.json +919 -0
  283. package/schemas/skill.v2.schema.json +201 -0
  284. package/schemas/skill.v3.schema.json +827 -0
  285. package/schemas/skill.v4.schema.json +822 -0
  286. package/schemas/skill.v5.schema.json +830 -0
  287. package/schemas/skill.v6.schema.json +946 -0
  288. package/schemas/vocabulary/keywords.json +180 -0
  289. package/schemas/vocabulary/workspace_tags.json +23 -0
  290. package/scripts/__tests__/migrate-skill-v2-to-v3.test.js +161 -0
  291. package/scripts/__tests__/migrate-skill-v3-to-v4.test.js +158 -0
  292. package/scripts/__tests__/test-export-parser-drift.js +149 -0
  293. package/scripts/__tests__/test-marketplace-export.js +114 -0
  294. package/scripts/__tests__/test-router-paths.js +82 -0
  295. package/scripts/__tests__/test-stability-promotion.js +244 -0
  296. package/scripts/__tests__/test-v3-1-alias-contract.js +109 -0
  297. package/scripts/__tests__/test-v3-1-skos-runtime.js +116 -0
  298. package/scripts/backfill-schema-version.js +198 -0
  299. package/scripts/build-field-reference.js +160 -0
  300. package/scripts/build-retrieval-baseline.js +511 -0
  301. package/scripts/check-markdown-links.js +211 -0
  302. package/scripts/check-protocol-consistency.js +979 -0
  303. package/scripts/export-marketplace-skills.js +610 -0
  304. package/scripts/export-skill.js +374 -0
  305. package/scripts/generate-manifest.js +787 -0
  306. package/scripts/lib/alias-contract.js +83 -0
  307. package/scripts/lib/audit-prompt-builder.js +771 -0
  308. package/scripts/lib/mock-grader.js +134 -0
  309. package/scripts/lib/parse-frontmatter.js +429 -0
  310. package/scripts/lib/roots.js +119 -0
  311. package/scripts/lint/check-archetype-sections.js +185 -0
  312. package/scripts/lint/check-category-enum.js +83 -0
  313. package/scripts/lint/check-routing-eval.js +146 -0
  314. package/scripts/lint/check-routing-quality.js +211 -0
  315. package/scripts/lint/check-stability-promotion.js +220 -0
  316. package/scripts/lint/format-code-frame.js +206 -0
  317. package/scripts/marketplace-install.js +125 -0
  318. package/scripts/migrate-category-to-enum.js +169 -0
  319. package/scripts/migrate-skill-v2-to-v3.js +424 -0
  320. package/scripts/migrate-skill-v3-to-v4.js +200 -0
  321. package/scripts/migrate-skill-v5-to-v6.js +304 -0
  322. package/scripts/restructure-by-category.js +85 -0
  323. package/scripts/seed-publication-classification.js +282 -0
  324. package/scripts/skill-audit.js +893 -0
  325. package/scripts/skill-graph-drift.js +483 -0
  326. package/scripts/skill-graph-route.js +766 -0
  327. package/scripts/skill-graph-routing-eval.js +393 -0
  328. package/scripts/skill-lint.js +1317 -0
  329. package/scripts/skill-overlap.js +213 -0
  330. package/scripts/verify-skill-md-export.js +201 -0
@@ -0,0 +1,180 @@
1
+ {
2
+ "$comment": "Controlled vocabulary for the `keywords` field across Skill Graph skills. Prevents drift like 'e-commerce' vs 'ecommerce' as a library scales. Scope: soft-advisory — skill-lint.js emits a WARNING (not an error) when a skill uses a keyword not in this list. Update when a genuinely new domain emerges; do not over-curate.",
3
+ "version": "1.0.0",
4
+ "last_updated": "2026-05-11",
5
+ "synonyms": {
6
+ "e-commerce": "ecommerce",
7
+ "eCommerce": "ecommerce",
8
+ "e commerce": "ecommerce",
9
+ "nextjs": "next.js",
10
+ "nextJS": "next.js",
11
+ "NextJS": "next.js",
12
+ "dev": "engineering",
13
+ "development": "engineering",
14
+ "a11y": "accessibility",
15
+ "i18n": "internationalization",
16
+ "localisation": "localization",
17
+ "postgres": "postgresql",
18
+ "postgreSQL": "postgresql",
19
+ "nodeJS": "node.js",
20
+ "nodejs": "node.js",
21
+ "typescript-strict": "typescript",
22
+ "ts": "typescript",
23
+ "js": "javascript"
24
+ },
25
+ "canonical": [
26
+ "accessibility",
27
+ "agent-framework",
28
+ "skill-md",
29
+ "ai-agents",
30
+ "analytics",
31
+ "api",
32
+ "api-design",
33
+ "architecture",
34
+ "auditing",
35
+ "authentication",
36
+ "authorization",
37
+ "automation",
38
+ "async-api",
39
+ "backend",
40
+ "benchmarking",
41
+ "browser-automation",
42
+ "build-tooling",
43
+ "caching",
44
+ "ci-cd",
45
+ "cli",
46
+ "cloudevents",
47
+ "code-quality",
48
+ "code-review",
49
+ "compliance",
50
+ "configuration",
51
+ "content-strategy",
52
+ "contracts",
53
+ "copywriting",
54
+ "cron",
55
+ "css",
56
+ "dashboard",
57
+ "data-migration",
58
+ "data-modeling",
59
+ "data-pipeline",
60
+ "data-visualization",
61
+ "database",
62
+ "dbt",
63
+ "debugging",
64
+ "deployment",
65
+ "design-system",
66
+ "design-tokens",
67
+ "devops",
68
+ "docker",
69
+ "documentation",
70
+ "domain-driven-design",
71
+ "ecommerce",
72
+ "encryption",
73
+ "engineering",
74
+ "entity-resolution",
75
+ "error-handling",
76
+ "evaluation",
77
+ "event-contract",
78
+ "event-driven",
79
+ "fallback-strategy",
80
+ "feature-flags",
81
+ "fetch",
82
+ "financial-metrics",
83
+ "form-validation",
84
+ "form-ux",
85
+ "forms",
86
+ "frontend",
87
+ "fulfillment",
88
+ "gdpr",
89
+ "graphql",
90
+ "grounding",
91
+ "hitl",
92
+ "hooks",
93
+ "html",
94
+ "information-architecture",
95
+ "inngest",
96
+ "integration",
97
+ "internationalization",
98
+ "interaction-feedback",
99
+ "interaction-patterns",
100
+ "javascript",
101
+ "json",
102
+ "knowledge-graph",
103
+ "layout",
104
+ "legal",
105
+ "linear",
106
+ "linting",
107
+ "load-testing",
108
+ "localization",
109
+ "logging",
110
+ "markdown",
111
+ "layout-composition",
112
+ "mcp",
113
+ "memory",
114
+ "metrics",
115
+ "microcopy",
116
+ "middleware",
117
+ "migration",
118
+ "motion-design",
119
+ "multi-tenancy",
120
+ "neon",
121
+ "next.js",
122
+ "node.js",
123
+ "observability",
124
+ "ontology",
125
+ "orchestration",
126
+ "payments",
127
+ "performance",
128
+ "playwright",
129
+ "postgresql",
130
+ "prisma",
131
+ "privacy",
132
+ "product-strategy",
133
+ "prompt-engineering",
134
+ "provenance",
135
+ "quality",
136
+ "radix-ui",
137
+ "rate-limiting",
138
+ "react",
139
+ "real-time",
140
+ "refactoring",
141
+ "regression-testing",
142
+ "reliability",
143
+ "rendering",
144
+ "responsive",
145
+ "rest",
146
+ "retry",
147
+ "review",
148
+ "rls",
149
+ "routing",
150
+ "scss",
151
+ "security",
152
+ "seo",
153
+ "shopify",
154
+ "skill-audit",
155
+ "skill-graph",
156
+ "skill-routing",
157
+ "skill-scaffolding",
158
+ "stripe",
159
+ "taxonomy",
160
+ "telemetry",
161
+ "testing",
162
+ "theme",
163
+ "threading",
164
+ "tokens",
165
+ "tooling",
166
+ "typescript",
167
+ "ui",
168
+ "unit-testing",
169
+ "ux",
170
+ "validation",
171
+ "vercel",
172
+ "version-control",
173
+ "visual-design",
174
+ "webhook",
175
+ "websocket",
176
+ "woocommerce",
177
+ "workflow",
178
+ "yaml"
179
+ ]
180
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "$comment": "Controlled vocabulary for the `workspace_tags` field. Adopters declare their own literal project handles in their workspace config (`.skill-graph/config.json`); only `skill-graph` (this repo) is shipped as a literal handle. Semantic tags below are illustrative categories cross-project tags commonly fall into. Extend with your own. Scope: soft-advisory; skill-lint.js emits WARNING (not error) for unknown tags.",
3
+ "version": "2.0.0",
4
+ "last_updated": "2026-05-14",
5
+ "literal_project_handles": [
6
+ "skill-graph"
7
+ ],
8
+ "semantic_tags": [
9
+ "ecommerce",
10
+ "saas",
11
+ "b2b",
12
+ "b2c",
13
+ "ai-agent",
14
+ "design-system",
15
+ "infrastructure",
16
+ "analytics",
17
+ "integrations"
18
+ ],
19
+ "synonyms": {
20
+ "e-commerce": "ecommerce",
21
+ "eCommerce": "ecommerce"
22
+ }
23
+ }
@@ -0,0 +1,161 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Tests for migrate-skill-v2-to-v3.js CLI safety surface.
4
+ *
5
+ * Verifies exit codes and flag behaviour without touching migration logic.
6
+ * Uses spawnSync so each test is fully isolated from the current process.
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const fs = require('fs');
12
+ const os = require('os');
13
+ const path = require('path');
14
+ const { spawnSync } = require('child_process');
15
+
16
+ const REPO_ROOT = path.resolve(__dirname, '..', '..');
17
+ const SCRIPT = path.join(REPO_ROOT, 'scripts', 'migrate-skill-v2-to-v3.js');
18
+
19
+ // ---------------------------------------------------------------------------
20
+ // Minimal v2 SKILL.md fixture (has a field to migrate: family → browse_category).
21
+ // ---------------------------------------------------------------------------
22
+ const V2_FIXTURE = `---
23
+ schema_version: 2
24
+ name: test-skill
25
+ family: Testing
26
+ ---
27
+ # Test Skill
28
+ `;
29
+
30
+ // A skill that is already v3 — nothing to migrate.
31
+ const V3_FIXTURE = `---
32
+ schema_version: 3
33
+ name: test-skill
34
+ browse_category: Testing
35
+ ---
36
+ # Test Skill
37
+ `;
38
+
39
+ // ---------------------------------------------------------------------------
40
+ // Helpers
41
+ // ---------------------------------------------------------------------------
42
+
43
+ function run(args) {
44
+ return spawnSync(process.execPath, [SCRIPT, ...args], {
45
+ encoding: 'utf8',
46
+ env: process.env,
47
+ });
48
+ }
49
+
50
+ function withTempDir(fn) {
51
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'v2-to-v3-test-'));
52
+ try {
53
+ return fn(dir);
54
+ } finally {
55
+ fs.rmSync(dir, { recursive: true, force: true });
56
+ }
57
+ }
58
+
59
+ function writeFixture(dir, skillName, content) {
60
+ const skillDir = path.join(dir, skillName);
61
+ fs.mkdirSync(skillDir, { recursive: true });
62
+ const skillMd = path.join(skillDir, 'SKILL.md');
63
+ fs.writeFileSync(skillMd, content, 'utf8');
64
+ return skillMd;
65
+ }
66
+
67
+ // ---------------------------------------------------------------------------
68
+ // Test harness
69
+ // ---------------------------------------------------------------------------
70
+
71
+ let passed = 0;
72
+ let failed = 0;
73
+
74
+ function test(label, fn) {
75
+ try {
76
+ fn();
77
+ process.stdout.write(`PASS migrate-skill-v2-to-v3: ${label}\n`);
78
+ passed++;
79
+ } catch (err) {
80
+ process.stderr.write(`FAIL migrate-skill-v2-to-v3: ${label}\n ${err.message}\n`);
81
+ failed++;
82
+ }
83
+ }
84
+
85
+ function assert(condition, msg) {
86
+ if (!condition) throw new Error(msg);
87
+ }
88
+
89
+ // ---------------------------------------------------------------------------
90
+ // Test 1: --help exits 0, prints usage, writes nothing.
91
+ // ---------------------------------------------------------------------------
92
+ test('--help exits 0 and prints usage', () => {
93
+ const result = run(['--help']);
94
+ assert(result.status === 0, `expected exit 0, got ${result.status}`);
95
+ assert(result.stdout.includes('Usage:'), `expected "Usage:" in stdout, got: ${result.stdout}`);
96
+ });
97
+
98
+ // ---------------------------------------------------------------------------
99
+ // Test 2: No args exits 1 with error message.
100
+ // ---------------------------------------------------------------------------
101
+ test('no args exits 1 with error', () => {
102
+ const result = run([]);
103
+ assert(result.status === 1, `expected exit 1, got ${result.status}`);
104
+ assert(
105
+ result.stderr.includes('must specify') || result.stderr.includes('ERROR'),
106
+ `expected error in stderr, got: ${result.stderr}`
107
+ );
108
+ });
109
+
110
+ // ---------------------------------------------------------------------------
111
+ // Test 3: --skill <nonexistent> exits 1.
112
+ // ---------------------------------------------------------------------------
113
+ test('--skill <nonexistent> exits 1', () => {
114
+ const result = run(['--skill', 'does-not-exist-skill-xyz']);
115
+ assert(result.status === 1, `expected exit 1, got ${result.status}`);
116
+ });
117
+
118
+ // ---------------------------------------------------------------------------
119
+ // Test 4: --all --dry-run exits 0, reports 0 files migrated.
120
+ // ---------------------------------------------------------------------------
121
+ test('--all --dry-run exits 0, reports 0 files migrated', () => {
122
+ // --all scans the repo's skills/ dir which is empty / does not exist in
123
+ // the skill-graph repo itself — this is the "already fully migrated" case.
124
+ const result = run(['--all', '--dry-run']);
125
+ assert(
126
+ result.status === 0,
127
+ `expected exit 0, got ${result.status}\nstdout: ${result.stdout}\nstderr: ${result.stderr}`
128
+ );
129
+ assert(
130
+ result.stdout.includes('0 file') || result.stdout.includes('0 would'),
131
+ `expected 0-files report, got: ${result.stdout}`
132
+ );
133
+ });
134
+
135
+ // ---------------------------------------------------------------------------
136
+ // Test 5: --dry-run with a v2 file exits 0 and shows DIFF, not OK.
137
+ // ---------------------------------------------------------------------------
138
+ test('--dry-run shows DIFF and exits 0 for a v2 file', () => {
139
+ withTempDir(dir => {
140
+ const skillMd = writeFixture(dir, 'test-skill', V2_FIXTURE);
141
+ // Pass the SKILL.md path directly as a positional argument.
142
+ const result = run(['--dry-run', skillMd]);
143
+ assert(
144
+ result.status === 0,
145
+ `expected exit 0, got ${result.status}\nstdout: ${result.stdout}\nstderr: ${result.stderr}`
146
+ );
147
+ assert(
148
+ result.stdout.includes('DIFF') || result.stdout.includes('SKIP') || result.stdout.includes('would migrate'),
149
+ `expected dry-run marker in stdout, got: ${result.stdout}`
150
+ );
151
+ // Verify the file was NOT modified.
152
+ const afterContent = fs.readFileSync(skillMd, 'utf8');
153
+ assert(afterContent === V2_FIXTURE, 'dry-run must not write the file');
154
+ });
155
+ });
156
+
157
+ // ---------------------------------------------------------------------------
158
+ // Summary
159
+ // ---------------------------------------------------------------------------
160
+ process.stdout.write(`\nmigrate-skill-v2-to-v3: ${passed} passed, ${failed} failed.\n`);
161
+ if (failed > 0) process.exit(1);
@@ -0,0 +1,158 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Tests for migrate-skill-v3-to-v4.js CLI safety surface.
4
+ *
5
+ * Verifies exit codes and flag behaviour without touching migration logic.
6
+ * Uses spawnSync so each test is fully isolated from the current process.
7
+ */
8
+
9
+ 'use strict';
10
+
11
+ const fs = require('fs');
12
+ const os = require('os');
13
+ const path = require('path');
14
+ const { spawnSync } = require('child_process');
15
+
16
+ const REPO_ROOT = path.resolve(__dirname, '..', '..');
17
+ const SCRIPT = path.join(REPO_ROOT, 'scripts', 'migrate-skill-v3-to-v4.js');
18
+
19
+ // ---------------------------------------------------------------------------
20
+ // Minimal v3 SKILL.md fixture (has a field to migrate: browse_category).
21
+ // ---------------------------------------------------------------------------
22
+ const V3_FIXTURE = `---
23
+ schema_version: 3
24
+ name: test-skill
25
+ browse_category: Testing
26
+ ---
27
+ # Test Skill
28
+ `;
29
+
30
+ // A skill that is already v4 — nothing to migrate.
31
+ const V4_FIXTURE = `---
32
+ schema_version: 4
33
+ name: test-skill
34
+ category: Testing
35
+ ---
36
+ # Test Skill
37
+ `;
38
+
39
+ // ---------------------------------------------------------------------------
40
+ // Helpers
41
+ // ---------------------------------------------------------------------------
42
+
43
+ function run(args, env) {
44
+ return spawnSync(process.execPath, [SCRIPT, ...args], {
45
+ encoding: 'utf8',
46
+ env: { ...process.env, ...env },
47
+ });
48
+ }
49
+
50
+ function withTempDir(fn) {
51
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'v3-to-v4-test-'));
52
+ try {
53
+ return fn(dir);
54
+ } finally {
55
+ fs.rmSync(dir, { recursive: true, force: true });
56
+ }
57
+ }
58
+
59
+ function writeFixture(dir, content) {
60
+ const skillDir = path.join(dir, 'test-skill');
61
+ fs.mkdirSync(skillDir, { recursive: true });
62
+ const skillMd = path.join(skillDir, 'SKILL.md');
63
+ fs.writeFileSync(skillMd, content, 'utf8');
64
+ return skillMd;
65
+ }
66
+
67
+ // ---------------------------------------------------------------------------
68
+ // Test harness
69
+ // ---------------------------------------------------------------------------
70
+
71
+ let passed = 0;
72
+ let failed = 0;
73
+
74
+ function test(label, fn) {
75
+ try {
76
+ fn();
77
+ process.stdout.write(`PASS migrate-skill-v3-to-v4: ${label}\n`);
78
+ passed++;
79
+ } catch (err) {
80
+ process.stderr.write(`FAIL migrate-skill-v3-to-v4: ${label}\n ${err.message}\n`);
81
+ failed++;
82
+ }
83
+ }
84
+
85
+ function assert(condition, msg) {
86
+ if (!condition) throw new Error(msg);
87
+ }
88
+
89
+ // ---------------------------------------------------------------------------
90
+ // Test 1: --help exits 0, prints usage, writes nothing.
91
+ // ---------------------------------------------------------------------------
92
+ test('--help exits 0 and prints usage', () => {
93
+ withTempDir(dir => {
94
+ const result = run(['--help']);
95
+ assert(result.status === 0, `expected exit 0, got ${result.status}`);
96
+ assert(result.stdout.includes('Usage:'), `expected "Usage:" in stdout, got: ${result.stdout}`);
97
+ });
98
+ });
99
+
100
+ // ---------------------------------------------------------------------------
101
+ // Test 2: No args exits 1 with error message.
102
+ // ---------------------------------------------------------------------------
103
+ test('no args exits 1 with error', () => {
104
+ const result = run([]);
105
+ assert(result.status === 1, `expected exit 1, got ${result.status}`);
106
+ assert(
107
+ result.stderr.includes('must specify') || result.stderr.includes('ERROR'),
108
+ `expected error in stderr, got: ${result.stderr}`
109
+ );
110
+ });
111
+
112
+ // ---------------------------------------------------------------------------
113
+ // Test 3: --skill <nonexistent> exits 1.
114
+ // ---------------------------------------------------------------------------
115
+ test('--skill <nonexistent> exits 1', () => {
116
+ const result = run(['--skill', 'does-not-exist-skill-xyz']);
117
+ assert(result.status === 1, `expected exit 1, got ${result.status}`);
118
+ });
119
+
120
+ // ---------------------------------------------------------------------------
121
+ // Test 4: --all --dry-run exits 0, reports 0 files (already v4 or empty).
122
+ // ---------------------------------------------------------------------------
123
+ test('--all --dry-run exits 0, reports 0 files (already v4)', () => {
124
+ // --all scans the repo's skills/ dir which is empty / does not exist in
125
+ // the skill-graph repo itself — all skills are already v4 or above.
126
+ const result = run(['--all', '--dry-run']);
127
+ assert(
128
+ result.status === 0,
129
+ `expected exit 0, got ${result.status}\nstdout: ${result.stdout}\nstderr: ${result.stderr}`
130
+ );
131
+ assert(
132
+ result.stdout.includes('0 file(s)'),
133
+ `expected "0 file(s)" in output, got: ${result.stdout}`
134
+ );
135
+ });
136
+
137
+ // ---------------------------------------------------------------------------
138
+ // Test 5: --dry-run with a v3 file exits 0 and prints WOULD, not OK.
139
+ // ---------------------------------------------------------------------------
140
+ test('--dry-run shows WOULD and exits 0 for a v3 file', () => {
141
+ withTempDir(dir => {
142
+ const skillMd = writeFixture(dir, V3_FIXTURE);
143
+ // Pass the file directly as a positional argument.
144
+ const result = run(['--dry-run', skillMd]);
145
+ assert(result.status === 0, `expected exit 0, got ${result.status}\nstdout: ${result.stdout}\nstderr: ${result.stderr}`);
146
+ assert(result.stdout.includes('WOULD'), `expected "WOULD" in stdout, got: ${result.stdout}`);
147
+ assert(!result.stdout.includes('OK '), `expected no "OK" writes in dry-run mode, got: ${result.stdout}`);
148
+ // Verify the file was NOT modified.
149
+ const afterContent = fs.readFileSync(skillMd, 'utf8');
150
+ assert(afterContent === V3_FIXTURE, 'dry-run must not write the file');
151
+ });
152
+ });
153
+
154
+ // ---------------------------------------------------------------------------
155
+ // Summary
156
+ // ---------------------------------------------------------------------------
157
+ process.stdout.write(`\nmigrate-skill-v3-to-v4: ${passed} passed, ${failed} failed.\n`);
158
+ if (failed > 0) process.exit(1);
@@ -0,0 +1,149 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Regression tests for export, frontmatter parsing, drift URL handling, and
4
+ * schema-conditional lint enforcement.
5
+ */
6
+
7
+ 'use strict';
8
+
9
+ const fs = require('fs');
10
+ const os = require('os');
11
+ const path = require('path');
12
+ const { spawnSync } = require('child_process');
13
+ const { buildExportedSkill, extractBody, normalizeExportName } = require('../export-skill');
14
+ const { parseFrontmatter } = require('../lib/parse-frontmatter');
15
+ const { sha256TruthSource } = require('../skill-graph-drift');
16
+
17
+ const REPO_ROOT = path.resolve(__dirname, '..', '..');
18
+
19
+ function fail(msg) {
20
+ process.stderr.write(`FAIL test-export-parser-drift: ${msg}\n`);
21
+ process.exit(1);
22
+ }
23
+
24
+ function assert(condition, msg) {
25
+ if (!condition) fail(msg);
26
+ }
27
+
28
+ function assertIncludes(value, expected, msg) {
29
+ if (!String(value).includes(expected)) {
30
+ fail(`${msg}; expected ${JSON.stringify(expected)} in ${JSON.stringify(String(value).slice(0, 500))}`);
31
+ }
32
+ }
33
+
34
+ const crlfSkill = [
35
+ '---',
36
+ 'schema_version: 4',
37
+ 'name: org/foo:bar',
38
+ 'description: "Use when testing export behavior. Do NOT use for production docs."',
39
+ 'version: 1.0.0',
40
+ 'type: capability',
41
+ 'category: quality',
42
+ 'scope: portable',
43
+ 'owner: test',
44
+ 'freshness: "2026-05-13"',
45
+ 'drift_check:',
46
+ ' last_verified: "2026-05-13"',
47
+ 'eval_artifacts: none',
48
+ 'eval_state: unverified',
49
+ 'routing_eval: absent',
50
+ 'workspace_tags: [ecommerce, shopify]',
51
+ 'grounding:',
52
+ ' truth_sources:',
53
+ ' - path: docs/field-reference.md',
54
+ ' line_range: { start: 1, end: 3 }',
55
+ '---',
56
+ '# Body',
57
+ '',
58
+ 'Body survives CRLF export.',
59
+ '',
60
+ ].join('\r\n');
61
+
62
+ assert(extractBody(crlfSkill).startsWith('# Body'), 'extractBody should preserve CRLF bodies');
63
+
64
+ const exported = buildExportedSkill(crlfSkill);
65
+ assert(exported, 'buildExportedSkill should return output for parseable input');
66
+ assertIncludes(exported, 'name: org-foo-bar', 'export should normalize namespaced Skill Graph names');
67
+ assertIncludes(exported, '# Body', 'export should include source body');
68
+ assert(normalizeExportName('org/foo:bar') === 'org-foo-bar', 'normalizeExportName should replace / and : with hyphens');
69
+
70
+ const parsed = parseFrontmatter(crlfSkill);
71
+ assert(Array.isArray(parsed.workspace_tags), 'inline arrays should parse as arrays');
72
+ assert(parsed.workspace_tags[0] === 'ecommerce', 'inline array values should parse as scalars');
73
+ assert(
74
+ parsed.grounding.truth_sources[0].line_range &&
75
+ parsed.grounding.truth_sources[0].line_range.start === 1 &&
76
+ parsed.grounding.truth_sources[0].line_range.end === 3,
77
+ 'inline maps should parse as objects'
78
+ );
79
+
80
+ const parsedSequenceObject = parseFrontmatter([
81
+ '---',
82
+ 'relations:',
83
+ ' boundary:',
84
+ ' - { skill: debugging, reason: "runtime failure" }',
85
+ '---',
86
+ '',
87
+ ].join('\n'));
88
+ assert(
89
+ parsedSequenceObject.relations.boundary[0].skill === 'debugging',
90
+ 'inline object sequence items should parse as objects'
91
+ );
92
+
93
+ const remoteHash = sha256TruthSource('https://example.com/spec');
94
+ assert(remoteHash.external, 'remote truth sources should be marked external');
95
+ assert(remoteHash.hash === null, 'remote truth sources should not be locally hashed');
96
+
97
+ const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'skill-graph-lint-'));
98
+ try {
99
+ const skillDir = path.join(tempRoot, 'deprecated-missing');
100
+ fs.mkdirSync(skillDir, { recursive: true });
101
+ fs.writeFileSync(path.join(skillDir, 'SKILL.md'), [
102
+ '---',
103
+ 'schema_version: 4',
104
+ 'name: deprecated-missing',
105
+ 'description: "Use when testing conditional lint enforcement. Do NOT use for real skills."',
106
+ 'version: 1.0.0',
107
+ 'type: capability',
108
+ 'category: quality',
109
+ 'scope: portable',
110
+ 'owner: test',
111
+ 'freshness: "2026-05-13"',
112
+ 'drift_check:',
113
+ ' last_verified: "2026-05-13"',
114
+ 'eval_artifacts: none',
115
+ 'eval_state: unverified',
116
+ 'routing_eval: absent',
117
+ 'stability: deprecated',
118
+ 'comprehension_state: present',
119
+ '---',
120
+ '# Deprecated Missing',
121
+ '',
122
+ '## Coverage',
123
+ 'Enough text to avoid section-empty warnings while testing conditionals.',
124
+ '',
125
+ '## Philosophy',
126
+ 'Enough text to avoid section-empty warnings while testing conditionals.',
127
+ '',
128
+ '## Verification',
129
+ 'Enough text to avoid section-empty warnings while testing conditionals.',
130
+ '',
131
+ '## Do NOT Use When',
132
+ 'Enough text to avoid section-empty warnings while testing conditionals.',
133
+ '',
134
+ ].join('\n'), 'utf8');
135
+
136
+ const result = spawnSync(
137
+ process.execPath,
138
+ [path.join(REPO_ROOT, 'scripts', 'skill-lint.js'), skillDir, '--no-color', '--skip-generator-parity'],
139
+ { cwd: REPO_ROOT, encoding: 'utf8' }
140
+ );
141
+ const output = `${result.stdout}\n${result.stderr}`;
142
+ assert(result.status === 1, 'lint should fail for missing conditional fields');
143
+ assertIncludes(output, 'stability: deprecated requires superseded_by field', 'lint should enforce deprecated replacement');
144
+ assertIncludes(output, 'comprehension_state: present requires concept field', 'lint should enforce concept block');
145
+ } finally {
146
+ fs.rmSync(tempRoot, { recursive: true, force: true });
147
+ }
148
+
149
+ process.stdout.write('PASS test-export-parser-drift: export/parser/drift/lint edge cases covered\n');