@1agh/maude 1.0.11 → 1.3.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 (567) hide show
  1. package/README.md +3 -1
  2. package/apps/studio/acp/bridge.ts +18 -13
  3. package/apps/studio/acp/index.ts +43 -7
  4. package/apps/studio/acp/transcript-io.ts +394 -0
  5. package/apps/studio/acp/transcript.ts +103 -38
  6. package/apps/studio/annotations-layer.tsx +191 -116
  7. package/apps/studio/annotations-model.ts +39 -0
  8. package/apps/studio/annotations-sync.ts +50 -0
  9. package/apps/studio/api.ts +821 -55
  10. package/apps/studio/bin/_import-figma.mjs +57 -11
  11. package/apps/studio/bin/_seed-fixture.mjs +163 -0
  12. package/apps/studio/bin/annotate.mjs +3 -1
  13. package/apps/studio/bin/server-up.sh +17 -2
  14. package/apps/studio/canvas-edit.ts +391 -7
  15. package/apps/studio/canvas-imports.ts +89 -0
  16. package/apps/studio/canvas-lib.tsx +82 -18
  17. package/apps/studio/canvas-notice-message.ts +16 -0
  18. package/apps/studio/canvas-notifications.tsx +19 -0
  19. package/apps/studio/canvas-shell.tsx +57 -6
  20. package/apps/studio/client/app.jsx +943 -248
  21. package/apps/studio/client/apply-edit-request.ts +55 -0
  22. package/apps/studio/client/export-center.jsx +125 -67
  23. package/apps/studio/client/github.js +38 -1
  24. package/apps/studio/client/index-loader.ts +76 -0
  25. package/apps/studio/client/panels/CloudBar.jsx +52 -6
  26. package/apps/studio/client/panels/GitPanel.jsx +103 -0
  27. package/apps/studio/client/panels/OnboardingWizard.jsx +36 -7
  28. package/apps/studio/client/panels/RepoBranchSwitcher.jsx +92 -27
  29. package/apps/studio/client/panels/SourceConflictPanel.jsx +166 -0
  30. package/apps/studio/client/panels/SyncPanel.jsx +238 -4
  31. package/apps/studio/client/panels/TeamProjects.jsx +376 -0
  32. package/apps/studio/client/panels/file-deep-link-dialog.jsx +54 -0
  33. package/apps/studio/client/photo-knobs.jsx +3 -0
  34. package/apps/studio/client/report-bug.jsx +19 -1
  35. package/apps/studio/client/share-dialog.jsx +91 -0
  36. package/apps/studio/client/share-link.js +94 -0
  37. package/apps/studio/client/styles/3-shell-maude.css +69 -18
  38. package/apps/studio/client/styles/4-components.css +44 -1
  39. package/apps/studio/client/tree-row-menu.jsx +48 -3
  40. package/apps/studio/client/whats-new.jsx +26 -32
  41. package/apps/studio/cloud/endpoints.ts +132 -0
  42. package/apps/studio/collab/index.ts +4 -0
  43. package/apps/studio/collab/persistence.ts +137 -17
  44. package/apps/studio/collab/registry.ts +19 -21
  45. package/apps/studio/collab/room.ts +13 -2
  46. package/apps/studio/context.ts +59 -0
  47. package/apps/studio/debug-bundle.ts +13 -0
  48. package/apps/studio/dist/client.bundle.js +1911 -1879
  49. package/apps/studio/dist/runtime/.min-sizes.json +1 -0
  50. package/apps/studio/dist/runtime/sonner.js +1 -0
  51. package/apps/studio/dist/styles.css +1 -1
  52. package/apps/studio/export-dialog.tsx +54 -0
  53. package/apps/studio/exporters/degraded.ts +19 -3
  54. package/apps/studio/exporters/ghostscript.ts +194 -0
  55. package/apps/studio/exporters/pdf-fonts.ts +261 -0
  56. package/apps/studio/exporters/pdf.ts +152 -3
  57. package/apps/studio/exporters/remote.ts +36 -1
  58. package/apps/studio/fs-watch.ts +45 -1
  59. package/apps/studio/http.ts +296 -19
  60. package/apps/studio/inspect.ts +19 -0
  61. package/apps/studio/managed-projects.ts +150 -0
  62. package/apps/studio/mem.ts +45 -9
  63. package/apps/studio/notifications.tsx +292 -0
  64. package/apps/studio/runtime-bundle.ts +2 -0
  65. package/apps/studio/server.ts +69 -6
  66. package/apps/studio/sync/accepted-cold-start.ts +225 -0
  67. package/apps/studio/sync/accepted-link.ts +320 -0
  68. package/apps/studio/sync/action-stage.ts +343 -0
  69. package/apps/studio/sync/agent.ts +104 -45
  70. package/apps/studio/sync/asset-push.ts +1 -47
  71. package/apps/studio/sync/cell-file-events.ts +3 -0
  72. package/apps/studio/sync/codec.ts +192 -34
  73. package/apps/studio/sync/cold-start-apply.ts +7 -0
  74. package/apps/studio/sync/cold-start.ts +118 -22
  75. package/apps/studio/sync/comment-identity.ts +68 -0
  76. package/apps/studio/sync/connection-state.ts +15 -1
  77. package/apps/studio/sync/ctl-provider.ts +15 -2
  78. package/apps/studio/sync/document-discovery.ts +81 -0
  79. package/apps/studio/sync/file-ledger.ts +117 -0
  80. package/apps/studio/sync/file-membership.ts +10 -2
  81. package/apps/studio/sync/file-plane.ts +926 -47
  82. package/apps/studio/sync/index.ts +1786 -36
  83. package/apps/studio/sync/journal-client.ts +13 -1
  84. package/apps/studio/sync/migrate-seed.ts +150 -22
  85. package/apps/studio/sync/poke.ts +4 -2
  86. package/apps/studio/sync/presentation.ts +311 -5
  87. package/apps/studio/sync/projection.ts +820 -23
  88. package/apps/studio/sync/repeated-module.ts +73 -0
  89. package/apps/studio/sync/retry-after.ts +169 -0
  90. package/apps/studio/sync/revision-barrier.ts +129 -0
  91. package/apps/studio/sync/seed-progress.ts +218 -0
  92. package/apps/studio/sync/seed-repair.ts +46 -0
  93. package/apps/studio/sync/source-merge.ts +100 -0
  94. package/apps/studio/sync/source-ops.ts +289 -0
  95. package/apps/studio/sync/source-recovery.ts +70 -0
  96. package/apps/studio/sync/source-validation.ts +56 -0
  97. package/apps/studio/sync/status.ts +201 -6
  98. package/apps/studio/sync/transaction-client.ts +460 -0
  99. package/apps/studio/sync/transport-error.ts +111 -0
  100. package/apps/studio/sync/writer-registry.ts +236 -0
  101. package/apps/studio/text-caret.ts +35 -0
  102. package/apps/studio/undo-hud.tsx +9 -87
  103. package/apps/studio/use-canvas-media-drop.tsx +4 -39
  104. package/apps/studio/whats-new.json +173 -0
  105. package/cli/bin/maude.mjs +2 -0
  106. package/cli/commands/codex.mjs +191 -0
  107. package/cli/commands/harness.mjs +1051 -0
  108. package/cli/commands/help.mjs +13 -0
  109. package/cli/lib/design-link.mjs +190 -2
  110. package/cli/lib/harness/capabilities.mjs +302 -0
  111. package/cli/lib/harness/codex-runtime.mjs +892 -0
  112. package/cli/lib/harness/compatibility.mjs +27 -0
  113. package/cli/lib/harness/discover-claude.mjs +1393 -0
  114. package/cli/lib/harness/managed-state.mjs +1296 -0
  115. package/cli/lib/harness/model.mjs +86 -0
  116. package/cli/lib/harness/secrets.mjs +390 -0
  117. package/cli/lib/harness/targets/codex.mjs +1141 -0
  118. package/cli/lib/harness/targets/opencode.mjs +807 -0
  119. package/cli/lib/harness/transaction.mjs +1099 -0
  120. package/cli/lib/hubs-config.mjs +35 -8
  121. package/cli/templates/harness/opencode/maude-projector.ts +58 -0
  122. package/docs/harness-capability-matrix.md +125 -0
  123. package/docs/harness-environment-projection.md +95 -0
  124. package/package.json +33 -9
  125. package/plugins/design/dependencies.json +3 -3
  126. package/plugins/design/templates/_shell.html +47 -0
  127. package/plugins/flow/.claude-plugin/config.schema.json +8 -0
  128. package/plugins/flow/dependencies.json +3 -3
  129. package/apps/studio/.ai/cache/_stats.json +0 -7
  130. package/apps/studio/bin/_agent-browser-safe.test.mjs +0 -165
  131. package/apps/studio/bin/_curl-local.test.mjs +0 -280
  132. package/apps/studio/bin/_pw-launch.test.mjs +0 -90
  133. package/apps/studio/bin/_smart-frames.test.mjs +0 -195
  134. package/apps/studio/bin/_transcribe.test.mjs +0 -80
  135. package/apps/studio/bun.lock +0 -928
  136. package/apps/studio/draw/test/animate.test.ts +0 -172
  137. package/apps/studio/draw/test/brush.test.ts +0 -213
  138. package/apps/studio/draw/test/composition.test.ts +0 -141
  139. package/apps/studio/draw/test/geometry.test.ts +0 -199
  140. package/apps/studio/draw/test/gradient.test.ts +0 -167
  141. package/apps/studio/draw/test/layout.test.ts +0 -120
  142. package/apps/studio/draw/test/morph.test.ts +0 -107
  143. package/apps/studio/draw/test/optimize.test.ts +0 -40
  144. package/apps/studio/draw/test/palette.test.ts +0 -123
  145. package/apps/studio/draw/test/primitives.test.ts +0 -129
  146. package/apps/studio/draw/test/serialize-animate.test.ts +0 -142
  147. package/apps/studio/draw/test/serialize.test.ts +0 -105
  148. package/apps/studio/figma/assets.test.ts +0 -464
  149. package/apps/studio/figma/client.test.ts +0 -395
  150. package/apps/studio/figma/codegen-client.test.ts +0 -276
  151. package/apps/studio/figma/codegen-fonts.test.ts +0 -103
  152. package/apps/studio/figma/codegen-values.test.ts +0 -179
  153. package/apps/studio/figma/comments-to-strokes.test.ts +0 -194
  154. package/apps/studio/figma/fig-decode.test.ts +0 -788
  155. package/apps/studio/figma/fig-differential.test.ts +0 -182
  156. package/apps/studio/figma/fig-translator.test.ts +0 -192
  157. package/apps/studio/figma/fig-vector.test.ts +0 -113
  158. package/apps/studio/figma/from-codegen.test.ts +0 -408
  159. package/apps/studio/figma/sanitize.test.ts +0 -325
  160. package/apps/studio/figma/tailwind-map.test.ts +0 -142
  161. package/apps/studio/figma/to-artboard.test.ts +0 -808
  162. package/apps/studio/figma/to-render.test.ts +0 -180
  163. package/apps/studio/figma/to-strokes-roundtrip.test.ts +0 -152
  164. package/apps/studio/figma/to-strokes.test.ts +0 -705
  165. package/apps/studio/figma/to-tokens.test.ts +0 -321
  166. package/apps/studio/figma/url.test.ts +0 -167
  167. package/apps/studio/footage/schema.test.ts +0 -287
  168. package/apps/studio/generation/adapters/groq.test.ts +0 -80
  169. package/apps/studio/generation/audio-library.test.ts +0 -95
  170. package/apps/studio/generation/captions.test.ts +0 -78
  171. package/apps/studio/generation/elevenlabs.test.ts +0 -223
  172. package/apps/studio/generation/gemini.test.ts +0 -350
  173. package/apps/studio/generation/jobs.test.ts +0 -128
  174. package/apps/studio/generation/keys.test.ts +0 -75
  175. package/apps/studio/generation/prefs.test.ts +0 -95
  176. package/apps/studio/generation/types.test.ts +0 -123
  177. package/apps/studio/generation/whisper-models.test.ts +0 -179
  178. package/apps/studio/test/_helpers.ts +0 -108
  179. package/apps/studio/test/acp-activity-endpoint.test.ts +0 -183
  180. package/apps/studio/test/acp-activity.test.ts +0 -154
  181. package/apps/studio/test/acp-ai-activity.test.ts +0 -182
  182. package/apps/studio/test/acp-attachment-serve.test.ts +0 -74
  183. package/apps/studio/test/acp-bootstrap-brief.test.ts +0 -178
  184. package/apps/studio/test/acp-branch-guard.test.ts +0 -123
  185. package/apps/studio/test/acp-bridge-lifetime.test.ts +0 -475
  186. package/apps/studio/test/acp-bridge.test.ts +0 -545
  187. package/apps/studio/test/acp-capabilities.test.ts +0 -123
  188. package/apps/studio/test/acp-caps-bridge.test.ts +0 -279
  189. package/apps/studio/test/acp-commands.test.ts +0 -119
  190. package/apps/studio/test/acp-elicitation-bridge.test.ts +0 -480
  191. package/apps/studio/test/acp-elicitation.test.ts +0 -251
  192. package/apps/studio/test/acp-env.test.ts +0 -95
  193. package/apps/studio/test/acp-mode-banner.test.ts +0 -45
  194. package/apps/studio/test/acp-origin-gate.test.ts +0 -160
  195. package/apps/studio/test/acp-permission-prompt.test.ts +0 -251
  196. package/apps/studio/test/acp-permission.test.ts +0 -278
  197. package/apps/studio/test/acp-plugin-bootstrap.test.ts +0 -89
  198. package/apps/studio/test/acp-session-allowed-tools.test.ts +0 -235
  199. package/apps/studio/test/acp-session-plugins.test.ts +0 -209
  200. package/apps/studio/test/acp-toolgroup.test.ts +0 -76
  201. package/apps/studio/test/acp-transcript-view.test.ts +0 -71
  202. package/apps/studio/test/acp-transcript.test.ts +0 -238
  203. package/apps/studio/test/acp-usage-bridge.test.ts +0 -141
  204. package/apps/studio/test/acp-usage.test.ts +0 -143
  205. package/apps/studio/test/acp-write-gate.test.ts +0 -323
  206. package/apps/studio/test/acp-write-scope.test.ts +0 -533
  207. package/apps/studio/test/active-state.test.ts +0 -186
  208. package/apps/studio/test/activity.test.ts +0 -189
  209. package/apps/studio/test/ai-activity.test.ts +0 -113
  210. package/apps/studio/test/annotate-write.test.ts +0 -1074
  211. package/apps/studio/test/annotation-strokes-command.test.ts +0 -166
  212. package/apps/studio/test/annotations-align.test.ts +0 -88
  213. package/apps/studio/test/annotations-api.test.ts +0 -145
  214. package/apps/studio/test/annotations-bindings.test.ts +0 -262
  215. package/apps/studio/test/annotations-draw-modifiers.test.ts +0 -206
  216. package/apps/studio/test/annotations-groups.test.ts +0 -231
  217. package/apps/studio/test/annotations-layer.test.ts +0 -1011
  218. package/apps/studio/test/annotations-roundtrip.test.ts +0 -663
  219. package/apps/studio/test/annotations-snap.test.ts +0 -135
  220. package/apps/studio/test/annotations-text-format.test.ts +0 -396
  221. package/apps/studio/test/artboard-activity-overlay.test.tsx +0 -56
  222. package/apps/studio/test/artboard-guides-overlay.test.tsx +0 -152
  223. package/apps/studio/test/artboard-hug-commit.test.ts +0 -36
  224. package/apps/studio/test/artboard-kinds.test.tsx +0 -83
  225. package/apps/studio/test/artboard-selection-attrs.test.ts +0 -69
  226. package/apps/studio/test/asset-api.test.ts +0 -149
  227. package/apps/studio/test/assets-s3.test.ts +0 -249
  228. package/apps/studio/test/binary-smoke.test.ts +0 -47
  229. package/apps/studio/test/boot-self-heal.test.ts +0 -87
  230. package/apps/studio/test/browse-posture.test.tsx +0 -107
  231. package/apps/studio/test/bundle-smoke.test.ts +0 -46
  232. package/apps/studio/test/camera-reveal.test.tsx +0 -173
  233. package/apps/studio/test/canvas-artifacts.test.ts +0 -125
  234. package/apps/studio/test/canvas-build-sandbox.test.ts +0 -69
  235. package/apps/studio/test/canvas-build.test.ts +0 -141
  236. package/apps/studio/test/canvas-create-api.test.ts +0 -676
  237. package/apps/studio/test/canvas-cursors.test.ts +0 -164
  238. package/apps/studio/test/canvas-edit.test.ts +0 -470
  239. package/apps/studio/test/canvas-freshness-deps.test.ts +0 -64
  240. package/apps/studio/test/canvas-header.test.ts +0 -127
  241. package/apps/studio/test/canvas-hide-chrome.test.ts +0 -88
  242. package/apps/studio/test/canvas-hmr-runtime.test.tsx +0 -114
  243. package/apps/studio/test/canvas-lib-inline.test.ts +0 -146
  244. package/apps/studio/test/canvas-lib-motion.test.ts +0 -131
  245. package/apps/studio/test/canvas-lib-resolver.test.ts +0 -111
  246. package/apps/studio/test/canvas-list-watch.test.ts +0 -388
  247. package/apps/studio/test/canvas-media-drop.test.ts +0 -187
  248. package/apps/studio/test/canvas-meta-api.test.ts +0 -707
  249. package/apps/studio/test/canvas-move-api.test.ts +0 -587
  250. package/apps/studio/test/canvas-origin-gate.test.ts +0 -417
  251. package/apps/studio/test/canvas-pipeline.test.ts +0 -180
  252. package/apps/studio/test/canvas-rects.test.ts +0 -198
  253. package/apps/studio/test/canvas-reorder.test.ts +0 -211
  254. package/apps/studio/test/canvas-route.test.ts +0 -179
  255. package/apps/studio/test/canvas-shell-base.test.ts +0 -107
  256. package/apps/studio/test/canvas-shell-build-error.test.ts +0 -52
  257. package/apps/studio/test/canvas-url.test.ts +0 -138
  258. package/apps/studio/test/canvas-wheel-delta.test.ts +0 -42
  259. package/apps/studio/test/canvas-zoom-floor.test.ts +0 -73
  260. package/apps/studio/test/capture-core.test.ts +0 -32
  261. package/apps/studio/test/capture-determinism-shape.test.ts +0 -135
  262. package/apps/studio/test/chat-attachments.test.ts +0 -117
  263. package/apps/studio/test/chat-context.test.ts +0 -129
  264. package/apps/studio/test/chat-markdown.test.tsx +0 -58
  265. package/apps/studio/test/clip-addressing.test.ts +0 -738
  266. package/apps/studio/test/clip-ops.test.ts +0 -922
  267. package/apps/studio/test/cloud-build.test.ts +0 -95
  268. package/apps/studio/test/cloud-connect-note.test.ts +0 -135
  269. package/apps/studio/test/cloud-endpoints.test.ts +0 -590
  270. package/apps/studio/test/cloud-history-hardening.test.ts +0 -165
  271. package/apps/studio/test/cloud-history-posture.test.ts +0 -230
  272. package/apps/studio/test/cloud-managed-save-surfaces.test.ts +0 -90
  273. package/apps/studio/test/cloud-renew.test.ts +0 -205
  274. package/apps/studio/test/cloud-session-role.test.ts +0 -161
  275. package/apps/studio/test/cloud-shell-surfaces.test.ts +0 -170
  276. package/apps/studio/test/cold-start-apply.test.ts +0 -303
  277. package/apps/studio/test/collab-annotations-bridge.test.ts +0 -55
  278. package/apps/studio/test/collab-awareness-bridge.test.ts +0 -223
  279. package/apps/studio/test/collab-bridge.test.ts +0 -79
  280. package/apps/studio/test/collab-loopback.test.ts +0 -63
  281. package/apps/studio/test/collab-origin-gate.test.ts +0 -323
  282. package/apps/studio/test/collab-protocol.test.ts +0 -146
  283. package/apps/studio/test/collab-readonly-gate.test.ts +0 -194
  284. package/apps/studio/test/collab-reseed-guard.test.ts +0 -78
  285. package/apps/studio/test/collab-room.test.ts +0 -188
  286. package/apps/studio/test/collab-session-survival.test.tsx +0 -176
  287. package/apps/studio/test/collab-stress.test.ts +0 -129
  288. package/apps/studio/test/comment-mount.test.ts +0 -97
  289. package/apps/studio/test/comment-relay-origin-gate.test.ts +0 -117
  290. package/apps/studio/test/comments-api.test.ts +0 -277
  291. package/apps/studio/test/comments-fs-rebroadcast.test.ts +0 -155
  292. package/apps/studio/test/comments-overlay.test.ts +0 -117
  293. package/apps/studio/test/compile-entry.test.ts +0 -133
  294. package/apps/studio/test/component-map.test.ts +0 -48
  295. package/apps/studio/test/config-projection.test.ts +0 -104
  296. package/apps/studio/test/config-reload.test.ts +0 -230
  297. package/apps/studio/test/config-version.test.ts +0 -88
  298. package/apps/studio/test/context-resolve-tokens.test.ts +0 -97
  299. package/apps/studio/test/convert-to-absolute.test.ts +0 -333
  300. package/apps/studio/test/credential-grammar.test.ts +0 -107
  301. package/apps/studio/test/csp-canvas-shell.test.ts +0 -62
  302. package/apps/studio/test/csrf-write-guard.test.ts +0 -141
  303. package/apps/studio/test/debug-bundle.test.ts +0 -105
  304. package/apps/studio/test/design-setup-readiness.test.ts +0 -155
  305. package/apps/studio/test/detach-component.test.ts +0 -94
  306. package/apps/studio/test/dns-rebinding-guard.test.ts +0 -101
  307. package/apps/studio/test/dom-selection.test.ts +0 -198
  308. package/apps/studio/test/dynamic-text-edit.test.ts +0 -162
  309. package/apps/studio/test/edit-css-occurrence.test.ts +0 -81
  310. package/apps/studio/test/edit-persistence.test.ts +0 -91
  311. package/apps/studio/test/edit-scope-api.test.ts +0 -119
  312. package/apps/studio/test/edit-source-command.test.ts +0 -142
  313. package/apps/studio/test/edit-suppress.test.ts +0 -170
  314. package/apps/studio/test/editing-presence.test.ts +0 -103
  315. package/apps/studio/test/element-resize.test.ts +0 -136
  316. package/apps/studio/test/element-structural-api.test.ts +0 -434
  317. package/apps/studio/test/element-structural-edit.test.ts +0 -750
  318. package/apps/studio/test/ensure-browser.test.ts +0 -92
  319. package/apps/studio/test/equal-spacing-detector.test.ts +0 -257
  320. package/apps/studio/test/export-assemble.test.ts +0 -53
  321. package/apps/studio/test/export-browser-lane.test.ts +0 -126
  322. package/apps/studio/test/export-capture-fidelity.test.ts +0 -146
  323. package/apps/studio/test/export-capture-hygiene.test.ts +0 -675
  324. package/apps/studio/test/export-center.test.tsx +0 -287
  325. package/apps/studio/test/export-e2e-lanes.test.ts +0 -857
  326. package/apps/studio/test/export-format-scope-coherence.test.ts +0 -89
  327. package/apps/studio/test/export-lane.test.ts +0 -245
  328. package/apps/studio/test/export-shim-multi-capture.test.ts +0 -83
  329. package/apps/studio/test/exporters/canva.test.ts +0 -63
  330. package/apps/studio/test/exporters/degraded-propagation.test.ts +0 -123
  331. package/apps/studio/test/exporters/endpoint.test.ts +0 -121
  332. package/apps/studio/test/exporters/history.test.ts +0 -107
  333. package/apps/studio/test/exporters/html.test.ts +0 -26
  334. package/apps/studio/test/exporters/jobs.test.ts +0 -342
  335. package/apps/studio/test/exporters/pdf.test.ts +0 -85
  336. package/apps/studio/test/exporters/png.test.ts +0 -103
  337. package/apps/studio/test/exporters/pptx-deck.test.ts +0 -112
  338. package/apps/studio/test/exporters/pptx.test.ts +0 -31
  339. package/apps/studio/test/exporters/pw-launch.test.ts +0 -49
  340. package/apps/studio/test/exporters/runtime.test.ts +0 -59
  341. package/apps/studio/test/exporters/scope.test.ts +0 -292
  342. package/apps/studio/test/exporters/svg.test.ts +0 -29
  343. package/apps/studio/test/exporters/unsupported-media.test.ts +0 -123
  344. package/apps/studio/test/exporters/zip.test.ts +0 -104
  345. package/apps/studio/test/fetch-asset-gate.test.ts +0 -189
  346. package/apps/studio/test/figjam-v3-model.test.ts +0 -342
  347. package/apps/studio/test/figma-explode.test.ts +0 -438
  348. package/apps/studio/test/figma-provenance.test.ts +0 -108
  349. package/apps/studio/test/figma-routes.test.ts +0 -294
  350. package/apps/studio/test/file-lock.test.ts +0 -84
  351. package/apps/studio/test/fixtures/backgrounding-claude-auth.sh +0 -12
  352. package/apps/studio/test/fixtures/fake-claude-auth.mjs +0 -23
  353. package/apps/studio/test/fixtures/figjam-v3-groups-bindings.svg +0 -1
  354. package/apps/studio/test/fixtures/mock-acp-agent-caps.mjs +0 -158
  355. package/apps/studio/test/fixtures/mock-acp-agent-commands.mjs +0 -44
  356. package/apps/studio/test/fixtures/mock-acp-agent-elicit-flood.mjs +0 -46
  357. package/apps/studio/test/fixtures/mock-acp-agent-elicit-url.mjs +0 -42
  358. package/apps/studio/test/fixtures/mock-acp-agent-elicit.mjs +0 -63
  359. package/apps/studio/test/fixtures/mock-acp-agent-permission-flood.mjs +0 -51
  360. package/apps/studio/test/fixtures/mock-acp-agent-permission.mjs +0 -50
  361. package/apps/studio/test/fixtures/mock-acp-agent-slow.mjs +0 -45
  362. package/apps/studio/test/fixtures/mock-acp-agent-usage.mjs +0 -56
  363. package/apps/studio/test/fixtures/mock-acp-agent-wedged.mjs +0 -37
  364. package/apps/studio/test/fixtures/mock-acp-agent-write.mjs +0 -118
  365. package/apps/studio/test/fixtures/mock-acp-agent.mjs +0 -69
  366. package/apps/studio/test/fixtures/noisy-claude-auth.mjs +0 -27
  367. package/apps/studio/test/fixtures/perf-canvas.mjs +0 -201
  368. package/apps/studio/test/fixtures/phase-20-annotations.svg +0 -1
  369. package/apps/studio/test/fixtures/phase-21-annotations.svg +0 -1
  370. package/apps/studio/test/fixtures/tiny-subset.woff2 +0 -0
  371. package/apps/studio/test/fixtures/video-comp-fixture.tsx +0 -82
  372. package/apps/studio/test/fixtures/wedged-claude-auth.sh +0 -11
  373. package/apps/studio/test/footage-store.test.ts +0 -100
  374. package/apps/studio/test/fs-mkdir-api.test.ts +0 -248
  375. package/apps/studio/test/fs-watch.test.ts +0 -41
  376. package/apps/studio/test/gemma-models.test.ts +0 -245
  377. package/apps/studio/test/generate-route.test.ts +0 -106
  378. package/apps/studio/test/git-api.test.ts +0 -0
  379. package/apps/studio/test/git-branches.test.ts +0 -341
  380. package/apps/studio/test/git-cloud-posture.test.ts +0 -59
  381. package/apps/studio/test/git-grouping.test.ts +0 -106
  382. package/apps/studio/test/git-lifecycle.test.ts +0 -100
  383. package/apps/studio/test/git-log-format.test.ts +0 -95
  384. package/apps/studio/test/git-safe-rel.test.ts +0 -132
  385. package/apps/studio/test/git-system-engine.test.ts +0 -135
  386. package/apps/studio/test/git-watch.test.ts +0 -97
  387. package/apps/studio/test/github-api.test.ts +0 -577
  388. package/apps/studio/test/grid-track-handles.test.ts +0 -160
  389. package/apps/studio/test/handoff-static-frames.test.ts +0 -215
  390. package/apps/studio/test/handoff.test.ts +0 -329
  391. package/apps/studio/test/history-rollback.test.ts +0 -88
  392. package/apps/studio/test/hmr-broadcast.test.ts +0 -236
  393. package/apps/studio/test/hmr-classify.test.ts +0 -87
  394. package/apps/studio/test/hub-link.test.ts +0 -80
  395. package/apps/studio/test/identity-cache.test.ts +0 -83
  396. package/apps/studio/test/import-asset-browser.test.ts +0 -64
  397. package/apps/studio/test/import-asset-route.test.ts +0 -71
  398. package/apps/studio/test/import-asset.test.ts +0 -427
  399. package/apps/studio/test/import-brand-browser.test.ts +0 -88
  400. package/apps/studio/test/import-brand-route.test.ts +0 -120
  401. package/apps/studio/test/import-brand.test.ts +0 -206
  402. package/apps/studio/test/import-figma.test.ts +0 -667
  403. package/apps/studio/test/import-tokens.test.ts +0 -722
  404. package/apps/studio/test/index-data-canvas-ds.test.ts +0 -97
  405. package/apps/studio/test/input-router.test.ts +0 -757
  406. package/apps/studio/test/inspect-script-syntax.test.ts +0 -53
  407. package/apps/studio/test/inspect-selections.test.ts +0 -219
  408. package/apps/studio/test/knob-props-authored.test.ts +0 -87
  409. package/apps/studio/test/layers-synthetic-groups.test.ts +0 -96
  410. package/apps/studio/test/locator.test.ts +0 -214
  411. package/apps/studio/test/marquee-overlay.test.ts +0 -94
  412. package/apps/studio/test/media-commit-chain.test.ts +0 -210
  413. package/apps/studio/test/mode-toggle.test.tsx +0 -226
  414. package/apps/studio/test/motion-sample.test.ts +0 -35
  415. package/apps/studio/test/move-artboards-command.test.ts +0 -108
  416. package/apps/studio/test/participants-chrome.test.ts +0 -65
  417. package/apps/studio/test/paths.test.ts +0 -88
  418. package/apps/studio/test/pdf-print-boxes.test.ts +0 -359
  419. package/apps/studio/test/peer-selection-follows-camera.test.tsx +0 -131
  420. package/apps/studio/test/perf-harness.ts +0 -193
  421. package/apps/studio/test/phase-3.6-smoke.test.ts +0 -79
  422. package/apps/studio/test/photo-bg-remove-validation.test.ts +0 -71
  423. package/apps/studio/test/photo-canvas-bundle.test.ts +0 -79
  424. package/apps/studio/test/photo-edit-api.test.ts +0 -201
  425. package/apps/studio/test/photo-filters.test.ts +0 -149
  426. package/apps/studio/test/photo-pipeline.test.ts +0 -106
  427. package/apps/studio/test/photo-taxonomy.test.ts +0 -96
  428. package/apps/studio/test/print-marks.test.ts +0 -113
  429. package/apps/studio/test/print-units.test.ts +0 -173
  430. package/apps/studio/test/read-annotations.test.ts +0 -727
  431. package/apps/studio/test/read-only-gate.test.ts +0 -188
  432. package/apps/studio/test/read-only-role.test.ts +0 -95
  433. package/apps/studio/test/readiness.test.ts +0 -337
  434. package/apps/studio/test/remote-ahead-behind-cache.test.ts +0 -89
  435. package/apps/studio/test/reorder-api.test.ts +0 -210
  436. package/apps/studio/test/repo-concurrency.test.ts +0 -146
  437. package/apps/studio/test/repo-lock.test.ts +0 -350
  438. package/apps/studio/test/report-proxy.test.ts +0 -125
  439. package/apps/studio/test/ripple.test.ts +0 -197
  440. package/apps/studio/test/runtime-bundle-error-mapping.test.ts +0 -43
  441. package/apps/studio/test/runtime-bundle.test.ts +0 -69
  442. package/apps/studio/test/sanitize-annotation-svg.test.ts +0 -238
  443. package/apps/studio/test/scaffold-design.test.ts +0 -122
  444. package/apps/studio/test/server-lifecycle.test.ts +0 -38
  445. package/apps/studio/test/session-runtime-state.test.ts +0 -226
  446. package/apps/studio/test/session-scope.test.ts +0 -100
  447. package/apps/studio/test/shared-doc-cell-pairing.test.ts +0 -642
  448. package/apps/studio/test/shared-doc-convergence.test.ts +0 -265
  449. package/apps/studio/test/shared-doc-foundation.test.ts +0 -63
  450. package/apps/studio/test/shared-doc-migrate.test.ts +0 -369
  451. package/apps/studio/test/shared-doc-projection.test.ts +0 -238
  452. package/apps/studio/test/shell-importmap.test.ts +0 -56
  453. package/apps/studio/test/sizing-mode.test.ts +0 -102
  454. package/apps/studio/test/slash-commands.test.ts +0 -117
  455. package/apps/studio/test/snap-distance-pill.test.ts +0 -68
  456. package/apps/studio/test/spacing-handles.test.ts +0 -138
  457. package/apps/studio/test/specimen-select.test.ts +0 -88
  458. package/apps/studio/test/sync-agent.test.ts +0 -660
  459. package/apps/studio/test/sync-annotations-cold-start.test.ts +0 -302
  460. package/apps/studio/test/sync-asset-push.test.ts +0 -931
  461. package/apps/studio/test/sync-atomic-write.test.ts +0 -62
  462. package/apps/studio/test/sync-attach-incremental.test.ts +0 -527
  463. package/apps/studio/test/sync-autocommit.test.ts +0 -537
  464. package/apps/studio/test/sync-canvas-path.test.ts +0 -200
  465. package/apps/studio/test/sync-cell-write-nudge.test.ts +0 -346
  466. package/apps/studio/test/sync-codec.test.ts +0 -230
  467. package/apps/studio/test/sync-cold-seed-dedup.test.ts +0 -187
  468. package/apps/studio/test/sync-cold-start.test.ts +0 -304
  469. package/apps/studio/test/sync-connect-honesty.test.ts +0 -114
  470. package/apps/studio/test/sync-connection-state.test.ts +0 -337
  471. package/apps/studio/test/sync-ctl-channel.test.ts +0 -508
  472. package/apps/studio/test/sync-decide-file.test.ts +0 -420
  473. package/apps/studio/test/sync-doc-name.test.ts +0 -281
  474. package/apps/studio/test/sync-echo-guard.test.ts +0 -96
  475. package/apps/studio/test/sync-file-ledger.test.ts +0 -334
  476. package/apps/studio/test/sync-file-membership.test.ts +0 -347
  477. package/apps/studio/test/sync-file-plane.test.ts +0 -976
  478. package/apps/studio/test/sync-file-pull.test.ts +0 -333
  479. package/apps/studio/test/sync-fresh-link-parity.test.ts +0 -267
  480. package/apps/studio/test/sync-fs-mirror.test.ts +0 -181
  481. package/apps/studio/test/sync-hardening.test.ts +0 -586
  482. package/apps/studio/test/sync-hub-listing.test.ts +0 -46
  483. package/apps/studio/test/sync-hubs-config.test.ts +0 -133
  484. package/apps/studio/test/sync-incident-replay.test.ts +0 -211
  485. package/apps/studio/test/sync-journal.test.ts +0 -176
  486. package/apps/studio/test/sync-meta-codec.test.ts +0 -199
  487. package/apps/studio/test/sync-migrate-flat-fallback.test.ts +0 -98
  488. package/apps/studio/test/sync-move-retirement.test.ts +0 -231
  489. package/apps/studio/test/sync-panel-surface.test.ts +0 -153
  490. package/apps/studio/test/sync-path-pull.test.ts +0 -531
  491. package/apps/studio/test/sync-presentation.test.ts +0 -262
  492. package/apps/studio/test/sync-pull-budget.test.ts +0 -169
  493. package/apps/studio/test/sync-remote-docs.test.ts +0 -333
  494. package/apps/studio/test/sync-resync-routes.test.ts +0 -168
  495. package/apps/studio/test/sync-runtime.test.ts +0 -1675
  496. package/apps/studio/test/sync-seed-defers-to-hub.test.ts +0 -83
  497. package/apps/studio/test/sync-settings-routes.test.ts +0 -195
  498. package/apps/studio/test/sync-settings.test.ts +0 -151
  499. package/apps/studio/test/sync-status.test.ts +0 -261
  500. package/apps/studio/test/sync-supervisor.test.ts +0 -262
  501. package/apps/studio/test/sync-tombstone-apply.test.ts +0 -111
  502. package/apps/studio/test/sync-trash.test.ts +0 -132
  503. package/apps/studio/test/sync-two-peer-discovery.test.ts +0 -343
  504. package/apps/studio/test/sync-untrusted.test.ts +0 -103
  505. package/apps/studio/test/system-endpoint.test.ts +0 -144
  506. package/apps/studio/test/text-editability-stamp.test.ts +0 -131
  507. package/apps/studio/test/timeline-comp-target.test.ts +0 -139
  508. package/apps/studio/test/timeline-media-cache.test.ts +0 -41
  509. package/apps/studio/test/timeline-parse.test.ts +0 -184
  510. package/apps/studio/test/timeline-scale.test.ts +0 -65
  511. package/apps/studio/test/timeline-snap.test.ts +0 -85
  512. package/apps/studio/test/tool-palette-insert-anchor.test.ts +0 -86
  513. package/apps/studio/test/tool-palette.test.tsx +0 -55
  514. package/apps/studio/test/tour-overlay.test.tsx +0 -90
  515. package/apps/studio/test/trusted-request-host.test.ts +0 -66
  516. package/apps/studio/test/undo-sequence-byte-compare.test.ts +0 -211
  517. package/apps/studio/test/undo-stack.test.ts +0 -244
  518. package/apps/studio/test/use-agent-presence.test.tsx +0 -117
  519. package/apps/studio/test/use-annotation-resize.test.ts +0 -402
  520. package/apps/studio/test/use-annotation-selection.test.tsx +0 -77
  521. package/apps/studio/test/use-artboard-drag.test.ts +0 -324
  522. package/apps/studio/test/use-canvas-activity.test.tsx +0 -206
  523. package/apps/studio/test/use-collab.test.ts +0 -0
  524. package/apps/studio/test/use-cursor-modifiers.test.ts +0 -59
  525. package/apps/studio/test/use-keyboard-discipline.test.ts +0 -27
  526. package/apps/studio/test/use-selection-set.test.tsx +0 -166
  527. package/apps/studio/test/use-snap-guides.test.ts +0 -271
  528. package/apps/studio/test/use-tool-mode.test.tsx +0 -186
  529. package/apps/studio/test/use-undo-stack.test.tsx +0 -223
  530. package/apps/studio/test/video-asset.test.ts +0 -163
  531. package/apps/studio/test/video-comp-fixture.test.ts +0 -50
  532. package/apps/studio/test/video-comp.test.ts +0 -270
  533. package/apps/studio/test/video-encode-lib.test.ts +0 -63
  534. package/apps/studio/test/video-render-bridge.test.ts +0 -171
  535. package/apps/studio/test/whats-new.test.ts +0 -113
  536. package/apps/studio/test/whisper-setup.test.ts +0 -97
  537. package/apps/studio/test/workspace-containment.test.ts +0 -382
  538. package/apps/studio/test/workspace-signin.test.ts +0 -292
  539. package/apps/studio/test/ws-handshake.test.ts +0 -33
  540. package/cli/commands/cache.test.mjs +0 -166
  541. package/cli/commands/design-link.test.mjs +0 -419
  542. package/cli/commands/design.test.mjs +0 -240
  543. package/cli/commands/doctor.test.mjs +0 -237
  544. package/cli/commands/hub-workspace.test.mjs +0 -275
  545. package/cli/commands/hub.test.mjs +0 -225
  546. package/cli/commands/kg.test.mjs +0 -142
  547. package/cli/commands/preflight.test.mjs +0 -46
  548. package/cli/lib/argv.test.mjs +0 -46
  549. package/cli/lib/cache.test.mjs +0 -303
  550. package/cli/lib/cell-plan.test.mjs +0 -225
  551. package/cli/lib/config-lint.test.mjs +0 -117
  552. package/cli/lib/ddr-to-kgai.test.mjs +0 -118
  553. package/cli/lib/design-ownership.test.mjs +0 -329
  554. package/cli/lib/fetch-asset.test.mjs +0 -213
  555. package/cli/lib/figma-codegen-reachability.test.mjs +0 -104
  556. package/cli/lib/figma-import-controls.test.mjs +0 -70
  557. package/cli/lib/flow-design-integration.test.mjs +0 -165
  558. package/cli/lib/gitignore-block.test.mjs +0 -136
  559. package/cli/lib/gitignore-drift.test.mjs +0 -156
  560. package/cli/lib/hubs-config.test.mjs +0 -165
  561. package/cli/lib/pkg-root.test.mjs +0 -111
  562. package/cli/lib/plugin-cli-reachability.test.mjs +0 -57
  563. package/cli/lib/plugin-name-namespace.test.mjs +0 -71
  564. package/cli/lib/reconstruct-toolset.test.mjs +0 -194
  565. package/cli/lib/stack-detect.test.mjs +0 -121
  566. package/cli/lib/update-check.test.mjs +0 -32
  567. package/cli/lib/workspace-plan.test.mjs +0 -699
@@ -1,97 +0,0 @@
1
- // whisper-setup.test.ts — the subtitle stack's runtime detection and the `auto`
2
- // engine choice. Both exist to close the same gap the scout card had: the card
3
- // used to print `brew install whisper-cpp` unconditionally, never checked
4
- // whether the engine was there, and never adapted to the keys you'd set.
5
-
6
- import { describe, expect, test } from 'bun:test';
7
- import { resolveAutoEngine, whisperSetup } from '../generation/whisper-models.ts';
8
-
9
- describe('whisperSetup', () => {
10
- test('either installed with nothing to do, or a route to fix it', () => {
11
- const s = whisperSetup();
12
- if (s.installed) expect(s.options).toHaveLength(0);
13
- else expect(s.options.length).toBeGreaterThan(0);
14
- });
15
-
16
- test('every offered route is actionable as-is', () => {
17
- for (const o of whisperSetup().options)
18
- expect(o.kind === 'command' ? o.command : o.url).toBeTruthy();
19
- });
20
-
21
- test('a source-build route is always among the options when not installed', () => {
22
- const s = whisperSetup();
23
- if (!s.installed) expect(s.options.some((o) => o.id === 'source')).toBe(true);
24
- });
25
- });
26
-
27
- // DDR-164's rule is "no engine switch behind your back". `auto` keeps it by
28
- // being a SELECTED mode whose resolution is stated — these tests pin the
29
- // resolution itself, including the part that costs money.
30
- describe('resolveAutoEngine', () => {
31
- test('no keys → local whisper, and it says nothing leaves the machine', () => {
32
- const r = resolveAutoEngine([], true);
33
- expect(r.engine).toBe('whisper');
34
- expect(r.cloud).toBe(false);
35
- expect(r.reason).toContain('No cloud key');
36
- });
37
-
38
- test('an ElevenLabs key wins — Scribe beats a local base model', () => {
39
- const r = resolveAutoEngine(['elevenlabs'], true);
40
- expect(r.engine).toBe('elevenlabs');
41
- expect(r.cloud).toBe(true);
42
- });
43
-
44
- test('Groq is used when it is the only key', () => {
45
- expect(resolveAutoEngine(['groq'], true).engine).toBe('groq');
46
- });
47
-
48
- test('ElevenLabs outranks Groq when both keys are set', () => {
49
- expect(resolveAutoEngine(['groq', 'elevenlabs'], true).engine).toBe('elevenlabs');
50
- });
51
-
52
- test('an unrelated provider key never routes audio to the cloud', () => {
53
- // A Google key is for image generation — it must not drag transcription
54
- // off-machine.
55
- const r = resolveAutoEngine(['google'], true);
56
- expect(r.engine).toBe('whisper');
57
- expect(r.cloud).toBe(false);
58
- });
59
-
60
- test('a cloud resolution is always flagged as cloud (the billing/egress tell)', () => {
61
- for (const keys of [['elevenlabs'], ['groq']])
62
- expect(resolveAutoEngine(keys, true).cloud).toBe(true);
63
- });
64
-
65
- test('without the whisper binary it still resolves local, but says "once installed"', () => {
66
- const r = resolveAutoEngine([], false);
67
- expect(r.engine).toBe('whisper');
68
- expect(r.reason).toContain('once its binary is installed');
69
- });
70
- });
71
-
72
- // The server-side probe and the transcriber's own resolution MUST agree, or the
73
- // card claims an engine the CLI can't find. Same drift guard the scout has.
74
- describe('server ↔ CLI whisper resolution parity', () => {
75
- test('the same candidate names, and `main` is excluded in both', async () => {
76
- const cli = await import('../bin/_transcribe.mjs');
77
- const src = await Bun.file(`${import.meta.dir}/../bin/_transcribe.mjs`).text();
78
- const serverSrc = await Bun.file(`${import.meta.dir}/../generation/whisper-models.ts`).text();
79
- // Both probe whisper-cli then whisper, and neither probes the bare `main`
80
- // (executing a seeded `main` from `.` on $PATH was a security finding).
81
- for (const s of [src, serverSrc]) {
82
- expect(s).toContain("'whisper-cli'");
83
- expect(s).toContain("'whisper'");
84
- expect(s).not.toContain("'main'");
85
- }
86
- expect(typeof cli.resolveProvider).toBe('function');
87
- });
88
-
89
- test('both accept the same engine vocabulary incl. auto', async () => {
90
- const cli = await import('../bin/_transcribe.mjs');
91
- const { TRANSCRIPTION_PROVIDERS } = await import('../generation/prefs.ts');
92
- // resolveProvider rejects anything outside the vocabulary, so a value the
93
- // UI can persist must survive it.
94
- for (const p of TRANSCRIPTION_PROVIDERS)
95
- expect(cli.resolveProvider(p, '/nonexistent').provider).toBe(p);
96
- });
97
- });
@@ -1,382 +0,0 @@
1
- // Cloud Phase 3 — the containment invariant's boot-assert (DDR-193 §2).
2
- //
3
- // > No tenant-authored TSX is ever evaluated by vendor-operated compute.
4
- //
5
- // The thing being tested is a REFUSAL. So the tests that matter are the ones
6
- // that prove the gate fires: a cell exposing an export route, a canvas shell, a
7
- // runtime bundle, or shipping Playwright must not be able to start.
8
- //
9
- // The negative case matters just as much: none of this may fire outside
10
- // workspace mode, or every local dev-server stops booting.
11
-
12
- import { describe, expect, test } from 'bun:test';
13
-
14
- import {
15
- assertContainment,
16
- checkContainment,
17
- FORBIDDEN_MODULES,
18
- FORBIDDEN_ROUTE_PREFIXES,
19
- formatContainmentFailure,
20
- isForbiddenRoute,
21
- isSandboxedRoute,
22
- isWorkspaceMode,
23
- pruneForWorkspace,
24
- SANDBOXED_ROUTE_PREFIXES,
25
- } from '../workspace-mode.ts';
26
-
27
- const CELL = { MAUDE_WORKSPACE_MODE: '1' } as NodeJS.ProcessEnv;
28
- const LAPTOP = {} as NodeJS.ProcessEnv;
29
-
30
- /** The routes a cell legitimately serves: sync + git + assets, nothing else. */
31
- const ALLOWED_ROUTES = [
32
- '/_health',
33
- '/_api/asset',
34
- '/_api/comments',
35
- '/_api/annotations',
36
- '/_api/git-committers',
37
- '/_config',
38
- '/_ws',
39
- ];
40
-
41
- describe('workspace mode detection', () => {
42
- test('only MAUDE_WORKSPACE_MODE=1 turns it on', () => {
43
- expect(isWorkspaceMode(CELL)).toBe(true);
44
- expect(isWorkspaceMode(LAPTOP)).toBe(false);
45
- expect(isWorkspaceMode({ MAUDE_WORKSPACE_MODE: 'true' })).toBe(false);
46
- expect(isWorkspaceMode({ MAUDE_WORKSPACE_MODE: '0' })).toBe(false);
47
- expect(isWorkspaceMode({ MAUDE_WORKSPACE_MODE: '' })).toBe(false);
48
- });
49
- });
50
-
51
- describe('checkContainment — what a cell may serve', () => {
52
- test('sync + git + asset routes pass', () => {
53
- const report = checkContainment(ALLOWED_ROUTES);
54
- expect(report.ok).toBe(true);
55
- expect(report.routes).toEqual([]);
56
- expect(report.modules).toEqual([]);
57
- });
58
-
59
- test('every forbidden prefix is caught, and the reason travels with it', () => {
60
- for (const { prefix, why } of FORBIDDEN_ROUTE_PREFIXES) {
61
- const report = checkContainment([...ALLOWED_ROUTES, prefix]);
62
- expect(report.ok).toBe(false);
63
- expect(report.routes).toHaveLength(1);
64
- expect(report.routes[0]?.prefix).toBe(prefix);
65
- // The message has to teach, not just refuse — this is read by someone who
66
- // added a route in 2027 and has never heard of this invariant.
67
- expect(report.routes[0]?.why).toBe(why);
68
- expect(why.length).toBeGreaterThan(20);
69
- }
70
- });
71
-
72
- test('a VARIANT of a forbidden route is still forbidden', () => {
73
- // The realistic way this gets reintroduced: not `/_api/export` verbatim, but
74
- // a sibling that does the same thing under a new name. (`/_api/export-jobs`
75
- // moved OUT of this list when render-workers excepted it explicitly — an
76
- // except-listed exact path is a classified decision, not a variant.)
77
- for (const route of [
78
- '/_api/export/png',
79
- '/_api/export-jobs-v2',
80
- '/_api/github/repos',
81
- '/_api/claude/signin',
82
- '/_ws/acp',
83
- ]) {
84
- const report = checkContainment([...ALLOWED_ROUTES, route]);
85
- expect(report.ok).toBe(false);
86
- expect(report.routes[0]?.route).toBe(route);
87
- }
88
- });
89
-
90
- test('a route that merely CONTAINS a forbidden word is not a false positive', () => {
91
- // Prefix matching, not substring — `/_api/asset` must not trip on nothing,
92
- // and a route about exports in its docs must not be blocked by name alone.
93
- const report = checkContainment([
94
- '/_api/asset',
95
- '/_api/export-history-docs-link',
96
- '/_api/no-export',
97
- '/_api/git-export-status',
98
- ]);
99
- expect(report.routes.map((r) => r.route)).toEqual(['/_api/export-history-docs-link']);
100
- // ...that one DOES start with /_api/export, and being caught is correct:
101
- // a surface named "export-*" is exactly what needs a human to look at it.
102
- });
103
-
104
- test('a resolvable browser automation module fails the check', () => {
105
- const report = checkContainment(ALLOWED_ROUTES, {
106
- resolveModule: (s) => s === 'playwright',
107
- });
108
- expect(report.ok).toBe(false);
109
- expect(report.modules).toEqual(['playwright']);
110
- // All four are checked, not just the popular one.
111
- const all = checkContainment(ALLOWED_ROUTES, { resolveModule: () => true });
112
- expect(all.modules).toEqual([...FORBIDDEN_MODULES]);
113
- });
114
-
115
- test('no resolver supplied ⇒ modules are simply not checked (not silently passed)', () => {
116
- const report = checkContainment(ALLOWED_ROUTES);
117
- expect(report.modules).toEqual([]);
118
- });
119
- });
120
-
121
- describe('assertContainment — the boot gate', () => {
122
- test('OUTSIDE workspace mode it never fires, whatever is exposed', () => {
123
- // A developer's laptop serves every one of these. If the gate fired here,
124
- // the entire local product would stop booting.
125
- expect(() =>
126
- assertContainment([...ALLOWED_ROUTES, ...FORBIDDEN_ROUTE_PREFIXES.map((f) => f.prefix)], {
127
- env: LAPTOP,
128
- resolveModule: () => true,
129
- })
130
- ).not.toThrow();
131
- });
132
-
133
- test('in a cell, a clean route table starts', () => {
134
- expect(() => assertContainment(ALLOWED_ROUTES, { env: CELL })).not.toThrow();
135
- });
136
-
137
- test('in a cell, an export route REFUSES TO START', () => {
138
- expect(() => assertContainment([...ALLOWED_ROUTES, '/_api/export'], { env: CELL })).toThrow(
139
- /REFUSING TO START/
140
- );
141
- });
142
-
143
- test('in a cell, shipping Playwright REFUSES TO START even with clean routes', () => {
144
- expect(() =>
145
- assertContainment(ALLOWED_ROUTES, { env: CELL, resolveModule: (s) => s === 'playwright' })
146
- ).toThrow(/playwright/);
147
- });
148
-
149
- test('the failure message names the surface, the reason, and the way out', () => {
150
- let message = '';
151
- try {
152
- assertContainment([...ALLOWED_ROUTES, '/_api/export'], { env: CELL });
153
- } catch (err) {
154
- message = (err as Error).message;
155
- }
156
- expect(message).toContain('/_api/export');
157
- expect(message).toContain('DDR-193');
158
- expect(message).toContain('headless browser');
159
- // The escape hatch is named so the next engineer doesn't invent a flag.
160
- expect(message).toContain('Direction B');
161
- expect(message).toContain('HARD PREREQUISITE');
162
- });
163
-
164
- // ---- DDR-209 A′1: the sandboxed lane -----------------------------------
165
- //
166
- // `/_canvas-shell` and `/_canvas-runtime` used to be on the forbidden list.
167
- // They are not forbidden and they are not free: a cell may serve them ONLY
168
- // while the out-of-process build sandbox is armed. These three tests are the
169
- // difference between a reclassification and a loosening.
170
-
171
- test('a canvas surface is REFUSED when the build sandbox is not armed', () => {
172
- const report = checkContainment([...ALLOWED_ROUTES, '/_canvas-shell.html'], {
173
- sandboxArmed: false,
174
- });
175
- expect(report.ok).toBe(false);
176
- expect(report.unattested[0]?.route).toBe('/_canvas-shell.html');
177
- // And it is NOT reported as forbidden — the two failures have different
178
- // fixes, and collapsing them would send someone to delete a route that is
179
- // supposed to be there.
180
- expect(report.routes).toEqual([]);
181
- });
182
-
183
- test('a canvas surface is PERMITTED once the sandbox is armed', () => {
184
- const report = checkContainment(
185
- [...ALLOWED_ROUTES, '/_canvas-shell.html', '/_canvas-runtime/react.js'],
186
- { sandboxArmed: true }
187
- );
188
- expect(report.ok).toBe(true);
189
- });
190
-
191
- test('the attestation defaults to UNMET — an unstated contract is not a contract', () => {
192
- expect(checkContainment(['/_canvas-shell.html']).ok).toBe(false);
193
- });
194
-
195
- test('arming the sandbox does not permit anything on the FORBIDDEN list', () => {
196
- // The failure this rules out: `sandboxArmed: true` becoming a master key.
197
- const report = checkContainment([...ALLOWED_ROUTES, '/_api/export', '/_ws/acp'], {
198
- sandboxArmed: true,
199
- });
200
- expect(report.ok).toBe(false);
201
- expect(report.routes.map((r) => r.route).sort()).toEqual(['/_api/export', '/_ws/acp']);
202
- });
203
-
204
- test('the unattested message explains the contract rather than just refusing', () => {
205
- const message = formatContainmentFailure(
206
- checkContainment(['/_canvas-shell.html'], { sandboxArmed: false })
207
- );
208
- expect(message).toContain('BUILD SANDBOX is not armed');
209
- expect(message).toContain('EMPTY environment');
210
- expect(message).toContain('DDR-209');
211
- });
212
-
213
- test('formatContainmentFailure reports routes and modules together', () => {
214
- const report = checkContainment([...ALLOWED_ROUTES, '/_api/export'], {
215
- resolveModule: (s) => s === 'puppeteer',
216
- });
217
- const message = formatContainmentFailure(report);
218
- expect(message).toContain('/_api/export');
219
- expect(message).toContain('puppeteer');
220
- expect(message).toContain('Reachable routes');
221
- expect(message).toContain('Modules that resolve');
222
- });
223
- });
224
-
225
- describe('the vocabulary itself', () => {
226
- test('the forbidden set covers every way a cell could evaluate tenant code', () => {
227
- // Pinned deliberately: the realistic loss of this invariant is a refactor
228
- // quietly dropping an entry while every other test stays green. Changing
229
- // this list should require changing this test, on purpose.
230
- expect(FORBIDDEN_ROUTE_PREFIXES.map((f) => f.prefix).sort()).toEqual([
231
- // Surfaces that EVALUATE tenant content on our compute…
232
- '/_api/acp',
233
- '/_api/claude',
234
- '/_api/cloud',
235
- '/_api/debug-bundle',
236
- '/_api/design',
237
- '/_api/export',
238
- '/_api/figma',
239
- '/_api/generate',
240
- '/_api/github',
241
- '/_api/hub',
242
- // `/_api/photo-edit` left this list on purpose: it stores a validated
243
- // JSON sidecar and evaluates nothing — the decode happens in the
244
- // member's browser. Withholding it made photo edits unsavable in the
245
- // cloud. See workspace-mode.ts's header for the fuller account.
246
- // Spawns a headless browser against the studio — same evaluation as
247
- // `/_api/export`, and there is no browser in a cell image.
248
- '/_api/shell-shot',
249
- '/_ws/acp',
250
- ]);
251
- // …and the two that a cell SERVES, under an asserted contract (DDR-209 A′1).
252
- // They moved lists; they did not stop being checked. See the sandbox tests
253
- // above for what "under contract" is worth.
254
- expect(SANDBOXED_ROUTE_PREFIXES.map((f) => f.prefix).sort()).toEqual([
255
- '/_canvas-runtime',
256
- '/_canvas-shell',
257
- ]);
258
- // Nothing may be on both lists — that would make the weaker one decorative.
259
- const forbidden = new Set(FORBIDDEN_ROUTE_PREFIXES.map((f) => f.prefix));
260
- for (const { prefix } of SANDBOXED_ROUTE_PREFIXES) {
261
- expect(forbidden.has(prefix)).toBe(false);
262
- }
263
- expect([...FORBIDDEN_MODULES].sort()).toEqual([
264
- 'playwright',
265
- 'playwright-core',
266
- 'puppeteer',
267
- 'puppeteer-core',
268
- ]);
269
- });
270
- });
271
-
272
- describe('pruneForWorkspace — how a cell can boot at all', () => {
273
- test('keeps the sync/git/asset surface and removes exactly the forbidden one', () => {
274
- const table = {
275
- '/_health': 'h',
276
- '/_api/asset': 'a',
277
- '/_api/comments': 'c',
278
- '/_api/git-committers': 'g',
279
- '/_api/export': 'x',
280
- '/_api/export-jobs': 'x2',
281
- '/_api/photo-edit': 'p',
282
- '/_api/generate/keys': 'k',
283
- };
284
- const { routes, removed } = pruneForWorkspace(table);
285
-
286
- expect(Object.keys(routes).sort()).toEqual([
287
- '/_api/asset',
288
- '/_api/comments',
289
- // Kept since render-workers — the job lane enqueues/streams, it never
290
- // evaluates (the `except` escape on the `/_api/export` prefix).
291
- '/_api/export-jobs',
292
- '/_api/git-committers',
293
- // Kept since the unwithhold — a photo edit is a stored sidecar, and a
294
- // cell that cannot store it cannot save photo edits at all.
295
- '/_api/photo-edit',
296
- '/_health',
297
- ]);
298
- expect(removed).toEqual(['/_api/export', '/_api/generate/keys']);
299
- // Handlers are carried through by reference — pruning must not rebuild them.
300
- expect(routes['/_api/asset']).toBe('a');
301
- });
302
-
303
- test('the pruned table then PASSES the boot assert — prune and assert agree', () => {
304
- // This is the whole design: the assert is a post-condition on the pruning,
305
- // so a prefix added to the vocabulary both prunes and is verified, and the
306
- // two can never drift into disagreeing.
307
- const table = Object.fromEntries(
308
- [...FORBIDDEN_ROUTE_PREFIXES.map((f) => f.prefix), '/_health', '/_api/asset'].map((r) => [
309
- r,
310
- () => {},
311
- ])
312
- );
313
- const { routes } = pruneForWorkspace(table);
314
- expect(() => assertContainment(Object.keys(routes), { env: CELL })).not.toThrow();
315
- // ...and the unpruned table would have refused.
316
- expect(() => assertContainment(Object.keys(table), { env: CELL })).toThrow(/REFUSING TO START/);
317
- });
318
-
319
- test('the export JOB lane survives the prune; the synchronous render does not (render-workers)', () => {
320
- // feature-cloud-export-render-workers: enqueue/list/download evaluate
321
- // nothing — the render happens in the maude-render service (or refuses,
322
- // lane `none`). The synchronous `/_api/export` stays forbidden, and so
323
- // does any FUTURE `/_api/export-*` variant nobody has classified — the
324
- // escape is an explicit exact-path allowlist, not a loosened prefix.
325
- const table = {
326
- '/_api/export': 'x',
327
- '/_api/export-jobs': 'j',
328
- '/_api/export-jobs/download': 'd',
329
- '/_api/export-history': 'h',
330
- // DDR-231 — the browser lane's assemble half: pure data (client-captured
331
- // PNGs) → PptxGenJS in-cell; nothing evaluates, same class as zip.
332
- '/_api/export-assemble': 'a',
333
- // DDR-231 T7 — warm-up ping: proxies GET /_health to the render service
334
- // so the container wakes while the member is still picking options.
335
- '/_api/export-warmup': 'w',
336
- '/_api/export-next-phase-surprise': 'f',
337
- '/_health': 'ok',
338
- };
339
- const { routes, removed } = pruneForWorkspace(table);
340
- expect(Object.keys(routes).sort()).toEqual([
341
- '/_api/export-assemble',
342
- '/_api/export-history',
343
- '/_api/export-jobs',
344
- '/_api/export-jobs/download',
345
- '/_api/export-warmup',
346
- '/_health',
347
- ]);
348
- expect(removed).toEqual(['/_api/export', '/_api/export-next-phase-surprise']);
349
- // The single predicate agrees (the fetch fall-through gates on it too).
350
- expect(isForbiddenRoute('/_api/export')).toBe(true);
351
- expect(isForbiddenRoute('/_api/export-jobs')).toBe(false);
352
- expect(isForbiddenRoute('/_api/export-jobs/download')).toBe(false);
353
- expect(isForbiddenRoute('/_api/export-history')).toBe(false);
354
- expect(isForbiddenRoute('/_api/export-next-phase-surprise')).toBe(true);
355
- });
356
-
357
- test('pruning an already-clean table is a no-op', () => {
358
- const table = Object.fromEntries(ALLOWED_ROUTES.map((r) => [r, () => {}]));
359
- const { routes, removed } = pruneForWorkspace(table);
360
- expect(removed).toEqual([]);
361
- expect(Object.keys(routes).sort()).toEqual([...ALLOWED_ROUTES].sort());
362
- });
363
-
364
- test('isForbiddenRoute is the single predicate both the table and fetch use', () => {
365
- // The `fetch` fall-through owns `/_ws/acp`, which is not in the route table,
366
- // so it gates on this same function. One predicate, so the two gates cannot
367
- // disagree.
368
- expect(isForbiddenRoute('/_ws/acp')).toBe(true);
369
- expect(isForbiddenRoute('/_api/github/repos')).toBe(true);
370
- expect(isForbiddenRoute('/_ws')).toBe(false);
371
- expect(isForbiddenRoute('/_health')).toBe(false);
372
- expect(isForbiddenRoute('/_api/asset')).toBe(false);
373
- // DDR-209 A′1 — the canvas surfaces are NOT forbidden, which is exactly why
374
- // the fall-through stopped 404-ing them. `isSandboxedRoute` is where they
375
- // are now accounted for.
376
- expect(isForbiddenRoute('/_canvas-shell.html')).toBe(false);
377
- expect(isForbiddenRoute('/_canvas-runtime/react.js')).toBe(false);
378
- expect(isSandboxedRoute('/_canvas-shell.html')).toBe(true);
379
- expect(isSandboxedRoute('/_canvas-runtime/react.js')).toBe(true);
380
- expect(isSandboxedRoute('/_health')).toBe(false);
381
- });
382
- });