@1agh/maude 1.0.9 → 1.2.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 (506) hide show
  1. package/apps/studio/acp/bridge.ts +18 -13
  2. package/apps/studio/acp/probe.ts +268 -16
  3. package/apps/studio/acp/transcript-io.ts +394 -0
  4. package/apps/studio/acp/transcript.ts +103 -38
  5. package/apps/studio/api.ts +139 -26
  6. package/apps/studio/bin/_import-figma.mjs +57 -11
  7. package/apps/studio/bin/_seed-fixture.mjs +163 -0
  8. package/apps/studio/canvas-imports.ts +89 -0
  9. package/apps/studio/client/app.jsx +257 -7
  10. package/apps/studio/client/export-center.jsx +15 -7
  11. package/apps/studio/client/panels/ReadinessList.jsx +7 -1
  12. package/apps/studio/client/panels/SyncPanel.jsx +125 -4
  13. package/apps/studio/client/report-bug.jsx +19 -1
  14. package/apps/studio/client/styles/3-shell-maude.css +34 -0
  15. package/apps/studio/client/styles/4-components.css +26 -0
  16. package/apps/studio/collab/persistence.ts +132 -16
  17. package/apps/studio/collab/registry.ts +10 -18
  18. package/apps/studio/debug-bundle.ts +13 -0
  19. package/apps/studio/dist/client.bundle.js +1128 -1128
  20. package/apps/studio/dist/styles.css +1 -1
  21. package/apps/studio/export-dialog.tsx +54 -0
  22. package/apps/studio/exporters/degraded.ts +19 -3
  23. package/apps/studio/exporters/ghostscript.ts +194 -0
  24. package/apps/studio/exporters/pdf-fonts.ts +261 -0
  25. package/apps/studio/exporters/pdf.ts +152 -3
  26. package/apps/studio/exporters/remote.ts +36 -1
  27. package/apps/studio/fs-watch.ts +45 -1
  28. package/apps/studio/http.ts +7 -1
  29. package/apps/studio/mem.ts +45 -9
  30. package/apps/studio/readiness.ts +42 -7
  31. package/apps/studio/server.ts +11 -4
  32. package/apps/studio/sync/agent.ts +136 -29
  33. package/apps/studio/sync/asset-push.ts +1 -47
  34. package/apps/studio/sync/codec.ts +122 -31
  35. package/apps/studio/sync/cold-start-apply.ts +7 -0
  36. package/apps/studio/sync/cold-start.ts +118 -22
  37. package/apps/studio/sync/comment-identity.ts +68 -0
  38. package/apps/studio/sync/connection-state.ts +15 -1
  39. package/apps/studio/sync/file-ledger.ts +117 -0
  40. package/apps/studio/sync/file-plane.ts +623 -27
  41. package/apps/studio/sync/index.ts +711 -20
  42. package/apps/studio/sync/journal-client.ts +13 -1
  43. package/apps/studio/sync/migrate-seed.ts +40 -3
  44. package/apps/studio/sync/presentation.ts +26 -3
  45. package/apps/studio/sync/retry-after.ts +169 -0
  46. package/apps/studio/sync/seed-progress.ts +218 -0
  47. package/apps/studio/sync/status.ts +122 -5
  48. package/apps/studio/sync/transport-error.ts +111 -0
  49. package/apps/studio/whats-new.json +91 -0
  50. package/cli/bin/maude.mjs +2 -0
  51. package/cli/commands/codex.mjs +191 -0
  52. package/cli/commands/harness.mjs +1051 -0
  53. package/cli/commands/help.mjs +13 -0
  54. package/cli/lib/design-link.mjs +190 -2
  55. package/cli/lib/harness/capabilities.mjs +302 -0
  56. package/cli/lib/harness/codex-runtime.mjs +889 -0
  57. package/cli/lib/harness/compatibility.mjs +27 -0
  58. package/cli/lib/harness/discover-claude.mjs +1393 -0
  59. package/cli/lib/harness/managed-state.mjs +1296 -0
  60. package/cli/lib/harness/model.mjs +86 -0
  61. package/cli/lib/harness/secrets.mjs +390 -0
  62. package/cli/lib/harness/targets/codex.mjs +1141 -0
  63. package/cli/lib/harness/targets/opencode.mjs +807 -0
  64. package/cli/lib/harness/transaction.mjs +1099 -0
  65. package/cli/lib/hubs-config.mjs +35 -8
  66. package/cli/templates/harness/opencode/maude-projector.ts +58 -0
  67. package/docs/harness-capability-matrix.md +125 -0
  68. package/docs/harness-environment-projection.md +95 -0
  69. package/package.json +32 -9
  70. package/plugins/flow/.claude-plugin/config.schema.json +8 -0
  71. package/apps/studio/.ai/cache/_stats.json +0 -7
  72. package/apps/studio/bin/_agent-browser-safe.test.mjs +0 -165
  73. package/apps/studio/bin/_curl-local.test.mjs +0 -280
  74. package/apps/studio/bin/_pw-launch.test.mjs +0 -90
  75. package/apps/studio/bin/_smart-frames.test.mjs +0 -195
  76. package/apps/studio/bin/_transcribe.test.mjs +0 -80
  77. package/apps/studio/bun.lock +0 -928
  78. package/apps/studio/draw/test/animate.test.ts +0 -172
  79. package/apps/studio/draw/test/brush.test.ts +0 -213
  80. package/apps/studio/draw/test/composition.test.ts +0 -141
  81. package/apps/studio/draw/test/geometry.test.ts +0 -199
  82. package/apps/studio/draw/test/gradient.test.ts +0 -167
  83. package/apps/studio/draw/test/layout.test.ts +0 -120
  84. package/apps/studio/draw/test/morph.test.ts +0 -107
  85. package/apps/studio/draw/test/optimize.test.ts +0 -40
  86. package/apps/studio/draw/test/palette.test.ts +0 -123
  87. package/apps/studio/draw/test/primitives.test.ts +0 -129
  88. package/apps/studio/draw/test/serialize-animate.test.ts +0 -142
  89. package/apps/studio/draw/test/serialize.test.ts +0 -105
  90. package/apps/studio/figma/assets.test.ts +0 -464
  91. package/apps/studio/figma/client.test.ts +0 -395
  92. package/apps/studio/figma/codegen-client.test.ts +0 -276
  93. package/apps/studio/figma/codegen-fonts.test.ts +0 -103
  94. package/apps/studio/figma/codegen-values.test.ts +0 -179
  95. package/apps/studio/figma/comments-to-strokes.test.ts +0 -194
  96. package/apps/studio/figma/fig-decode.test.ts +0 -788
  97. package/apps/studio/figma/fig-differential.test.ts +0 -182
  98. package/apps/studio/figma/fig-translator.test.ts +0 -192
  99. package/apps/studio/figma/fig-vector.test.ts +0 -113
  100. package/apps/studio/figma/from-codegen.test.ts +0 -408
  101. package/apps/studio/figma/sanitize.test.ts +0 -325
  102. package/apps/studio/figma/tailwind-map.test.ts +0 -142
  103. package/apps/studio/figma/to-artboard.test.ts +0 -808
  104. package/apps/studio/figma/to-render.test.ts +0 -180
  105. package/apps/studio/figma/to-strokes-roundtrip.test.ts +0 -152
  106. package/apps/studio/figma/to-strokes.test.ts +0 -705
  107. package/apps/studio/figma/to-tokens.test.ts +0 -321
  108. package/apps/studio/figma/url.test.ts +0 -167
  109. package/apps/studio/footage/schema.test.ts +0 -287
  110. package/apps/studio/generation/adapters/groq.test.ts +0 -80
  111. package/apps/studio/generation/audio-library.test.ts +0 -95
  112. package/apps/studio/generation/captions.test.ts +0 -78
  113. package/apps/studio/generation/elevenlabs.test.ts +0 -223
  114. package/apps/studio/generation/gemini.test.ts +0 -350
  115. package/apps/studio/generation/jobs.test.ts +0 -128
  116. package/apps/studio/generation/keys.test.ts +0 -75
  117. package/apps/studio/generation/prefs.test.ts +0 -95
  118. package/apps/studio/generation/types.test.ts +0 -123
  119. package/apps/studio/generation/whisper-models.test.ts +0 -179
  120. package/apps/studio/test/_helpers.ts +0 -108
  121. package/apps/studio/test/acp-activity-endpoint.test.ts +0 -183
  122. package/apps/studio/test/acp-activity.test.ts +0 -154
  123. package/apps/studio/test/acp-ai-activity.test.ts +0 -182
  124. package/apps/studio/test/acp-attachment-serve.test.ts +0 -74
  125. package/apps/studio/test/acp-bootstrap-brief.test.ts +0 -178
  126. package/apps/studio/test/acp-branch-guard.test.ts +0 -123
  127. package/apps/studio/test/acp-bridge-lifetime.test.ts +0 -475
  128. package/apps/studio/test/acp-bridge.test.ts +0 -301
  129. package/apps/studio/test/acp-capabilities.test.ts +0 -123
  130. package/apps/studio/test/acp-caps-bridge.test.ts +0 -279
  131. package/apps/studio/test/acp-commands.test.ts +0 -119
  132. package/apps/studio/test/acp-elicitation-bridge.test.ts +0 -480
  133. package/apps/studio/test/acp-elicitation.test.ts +0 -251
  134. package/apps/studio/test/acp-env.test.ts +0 -95
  135. package/apps/studio/test/acp-mode-banner.test.ts +0 -45
  136. package/apps/studio/test/acp-origin-gate.test.ts +0 -160
  137. package/apps/studio/test/acp-permission-prompt.test.ts +0 -251
  138. package/apps/studio/test/acp-permission.test.ts +0 -278
  139. package/apps/studio/test/acp-plugin-bootstrap.test.ts +0 -89
  140. package/apps/studio/test/acp-session-allowed-tools.test.ts +0 -235
  141. package/apps/studio/test/acp-session-plugins.test.ts +0 -209
  142. package/apps/studio/test/acp-toolgroup.test.ts +0 -76
  143. package/apps/studio/test/acp-transcript-view.test.ts +0 -71
  144. package/apps/studio/test/acp-transcript.test.ts +0 -238
  145. package/apps/studio/test/acp-usage-bridge.test.ts +0 -141
  146. package/apps/studio/test/acp-usage.test.ts +0 -143
  147. package/apps/studio/test/acp-write-gate.test.ts +0 -323
  148. package/apps/studio/test/acp-write-scope.test.ts +0 -533
  149. package/apps/studio/test/active-state.test.ts +0 -186
  150. package/apps/studio/test/activity.test.ts +0 -189
  151. package/apps/studio/test/ai-activity.test.ts +0 -113
  152. package/apps/studio/test/annotate-write.test.ts +0 -1074
  153. package/apps/studio/test/annotation-strokes-command.test.ts +0 -166
  154. package/apps/studio/test/annotations-align.test.ts +0 -88
  155. package/apps/studio/test/annotations-api.test.ts +0 -145
  156. package/apps/studio/test/annotations-bindings.test.ts +0 -262
  157. package/apps/studio/test/annotations-draw-modifiers.test.ts +0 -206
  158. package/apps/studio/test/annotations-groups.test.ts +0 -231
  159. package/apps/studio/test/annotations-layer.test.ts +0 -1011
  160. package/apps/studio/test/annotations-roundtrip.test.ts +0 -663
  161. package/apps/studio/test/annotations-snap.test.ts +0 -135
  162. package/apps/studio/test/annotations-text-format.test.ts +0 -396
  163. package/apps/studio/test/artboard-activity-overlay.test.tsx +0 -56
  164. package/apps/studio/test/artboard-guides-overlay.test.tsx +0 -152
  165. package/apps/studio/test/artboard-hug-commit.test.ts +0 -36
  166. package/apps/studio/test/artboard-kinds.test.tsx +0 -83
  167. package/apps/studio/test/artboard-selection-attrs.test.ts +0 -69
  168. package/apps/studio/test/asset-api.test.ts +0 -149
  169. package/apps/studio/test/assets-s3.test.ts +0 -249
  170. package/apps/studio/test/binary-smoke.test.ts +0 -47
  171. package/apps/studio/test/boot-self-heal.test.ts +0 -87
  172. package/apps/studio/test/browse-posture.test.tsx +0 -107
  173. package/apps/studio/test/bundle-smoke.test.ts +0 -46
  174. package/apps/studio/test/camera-reveal.test.tsx +0 -173
  175. package/apps/studio/test/canvas-artifacts.test.ts +0 -125
  176. package/apps/studio/test/canvas-build-sandbox.test.ts +0 -69
  177. package/apps/studio/test/canvas-build.test.ts +0 -141
  178. package/apps/studio/test/canvas-create-api.test.ts +0 -676
  179. package/apps/studio/test/canvas-cursors.test.ts +0 -164
  180. package/apps/studio/test/canvas-edit.test.ts +0 -470
  181. package/apps/studio/test/canvas-freshness-deps.test.ts +0 -64
  182. package/apps/studio/test/canvas-header.test.ts +0 -127
  183. package/apps/studio/test/canvas-hide-chrome.test.ts +0 -88
  184. package/apps/studio/test/canvas-hmr-runtime.test.tsx +0 -114
  185. package/apps/studio/test/canvas-lib-inline.test.ts +0 -146
  186. package/apps/studio/test/canvas-lib-motion.test.ts +0 -131
  187. package/apps/studio/test/canvas-lib-resolver.test.ts +0 -111
  188. package/apps/studio/test/canvas-list-watch.test.ts +0 -388
  189. package/apps/studio/test/canvas-media-drop.test.ts +0 -187
  190. package/apps/studio/test/canvas-meta-api.test.ts +0 -707
  191. package/apps/studio/test/canvas-move-api.test.ts +0 -587
  192. package/apps/studio/test/canvas-origin-gate.test.ts +0 -417
  193. package/apps/studio/test/canvas-pipeline.test.ts +0 -180
  194. package/apps/studio/test/canvas-rects.test.ts +0 -198
  195. package/apps/studio/test/canvas-reorder.test.ts +0 -211
  196. package/apps/studio/test/canvas-route.test.ts +0 -179
  197. package/apps/studio/test/canvas-shell-base.test.ts +0 -107
  198. package/apps/studio/test/canvas-shell-build-error.test.ts +0 -52
  199. package/apps/studio/test/canvas-url.test.ts +0 -138
  200. package/apps/studio/test/canvas-wheel-delta.test.ts +0 -42
  201. package/apps/studio/test/canvas-zoom-floor.test.ts +0 -73
  202. package/apps/studio/test/capture-core.test.ts +0 -32
  203. package/apps/studio/test/capture-determinism-shape.test.ts +0 -135
  204. package/apps/studio/test/chat-attachments.test.ts +0 -117
  205. package/apps/studio/test/chat-context.test.ts +0 -129
  206. package/apps/studio/test/chat-markdown.test.tsx +0 -58
  207. package/apps/studio/test/clip-addressing.test.ts +0 -738
  208. package/apps/studio/test/clip-ops.test.ts +0 -922
  209. package/apps/studio/test/cloud-build.test.ts +0 -95
  210. package/apps/studio/test/cloud-connect-note.test.ts +0 -135
  211. package/apps/studio/test/cloud-endpoints.test.ts +0 -590
  212. package/apps/studio/test/cloud-history-hardening.test.ts +0 -165
  213. package/apps/studio/test/cloud-history-posture.test.ts +0 -230
  214. package/apps/studio/test/cloud-managed-save-surfaces.test.ts +0 -90
  215. package/apps/studio/test/cloud-renew.test.ts +0 -205
  216. package/apps/studio/test/cloud-session-role.test.ts +0 -161
  217. package/apps/studio/test/cloud-shell-surfaces.test.ts +0 -170
  218. package/apps/studio/test/cold-start-apply.test.ts +0 -303
  219. package/apps/studio/test/collab-annotations-bridge.test.ts +0 -55
  220. package/apps/studio/test/collab-awareness-bridge.test.ts +0 -223
  221. package/apps/studio/test/collab-bridge.test.ts +0 -79
  222. package/apps/studio/test/collab-loopback.test.ts +0 -63
  223. package/apps/studio/test/collab-origin-gate.test.ts +0 -323
  224. package/apps/studio/test/collab-protocol.test.ts +0 -146
  225. package/apps/studio/test/collab-readonly-gate.test.ts +0 -194
  226. package/apps/studio/test/collab-reseed-guard.test.ts +0 -78
  227. package/apps/studio/test/collab-room.test.ts +0 -188
  228. package/apps/studio/test/collab-session-survival.test.tsx +0 -176
  229. package/apps/studio/test/collab-stress.test.ts +0 -129
  230. package/apps/studio/test/comment-mount.test.ts +0 -97
  231. package/apps/studio/test/comment-relay-origin-gate.test.ts +0 -117
  232. package/apps/studio/test/comments-api.test.ts +0 -277
  233. package/apps/studio/test/comments-fs-rebroadcast.test.ts +0 -155
  234. package/apps/studio/test/comments-overlay.test.ts +0 -117
  235. package/apps/studio/test/compile-entry.test.ts +0 -133
  236. package/apps/studio/test/component-map.test.ts +0 -48
  237. package/apps/studio/test/config-projection.test.ts +0 -104
  238. package/apps/studio/test/config-reload.test.ts +0 -230
  239. package/apps/studio/test/config-version.test.ts +0 -88
  240. package/apps/studio/test/context-resolve-tokens.test.ts +0 -97
  241. package/apps/studio/test/convert-to-absolute.test.ts +0 -333
  242. package/apps/studio/test/credential-grammar.test.ts +0 -107
  243. package/apps/studio/test/csp-canvas-shell.test.ts +0 -62
  244. package/apps/studio/test/csrf-write-guard.test.ts +0 -141
  245. package/apps/studio/test/debug-bundle.test.ts +0 -105
  246. package/apps/studio/test/design-setup-readiness.test.ts +0 -155
  247. package/apps/studio/test/detach-component.test.ts +0 -94
  248. package/apps/studio/test/dns-rebinding-guard.test.ts +0 -101
  249. package/apps/studio/test/dom-selection.test.ts +0 -198
  250. package/apps/studio/test/dynamic-text-edit.test.ts +0 -162
  251. package/apps/studio/test/edit-css-occurrence.test.ts +0 -81
  252. package/apps/studio/test/edit-persistence.test.ts +0 -91
  253. package/apps/studio/test/edit-scope-api.test.ts +0 -119
  254. package/apps/studio/test/edit-source-command.test.ts +0 -142
  255. package/apps/studio/test/edit-suppress.test.ts +0 -170
  256. package/apps/studio/test/editing-presence.test.ts +0 -103
  257. package/apps/studio/test/element-resize.test.ts +0 -136
  258. package/apps/studio/test/element-structural-api.test.ts +0 -434
  259. package/apps/studio/test/element-structural-edit.test.ts +0 -750
  260. package/apps/studio/test/ensure-browser.test.ts +0 -92
  261. package/apps/studio/test/equal-spacing-detector.test.ts +0 -257
  262. package/apps/studio/test/export-assemble.test.ts +0 -53
  263. package/apps/studio/test/export-browser-lane.test.ts +0 -126
  264. package/apps/studio/test/export-capture-fidelity.test.ts +0 -146
  265. package/apps/studio/test/export-capture-hygiene.test.ts +0 -675
  266. package/apps/studio/test/export-center.test.tsx +0 -287
  267. package/apps/studio/test/export-e2e-lanes.test.ts +0 -857
  268. package/apps/studio/test/export-format-scope-coherence.test.ts +0 -89
  269. package/apps/studio/test/export-lane.test.ts +0 -245
  270. package/apps/studio/test/export-shim-multi-capture.test.ts +0 -83
  271. package/apps/studio/test/exporters/canva.test.ts +0 -63
  272. package/apps/studio/test/exporters/degraded-propagation.test.ts +0 -123
  273. package/apps/studio/test/exporters/endpoint.test.ts +0 -121
  274. package/apps/studio/test/exporters/history.test.ts +0 -107
  275. package/apps/studio/test/exporters/html.test.ts +0 -26
  276. package/apps/studio/test/exporters/jobs.test.ts +0 -342
  277. package/apps/studio/test/exporters/pdf.test.ts +0 -85
  278. package/apps/studio/test/exporters/png.test.ts +0 -103
  279. package/apps/studio/test/exporters/pptx-deck.test.ts +0 -112
  280. package/apps/studio/test/exporters/pptx.test.ts +0 -31
  281. package/apps/studio/test/exporters/pw-launch.test.ts +0 -49
  282. package/apps/studio/test/exporters/runtime.test.ts +0 -59
  283. package/apps/studio/test/exporters/scope.test.ts +0 -292
  284. package/apps/studio/test/exporters/svg.test.ts +0 -29
  285. package/apps/studio/test/exporters/unsupported-media.test.ts +0 -123
  286. package/apps/studio/test/exporters/zip.test.ts +0 -104
  287. package/apps/studio/test/fetch-asset-gate.test.ts +0 -189
  288. package/apps/studio/test/figjam-v3-model.test.ts +0 -342
  289. package/apps/studio/test/figma-explode.test.ts +0 -438
  290. package/apps/studio/test/figma-provenance.test.ts +0 -108
  291. package/apps/studio/test/figma-routes.test.ts +0 -294
  292. package/apps/studio/test/file-lock.test.ts +0 -84
  293. package/apps/studio/test/fixtures/fake-claude-auth.mjs +0 -13
  294. package/apps/studio/test/fixtures/figjam-v3-groups-bindings.svg +0 -1
  295. package/apps/studio/test/fixtures/mock-acp-agent-caps.mjs +0 -158
  296. package/apps/studio/test/fixtures/mock-acp-agent-commands.mjs +0 -44
  297. package/apps/studio/test/fixtures/mock-acp-agent-elicit-flood.mjs +0 -46
  298. package/apps/studio/test/fixtures/mock-acp-agent-elicit-url.mjs +0 -42
  299. package/apps/studio/test/fixtures/mock-acp-agent-elicit.mjs +0 -63
  300. package/apps/studio/test/fixtures/mock-acp-agent-permission-flood.mjs +0 -51
  301. package/apps/studio/test/fixtures/mock-acp-agent-permission.mjs +0 -50
  302. package/apps/studio/test/fixtures/mock-acp-agent-slow.mjs +0 -45
  303. package/apps/studio/test/fixtures/mock-acp-agent-usage.mjs +0 -56
  304. package/apps/studio/test/fixtures/mock-acp-agent-wedged.mjs +0 -37
  305. package/apps/studio/test/fixtures/mock-acp-agent-write.mjs +0 -118
  306. package/apps/studio/test/fixtures/mock-acp-agent.mjs +0 -69
  307. package/apps/studio/test/fixtures/perf-canvas.mjs +0 -201
  308. package/apps/studio/test/fixtures/phase-20-annotations.svg +0 -1
  309. package/apps/studio/test/fixtures/phase-21-annotations.svg +0 -1
  310. package/apps/studio/test/fixtures/tiny-subset.woff2 +0 -0
  311. package/apps/studio/test/fixtures/video-comp-fixture.tsx +0 -82
  312. package/apps/studio/test/footage-store.test.ts +0 -100
  313. package/apps/studio/test/fs-mkdir-api.test.ts +0 -248
  314. package/apps/studio/test/fs-watch.test.ts +0 -41
  315. package/apps/studio/test/gemma-models.test.ts +0 -245
  316. package/apps/studio/test/generate-route.test.ts +0 -106
  317. package/apps/studio/test/git-api.test.ts +0 -0
  318. package/apps/studio/test/git-branches.test.ts +0 -341
  319. package/apps/studio/test/git-cloud-posture.test.ts +0 -59
  320. package/apps/studio/test/git-grouping.test.ts +0 -106
  321. package/apps/studio/test/git-lifecycle.test.ts +0 -100
  322. package/apps/studio/test/git-log-format.test.ts +0 -95
  323. package/apps/studio/test/git-safe-rel.test.ts +0 -132
  324. package/apps/studio/test/git-system-engine.test.ts +0 -135
  325. package/apps/studio/test/git-watch.test.ts +0 -97
  326. package/apps/studio/test/github-api.test.ts +0 -577
  327. package/apps/studio/test/grid-track-handles.test.ts +0 -160
  328. package/apps/studio/test/handoff-static-frames.test.ts +0 -215
  329. package/apps/studio/test/handoff.test.ts +0 -329
  330. package/apps/studio/test/history-rollback.test.ts +0 -88
  331. package/apps/studio/test/hmr-broadcast.test.ts +0 -236
  332. package/apps/studio/test/hmr-classify.test.ts +0 -87
  333. package/apps/studio/test/hub-link.test.ts +0 -80
  334. package/apps/studio/test/identity-cache.test.ts +0 -83
  335. package/apps/studio/test/import-asset-browser.test.ts +0 -64
  336. package/apps/studio/test/import-asset-route.test.ts +0 -71
  337. package/apps/studio/test/import-asset.test.ts +0 -427
  338. package/apps/studio/test/import-brand-browser.test.ts +0 -88
  339. package/apps/studio/test/import-brand-route.test.ts +0 -120
  340. package/apps/studio/test/import-brand.test.ts +0 -206
  341. package/apps/studio/test/import-figma.test.ts +0 -667
  342. package/apps/studio/test/import-tokens.test.ts +0 -722
  343. package/apps/studio/test/index-data-canvas-ds.test.ts +0 -97
  344. package/apps/studio/test/input-router.test.ts +0 -757
  345. package/apps/studio/test/inspect-script-syntax.test.ts +0 -53
  346. package/apps/studio/test/inspect-selections.test.ts +0 -219
  347. package/apps/studio/test/knob-props-authored.test.ts +0 -87
  348. package/apps/studio/test/layers-synthetic-groups.test.ts +0 -96
  349. package/apps/studio/test/locator.test.ts +0 -214
  350. package/apps/studio/test/marquee-overlay.test.ts +0 -94
  351. package/apps/studio/test/media-commit-chain.test.ts +0 -210
  352. package/apps/studio/test/mode-toggle.test.tsx +0 -226
  353. package/apps/studio/test/motion-sample.test.ts +0 -35
  354. package/apps/studio/test/move-artboards-command.test.ts +0 -108
  355. package/apps/studio/test/participants-chrome.test.ts +0 -65
  356. package/apps/studio/test/paths.test.ts +0 -88
  357. package/apps/studio/test/pdf-print-boxes.test.ts +0 -359
  358. package/apps/studio/test/peer-selection-follows-camera.test.tsx +0 -131
  359. package/apps/studio/test/perf-harness.ts +0 -193
  360. package/apps/studio/test/phase-3.6-smoke.test.ts +0 -79
  361. package/apps/studio/test/photo-bg-remove-validation.test.ts +0 -71
  362. package/apps/studio/test/photo-canvas-bundle.test.ts +0 -79
  363. package/apps/studio/test/photo-edit-api.test.ts +0 -201
  364. package/apps/studio/test/photo-filters.test.ts +0 -149
  365. package/apps/studio/test/photo-pipeline.test.ts +0 -106
  366. package/apps/studio/test/photo-taxonomy.test.ts +0 -96
  367. package/apps/studio/test/print-marks.test.ts +0 -113
  368. package/apps/studio/test/print-units.test.ts +0 -173
  369. package/apps/studio/test/read-annotations.test.ts +0 -727
  370. package/apps/studio/test/read-only-gate.test.ts +0 -188
  371. package/apps/studio/test/read-only-role.test.ts +0 -95
  372. package/apps/studio/test/readiness.test.ts +0 -226
  373. package/apps/studio/test/remote-ahead-behind-cache.test.ts +0 -89
  374. package/apps/studio/test/reorder-api.test.ts +0 -210
  375. package/apps/studio/test/repo-concurrency.test.ts +0 -146
  376. package/apps/studio/test/repo-lock.test.ts +0 -350
  377. package/apps/studio/test/report-proxy.test.ts +0 -125
  378. package/apps/studio/test/ripple.test.ts +0 -197
  379. package/apps/studio/test/runtime-bundle-error-mapping.test.ts +0 -43
  380. package/apps/studio/test/runtime-bundle.test.ts +0 -69
  381. package/apps/studio/test/sanitize-annotation-svg.test.ts +0 -238
  382. package/apps/studio/test/scaffold-design.test.ts +0 -122
  383. package/apps/studio/test/server-lifecycle.test.ts +0 -38
  384. package/apps/studio/test/session-runtime-state.test.ts +0 -226
  385. package/apps/studio/test/session-scope.test.ts +0 -100
  386. package/apps/studio/test/shared-doc-cell-pairing.test.ts +0 -642
  387. package/apps/studio/test/shared-doc-convergence.test.ts +0 -265
  388. package/apps/studio/test/shared-doc-foundation.test.ts +0 -63
  389. package/apps/studio/test/shared-doc-migrate.test.ts +0 -369
  390. package/apps/studio/test/shared-doc-projection.test.ts +0 -238
  391. package/apps/studio/test/shell-importmap.test.ts +0 -56
  392. package/apps/studio/test/sizing-mode.test.ts +0 -102
  393. package/apps/studio/test/slash-commands.test.ts +0 -117
  394. package/apps/studio/test/snap-distance-pill.test.ts +0 -68
  395. package/apps/studio/test/spacing-handles.test.ts +0 -138
  396. package/apps/studio/test/specimen-select.test.ts +0 -88
  397. package/apps/studio/test/sync-agent.test.ts +0 -660
  398. package/apps/studio/test/sync-annotations-cold-start.test.ts +0 -302
  399. package/apps/studio/test/sync-asset-push.test.ts +0 -931
  400. package/apps/studio/test/sync-atomic-write.test.ts +0 -62
  401. package/apps/studio/test/sync-attach-incremental.test.ts +0 -527
  402. package/apps/studio/test/sync-autocommit.test.ts +0 -537
  403. package/apps/studio/test/sync-canvas-path.test.ts +0 -200
  404. package/apps/studio/test/sync-cell-write-nudge.test.ts +0 -346
  405. package/apps/studio/test/sync-codec.test.ts +0 -230
  406. package/apps/studio/test/sync-cold-seed-dedup.test.ts +0 -187
  407. package/apps/studio/test/sync-cold-start.test.ts +0 -304
  408. package/apps/studio/test/sync-connect-honesty.test.ts +0 -114
  409. package/apps/studio/test/sync-connection-state.test.ts +0 -337
  410. package/apps/studio/test/sync-ctl-channel.test.ts +0 -508
  411. package/apps/studio/test/sync-decide-file.test.ts +0 -420
  412. package/apps/studio/test/sync-doc-name.test.ts +0 -281
  413. package/apps/studio/test/sync-echo-guard.test.ts +0 -96
  414. package/apps/studio/test/sync-file-ledger.test.ts +0 -334
  415. package/apps/studio/test/sync-file-membership.test.ts +0 -347
  416. package/apps/studio/test/sync-file-plane.test.ts +0 -976
  417. package/apps/studio/test/sync-file-pull.test.ts +0 -333
  418. package/apps/studio/test/sync-fresh-link-parity.test.ts +0 -267
  419. package/apps/studio/test/sync-fs-mirror.test.ts +0 -181
  420. package/apps/studio/test/sync-hardening.test.ts +0 -586
  421. package/apps/studio/test/sync-hub-listing.test.ts +0 -46
  422. package/apps/studio/test/sync-hubs-config.test.ts +0 -133
  423. package/apps/studio/test/sync-incident-replay.test.ts +0 -211
  424. package/apps/studio/test/sync-journal.test.ts +0 -176
  425. package/apps/studio/test/sync-meta-codec.test.ts +0 -199
  426. package/apps/studio/test/sync-migrate-flat-fallback.test.ts +0 -98
  427. package/apps/studio/test/sync-move-retirement.test.ts +0 -231
  428. package/apps/studio/test/sync-panel-surface.test.ts +0 -153
  429. package/apps/studio/test/sync-path-pull.test.ts +0 -531
  430. package/apps/studio/test/sync-presentation.test.ts +0 -262
  431. package/apps/studio/test/sync-pull-budget.test.ts +0 -169
  432. package/apps/studio/test/sync-remote-docs.test.ts +0 -333
  433. package/apps/studio/test/sync-resync-routes.test.ts +0 -168
  434. package/apps/studio/test/sync-runtime.test.ts +0 -1675
  435. package/apps/studio/test/sync-seed-defers-to-hub.test.ts +0 -83
  436. package/apps/studio/test/sync-settings-routes.test.ts +0 -195
  437. package/apps/studio/test/sync-settings.test.ts +0 -151
  438. package/apps/studio/test/sync-status.test.ts +0 -261
  439. package/apps/studio/test/sync-supervisor.test.ts +0 -262
  440. package/apps/studio/test/sync-tombstone-apply.test.ts +0 -111
  441. package/apps/studio/test/sync-trash.test.ts +0 -132
  442. package/apps/studio/test/sync-two-peer-discovery.test.ts +0 -343
  443. package/apps/studio/test/sync-untrusted.test.ts +0 -103
  444. package/apps/studio/test/system-endpoint.test.ts +0 -144
  445. package/apps/studio/test/text-editability-stamp.test.ts +0 -131
  446. package/apps/studio/test/timeline-comp-target.test.ts +0 -139
  447. package/apps/studio/test/timeline-media-cache.test.ts +0 -41
  448. package/apps/studio/test/timeline-parse.test.ts +0 -184
  449. package/apps/studio/test/timeline-scale.test.ts +0 -65
  450. package/apps/studio/test/timeline-snap.test.ts +0 -85
  451. package/apps/studio/test/tool-palette-insert-anchor.test.ts +0 -86
  452. package/apps/studio/test/tool-palette.test.tsx +0 -55
  453. package/apps/studio/test/tour-overlay.test.tsx +0 -90
  454. package/apps/studio/test/trusted-request-host.test.ts +0 -66
  455. package/apps/studio/test/undo-sequence-byte-compare.test.ts +0 -211
  456. package/apps/studio/test/undo-stack.test.ts +0 -244
  457. package/apps/studio/test/use-agent-presence.test.tsx +0 -117
  458. package/apps/studio/test/use-annotation-resize.test.ts +0 -402
  459. package/apps/studio/test/use-annotation-selection.test.tsx +0 -77
  460. package/apps/studio/test/use-artboard-drag.test.ts +0 -324
  461. package/apps/studio/test/use-canvas-activity.test.tsx +0 -206
  462. package/apps/studio/test/use-collab.test.ts +0 -0
  463. package/apps/studio/test/use-cursor-modifiers.test.ts +0 -59
  464. package/apps/studio/test/use-keyboard-discipline.test.ts +0 -27
  465. package/apps/studio/test/use-selection-set.test.tsx +0 -166
  466. package/apps/studio/test/use-snap-guides.test.ts +0 -271
  467. package/apps/studio/test/use-tool-mode.test.tsx +0 -186
  468. package/apps/studio/test/use-undo-stack.test.tsx +0 -223
  469. package/apps/studio/test/video-asset.test.ts +0 -163
  470. package/apps/studio/test/video-comp-fixture.test.ts +0 -50
  471. package/apps/studio/test/video-comp.test.ts +0 -270
  472. package/apps/studio/test/video-encode-lib.test.ts +0 -63
  473. package/apps/studio/test/video-render-bridge.test.ts +0 -171
  474. package/apps/studio/test/whats-new.test.ts +0 -113
  475. package/apps/studio/test/whisper-setup.test.ts +0 -97
  476. package/apps/studio/test/workspace-containment.test.ts +0 -382
  477. package/apps/studio/test/workspace-signin.test.ts +0 -292
  478. package/apps/studio/test/ws-handshake.test.ts +0 -33
  479. package/cli/commands/cache.test.mjs +0 -166
  480. package/cli/commands/design-link.test.mjs +0 -419
  481. package/cli/commands/design.test.mjs +0 -240
  482. package/cli/commands/doctor.test.mjs +0 -237
  483. package/cli/commands/hub-workspace.test.mjs +0 -275
  484. package/cli/commands/hub.test.mjs +0 -225
  485. package/cli/commands/kg.test.mjs +0 -142
  486. package/cli/commands/preflight.test.mjs +0 -46
  487. package/cli/lib/argv.test.mjs +0 -46
  488. package/cli/lib/cache.test.mjs +0 -303
  489. package/cli/lib/cell-plan.test.mjs +0 -225
  490. package/cli/lib/config-lint.test.mjs +0 -117
  491. package/cli/lib/ddr-to-kgai.test.mjs +0 -118
  492. package/cli/lib/design-ownership.test.mjs +0 -329
  493. package/cli/lib/fetch-asset.test.mjs +0 -213
  494. package/cli/lib/figma-codegen-reachability.test.mjs +0 -104
  495. package/cli/lib/figma-import-controls.test.mjs +0 -70
  496. package/cli/lib/flow-design-integration.test.mjs +0 -165
  497. package/cli/lib/gitignore-block.test.mjs +0 -136
  498. package/cli/lib/gitignore-drift.test.mjs +0 -156
  499. package/cli/lib/hubs-config.test.mjs +0 -165
  500. package/cli/lib/pkg-root.test.mjs +0 -111
  501. package/cli/lib/plugin-cli-reachability.test.mjs +0 -57
  502. package/cli/lib/plugin-name-namespace.test.mjs +0 -71
  503. package/cli/lib/reconstruct-toolset.test.mjs +0 -194
  504. package/cli/lib/stack-detect.test.mjs +0 -121
  505. package/cli/lib/update-check.test.mjs +0 -32
  506. package/cli/lib/workspace-plan.test.mjs +0 -699
@@ -1,235 +0,0 @@
1
- // DDR-184 (+ DDR-185, hardened per its security addendum) — the curated tool
2
- // allow-list the bridge auto-approves so the design workflow never stalls on
3
- // a per-edit / per-`maude` permission prompt (the "Manual mode blocks every
4
- // edit" complaint). Three things under test:
5
- //
6
- // (1) WIRE contract — the list lands on `_meta.claudeCode.options.allowedTools`
7
- // (SDK `allowedTools`, sdk.d.ts:1331), coexisting with the DDR-144
8
- // `settingSources` narrowing and the DDR-143 `plugins` carrier. Same
9
- // adapter/SDK-INTERNAL `_meta` path as acp-session-plugins.test.ts — a
10
- // bump that stops forwarding it must fail HERE, not silently re-prompt.
11
- // (2) SOURCE-OF-TRUTH guard — the Bash rules are EXACTLY `Bash(maude:*)`
12
- // plus a closed read-only fs verb set (DDR-185) — nothing else. A
13
- // security fan-out found the ORIGINAL DDR-185 cut's `Bash(agent-browser:*)`
14
- // entry was a zero-confirmation session-hijack primitive (agent-browser's
15
- // own bundled skill recommends a persistent, real-login Chrome profile)
16
- // and `Bash(find:*)` was unrestricted command execution via `-exec`, not
17
- // "mutation" as first characterized — both are cut, not patched, because
18
- // neither residual is fixable via prefix-matching. `agent-browser` is
19
- // now reached ONLY through the hardened `agent-browser-safe` verb
20
- // (`Bash(maude:*)` covers it — no separate allow-list entry). If any of
21
- // this drifts, this test fails loudly.
22
- // (3) `WebSearch`/`WebFetch` (DDR-185) are present as bare native tool names
23
- // — no prefix-matching involved, so no source-of-truth guard needed the
24
- // way the Bash rules need one.
25
- // (4) NO WRITE TOOL is on this list (feature-acp-write-path-scope). This
26
- // file used to assert the exact opposite — that Edit/Write/NotebookEdit
27
- // WERE present — so read the test's own comment before "restoring" it.
28
- // Write auto-approval moved into the bridge's path gate, which is the
29
- // only place a per-call target path exists; see acp-write-scope.test.ts.
30
-
31
- import { describe, expect, test } from 'bun:test';
32
- import { existsSync, readFileSync, realpathSync } from 'node:fs';
33
- import { dirname, join } from 'node:path';
34
-
35
- import { MAUDE_DEFAULT_ALLOWED_TOOLS, newSessionParams } from '../acp/bridge.ts';
36
- import type { SdkPluginConfig } from '../acp/plugin-bootstrap.ts';
37
- import { WRITE_TOOL_NAMES } from '../acp/write-scope.ts';
38
-
39
- type Meta = {
40
- systemPrompt?: { append?: string };
41
- claudeCode?: {
42
- options?: {
43
- allowedTools?: string[];
44
- plugins?: SdkPluginConfig[];
45
- settingSources?: string[];
46
- };
47
- };
48
- };
49
-
50
- const PLUGINS: SdkPluginConfig[] = [
51
- { type: 'local', path: '/bundle/plugins/design', skipMcpDiscovery: true },
52
- ];
53
-
54
- describe('newSessionParams — allowedTools carrier shape (DDR-184)', () => {
55
- test('the allow-list rides _meta.claudeCode.options.allowedTools', () => {
56
- const opts = (newSessionParams('/repo', undefined)._meta as Meta).claudeCode?.options;
57
- expect(opts?.allowedTools).toEqual([...MAUDE_DEFAULT_ALLOWED_TOOLS]);
58
- });
59
-
60
- test('allowedTools is a COPY, not the shared module constant (no accidental mutation)', () => {
61
- const opts = (newSessionParams('/repo')._meta as Meta).claudeCode?.options;
62
- expect(opts?.allowedTools).not.toBe(MAUDE_DEFAULT_ALLOWED_TOOLS);
63
- });
64
-
65
- test('coexists with settingSources (DDR-144) and plugins (DDR-143) under one options', () => {
66
- const opts = (newSessionParams('/repo', 'BRIEF', PLUGINS)._meta as Meta).claudeCode?.options;
67
- expect(opts?.settingSources).toEqual(['user']);
68
- expect(opts?.plugins).toEqual(PLUGINS);
69
- expect(opts?.allowedTools).toEqual([...MAUDE_DEFAULT_ALLOWED_TOOLS]);
70
- });
71
-
72
- test('present even with no plugins (npm / web / power-user path)', () => {
73
- const opts = (newSessionParams('/repo', 'BRIEF', [])._meta as Meta).claudeCode?.options;
74
- expect(opts?.plugins).toBeUndefined();
75
- expect(opts?.allowedTools).toEqual([...MAUDE_DEFAULT_ALLOWED_TOOLS]);
76
- });
77
- });
78
-
79
- describe('MAUDE_DEFAULT_ALLOWED_TOOLS — source-of-truth guard (DDR-184 / DDR-062)', () => {
80
- const bashRules = MAUDE_DEFAULT_ALLOWED_TOOLS.filter((t) => t.startsWith('Bash'));
81
-
82
- test('the READ-ONLY file tools are present', () => {
83
- for (const t of ['Read', 'Glob', 'Grep']) {
84
- expect(MAUDE_DEFAULT_ALLOWED_TOOLS).toContain(t);
85
- }
86
- });
87
-
88
- test('NO write tool is name-allowed — they are path-gated instead (feature-acp-write-path-scope)', () => {
89
- // This assertion is the whole point of the change, so it is worth being
90
- // explicit about WHY it inverts what this file used to assert.
91
- //
92
- // A bare tool name on this list means the CLI approves the call itself and
93
- // `requestPermission` is NEVER invoked — so a path condition cannot be
94
- // attached to an entry here, at all. Auto-approving a write therefore had
95
- // to be moved into the bridge's own gate (`classifyWrite` →
96
- // `writeTargetsInsideProject`), where a per-call path exists. DDR-184's
97
- // no-prompt-per-edit outcome is fully preserved for in-project writes; what
98
- // changed is that a write to `~/.zshenv` now prompts instead of landing
99
- // silently with no rollback.
100
- //
101
- // If someone "fixes" a re-prompting regression by putting Write back on this
102
- // list, this test is what tells them they just reopened the hole.
103
- for (const t of [...WRITE_TOOL_NAMES]) {
104
- expect(MAUDE_DEFAULT_ALLOWED_TOOLS).not.toContain(t);
105
- }
106
- // Guard the shape too — an `Edit(...)`-style scoped entry would also bypass
107
- // the bridge gate, and `not.toContain` on the bare name would miss it.
108
- for (const t of MAUDE_DEFAULT_ALLOWED_TOOLS) {
109
- const bare = t.replace(/\(.*$/, '');
110
- expect(WRITE_TOOL_NAMES.has(bare)).toBe(false);
111
- }
112
- });
113
-
114
- test('WebSearch and WebFetch are present (DDR-185)', () => {
115
- for (const t of ['WebSearch', 'WebFetch']) {
116
- expect(MAUDE_DEFAULT_ALLOWED_TOOLS).toContain(t);
117
- }
118
- });
119
-
120
- test('the Bash rules are EXACTLY this closed set — never a bare/un-scoped Bash', () => {
121
- // A bare `Bash` (or `Bash(*)`) would auto-approve arbitrary command execution
122
- // — exactly the blanket surface DDR-179 kept behind the prompt. Guard against
123
- // anyone widening it: the list may auto-approve `maude` and the closed
124
- // read-only fs verb set (DDR-185) — nothing else. In particular:
125
- // - `Bash(curl:*)` must NEVER appear — curl is routed through the
126
- // `curl-local` verb (covered by `Bash(maude:*)`) instead.
127
- // - `Bash(agent-browser:*)` must NEVER appear — a security fan-out found
128
- // it was a zero-confirmation session-hijack primitive; agent-browser is
129
- // routed through the `agent-browser-safe` verb instead.
130
- // - `Bash(find:*)` must NEVER appear — `find -exec` is unrestricted
131
- // command execution, not "mutation"; there is no verb substitute, it
132
- // is simply cut.
133
- // - the read-only fs verb group must NEVER appear — every one of them
134
- // accepts `>`, making the rule an arbitrary-write grant. See the
135
- // dedicated test below.
136
- expect(bashRules).toEqual(['Bash(maude:*)']);
137
- });
138
-
139
- test('NO redirect-capable bare-command Bash rule — `cat > file` is an arbitrary write (F1)', () => {
140
- // SECURITY (security-auditor F1, PoC'd live against claude 2.1.220). The
141
- // read-only fs group (ls/cat/pwd/head/tail/wc/tree/file/stat) USED to be on
142
- // this list, justified as adding no incremental READ capability. True, and
143
- // beside the point: Claude Code's `Bash(<cmd>:*)` prefix rule does not
144
- // reject shell redirection, so `cat > ~/.zshenv <<'EOF' … EOF` matched
145
- // `Bash(cat:*)`, was self-approved by the CLI, never reached
146
- // `requestPermission`, and wrote model-authored arbitrary content to an
147
- // arbitrary path — with no write tool involved at all. That is the A2
148
- // primitive the write-path gate exists to close, reachable by a CHEAPER
149
- // route than the write tools themselves.
150
- //
151
- // Cut rather than patched (same call DDR-185 made for `find` and
152
- // `agent-browser`): a prefix rule cannot inspect what follows the command
153
- // name, so there is nothing to patch. If they come back, they must come
154
- // back as a hardened `maude design` wrapper verb, which CAN reject `>`.
155
- //
156
- // This test is what makes re-adding any of them a loud failure rather than
157
- // a silent reopening of the hole.
158
- for (const verb of ['ls', 'cat', 'pwd', 'head', 'tail', 'wc', 'tree', 'file', 'stat']) {
159
- expect(MAUDE_DEFAULT_ALLOWED_TOOLS).not.toContain(`Bash(${verb}:*)`);
160
- }
161
- });
162
-
163
- test('the `maude` Bash rule is load-bearing on DDR-062: every design helper is a `maude design <verb>`', () => {
164
- // Resolve cli/commands/design.mjs relative to this test file's real path
165
- // (mirrors acp-session-plugins.test.ts's realpath dance for compiled roots).
166
- const here = dirname(realpathSync(import.meta.url.replace('file://', '')));
167
- const designCli = join(here, '..', '..', '..', 'cli', 'commands', 'design.mjs');
168
- expect(existsSync(designCli)).toBe(true);
169
- const src = readFileSync(designCli, 'utf8');
170
- // The dispatch table the `Bash(maude:*)` scope rests on — helpers reached via
171
- // `maude design <verb>`, not raw `bash <path>.sh` (DDR-062). If this marker
172
- // disappears, the one-rule assumption needs re-checking.
173
- expect(src).toContain('BIN_VERBS');
174
- expect(src).toMatch(/maude design <verb>/);
175
- });
176
-
177
- test('the `curl-local` verb exists and is reached via `maude design <verb>` (DDR-185)', () => {
178
- // The mechanism the `Bash(agent-browser:*)`/fs-list comment in bridge.ts
179
- // promises for curl: real host enforcement via a first-party verb, not a
180
- // Bash prefix rule. If this verb disappears from BIN_VERBS, the DDR-185
181
- // curl story (and the bootstrap-brief nudge pointing at it) goes stale.
182
- const here = dirname(realpathSync(import.meta.url.replace('file://', '')));
183
- const designCli = join(here, '..', '..', '..', 'cli', 'commands', 'design.mjs');
184
- const src = readFileSync(designCli, 'utf8');
185
- expect(src).toMatch(/'curl-local'/);
186
- });
187
-
188
- test('the `agent-browser-safe` verb exists and is reached via `maude design <verb>` (DDR-185 security addendum)', () => {
189
- // The replacement for the reverted `Bash(agent-browser:*)` entry — real
190
- // subcommand/flag enforcement via a first-party verb, not a Bash prefix
191
- // rule. If this verb disappears from BIN_VERBS, motion-critic.md/edit.md's
192
- // documented raw agent-browser calls go back to prompting (not silently
193
- // insecure — but the friction-reduction this DDR promises goes stale).
194
- const here = dirname(realpathSync(import.meta.url.replace('file://', '')));
195
- const designCli = join(here, '..', '..', '..', 'cli', 'commands', 'design.mjs');
196
- const src = readFileSync(designCli, 'utf8');
197
- expect(src).toMatch(/'agent-browser-safe'/);
198
- });
199
-
200
- test('plugin markdown no longer documents a RAW agent-browser SCREENSHOT/OPEN/NAVIGATE call (DDR-185 security addendum)', () => {
201
- // motion-critic.md and edit.md are the two files that originally justified
202
- // `Bash(agent-browser:*)` (raw calls not reached via `maude design <verb>`).
203
- // screenshot/open/navigate now go through the hardened wrapper — a
204
- // regression here means either those calls silently went back to
205
- // prompting every time, or (worse) someone re-introduced a raw call the
206
- // allow-list no longer covers. `eval` is the deliberate exception (round
207
- // 3: removed from the wrapper's own allow-list entirely — arbitrary JS
208
- // execution can't be argv-constrained — so it's EXPECTED to stay a raw,
209
- // prompting `agent-browser eval` call; see both files' own comments).
210
- const here = dirname(realpathSync(import.meta.url.replace('file://', '')));
211
- const pluginsDir = join(here, '..', '..', '..', 'plugins', 'design');
212
- for (const rel of ['agents/motion-critic.md', 'commands/edit.md']) {
213
- const src = readFileSync(join(pluginsDir, rel), 'utf8');
214
- expect(src).not.toMatch(/(?<!maude design )agent-browser (screenshot|open|navigate)\b/);
215
- expect(src).toContain('agent-browser eval'); // deliberately raw — see comment above
216
- }
217
- // Only motion-critic.md actually calls the wrapper (for `screenshot`) —
218
- // edit.md's sole agent-browser use was `eval`, which reverted fully to
219
- // raw, so it has no `agent-browser-safe` invocation left at all.
220
- const motionCritic = readFileSync(join(pluginsDir, 'agents/motion-critic.md'), 'utf8');
221
- expect(motionCritic).toContain('maude design agent-browser-safe');
222
- });
223
-
224
- test('agent-browser-safe does NOT support eval (DDR-185 round-3 security addendum)', () => {
225
- // A future accidental re-add of eval to the wrapper's own allow-list
226
- // would silently reopen the zero-click session-hijack chain (ethical-
227
- // hacker Finding 1: eval's fetch()/window.location defeat
228
- // --allowed-domains entirely, and no argv check can constrain arbitrary
229
- // JS execution). Source-of-truth guard against bridge.ts's own wrapper.
230
- const here = dirname(realpathSync(import.meta.url.replace('file://', '')));
231
- const wrapperPath = join(here, '..', 'bin', '_agent-browser-safe.mjs');
232
- const src = readFileSync(wrapperPath, 'utf8');
233
- expect(src).not.toMatch(/^\s*eval:\s*\[/m);
234
- });
235
- });
@@ -1,209 +0,0 @@
1
- // DDR-143 — session-scoped plugin auto-bootstrap: the WIRE contract.
2
- //
3
- // Two layers: (1) the newSession params carrier — the resolved plugin configs
4
- // must land on `_meta.claudeCode.options.plugins`, coexisting with the studio
5
- // brief's `_meta.systemPrompt.append`; (2) the UPGRADE GUARD — that `_meta` path
6
- // is adapter/SDK-INTERNAL and undocumented, so a dependency bump that stops
7
- // forwarding `_meta.claudeCode.options` (adapter) or drops `plugins` (SDK) must
8
- // fail HERE, loudly, instead of silently shipping a desktop app whose chat
9
- // resolves no `/design:*` on a pristine machine.
10
-
11
- import { describe, expect, test } from 'bun:test';
12
- import { existsSync, readFileSync, realpathSync } from 'node:fs';
13
- import { dirname, join } from 'node:path';
14
-
15
- import { newSessionParams } from '../acp/bridge.ts';
16
- import type { SdkPluginConfig } from '../acp/plugin-bootstrap.ts';
17
-
18
- const PLUGINS: SdkPluginConfig[] = [
19
- { type: 'local', path: '/bundle/plugins/design', skipMcpDiscovery: true },
20
- { type: 'local', path: '/bundle/plugins/flow', skipMcpDiscovery: true },
21
- ];
22
-
23
- type Meta = {
24
- systemPrompt?: { append?: string };
25
- claudeCode?: {
26
- options?: {
27
- plugins?: SdkPluginConfig[];
28
- settingSources?: string[];
29
- settings?: { enabledPlugins?: Record<string, boolean> };
30
- };
31
- };
32
- };
33
-
34
- describe('newSessionParams — plugin carrier shape', () => {
35
- test('with plugins: they ride _meta.claudeCode.options.plugins', () => {
36
- const p = newSessionParams('/repo', undefined, PLUGINS);
37
- expect(p.cwd).toBe('/repo');
38
- expect((p._meta as Meta).claudeCode?.options?.plugins).toEqual(PLUGINS);
39
- });
40
-
41
- test('empty plugins: claudeCode carries settingSources but NO plugins (power-user / web no-op)', () => {
42
- const p = newSessionParams('/repo', 'BRIEF', []);
43
- const opts = (p._meta as Meta).claudeCode?.options;
44
- expect(opts?.plugins).toBeUndefined();
45
- expect(opts?.settingSources).toEqual(['user']); // security narrowing always present
46
- });
47
-
48
- test('undefined plugins: claudeCode carries settingSources, no plugins', () => {
49
- const p = newSessionParams('/repo', 'BRIEF');
50
- const opts = (p._meta as Meta).claudeCode?.options;
51
- expect(opts?.plugins).toBeUndefined();
52
- expect(opts?.settingSources).toEqual(['user']);
53
- });
54
-
55
- test('brief + plugins coexist under one _meta (both siblings intact)', () => {
56
- const p = newSessionParams('/repo', 'BRIEF', PLUGINS);
57
- const meta = p._meta as Meta;
58
- expect(meta.systemPrompt?.append).toBe('BRIEF');
59
- expect(meta.claudeCode?.options?.plugins).toEqual(PLUGINS);
60
- });
61
-
62
- test('plugins only, no brief: still no systemPrompt, but claudeCode present', () => {
63
- const p = newSessionParams('/repo', undefined, PLUGINS);
64
- const meta = p._meta as Meta;
65
- expect(meta.systemPrompt).toBeUndefined();
66
- expect(meta.claudeCode?.options?.plugins).toEqual(PLUGINS);
67
- });
68
-
69
- test('nothing injected: _meta still carries the settingSources security narrowing', () => {
70
- const p = newSessionParams('/repo', undefined, []);
71
- const meta = p._meta as Meta;
72
- expect(meta.systemPrompt).toBeUndefined();
73
- expect(meta.claudeCode?.options?.plugins).toBeUndefined();
74
- // Every Maude bridge session is auto-approving → settingSources is ALWAYS narrowed.
75
- expect(meta.claudeCode?.options?.settingSources).toEqual(['user']);
76
- });
77
-
78
- test('settingSources is narrowed to user-only on EVERY session (DDR-144 F2)', () => {
79
- for (const p of [
80
- newSessionParams('/repo'),
81
- newSessionParams('/repo', 'BRIEF'),
82
- newSessionParams('/repo', 'BRIEF', PLUGINS),
83
- newSessionParams('/repo', undefined, PLUGINS),
84
- ]) {
85
- expect((p._meta as Meta).claudeCode?.options?.settingSources).toEqual(['user']);
86
- }
87
- });
88
-
89
- // DDR-168 — the structural double-registration guard: a non-empty `plugins`
90
- // must also force off any natively-loaded user-level copy of the same id via
91
- // the SDK's "flag" settings layer, so the bundled copy is the ONLY one that
92
- // ever loads.
93
- test('with plugins: forces design@maude off via options.settings.enabledPlugins (double-registration guard)', () => {
94
- const p = newSessionParams('/repo', undefined, PLUGINS);
95
- expect((p._meta as Meta).claudeCode?.options?.settings?.enabledPlugins).toEqual({
96
- 'design@maude': false,
97
- // kgai (third-party, injected by the desktop bundle for autonomous capture —
98
- // feature-kgai-ecosystem-integration Phase 8). Suppressing a user-installed
99
- // copy matters MORE here than for our own plugins: it would run its own
100
- // SessionStart install.sh and point at a different engine version than the
101
- // pinned, signed sidecar we ship.
102
- kgai: false,
103
- });
104
- });
105
-
106
- test('empty plugins: options.settings is entirely absent (web/npm path unaffected)', () => {
107
- const p = newSessionParams('/repo', 'BRIEF', []);
108
- expect((p._meta as Meta).claudeCode?.options?.settings).toBeUndefined();
109
- });
110
-
111
- test('undefined plugins: options.settings is entirely absent', () => {
112
- const p = newSessionParams('/repo', 'BRIEF');
113
- expect((p._meta as Meta).claudeCode?.options?.settings).toBeUndefined();
114
- });
115
- });
116
-
117
- describe('upgrade guard — installed adapter + SDK still honor the plugins contract', () => {
118
- const adapterEntry = join(
119
- import.meta.dir,
120
- '..',
121
- 'node_modules',
122
- '@agentclientprotocol',
123
- 'claude-agent-acp',
124
- 'dist',
125
- 'acp-agent.js'
126
- );
127
-
128
- test('adapter newSession reads _meta.claudeCode.options and forwards it to query()', () => {
129
- expect(existsSync(adapterEntry)).toBe(true);
130
- const src = readFileSync(adapterEntry, 'utf8');
131
- // Verified at claude-agent-acp@0.49.0 (acp-agent.js newSession):
132
- // const userProvidedOptions = sessionMeta?.claudeCode?.options; (:2302)
133
- // const options = { …, ...userProvidedOptions, … }; (:2333)
134
- // const q = query({ prompt: input, options }); (:2455)
135
- // `plugins` is not in the override list after the spread, so it survives into
136
- // query(). A bump that renames/drops any link in this chain must fail here —
137
- // then adapt, or fall back to settings.enabledPlugins + a local marketplace
138
- // (plan Task 1 fallback).
139
- expect(src).toMatch(/claudeCode\s*(\?\.|\.)\s*options/);
140
- expect(src).toContain('userProvidedOptions');
141
- expect(src).toMatch(/\.\.\.userProvidedOptions/);
142
- expect(src).toMatch(/query\(\{[\s\S]{0,80}options[\s\S]{0,40}\}\)/);
143
- });
144
-
145
- test('SDK Options declares plugins?: SdkPluginConfig[] (the accepted field)', () => {
146
- // Resolve the transitive @anthropic-ai/claude-agent-sdk. Resolve from the
147
- // adapter's REAL dir (pnpm store), where the SDK is a peer sibling — the
148
- // apps/studio symlink alone doesn't expose the pnpm peer node_modules.
149
- let sdkPkg: string | null = null;
150
- try {
151
- const realAdapterDir = dirname(realpathSync(adapterEntry));
152
- sdkPkg = Bun.resolveSync('@anthropic-ai/claude-agent-sdk/package.json', realAdapterDir);
153
- } catch {
154
- sdkPkg = null;
155
- }
156
- expect(sdkPkg).not.toBeNull();
157
- const dts = join(dirname(sdkPkg as string), 'sdk.d.ts');
158
- expect(existsSync(dts)).toBe(true);
159
- const src = readFileSync(dts, 'utf8');
160
- // sdk.d.ts:1683 `plugins?: SdkPluginConfig[];` + :3766 the { type:'local'; path } shape.
161
- expect(src).toMatch(/plugins\?\s*:\s*SdkPluginConfig\[\]/);
162
- expect(src).toMatch(/SdkPluginConfig\s*=\s*\{/);
163
- expect(src).toMatch(/type:\s*'local'/);
164
- });
165
-
166
- // DDR-168 — the same style of guard, for the `options.settings` mechanism the
167
- // double-registration fix depends on: `settings` must NOT be among the fields
168
- // the adapter overrides after the `...userProvidedOptions` spread (else our
169
- // `enabledPlugins: false` override would be silently discarded), and the SDK
170
- // must still declare `Settings.enabledPlugins` as an accepted field.
171
- test('adapter forwards `settings` from userProvidedOptions and only ever overrides it conditionally when the caller left it unset', () => {
172
- expect(existsSync(adapterEntry)).toBe(true);
173
- const src = readFileSync(adapterEntry, 'utf8');
174
- // Locate the `...userProvidedOptions` spread and inspect what follows it up
175
- // to the `query({ options })` call. Verified live at claude-agent-acp@0.57.0:
176
- // the object DOES contain a later `settings:` assignment (a
177
- // CLAUDE_MODEL_CONFIG env-var fallback) — but it's gated behind
178
- // `!userProvidedOptions?.settings && …`, i.e. it only fires when the caller
179
- // did NOT already provide a settings object. A caller-provided `settings`
180
- // (ours, carrying `enabledPlugins`) always wins. A bump that drops that
181
- // guard — making the fallback unconditional — must fail here, since it
182
- // would silently clobber DDR-168's double-registration override.
183
- const spreadIdx = src.indexOf('...userProvidedOptions');
184
- expect(spreadIdx).toBeGreaterThan(-1);
185
- const queryIdx = src.indexOf('query(', spreadIdx);
186
- expect(queryIdx).toBeGreaterThan(spreadIdx);
187
- const window = src.slice(spreadIdx, queryIdx);
188
- expect(window).toMatch(/!userProvidedOptions\?\.settings\s*&&/);
189
- });
190
-
191
- test("SDK Options declares settings (Settings.enabledPlugins is the field DDR-168's guard relies on)", () => {
192
- let sdkPkg: string | null = null;
193
- try {
194
- const realAdapterDir = dirname(realpathSync(adapterEntry));
195
- sdkPkg = Bun.resolveSync('@anthropic-ai/claude-agent-sdk/package.json', realAdapterDir);
196
- } catch {
197
- sdkPkg = null;
198
- }
199
- expect(sdkPkg).not.toBeNull();
200
- const dts = join(dirname(sdkPkg as string), 'sdk.d.ts');
201
- expect(existsSync(dts)).toBe(true);
202
- const src = readFileSync(dts, 'utf8');
203
- // sdk.d.ts:1831 `settings?: Settings;` (or similarly named field on Options) +
204
- // :5193 `Settings.enabledPlugins` — a bump that renames/drops either must
205
- // fail here, then adapt, rather than silently reopening double-registration.
206
- expect(src).toMatch(/settings\?\s*:/);
207
- expect(src).toMatch(/enabledPlugins\??\s*:/);
208
- });
209
- });
@@ -1,76 +0,0 @@
1
- // Pure unit tests for client/panels/ToolGroup.jsx's grouping/summary helpers
2
- // (Task C1 — collapsed consecutive-tool-call groups).
3
-
4
- import { describe, expect, test } from 'bun:test';
5
-
6
- import { groupToolCalls, summarizeGroup } from '../client/panels/ToolGroup.jsx';
7
-
8
- describe('groupToolCalls', () => {
9
- test('a lone tool-call stays a single item, not a group', () => {
10
- const parts = [{ type: 'tool-call', toolCallId: '1', toolName: 'Read file' }];
11
- expect(groupToolCalls(parts)).toEqual([{ type: 'single', part: parts[0] }]);
12
- });
13
-
14
- test('2+ CONSECUTIVE tool-calls fold into one group', () => {
15
- const parts = [
16
- { type: 'tool-call', toolCallId: '1', toolName: 'Read file' },
17
- { type: 'tool-call', toolCallId: '2', toolName: 'Run command' },
18
- { type: 'tool-call', toolCallId: '3', toolName: 'Write file' },
19
- ];
20
- const grouped = groupToolCalls(parts);
21
- expect(grouped).toEqual([{ type: 'tool-group', parts }]);
22
- });
23
-
24
- test('text/reasoning parts break a run into separate groups', () => {
25
- const parts = [
26
- { type: 'tool-call', toolCallId: '1', toolName: 'Read file' },
27
- { type: 'tool-call', toolCallId: '2', toolName: 'Write file' },
28
- { type: 'text', text: 'done reading and writing' },
29
- { type: 'tool-call', toolCallId: '3', toolName: 'Run command' },
30
- ];
31
- const grouped = groupToolCalls(parts);
32
- expect(grouped).toEqual([
33
- { type: 'tool-group', parts: [parts[0], parts[1]] },
34
- { type: 'single', part: parts[2] },
35
- { type: 'single', part: parts[3] }, // lone tool-call after the break — not a group
36
- ]);
37
- });
38
-
39
- test('a mix of text and reasoning parts each stay single, in order', () => {
40
- const parts = [
41
- { type: 'text', text: 'thinking about it' },
42
- { type: 'reasoning', text: '...' },
43
- { type: 'text', text: 'here is my answer' },
44
- ];
45
- expect(groupToolCalls(parts)).toEqual(parts.map((part) => ({ type: 'single', part })));
46
- });
47
-
48
- test('tolerates an empty/missing parts array', () => {
49
- expect(groupToolCalls([])).toEqual([]);
50
- expect(groupToolCalls(undefined)).toEqual([]);
51
- expect(groupToolCalls(null)).toEqual([]);
52
- });
53
- });
54
-
55
- describe('summarizeGroup', () => {
56
- test('all entries sharing one title collapse to "Ran N × <title>"', () => {
57
- const parts = [{ toolName: 'Read file' }, { toolName: 'Read file' }, { toolName: 'Read file' }];
58
- expect(summarizeGroup(parts)).toBe('Ran 3 × Read file');
59
- });
60
-
61
- test('mixed titles list the distinct ones, capped at 3 with an ellipsis', () => {
62
- const parts = [
63
- { toolName: 'Read file' },
64
- { toolName: 'Run command' },
65
- { toolName: 'Web search' },
66
- { toolName: 'Write file' },
67
- { toolName: 'Read file' }, // duplicate — must not inflate the unique count
68
- ];
69
- const summary = summarizeGroup(parts);
70
- expect(summary).toBe('Ran 5 tools — Read file, Run command, Web search…');
71
- });
72
-
73
- test('a missing toolName falls back to the generic label, not undefined', () => {
74
- expect(summarizeGroup([{}, {}])).toBe('Ran 2 × tool');
75
- });
76
- });
@@ -1,71 +0,0 @@
1
- // Pure unit tests for client/panels/transcript-view.js (Task C4).
2
-
3
- import { describe, expect, test } from 'bun:test';
4
-
5
- import {
6
- DEFAULT_TRANSCRIPT_VIEW,
7
- filterTranscriptParts,
8
- TRANSCRIPT_VIEWS,
9
- transcriptForcesExpand,
10
- } from '../client/panels/transcript-view.js';
11
-
12
- const PARTS = [
13
- { type: 'reasoning', text: 'let me think' },
14
- { type: 'tool-call', toolCallId: '1', toolName: 'Read file' },
15
- { type: 'text', text: 'first answer' },
16
- { type: 'reasoning', text: 'more thinking' },
17
- { type: 'text', text: 'final answer' },
18
- ];
19
-
20
- describe('filterTranscriptParts', () => {
21
- test('normal hides reasoning, keeps text + tool-calls in order', () => {
22
- const result = filterTranscriptParts(PARTS, 'normal');
23
- expect(result.map((p) => p.type)).toEqual(['tool-call', 'text', 'text']);
24
- });
25
-
26
- test('thinking keeps everything, including reasoning', () => {
27
- expect(filterTranscriptParts(PARTS, 'thinking')).toEqual(PARTS);
28
- });
29
-
30
- test('verbose also keeps everything (the extra verbosity is a render-detail toggle)', () => {
31
- expect(filterTranscriptParts(PARTS, 'verbose')).toEqual(PARTS);
32
- });
33
-
34
- test('summary keeps ONLY the last text part', () => {
35
- const result = filterTranscriptParts(PARTS, 'summary');
36
- expect(result).toEqual([{ type: 'text', text: 'final answer' }]);
37
- });
38
-
39
- test('summary with no text parts at all returns empty, not a crash', () => {
40
- expect(filterTranscriptParts([{ type: 'tool-call', toolCallId: '1' }], 'summary')).toEqual([]);
41
- });
42
-
43
- test('an unrecognized mode fails toward normal (less noise), not everything', () => {
44
- expect(filterTranscriptParts(PARTS, 'nonsense')).toEqual(
45
- filterTranscriptParts(PARTS, 'normal')
46
- );
47
- });
48
-
49
- test('tolerates missing/empty input', () => {
50
- expect(filterTranscriptParts(undefined, 'normal')).toEqual([]);
51
- expect(filterTranscriptParts(null, 'thinking')).toEqual([]);
52
- expect(filterTranscriptParts([], 'summary')).toEqual([]);
53
- });
54
- });
55
-
56
- describe('transcriptForcesExpand', () => {
57
- test('only verbose forces expansion', () => {
58
- expect(transcriptForcesExpand('verbose')).toBe(true);
59
- expect(transcriptForcesExpand('normal')).toBe(false);
60
- expect(transcriptForcesExpand('thinking')).toBe(false);
61
- expect(transcriptForcesExpand('summary')).toBe(false);
62
- expect(transcriptForcesExpand(undefined)).toBe(false);
63
- });
64
- });
65
-
66
- describe('constants', () => {
67
- test('the view list + default are stable and consistent', () => {
68
- expect(TRANSCRIPT_VIEWS).toEqual(['normal', 'thinking', 'verbose', 'summary']);
69
- expect(TRANSCRIPT_VIEWS).toContain(DEFAULT_TRANSCRIPT_VIEW);
70
- });
71
- });