@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,216 @@
1
+ import { existsSync } from "node:fs";
2
+ import { resolve } from "node:path";
3
+
4
+ import {
5
+ type FacetEnvelope,
6
+ type FacetErrorBody,
7
+ parseEnvelope,
8
+ } from "../../shared/contracts/envelope";
9
+
10
+ const STDERR_DETAIL_LIMIT = 4_096;
11
+
12
+ export type FacetToolName = "publish" | "read_back" | "status" | "export" | "open";
13
+
14
+ export interface FacetCliInvocation {
15
+ readonly command: string;
16
+ readonly args: readonly string[];
17
+ readonly cwd?: string;
18
+ readonly env?: NodeJS.ProcessEnv;
19
+ readonly stdin?: string;
20
+ }
21
+
22
+ export interface FacetCliResult {
23
+ readonly exitCode: number;
24
+ readonly stderr: string;
25
+ readonly stdout: string;
26
+ }
27
+
28
+ export type FacetCliRunner = (invocation: FacetCliInvocation) => Promise<FacetCliResult>;
29
+
30
+ export interface InvokeFacetOptions {
31
+ readonly cwd?: string;
32
+ readonly env?: NodeJS.ProcessEnv;
33
+ readonly runner?: FacetCliRunner;
34
+ readonly stdin?: string;
35
+ }
36
+
37
+ export class FacetBridgeError extends Error {
38
+ constructor(
39
+ readonly body: FacetErrorBody,
40
+ cause?: unknown,
41
+ ) {
42
+ super(body.message, { cause });
43
+ }
44
+ }
45
+
46
+ function bridgeError(
47
+ code: string,
48
+ message: string,
49
+ details?: FacetErrorBody["details"],
50
+ cause?: unknown,
51
+ ): FacetBridgeError {
52
+ return new FacetBridgeError(
53
+ {
54
+ code,
55
+ message,
56
+ retryable: false,
57
+ ...(details === undefined ? {} : { details }),
58
+ },
59
+ cause,
60
+ );
61
+ }
62
+
63
+ function requiredString(input: Readonly<Record<string, unknown>>, key: string): string {
64
+ const value = input[key];
65
+ if (typeof value === "string" && value.length > 0) return value;
66
+ throw bridgeError("invalid_request", `${key} is required`);
67
+ }
68
+
69
+ function appendString(args: string[], flag: string, value: unknown): void {
70
+ if (typeof value === "string" && value.length > 0) args.push(flag, value);
71
+ }
72
+
73
+ export function buildFacetArgs(
74
+ tool: FacetToolName,
75
+ input: Readonly<Record<string, unknown>>,
76
+ ): string[] {
77
+ switch (tool) {
78
+ case "publish": {
79
+ const args = [
80
+ "publish",
81
+ "--artifact-id",
82
+ requiredString(input, "artifactId"),
83
+ "--type",
84
+ requiredString(input, "type"),
85
+ ];
86
+ appendString(args, "--renderer", input.renderer);
87
+ appendString(args, "--execution", input.execution);
88
+ appendString(args, "--file", input.file);
89
+ appendString(args, "--note", input.note);
90
+ appendString(args, "--parent-revision-id", input.parentRevisionId);
91
+ return args;
92
+ }
93
+ case "read_back": {
94
+ const args = ["read-back", "--artifact-id", requiredString(input, "artifactId")];
95
+ appendString(args, "--revision-sha", input.revisionSha);
96
+ if (input.tier !== undefined) args.push("--tier", String(input.tier));
97
+ return args;
98
+ }
99
+ case "status": {
100
+ const args = ["status"];
101
+ appendString(args, "--artifact-id", input.artifactId);
102
+ if (input.start === true) args.push("--start");
103
+ return args;
104
+ }
105
+ case "export": {
106
+ const args = [
107
+ "export",
108
+ requiredString(input, "artifactId"),
109
+ "--format",
110
+ requiredString(input, "format"),
111
+ ];
112
+ appendString(args, "--revision", input.revisionSha);
113
+ if (input.force === true) args.push("--force");
114
+ if (input.includeBytes === true) args.push("--include-bytes");
115
+ return args;
116
+ }
117
+ case "open": {
118
+ const args = ["open", "--artifact-id", requiredString(input, "artifactId")];
119
+ appendString(args, "--revision-sha", input.revisionSha);
120
+ args.push("--no-launch");
121
+ return args;
122
+ }
123
+ }
124
+ }
125
+
126
+ function resolveFacetCommand(env: NodeJS.ProcessEnv): Pick<FacetCliInvocation, "command" | "args"> {
127
+ const override = env.FACET_CLI?.trim();
128
+ if (override !== undefined && override.length > 0) return { command: override, args: [] };
129
+
130
+ const sourceCli = resolve(import.meta.dir, "../../cli/main.ts");
131
+ if (existsSync(sourceCli)) return { command: Bun.which("bun") ?? "bun", args: [sourceCli] };
132
+ return { command: "facet", args: [] };
133
+ }
134
+
135
+ async function runFacetCli(invocation: FacetCliInvocation): Promise<FacetCliResult> {
136
+ const proc = Bun.spawn([invocation.command, ...invocation.args], {
137
+ stderr: "pipe",
138
+ stdin: invocation.stdin === undefined ? "ignore" : "pipe",
139
+ stdout: "pipe",
140
+ ...(invocation.cwd === undefined ? {} : { cwd: invocation.cwd }),
141
+ ...(invocation.env === undefined ? {} : { env: invocation.env }),
142
+ });
143
+ if (invocation.stdin !== undefined) {
144
+ const stdin = proc.stdin;
145
+ if (stdin === undefined) throw new Error("Facet CLI stdin pipe was not created");
146
+ stdin.write(invocation.stdin);
147
+ stdin.end();
148
+ }
149
+ const [exitCode, stdout, stderr] = await Promise.all([
150
+ proc.exited,
151
+ new Response(proc.stdout).text(),
152
+ new Response(proc.stderr).text(),
153
+ ]);
154
+ return { exitCode, stdout, stderr };
155
+ }
156
+
157
+ function boundedStderr(stderr: string): string {
158
+ const normalized = stderr.trim();
159
+ if (normalized.length <= STDERR_DETAIL_LIMIT) return normalized;
160
+ return `${normalized.slice(0, STDERR_DETAIL_LIMIT)}…`;
161
+ }
162
+
163
+ export function parseFacetStdout(stdout: string): FacetEnvelope<unknown> {
164
+ let value: unknown;
165
+ try {
166
+ value = JSON.parse(stdout);
167
+ } catch (cause) {
168
+ throw bridgeError("invalid_envelope", "Invalid Facet envelope on stdout", undefined, cause);
169
+ }
170
+ const parsed = parseEnvelope(value);
171
+ if (parsed.ok) return parsed.envelope;
172
+ throw new FacetBridgeError({
173
+ ...parsed.body,
174
+ message: `Invalid Facet envelope: ${parsed.body.message}`,
175
+ });
176
+ }
177
+
178
+ export async function invokeFacet(
179
+ args: readonly string[],
180
+ options: InvokeFacetOptions = {},
181
+ ): Promise<FacetEnvelope<unknown>> {
182
+ const env = options.env ?? process.env;
183
+ const resolved = resolveFacetCommand(env);
184
+ const invocation: FacetCliInvocation = {
185
+ command: resolved.command,
186
+ args: [...resolved.args, ...args],
187
+ ...(options.cwd === undefined ? {} : { cwd: options.cwd }),
188
+ env,
189
+ ...(options.stdin === undefined ? {} : { stdin: options.stdin }),
190
+ };
191
+ const result = await (options.runner ?? runFacetCli)(invocation);
192
+ try {
193
+ return parseFacetStdout(result.stdout);
194
+ } catch (cause) {
195
+ const error =
196
+ cause instanceof FacetBridgeError
197
+ ? cause
198
+ : bridgeError(
199
+ "invalid_envelope",
200
+ cause instanceof Error ? cause.message : String(cause),
201
+ undefined,
202
+ cause,
203
+ );
204
+ throw new FacetBridgeError(
205
+ {
206
+ ...error.body,
207
+ details: {
208
+ ...error.body.details,
209
+ exitCode: result.exitCode,
210
+ ...(result.stderr.length === 0 ? {} : { stderr: boundedStderr(result.stderr) }),
211
+ },
212
+ },
213
+ cause,
214
+ );
215
+ }
216
+ }
@@ -0,0 +1,15 @@
1
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
2
+
3
+ import { createFacetMcpServer } from "./server";
4
+
5
+ async function main(): Promise<void> {
6
+ const server = createFacetMcpServer();
7
+ await server.connect(new StdioServerTransport());
8
+ }
9
+
10
+ void main().catch((error: unknown) => {
11
+ process.stderr.write(
12
+ `facet MCP server failed: ${error instanceof Error ? error.message : String(error)}\n`,
13
+ );
14
+ process.exitCode = 1;
15
+ });
@@ -0,0 +1,164 @@
1
+ import { mkdirSync } from "node:fs";
2
+
3
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
+ import { z, ZodError } from "zod";
5
+ import { FACET_VERSION } from "../../shared/version";
6
+
7
+ import { buildFacetArgs, FacetBridgeError, invokeFacet } from "./cli-bridge";
8
+ import {
9
+ ExportToolSchema,
10
+ OpenUrlToolSchema,
11
+ PublishToolSchema,
12
+ type PublishToolInput,
13
+ ReadBackToolSchema,
14
+ StatusToolSchema,
15
+ } from "./tool-schemas";
16
+ import { errEnvelope, type FacetEnvelope } from "../../shared/contracts/envelope";
17
+
18
+ function requestId(): string {
19
+ return `req-mcp-${crypto.randomUUID()}`;
20
+ }
21
+
22
+ function errorEnvelope(cause: unknown): FacetEnvelope<never> {
23
+ if (cause instanceof ZodError) {
24
+ const issue = cause.issues[0];
25
+ const field = issue?.path.join(".") || "arguments";
26
+ return errEnvelope(requestId(), {
27
+ code: "invalid_request",
28
+ message: `Invalid MCP argument '${field}': ${issue?.message ?? "schema validation failed"}`,
29
+ retryable: false,
30
+ details: { field },
31
+ });
32
+ }
33
+ const body =
34
+ cause instanceof FacetBridgeError
35
+ ? cause.body
36
+ : {
37
+ code: "invalid_envelope",
38
+ message: cause instanceof Error ? cause.message : String(cause),
39
+ retryable: false,
40
+ };
41
+ return errEnvelope(requestId(), body);
42
+ }
43
+
44
+ const LooseToolInputSchema = z.record(z.unknown());
45
+
46
+ function toolResult(envelope: FacetEnvelope<unknown>) {
47
+ return {
48
+ content: [{ type: "text" as const, text: JSON.stringify(envelope) }],
49
+ ...(envelope.ok ? {} : { isError: true }),
50
+ };
51
+ }
52
+
53
+ async function invoke(args: readonly string[], options: { cwd?: string; stdin?: string } = {}) {
54
+ try {
55
+ return toolResult(await invokeFacet(args, options));
56
+ } catch (cause) {
57
+ return toolResult(errorEnvelope(cause));
58
+ }
59
+ }
60
+
61
+ async function withInput<T>(
62
+ args: unknown,
63
+ parse: (input: unknown) => T,
64
+ run: (input: T) => Promise<ReturnType<typeof toolResult>>,
65
+ ): Promise<ReturnType<typeof toolResult>> {
66
+ try {
67
+ return await run(parse(args));
68
+ } catch (cause) {
69
+ return toolResult(errorEnvelope(cause));
70
+ }
71
+ }
72
+
73
+ function publishSource(input: PublishToolInput): {
74
+ file?: string;
75
+ stdin?: string;
76
+ } {
77
+ if (input.sourceText !== undefined && input.file !== undefined) {
78
+ throw new FacetBridgeError({
79
+ code: "invalid_request",
80
+ message: "Pass sourceText or file, not both",
81
+ retryable: false,
82
+ });
83
+ }
84
+ if (input.sourceText !== undefined) return { stdin: input.sourceText };
85
+ if (input.file !== undefined) return { file: input.file };
86
+ throw new FacetBridgeError({
87
+ code: "invalid_request",
88
+ message: "publish requires sourceText or file",
89
+ retryable: false,
90
+ });
91
+ }
92
+
93
+ export function createFacetMcpServer(): McpServer {
94
+ const server = new McpServer({ name: "facet", version: FACET_VERSION });
95
+
96
+ server.registerTool(
97
+ "facet_export",
98
+ {
99
+ description:
100
+ "Export source or stored render evidence into outDir. Check envelope.ok for transport success; a successful publish verdict remains a separate data.verdict.status decision.",
101
+ inputSchema: LooseToolInputSchema,
102
+ },
103
+ async (args) =>
104
+ withInput(args, ExportToolSchema.parse, async (input) => {
105
+ mkdirSync(input.outDir, { recursive: true });
106
+ return invoke(buildFacetArgs("export", input), { cwd: input.outDir });
107
+ }),
108
+ );
109
+
110
+ server.registerTool(
111
+ "facet_open_url",
112
+ {
113
+ description:
114
+ "Return a Facet gallery frameUrl without launching a browser. This always invokes facet open --no-launch; agents must not launch desktop display.",
115
+ inputSchema: LooseToolInputSchema,
116
+ },
117
+ async (args) =>
118
+ withInput(args, OpenUrlToolSchema.parse, async (input) =>
119
+ invoke(buildFacetArgs("open", input)),
120
+ ),
121
+ );
122
+
123
+ server.registerTool(
124
+ "facet_publish",
125
+ {
126
+ description:
127
+ "Publish exactly one sourceText or local file. Check envelope.ok separately from data.verdict.status: stored verdict status error is not a transport failure.",
128
+ inputSchema: LooseToolInputSchema,
129
+ },
130
+ async (args) =>
131
+ withInput(args, PublishToolSchema.parse, async (input) => {
132
+ const source = publishSource(input);
133
+ return invoke(buildFacetArgs("publish", { ...input, ...source }), source);
134
+ }),
135
+ );
136
+
137
+ server.registerTool(
138
+ "facet_read_back",
139
+ {
140
+ description:
141
+ "Read back the latest or revision-bound stored verdict at Tier 0, Tier 1, or visual. Tier 1 and visual need browser evidence; inspect envelope.ok before verdict status.",
142
+ inputSchema: LooseToolInputSchema,
143
+ },
144
+ async (args) =>
145
+ withInput(args, ReadBackToolSchema.parse, async (input) =>
146
+ invoke(buildFacetArgs("read_back", input)),
147
+ ),
148
+ );
149
+
150
+ server.registerTool(
151
+ "facet_status",
152
+ {
153
+ description:
154
+ "Read Facet status. Set start only when activation is intended; envelope.ok reports command transport and never replaces verdict.status inspection.",
155
+ inputSchema: LooseToolInputSchema,
156
+ },
157
+ async (args) =>
158
+ withInput(args, StatusToolSchema.parse, async (input) =>
159
+ invoke(buildFacetArgs("status", input)),
160
+ ),
161
+ );
162
+
163
+ return server;
164
+ }
@@ -0,0 +1,53 @@
1
+ import { z } from "zod";
2
+
3
+ import { ArtifactTypeSchema, RendererSchema } from "../../shared/contracts/artifact";
4
+
5
+ const RevisionShaSchema = z.string().regex(/^[a-f0-9]{64}$/);
6
+ const ExecutionSchema = z.enum(["static", "interactive"]);
7
+ const ReadBackTierSchema = z.union([z.literal(0), z.literal(1), z.literal("visual")]);
8
+
9
+ export const PublishToolShape = {
10
+ artifactId: z.string().min(1),
11
+ type: ArtifactTypeSchema,
12
+ execution: ExecutionSchema.optional(),
13
+ renderer: RendererSchema.optional(),
14
+ sourceText: z.string().min(1).optional(),
15
+ file: z.string().min(1).optional(),
16
+ note: z.string().min(1).optional(),
17
+ parentRevisionId: z.string().min(1).optional(),
18
+ };
19
+ export const PublishToolSchema = z.object(PublishToolShape).strict();
20
+ export type PublishToolInput = z.infer<typeof PublishToolSchema>;
21
+
22
+ export const ReadBackToolShape = {
23
+ artifactId: z.string().min(1),
24
+ revisionSha: RevisionShaSchema.optional(),
25
+ tier: ReadBackTierSchema.optional(),
26
+ };
27
+ export const ReadBackToolSchema = z.object(ReadBackToolShape).strict();
28
+ export type ReadBackToolInput = z.infer<typeof ReadBackToolSchema>;
29
+
30
+ export const StatusToolShape = {
31
+ artifactId: z.string().min(1).optional(),
32
+ start: z.boolean().optional(),
33
+ };
34
+ export const StatusToolSchema = z.object(StatusToolShape).strict();
35
+ export type StatusToolInput = z.infer<typeof StatusToolSchema>;
36
+
37
+ export const ExportToolShape = {
38
+ artifactId: z.string().min(1),
39
+ revisionSha: RevisionShaSchema.optional(),
40
+ format: z.enum(["source", "render"]).default("source"),
41
+ outDir: z.string().min(1),
42
+ force: z.boolean().optional(),
43
+ includeBytes: z.boolean().optional(),
44
+ };
45
+ export const ExportToolSchema = z.object(ExportToolShape).strict();
46
+ export type ExportToolInput = z.infer<typeof ExportToolSchema>;
47
+
48
+ export const OpenUrlToolShape = {
49
+ artifactId: z.string().min(1),
50
+ revisionSha: RevisionShaSchema.optional(),
51
+ };
52
+ export const OpenUrlToolSchema = z.object(OpenUrlToolShape).strict();
53
+ export type OpenUrlToolInput = z.infer<typeof OpenUrlToolSchema>;
@@ -0,0 +1,10 @@
1
+ # Facet adapter for OpenCode
2
+
3
+ Install the adapter where OpenCode 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,69 @@
1
+ import {
2
+ runServiceProcess,
3
+ type ParsedServiceArgs,
4
+ type ServiceRunnerModules,
5
+ } from "../service/process";
6
+ import { createTier0Runner, probeTier0Isolation } from "../validation/tier0/runner";
7
+ import { formatWorkerUnhandled, runWorkerLoop } from "../validation/tier0/worker-entry";
8
+ import { createTier1Runner, probeTier1Availability } from "../validation/tier1/runner";
9
+
10
+ export { buildTier0WorkerArgs } from "../shared/build-mode";
11
+
12
+ export interface CompiledEntrypointHooks {
13
+ readonly runService?: (argv: readonly string[]) => Promise<number>;
14
+ readonly runTier0Worker?: () => Promise<number>;
15
+ }
16
+
17
+ export interface CompiledServiceDeps {
18
+ readonly runServiceProcess?: typeof runServiceProcess;
19
+ }
20
+
21
+ export interface CompiledWorkerDeps {
22
+ readonly stdin?: ReadableStreamDefaultReader<Uint8Array>;
23
+ readonly runWorkerLoop?: typeof runWorkerLoop;
24
+ readonly writeStderr?: (text: string) => void;
25
+ readonly writeStdout?: (text: string) => void;
26
+ }
27
+
28
+ function loadCompiledModules(
29
+ _args: ParsedServiceArgs,
30
+ _env: NodeJS.ProcessEnv,
31
+ ): Promise<ServiceRunnerModules> {
32
+ return Promise.resolve({
33
+ tier0: { factory: createTier0Runner, probe: probeTier0Isolation },
34
+ loadTier1: () => Promise.resolve({ factory: createTier1Runner, probe: probeTier1Availability }),
35
+ });
36
+ }
37
+
38
+ export async function runCompiledService(
39
+ argv: readonly string[],
40
+ deps: CompiledServiceDeps = {},
41
+ ): Promise<number> {
42
+ return (deps.runServiceProcess ?? runServiceProcess)(argv, process.env, loadCompiledModules);
43
+ }
44
+
45
+ export async function runCompiledTier0Worker(deps: CompiledWorkerDeps = {}): Promise<number> {
46
+ const stdin = deps.stdin ?? Bun.stdin.stream().getReader();
47
+ const writeStdout = deps.writeStdout ?? process.stdout.write.bind(process.stdout);
48
+ const writeStderr = deps.writeStderr ?? process.stderr.write.bind(process.stderr);
49
+ const workerLoop = deps.runWorkerLoop ?? runWorkerLoop;
50
+ try {
51
+ return await workerLoop(stdin, writeStdout, writeStderr);
52
+ } catch (error) {
53
+ writeStderr(formatWorkerUnhandled(error));
54
+ return 1;
55
+ }
56
+ }
57
+
58
+ export async function dispatchCompiledEntrypoint(
59
+ argv: readonly string[],
60
+ hooks: CompiledEntrypointHooks = {},
61
+ ): Promise<number | null> {
62
+ if (argv[0] === "--facet-internal-service") {
63
+ return (hooks.runService ?? runCompiledService)(argv.slice(1));
64
+ }
65
+ if (argv[0] === "--facet-internal-tier0-worker") {
66
+ return (hooks.runTier0Worker ?? runCompiledTier0Worker)();
67
+ }
68
+ return null;
69
+ }