@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.
- package/apps/studio/acp/bridge.ts +18 -13
- package/apps/studio/acp/probe.ts +268 -16
- package/apps/studio/acp/transcript-io.ts +394 -0
- package/apps/studio/acp/transcript.ts +103 -38
- package/apps/studio/api.ts +139 -26
- package/apps/studio/bin/_import-figma.mjs +57 -11
- package/apps/studio/bin/_seed-fixture.mjs +163 -0
- package/apps/studio/canvas-imports.ts +89 -0
- package/apps/studio/client/app.jsx +257 -7
- package/apps/studio/client/export-center.jsx +15 -7
- package/apps/studio/client/panels/ReadinessList.jsx +7 -1
- package/apps/studio/client/panels/SyncPanel.jsx +125 -4
- package/apps/studio/client/report-bug.jsx +19 -1
- package/apps/studio/client/styles/3-shell-maude.css +34 -0
- package/apps/studio/client/styles/4-components.css +26 -0
- package/apps/studio/collab/persistence.ts +132 -16
- package/apps/studio/collab/registry.ts +10 -18
- package/apps/studio/debug-bundle.ts +13 -0
- package/apps/studio/dist/client.bundle.js +1128 -1128
- package/apps/studio/dist/styles.css +1 -1
- package/apps/studio/export-dialog.tsx +54 -0
- package/apps/studio/exporters/degraded.ts +19 -3
- package/apps/studio/exporters/ghostscript.ts +194 -0
- package/apps/studio/exporters/pdf-fonts.ts +261 -0
- package/apps/studio/exporters/pdf.ts +152 -3
- package/apps/studio/exporters/remote.ts +36 -1
- package/apps/studio/fs-watch.ts +45 -1
- package/apps/studio/http.ts +7 -1
- package/apps/studio/mem.ts +45 -9
- package/apps/studio/readiness.ts +42 -7
- package/apps/studio/server.ts +11 -4
- package/apps/studio/sync/agent.ts +136 -29
- package/apps/studio/sync/asset-push.ts +1 -47
- package/apps/studio/sync/codec.ts +122 -31
- package/apps/studio/sync/cold-start-apply.ts +7 -0
- package/apps/studio/sync/cold-start.ts +118 -22
- package/apps/studio/sync/comment-identity.ts +68 -0
- package/apps/studio/sync/connection-state.ts +15 -1
- package/apps/studio/sync/file-ledger.ts +117 -0
- package/apps/studio/sync/file-plane.ts +623 -27
- package/apps/studio/sync/index.ts +711 -20
- package/apps/studio/sync/journal-client.ts +13 -1
- package/apps/studio/sync/migrate-seed.ts +40 -3
- package/apps/studio/sync/presentation.ts +26 -3
- package/apps/studio/sync/retry-after.ts +169 -0
- package/apps/studio/sync/seed-progress.ts +218 -0
- package/apps/studio/sync/status.ts +122 -5
- package/apps/studio/sync/transport-error.ts +111 -0
- package/apps/studio/whats-new.json +91 -0
- package/cli/bin/maude.mjs +2 -0
- package/cli/commands/codex.mjs +191 -0
- package/cli/commands/harness.mjs +1051 -0
- package/cli/commands/help.mjs +13 -0
- package/cli/lib/design-link.mjs +190 -2
- package/cli/lib/harness/capabilities.mjs +302 -0
- package/cli/lib/harness/codex-runtime.mjs +889 -0
- package/cli/lib/harness/compatibility.mjs +27 -0
- package/cli/lib/harness/discover-claude.mjs +1393 -0
- package/cli/lib/harness/managed-state.mjs +1296 -0
- package/cli/lib/harness/model.mjs +86 -0
- package/cli/lib/harness/secrets.mjs +390 -0
- package/cli/lib/harness/targets/codex.mjs +1141 -0
- package/cli/lib/harness/targets/opencode.mjs +807 -0
- package/cli/lib/harness/transaction.mjs +1099 -0
- package/cli/lib/hubs-config.mjs +35 -8
- package/cli/templates/harness/opencode/maude-projector.ts +58 -0
- package/docs/harness-capability-matrix.md +125 -0
- package/docs/harness-environment-projection.md +95 -0
- package/package.json +32 -9
- package/plugins/flow/.claude-plugin/config.schema.json +8 -0
- package/apps/studio/.ai/cache/_stats.json +0 -7
- package/apps/studio/bin/_agent-browser-safe.test.mjs +0 -165
- package/apps/studio/bin/_curl-local.test.mjs +0 -280
- package/apps/studio/bin/_pw-launch.test.mjs +0 -90
- package/apps/studio/bin/_smart-frames.test.mjs +0 -195
- package/apps/studio/bin/_transcribe.test.mjs +0 -80
- package/apps/studio/bun.lock +0 -928
- package/apps/studio/draw/test/animate.test.ts +0 -172
- package/apps/studio/draw/test/brush.test.ts +0 -213
- package/apps/studio/draw/test/composition.test.ts +0 -141
- package/apps/studio/draw/test/geometry.test.ts +0 -199
- package/apps/studio/draw/test/gradient.test.ts +0 -167
- package/apps/studio/draw/test/layout.test.ts +0 -120
- package/apps/studio/draw/test/morph.test.ts +0 -107
- package/apps/studio/draw/test/optimize.test.ts +0 -40
- package/apps/studio/draw/test/palette.test.ts +0 -123
- package/apps/studio/draw/test/primitives.test.ts +0 -129
- package/apps/studio/draw/test/serialize-animate.test.ts +0 -142
- package/apps/studio/draw/test/serialize.test.ts +0 -105
- package/apps/studio/figma/assets.test.ts +0 -464
- package/apps/studio/figma/client.test.ts +0 -395
- package/apps/studio/figma/codegen-client.test.ts +0 -276
- package/apps/studio/figma/codegen-fonts.test.ts +0 -103
- package/apps/studio/figma/codegen-values.test.ts +0 -179
- package/apps/studio/figma/comments-to-strokes.test.ts +0 -194
- package/apps/studio/figma/fig-decode.test.ts +0 -788
- package/apps/studio/figma/fig-differential.test.ts +0 -182
- package/apps/studio/figma/fig-translator.test.ts +0 -192
- package/apps/studio/figma/fig-vector.test.ts +0 -113
- package/apps/studio/figma/from-codegen.test.ts +0 -408
- package/apps/studio/figma/sanitize.test.ts +0 -325
- package/apps/studio/figma/tailwind-map.test.ts +0 -142
- package/apps/studio/figma/to-artboard.test.ts +0 -808
- package/apps/studio/figma/to-render.test.ts +0 -180
- package/apps/studio/figma/to-strokes-roundtrip.test.ts +0 -152
- package/apps/studio/figma/to-strokes.test.ts +0 -705
- package/apps/studio/figma/to-tokens.test.ts +0 -321
- package/apps/studio/figma/url.test.ts +0 -167
- package/apps/studio/footage/schema.test.ts +0 -287
- package/apps/studio/generation/adapters/groq.test.ts +0 -80
- package/apps/studio/generation/audio-library.test.ts +0 -95
- package/apps/studio/generation/captions.test.ts +0 -78
- package/apps/studio/generation/elevenlabs.test.ts +0 -223
- package/apps/studio/generation/gemini.test.ts +0 -350
- package/apps/studio/generation/jobs.test.ts +0 -128
- package/apps/studio/generation/keys.test.ts +0 -75
- package/apps/studio/generation/prefs.test.ts +0 -95
- package/apps/studio/generation/types.test.ts +0 -123
- package/apps/studio/generation/whisper-models.test.ts +0 -179
- package/apps/studio/test/_helpers.ts +0 -108
- package/apps/studio/test/acp-activity-endpoint.test.ts +0 -183
- package/apps/studio/test/acp-activity.test.ts +0 -154
- package/apps/studio/test/acp-ai-activity.test.ts +0 -182
- package/apps/studio/test/acp-attachment-serve.test.ts +0 -74
- package/apps/studio/test/acp-bootstrap-brief.test.ts +0 -178
- package/apps/studio/test/acp-branch-guard.test.ts +0 -123
- package/apps/studio/test/acp-bridge-lifetime.test.ts +0 -475
- package/apps/studio/test/acp-bridge.test.ts +0 -301
- package/apps/studio/test/acp-capabilities.test.ts +0 -123
- package/apps/studio/test/acp-caps-bridge.test.ts +0 -279
- package/apps/studio/test/acp-commands.test.ts +0 -119
- package/apps/studio/test/acp-elicitation-bridge.test.ts +0 -480
- package/apps/studio/test/acp-elicitation.test.ts +0 -251
- package/apps/studio/test/acp-env.test.ts +0 -95
- package/apps/studio/test/acp-mode-banner.test.ts +0 -45
- package/apps/studio/test/acp-origin-gate.test.ts +0 -160
- package/apps/studio/test/acp-permission-prompt.test.ts +0 -251
- package/apps/studio/test/acp-permission.test.ts +0 -278
- package/apps/studio/test/acp-plugin-bootstrap.test.ts +0 -89
- package/apps/studio/test/acp-session-allowed-tools.test.ts +0 -235
- package/apps/studio/test/acp-session-plugins.test.ts +0 -209
- package/apps/studio/test/acp-toolgroup.test.ts +0 -76
- package/apps/studio/test/acp-transcript-view.test.ts +0 -71
- package/apps/studio/test/acp-transcript.test.ts +0 -238
- package/apps/studio/test/acp-usage-bridge.test.ts +0 -141
- package/apps/studio/test/acp-usage.test.ts +0 -143
- package/apps/studio/test/acp-write-gate.test.ts +0 -323
- package/apps/studio/test/acp-write-scope.test.ts +0 -533
- package/apps/studio/test/active-state.test.ts +0 -186
- package/apps/studio/test/activity.test.ts +0 -189
- package/apps/studio/test/ai-activity.test.ts +0 -113
- package/apps/studio/test/annotate-write.test.ts +0 -1074
- package/apps/studio/test/annotation-strokes-command.test.ts +0 -166
- package/apps/studio/test/annotations-align.test.ts +0 -88
- package/apps/studio/test/annotations-api.test.ts +0 -145
- package/apps/studio/test/annotations-bindings.test.ts +0 -262
- package/apps/studio/test/annotations-draw-modifiers.test.ts +0 -206
- package/apps/studio/test/annotations-groups.test.ts +0 -231
- package/apps/studio/test/annotations-layer.test.ts +0 -1011
- package/apps/studio/test/annotations-roundtrip.test.ts +0 -663
- package/apps/studio/test/annotations-snap.test.ts +0 -135
- package/apps/studio/test/annotations-text-format.test.ts +0 -396
- package/apps/studio/test/artboard-activity-overlay.test.tsx +0 -56
- package/apps/studio/test/artboard-guides-overlay.test.tsx +0 -152
- package/apps/studio/test/artboard-hug-commit.test.ts +0 -36
- package/apps/studio/test/artboard-kinds.test.tsx +0 -83
- package/apps/studio/test/artboard-selection-attrs.test.ts +0 -69
- package/apps/studio/test/asset-api.test.ts +0 -149
- package/apps/studio/test/assets-s3.test.ts +0 -249
- package/apps/studio/test/binary-smoke.test.ts +0 -47
- package/apps/studio/test/boot-self-heal.test.ts +0 -87
- package/apps/studio/test/browse-posture.test.tsx +0 -107
- package/apps/studio/test/bundle-smoke.test.ts +0 -46
- package/apps/studio/test/camera-reveal.test.tsx +0 -173
- package/apps/studio/test/canvas-artifacts.test.ts +0 -125
- package/apps/studio/test/canvas-build-sandbox.test.ts +0 -69
- package/apps/studio/test/canvas-build.test.ts +0 -141
- package/apps/studio/test/canvas-create-api.test.ts +0 -676
- package/apps/studio/test/canvas-cursors.test.ts +0 -164
- package/apps/studio/test/canvas-edit.test.ts +0 -470
- package/apps/studio/test/canvas-freshness-deps.test.ts +0 -64
- package/apps/studio/test/canvas-header.test.ts +0 -127
- package/apps/studio/test/canvas-hide-chrome.test.ts +0 -88
- package/apps/studio/test/canvas-hmr-runtime.test.tsx +0 -114
- package/apps/studio/test/canvas-lib-inline.test.ts +0 -146
- package/apps/studio/test/canvas-lib-motion.test.ts +0 -131
- package/apps/studio/test/canvas-lib-resolver.test.ts +0 -111
- package/apps/studio/test/canvas-list-watch.test.ts +0 -388
- package/apps/studio/test/canvas-media-drop.test.ts +0 -187
- package/apps/studio/test/canvas-meta-api.test.ts +0 -707
- package/apps/studio/test/canvas-move-api.test.ts +0 -587
- package/apps/studio/test/canvas-origin-gate.test.ts +0 -417
- package/apps/studio/test/canvas-pipeline.test.ts +0 -180
- package/apps/studio/test/canvas-rects.test.ts +0 -198
- package/apps/studio/test/canvas-reorder.test.ts +0 -211
- package/apps/studio/test/canvas-route.test.ts +0 -179
- package/apps/studio/test/canvas-shell-base.test.ts +0 -107
- package/apps/studio/test/canvas-shell-build-error.test.ts +0 -52
- package/apps/studio/test/canvas-url.test.ts +0 -138
- package/apps/studio/test/canvas-wheel-delta.test.ts +0 -42
- package/apps/studio/test/canvas-zoom-floor.test.ts +0 -73
- package/apps/studio/test/capture-core.test.ts +0 -32
- package/apps/studio/test/capture-determinism-shape.test.ts +0 -135
- package/apps/studio/test/chat-attachments.test.ts +0 -117
- package/apps/studio/test/chat-context.test.ts +0 -129
- package/apps/studio/test/chat-markdown.test.tsx +0 -58
- package/apps/studio/test/clip-addressing.test.ts +0 -738
- package/apps/studio/test/clip-ops.test.ts +0 -922
- package/apps/studio/test/cloud-build.test.ts +0 -95
- package/apps/studio/test/cloud-connect-note.test.ts +0 -135
- package/apps/studio/test/cloud-endpoints.test.ts +0 -590
- package/apps/studio/test/cloud-history-hardening.test.ts +0 -165
- package/apps/studio/test/cloud-history-posture.test.ts +0 -230
- package/apps/studio/test/cloud-managed-save-surfaces.test.ts +0 -90
- package/apps/studio/test/cloud-renew.test.ts +0 -205
- package/apps/studio/test/cloud-session-role.test.ts +0 -161
- package/apps/studio/test/cloud-shell-surfaces.test.ts +0 -170
- package/apps/studio/test/cold-start-apply.test.ts +0 -303
- package/apps/studio/test/collab-annotations-bridge.test.ts +0 -55
- package/apps/studio/test/collab-awareness-bridge.test.ts +0 -223
- package/apps/studio/test/collab-bridge.test.ts +0 -79
- package/apps/studio/test/collab-loopback.test.ts +0 -63
- package/apps/studio/test/collab-origin-gate.test.ts +0 -323
- package/apps/studio/test/collab-protocol.test.ts +0 -146
- package/apps/studio/test/collab-readonly-gate.test.ts +0 -194
- package/apps/studio/test/collab-reseed-guard.test.ts +0 -78
- package/apps/studio/test/collab-room.test.ts +0 -188
- package/apps/studio/test/collab-session-survival.test.tsx +0 -176
- package/apps/studio/test/collab-stress.test.ts +0 -129
- package/apps/studio/test/comment-mount.test.ts +0 -97
- package/apps/studio/test/comment-relay-origin-gate.test.ts +0 -117
- package/apps/studio/test/comments-api.test.ts +0 -277
- package/apps/studio/test/comments-fs-rebroadcast.test.ts +0 -155
- package/apps/studio/test/comments-overlay.test.ts +0 -117
- package/apps/studio/test/compile-entry.test.ts +0 -133
- package/apps/studio/test/component-map.test.ts +0 -48
- package/apps/studio/test/config-projection.test.ts +0 -104
- package/apps/studio/test/config-reload.test.ts +0 -230
- package/apps/studio/test/config-version.test.ts +0 -88
- package/apps/studio/test/context-resolve-tokens.test.ts +0 -97
- package/apps/studio/test/convert-to-absolute.test.ts +0 -333
- package/apps/studio/test/credential-grammar.test.ts +0 -107
- package/apps/studio/test/csp-canvas-shell.test.ts +0 -62
- package/apps/studio/test/csrf-write-guard.test.ts +0 -141
- package/apps/studio/test/debug-bundle.test.ts +0 -105
- package/apps/studio/test/design-setup-readiness.test.ts +0 -155
- package/apps/studio/test/detach-component.test.ts +0 -94
- package/apps/studio/test/dns-rebinding-guard.test.ts +0 -101
- package/apps/studio/test/dom-selection.test.ts +0 -198
- package/apps/studio/test/dynamic-text-edit.test.ts +0 -162
- package/apps/studio/test/edit-css-occurrence.test.ts +0 -81
- package/apps/studio/test/edit-persistence.test.ts +0 -91
- package/apps/studio/test/edit-scope-api.test.ts +0 -119
- package/apps/studio/test/edit-source-command.test.ts +0 -142
- package/apps/studio/test/edit-suppress.test.ts +0 -170
- package/apps/studio/test/editing-presence.test.ts +0 -103
- package/apps/studio/test/element-resize.test.ts +0 -136
- package/apps/studio/test/element-structural-api.test.ts +0 -434
- package/apps/studio/test/element-structural-edit.test.ts +0 -750
- package/apps/studio/test/ensure-browser.test.ts +0 -92
- package/apps/studio/test/equal-spacing-detector.test.ts +0 -257
- package/apps/studio/test/export-assemble.test.ts +0 -53
- package/apps/studio/test/export-browser-lane.test.ts +0 -126
- package/apps/studio/test/export-capture-fidelity.test.ts +0 -146
- package/apps/studio/test/export-capture-hygiene.test.ts +0 -675
- package/apps/studio/test/export-center.test.tsx +0 -287
- package/apps/studio/test/export-e2e-lanes.test.ts +0 -857
- package/apps/studio/test/export-format-scope-coherence.test.ts +0 -89
- package/apps/studio/test/export-lane.test.ts +0 -245
- package/apps/studio/test/export-shim-multi-capture.test.ts +0 -83
- package/apps/studio/test/exporters/canva.test.ts +0 -63
- package/apps/studio/test/exporters/degraded-propagation.test.ts +0 -123
- package/apps/studio/test/exporters/endpoint.test.ts +0 -121
- package/apps/studio/test/exporters/history.test.ts +0 -107
- package/apps/studio/test/exporters/html.test.ts +0 -26
- package/apps/studio/test/exporters/jobs.test.ts +0 -342
- package/apps/studio/test/exporters/pdf.test.ts +0 -85
- package/apps/studio/test/exporters/png.test.ts +0 -103
- package/apps/studio/test/exporters/pptx-deck.test.ts +0 -112
- package/apps/studio/test/exporters/pptx.test.ts +0 -31
- package/apps/studio/test/exporters/pw-launch.test.ts +0 -49
- package/apps/studio/test/exporters/runtime.test.ts +0 -59
- package/apps/studio/test/exporters/scope.test.ts +0 -292
- package/apps/studio/test/exporters/svg.test.ts +0 -29
- package/apps/studio/test/exporters/unsupported-media.test.ts +0 -123
- package/apps/studio/test/exporters/zip.test.ts +0 -104
- package/apps/studio/test/fetch-asset-gate.test.ts +0 -189
- package/apps/studio/test/figjam-v3-model.test.ts +0 -342
- package/apps/studio/test/figma-explode.test.ts +0 -438
- package/apps/studio/test/figma-provenance.test.ts +0 -108
- package/apps/studio/test/figma-routes.test.ts +0 -294
- package/apps/studio/test/file-lock.test.ts +0 -84
- package/apps/studio/test/fixtures/fake-claude-auth.mjs +0 -13
- package/apps/studio/test/fixtures/figjam-v3-groups-bindings.svg +0 -1
- package/apps/studio/test/fixtures/mock-acp-agent-caps.mjs +0 -158
- package/apps/studio/test/fixtures/mock-acp-agent-commands.mjs +0 -44
- package/apps/studio/test/fixtures/mock-acp-agent-elicit-flood.mjs +0 -46
- package/apps/studio/test/fixtures/mock-acp-agent-elicit-url.mjs +0 -42
- package/apps/studio/test/fixtures/mock-acp-agent-elicit.mjs +0 -63
- package/apps/studio/test/fixtures/mock-acp-agent-permission-flood.mjs +0 -51
- package/apps/studio/test/fixtures/mock-acp-agent-permission.mjs +0 -50
- package/apps/studio/test/fixtures/mock-acp-agent-slow.mjs +0 -45
- package/apps/studio/test/fixtures/mock-acp-agent-usage.mjs +0 -56
- package/apps/studio/test/fixtures/mock-acp-agent-wedged.mjs +0 -37
- package/apps/studio/test/fixtures/mock-acp-agent-write.mjs +0 -118
- package/apps/studio/test/fixtures/mock-acp-agent.mjs +0 -69
- package/apps/studio/test/fixtures/perf-canvas.mjs +0 -201
- package/apps/studio/test/fixtures/phase-20-annotations.svg +0 -1
- package/apps/studio/test/fixtures/phase-21-annotations.svg +0 -1
- package/apps/studio/test/fixtures/tiny-subset.woff2 +0 -0
- package/apps/studio/test/fixtures/video-comp-fixture.tsx +0 -82
- package/apps/studio/test/footage-store.test.ts +0 -100
- package/apps/studio/test/fs-mkdir-api.test.ts +0 -248
- package/apps/studio/test/fs-watch.test.ts +0 -41
- package/apps/studio/test/gemma-models.test.ts +0 -245
- package/apps/studio/test/generate-route.test.ts +0 -106
- package/apps/studio/test/git-api.test.ts +0 -0
- package/apps/studio/test/git-branches.test.ts +0 -341
- package/apps/studio/test/git-cloud-posture.test.ts +0 -59
- package/apps/studio/test/git-grouping.test.ts +0 -106
- package/apps/studio/test/git-lifecycle.test.ts +0 -100
- package/apps/studio/test/git-log-format.test.ts +0 -95
- package/apps/studio/test/git-safe-rel.test.ts +0 -132
- package/apps/studio/test/git-system-engine.test.ts +0 -135
- package/apps/studio/test/git-watch.test.ts +0 -97
- package/apps/studio/test/github-api.test.ts +0 -577
- package/apps/studio/test/grid-track-handles.test.ts +0 -160
- package/apps/studio/test/handoff-static-frames.test.ts +0 -215
- package/apps/studio/test/handoff.test.ts +0 -329
- package/apps/studio/test/history-rollback.test.ts +0 -88
- package/apps/studio/test/hmr-broadcast.test.ts +0 -236
- package/apps/studio/test/hmr-classify.test.ts +0 -87
- package/apps/studio/test/hub-link.test.ts +0 -80
- package/apps/studio/test/identity-cache.test.ts +0 -83
- package/apps/studio/test/import-asset-browser.test.ts +0 -64
- package/apps/studio/test/import-asset-route.test.ts +0 -71
- package/apps/studio/test/import-asset.test.ts +0 -427
- package/apps/studio/test/import-brand-browser.test.ts +0 -88
- package/apps/studio/test/import-brand-route.test.ts +0 -120
- package/apps/studio/test/import-brand.test.ts +0 -206
- package/apps/studio/test/import-figma.test.ts +0 -667
- package/apps/studio/test/import-tokens.test.ts +0 -722
- package/apps/studio/test/index-data-canvas-ds.test.ts +0 -97
- package/apps/studio/test/input-router.test.ts +0 -757
- package/apps/studio/test/inspect-script-syntax.test.ts +0 -53
- package/apps/studio/test/inspect-selections.test.ts +0 -219
- package/apps/studio/test/knob-props-authored.test.ts +0 -87
- package/apps/studio/test/layers-synthetic-groups.test.ts +0 -96
- package/apps/studio/test/locator.test.ts +0 -214
- package/apps/studio/test/marquee-overlay.test.ts +0 -94
- package/apps/studio/test/media-commit-chain.test.ts +0 -210
- package/apps/studio/test/mode-toggle.test.tsx +0 -226
- package/apps/studio/test/motion-sample.test.ts +0 -35
- package/apps/studio/test/move-artboards-command.test.ts +0 -108
- package/apps/studio/test/participants-chrome.test.ts +0 -65
- package/apps/studio/test/paths.test.ts +0 -88
- package/apps/studio/test/pdf-print-boxes.test.ts +0 -359
- package/apps/studio/test/peer-selection-follows-camera.test.tsx +0 -131
- package/apps/studio/test/perf-harness.ts +0 -193
- package/apps/studio/test/phase-3.6-smoke.test.ts +0 -79
- package/apps/studio/test/photo-bg-remove-validation.test.ts +0 -71
- package/apps/studio/test/photo-canvas-bundle.test.ts +0 -79
- package/apps/studio/test/photo-edit-api.test.ts +0 -201
- package/apps/studio/test/photo-filters.test.ts +0 -149
- package/apps/studio/test/photo-pipeline.test.ts +0 -106
- package/apps/studio/test/photo-taxonomy.test.ts +0 -96
- package/apps/studio/test/print-marks.test.ts +0 -113
- package/apps/studio/test/print-units.test.ts +0 -173
- package/apps/studio/test/read-annotations.test.ts +0 -727
- package/apps/studio/test/read-only-gate.test.ts +0 -188
- package/apps/studio/test/read-only-role.test.ts +0 -95
- package/apps/studio/test/readiness.test.ts +0 -226
- package/apps/studio/test/remote-ahead-behind-cache.test.ts +0 -89
- package/apps/studio/test/reorder-api.test.ts +0 -210
- package/apps/studio/test/repo-concurrency.test.ts +0 -146
- package/apps/studio/test/repo-lock.test.ts +0 -350
- package/apps/studio/test/report-proxy.test.ts +0 -125
- package/apps/studio/test/ripple.test.ts +0 -197
- package/apps/studio/test/runtime-bundle-error-mapping.test.ts +0 -43
- package/apps/studio/test/runtime-bundle.test.ts +0 -69
- package/apps/studio/test/sanitize-annotation-svg.test.ts +0 -238
- package/apps/studio/test/scaffold-design.test.ts +0 -122
- package/apps/studio/test/server-lifecycle.test.ts +0 -38
- package/apps/studio/test/session-runtime-state.test.ts +0 -226
- package/apps/studio/test/session-scope.test.ts +0 -100
- package/apps/studio/test/shared-doc-cell-pairing.test.ts +0 -642
- package/apps/studio/test/shared-doc-convergence.test.ts +0 -265
- package/apps/studio/test/shared-doc-foundation.test.ts +0 -63
- package/apps/studio/test/shared-doc-migrate.test.ts +0 -369
- package/apps/studio/test/shared-doc-projection.test.ts +0 -238
- package/apps/studio/test/shell-importmap.test.ts +0 -56
- package/apps/studio/test/sizing-mode.test.ts +0 -102
- package/apps/studio/test/slash-commands.test.ts +0 -117
- package/apps/studio/test/snap-distance-pill.test.ts +0 -68
- package/apps/studio/test/spacing-handles.test.ts +0 -138
- package/apps/studio/test/specimen-select.test.ts +0 -88
- package/apps/studio/test/sync-agent.test.ts +0 -660
- package/apps/studio/test/sync-annotations-cold-start.test.ts +0 -302
- package/apps/studio/test/sync-asset-push.test.ts +0 -931
- package/apps/studio/test/sync-atomic-write.test.ts +0 -62
- package/apps/studio/test/sync-attach-incremental.test.ts +0 -527
- package/apps/studio/test/sync-autocommit.test.ts +0 -537
- package/apps/studio/test/sync-canvas-path.test.ts +0 -200
- package/apps/studio/test/sync-cell-write-nudge.test.ts +0 -346
- package/apps/studio/test/sync-codec.test.ts +0 -230
- package/apps/studio/test/sync-cold-seed-dedup.test.ts +0 -187
- package/apps/studio/test/sync-cold-start.test.ts +0 -304
- package/apps/studio/test/sync-connect-honesty.test.ts +0 -114
- package/apps/studio/test/sync-connection-state.test.ts +0 -337
- package/apps/studio/test/sync-ctl-channel.test.ts +0 -508
- package/apps/studio/test/sync-decide-file.test.ts +0 -420
- package/apps/studio/test/sync-doc-name.test.ts +0 -281
- package/apps/studio/test/sync-echo-guard.test.ts +0 -96
- package/apps/studio/test/sync-file-ledger.test.ts +0 -334
- package/apps/studio/test/sync-file-membership.test.ts +0 -347
- package/apps/studio/test/sync-file-plane.test.ts +0 -976
- package/apps/studio/test/sync-file-pull.test.ts +0 -333
- package/apps/studio/test/sync-fresh-link-parity.test.ts +0 -267
- package/apps/studio/test/sync-fs-mirror.test.ts +0 -181
- package/apps/studio/test/sync-hardening.test.ts +0 -586
- package/apps/studio/test/sync-hub-listing.test.ts +0 -46
- package/apps/studio/test/sync-hubs-config.test.ts +0 -133
- package/apps/studio/test/sync-incident-replay.test.ts +0 -211
- package/apps/studio/test/sync-journal.test.ts +0 -176
- package/apps/studio/test/sync-meta-codec.test.ts +0 -199
- package/apps/studio/test/sync-migrate-flat-fallback.test.ts +0 -98
- package/apps/studio/test/sync-move-retirement.test.ts +0 -231
- package/apps/studio/test/sync-panel-surface.test.ts +0 -153
- package/apps/studio/test/sync-path-pull.test.ts +0 -531
- package/apps/studio/test/sync-presentation.test.ts +0 -262
- package/apps/studio/test/sync-pull-budget.test.ts +0 -169
- package/apps/studio/test/sync-remote-docs.test.ts +0 -333
- package/apps/studio/test/sync-resync-routes.test.ts +0 -168
- package/apps/studio/test/sync-runtime.test.ts +0 -1675
- package/apps/studio/test/sync-seed-defers-to-hub.test.ts +0 -83
- package/apps/studio/test/sync-settings-routes.test.ts +0 -195
- package/apps/studio/test/sync-settings.test.ts +0 -151
- package/apps/studio/test/sync-status.test.ts +0 -261
- package/apps/studio/test/sync-supervisor.test.ts +0 -262
- package/apps/studio/test/sync-tombstone-apply.test.ts +0 -111
- package/apps/studio/test/sync-trash.test.ts +0 -132
- package/apps/studio/test/sync-two-peer-discovery.test.ts +0 -343
- package/apps/studio/test/sync-untrusted.test.ts +0 -103
- package/apps/studio/test/system-endpoint.test.ts +0 -144
- package/apps/studio/test/text-editability-stamp.test.ts +0 -131
- package/apps/studio/test/timeline-comp-target.test.ts +0 -139
- package/apps/studio/test/timeline-media-cache.test.ts +0 -41
- package/apps/studio/test/timeline-parse.test.ts +0 -184
- package/apps/studio/test/timeline-scale.test.ts +0 -65
- package/apps/studio/test/timeline-snap.test.ts +0 -85
- package/apps/studio/test/tool-palette-insert-anchor.test.ts +0 -86
- package/apps/studio/test/tool-palette.test.tsx +0 -55
- package/apps/studio/test/tour-overlay.test.tsx +0 -90
- package/apps/studio/test/trusted-request-host.test.ts +0 -66
- package/apps/studio/test/undo-sequence-byte-compare.test.ts +0 -211
- package/apps/studio/test/undo-stack.test.ts +0 -244
- package/apps/studio/test/use-agent-presence.test.tsx +0 -117
- package/apps/studio/test/use-annotation-resize.test.ts +0 -402
- package/apps/studio/test/use-annotation-selection.test.tsx +0 -77
- package/apps/studio/test/use-artboard-drag.test.ts +0 -324
- package/apps/studio/test/use-canvas-activity.test.tsx +0 -206
- package/apps/studio/test/use-collab.test.ts +0 -0
- package/apps/studio/test/use-cursor-modifiers.test.ts +0 -59
- package/apps/studio/test/use-keyboard-discipline.test.ts +0 -27
- package/apps/studio/test/use-selection-set.test.tsx +0 -166
- package/apps/studio/test/use-snap-guides.test.ts +0 -271
- package/apps/studio/test/use-tool-mode.test.tsx +0 -186
- package/apps/studio/test/use-undo-stack.test.tsx +0 -223
- package/apps/studio/test/video-asset.test.ts +0 -163
- package/apps/studio/test/video-comp-fixture.test.ts +0 -50
- package/apps/studio/test/video-comp.test.ts +0 -270
- package/apps/studio/test/video-encode-lib.test.ts +0 -63
- package/apps/studio/test/video-render-bridge.test.ts +0 -171
- package/apps/studio/test/whats-new.test.ts +0 -113
- package/apps/studio/test/whisper-setup.test.ts +0 -97
- package/apps/studio/test/workspace-containment.test.ts +0 -382
- package/apps/studio/test/workspace-signin.test.ts +0 -292
- package/apps/studio/test/ws-handshake.test.ts +0 -33
- package/cli/commands/cache.test.mjs +0 -166
- package/cli/commands/design-link.test.mjs +0 -419
- package/cli/commands/design.test.mjs +0 -240
- package/cli/commands/doctor.test.mjs +0 -237
- package/cli/commands/hub-workspace.test.mjs +0 -275
- package/cli/commands/hub.test.mjs +0 -225
- package/cli/commands/kg.test.mjs +0 -142
- package/cli/commands/preflight.test.mjs +0 -46
- package/cli/lib/argv.test.mjs +0 -46
- package/cli/lib/cache.test.mjs +0 -303
- package/cli/lib/cell-plan.test.mjs +0 -225
- package/cli/lib/config-lint.test.mjs +0 -117
- package/cli/lib/ddr-to-kgai.test.mjs +0 -118
- package/cli/lib/design-ownership.test.mjs +0 -329
- package/cli/lib/fetch-asset.test.mjs +0 -213
- package/cli/lib/figma-codegen-reachability.test.mjs +0 -104
- package/cli/lib/figma-import-controls.test.mjs +0 -70
- package/cli/lib/flow-design-integration.test.mjs +0 -165
- package/cli/lib/gitignore-block.test.mjs +0 -136
- package/cli/lib/gitignore-drift.test.mjs +0 -156
- package/cli/lib/hubs-config.test.mjs +0 -165
- package/cli/lib/pkg-root.test.mjs +0 -111
- package/cli/lib/plugin-cli-reachability.test.mjs +0 -57
- package/cli/lib/plugin-name-namespace.test.mjs +0 -71
- package/cli/lib/reconstruct-toolset.test.mjs +0 -194
- package/cli/lib/stack-detect.test.mjs +0 -121
- package/cli/lib/update-check.test.mjs +0 -32
- package/cli/lib/workspace-plan.test.mjs +0 -699
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
// artboard-guides-overlay — feature-1-artboard-kinds-foundation, T4.
|
|
2
|
-
// Registry contract + generic guides rendering. Pure renderToStaticMarkup —
|
|
3
|
-
// this component has no hooks/context, so (unlike DCArtboard's own overlays)
|
|
4
|
-
// it renders fully outside a live DesignCanvas.
|
|
5
|
-
|
|
6
|
-
import { afterEach, describe, expect, test } from 'bun:test';
|
|
7
|
-
|
|
8
|
-
import { renderToStaticMarkup } from 'react-dom/server';
|
|
9
|
-
|
|
10
|
-
import {
|
|
11
|
-
__resetKindOverlayRegistryForTests,
|
|
12
|
-
ArtboardGuidesOverlay,
|
|
13
|
-
registerKindOverlay,
|
|
14
|
-
} from '../artboard-guides-overlay.tsx';
|
|
15
|
-
|
|
16
|
-
const RECT = { x: 10, y: 20, w: 400, h: 200 };
|
|
17
|
-
|
|
18
|
-
afterEach(() => {
|
|
19
|
-
__resetKindOverlayRegistryForTests();
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
describe('ArtboardGuidesOverlay — generic guides', () => {
|
|
23
|
-
test('renders nothing with no guides and no registered kind content', () => {
|
|
24
|
-
const html = renderToStaticMarkup(
|
|
25
|
-
<ArtboardGuidesOverlay rect={RECT} kind="digital" visibility={{}} />
|
|
26
|
-
);
|
|
27
|
-
expect(html).toBe('');
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
test('positions the overlay at the artboard world rect', () => {
|
|
31
|
-
const html = renderToStaticMarkup(
|
|
32
|
-
<ArtboardGuidesOverlay
|
|
33
|
-
rect={RECT}
|
|
34
|
-
kind="print"
|
|
35
|
-
guides={{ grid: { size: 40 } }}
|
|
36
|
-
visibility={{ guides: true }}
|
|
37
|
-
/>
|
|
38
|
-
);
|
|
39
|
-
expect(html).toMatch(/left:\s*10px/);
|
|
40
|
-
expect(html).toMatch(/top:\s*20px/);
|
|
41
|
-
expect(html).toMatch(/width:\s*400px/);
|
|
42
|
-
expect(html).toMatch(/height:\s*200px/);
|
|
43
|
-
expect(html).toContain('aria-hidden="true"');
|
|
44
|
-
expect(html).toContain('pointer-events:none');
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
test('visibility.guides === false suppresses the generic guides', () => {
|
|
48
|
-
const html = renderToStaticMarkup(
|
|
49
|
-
<ArtboardGuidesOverlay
|
|
50
|
-
rect={RECT}
|
|
51
|
-
kind="print"
|
|
52
|
-
guides={{ grid: { size: 40 } }}
|
|
53
|
-
visibility={{ guides: false }}
|
|
54
|
-
/>
|
|
55
|
-
);
|
|
56
|
-
expect(html).toBe('');
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
test('columns render as one band per column, respecting margin/gutter', () => {
|
|
60
|
-
const html = renderToStaticMarkup(
|
|
61
|
-
<ArtboardGuidesOverlay
|
|
62
|
-
rect={RECT}
|
|
63
|
-
kind="web"
|
|
64
|
-
guides={{ columns: { count: 4, gutter: 10, margin: 20 } }}
|
|
65
|
-
visibility={{ guides: true }}
|
|
66
|
-
/>
|
|
67
|
-
);
|
|
68
|
-
// usable = 400 - 2*20 = 360; (360 - 3*10) / 4 = 82.5px per column, 4 bands.
|
|
69
|
-
const bandCount = (html.match(/width:82\.5px/g) || []).length;
|
|
70
|
-
expect(bandCount).toBe(4);
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
// Security review (defender + adversarial pass, /flow:done on 0e001da7) —
|
|
74
|
-
// columns/rows `count` had no cap, unlike the grid path: a malicious/
|
|
75
|
-
// poisoned canvas (guides is an authored JSX prop, part of the DDR-054
|
|
76
|
-
// untrusted-canvas surface) could set `columns.count` to a huge number and
|
|
77
|
-
// mount one <div> per band, freezing the viewer's tab. Regression-tests the
|
|
78
|
-
// MAX_BANDS_PER_AXIS clamp both independent reviews confirmed as the fix.
|
|
79
|
-
test('a pathologically large column count is clamped, never a runaway render', () => {
|
|
80
|
-
const html = renderToStaticMarkup(
|
|
81
|
-
<ArtboardGuidesOverlay
|
|
82
|
-
rect={RECT}
|
|
83
|
-
kind="web"
|
|
84
|
-
guides={{ columns: { count: 1_000_000_000, gutter: 0, margin: 0 } }}
|
|
85
|
-
visibility={{ guides: true }}
|
|
86
|
-
/>
|
|
87
|
-
);
|
|
88
|
-
const bandCount = (html.match(/position:absolute/g) || []).length - 1; // minus the wrapper div
|
|
89
|
-
expect(bandCount).toBeLessThanOrEqual(64);
|
|
90
|
-
expect(bandCount).toBeGreaterThan(0);
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
test('a pathologically large row count is clamped the same way', () => {
|
|
94
|
-
const html = renderToStaticMarkup(
|
|
95
|
-
<ArtboardGuidesOverlay
|
|
96
|
-
rect={RECT}
|
|
97
|
-
kind="web"
|
|
98
|
-
guides={{ rows: { count: 999_999_999, gutter: 0, margin: 0 } }}
|
|
99
|
-
visibility={{ guides: true }}
|
|
100
|
-
/>
|
|
101
|
-
);
|
|
102
|
-
const bandCount = (html.match(/position:absolute/g) || []).length - 1;
|
|
103
|
-
expect(bandCount).toBeLessThanOrEqual(64);
|
|
104
|
-
expect(bandCount).toBeGreaterThan(0);
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
test('grid lines are capped, never runaway for a degenerate small size', () => {
|
|
108
|
-
const html = renderToStaticMarkup(
|
|
109
|
-
<ArtboardGuidesOverlay
|
|
110
|
-
rect={{ x: 0, y: 0, w: 5000, h: 5000 }}
|
|
111
|
-
kind="digital"
|
|
112
|
-
guides={{ grid: { size: 2 } }}
|
|
113
|
-
visibility={{ guides: true }}
|
|
114
|
-
/>
|
|
115
|
-
);
|
|
116
|
-
const lineCount = (html.match(/width:1px/g) || []).length;
|
|
117
|
-
expect(lineCount).toBeLessThanOrEqual(400);
|
|
118
|
-
});
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
describe('ArtboardGuidesOverlay — per-kind registry', () => {
|
|
122
|
-
test('registered kind renderer is invoked with rect/kind/guides/visibility', () => {
|
|
123
|
-
let seen: unknown;
|
|
124
|
-
registerKindOverlay('print', (props) => {
|
|
125
|
-
seen = props;
|
|
126
|
-
return <div data-testid="print-bleed" />;
|
|
127
|
-
});
|
|
128
|
-
const html = renderToStaticMarkup(
|
|
129
|
-
<ArtboardGuidesOverlay rect={RECT} kind="print" visibility={{ bleed: true }} />
|
|
130
|
-
);
|
|
131
|
-
expect(html).toContain('data-testid="print-bleed"');
|
|
132
|
-
expect(seen).toMatchObject({ rect: RECT, kind: 'print', visibility: { bleed: true } });
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
test('a renderer registered for one kind does not fire for another', () => {
|
|
136
|
-
registerKindOverlay('web', () => <div data-testid="breakpoint-band" />);
|
|
137
|
-
const html = renderToStaticMarkup(
|
|
138
|
-
<ArtboardGuidesOverlay rect={RECT} kind="print" visibility={{}} />
|
|
139
|
-
);
|
|
140
|
-
expect(html).not.toContain('breakpoint-band');
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
test('re-registering the same kind replaces the previous renderer (HMR-safe)', () => {
|
|
144
|
-
registerKindOverlay('print', () => <div data-testid="v1" />);
|
|
145
|
-
registerKindOverlay('print', () => <div data-testid="v2" />);
|
|
146
|
-
const html = renderToStaticMarkup(
|
|
147
|
-
<ArtboardGuidesOverlay rect={RECT} kind="print" visibility={{}} />
|
|
148
|
-
);
|
|
149
|
-
expect(html).not.toContain('v1');
|
|
150
|
-
expect(html).toContain('v2');
|
|
151
|
-
});
|
|
152
|
-
});
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
// artboard-hug-commit.ts — issue #79. The Artboard Inspector's Height
|
|
2
|
-
// NumberField silently dropped a typed value whenever the artboard was in
|
|
3
|
-
// Hug mode (fixed=false, the default per DDR-027 Design Decision 1) — Width
|
|
4
|
-
// always worked because it has no such mode. Typing a height should instead
|
|
5
|
-
// promote the artboard to Fixed at that height, same as the Hug/Fixed
|
|
6
|
-
// toggle's own freeze-current-height write.
|
|
7
|
-
|
|
8
|
-
import { describe, expect, test } from 'bun:test';
|
|
9
|
-
|
|
10
|
-
import { resolveHeightCommit } from '../artboard-hug-commit.ts';
|
|
11
|
-
|
|
12
|
-
describe('artboard-hug-commit / resolveHeightCommit', () => {
|
|
13
|
-
test('fixed=true → plain resize (Width-field parity)', () => {
|
|
14
|
-
expect(resolveHeightCommit(true, 480)).toEqual({ kind: 'resize', height: 480 });
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
test('fixed=false (Hug, the default) → promotes to Fixed at the typed height', () => {
|
|
18
|
-
// Before the fix this typed value was dropped entirely (no action) —
|
|
19
|
-
// reproducing "when I want to set height... manually from inspector
|
|
20
|
-
// panel, nothing happened. Width works."
|
|
21
|
-
expect(resolveHeightCommit(false, 480)).toEqual({ kind: 'promote-to-fixed', height: 480 });
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
test('rounds a fractional typed value', () => {
|
|
25
|
-
expect(resolveHeightCommit(true, 480.6)).toEqual({ kind: 'resize', height: 481 });
|
|
26
|
-
expect(resolveHeightCommit(false, 480.6)).toEqual({ kind: 'promote-to-fixed', height: 481 });
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
test('non-finite or non-positive input → noop, in either mode', () => {
|
|
30
|
-
expect(resolveHeightCommit(true, Number.NaN)).toEqual({ kind: 'noop' });
|
|
31
|
-
expect(resolveHeightCommit(true, 0)).toEqual({ kind: 'noop' });
|
|
32
|
-
expect(resolveHeightCommit(true, -10)).toEqual({ kind: 'noop' });
|
|
33
|
-
expect(resolveHeightCommit(false, Number.NaN)).toEqual({ kind: 'noop' });
|
|
34
|
-
expect(resolveHeightCommit(false, 0)).toEqual({ kind: 'noop' });
|
|
35
|
-
});
|
|
36
|
-
});
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
// artboard-kinds — feature-1-artboard-kinds-foundation, T1/T2.
|
|
2
|
-
//
|
|
3
|
-
// DCArtboard rendered OUTSIDE a DesignCanvas (no WorldContext, no rect) takes
|
|
4
|
-
// the specimen/legacy early-return branch — it still computes + emits the
|
|
5
|
-
// resolved `data-dc-kind` attribute (readBackAttrs is built before the
|
|
6
|
-
// `!ctx || !rect` check), so that resolution logic is testable via
|
|
7
|
-
// renderToStaticMarkup without a live DOM/layout pass. The label-strip kind
|
|
8
|
-
// chip (T3) only renders in the full DesignCanvas layout path (like the
|
|
9
|
-
// video corner badge it sits beside) — covered by /design:smoke, not here
|
|
10
|
-
// (see use-canvas-activity.test.tsx's header comment for the same split).
|
|
11
|
-
|
|
12
|
-
import { describe, expect, test } from 'bun:test';
|
|
13
|
-
|
|
14
|
-
import { renderToStaticMarkup } from 'react-dom/server';
|
|
15
|
-
|
|
16
|
-
import { DCArtboard } from '../canvas-lib.tsx';
|
|
17
|
-
|
|
18
|
-
// Minimal displayName-only stand-in for VideoComp — subtreeHasVideoComp
|
|
19
|
-
// identity-matches OR falls back to `displayName === 'VideoComp'` (the same
|
|
20
|
-
// fallback minified builds rely on), so this exercises the fallback path
|
|
21
|
-
// without pulling in the real VideoComp's rendering/registration machinery.
|
|
22
|
-
function FakeVideoComp() {
|
|
23
|
-
return null;
|
|
24
|
-
}
|
|
25
|
-
FakeVideoComp.displayName = 'VideoComp';
|
|
26
|
-
|
|
27
|
-
describe('DCArtboard kind resolution (data-dc-kind readback)', () => {
|
|
28
|
-
test('absent kind, no video subtree ⇒ digital', () => {
|
|
29
|
-
const html = renderToStaticMarkup(
|
|
30
|
-
<DCArtboard id="a" label="A" width={100} height={100}>
|
|
31
|
-
hi
|
|
32
|
-
</DCArtboard>
|
|
33
|
-
);
|
|
34
|
-
expect(html).toContain('data-dc-kind="digital"');
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
test('explicit kind="print" is emitted verbatim', () => {
|
|
38
|
-
const html = renderToStaticMarkup(
|
|
39
|
-
<DCArtboard id="a" label="A" width={100} height={100} kind="print">
|
|
40
|
-
hi
|
|
41
|
-
</DCArtboard>
|
|
42
|
-
);
|
|
43
|
-
expect(html).toContain('data-dc-kind="print"');
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
test('explicit kind="web" is emitted verbatim', () => {
|
|
47
|
-
const html = renderToStaticMarkup(
|
|
48
|
-
<DCArtboard id="a" label="A" width={100} height={100} kind="web">
|
|
49
|
-
hi
|
|
50
|
-
</DCArtboard>
|
|
51
|
-
);
|
|
52
|
-
expect(html).toContain('data-dc-kind="web"');
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
test('absent kind + VideoComp subtree ⇒ video fallback (Design Decision 1)', () => {
|
|
56
|
-
const html = renderToStaticMarkup(
|
|
57
|
-
<DCArtboard id="a" label="A" width={100} height={100}>
|
|
58
|
-
<FakeVideoComp />
|
|
59
|
-
</DCArtboard>
|
|
60
|
-
);
|
|
61
|
-
expect(html).toContain('data-dc-kind="video"');
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
test('explicit kind="digital" supersedes a VideoComp subtree', () => {
|
|
65
|
-
const html = renderToStaticMarkup(
|
|
66
|
-
<DCArtboard id="a" label="A" width={100} height={100} kind="digital">
|
|
67
|
-
<FakeVideoComp />
|
|
68
|
-
</DCArtboard>
|
|
69
|
-
);
|
|
70
|
-
expect(html).toContain('data-dc-kind="digital"');
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
test('digital kind (default) carries no other resolved-kind attribute value', () => {
|
|
74
|
-
const html = renderToStaticMarkup(
|
|
75
|
-
<DCArtboard id="a" label="A" width={100} height={100}>
|
|
76
|
-
hi
|
|
77
|
-
</DCArtboard>
|
|
78
|
-
);
|
|
79
|
-
expect(html).not.toContain('data-dc-kind="print"');
|
|
80
|
-
expect(html).not.toContain('data-dc-kind="web"');
|
|
81
|
-
expect(html).not.toContain('data-dc-kind="video"');
|
|
82
|
-
});
|
|
83
|
-
});
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
// Dogfood follow-up (print artboards) — whole-ARTBOARD selections must carry
|
|
2
|
-
// the DCArtboard readBack attrs (`data-dc-kind`, `data-dc-print`, `data-dc-
|
|
3
|
-
// fixed`, `data-dc-bg`, …) in `Selection.attrs`, because the Inspector's
|
|
4
|
-
// ArtboardKnobs panel pre-fills its Kind picker / paper preset / Hug toggle /
|
|
5
|
-
// Style fields from exactly these. ATTR_SKIP deliberately hides `data-dc-*`
|
|
6
|
-
// from the generic custom-attributes surface on ORDINARY elements — the bug
|
|
7
|
-
// was that the blanket skip also applied to the artboard element itself, so
|
|
8
|
-
// every readback silently fell back to its default ('digital', screen
|
|
9
|
-
// presets, Hug, empty Bg) no matter what the artboard actually was.
|
|
10
|
-
//
|
|
11
|
-
// Same happy-dom + hoverTargetToSelection harness as knob-props-authored.
|
|
12
|
-
|
|
13
|
-
import { afterAll, beforeAll, describe, expect, test } from 'bun:test';
|
|
14
|
-
import { GlobalRegistrator } from '@happy-dom/global-registrator';
|
|
15
|
-
|
|
16
|
-
beforeAll(() => {
|
|
17
|
-
GlobalRegistrator.register();
|
|
18
|
-
});
|
|
19
|
-
afterAll(() => {
|
|
20
|
-
GlobalRegistrator.unregister();
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
import { hoverTargetToSelection } from '../dom-selection.ts';
|
|
24
|
-
import type { HoverTarget } from '../input-router.tsx';
|
|
25
|
-
|
|
26
|
-
function artboardSelection(attrsHtml: string) {
|
|
27
|
-
document.body.innerHTML = `<article class="dc-artboard" data-dc-screen="ab-1" ${attrsHtml}><div>content</div></article>`;
|
|
28
|
-
const el = document.querySelector('[data-dc-screen]') as HTMLElement;
|
|
29
|
-
const target: HoverTarget = { el, cdId: null, artboardId: 'ab-1' };
|
|
30
|
-
return hoverTargetToSelection(target);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
describe('whole-artboard selection — data-dc-* readback attrs', () => {
|
|
34
|
-
test('data-dc-kind + data-dc-print reach Selection.attrs (the ArtboardKnobs payload)', () => {
|
|
35
|
-
const sel = artboardSelection(
|
|
36
|
-
'data-dc-kind="print" data-dc-print=\'{"paper":"a4","bleedMm":3}\''
|
|
37
|
-
);
|
|
38
|
-
expect(sel.attrs?.['data-dc-kind']).toBe('print');
|
|
39
|
-
expect(sel.attrs?.['data-dc-print']).toBe('{"paper":"a4","bleedMm":3}');
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
test('the other readback attrs come through too (fixed/bg/padding/layout/gap)', () => {
|
|
43
|
-
const sel = artboardSelection(
|
|
44
|
-
'data-dc-kind="digital" data-dc-fixed="true" data-dc-bg="var(--bg-1)" data-dc-padding="16" data-dc-layout="flex-col" data-dc-gap="8"'
|
|
45
|
-
);
|
|
46
|
-
expect(sel.attrs?.['data-dc-fixed']).toBe('true');
|
|
47
|
-
expect(sel.attrs?.['data-dc-bg']).toBe('var(--bg-1)');
|
|
48
|
-
expect(sel.attrs?.['data-dc-padding']).toBe('16');
|
|
49
|
-
expect(sel.attrs?.['data-dc-layout']).toBe('flex-col');
|
|
50
|
-
expect(sel.attrs?.['data-dc-gap']).toBe('8');
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
test('an ORDINARY element (no data-dc-screen) keeps the data-dc-* filter', () => {
|
|
54
|
-
document.body.innerHTML =
|
|
55
|
-
'<div data-cd-id="bbbbbbbb" data-dc-kind="print" data-custom="yes">x</div>';
|
|
56
|
-
const el = document.querySelector('[data-cd-id]') as HTMLElement;
|
|
57
|
-
const target: HoverTarget = { el, cdId: 'bbbbbbbb', artboardId: null };
|
|
58
|
-
const sel = hoverTargetToSelection(target);
|
|
59
|
-
// Engine plumbing stays hidden from the generic custom-attributes panel…
|
|
60
|
-
expect(sel.attrs?.['data-dc-kind']).toBeUndefined();
|
|
61
|
-
// …while genuinely custom attributes still surface.
|
|
62
|
-
expect(sel.attrs?.['data-custom']).toBe('yes');
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
test('data-dc-screen itself is included for the artboard (harmless, self-describing)', () => {
|
|
66
|
-
const sel = artboardSelection('data-dc-kind="print"');
|
|
67
|
-
expect(sel.attrs?.['data-dc-screen']).toBe('ab-1');
|
|
68
|
-
});
|
|
69
|
-
});
|
|
@@ -1,149 +0,0 @@
|
|
|
1
|
-
// POST /_api/asset — Phase 23 content-addressed image upload (Task 5).
|
|
2
|
-
//
|
|
3
|
-
// Two layers:
|
|
4
|
-
// (1) the pure magic-byte sniff (`sniffImageType`) — the ONE gate that decides
|
|
5
|
-
// the stored type; a header lie / SVG is caught here;
|
|
6
|
-
// (2) the POST endpoint round-trip (boots a real server against a sandbox) —
|
|
7
|
-
// happy path for all four types, header-lie, oversize, SVG-reject,
|
|
8
|
-
// content-addressed dedupe, method gate.
|
|
9
|
-
|
|
10
|
-
import { describe, expect, test } from 'bun:test';
|
|
11
|
-
import { existsSync, readdirSync } from 'node:fs';
|
|
12
|
-
import { join } from 'node:path';
|
|
13
|
-
|
|
14
|
-
import { ASSET_MAX_BYTES, sniffImageType } from '../api.ts';
|
|
15
|
-
import { bootServer, killProc, makeSandbox, nextPort } from './_helpers.ts';
|
|
16
|
-
|
|
17
|
-
// ── Minimal valid magic-byte headers (padded so length checks pass). ──────────
|
|
18
|
-
const pad = (header: number[], len = 64): Uint8Array => {
|
|
19
|
-
const out = new Uint8Array(len);
|
|
20
|
-
out.set(header, 0);
|
|
21
|
-
return out;
|
|
22
|
-
};
|
|
23
|
-
const PNG = pad([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
|
|
24
|
-
const JPEG = pad([0xff, 0xd8, 0xff, 0xe0]);
|
|
25
|
-
const GIF = pad([0x47, 0x49, 0x46, 0x38, 0x39, 0x61]); // "GIF89a"
|
|
26
|
-
const WEBP = pad([0x52, 0x49, 0x46, 0x46, 0, 0, 0, 0, 0x57, 0x45, 0x42, 0x50]); // RIFF????WEBP
|
|
27
|
-
const SVG = new TextEncoder().encode('<svg xmlns="http://www.w3.org/2000/svg"><script/></svg>');
|
|
28
|
-
|
|
29
|
-
describe('asset-api / sniffImageType (the type gate)', () => {
|
|
30
|
-
test('recognizes each supported raster type by magic bytes', () => {
|
|
31
|
-
expect(sniffImageType(PNG)).toBe('png');
|
|
32
|
-
expect(sniffImageType(JPEG)).toBe('jpg');
|
|
33
|
-
expect(sniffImageType(GIF)).toBe('gif');
|
|
34
|
-
expect(sniffImageType(WEBP)).toBe('webp');
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
test('rejects SVG / text / empty / truncated headers', () => {
|
|
38
|
-
expect(sniffImageType(SVG)).toBeNull();
|
|
39
|
-
expect(sniffImageType(new TextEncoder().encode('not an image'))).toBeNull();
|
|
40
|
-
expect(sniffImageType(new Uint8Array(0))).toBeNull();
|
|
41
|
-
// Truncated PNG signature (only 4 of 8 bytes) must NOT match.
|
|
42
|
-
expect(sniffImageType(new Uint8Array([0x89, 0x50, 0x4e, 0x47]))).toBeNull();
|
|
43
|
-
// RIFF without the WEBP fourcc (e.g. a WAV) must NOT match.
|
|
44
|
-
expect(
|
|
45
|
-
sniffImageType(pad([0x52, 0x49, 0x46, 0x46, 0, 0, 0, 0, 0x57, 0x41, 0x56, 0x45]))
|
|
46
|
-
).toBeNull();
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
test('content addresses the stored ext (a .png NAME with GIF bytes sniffs gif)', () => {
|
|
50
|
-
// The route names the file from sniffImageType(bytes), never the upload name.
|
|
51
|
-
expect(sniffImageType(GIF)).toBe('gif');
|
|
52
|
-
});
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
describe('asset-api / POST /_api/asset (endpoint round-trip)', () => {
|
|
56
|
-
async function withServer(
|
|
57
|
-
fn: (port: number, designRoot: string) => Promise<void>,
|
|
58
|
-
extraEnv?: Record<string, string>
|
|
59
|
-
) {
|
|
60
|
-
const sandbox = makeSandbox();
|
|
61
|
-
const port = nextPort();
|
|
62
|
-
const proc = await bootServer(sandbox.root, port, extraEnv);
|
|
63
|
-
try {
|
|
64
|
-
await fn(port, sandbox.designRoot);
|
|
65
|
-
} finally {
|
|
66
|
-
await killProc(proc);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const postAsset = (port: number, body: Uint8Array, contentType = 'application/octet-stream') =>
|
|
71
|
-
fetch(`http://localhost:${port}/_api/asset`, {
|
|
72
|
-
method: 'POST',
|
|
73
|
-
headers: { 'Content-Type': contentType },
|
|
74
|
-
body,
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
test('writes a valid PNG/JPEG/WEBP/GIF and returns its assets path', async () => {
|
|
78
|
-
await withServer(async (port, designRoot) => {
|
|
79
|
-
for (const [bytes, ext] of [
|
|
80
|
-
[PNG, 'png'],
|
|
81
|
-
[JPEG, 'jpg'],
|
|
82
|
-
[WEBP, 'webp'],
|
|
83
|
-
[GIF, 'gif'],
|
|
84
|
-
] as const) {
|
|
85
|
-
const res = await postAsset(port, bytes);
|
|
86
|
-
expect(res.status).toBe(201);
|
|
87
|
-
const json = (await res.json()) as { path: string };
|
|
88
|
-
expect(json.path).toMatch(new RegExp(`^assets/[0-9a-f]{8}\\.${ext}$`));
|
|
89
|
-
expect(existsSync(join(designRoot, json.path))).toBe(true);
|
|
90
|
-
}
|
|
91
|
-
});
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
test('a header-lie (declared image/png, GIF bytes) is stored as .gif (sniff wins)', async () => {
|
|
95
|
-
await withServer(async (port) => {
|
|
96
|
-
const res = await postAsset(port, GIF, 'image/png');
|
|
97
|
-
expect(res.status).toBe(201);
|
|
98
|
-
const json = (await res.json()) as { path: string };
|
|
99
|
-
expect(json.path.endsWith('.gif')).toBe(true);
|
|
100
|
-
});
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
test('rejects an SVG upload (no script-bearing vector) with 415', async () => {
|
|
104
|
-
await withServer(async (port) => {
|
|
105
|
-
const res = await postAsset(port, SVG, 'image/svg+xml');
|
|
106
|
-
expect(res.status).toBe(415);
|
|
107
|
-
});
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
test('rejects an oversize body (> ASSET_MAX_BYTES) with 413', async () => {
|
|
111
|
-
await withServer(async (port) => {
|
|
112
|
-
const big = new Uint8Array(ASSET_MAX_BYTES + 1);
|
|
113
|
-
big.set([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a], 0); // valid PNG header
|
|
114
|
-
const res = await postAsset(port, big);
|
|
115
|
-
expect(res.status).toBe(413);
|
|
116
|
-
});
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
test('identical bytes dedupe to ONE file (content-addressed; disk-fill guard)', async () => {
|
|
120
|
-
await withServer(async (port, designRoot) => {
|
|
121
|
-
const a = await (await postAsset(port, PNG)).json();
|
|
122
|
-
const b = await (await postAsset(port, PNG)).json();
|
|
123
|
-
expect(a.path).toBe(b.path);
|
|
124
|
-
const files = readdirSync(join(designRoot, 'assets'));
|
|
125
|
-
expect(files.length).toBe(1);
|
|
126
|
-
});
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
test('GET /_api/asset is method-not-allowed (write-only)', async () => {
|
|
130
|
-
await withServer(async (port) => {
|
|
131
|
-
const res = await fetch(`http://localhost:${port}/_api/asset`);
|
|
132
|
-
expect(res.status).toBe(405);
|
|
133
|
-
});
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
test('enforces the aggregate session write budget (disk-fill guard → 429)', async () => {
|
|
137
|
-
// Budget = 100 bytes; each padded magic-byte image is 64 bytes. The first
|
|
138
|
-
// DISTINCT write fits (64); a second distinct image (64) would total 128 >
|
|
139
|
-
// 100 → rejected. A dedupe hit (same bytes) is free and must NOT count.
|
|
140
|
-
await withServer(
|
|
141
|
-
async (port) => {
|
|
142
|
-
expect((await postAsset(port, PNG)).status).toBe(201); // 64 written
|
|
143
|
-
expect((await postAsset(port, PNG)).status).toBe(201); // dedupe — free
|
|
144
|
-
expect((await postAsset(port, JPEG)).status).toBe(429); // 64+64 > 100
|
|
145
|
-
},
|
|
146
|
-
{ MAUDE_ASSET_SESSION_BUDGET: '100' }
|
|
147
|
-
);
|
|
148
|
-
});
|
|
149
|
-
});
|