@legionworks/facet 1.9.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 (327) hide show
  1. package/LICENSE-APACHE +202 -0
  2. package/LICENSE-MIT +23 -0
  3. package/README.md +158 -0
  4. package/dist/gallery/chunk-4g8rem85.css +656 -0
  5. package/dist/gallery/chunk-c6s9k9ty.js +5970 -0
  6. package/dist/gallery/frame/artifact.css +8424 -0
  7. package/dist/gallery/frame/chunks/abnfDiagram-N423BO3Z-jj74szbm.js +155 -0
  8. package/dist/gallery/frame/chunks/architecture-TIHT7OUA-cvdjn7dt.js +10 -0
  9. package/dist/gallery/frame/chunks/architectureDiagram-T3A2C74G-n4z77eg6.js +8675 -0
  10. package/dist/gallery/frame/chunks/blockDiagram-VBNYF7ZC-7xsqzrd1.js +3529 -0
  11. package/dist/gallery/frame/chunks/c4Diagram-5PPSVZJV-z2zjs7wx.js +2413 -0
  12. package/dist/gallery/frame/chunks/classDiagram-JCYQIIEL-ve8rngqp.js +47 -0
  13. package/dist/gallery/frame/chunks/classDiagram-v2-OCEON4UE-8cfaxb8z.js +47 -0
  14. package/dist/gallery/frame/chunks/cose-bilkent-JH36ORCC-sn92qexx.js +4822 -0
  15. package/dist/gallery/frame/chunks/cynefin-VYW2F7L2-tqjv913d.js +10 -0
  16. package/dist/gallery/frame/chunks/cynefinDiagram-MW4NZA55-c1c0dj12.js +500 -0
  17. package/dist/gallery/frame/chunks/dagre-VZM6K2ZE-7tyg4yt2.js +476 -0
  18. package/dist/gallery/frame/chunks/diagram-7IWD3JNH-y4eng9sc.js +526 -0
  19. package/dist/gallery/frame/chunks/diagram-B4RE2ZJO-rn3p7j5h.js +673 -0
  20. package/dist/gallery/frame/chunks/diagram-LBJQPF4R-w4a2cm9q.js +255 -0
  21. package/dist/gallery/frame/chunks/diagram-Q27KOJAE-aqc2v7wy.js +575 -0
  22. package/dist/gallery/frame/chunks/diagram-UB23O5K3-xncy8nyd.js +355 -0
  23. package/dist/gallery/frame/chunks/ebnfDiagram-BXEA7PRR-acwgxz16.js +175 -0
  24. package/dist/gallery/frame/chunks/erDiagram-JOGREHBK-mzp5nswt.js +1332 -0
  25. package/dist/gallery/frame/chunks/eventmodeling-45OFAUF4-sg07qr0c.js +10 -0
  26. package/dist/gallery/frame/chunks/flowDiagram-UKHOOZJN-2e5ygs44.js +29 -0
  27. package/dist/gallery/frame/chunks/ganttDiagram-PKOTCBZU-p2hhh7hr.js +2620 -0
  28. package/dist/gallery/frame/chunks/gitGraph-TEB2WS4Q-j6kw0naa.js +10 -0
  29. package/dist/gallery/frame/chunks/gitGraphDiagram-DS77QQ5N-4z9z8wjm.js +1347 -0
  30. package/dist/gallery/frame/chunks/info-DKCQHKI2-mpt80jd3.js +10 -0
  31. package/dist/gallery/frame/chunks/infoDiagram-6WML65LV-5rqm3mgg.js +65 -0
  32. package/dist/gallery/frame/chunks/ishikawaDiagram-WSZJBQD7-b51z96jy.js +975 -0
  33. package/dist/gallery/frame/chunks/journeyDiagram-NVQOT4AX-9jbfp0pk.js +1272 -0
  34. package/dist/gallery/frame/chunks/kanban-definition-27J2QSJJ-4x0vx4se.js +1116 -0
  35. package/dist/gallery/frame/chunks/katex-xfgk95tv.js +14034 -0
  36. package/dist/gallery/frame/chunks/markdown-1s5vwkf2.js +9 -0
  37. package/dist/gallery/frame/chunks/markdown-2h6bwsms.js +3239 -0
  38. package/dist/gallery/frame/chunks/markdown-2x113yh8.js +107 -0
  39. package/dist/gallery/frame/chunks/markdown-30b7rwmp.js +1943 -0
  40. package/dist/gallery/frame/chunks/markdown-356bfj4g.js +2031 -0
  41. package/dist/gallery/frame/chunks/markdown-44n9ea69.js +2406 -0
  42. package/dist/gallery/frame/chunks/markdown-56enrf2r.js +39 -0
  43. package/dist/gallery/frame/chunks/markdown-5avymm8t.js +725 -0
  44. package/dist/gallery/frame/chunks/markdown-6r4svars.js +33 -0
  45. package/dist/gallery/frame/chunks/markdown-6zz8efx2.js +24 -0
  46. package/dist/gallery/frame/chunks/markdown-7jp6prnb.js +19 -0
  47. package/dist/gallery/frame/chunks/markdown-809k7q41.js +55 -0
  48. package/dist/gallery/frame/chunks/markdown-82xmzhzd.js +1076 -0
  49. package/dist/gallery/frame/chunks/markdown-92n37gd4.js +7627 -0
  50. package/dist/gallery/frame/chunks/markdown-ag2sssf8.js +36 -0
  51. package/dist/gallery/frame/chunks/markdown-b4s7ntq2.js +19 -0
  52. package/dist/gallery/frame/chunks/markdown-c9k0fvp1.js +100 -0
  53. package/dist/gallery/frame/chunks/markdown-ceefymn8.js +125 -0
  54. package/dist/gallery/frame/chunks/markdown-d1wfbs70.js +243 -0
  55. package/dist/gallery/frame/chunks/markdown-dy5sgjhc.js +11022 -0
  56. package/dist/gallery/frame/chunks/markdown-dz3z5w30.js +30868 -0
  57. package/dist/gallery/frame/chunks/markdown-eg6ngz7y.js +30340 -0
  58. package/dist/gallery/frame/chunks/markdown-ff5wvb43.js +1149 -0
  59. package/dist/gallery/frame/chunks/markdown-ffg06nfz.js +86 -0
  60. package/dist/gallery/frame/chunks/markdown-fvfncadf.js +472 -0
  61. package/dist/gallery/frame/chunks/markdown-gvyszqpv.js +19 -0
  62. package/dist/gallery/frame/chunks/markdown-gx1p0ew0.js +88 -0
  63. package/dist/gallery/frame/chunks/markdown-gxye5frz.js +65 -0
  64. package/dist/gallery/frame/chunks/markdown-h7pzv34e.js +105 -0
  65. package/dist/gallery/frame/chunks/markdown-hab789t9.js +47 -0
  66. package/dist/gallery/frame/chunks/markdown-hjp6sj8t.js +125 -0
  67. package/dist/gallery/frame/chunks/markdown-jka64qgp.js +1993 -0
  68. package/dist/gallery/frame/chunks/markdown-k8xkn8mw.js +56 -0
  69. package/dist/gallery/frame/chunks/markdown-m7frq8x8.js +112 -0
  70. package/dist/gallery/frame/chunks/markdown-p740v4qm.js +36 -0
  71. package/dist/gallery/frame/chunks/markdown-pxfeh231.js +57 -0
  72. package/dist/gallery/frame/chunks/markdown-pzgd8z3s.js +87 -0
  73. package/dist/gallery/frame/chunks/markdown-qx3cngz2.js +1673 -0
  74. package/dist/gallery/frame/chunks/markdown-rawhfvvc.js +85 -0
  75. package/dist/gallery/frame/chunks/markdown-rd8w0ng9.js +49 -0
  76. package/dist/gallery/frame/chunks/markdown-rm2yxfjj.js +2773 -0
  77. package/dist/gallery/frame/chunks/markdown-s1jatrnk.js +993 -0
  78. package/dist/gallery/frame/chunks/markdown-sgfg5vvq.js +59 -0
  79. package/dist/gallery/frame/chunks/markdown-t4ethv9d.js +409 -0
  80. package/dist/gallery/frame/chunks/markdown-tnmabqvz.js +36 -0
  81. package/dist/gallery/frame/chunks/markdown-tvdpppw8.js +5292 -0
  82. package/dist/gallery/frame/chunks/markdown-v0x27twr.js +22 -0
  83. package/dist/gallery/frame/chunks/markdown-v14td68x.js +36 -0
  84. package/dist/gallery/frame/chunks/markdown-w6sgd54z.js +36 -0
  85. package/dist/gallery/frame/chunks/markdown-xw8dsk8b.js +2125 -0
  86. package/dist/gallery/frame/chunks/markdown-y18mve73.js +85 -0
  87. package/dist/gallery/frame/chunks/markdown-yengsms5.js +427 -0
  88. package/dist/gallery/frame/chunks/markdown-z1wc0v0d.js +1826 -0
  89. package/dist/gallery/frame/chunks/markdown-zazx9h4n.js +329 -0
  90. package/dist/gallery/frame/chunks/mermaid-de7p4v0x.js +30 -0
  91. package/dist/gallery/frame/chunks/mindmap-definition-FAOFIHXS-ra44cbem.js +1216 -0
  92. package/dist/gallery/frame/chunks/packet-7NZHBO7P-xppm5913.js +10 -0
  93. package/dist/gallery/frame/chunks/pegDiagram-VL7TDLO6-a2a4wg03.js +163 -0
  94. package/dist/gallery/frame/chunks/pie-RZYD4A2V-hnbxk152.js +10 -0
  95. package/dist/gallery/frame/chunks/pieDiagram-7S7Q4E2Y-f1vxjtmx.js +311 -0
  96. package/dist/gallery/frame/chunks/quadrantDiagram-CIZ2JOQS-ywafa6kh.js +1390 -0
  97. package/dist/gallery/frame/chunks/radar-I7S5WNFK-ewqd27se.js +10 -0
  98. package/dist/gallery/frame/chunks/railroad-3IZDKUUU-5hy4bdx3.js +10 -0
  99. package/dist/gallery/frame/chunks/railroad-abnf-AHOZXSZD-bh5sxz0d.js +10 -0
  100. package/dist/gallery/frame/chunks/railroad-ebnf-EBAXGLYW-6b9c3zeh.js +10 -0
  101. package/dist/gallery/frame/chunks/railroad-peg-LSFZ7HO6-avc8v39s.js +10 -0
  102. package/dist/gallery/frame/chunks/railroadDiagram-AXF67PYL-qc61wax4.js +131 -0
  103. package/dist/gallery/frame/chunks/requirementDiagram-LRYGKXZP-9bs4786c.js +1295 -0
  104. package/dist/gallery/frame/chunks/sankeyDiagram-W5VNT64P-awt1em8b.js +1339 -0
  105. package/dist/gallery/frame/chunks/sequenceDiagram-SI44F4Z6-qaf9mz3t.js +4324 -0
  106. package/dist/gallery/frame/chunks/sizeCapture-X5ZJPWSS-9fq685xd.js +64 -0
  107. package/dist/gallery/frame/chunks/stateDiagram-OKZ733FA-vx7a7hh0.js +456 -0
  108. package/dist/gallery/frame/chunks/stateDiagram-v2-UEYNNEHI-x4m6ws5t.js +46 -0
  109. package/dist/gallery/frame/chunks/swimlanes-SLNWSIFB-e4mxm1gh.js +8287 -0
  110. package/dist/gallery/frame/chunks/swimlanesDiagram-ULZ7WXOC-0h93e2qq.js +42 -0
  111. package/dist/gallery/frame/chunks/timeline-definition-Z64GVDOM-wp0bhbzg.js +1549 -0
  112. package/dist/gallery/frame/chunks/treeView-QDETBFTQ-hcx7n0vt.js +10 -0
  113. package/dist/gallery/frame/chunks/treemap-6X3UGDF4-av02skdw.js +10 -0
  114. package/dist/gallery/frame/chunks/vennDiagram-T6HMQDX7-pmvk1p7n.js +2566 -0
  115. package/dist/gallery/frame/chunks/wardley-OPB4EBWU-njsp6e40.js +10 -0
  116. package/dist/gallery/frame/chunks/wardleyDiagram-T6FBY63Y-eggmnv4z.js +979 -0
  117. package/dist/gallery/frame/chunks/xychartDiagram-ELKLHX3M-q40tnpe5.js +1954 -0
  118. package/dist/gallery/frame/frame.css +183 -0
  119. package/dist/gallery/frame/runtime/chart.js +42744 -0
  120. package/dist/gallery/frame/runtime/html.js +14 -0
  121. package/dist/gallery/frame/runtime/markdown.js +1403 -0
  122. package/dist/gallery/frame/runtime/mermaid.js +32 -0
  123. package/dist/gallery/frame/runtime/svg.js +14 -0
  124. package/dist/gallery/frame/runtime/tsx.js +52 -0
  125. package/dist/gallery/index.html +104 -0
  126. package/docs/reference/cli.md +163 -0
  127. package/docs/reference/export.md +106 -0
  128. package/docs/reference/html.md +215 -0
  129. package/docs/reference/http.md +85 -0
  130. package/docs/reference/mcp.md +78 -0
  131. package/docs/reference/security.md +119 -0
  132. package/docs/reference/storage.md +93 -0
  133. package/docs/reference/tsx.md +101 -0
  134. package/docs/reference/validation.md +212 -0
  135. package/package.json +89 -0
  136. package/scripts/build-gallery.ts +127 -0
  137. package/scripts/launch-netns.sh +67 -0
  138. package/skills/facet/SKILL.md +100 -0
  139. package/src/cli/client.ts +311 -0
  140. package/src/cli/commands/create.ts +49 -0
  141. package/src/cli/commands/doctor.ts +249 -0
  142. package/src/cli/commands/export.ts +179 -0
  143. package/src/cli/commands/instantiate.ts +35 -0
  144. package/src/cli/commands/list.ts +49 -0
  145. package/src/cli/commands/open.ts +75 -0
  146. package/src/cli/commands/pin.ts +39 -0
  147. package/src/cli/commands/promote.ts +49 -0
  148. package/src/cli/commands/publish.ts +122 -0
  149. package/src/cli/commands/read-back.ts +56 -0
  150. package/src/cli/commands/status.ts +114 -0
  151. package/src/cli/commands/watch.ts +146 -0
  152. package/src/cli/main.ts +522 -0
  153. package/src/cli/output.ts +106 -0
  154. package/src/cli/parser.ts +376 -0
  155. package/src/cli/presenter.ts +212 -0
  156. package/src/cli/service-metadata.ts +134 -0
  157. package/src/cli/spawn-service.ts +326 -0
  158. package/src/css.d.ts +4 -0
  159. package/src/gallery-web/app.ts +1581 -0
  160. package/src/gallery-web/export-menu.ts +121 -0
  161. package/src/gallery-web/export.ts +112 -0
  162. package/src/gallery-web/favicon.ts +54 -0
  163. package/src/gallery-web/frame/entries/chart.ts +6 -0
  164. package/src/gallery-web/frame/entries/html.ts +6 -0
  165. package/src/gallery-web/frame/entries/markdown.ts +6 -0
  166. package/src/gallery-web/frame/entries/mermaid.ts +6 -0
  167. package/src/gallery-web/frame/entries/svg.ts +6 -0
  168. package/src/gallery-web/frame/entries/tsx.ts +6 -0
  169. package/src/gallery-web/frame/frame-payload.ts +91 -0
  170. package/src/gallery-web/frame/renderer-validation.ts +13 -0
  171. package/src/gallery-web/frame/renderers/chart.ts +182 -0
  172. package/src/gallery-web/frame/renderers/dompurify-shim.ts +112 -0
  173. package/src/gallery-web/frame/renderers/html.ts +48 -0
  174. package/src/gallery-web/frame/renderers/markdown.ts +81 -0
  175. package/src/gallery-web/frame/renderers/mermaid.ts +120 -0
  176. package/src/gallery-web/frame/renderers/registry.ts +260 -0
  177. package/src/gallery-web/frame/renderers/svg.ts +393 -0
  178. package/src/gallery-web/frame/renderers/tsx.ts +61 -0
  179. package/src/gallery-web/frame/runtime.ts +501 -0
  180. package/src/gallery-web/frame/styles/artifact.css +8424 -0
  181. package/src/gallery-web/frame/styles/frame.css +183 -0
  182. package/src/gallery-web/frame/styles/html-source.css +23 -0
  183. package/src/gallery-web/frame/view-box.ts +33 -0
  184. package/src/gallery-web/frame-html.ts +72 -0
  185. package/src/gallery-web/index.html +104 -0
  186. package/src/gallery-web/session.ts +107 -0
  187. package/src/gallery-web/sse-client.ts +212 -0
  188. package/src/gallery-web/styles/app.css +420 -0
  189. package/src/gallery-web/styles/tokens.css +112 -0
  190. package/src/gallery-web/styles/verdict.css +186 -0
  191. package/src/gallery-web/swap.ts +64 -0
  192. package/src/gallery-web/theme.ts +40 -0
  193. package/src/gallery-web/view-state.ts +93 -0
  194. package/src/harness-adapters/claude-code/README.md +10 -0
  195. package/src/harness-adapters/claude-code/facet.sh +4 -0
  196. package/src/harness-adapters/codex/README.md +10 -0
  197. package/src/harness-adapters/codex/facet.sh +4 -0
  198. package/src/harness-adapters/mcp/README.md +13 -0
  199. package/src/harness-adapters/mcp/cli-bridge.ts +216 -0
  200. package/src/harness-adapters/mcp/main.ts +15 -0
  201. package/src/harness-adapters/mcp/server.ts +164 -0
  202. package/src/harness-adapters/mcp/tool-schemas.ts +53 -0
  203. package/src/harness-adapters/opencode/README.md +10 -0
  204. package/src/harness-adapters/opencode/facet.sh +4 -0
  205. package/src/runtime/compiled-entrypoints.ts +69 -0
  206. package/src/service/dispatcher.ts +717 -0
  207. package/src/service/export.ts +218 -0
  208. package/src/service/http-utils.ts +55 -0
  209. package/src/service/lexical/expectations.ts +210 -0
  210. package/src/service/lifecycle/idle-controller.ts +125 -0
  211. package/src/service/lifecycle/orphan-cleanup.ts +128 -0
  212. package/src/service/lifecycle/process-lock.ts +235 -0
  213. package/src/service/main.ts +136 -0
  214. package/src/service/process.ts +240 -0
  215. package/src/service/router-guards.ts +239 -0
  216. package/src/service/router.ts +627 -0
  217. package/src/service/security/auth.ts +168 -0
  218. package/src/service/security/host-origin.ts +138 -0
  219. package/src/service/security/http-guards.ts +13 -0
  220. package/src/service/security/leases.ts +182 -0
  221. package/src/service/security/token-store.ts +138 -0
  222. package/src/service/server.ts +356 -0
  223. package/src/service/store/database.ts +61 -0
  224. package/src/service/store/evidence-retention.ts +234 -0
  225. package/src/service/store/migrations.ts +167 -0
  226. package/src/service/store/repository-lifecycle.ts +121 -0
  227. package/src/service/store/repository.ts +732 -0
  228. package/src/service/store/schema.ts +218 -0
  229. package/src/service/stored-verdict.ts +97 -0
  230. package/src/service/stream.ts +301 -0
  231. package/src/service/verdict-enrichment.ts +45 -0
  232. package/src/shared/build/frame-bundle-plugins.ts +61 -0
  233. package/src/shared/build-mode.ts +28 -0
  234. package/src/shared/config/evidence-read.ts +98 -0
  235. package/src/shared/config/limits.ts +56 -0
  236. package/src/shared/config/paths.ts +96 -0
  237. package/src/shared/contracts/artifact-types.ts +2 -0
  238. package/src/shared/contracts/artifact.ts +98 -0
  239. package/src/shared/contracts/commands/_shared.ts +59 -0
  240. package/src/shared/contracts/commands/guards.ts +86 -0
  241. package/src/shared/contracts/commands/index.ts +204 -0
  242. package/src/shared/contracts/commands/names.ts +35 -0
  243. package/src/shared/contracts/commands/requests.ts +149 -0
  244. package/src/shared/contracts/commands/results.ts +200 -0
  245. package/src/shared/contracts/envelope.ts +140 -0
  246. package/src/shared/contracts/events.ts +41 -0
  247. package/src/shared/contracts/observed-counts.ts +19 -0
  248. package/src/shared/contracts/renderers.ts +6 -0
  249. package/src/shared/contracts/validation.ts +296 -0
  250. package/src/shared/errors/facet-error.ts +127 -0
  251. package/src/shared/errors/store-error.ts +68 -0
  252. package/src/shared/evidence-image.ts +37 -0
  253. package/src/shared/export.ts +31 -0
  254. package/src/shared/html/policy.ts +108 -0
  255. package/src/shared/html/style-vocabulary.ts +352 -0
  256. package/src/shared/logging/logger.ts +108 -0
  257. package/src/shared/logging/redact.ts +49 -0
  258. package/src/shared/security/frozen-csp.ts +13 -0
  259. package/src/shared/storage-version.ts +2 -0
  260. package/src/shared/tsx/execution.ts +29 -0
  261. package/src/shared/tsx/import-policy.ts +94 -0
  262. package/src/shared/util/dir-permissions.ts +94 -0
  263. package/src/shared/util/mermaid-nodes.ts +230 -0
  264. package/src/shared/util/process.ts +67 -0
  265. package/src/shared/util/time.ts +21 -0
  266. package/src/shared/version.ts +3 -0
  267. package/src/validation/sandbox/limits.ts +41 -0
  268. package/src/validation/sandbox/netns.ts +177 -0
  269. package/src/validation/tier0/chart.ts +177 -0
  270. package/src/validation/tier0/dom-shim.ts +54 -0
  271. package/src/validation/tier0/html.ts +408 -0
  272. package/src/validation/tier0/markdown.ts +285 -0
  273. package/src/validation/tier0/mermaid.ts +98 -0
  274. package/src/validation/tier0/runner.ts +504 -0
  275. package/src/validation/tier0/svg.ts +321 -0
  276. package/src/validation/tier0/tsx/allowlist-resolver.ts +77 -0
  277. package/src/validation/tier0/tsx/ast-policy-capabilities.ts +238 -0
  278. package/src/validation/tier0/tsx/ast-policy-shared.ts +71 -0
  279. package/src/validation/tier0/tsx/ast-policy.ts +181 -0
  280. package/src/validation/tier0/tsx/compiler.ts +156 -0
  281. package/src/validation/tier0/worker-dispatch.ts +211 -0
  282. package/src/validation/tier0/worker-entry.ts +96 -0
  283. package/src/validation/tier0/worker-input.ts +75 -0
  284. package/src/validation/tier1/browser-process.ts +147 -0
  285. package/src/validation/tier1/cdp-pipe.ts +281 -0
  286. package/src/validation/tier1/entries/chart.ts +5 -0
  287. package/src/validation/tier1/entries/html.ts +6 -0
  288. package/src/validation/tier1/entries/markdown.ts +5 -0
  289. package/src/validation/tier1/entries/mermaid.ts +5 -0
  290. package/src/validation/tier1/entries/svg.ts +5 -0
  291. package/src/validation/tier1/entries/tsx.ts +5 -0
  292. package/src/validation/tier1/frame-target.ts +162 -0
  293. package/src/validation/tier1/harness-entry.ts +261 -0
  294. package/src/validation/tier1/harness.ts +215 -0
  295. package/src/validation/tier1/isolated-probe.ts +94 -0
  296. package/src/validation/tier1/launcher.ts +177 -0
  297. package/src/validation/tier1/limits.ts +80 -0
  298. package/src/validation/tier1/nonce.ts +17 -0
  299. package/src/validation/tier1/protocol-probe.ts +519 -0
  300. package/src/validation/tier1/runner.ts +1122 -0
  301. package/src/validation/tier1/verdict.ts +246 -0
  302. package/src/validation/tier1/webp.ts +69 -0
  303. package/templates/README.md +88 -0
  304. package/templates/bar-compare.vl.json +63 -0
  305. package/templates/capacity-report.tsx +102 -0
  306. package/templates/decision-record.md +24 -0
  307. package/templates/deployment-state.mmd +40 -0
  308. package/templates/exemplar.md +91 -0
  309. package/templates/facet-story.tsx +799 -0
  310. package/templates/fleet-dashboard.html +141 -0
  311. package/templates/html-release-ledger.html +91 -0
  312. package/templates/html-status-report.html +114 -0
  313. package/templates/incident-console.tsx +147 -0
  314. package/templates/legion-boundaries.mmd +23 -0
  315. package/templates/legion-flow.mmd +15 -0
  316. package/templates/legion-sequence.mmd +14 -0
  317. package/templates/legion-state.mmd +7 -0
  318. package/templates/metric-card.svg +29 -0
  319. package/templates/observability-map.svg +101 -0
  320. package/templates/pipeline-audit.md +108 -0
  321. package/templates/release-metrics.vl.json +98 -0
  322. package/templates/service-topology.mmd +47 -0
  323. package/templates/status-report.md +32 -0
  324. package/templates/system-map.svg +53 -0
  325. package/templates/timeseries.vl.json +71 -0
  326. package/templates/tsx-interactive-counter.tsx +19 -0
  327. package/templates/tsx-status-report.tsx +31 -0
@@ -0,0 +1,112 @@
1
+ /*
2
+ * Legion Works design tokens — vendored for offline use.
3
+ *
4
+ * The gallery renders fully OFFLINE on 127.0.0.1; no remote font or
5
+ * CDN fetch is allowed. The font stacks reference locally-installed
6
+ * faces (Space Grotesk, Geist, JetBrains Mono); when those are absent
7
+ * the system-stack fallback takes over. The CSP forbids external
8
+ * resource loads anyway, so missing faces degrade silently.
9
+ */
10
+
11
+ :root {
12
+ /* Brand palette — vendored Legion Works colors */
13
+ --facet-cyan: #86e1fc;
14
+ --facet-amber: #ff966c;
15
+ --facet-navy: #16161e;
16
+ --facet-navy-2: #1d1d27;
17
+ --facet-navy-3: #232330;
18
+ --facet-ink: #e9eaf0;
19
+ --facet-ink-dim: #b6b7c2;
20
+ --facet-ink-faint: #a6a8b5;
21
+ --facet-rule: #2e2e3a;
22
+ --facet-error: #ff6e6e;
23
+
24
+ /* Semantic shell surfaces and content roles. */
25
+ --facet-surface: var(--facet-navy);
26
+ --facet-surface-raised: var(--facet-navy-2);
27
+ --facet-surface-stage: #101018;
28
+ --facet-surface-control: var(--facet-navy-3);
29
+ --facet-text: var(--facet-ink);
30
+ --facet-text-muted: var(--facet-ink-dim);
31
+ --facet-text-faint: var(--facet-ink-faint);
32
+ --facet-rule-semantic: var(--facet-rule);
33
+ --facet-focus: var(--facet-cyan);
34
+ --facet-link: var(--facet-cyan);
35
+ --facet-shadow-export: rgba(0, 0, 0, 0.28);
36
+ --facet-live-ok: #c3e88d;
37
+ --facet-live-partial: #ffc777;
38
+ --facet-ok: #c3e88d;
39
+ --facet-fail: #ff757f;
40
+ --facet-partial: #ffc777;
41
+ --facet-inert: #a9b8e8;
42
+ --facet-tamper-ink: #16161e;
43
+ --facet-ok-border: color-mix(in srgb, var(--facet-ok) 45%, transparent);
44
+ --facet-ok-fill: transparent;
45
+ --facet-fail-border: color-mix(in srgb, var(--facet-fail) 45%, transparent);
46
+ --facet-fail-fill: transparent;
47
+ --facet-partial-border: color-mix(in srgb, var(--facet-partial) 45%, transparent);
48
+ --facet-partial-fill: transparent;
49
+ --facet-inert-border: color-mix(in srgb, var(--facet-inert) 38%, transparent);
50
+ --facet-inert-fill: transparent;
51
+ --facet-glow-danger:
52
+ 0 0 0 1px color-mix(in srgb, var(--facet-fail) 40%, transparent),
53
+ 0 8px 32px -8px color-mix(in srgb, var(--facet-fail) 55%, transparent);
54
+ --facet-tier-border: color-mix(in srgb, var(--facet-ink) 28%, transparent);
55
+ --facet-tier-fill: color-mix(in srgb, var(--facet-ink) 6%, transparent);
56
+ --facet-tier-strong-border: color-mix(in srgb, var(--facet-cyan) 45%, transparent);
57
+ --facet-tier-strong-fill: color-mix(in srgb, var(--facet-cyan) 8%, transparent);
58
+
59
+ /* Spacing scale (4px base) */
60
+ --facet-space-1: 4px;
61
+ --facet-space-2: 8px;
62
+ --facet-space-3: 12px;
63
+ --facet-space-4: 16px;
64
+ --facet-space-5: 24px;
65
+ --facet-space-6: 32px;
66
+
67
+ /* Radii */
68
+ --facet-radius-1: 4px;
69
+ --facet-radius-2: 8px;
70
+
71
+ /* Type */
72
+ --facet-font-sans:
73
+ "Space Grotesk", "Geist", "Inter", system-ui, -apple-system, "Segoe UI", Roboto,
74
+ "Helvetica Neue", Arial, sans-serif;
75
+ --facet-font-mono: "JetBrains Mono", "Geist Mono", "SF Mono", "Menlo", "Consolas", monospace;
76
+ }
77
+
78
+ [data-theme="light"] {
79
+ color-scheme: light;
80
+ --facet-cyan: #075985;
81
+ --facet-amber: #9a3412;
82
+ --facet-navy: #f8fafc;
83
+ --facet-navy-2: #ffffff;
84
+ --facet-navy-3: #e2e8f0;
85
+ --facet-ink: #172033;
86
+ --facet-ink-dim: #334155;
87
+ --facet-ink-faint: #475569;
88
+ --facet-rule: #cbd5e1;
89
+ --facet-error: #b91c1c;
90
+ --facet-surface-stage: #f1f5f9;
91
+ --facet-focus: #075985;
92
+ --facet-link: #075985;
93
+ --facet-shadow-export: rgba(15, 23, 42, 0.2);
94
+ --facet-live-ok: #166534;
95
+ --facet-live-partial: #9a3412;
96
+ --facet-ok: #166534;
97
+ --facet-fail: #b91c1c;
98
+ --facet-partial: #9a3412;
99
+ --facet-inert: #475569;
100
+ --facet-tamper-ink: #ffffff;
101
+ --facet-ok-border: color-mix(in srgb, var(--facet-ok) 50%, transparent);
102
+ --facet-fail-border: color-mix(in srgb, var(--facet-fail) 50%, transparent);
103
+ --facet-partial-border: color-mix(in srgb, var(--facet-partial) 50%, transparent);
104
+ --facet-inert-border: color-mix(in srgb, var(--facet-inert) 45%, transparent);
105
+ --facet-tier-border: color-mix(in srgb, var(--facet-inert) 45%, transparent);
106
+ --facet-tier-fill: color-mix(in srgb, var(--facet-inert) 8%, transparent);
107
+ --facet-tier-strong-border: color-mix(in srgb, var(--facet-cyan) 50%, transparent);
108
+ --facet-tier-strong-fill: color-mix(in srgb, var(--facet-cyan) 8%, transparent);
109
+ --facet-glow-danger:
110
+ 0 0 0 1px color-mix(in srgb, var(--facet-fail) 35%, transparent),
111
+ 0 8px 32px -8px color-mix(in srgb, var(--facet-fail) 25%, transparent);
112
+ }
@@ -0,0 +1,186 @@
1
+ /*
2
+ * Facet verdict language — tokens + components.
3
+ * Vendored Legion Works semantics (Tokyo Night palette), fully
4
+ * offline, no imports, no remote assets. Safe under the frozen CSP.
5
+ *
6
+ * Grammar: every verdict is glyph + hue + weight. Glyphs survive
7
+ * no-color; hue survives small sizes; weight survives peripheral
8
+ * vision. Only `tampered` is filled and glowing — nothing animates.
9
+ */
10
+
11
+ /*
12
+ * Verdict badge.
13
+ * <span class="facet-verdict" data-status="ok">ok<span class="tier">· T1</span></span>
14
+ * JS sets data-status to the FULL wire enum value and the text to the
15
+ * status word (`status.split(":")[0]`). The glyph comes from CSS so
16
+ * markup stays free of presentation.
17
+ */
18
+ .facet-verdict {
19
+ display: inline-flex;
20
+ align-items: center;
21
+ gap: 7px;
22
+ height: 24px;
23
+ padding: 0 11px;
24
+ border-radius: 999px;
25
+ border: 1px solid var(--facet-inert-border);
26
+ background: var(--facet-inert-fill);
27
+ color: var(--facet-inert);
28
+ font-family: var(--facet-font-mono);
29
+ font-size: 10.5px;
30
+ font-weight: 600;
31
+ letter-spacing: 0.1em;
32
+ text-transform: uppercase;
33
+ white-space: nowrap;
34
+ }
35
+ .facet-verdict::before {
36
+ font-size: 12px;
37
+ font-weight: 400;
38
+ letter-spacing: 0;
39
+ }
40
+ .facet-verdict .tier {
41
+ opacity: 0.62;
42
+ font-weight: 500;
43
+ }
44
+ .facet-verdict--sm {
45
+ height: 20px;
46
+ padding: 0 9px;
47
+ gap: 6px;
48
+ font-size: 10px;
49
+ }
50
+
51
+ .facet-verdict[data-status="ok"] {
52
+ border-color: var(--facet-ok-border);
53
+ background: var(--facet-ok-fill);
54
+ color: var(--facet-ok);
55
+ }
56
+ .facet-verdict[data-status="ok"]::before {
57
+ content: "✓";
58
+ }
59
+
60
+ .facet-verdict[data-status="error"] {
61
+ border-color: var(--facet-fail-border);
62
+ background: var(--facet-fail-fill);
63
+ color: var(--facet-fail);
64
+ }
65
+ .facet-verdict[data-status="error"]::before {
66
+ content: "✗";
67
+ }
68
+
69
+ .facet-verdict[data-status="partial:layout_unverified"] {
70
+ border-color: var(--facet-partial-border);
71
+ background: var(--facet-partial-fill);
72
+ color: var(--facet-partial);
73
+ }
74
+ .facet-verdict[data-status="partial:layout_unverified"]::before {
75
+ content: "◐";
76
+ }
77
+ .facet-verdict[data-status="partial:opaque_content"] {
78
+ border-color: var(--facet-partial-border);
79
+ background: var(--facet-partial-fill);
80
+ color: var(--facet-partial);
81
+ }
82
+ .facet-verdict[data-status="partial:opaque_content"]::before {
83
+ content: "◐";
84
+ }
85
+ .facet-verdict[data-status="partial:external_resources"] {
86
+ border-color: var(--facet-partial-border);
87
+ background: var(--facet-partial-fill);
88
+ color: var(--facet-partial);
89
+ }
90
+ .facet-verdict[data-status="partial:external_resources"]::before {
91
+ content: "◐";
92
+ }
93
+
94
+ .facet-verdict[data-status="partial:unstable"] {
95
+ border-color: var(--facet-partial-border);
96
+ background: var(--facet-partial-fill);
97
+ color: var(--facet-partial);
98
+ }
99
+ .facet-verdict[data-status="partial:unstable"]::before {
100
+ content: "◐";
101
+ }
102
+
103
+ /* The alarm. The only fill, the only glow. Never animated. */
104
+ .facet-verdict[data-status="tampered"],
105
+ .facet-verdict[data-status="insecure:unvalidated"] {
106
+ border-color: var(--facet-fail);
107
+ background: var(--facet-fail);
108
+ color: var(--facet-tamper-ink);
109
+ font-weight: 700;
110
+ box-shadow: var(--facet-glow-danger);
111
+ }
112
+ .facet-verdict[data-status="tampered"]::before {
113
+ content: "⊘";
114
+ }
115
+
116
+ .facet-verdict[data-status="tampered"]::before,
117
+ .facet-verdict[data-status="insecure:unvalidated"]::before {
118
+ content: "⊘";
119
+ }
120
+
121
+ .facet-verdict[data-status="timeout"]::before {
122
+ content: "◌";
123
+ }
124
+ .facet-verdict[data-status="shim_only"]::before {
125
+ content: "◇";
126
+ }
127
+ .facet-verdict[data-status="probe_only"]::before {
128
+ content: "◈";
129
+ }
130
+
131
+ /* No verdict yet for the displayed revision — dashed, tierless. */
132
+ .facet-verdict[data-status="unverified"] {
133
+ border-style: dashed;
134
+ background: transparent;
135
+ }
136
+ .facet-verdict[data-status="unverified"]::before {
137
+ content: "◌";
138
+ }
139
+
140
+ /*
141
+ * Tier tag — metadata, not a verdict. Square, mono.
142
+ * <span class="facet-tier" data-tier="1">T1<span>browser</span></span>
143
+ * T2 is dashed: it displays, it never testifies.
144
+ */
145
+ .facet-tier {
146
+ display: inline-flex;
147
+ align-items: center;
148
+ gap: 8px;
149
+ height: 24px;
150
+ padding: 0 10px;
151
+ border-radius: 6px;
152
+ border: 1px solid var(--facet-tier-border);
153
+ background: var(--facet-tier-fill);
154
+ color: var(--facet-text);
155
+ font-family: var(--facet-font-mono);
156
+ font-size: 11px;
157
+ font-weight: 600;
158
+ letter-spacing: 0.1em;
159
+ }
160
+ .facet-tier span {
161
+ font-weight: 500;
162
+ opacity: 0.75;
163
+ }
164
+ .facet-tier[data-tier="1"] {
165
+ border-color: var(--facet-tier-strong-border);
166
+ background: var(--facet-tier-strong-fill);
167
+ color: var(--facet-focus);
168
+ }
169
+ .facet-tier[data-tier="2"] {
170
+ border-style: dashed;
171
+ background: transparent;
172
+ color: var(--facet-inert);
173
+ }
174
+
175
+ /* Evidence-channel dots (expanded panels only, never in the badge). */
176
+ .facet-channels {
177
+ font-family: var(--facet-font-mono);
178
+ letter-spacing: 4px;
179
+ color: var(--facet-ink-dim);
180
+ }
181
+ .facet-channels[data-agree="true"] {
182
+ color: var(--facet-ok);
183
+ }
184
+ .facet-channels[data-agree="false"] {
185
+ color: var(--facet-fail);
186
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Double-buffered HMR swap plan — pure state machine.
3
+ *
4
+ * The shell calls `run()` on each step in order. The steps are a
5
+ * tagged union so callers can introspect the plan without re-deriving
6
+ * it from a state machine.
7
+ *
8
+ * Ordering invariant: `render-new` < `swap` < `apply-view-state` <
9
+ * `remove-old`. If the new frame fails to render within the wait window,
10
+ * the plan stops short of `swap` /
11
+ * `remove-old` — the old frame stays visible with an error badge.
12
+ */
13
+
14
+ export type SwapPlanStep =
15
+ | { readonly name: "build-new"; readonly run: () => void; readonly frameId: string }
16
+ | { readonly name: "load-new"; readonly run: () => void; readonly frameId: string }
17
+ | { readonly name: "render-new"; readonly run: () => void; readonly frameId: string }
18
+ | { readonly name: "swap"; readonly run: () => void }
19
+ | { readonly name: "apply-view-state"; readonly run: () => void; readonly zoom: number }
20
+ | { readonly name: "remove-old"; readonly run: () => void; readonly frameId: string };
21
+
22
+ export interface PlanSwapOptions {
23
+ readonly currentFrameId: string;
24
+ readonly nextFrameId: string;
25
+ readonly viewState: { readonly zoom: number };
26
+ readonly failNewRender?: boolean;
27
+ readonly onStep?: (step: SwapPlanStep) => void;
28
+ }
29
+
30
+ const NOOP = (): void => {};
31
+
32
+ export function planSwap(options: PlanSwapOptions): readonly SwapPlanStep[] {
33
+ const { currentFrameId, nextFrameId, viewState, failNewRender, onStep } = options;
34
+ const emit = (s: SwapPlanStep): SwapPlanStep => {
35
+ onStep?.(s);
36
+ return s;
37
+ };
38
+ const steps: SwapPlanStep[] = [
39
+ emit({
40
+ name: "build-new",
41
+ frameId: nextFrameId,
42
+ run: NOOP,
43
+ }),
44
+ emit({
45
+ name: "load-new",
46
+ frameId: nextFrameId,
47
+ run: NOOP,
48
+ }),
49
+ emit({
50
+ name: "render-new",
51
+ frameId: nextFrameId,
52
+ run: NOOP,
53
+ }),
54
+ ];
55
+ if (failNewRender === true) {
56
+ return steps;
57
+ }
58
+ steps.push(
59
+ emit({ name: "swap", run: NOOP }),
60
+ emit({ name: "apply-view-state", zoom: viewState.zoom, run: NOOP }),
61
+ emit({ name: "remove-old", frameId: currentFrameId, run: NOOP }),
62
+ );
63
+ return steps;
64
+ }
@@ -0,0 +1,40 @@
1
+ export type GalleryThemeMode = "dark" | "light" | "system";
2
+
3
+ export type ResolvedGalleryTheme = Exclude<GalleryThemeMode, "system">;
4
+
5
+ export type GalleryMatchMedia =
6
+ | ((query: string) => Pick<MediaQueryList, "matches"> | null | undefined)
7
+ | null
8
+ | undefined;
9
+
10
+ export function isGalleryThemeMode(value: unknown): value is GalleryThemeMode {
11
+ return value === "dark" || value === "light" || value === "system";
12
+ }
13
+
14
+ export function isResolvedGalleryTheme(value: unknown): value is ResolvedGalleryTheme {
15
+ return value === "dark" || value === "light";
16
+ }
17
+
18
+ export function resolveGalleryTheme(
19
+ mode: GalleryThemeMode,
20
+ matchMedia: GalleryMatchMedia,
21
+ ): ResolvedGalleryTheme {
22
+ if (mode !== "system") return mode;
23
+ try {
24
+ const preference = matchMedia?.("(prefers-color-scheme: dark)");
25
+ if (
26
+ preference === null ||
27
+ preference === undefined ||
28
+ typeof preference.matches !== "boolean"
29
+ ) {
30
+ return "dark";
31
+ }
32
+ return preference.matches ? "dark" : "light";
33
+ } catch {
34
+ return "dark";
35
+ }
36
+ }
37
+
38
+ export function galleryDataTheme(theme: ResolvedGalleryTheme): "night" | "winter" {
39
+ return theme === "light" ? "winter" : "night";
40
+ }
@@ -0,0 +1,93 @@
1
+ import type { ViewportSize } from "./frame/view-box";
2
+
3
+ export const MIN_ZOOM = 0.25;
4
+ export const MAX_ZOOM = 8;
5
+
6
+ export interface ViewState {
7
+ zoom: number;
8
+ panX?: number;
9
+ panY?: number;
10
+ }
11
+
12
+ export function clampZoom(zoom: number): number {
13
+ if (!Number.isFinite(zoom)) return 1;
14
+ return Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, zoom));
15
+ }
16
+
17
+ /** Canonical zero state — the one home for the `{ zoom: 1, panX: 0, panY: 0 }` literal. */
18
+ export const EMPTY_VIEW_STATE: Required<ViewState> = { zoom: 1, panX: 0, panY: 0 };
19
+
20
+ export function resetViewState(_state: ViewState): ViewState {
21
+ return { ...EMPTY_VIEW_STATE };
22
+ }
23
+
24
+ /** Fill the optional pan fields so callers stop open-coding `?? 0`. */
25
+ export function normalizeViewState(state: ViewState): Required<ViewState> {
26
+ return { zoom: state.zoom, panX: state.panX ?? 0, panY: state.panY ?? 0 };
27
+ }
28
+
29
+ export function zoomAtPoint(
30
+ state: ViewState,
31
+ nextZoom: number,
32
+ cursorX: number,
33
+ cursorY: number,
34
+ ): ViewState {
35
+ const zoom = clampZoom(nextZoom);
36
+ const ratio = zoom / state.zoom;
37
+ const panX = state.panX ?? 0;
38
+ const panY = state.panY ?? 0;
39
+ return {
40
+ zoom,
41
+ panX: cursorX - (cursorX - panX) * ratio,
42
+ panY: cursorY - (cursorY - panY) * ratio,
43
+ };
44
+ }
45
+
46
+ const ZOOM_KEY_FACTOR = Math.exp(100 * 0.001);
47
+ const PAN_STEP_PX = 10;
48
+ const PAN_STEP_PX_SHIFT = 50;
49
+
50
+ /**
51
+ * Map a keydown event to the resulting view state, or null if the key
52
+ * isn't one of the bound zoom/pan/reset keys. Pure — no DOM access —
53
+ * so both the shell (parent document) and the frame (iframe document)
54
+ * keydown listeners can share one tested key-to-state mapping instead
55
+ * of maintaining parallel copies.
56
+ */
57
+ export function nextViewStateForKey(
58
+ state: ViewState,
59
+ key: string,
60
+ shiftKey: boolean,
61
+ rect: ViewportSize,
62
+ ): ViewState | null {
63
+ if (key === "+" || key === "=") {
64
+ return zoomAtPoint(
65
+ state,
66
+ clampZoom(state.zoom * ZOOM_KEY_FACTOR),
67
+ rect.width / 2,
68
+ rect.height / 2,
69
+ );
70
+ }
71
+ if (key === "-") {
72
+ return zoomAtPoint(
73
+ state,
74
+ clampZoom(state.zoom / ZOOM_KEY_FACTOR),
75
+ rect.width / 2,
76
+ rect.height / 2,
77
+ );
78
+ }
79
+ if (key === "0") {
80
+ return resetViewState(state);
81
+ }
82
+ if (key === "ArrowLeft" || key === "ArrowRight" || key === "ArrowUp" || key === "ArrowDown") {
83
+ const amount = shiftKey ? PAN_STEP_PX_SHIFT : PAN_STEP_PX;
84
+ const dx = key === "ArrowLeft" ? -amount : key === "ArrowRight" ? amount : 0;
85
+ const dy = key === "ArrowUp" ? -amount : key === "ArrowDown" ? amount : 0;
86
+ return {
87
+ ...state,
88
+ panX: (state.panX ?? 0) + dx,
89
+ panY: (state.panY ?? 0) + dy,
90
+ };
91
+ }
92
+ return null;
93
+ }
@@ -0,0 +1,10 @@
1
+ # Facet adapter for Claude Code
2
+
3
+ Install the adapter where Claude Code can invoke local tools, then point it at
4
+ `facet.sh`. The adapter forwards argv and stdin to the Facet CLI and returns
5
+ stdout unchanged.
6
+
7
+ Use `facet status` before a workflow. Publish source through stdin; keep
8
+ secrets out of artifacts. Promotion remains operator-only.
9
+
10
+ → [Facet agent skill](../../../skills/facet/SKILL.md) · [CLI reference](../../../docs/reference/cli.md)
@@ -0,0 +1,4 @@
1
+ #!/bin/sh
2
+ set -eu
3
+ SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
4
+ exec bun "$SCRIPT_DIR/../../../src/cli/main.ts" "$@"
@@ -0,0 +1,10 @@
1
+ # Facet adapter for Codex
2
+
3
+ Install the adapter where Codex can invoke local tools, then point it at
4
+ `facet.sh`. The adapter forwards argv and stdin to the Facet CLI and returns
5
+ stdout unchanged.
6
+
7
+ Use `facet status` before a workflow. Publish source through stdin; keep
8
+ secrets out of artifacts. Promotion remains operator-only.
9
+
10
+ → [Facet agent skill](../../../skills/facet/SKILL.md) · [CLI reference](../../../docs/reference/cli.md)
@@ -0,0 +1,4 @@
1
+ #!/bin/sh
2
+ set -eu
3
+ SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
4
+ exec bun "$SCRIPT_DIR/../../../src/cli/main.ts" "$@"
@@ -0,0 +1,13 @@
1
+ # Facet MCP adapter
2
+
3
+ Run this source-archive adapter with Bun:
4
+
5
+ ```sh
6
+ bun src/harness-adapters/mcp/main.ts
7
+ ```
8
+
9
+ It shells out to the Facet CLI, returns the strict CLI envelope as MCP text content, and maps typed CLI failures to MCP tool errors. `FACET_CLI` selects an alternate CLI executable; otherwise the adapter uses the repository CLI, then `facet` on `PATH`.
10
+
11
+ The adapter imports only adapter-local code, shared contracts, the MCP SDK, Zod, and Node builtins. Do not add service, validation, or gallery imports.
12
+
13
+ → [MCP reference](../../../docs/reference/mcp.md)