stylegallery 0.1.0

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 (346) hide show
  1. package/AGENTS.md +156 -0
  2. package/CATALOG.md +69 -0
  3. package/DOMAINS.md +65 -0
  4. package/GOVERNANCE.md +222 -0
  5. package/GUIDE.md +59 -0
  6. package/README.md +313 -0
  7. package/consumer-reference/adapters/style-dictionary.config.mjs +36 -0
  8. package/consumer-reference/agent-native/README.md +157 -0
  9. package/consumer-reference/agent-native/registry.json +640 -0
  10. package/consumer-reference/agent-native/schema/agent-native.schema.json +848 -0
  11. package/consumer-reference/agent-native/schema/epistemic.schema.json +14 -0
  12. package/consumer-reference/agent-native/schema/execution.schema.json +12 -0
  13. package/consumer-reference/agent-native/schema/identity.schema.json +10 -0
  14. package/consumer-reference/agent-native/schema/learning.schema.json +12 -0
  15. package/consumer-reference/agent-native/schema/manifest.schema.json +6 -0
  16. package/consumer-reference/agent-native/schema/operation.schema.json +12 -0
  17. package/consumer-reference/agent-native/schema/protocol-binding.schema.json +9 -0
  18. package/consumer-reference/agent-native/schema/retrieval.schema.json +10 -0
  19. package/consumer-reference/baselines/calibration.json +260 -0
  20. package/consumer-reference/baselines/manifest.json +21 -0
  21. package/consumer-reference/contract.md +83 -0
  22. package/consumer-reference/fixtures/consumer-conformance/e2e-fixture.mjs +282 -0
  23. package/consumer-reference/fixtures/consumer-conformance/manifest.json +102 -0
  24. package/consumer-reference/fixtures/consumer-conformance/runtime-proof.mjs +32 -0
  25. package/consumer-reference/fixtures/consumer-conformance/valid-migration-result.json +18 -0
  26. package/consumer-reference/fixtures/consumer-conformance/valid-migration.json +142 -0
  27. package/consumer-reference/fixtures/invalid-stable-ended-support.json +19 -0
  28. package/consumer-reference/fixtures/promotion/invalid-blocking-evidence.json +26 -0
  29. package/consumer-reference/fixtures/promotion/invalid-count-only.json +29 -0
  30. package/consumer-reference/fixtures/promotion/invalid-missing-owner-migration.json +25 -0
  31. package/consumer-reference/fixtures/promotion/invalid-normative-bypass-no-regression.json +25 -0
  32. package/consumer-reference/fixtures/promotion/invalid-related-counted-independent.json +45 -0
  33. package/consumer-reference/fixtures/promotion/invalid-stable-ended-support.json +26 -0
  34. package/consumer-reference/fixtures/promotion/manifest.json +15 -0
  35. package/consumer-reference/fixtures/promotion/valid-deferred-example.json +67 -0
  36. package/consumer-reference/fixtures/promotion/valid-normative-bypass.json +67 -0
  37. package/consumer-reference/fixtures/token-portability/invalid-cycle.json +7 -0
  38. package/consumer-reference/fixtures/token-portability/invalid-dangling-alias.json +6 -0
  39. package/consumer-reference/fixtures/token-portability/invalid-extends.json +4 -0
  40. package/consumer-reference/fixtures/token-portability/invalid-json-pointer.json +7 -0
  41. package/consumer-reference/fixtures/token-portability/invalid-resolver.json +9 -0
  42. package/consumer-reference/fixtures/token-portability/invalid-type-mismatch.json +10 -0
  43. package/consumer-reference/fixtures/token-portability/invalid-unknown-reserved.json +6 -0
  44. package/consumer-reference/fixtures/token-portability/invalid-untested-type.json +6 -0
  45. package/consumer-reference/fixtures/token-portability/valid-border.json +14 -0
  46. package/consumer-reference/fixtures/token-portability/valid-reference.json +32 -0
  47. package/consumer-reference/fixtures/token-portability/valid-whole-alias.json +7 -0
  48. package/consumer-reference/fixtures/valid-deprecated.json +21 -0
  49. package/consumer-reference/fixtures/valid-experimental.json +19 -0
  50. package/consumer-reference/generated/manifest.json +40 -0
  51. package/consumer-reference/generated/tokens.css +12 -0
  52. package/consumer-reference/index.md +32 -0
  53. package/consumer-reference/policies/shared-experimental.json +37 -0
  54. package/consumer-reference/schema/ax-evidence.schema.json +30 -0
  55. package/consumer-reference/schema/baseline-manifest.schema.json +55 -0
  56. package/consumer-reference/schema/calibration-record.schema.json +190 -0
  57. package/consumer-reference/schema/capture-session.schema.json +161 -0
  58. package/consumer-reference/schema/component-state.schema.json +150 -0
  59. package/consumer-reference/schema/consumer-conformance-record.schema.json +365 -0
  60. package/consumer-reference/schema/dom-evidence.schema.json +38 -0
  61. package/consumer-reference/schema/evidence-record.schema.json +81 -0
  62. package/consumer-reference/schema/fixture-manifest.schema.json +32 -0
  63. package/consumer-reference/schema/item.schema.json +188 -0
  64. package/consumer-reference/schema/page-evidence-manifest.schema.json +216 -0
  65. package/consumer-reference/schema/page-evidence-session.schema.json +119 -0
  66. package/consumer-reference/schema/portable-tokens.schema.json +104 -0
  67. package/consumer-reference/schema/promotion-rfc.schema.json +219 -0
  68. package/consumer-reference/schema/runtime-evidence-manifest.schema.json +33 -0
  69. package/consumer-reference/schema/visual-evidence.schema.json +31 -0
  70. package/design-engineering/consumer-migration-readiness.md +124 -0
  71. package/design-engineering/index.md +28 -0
  72. package/design-engineering/interface-craft.md +107 -0
  73. package/design-engineering/reference-profiles/external-adaptation/index.md +12 -0
  74. package/design-engineering/reference-profiles/governed-local/editorial/components/button.component.json +125 -0
  75. package/design-engineering/reference-profiles/governed-local/editorial/evidence/button.evidence.json +3504 -0
  76. package/design-engineering/reference-profiles/governed-local/editorial/fixtures/button.fixture.json +65 -0
  77. package/design-engineering/reference-profiles/governed-local/editorial/generated/evidence-coverage.md +23 -0
  78. package/design-engineering/reference-profiles/governed-local/editorial/generated/keyboard-matrix.md +19 -0
  79. package/design-engineering/reference-profiles/governed-local/editorial/generated/state-matrix.md +21 -0
  80. package/design-engineering/reference-profiles/governed-local/editorial/local-foundations.json +12 -0
  81. package/design-engineering/reference-profiles/governed-local/editorial/profile.json +43 -0
  82. package/design-engineering/reference-profiles/governed-local/editorial/states/button.states.json +195 -0
  83. package/design-engineering/reference-profiles/governed-local/editorial/tokens.dtcg.json +17 -0
  84. package/design-engineering/reference-profiles/governed-local/index.md +26 -0
  85. package/design-engineering/reference-profiles/governed-local/terminal/components/button.component.json +125 -0
  86. package/design-engineering/reference-profiles/governed-local/terminal/evidence/button.evidence.json +3504 -0
  87. package/design-engineering/reference-profiles/governed-local/terminal/fixtures/button.fixture.json +65 -0
  88. package/design-engineering/reference-profiles/governed-local/terminal/generated/evidence-coverage.md +23 -0
  89. package/design-engineering/reference-profiles/governed-local/terminal/generated/keyboard-matrix.md +19 -0
  90. package/design-engineering/reference-profiles/governed-local/terminal/generated/state-matrix.md +21 -0
  91. package/design-engineering/reference-profiles/governed-local/terminal/local-foundations.json +12 -0
  92. package/design-engineering/reference-profiles/governed-local/terminal/profile.json +43 -0
  93. package/design-engineering/reference-profiles/governed-local/terminal/states/button.states.json +195 -0
  94. package/design-engineering/reference-profiles/governed-local/terminal/tokens.dtcg.json +17 -0
  95. package/design-engineering/reference-profiles/index.md +19 -0
  96. package/game-ui/classification.md +82 -0
  97. package/game-ui/index.md +35 -0
  98. package/game-ui/reference-record.md +62 -0
  99. package/game-ui/screen-hierarchy.md +107 -0
  100. package/game-ui/unity/architecture.md +166 -0
  101. package/game-ui/unity/cli-loop.md +84 -0
  102. package/game-ui/unity/data/unity-technologies-public-repositories.json +26654 -0
  103. package/game-ui/unity/org-wiki.md +146 -0
  104. package/game-ui/unity/repository-map.md +102 -0
  105. package/game-ui/unity/ui-systems.md +85 -0
  106. package/guides/decision-tree.md +149 -0
  107. package/guides/documentation-mode-taxonomy.md +157 -0
  108. package/guides/layout-brief.md +220 -0
  109. package/guides/vocabulary.md +148 -0
  110. package/guides/webpage-generation-workflow.md +185 -0
  111. package/index.md +36 -0
  112. package/layout/index.md +26 -0
  113. package/motion/index.md +24 -0
  114. package/motion/practice-reference.md +145 -0
  115. package/motion/review-workflow.md +86 -0
  116. package/motion/vocabulary.md +82 -0
  117. package/package.json +78 -0
  118. package/patterns/centering/center.md +87 -0
  119. package/patterns/centering/index.md +6 -0
  120. package/patterns/centering/super-center.md +89 -0
  121. package/patterns/containment/box.md +87 -0
  122. package/patterns/containment/clamped-card.md +86 -0
  123. package/patterns/containment/content-limiter.md +87 -0
  124. package/patterns/containment/fluid-styles.md +86 -0
  125. package/patterns/containment/index.md +8 -0
  126. package/patterns/grid-repetition/card-grid.md +88 -0
  127. package/patterns/grid-repetition/columns.md +87 -0
  128. package/patterns/grid-repetition/dense-grid.md +88 -0
  129. package/patterns/grid-repetition/grid-wrapper.md +89 -0
  130. package/patterns/grid-repetition/index.md +12 -0
  131. package/patterns/grid-repetition/masonry-approx.md +87 -0
  132. package/patterns/grid-repetition/page-grid.md +90 -0
  133. package/patterns/grid-repetition/ram-grid.md +88 -0
  134. package/patterns/grid-repetition/twelve-span-grid.md +92 -0
  135. package/patterns/in-line-grouping/badge-list.md +94 -0
  136. package/patterns/in-line-grouping/breadcrumb.md +89 -0
  137. package/patterns/in-line-grouping/cluster.md +89 -0
  138. package/patterns/in-line-grouping/deconstructed-pancake.md +92 -0
  139. package/patterns/in-line-grouping/index.md +13 -0
  140. package/patterns/in-line-grouping/pagination.md +89 -0
  141. package/patterns/in-line-grouping/reel.md +90 -0
  142. package/patterns/in-line-grouping/split-nav.md +97 -0
  143. package/patterns/in-line-grouping/tab-strip.md +88 -0
  144. package/patterns/in-line-grouping/wrap-row.md +89 -0
  145. package/patterns/index.md +13 -0
  146. package/patterns/media-fit/frame.md +95 -0
  147. package/patterns/media-fit/icon-frame.md +87 -0
  148. package/patterns/media-fit/index.md +6 -0
  149. package/patterns/overlay-exception/imposter.md +95 -0
  150. package/patterns/overlay-exception/index.md +6 -0
  151. package/patterns/overlay-exception/overlay-stack.md +89 -0
  152. package/patterns/split-sidebar/index.md +12 -0
  153. package/patterns/split-sidebar/list-detail.md +95 -0
  154. package/patterns/split-sidebar/main-with-rail.md +95 -0
  155. package/patterns/split-sidebar/media-object.md +102 -0
  156. package/patterns/split-sidebar/sidebar.md +101 -0
  157. package/patterns/split-sidebar/split-screen.md +92 -0
  158. package/patterns/split-sidebar/sticky-aside.md +97 -0
  159. package/patterns/split-sidebar/supporting-pane.md +95 -0
  160. package/patterns/split-sidebar/switcher.md +93 -0
  161. package/patterns/stacking/feed.md +88 -0
  162. package/patterns/stacking/index.md +8 -0
  163. package/patterns/stacking/line-up.md +95 -0
  164. package/patterns/stacking/stack.md +87 -0
  165. package/patterns/stacking/step-nav.md +88 -0
  166. package/patterns/viewport-shell/cover.md +90 -0
  167. package/patterns/viewport-shell/fixed-sidenav-shell.md +97 -0
  168. package/patterns/viewport-shell/holy-grail.md +112 -0
  169. package/patterns/viewport-shell/index.md +11 -0
  170. package/patterns/viewport-shell/panel-layout.md +95 -0
  171. package/patterns/viewport-shell/scroll-body-shell.md +93 -0
  172. package/patterns/viewport-shell/sticky-footer.md +92 -0
  173. package/patterns/viewport-shell/sticky-header.md +86 -0
  174. package/platform-guides/apple-interaction.md +89 -0
  175. package/platform-guides/index.md +26 -0
  176. package/quality/claim-records/index.md +3 -0
  177. package/quality/claim-records/samples.md +92 -0
  178. package/quality/claim-records/stylegallery-multidomain-scope.md +42 -0
  179. package/quality/claims.md +77 -0
  180. package/quality/evidence/accessibility.md +58 -0
  181. package/quality/evidence/consumer-migration.md +42 -0
  182. package/quality/evidence/design-rationale.md +34 -0
  183. package/quality/evidence/executable-evidence.md +79 -0
  184. package/quality/evidence/families.md +56 -0
  185. package/quality/evidence/hci-evaluation.md +36 -0
  186. package/quality/evidence/index.md +16 -0
  187. package/quality/evidence/pattern-contract-audit.md +96 -0
  188. package/quality/evidence/search-metadata-polyhierarchy.md +86 -0
  189. package/quality/evidence/sources.md +43 -0
  190. package/quality/evidence/tokens.md +33 -0
  191. package/quality/evidence/visual-qa.md +41 -0
  192. package/quality/gates/accessibility-evidence.md +60 -0
  193. package/quality/gates/consumer-migration-evidence.md +53 -0
  194. package/quality/gates/design-claim.md +56 -0
  195. package/quality/gates/harmony-evaluation.md +78 -0
  196. package/quality/gates/index.md +13 -0
  197. package/quality/gates/layout.md +52 -0
  198. package/quality/gates/rationale.md +53 -0
  199. package/quality/gates/visual-evidence.md +47 -0
  200. package/quality/index.md +55 -0
  201. package/quality/principles.md +58 -0
  202. package/recipes/article-page.md +52 -0
  203. package/recipes/command-surface.md +55 -0
  204. package/recipes/dashboard.md +56 -0
  205. package/recipes/form-flow.md +55 -0
  206. package/recipes/homepage.md +89 -0
  207. package/recipes/index.md +13 -0
  208. package/recipes/list-detail.md +55 -0
  209. package/recipes/primitive-to-recipe-matrix.md +83 -0
  210. package/recipes/saas-settings.md +52 -0
  211. package/scripts/agent-native/a2a-projection.mjs +248 -0
  212. package/scripts/agent-native/agui-projection.mjs +178 -0
  213. package/scripts/agent-native/canonical-json.mjs +109 -0
  214. package/scripts/agent-native/cli-adapter.mjs +68 -0
  215. package/scripts/agent-native/events.mjs +113 -0
  216. package/scripts/agent-native/execution.mjs +227 -0
  217. package/scripts/agent-native/fixture.mjs +159 -0
  218. package/scripts/agent-native/identity.mjs +184 -0
  219. package/scripts/agent-native/immutable-store.mjs +102 -0
  220. package/scripts/agent-native/knowledge.mjs +168 -0
  221. package/scripts/agent-native/learning-records.mjs +244 -0
  222. package/scripts/agent-native/learning.mjs +247 -0
  223. package/scripts/agent-native/mcp-adapter.mjs +173 -0
  224. package/scripts/agent-native/queries.mjs +173 -0
  225. package/scripts/agent-native/registry.mjs +154 -0
  226. package/scripts/agent-native/retrieval.mjs +171 -0
  227. package/scripts/agent-native/self-description.mjs +160 -0
  228. package/scripts/artifact-metadata.mjs +20 -0
  229. package/scripts/audit-evidence-freshness.mjs +308 -0
  230. package/scripts/baseline-contract.mjs +189 -0
  231. package/scripts/baseline-schema-parity.mjs +40 -0
  232. package/scripts/build-reference-artifacts.mjs +127 -0
  233. package/scripts/calibration-raw-contract.mjs +172 -0
  234. package/scripts/capture-session-contract.mjs +187 -0
  235. package/scripts/component-state-artifact-fixture.mjs +44 -0
  236. package/scripts/component-state-contract.mjs +99 -0
  237. package/scripts/component-state-semantics.mjs +128 -0
  238. package/scripts/component-state-workflow-contract.mjs +67 -0
  239. package/scripts/component-state-workflow-negative-cases.mjs +64 -0
  240. package/scripts/consumer-conformance-contract.mjs +198 -0
  241. package/scripts/consumer-evidence-governance-contract.mjs +210 -0
  242. package/scripts/consumer-reference-case-runner.mjs +93 -0
  243. package/scripts/consumer-reference-schema.mjs +155 -0
  244. package/scripts/create-component-state-session.mjs +100 -0
  245. package/scripts/create-page-evidence-session.mjs +139 -0
  246. package/scripts/domain-document-boundaries.mjs +40 -0
  247. package/scripts/domain-validation-checks.mjs +141 -0
  248. package/scripts/evidence-artifact-contract.mjs +191 -0
  249. package/scripts/finalize-component-state-evidence.mjs +165 -0
  250. package/scripts/finalize-page-evidence.mjs +197 -0
  251. package/scripts/generate-consumer-reference-evidence.mjs +154 -0
  252. package/scripts/generate-patterns.mjs +218 -0
  253. package/scripts/governance-matrix-contract.mjs +73 -0
  254. package/scripts/governance-matrix-negative-cases.mjs +114 -0
  255. package/scripts/governance-policy-contract.mjs +49 -0
  256. package/scripts/governance-test-fixture.mjs +321 -0
  257. package/scripts/governance-workflow-negative-cases.mjs +241 -0
  258. package/scripts/governed-profile-registry.mjs +125 -0
  259. package/scripts/json-schema-formats.mjs +31 -0
  260. package/scripts/markdown-structure.mjs +45 -0
  261. package/scripts/page-artifact-metadata.mjs +124 -0
  262. package/scripts/page-evidence-contract.mjs +297 -0
  263. package/scripts/page-evidence-fixture.mjs +271 -0
  264. package/scripts/pattern-data.mjs +325 -0
  265. package/scripts/profile-record-contract.mjs +140 -0
  266. package/scripts/promotion-attestation-contract.mjs +91 -0
  267. package/scripts/promotion-boundary-test-contract.mjs +92 -0
  268. package/scripts/promotion-fixture-inventory.mjs +109 -0
  269. package/scripts/promotion-governance-contract.mjs +28 -0
  270. package/scripts/reference-artifact-path-contract.mjs +28 -0
  271. package/scripts/reference-profile-contract.mjs +114 -0
  272. package/scripts/reference-token-contract.mjs +156 -0
  273. package/scripts/run-consumer-page-evidence-ci.mjs +170 -0
  274. package/scripts/sg-mcp.mjs +16 -0
  275. package/scripts/sg.mjs +27 -0
  276. package/scripts/strict-json.mjs +72 -0
  277. package/scripts/summarize-sentinel-calibration.mjs +98 -0
  278. package/scripts/test-agent-adapter-conformance.mjs +250 -0
  279. package/scripts/test-agent-conformance-receipt.mjs +106 -0
  280. package/scripts/test-agent-events.mjs +81 -0
  281. package/scripts/test-agent-execution-effects.mjs +114 -0
  282. package/scripts/test-agent-execution-fixtures.mjs +140 -0
  283. package/scripts/test-agent-execution-kernel.mjs +39 -0
  284. package/scripts/test-agent-execution-learning.mjs +130 -0
  285. package/scripts/test-agent-execution-lifecycle.mjs +143 -0
  286. package/scripts/test-agent-execution-safety.mjs +158 -0
  287. package/scripts/test-agent-execution-views.mjs +117 -0
  288. package/scripts/test-agent-identity-integrity-cases.mjs +160 -0
  289. package/scripts/test-agent-knowledge-kernel.mjs +183 -0
  290. package/scripts/test-agent-learning.mjs +246 -0
  291. package/scripts/test-agent-mcp.mjs +246 -0
  292. package/scripts/test-agent-native-schemas.mjs +215 -0
  293. package/scripts/test-agent-projections.mjs +249 -0
  294. package/scripts/test-agent-registry-mcp-integrity.mjs +215 -0
  295. package/scripts/test-agent-registry-mutations.mjs +110 -0
  296. package/scripts/test-audit-evidence-freshness.mjs +177 -0
  297. package/scripts/test-component-state-sentinel.mjs +35 -0
  298. package/scripts/test-component-state-source-contract.mjs +83 -0
  299. package/scripts/test-consumer-conformance-sentinel.mjs +165 -0
  300. package/scripts/test-consumer-reference-sentinel.mjs +31 -0
  301. package/scripts/test-generate-consumer-reference-evidence.mjs +124 -0
  302. package/scripts/test-json-cli-output.mjs +151 -0
  303. package/scripts/test-json-schema-formats.mjs +40 -0
  304. package/scripts/test-reference-adapters.mjs +199 -0
  305. package/scripts/test-renderer-purity.mjs +34 -0
  306. package/scripts/test-sg-cli.mjs +129 -0
  307. package/scripts/test-summarize-sentinel-calibration.mjs +226 -0
  308. package/scripts/test-validate-baseline-manifest.mjs +234 -0
  309. package/scripts/test-validate-component-state-artifacts.mjs +243 -0
  310. package/scripts/test-validate-component-state.mjs +106 -0
  311. package/scripts/test-validate-consumer-conformance.mjs +427 -0
  312. package/scripts/test-validate-consumer-reference-cli.mjs +69 -0
  313. package/scripts/test-validate-consumer-reference.mjs +263 -0
  314. package/scripts/test-validate-domains.mjs +357 -0
  315. package/scripts/test-validate-governance.mjs +292 -0
  316. package/scripts/test-validate-ia.mjs +262 -0
  317. package/scripts/test-validate-okf.mjs +73 -0
  318. package/scripts/test-validate-page-evidence.mjs +302 -0
  319. package/scripts/test-validate-patterns.mjs +157 -0
  320. package/scripts/test-validate-promotion-rfc.mjs +250 -0
  321. package/scripts/test-validate-reference-profiles.mjs +170 -0
  322. package/scripts/test-validate-unity-org-wiki.mjs +57 -0
  323. package/scripts/test-validate-unity-source-contracts.mjs +67 -0
  324. package/scripts/test-validate-vocabulary.mjs +174 -0
  325. package/scripts/test-validate-webpage-workflow.mjs +293 -0
  326. package/scripts/validate-baseline-manifest.mjs +44 -0
  327. package/scripts/validate-catalog.mjs +65 -0
  328. package/scripts/validate-component-state.mjs +141 -0
  329. package/scripts/validate-consumer-conformance.mjs +477 -0
  330. package/scripts/validate-consumer-reference.mjs +288 -0
  331. package/scripts/validate-domains.mjs +237 -0
  332. package/scripts/validate-governance.mjs +248 -0
  333. package/scripts/validate-ia.mjs +136 -0
  334. package/scripts/validate-links.mjs +66 -0
  335. package/scripts/validate-okf.mjs +104 -0
  336. package/scripts/validate-page-evidence.mjs +191 -0
  337. package/scripts/validate-patterns.mjs +246 -0
  338. package/scripts/validate-promotion-rfc.mjs +224 -0
  339. package/scripts/validate-reference-artifacts.mjs +125 -0
  340. package/scripts/validate-renderer-purity.mjs +56 -0
  341. package/scripts/validate-unity-org-wiki.mjs +146 -0
  342. package/scripts/validate-unity-source-contracts.mjs +107 -0
  343. package/scripts/validate-vocabulary.mjs +115 -0
  344. package/scripts/validate-webpage-workflow.mjs +254 -0
  345. package/scripts/visual-expectation-contract.mjs +20 -0
  346. package/scripts/workflow-action-contract.mjs +163 -0
@@ -0,0 +1,292 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from "node:fs";
4
+ import os from "node:os";
5
+ import path from "node:path";
6
+ import { spawnSync } from "node:child_process";
7
+ import { fileURLToPath } from "node:url";
8
+ import { files, generatedWarning, sentinelProvenanceClauses } from "./governance-test-fixture.mjs";
9
+ import { governanceMatrixCases } from "./governance-matrix-negative-cases.mjs";
10
+ import { componentStateWorkflowCases } from "./component-state-workflow-negative-cases.mjs";
11
+ import { workflowSafetyCases } from "./governance-workflow-negative-cases.mjs";
12
+
13
+ const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
14
+ const validator = path.join(root, "scripts", "validate-governance.mjs");
15
+ const adapterHarness = path.join(root, "scripts", "test-reference-adapters.mjs");
16
+ const adapterPipeParser = 'let output = ""; process.stdin.setEncoding("utf8"); process.stdin.on("data", (chunk) => { output += chunk; }); process.stdin.on("end", () => { const report = JSON.parse(output); const complete = report.ok === true && report.failures.length === 0 && report.results.length === 42; process.stdout.write(complete ? "42\\n" : "incomplete\\n"); process.exitCode = complete ? 0 : 1; });';
17
+
18
+ const cases = [
19
+ { name: "missing_governance", omit: ["GOVERNANCE.md"], expect: "GOVERNANCE.md: missing file" },
20
+ { name: "broad_profile_sources_claim_no_generated_artifacts", mutate: { "GOVERNANCE.md": files["GOVERNANCE.md"].replace(/`design-engineering\/reference-profiles\/governed-local\/editorial\/profile\.json`[^|]+/, "`design-engineering/reference-profiles/governed-local/**`") }, expect: "GOVERNANCE.md: governed local reference profile sources must be the six explicit canonical profile files" },
21
+ { name: "missing_matrix_stale_trigger", mutate: { "GOVERNANCE.md": files["GOVERNANCE.md"].replace("Generated structure changes, generated-warning changes, or generated metadata changes.", "Generated structure changes.") }, expect: "GOVERNANCE.md: missing Generated structure changes, generated-warning changes, or generated metadata changes." },
22
+ { name: "missing_game_ui_domain_family", mutate: { "GOVERNANCE.md": files["GOVERNANCE.md"].replace(/^\| Game UI domain guidance .*\n/m, "") }, expect: "GOVERNANCE.md: missing Game UI domain guidance" },
23
+ { name: "missing_evidence_fixture_coverage", mutate: { "quality/evidence/executable-evidence.md": "Missing governance file or generated warning fixtures must fail." }, expect: "quality/evidence/executable-evidence.md: missing Missing governance file, generated warning, generated metadata, CODEOWNERS coverage, or stale policy fixtures must fail." },
24
+ {
25
+ name: "missing_generated_warning",
26
+ mutate: {
27
+ "patterns/stacking/stack.md": [
28
+ "---",
29
+ "lifecycle: generated",
30
+ "generated_from: scripts/generate-patterns.mjs, scripts/pattern-data.mjs",
31
+ "---",
32
+ "",
33
+ "# stack",
34
+ "",
35
+ ].join("\n"),
36
+ },
37
+ expect: "patterns/stacking/stack.md: missing generated warning",
38
+ },
39
+ { name: "missing_generated_metadata", mutate: { "patterns/stacking/stack.md": `# stack\n\n${generatedWarning}\n` }, expect: "patterns/stacking/stack.md: missing lifecycle: generated" },
40
+ {
41
+ name: "missing_codeowners_coverage",
42
+ mutate: {
43
+ ".github/CODEOWNERS": [
44
+ "* @changeroa",
45
+ "/GOVERNANCE.md @changeroa",
46
+ "/scripts/pattern-data.mjs @changeroa",
47
+ "/patterns/ @changeroa",
48
+ "",
49
+ ].join("\n"),
50
+ },
51
+ expect: ".github/CODEOWNERS: missing /README.md @changeroa",
52
+ },
53
+ {
54
+ name: "missing_workflow_permissions",
55
+ mutate: {
56
+ ".github/workflows/validate.yml": [
57
+ "node -c scripts/validate-governance.mjs",
58
+ "node -c scripts/test-validate-governance.mjs",
59
+ "node scripts/validate-governance.mjs --json",
60
+ "node scripts/test-validate-governance.mjs --json",
61
+ "",
62
+ ].join("\n"),
63
+ },
64
+ expect: ".github/workflows/validate.yml: missing permissions:",
65
+ },
66
+ { name: "missing_stale_policy", mutate: { "GOVERNANCE.md": files["GOVERNANCE.md"].replace("scheduled_stale_audit: deferred\n", "") }, expect: "GOVERNANCE.md: missing scheduled_stale_audit: deferred" },
67
+ { name: "missing_evidence_audit_policy", mutate: { "GOVERNANCE.md": files["GOVERNANCE.md"].replace("scheduled_evidence_audit: active_advisory\n", "") }, expect: "GOVERNANCE.md: missing scheduled_evidence_audit: active_advisory" },
68
+ {
69
+ name: "paraphrased_stale_policy",
70
+ mutate: {
71
+ "GOVERNANCE.md": files["GOVERNANCE.md"].replace(
72
+ "Decision: run a weekly advisory audit only for evidence records that already declare `expires_at` or `review_by`.",
73
+ "Decision: inspect old evidence from time to time.",
74
+ ),
75
+ },
76
+ expect: "GOVERNANCE.md: missing Decision: run a weekly advisory audit only for evidence records that already declare `expires_at` or `review_by`.",
77
+ },
78
+ { name: "missing_no_universal_age_boundary", mutate: { "GOVERNANCE.md": files["GOVERNANCE.md"].replace("No repository-wide maximum age or inferred time-to-live applies.", "Evidence gets old after 30 days.") }, expect: "GOVERNANCE.md: missing No repository-wide maximum age or inferred time-to-live applies." },
79
+ { name: "missing_freshness_workflow", omit: [".github/workflows/evidence-freshness.yml"], expect: ".github/workflows/evidence-freshness.yml: missing file" },
80
+ { name: "freshness_schedule_drift", mutate: { ".github/workflows/evidence-freshness.yml": files[".github/workflows/evidence-freshness.yml"].replace("cron: '0 5 * * 1'", "cron: '0 5 * * 2'") }, expect: ".github/workflows/evidence-freshness.yml: missing Monday 05:00 UTC schedule" },
81
+ { name: "freshness_mode_became_blocking", mutate: { ".github/workflows/evidence-freshness.yml": files[".github/workflows/evidence-freshness.yml"].replace("--mode advisory", "--mode blocking") }, expect: ".github/workflows/evidence-freshness.yml: missing --mode advisory" },
82
+ { name: "freshness_blanket_continue", mutate: { ".github/workflows/evidence-freshness.yml": `${files[".github/workflows/evidence-freshness.yml"]}\ncontinue-on-error: true\n` }, expect: ".github/workflows/evidence-freshness.yml: continue-on-error is forbidden because malformed records and tool failures must block" },
83
+ { name: "consumer_browser_became_nonblocking", mutate: { ".github/workflows/validate.yml": files[".github/workflows/validate.yml"].replace(" consumer-conformance:\n", " consumer-conformance:\n continue-on-error: true\n") }, expect: ".github/workflows/validate.yml: consumer-conformance must be blocking" },
84
+ {
85
+ name: "consumer_browser_command_commented_out",
86
+ mutate: { ".github/workflows/validate.yml": files[".github/workflows/validate.yml"].replace(" - run: npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line", " - run: |\n # npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line\n true") },
87
+ expect: ".github/workflows/validate.yml: consumer-conformance: missing npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line",
88
+ },
89
+ {
90
+ name: "consumer_browser_command_relocated",
91
+ mutate: { ".github/workflows/validate.yml": files[".github/workflows/validate.yml"].replace(" - run: npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line", " - run: true").replace(" chromium-sentinel:\n", " chromium-sentinel:\n steps:\n - run: npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line\n") },
92
+ expect: ".github/workflows/validate.yml: consumer-conformance: missing npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line",
93
+ },
94
+ {
95
+ name: "consumer_browser_command_hidden_in_env",
96
+ mutate: { ".github/workflows/validate.yml": files[".github/workflows/validate.yml"].replace(" - run: npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line", " - name: Hidden browser command\n env:\n run: npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line\n run: true") },
97
+ expect: ".github/workflows/validate.yml: consumer-conformance: missing npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line",
98
+ },
99
+ {
100
+ name: "consumer_browser_command_hidden_in_inline_comment",
101
+ mutate: { ".github/workflows/validate.yml": files[".github/workflows/validate.yml"].replace(" - run: npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line", " - run: true # npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line") },
102
+ expect: ".github/workflows/validate.yml: consumer-conformance: missing npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line",
103
+ },
104
+ {
105
+ name: "consumer_browser_command_in_disabled_step",
106
+ mutate: { ".github/workflows/validate.yml": files[".github/workflows/validate.yml"].replace(" - run: npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line", " - name: Disabled browser command\n if: false\n run: npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line") },
107
+ expect: ".github/workflows/validate.yml: consumer-conformance: missing npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line",
108
+ },
109
+ {
110
+ name: "consumer_browser_command_hidden_in_heredoc",
111
+ mutate: { ".github/workflows/validate.yml": files[".github/workflows/validate.yml"].replace(" - run: npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line", " - run: |\n cat <<'PROBE'\n npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line\n PROBE\n true") },
112
+ expect: ".github/workflows/validate.yml: consumer-conformance: missing npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line",
113
+ },
114
+ {
115
+ name: "consumer_browser_command_hidden_in_numeric_heredoc",
116
+ mutate: { ".github/workflows/validate.yml": files[".github/workflows/validate.yml"].replace(" - run: npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line", " - run: |\n cat <<'123'\n npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line\n 123\n true") },
117
+ expect: ".github/workflows/validate.yml: consumer-conformance: missing npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line",
118
+ },
119
+ {
120
+ name: "consumer_browser_command_echo_only",
121
+ mutate: { ".github/workflows/validate.yml": files[".github/workflows/validate.yml"].replace(" - run: npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line", " - run: echo npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line") },
122
+ expect: ".github/workflows/validate.yml: consumer-conformance: missing npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line",
123
+ },
124
+ {
125
+ name: "consumer_browser_command_shell_builtin_echo",
126
+ mutate: { ".github/workflows/validate.yml": files[".github/workflows/validate.yml"].replace(" - run: npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line", " - run: command echo npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line") },
127
+ expect: ".github/workflows/validate.yml: consumer-conformance: missing npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line",
128
+ },
129
+ {
130
+ name: "consumer_browser_command_short_circuited",
131
+ mutate: { ".github/workflows/validate.yml": files[".github/workflows/validate.yml"].replace(" - run: npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line", " - run: false && npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line") },
132
+ expect: ".github/workflows/validate.yml: consumer-conformance: missing npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line",
133
+ },
134
+ {
135
+ name: "consumer_browser_command_failure_ignored",
136
+ mutate: { ".github/workflows/validate.yml": files[".github/workflows/validate.yml"].replace(" - run: npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line", " - run: npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line || true") },
137
+ expect: ".github/workflows/validate.yml: consumer-conformance: missing npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line",
138
+ },
139
+ {
140
+ name: "consumer_browser_command_split_failure_ignored",
141
+ mutate: { ".github/workflows/validate.yml": files[".github/workflows/validate.yml"].replace(" - run: npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line", " - run: |\n npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line \\\n || true") },
142
+ expect: ".github/workflows/validate.yml: consumer-conformance: missing npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line",
143
+ },
144
+ {
145
+ name: "consumer_browser_command_folded_failure_ignored",
146
+ mutate: { ".github/workflows/validate.yml": files[".github/workflows/validate.yml"].replace(" - run: npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line", " - run: >-\n npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line\n || true") },
147
+ expect: ".github/workflows/validate.yml: consumer-conformance: missing npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line",
148
+ },
149
+ {
150
+ name: "consumer_browser_command_compound_false_step",
151
+ mutate: { ".github/workflows/validate.yml": files[".github/workflows/validate.yml"].replace(" - run: npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line", " - if: ${{ false && true }}\n run: npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line") },
152
+ expect: ".github/workflows/validate.yml: consumer-conformance: required command steps must be unconditional",
153
+ },
154
+ {
155
+ name: "consumer_browser_job_compound_false",
156
+ mutate: { ".github/workflows/validate.yml": files[".github/workflows/validate.yml"].replace(" consumer-conformance:\n", " consumer-conformance:\n if: ${{ false && true }}\n") },
157
+ expect: ".github/workflows/validate.yml: consumer-conformance job must be unconditional",
158
+ },
159
+ {
160
+ name: "consumer_browser_command_quoted_disabled_step",
161
+ mutate: { ".github/workflows/validate.yml": files[".github/workflows/validate.yml"].replace(" - run: npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line", " - name: Disabled browser command\n \"if\": false # disabled\n run: npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line") },
162
+ expect: ".github/workflows/validate.yml: consumer-conformance: missing npx playwright test tests/consumer-conformance.spec.mjs --project=chromium --reporter=line",
163
+ },
164
+ {
165
+ name: "consumer_browser_job_disabled",
166
+ mutate: { ".github/workflows/validate.yml": files[".github/workflows/validate.yml"].replace(" consumer-conformance:\n", " consumer-conformance:\n if: false\n") },
167
+ expect: ".github/workflows/validate.yml: consumer-conformance job must be enabled",
168
+ },
169
+ {
170
+ name: "page_lifecycle_command_commented_out",
171
+ mutate: { ".github/workflows/validate.yml": files[".github/workflows/validate.yml"].replace(" - run: node scripts/finalize-page-evidence.mjs --json", " - run: |\n # node scripts/finalize-page-evidence.mjs --json\n true") },
172
+ expect: ".github/workflows/validate.yml: consumer-page-evidence: missing node scripts/finalize-page-evidence.mjs",
173
+ },
174
+ { name: "page_capture_became_blocking", mutate: { ".github/workflows/validate.yml": files[".github/workflows/validate.yml"].replace(" continue-on-error: true\n env:\n CONSUMER_CONFORMANCE_CAPTURE_DIR", " env:\n CONSUMER_CONFORMANCE_CAPTURE_DIR") }, expect: ".github/workflows/validate.yml: consumer-page-evidence must be nonblocking" },
175
+ { name: "paraphrased_governance_link_label", mutate: { "README.md": files["README.md"].replace("[Governance, Lifecycle, And Docs-As-Code]", "[Governance reference]") }, expectWarning: "README.md: recommended link label missing [Governance, Lifecycle, And Docs-As-Code](GOVERNANCE.md)" },
176
+ { name: "missing_motion_codeowner", mutate: { ".github/CODEOWNERS": files[".github/CODEOWNERS"].replace("/motion/ @changeroa\n", "") }, expect: ".github/CODEOWNERS: missing /motion/ @changeroa" },
177
+ { name: "missing_game_ui_codeowner", mutate: { ".github/CODEOWNERS": files[".github/CODEOWNERS"].replace("/game-ui/ @changeroa\n", "") }, expect: ".github/CODEOWNERS: missing /game-ui/ @changeroa" },
178
+ { name: "missing_consumer_reference_codeowner", mutate: { ".github/CODEOWNERS": files[".github/CODEOWNERS"].replace("/consumer-reference/ @changeroa\n", "") }, expect: ".github/CODEOWNERS: missing /consumer-reference/ @changeroa" },
179
+ { name: "missing_baseline_codeowner", mutate: { ".github/CODEOWNERS": files[".github/CODEOWNERS"].replace("/consumer-reference/baselines/ @changeroa\n", "") }, expect: ".github/CODEOWNERS: missing /consumer-reference/baselines/ @changeroa" },
180
+ { name: "missing_promotion_codeowner", mutate: { ".github/CODEOWNERS": files[".github/CODEOWNERS"].replace("/consumer-reference/policies/ @changeroa\n", "") }, expect: ".github/CODEOWNERS: missing /consumer-reference/policies/ @changeroa" },
181
+ { name: "missing_promotion_ci_wiring", mutate: { ".github/workflows/validate.yml": files[".github/workflows/validate.yml"].replace("node scripts/test-validate-promotion-rfc.mjs --json\n", "") }, expect: ".github/workflows/validate.yml: missing node scripts/test-validate-promotion-rfc.mjs --json" },
182
+ { name: "missing_stable_count_boundary", mutate: { "GOVERNANCE.md": files["GOVERNANCE.md"].replace("Shared stable has no numeric adoption threshold.", "Stable uses an adoption threshold.") }, expect: "GOVERNANCE.md: missing Shared stable has no numeric adoption threshold" },
183
+ { name: "fake_promotion_policy_claim", mutate: { "consumer-reference/policies/shared-experimental.json": files["consumer-reference/policies/shared-experimental.json"].replace('"promotion_occurred": false', '"promotion_occurred": true') }, expect: 'consumer-reference/policies/shared-experimental.json: missing "promotion_occurred": false' },
184
+ { name: "missing_domain_family", mutate: { "GOVERNANCE.md": files["GOVERNANCE.md"].replace("| Motion domain guidance |", "| Motion reference notes |") }, expect: "GOVERNANCE.md: missing Motion domain guidance" },
185
+ { name: "missing_domain_ci_wiring", mutate: { ".github/workflows/validate.yml": files[".github/workflows/validate.yml"].replace("node scripts/validate-domains.mjs --json\n", "") }, expect: ".github/workflows/validate.yml: missing node scripts/validate-domains.mjs --json" },
186
+ { name: "missing_domain_evidence_coverage", mutate: { "quality/evidence/executable-evidence.md": files["quality/evidence/executable-evidence.md"].replace("Domain metadata, immutable provenance, scope boundaries, and root-route fixtures must fail.", "Domain fixtures must fail.") }, expect: "quality/evidence/executable-evidence.md: missing Domain metadata, immutable provenance, scope boundaries, and root-route fixtures must fail." },
187
+ { name: "missing_sentinel_ci_wiring", mutate: { ".github/workflows/validate.yml": files[".github/workflows/validate.yml"].replaceAll("node scripts/test-consumer-reference-sentinel.mjs", "") }, expect: ".github/workflows/validate.yml: missing node scripts/test-consumer-reference-sentinel.mjs" },
188
+ { name: "missing_component_source_contract_ci", mutate: { ".github/workflows/validate.yml": files[".github/workflows/validate.yml"].replace("node scripts/test-component-state-source-contract.mjs", "") }, expect: ".github/workflows/validate.yml: missing node scripts/test-component-state-source-contract.mjs" },
189
+ { name: "missing_visual_schema_ci", mutate: { ".github/workflows/validate.yml": files[".github/workflows/validate.yml"].replace("consumer-reference/schema/visual-evidence.schema.json", "") }, expect: ".github/workflows/validate.yml: missing consumer-reference/schema/visual-evidence.schema.json" },
190
+ ...componentStateWorkflowCases(files[".github/workflows/validate.yml"]),
191
+ { name: "missing_sentinel_evidence_coverage", mutate: { "quality/evidence/executable-evidence.md": files["quality/evidence/executable-evidence.md"].replace("The proposed Chromium sentinel preserves canonical card-grid geometry and truth-derived calibration evidence.", "Chromium evidence exists.") }, expect: "quality/evidence/executable-evidence.md: missing The proposed Chromium sentinel preserves canonical card-grid geometry and truth-derived calibration evidence." },
192
+ { name: "missing_component_state_evidence_coverage", mutate: { "quality/evidence/executable-evidence.md": files["quality/evidence/executable-evidence.md"].replace("Governed-local button states retain source-bound visual, DOM, and accessibility-tree evidence across both example profiles.", "Component evidence exists.") }, expect: "quality/evidence/executable-evidence.md: missing Governed-local button states retain source-bound visual, DOM, and accessibility-tree evidence across both example profiles." },
193
+ {
194
+ name: "missing_scoped_checkout_sha_trust",
195
+ mutate: {
196
+ ".github/workflows/validate.yml": files[".github/workflows/validate.yml"].replace(
197
+ "checkout_sha=\"$(git -c safe.directory=\"$GITHUB_WORKSPACE\" rev-parse HEAD)\"",
198
+ "checkout_sha=\"$(git rev-parse HEAD)\"",
199
+ ),
200
+ },
201
+ expect: ".github/workflows/validate.yml: missing checkout_sha=\"$(git -c safe.directory=\"$GITHUB_WORKSPACE\" rev-parse HEAD)\"",
202
+ },
203
+ {
204
+ name: "reject_broad_checkout_sha_trust",
205
+ mutate: {
206
+ ".github/workflows/validate.yml": files[".github/workflows/validate.yml"].replace(
207
+ "checkout_sha=\"$(git -c safe.directory=\"$GITHUB_WORKSPACE\" rev-parse HEAD)\"",
208
+ "checkout_sha=\"$(git -c safe.directory='*' rev-parse HEAD)\"",
209
+ ),
210
+ },
211
+ expect: ".github/workflows/validate.yml: broad Git safe.directory wildcard is forbidden",
212
+ },
213
+ {
214
+ name: "missing_canonical_repository_wiring",
215
+ mutate: { ".github/workflows/validate.yml": files[".github/workflows/validate.yml"].replace("--repository \"changeroa/StyleGallery\" \\", "--repository \"$GITHUB_REPOSITORY\" \\") },
216
+ expect: ".github/workflows/validate.yml: missing --repository \"changeroa/StyleGallery\" \\",
217
+ },
218
+ {
219
+ name: "missing_execution_repository_wiring",
220
+ mutate: { ".github/workflows/validate.yml": files[".github/workflows/validate.yml"].replace("--execution-repository \"$GITHUB_REPOSITORY\" \\\n", "") },
221
+ expect: ".github/workflows/validate.yml: missing --execution-repository \"$GITHUB_REPOSITORY\" \\",
222
+ },
223
+ {
224
+ name: "workflow_metadata_repository_mismatch",
225
+ mutate: { ".github/workflows/validate.yml": files[".github/workflows/validate.yml"].replace("\"changeroa/StyleGallery\" \"$GITHUB_REPOSITORY\" \"$GITHUB_RUN_ID\"", "\"$GITHUB_REPOSITORY\" \"changeroa/StyleGallery\" \"$GITHUB_RUN_ID\"") },
226
+ expect: ".github/workflows/validate.yml: missing \"changeroa/StyleGallery\" \"$GITHUB_REPOSITORY\" \"$GITHUB_RUN_ID\"",
227
+ },
228
+ ...governanceMatrixCases(files["GOVERNANCE.md"]),
229
+ ...workflowSafetyCases(files[".github/workflows/validate.yml"]),
230
+ { name: "success_path", expect: null },
231
+ ];
232
+
233
+ for (const [pathIndex, relative] of ["consumer-reference/contract.md", "quality/evidence/executable-evidence.md", "GOVERNANCE.md"].entries()) {
234
+ for (const [clauseIndex, clause] of sentinelProvenanceClauses.entries()) {
235
+ cases.splice(cases.length - 1, 0,
236
+ { name: `provenance_clause_deleted_${pathIndex}_${clauseIndex}`, mutate: { [relative]: files[relative].replace(clause, "") }, expect: `${relative}: missing ${clause}` },
237
+ { name: `provenance_clause_misworded_${pathIndex}_${clauseIndex}`, mutate: { [relative]: files[relative].replace(clause, `Misworded ${clause.slice(1)}`) }, expect: `${relative}: missing ${clause}` },
238
+ );
239
+ }
240
+ }
241
+
242
+ function writeFixture(testCase) {
243
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), `layout-gallery-governance-${testCase.name}-`));
244
+ const omitted = new Set(testCase.omit ?? []);
245
+ const entries = { ...files, ...(testCase.mutate ?? {}) };
246
+ for (const [relative, content] of Object.entries(entries)) {
247
+ if (omitted.has(relative)) continue;
248
+ const target = path.join(dir, relative);
249
+ fs.mkdirSync(path.dirname(target), { recursive: true });
250
+ fs.writeFileSync(target, content);
251
+ }
252
+ return dir;
253
+ }
254
+
255
+ function runCase(testCase) {
256
+ const dir = writeFixture(testCase);
257
+ const result = spawnSync(process.execPath, [validator, "--json"], {
258
+ cwd: dir,
259
+ encoding: "utf8",
260
+ });
261
+ fs.rmSync(dir, { force: true, recursive: true });
262
+ const output = JSON.parse(result.stdout);
263
+ const passed = testCase.expectWarning
264
+ ? output.ok && output.warnings?.includes(testCase.expectWarning)
265
+ : testCase.expect
266
+ ? !output.ok && output.failures.includes(testCase.expect)
267
+ : output.ok;
268
+ return {
269
+ actual: output,
270
+ expected: testCase.expectWarning ?? testCase.expect ?? "ok:true",
271
+ name: testCase.name,
272
+ ok: passed,
273
+ };
274
+ }
275
+
276
+ const results = cases.map(runCase);
277
+ const adapterPipeCheck = spawnSync("sh", ["-c", '"$NODE_BIN" "$ADAPTER_HARNESS" --json | "$NODE_BIN" -e "$ADAPTER_PIPE_PARSER"'], {
278
+ cwd: root, encoding: "utf8", env: { ...process.env, ADAPTER_HARNESS: adapterHarness, ADAPTER_PIPE_PARSER: adapterPipeParser, NODE_BIN: process.execPath },
279
+ });
280
+ results.push({
281
+ actual: { status: adapterPipeCheck.status, stdout: adapterPipeCheck.stdout.trim() },
282
+ expected: "complete 42-result JSON report through a pipe",
283
+ name: "adapter_json_pipe_complete",
284
+ ok: adapterPipeCheck.status === 0 && adapterPipeCheck.stdout.trim() === "42",
285
+ });
286
+ const report = {
287
+ ok: results.every((result) => result.ok),
288
+ results,
289
+ };
290
+
291
+ console.log(JSON.stringify(report, null, 2));
292
+ process.exitCode = report.ok ? 0 : 1;
@@ -0,0 +1,262 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from "node:fs";
4
+ import os from "node:os";
5
+ import path from "node:path";
6
+ import { spawnSync } from "node:child_process";
7
+ import { fileURLToPath } from "node:url";
8
+
9
+ const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
10
+ const validator = path.join(root, "scripts", "validate-ia.mjs");
11
+ const governedProfileRoutes = [
12
+ ["Editorial profile", "editorial/profile.json"],
13
+ ["Editorial state matrix", "editorial/generated/state-matrix.md"],
14
+ ["Editorial keyboard matrix", "editorial/generated/keyboard-matrix.md"],
15
+ ["Editorial evidence coverage", "editorial/generated/evidence-coverage.md"],
16
+ ["Terminal profile", "terminal/profile.json"],
17
+ ["Terminal state matrix", "terminal/generated/state-matrix.md"],
18
+ ["Terminal keyboard matrix", "terminal/generated/keyboard-matrix.md"],
19
+ ["Terminal evidence coverage", "terminal/generated/evidence-coverage.md"],
20
+ ];
21
+
22
+ const baseFiles = {
23
+ "README.md": [
24
+ "# layout-gallery",
25
+ "",
26
+ "Primary role: repository guide.",
27
+ "",
28
+ "## Repository Entry Roles",
29
+ "",
30
+ "| Entry | Primary role |",
31
+ "| --- | --- |",
32
+ "| [README](README.md) | Repository guide |",
33
+ "| [Layout](layout/index.md) | Layout domain |",
34
+ "| [Motion](motion/index.md) | Motion domain |",
35
+ "| [Design Engineering](design-engineering/index.md) | Design Engineering domain |",
36
+ "| [Platform Guides](platform-guides/index.md) | Platform Guides domain |",
37
+ "| [Consumer Reference](consumer-reference/index.md) | Shared infrastructure contract |",
38
+ "| [Consumer Migration Readiness](design-engineering/consumer-migration-readiness.md) | Migration method |",
39
+ "",
40
+ "## Task Routes",
41
+ "",
42
+ "| Task | Primary route |",
43
+ "| --- | --- |",
44
+ "| `plan a layout` | [Guide](GUIDE.md) |",
45
+ "| `make a homepage` | [Homepage](recipes/homepage.md) |",
46
+ "| `choose a primitive` | [Catalog](CATALOG.md) |",
47
+ "| `review quality` | [Quality](quality/index.md) |",
48
+ "| `check links` | [Quality](quality/index.md) |",
49
+ "| `write a recipe` | [Recipes](recipes/index.md) |",
50
+ "| `inspect pattern categories` | [Patterns](patterns/index.md) |",
51
+ "| `fill a brief` | [Brief](guides/layout-brief.md) |",
52
+ "| `record evidence` | [Evidence](quality/evidence/index.md) |",
53
+ "| `run findability QA` | [Findability](quality/index.md) |",
54
+ "",
55
+ "## Link Policy",
56
+ "",
57
+ "- Navigation links move a reader to the next decision point.",
58
+ "- Citation links identify source lineage or evidence boundaries.",
59
+ "- Dependency links identify generated, validation, or composition relationships.",
60
+ "",
61
+ ].join("\n"),
62
+ "index.md": [
63
+ "# Bundle",
64
+ "",
65
+ "Primary role: OKF bundle map.",
66
+ "",
67
+ "- [Layout](layout/index.md)",
68
+ "- [Motion](motion/index.md)",
69
+ "- [Design Engineering](design-engineering/index.md)",
70
+ "- [Platform Guides](platform-guides/index.md)",
71
+ "- [Consumer reference](consumer-reference/index.md)",
72
+ "- [Consumer migration readiness](design-engineering/consumer-migration-readiness.md)",
73
+ "",
74
+ ].join("\n"),
75
+ "GUIDE.md": "# Guide\n\nPrimary role: planning workflow.\n",
76
+ "CATALOG.md": "# Catalog\n\nPrimary role: pattern lookup.\n",
77
+ "patterns/index.md": "# Patterns\n",
78
+ "patterns/stacking/index.md": "# Stacking\n",
79
+ "patterns/stacking/stack.md": leaf("Stack", "index.md", "../../recipes/index.md"),
80
+ "recipes/index.md": "# Recipes\n",
81
+ "recipes/homepage.md": leaf("Homepage", "index.md", "../quality/index.md"),
82
+ "quality/index.md": "# Quality\n\n- [Consumer migration evidence gate](gates/consumer-migration-evidence.md)\n\n## Tree-Test Findability QA\n",
83
+ "quality/gates/index.md": "# Gates\n\n- [Consumer migration evidence gate](consumer-migration-evidence.md)\n",
84
+ "quality/gates/layout.md": leaf("Layout", "index.md", "../evidence/index.md"),
85
+ "quality/gates/consumer-migration-evidence.md": leaf("Consumer Migration Evidence Gate", "index.md", "../evidence/consumer-migration.md"),
86
+ "quality/evidence/index.md": "# Evidence\n\n- [Consumer migration evidence](consumer-migration.md)\n",
87
+ "quality/evidence/consumer-migration.md": leaf("Consumer Migration Evidence", "index.md", "../../design-engineering/consumer-migration-readiness.md"),
88
+ "layout/index.md": "# Layout\n\n- [Catalog](../CATALOG.md)\n",
89
+ "motion/index.md": "# Motion\n\n- [Review](review.md)\n",
90
+ "motion/review.md": leaf("Motion review", "index.md", "../design-engineering/index.md"),
91
+ "design-engineering/index.md": "# Design Engineering\n\n- [Craft](craft.md)\n- [Consumer Migration Readiness](consumer-migration-readiness.md)\n- [Reference Profiles](reference-profiles/index.md)\n",
92
+ "design-engineering/craft.md": leaf("Craft", "index.md", "../platform-guides/index.md"),
93
+ "design-engineering/consumer-migration-readiness.md": leaf("Consumer Migration Readiness", "index.md", "../quality/gates/consumer-migration-evidence.md"),
94
+ "design-engineering/reference-profiles/index.md": "# Reference Profiles\n\n- [Governed Local Profiles](governed-local/index.md)\n- [External Adaptation](external-adaptation/index.md)\n\nParent: [Design Engineering](../index.md).\nNext: [Governed Local Profiles](governed-local/index.md).\n",
95
+ "design-engineering/reference-profiles/governed-local/index.md": [
96
+ "# Governed Local Profiles",
97
+ "",
98
+ ...governedProfileRoutes.map(([label, target]) => `- [${label}](${target})`),
99
+ "",
100
+ "Parent: [Reference Profiles](../index.md).",
101
+ "Next: [External Adaptation](../external-adaptation/index.md).",
102
+ "",
103
+ ].join("\n"),
104
+ "design-engineering/reference-profiles/external-adaptation/index.md": "# External Adaptation\n\nParent: [Reference Profiles](../index.md).\nNext: [Platform Guides](../../../platform-guides/index.md).\n",
105
+ "platform-guides/index.md": "# Platform Guides\n\n- [Apple](apple.md)\n",
106
+ "platform-guides/apple.md": leaf("Apple", "index.md", "../layout/index.md"),
107
+ "consumer-reference/index.md": "# Consumer Reference\n\n- [Contract](contract.md)\n- [Consumer Migration Readiness](../design-engineering/consumer-migration-readiness.md)\n",
108
+ "consumer-reference/contract.md": leaf("Consumer Reference Contract", "index.md", "../quality/index.md"),
109
+ };
110
+
111
+ const cases = [
112
+ {
113
+ name: "missing_leaf_parent",
114
+ mutate: {
115
+ "patterns/stacking/stack.md": "# Stack\n\nNext: [Recipes](../../recipes/index.md)\n",
116
+ },
117
+ expect: "patterns/stacking/stack.md: missing Parent navigation link",
118
+ },
119
+ {
120
+ name: "missing_leaf_next",
121
+ mutate: {
122
+ "patterns/stacking/stack.md": "# Stack\n\nParent: [Stacking](index.md)\n",
123
+ },
124
+ expect: "patterns/stacking/stack.md: missing Next navigation link",
125
+ },
126
+ {
127
+ name: "missing_task_routes",
128
+ mutate: {
129
+ "README.md": "# layout-gallery\n\nPrimary role: repository guide.\n\n## Repository Entry Roles\n",
130
+ },
131
+ expect: "README.md: missing ## Task Routes",
132
+ },
133
+ {
134
+ name: "missing_link_policy",
135
+ mutate: {
136
+ "README.md": baseFiles["README.md"].replace(/\n## Link Policy\n[\s\S]*$/, "\n"),
137
+ },
138
+ expect: "README.md: missing ## Link Policy",
139
+ },
140
+ {
141
+ name: "missing_motion_readme_route",
142
+ mutate: {
143
+ "README.md": baseFiles["README.md"].replace("| [Motion](motion/index.md) | Motion domain |\n", ""),
144
+ },
145
+ expect: "README.md: missing [Motion](motion/index.md)",
146
+ },
147
+ {
148
+ name: "motion_readme_route_only_in_fence",
149
+ mutate: {
150
+ "README.md": baseFiles["README.md"].replace("| [Motion](motion/index.md) | Motion domain |\n", "```md\n[Motion](motion/index.md)\n```\n"),
151
+ },
152
+ expect: "README.md: missing [Motion](motion/index.md)",
153
+ },
154
+ {
155
+ name: "missing_design_engineering_index_route",
156
+ mutate: {
157
+ "index.md": baseFiles["index.md"].replace("- [Design Engineering](design-engineering/index.md)\n", ""),
158
+ },
159
+ expect: "index.md: missing [Design Engineering](design-engineering/index.md)",
160
+ },
161
+ {
162
+ name: "missing_reference_profile_route",
163
+ mutate: {
164
+ "design-engineering/index.md": "# Design Engineering\n\n- [Craft](craft.md)\n",
165
+ },
166
+ expect: "design-engineering/index.md: missing [Reference Profiles](reference-profiles/index.md)",
167
+ },
168
+ ...governedProfileRoutes.map(([label, target]) => ({
169
+ name: `missing_governed_route_${target.replace(/[^a-z]+/g, "_").replace(/^_|_$/g, "")}`,
170
+ mutate: {
171
+ "design-engineering/reference-profiles/governed-local/index.md": baseFiles["design-engineering/reference-profiles/governed-local/index.md"].replace(`- [${label}](${target})\n`, ""),
172
+ },
173
+ expect: `design-engineering/reference-profiles/governed-local/index.md: missing [${label}](${target})`,
174
+ })),
175
+ {
176
+ name: "missing_external_adaptation_parent",
177
+ mutate: {
178
+ "design-engineering/reference-profiles/external-adaptation/index.md": "# External Adaptation\n\nNext: [Platform Guides](../../../platform-guides/index.md).\n",
179
+ },
180
+ expect: "design-engineering/reference-profiles/external-adaptation/index.md: missing Parent navigation link",
181
+ },
182
+ {
183
+ name: "missing_consumer_reference_route",
184
+ mutate: {
185
+ "index.md": baseFiles["index.md"].replace("- [Consumer reference](consumer-reference/index.md)\n", ""),
186
+ },
187
+ expect: "index.md: missing [Consumer reference](consumer-reference/index.md)",
188
+ },
189
+ {
190
+ name: "missing_consumer_migration_root_route",
191
+ mutate: {
192
+ "README.md": baseFiles["README.md"].replace("| [Consumer Migration Readiness](design-engineering/consumer-migration-readiness.md) | Migration method |\n", ""),
193
+ },
194
+ expect: "README.md: missing [Consumer Migration Readiness](design-engineering/consumer-migration-readiness.md)",
195
+ },
196
+ {
197
+ name: "missing_consumer_migration_gate_route",
198
+ mutate: {
199
+ "quality/index.md": "# Quality\n\n## Tree-Test Findability QA\n",
200
+ },
201
+ expect: "quality/index.md: missing [Consumer migration evidence gate](gates/consumer-migration-evidence.md)",
202
+ },
203
+ {
204
+ name: "missing_domain_leaf_parent",
205
+ mutate: {
206
+ "motion/review.md": "# Motion review\n\nNext: [Next](../design-engineering/index.md)\n",
207
+ },
208
+ expect: "motion/review.md: missing Parent navigation link",
209
+ },
210
+ {
211
+ name: "missing_domain_leaf_next",
212
+ mutate: {
213
+ "motion/review.md": "# Motion review\n\nParent: [Motion](index.md)\n",
214
+ },
215
+ expect: "motion/review.md: missing Next navigation link",
216
+ },
217
+ {
218
+ name: "success_path",
219
+ expect: null,
220
+ },
221
+ ];
222
+
223
+ function leaf(title, parent, next) {
224
+ return `# ${title}\n\n## IA Navigation\n\nParent: [Parent](${parent}).\nNext: [Next](${next}).\n`;
225
+ }
226
+
227
+ function writeFixture(testCase) {
228
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), `layout-gallery-ia-${testCase.name}-`));
229
+ const entries = { ...baseFiles, ...(testCase.mutate ?? {}) };
230
+ for (const [relative, content] of Object.entries(entries)) {
231
+ const target = path.join(dir, relative);
232
+ fs.mkdirSync(path.dirname(target), { recursive: true });
233
+ fs.writeFileSync(target, content);
234
+ }
235
+ return dir;
236
+ }
237
+
238
+ function runCase(testCase) {
239
+ const dir = writeFixture(testCase);
240
+ const result = spawnSync(process.execPath, [validator, "--json"], {
241
+ cwd: dir,
242
+ encoding: "utf8",
243
+ });
244
+ fs.rmSync(dir, { force: true, recursive: true });
245
+ const output = JSON.parse(result.stdout);
246
+ const passed = testCase.expect ? !output.ok && output.failures.includes(testCase.expect) : output.ok;
247
+ return {
248
+ name: testCase.name,
249
+ ok: passed,
250
+ expected: testCase.expect ?? "ok:true",
251
+ actual: output,
252
+ };
253
+ }
254
+
255
+ const results = cases.map(runCase);
256
+ const report = {
257
+ ok: results.every((result) => result.ok),
258
+ results,
259
+ };
260
+
261
+ console.log(JSON.stringify(report, null, 2));
262
+ process.exitCode = report.ok ? 0 : 1;
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env node
2
+
3
+ import fs from "node:fs";
4
+ import os from "node:os";
5
+ import path from "node:path";
6
+ import { spawnSync } from "node:child_process";
7
+ import { fileURLToPath } from "node:url";
8
+
9
+ const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
10
+ const validator = path.join(root, "scripts", "validate-okf.mjs");
11
+
12
+ const cases = [
13
+ {
14
+ name: "missing_frontmatter",
15
+ files: { "index.md": "# Bundle\n\n* [Bad](bad.md) - Bad\n", "log.md": "# Log\n\n## 2026-07-02\n* Init.\n", "bad.md": "# Bad\n" },
16
+ expect: "missing OKF frontmatter",
17
+ },
18
+ {
19
+ name: "missing_type",
20
+ files: { "index.md": "# Bundle\n\n* [Bad](bad.md) - Bad\n", "log.md": "# Log\n\n## 2026-07-02\n* Init.\n", "bad.md": "---\ntitle: Bad\n---\n# Bad\n" },
21
+ expect: "missing required OKF type",
22
+ },
23
+ {
24
+ name: "index_frontmatter",
25
+ files: { "index.md": "---\ntype: Index\n---\n# Bundle\n\n* [Good](good.md) - Good\n", "log.md": "# Log\n\n## 2026-07-02\n* Init.\n", "good.md": concept("Concept", "Good") },
26
+ expect: "index.md must not contain concept frontmatter",
27
+ },
28
+ {
29
+ name: "malformed_log_date",
30
+ files: { "index.md": "# Bundle\n\n* [Good](good.md) - Good\n", "log.md": "# Log\n\n## July 2, 2026\n* Init.\n", "good.md": concept("Concept", "Good") },
31
+ expect: "log.md date heading must be YYYY-MM-DD",
32
+ },
33
+ {
34
+ name: "success_path",
35
+ files: { "index.md": "---\nokf_version: \"0.1\"\n---\n# Bundle\n\n* [Good](good.md) - Good\n", "log.md": "# Log\n\n## 2026-07-02\n* Init.\n", "good.md": concept("Concept", "Good") },
36
+ expect: null,
37
+ },
38
+ ];
39
+
40
+ function concept(type, title) {
41
+ return `---\ntype: ${type}\ntitle: ${title}\ndescription: Valid OKF concept.\n---\n# ${title}\n`;
42
+ }
43
+
44
+ function runCase(testCase) {
45
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), `layout-gallery-okf-${testCase.name}-`));
46
+ for (const [relative, content] of Object.entries(testCase.files)) {
47
+ const target = path.join(dir, relative);
48
+ fs.mkdirSync(path.dirname(target), { recursive: true });
49
+ fs.writeFileSync(target, content);
50
+ }
51
+ const result = spawnSync(process.execPath, [validator, "--json"], {
52
+ cwd: dir,
53
+ encoding: "utf8",
54
+ });
55
+ fs.rmSync(dir, { force: true, recursive: true });
56
+ const output = JSON.parse(result.stdout);
57
+ const passed = testCase.expect ? !output.ok && output.failures.some((failure) => failure.includes(testCase.expect)) : output.ok;
58
+ return {
59
+ name: testCase.name,
60
+ ok: passed,
61
+ expected: testCase.expect ?? "ok:true",
62
+ actual: output,
63
+ };
64
+ }
65
+
66
+ const results = cases.map(runCase);
67
+ const report = {
68
+ ok: results.every((result) => result.ok),
69
+ results,
70
+ };
71
+
72
+ console.log(JSON.stringify(report, null, 2));
73
+ process.exitCode = report.ok ? 0 : 1;