@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,167 @@
1
+ import type { Database } from "bun:sqlite";
2
+
3
+ import { asStoreError, FacetStoreError } from "./database";
4
+ export { INITIAL_SCHEMA } from "./schema";
5
+ import {
6
+ INITIAL_SCHEMA,
7
+ V2_SCHEMA_FRAGMENT,
8
+ V3_SCHEMA_FRAGMENT,
9
+ V4_SCHEMA_FRAGMENT,
10
+ V5_SCHEMA_FRAGMENT,
11
+ V6_SCHEMA_FRAGMENT,
12
+ V7_SCHEMA_FRAGMENT,
13
+ V8_SCHEMA_FRAGMENT,
14
+ V9_SCHEMA_FRAGMENT,
15
+ } from "./schema";
16
+ import { CURRENT_STORAGE_VERSION } from "../../shared/storage-version";
17
+
18
+ export interface MigrationOptions {
19
+ readonly beforeRecordVersion?: (version: number) => void;
20
+ }
21
+
22
+ interface MigrationStep {
23
+ readonly version: number;
24
+ /** Idempotent body — safe to re-run against an already-migrated DB. */
25
+ readonly apply: (db: Database) => void;
26
+ /**
27
+ * `true` on steps that use the create-copy-drop-rename pattern on
28
+ * a self-FK-bearing table. SQLite refuses the DROP + ALTER TABLE
29
+ * RENAME sequence inside a transaction with FKs ON, because the
30
+ * inherited FK would dangle across the DROP. Steps that only add
31
+ * columns inherit nothing — a future rebuild opts in explicitly at
32
+ * its definition site. The flag gates the per-run
33
+ * `PRAGMA foreign_keys = OFF` toggle so a no-op re-run on an
34
+ * already-current database does not needlessly disable FKs.
35
+ */
36
+ readonly requiresForeignKeyDisable?: boolean;
37
+ }
38
+
39
+ const MIGRATION_STEPS: readonly MigrationStep[] = [
40
+ {
41
+ version: 1,
42
+ apply: (db) => {
43
+ db.exec(INITIAL_SCHEMA);
44
+ },
45
+ },
46
+ {
47
+ version: 2,
48
+ apply: (db) => {
49
+ // Evidence retention: the `retained` column exempts a render_run
50
+ // from the last-N cleanup policy. Default 0 (not retained) keeps
51
+ // every existing row eligible for eviction.
52
+ db.exec(V2_SCHEMA_FRAGMENT);
53
+ },
54
+ },
55
+ {
56
+ version: 3,
57
+ apply: (db) => {
58
+ db.exec(V3_SCHEMA_FRAGMENT);
59
+ },
60
+ },
61
+ {
62
+ version: 4,
63
+ apply: (db) => {
64
+ db.exec(V4_SCHEMA_FRAGMENT);
65
+ },
66
+ },
67
+ {
68
+ version: 5,
69
+ apply: (db) => {
70
+ db.exec(V5_SCHEMA_FRAGMENT);
71
+ },
72
+ },
73
+ {
74
+ version: 6,
75
+ apply: (db) => {
76
+ db.exec(V6_SCHEMA_FRAGMENT);
77
+ },
78
+ requiresForeignKeyDisable: true,
79
+ },
80
+ {
81
+ version: 7,
82
+ apply: (db) => {
83
+ // Backfill the observed_json columns on rows written before
84
+ // `opaqueRegionCount` (opaque-content arc) and `externalImageCount`
85
+ // (this arc) were added. The schema-level repair is the
86
+ // companion to the runtime tolerant read; either one alone
87
+ // would fix this specific break, but treating the instance
88
+ // (`VerdictObservedSchema.optional()`) would leave the next
89
+ // counter addition to recur. Treating the boundary makes it
90
+ // durable.
91
+ db.exec(V7_SCHEMA_FRAGMENT);
92
+ },
93
+ },
94
+ {
95
+ version: 8,
96
+ apply: (db) => {
97
+ // Widens `revisions.artifact_type` to include `tsx`, adds
98
+ // `revisions.execution` (D2, backfilled to 'static'), and adds
99
+ // `render_runs.compiled_path` (D7, nullable for non-tsx runs
100
+ // and pre-arc rows). The v6 FK-safe rebuild pattern is reused
101
+ // because SQLite cannot alter a CHECK in place. Every prior
102
+ // column is copied explicitly so the schema shape stays
103
+ // traceable from the SQL alone.
104
+ db.exec(V8_SCHEMA_FRAGMENT);
105
+ },
106
+ requiresForeignKeyDisable: true,
107
+ },
108
+ {
109
+ version: CURRENT_STORAGE_VERSION,
110
+ apply: (db) => {
111
+ db.exec(V9_SCHEMA_FRAGMENT);
112
+ },
113
+ },
114
+ ];
115
+
116
+ export function runMigrations(db: Database, options: MigrationOptions = {}): void {
117
+ try {
118
+ db.exec(
119
+ "CREATE TABLE IF NOT EXISTS schema_migrations(version INTEGER PRIMARY KEY, applied_at TEXT NOT NULL)",
120
+ );
121
+ const applied = db
122
+ .query("SELECT version FROM schema_migrations ORDER BY version")
123
+ .all() as Array<{ version: number }>;
124
+ const appliedSet = new Set(applied.map((row) => row.version));
125
+ const foreignKeys = db.query("PRAGMA foreign_keys").get() as { foreign_keys: number };
126
+ // Gate the FK pragma toggle to steps that opt in via
127
+ // `requiresForeignKeyDisable`. v6 and v8 carry the flag (both
128
+ // rebuild a self-FK-bearing table via create-copy-drop-rename);
129
+ // a v9 that only adds columns inherits nothing. The restore
130
+ // below is unconditional on the FK state, regardless of the
131
+ // entry-point state — a connection that comes in with FKs OFF
132
+ // would otherwise be silently left OFF after migration, breaking
133
+ // the invariant every read path relies on. The row-level
134
+ // constraints the data depended on are re-validated by
135
+ // `PRAGMA foreign_key_check` from every read path.
136
+ const disableForeignKeys =
137
+ foreignKeys.foreign_keys === 1 &&
138
+ MIGRATION_STEPS.some(
139
+ (step) => !appliedSet.has(step.version) && step.requiresForeignKeyDisable === true,
140
+ );
141
+ if (disableForeignKeys) db.exec("PRAGMA foreign_keys = OFF");
142
+ const migrate = db.transaction(() => {
143
+ for (const step of MIGRATION_STEPS) {
144
+ if (appliedSet.has(step.version)) continue;
145
+ step.apply(db);
146
+ options.beforeRecordVersion?.(step.version);
147
+ db.query("INSERT INTO schema_migrations(version, applied_at) VALUES (?, ?)").run(
148
+ step.version,
149
+ new Date().toISOString(),
150
+ );
151
+ }
152
+ });
153
+ try {
154
+ migrate();
155
+ } finally {
156
+ // Always restore FKs to ON, regardless of the initial state.
157
+ // The restore is unconditional so a connection that arrived
158
+ // with FKs OFF (or a probe that disabled them mid-run) ends
159
+ // up with FKs ON, matching the openDatabase invariant.
160
+ db.exec("PRAGMA foreign_keys = ON");
161
+ }
162
+ } catch (error) {
163
+ const mapped = asStoreError(error);
164
+ if (mapped.code === "database_corrupt" || mapped.code === "database_busy") throw mapped;
165
+ throw new FacetStoreError("migration_failed", mapped.message, { cause: error });
166
+ }
167
+ }
@@ -0,0 +1,121 @@
1
+ import type { Database } from "bun:sqlite";
2
+
3
+ import { type Template, TemplateSchema } from "../../shared/contracts/artifact";
4
+ import { now } from "../../shared/util/time";
5
+ import { asStoreError, FacetStoreError } from "./database";
6
+
7
+ export interface TemplateInput {
8
+ readonly artifactId: string;
9
+ readonly revisionId: string;
10
+ readonly name: string;
11
+ readonly description?: string | null;
12
+ readonly promotedBy: string;
13
+ readonly promotedAt?: string;
14
+ }
15
+
16
+ export interface PromoteRevisionInput {
17
+ readonly artifactId?: string;
18
+ readonly revisionId: string;
19
+ readonly name: string;
20
+ readonly description?: string | null;
21
+ readonly promotedBy: string;
22
+ readonly promotedAt?: string;
23
+ }
24
+
25
+ export function evictRevisions(
26
+ db: Database,
27
+ artifactId: string,
28
+ protectedRevisionId?: string,
29
+ ): void {
30
+ while (true) {
31
+ const count = db
32
+ .query("SELECT COUNT(*) AS count FROM revisions WHERE artifact_id = ?")
33
+ .get(artifactId) as {
34
+ count: number;
35
+ };
36
+ if (count.count <= 50) return;
37
+ const candidate =
38
+ protectedRevisionId === undefined
39
+ ? (db
40
+ .query(
41
+ "SELECT id FROM revisions WHERE artifact_id = ? AND pinned = 0 AND NOT EXISTS (SELECT 1 FROM templates WHERE templates.revision_id = revisions.id) ORDER BY revision_number ASC LIMIT 1",
42
+ )
43
+ .get(artifactId) as { id: string } | null)
44
+ : (db
45
+ .query(
46
+ "SELECT id FROM revisions WHERE artifact_id = ? AND id <> ? AND pinned = 0 AND NOT EXISTS (SELECT 1 FROM templates WHERE templates.revision_id = revisions.id) ORDER BY revision_number ASC LIMIT 1",
47
+ )
48
+ .get(artifactId, protectedRevisionId) as { id: string } | null);
49
+ if (!candidate) {
50
+ throw new FacetStoreError(
51
+ "revision_capacity_pinned",
52
+ `Revision capacity is full for artifact ${artifactId}; all revisions are pinned or template-bound`,
53
+ );
54
+ }
55
+ db.query("UPDATE revisions SET parent_revision_id = NULL WHERE parent_revision_id = ?").run(
56
+ candidate.id,
57
+ );
58
+ db.query("DELETE FROM revisions WHERE id = ?").run(candidate.id);
59
+ }
60
+ }
61
+
62
+ export function promoteRevision(db: Database, input: PromoteRevisionInput): Template {
63
+ const owner = db
64
+ .query("SELECT artifact_id FROM revisions WHERE id = ?")
65
+ .get(input.revisionId) as { artifact_id: string } | null;
66
+ if (!owner) throw new FacetStoreError("foreign_key", `Revision not found: ${input.revisionId}`);
67
+ // The template table has independent foreign keys on artifact_id and
68
+ // revision_id, not a composite ownership constraint, so an explicit
69
+ // artifactId that disagrees with the revision's real owner would
70
+ // otherwise insert silently — instantiation would then copy the wrong
71
+ // artifact's bytes under the caller-supplied artifact's identity.
72
+ if (input.artifactId !== undefined && input.artifactId !== owner.artifact_id) {
73
+ throw new FacetStoreError(
74
+ "foreign_key",
75
+ `Revision ${input.revisionId} belongs to artifact ${owner.artifact_id}, not ${input.artifactId}`,
76
+ );
77
+ }
78
+ return createTemplate(db, { ...input, artifactId: owner.artifact_id });
79
+ }
80
+
81
+ export function createTemplate(db: Database, input: TemplateInput): Template {
82
+ const promotedAt = input.promotedAt ?? now();
83
+ const value = {
84
+ id: crypto.randomUUID(),
85
+ artifactId: input.artifactId,
86
+ revisionId: input.revisionId,
87
+ name: input.name,
88
+ description: input.description ?? null,
89
+ promotedBy: input.promotedBy,
90
+ promotedAt,
91
+ };
92
+ try {
93
+ db.query(
94
+ "INSERT INTO templates(id, artifact_id, revision_id, name, description, promoted_by, promoted_at) VALUES (?, ?, ?, ?, ?, ?, ?)",
95
+ ).run(
96
+ value.id,
97
+ value.artifactId,
98
+ value.revisionId,
99
+ value.name,
100
+ value.description,
101
+ value.promotedBy,
102
+ value.promotedAt,
103
+ );
104
+ return TemplateSchema.parse(value);
105
+ } catch (error) {
106
+ throw asStoreError(error);
107
+ }
108
+ }
109
+
110
+ export function pinRevision(db: Database, revisionId: string, pinned = true): void {
111
+ try {
112
+ const result = db
113
+ .query("UPDATE revisions SET pinned = ? WHERE id = ?")
114
+ .run(pinned ? 1 : 0, revisionId);
115
+ if (result.changes === 0) {
116
+ throw new FacetStoreError("foreign_key", `Revision not found: ${revisionId}`);
117
+ }
118
+ } catch (error) {
119
+ throw asStoreError(error);
120
+ }
121
+ }