@1agh/maude 1.0.11 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/apps/studio/acp/bridge.ts +18 -13
- package/apps/studio/acp/index.ts +43 -7
- package/apps/studio/acp/transcript-io.ts +394 -0
- package/apps/studio/acp/transcript.ts +103 -38
- package/apps/studio/annotations-layer.tsx +191 -116
- package/apps/studio/annotations-model.ts +39 -0
- package/apps/studio/annotations-sync.ts +50 -0
- package/apps/studio/api.ts +821 -55
- package/apps/studio/bin/_import-figma.mjs +57 -11
- package/apps/studio/bin/_seed-fixture.mjs +163 -0
- package/apps/studio/bin/annotate.mjs +3 -1
- package/apps/studio/bin/server-up.sh +17 -2
- package/apps/studio/canvas-edit.ts +391 -7
- package/apps/studio/canvas-imports.ts +89 -0
- package/apps/studio/canvas-lib.tsx +82 -18
- package/apps/studio/canvas-notice-message.ts +16 -0
- package/apps/studio/canvas-notifications.tsx +19 -0
- package/apps/studio/canvas-shell.tsx +57 -6
- package/apps/studio/client/app.jsx +943 -248
- package/apps/studio/client/apply-edit-request.ts +55 -0
- package/apps/studio/client/export-center.jsx +125 -67
- package/apps/studio/client/github.js +38 -1
- package/apps/studio/client/index-loader.ts +76 -0
- package/apps/studio/client/panels/CloudBar.jsx +52 -6
- package/apps/studio/client/panels/GitPanel.jsx +103 -0
- package/apps/studio/client/panels/OnboardingWizard.jsx +36 -7
- package/apps/studio/client/panels/RepoBranchSwitcher.jsx +92 -27
- package/apps/studio/client/panels/SourceConflictPanel.jsx +166 -0
- package/apps/studio/client/panels/SyncPanel.jsx +238 -4
- package/apps/studio/client/panels/TeamProjects.jsx +376 -0
- package/apps/studio/client/panels/file-deep-link-dialog.jsx +54 -0
- package/apps/studio/client/photo-knobs.jsx +3 -0
- package/apps/studio/client/report-bug.jsx +19 -1
- package/apps/studio/client/share-dialog.jsx +91 -0
- package/apps/studio/client/share-link.js +94 -0
- package/apps/studio/client/styles/3-shell-maude.css +69 -18
- package/apps/studio/client/styles/4-components.css +44 -1
- package/apps/studio/client/tree-row-menu.jsx +48 -3
- package/apps/studio/client/whats-new.jsx +26 -32
- package/apps/studio/cloud/endpoints.ts +132 -0
- package/apps/studio/collab/index.ts +4 -0
- package/apps/studio/collab/persistence.ts +137 -17
- package/apps/studio/collab/registry.ts +19 -21
- package/apps/studio/collab/room.ts +13 -2
- package/apps/studio/context.ts +59 -0
- package/apps/studio/debug-bundle.ts +13 -0
- package/apps/studio/dist/client.bundle.js +1911 -1879
- package/apps/studio/dist/runtime/.min-sizes.json +1 -0
- package/apps/studio/dist/runtime/sonner.js +1 -0
- 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 +296 -19
- package/apps/studio/inspect.ts +19 -0
- package/apps/studio/managed-projects.ts +150 -0
- package/apps/studio/mem.ts +45 -9
- package/apps/studio/notifications.tsx +292 -0
- package/apps/studio/runtime-bundle.ts +2 -0
- package/apps/studio/server.ts +69 -6
- package/apps/studio/sync/accepted-cold-start.ts +225 -0
- package/apps/studio/sync/accepted-link.ts +320 -0
- package/apps/studio/sync/action-stage.ts +343 -0
- package/apps/studio/sync/agent.ts +104 -45
- package/apps/studio/sync/asset-push.ts +1 -47
- package/apps/studio/sync/cell-file-events.ts +3 -0
- package/apps/studio/sync/codec.ts +192 -34
- 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/ctl-provider.ts +15 -2
- package/apps/studio/sync/document-discovery.ts +81 -0
- package/apps/studio/sync/file-ledger.ts +117 -0
- package/apps/studio/sync/file-membership.ts +10 -2
- package/apps/studio/sync/file-plane.ts +926 -47
- package/apps/studio/sync/index.ts +1786 -36
- package/apps/studio/sync/journal-client.ts +13 -1
- package/apps/studio/sync/migrate-seed.ts +150 -22
- package/apps/studio/sync/poke.ts +4 -2
- package/apps/studio/sync/presentation.ts +311 -5
- package/apps/studio/sync/projection.ts +820 -23
- package/apps/studio/sync/repeated-module.ts +73 -0
- package/apps/studio/sync/retry-after.ts +169 -0
- package/apps/studio/sync/revision-barrier.ts +129 -0
- package/apps/studio/sync/seed-progress.ts +218 -0
- package/apps/studio/sync/seed-repair.ts +46 -0
- package/apps/studio/sync/source-merge.ts +100 -0
- package/apps/studio/sync/source-ops.ts +289 -0
- package/apps/studio/sync/source-recovery.ts +70 -0
- package/apps/studio/sync/source-validation.ts +56 -0
- package/apps/studio/sync/status.ts +201 -6
- package/apps/studio/sync/transaction-client.ts +460 -0
- package/apps/studio/sync/transport-error.ts +111 -0
- package/apps/studio/sync/writer-registry.ts +236 -0
- package/apps/studio/text-caret.ts +35 -0
- package/apps/studio/undo-hud.tsx +9 -87
- package/apps/studio/use-canvas-media-drop.tsx +4 -39
- package/apps/studio/whats-new.json +173 -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 +892 -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 +33 -9
- package/plugins/design/dependencies.json +3 -3
- package/plugins/design/templates/_shell.html +47 -0
- package/plugins/flow/.claude-plugin/config.schema.json +8 -0
- package/plugins/flow/dependencies.json +3 -3
- 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 -545
- 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/backgrounding-claude-auth.sh +0 -12
- package/apps/studio/test/fixtures/fake-claude-auth.mjs +0 -23
- 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/noisy-claude-auth.mjs +0 -27
- 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/fixtures/wedged-claude-auth.sh +0 -11
- 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 -337
- 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,104 +0,0 @@
|
|
|
1
|
-
// DDR-219 D2 regression guard — the codegen channel is a CONTROL, not an intent.
|
|
2
|
-
//
|
|
3
|
-
// The first draft of DDR-219 routed Figma Dev Mode codegen through the REMOTE
|
|
4
|
-
// MCP (`https://mcp.figma.com/mcp`) and treated our own code's inability to
|
|
5
|
-
// reach it as the safety property. The design-stage review took that apart:
|
|
6
|
-
//
|
|
7
|
-
// - the remote catalog "allowlist" is enforced on a self-reported OAuth
|
|
8
|
-
// `client_name`, and a public bypass for it exists — so it is a waitlist,
|
|
9
|
-
// not a boundary;
|
|
10
|
-
// - the LOCAL Dev Mode server (`http://127.0.0.1:3845/mcp`) takes plain
|
|
11
|
-
// loopback HTTP with NO credential and no catalog gate at all, so nothing
|
|
12
|
-
// but intent stands between a future contributor and `fetch(...)` inside
|
|
13
|
-
// `apps/studio/figma/`;
|
|
14
|
-
// - DDR-185's `curl-local` *permits* that endpoint by construction (its rule
|
|
15
|
-
// is "every resolved address is loopback", and 127.0.0.1 is), and an ACP
|
|
16
|
-
// session auto-approves `Bash(maude:*)` — so the one egress control the
|
|
17
|
-
// session trusts is, for this specific service, an allow rule.
|
|
18
|
-
//
|
|
19
|
-
// Reaching the remote endpoint from product code would put a third-party model's
|
|
20
|
-
// output into an ingestion path that DDR-216 D1 says is deterministic end to
|
|
21
|
-
// end. Reaching the local one from anywhere except the single designated client
|
|
22
|
-
// would make codegen a bulk ingestion route by accident — DDR-219 D1's table
|
|
23
|
-
// silently false, its fallback never firing, and nothing in CI noticing.
|
|
24
|
-
//
|
|
25
|
-
// So both halves are asserted here rather than described in a decision record.
|
|
26
|
-
|
|
27
|
-
import assert from 'node:assert/strict';
|
|
28
|
-
import { execSync } from 'node:child_process';
|
|
29
|
-
import { test } from 'node:test';
|
|
30
|
-
|
|
31
|
-
/** The ONE module allowed to name the local Dev Mode endpoint (DDR-219 D2). */
|
|
32
|
-
const CODEGEN_CLIENT = 'apps/studio/figma/codegen-client.ts';
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Tests under the Figma lane may name it too, and the widening is narrow on
|
|
36
|
-
* purpose. `codegen-client.test.ts` asserts the endpoint constant — that IS the
|
|
37
|
-
* control ("the URL is never influenced by input"), and a guard that forbids
|
|
38
|
-
* asserting the thing it guards would push the assertion out of the repo.
|
|
39
|
-
* `from-codegen.test.ts` carries a captured response fixture whose asset
|
|
40
|
-
* constants are loopback URLs, and the property under test is that the converter
|
|
41
|
-
* DISCARDS them — which can only be asserted against a fixture that has them.
|
|
42
|
-
*
|
|
43
|
-
* Neither executes anything against the port. What stays absolutely banned is a
|
|
44
|
-
* second non-test module reaching it, which is the shape that would make codegen
|
|
45
|
-
* a bulk ingestion route by accident.
|
|
46
|
-
*/
|
|
47
|
-
const TEST_FILE_RE = /^apps\/studio\/figma\/[a-z-]+\.test\.ts$/;
|
|
48
|
-
|
|
49
|
-
/** Trees that ship or execute. Prose (`.ai/`, `docs/`, `site/`) may name both. */
|
|
50
|
-
const RUNTIME_TREES = ['apps/studio', 'cli', 'plugins'];
|
|
51
|
-
|
|
52
|
-
/** Source only. `node_modules` vendors binaries that contain arbitrary strings
|
|
53
|
-
* (the bundled agent-sdk `claude` matched `mcp.figma.com` on the first run),
|
|
54
|
-
* and `dist/` is build output, not a code path anyone edits. `-I` drops binary
|
|
55
|
-
* files outright so a vendored blob can never turn this guard into noise —
|
|
56
|
-
* a guard that cries wolf gets deleted, which would be worse than not having it. */
|
|
57
|
-
function grep(pattern, trees) {
|
|
58
|
-
// `|| true` because grep exits 1 on no-match, which is the passing case.
|
|
59
|
-
const out = execSync(
|
|
60
|
-
`grep -rlIE --exclude-dir=node_modules --exclude-dir=dist --exclude-dir=.git ${JSON.stringify(pattern)} ${trees.join(' ')} 2>/dev/null || true`,
|
|
61
|
-
{ encoding: 'utf8', cwd: new URL('../../', import.meta.url).pathname }
|
|
62
|
-
);
|
|
63
|
-
return out
|
|
64
|
-
.trim()
|
|
65
|
-
.split('\n')
|
|
66
|
-
.filter(Boolean)
|
|
67
|
-
.filter((f) => !f.endsWith('figma-codegen-reachability.test.mjs'));
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
test('no runtime code names the REMOTE Figma MCP endpoint', () => {
|
|
71
|
-
const offenders = grep('mcp\\.figma\\.com', RUNTIME_TREES);
|
|
72
|
-
assert.deepEqual(
|
|
73
|
-
offenders,
|
|
74
|
-
[],
|
|
75
|
-
`These files name the remote Figma MCP endpoint. It is banned from every runtime code path (DDR-219 D2, and \`feature-figma-import\` § Out of scope before it): it is reachable only by a catalog-listed agent client, so any use here means a model is in the ingestion path. Codegen goes over the LOCAL server, with apps/studio as the client:\n ${offenders.join('\n ')}`
|
|
76
|
-
);
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
test('only the designated client names the LOCAL Dev Mode endpoint', () => {
|
|
80
|
-
// Match the endpoint shape, not a bare `3845`, which could legitimately occur
|
|
81
|
-
// as a byte count or a hash fragment.
|
|
82
|
-
const offenders = grep('(localhost|127\\.0\\.0\\.1|:)3845', RUNTIME_TREES).filter(
|
|
83
|
-
(f) => f !== CODEGEN_CLIENT && !TEST_FILE_RE.test(f)
|
|
84
|
-
);
|
|
85
|
-
assert.deepEqual(
|
|
86
|
-
offenders,
|
|
87
|
-
[],
|
|
88
|
-
`Only ${CODEGEN_CLIENT} may reach the local Figma Dev Mode MCP server (DDR-219 D2). A second caller makes codegen an ingestion route by accident — and the local server is UNAUTHENTICATED loopback, so there is no credential step to notice it. If codegen is genuinely needed elsewhere, route it through the client:\n ${offenders.join('\n ')}`
|
|
89
|
-
);
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
test('no canvas-reachable codegen route exists', () => {
|
|
93
|
-
// A canvas-origin codegen route would hand the untrusted iframe (DDR-054) a
|
|
94
|
-
// primitive that reads the user's open Figma document. It belongs in NEITHER
|
|
95
|
-
// allowlist — the same standing rule DDR-088 sets for every privileged route.
|
|
96
|
-
const offenders = grep('CANVAS_SAFE_API[^\\n]*codegen|codegen[^\\n]*CANVAS_SAFE_API', [
|
|
97
|
-
'apps/studio',
|
|
98
|
-
]);
|
|
99
|
-
assert.deepEqual(
|
|
100
|
-
offenders,
|
|
101
|
-
[],
|
|
102
|
-
`A codegen route appears near CANVAS_SAFE_API. Codegen is privileged-origin only (DDR-219 D2):\n ${offenders.join('\n ')}`
|
|
103
|
-
);
|
|
104
|
-
});
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
// DDR-216 D7 + D8 existence guard — the anti-recurrence test.
|
|
2
|
-
//
|
|
3
|
-
// This repo has now written the same mistake into three consecutive decision
|
|
4
|
-
// records: a DDR asserts a control, nobody builds it, and the NEXT DDR cites it
|
|
5
|
-
// as an existing mitigation. DDR-216 D7 promised `/design:edit` a pre-flight
|
|
6
|
-
// untrusted-content banner on an imported canvas; D8 promised Pass A.10 run
|
|
7
|
-
// promoted-to-blocker for `imported-figma`. Both were "shipped" in prose. When
|
|
8
|
-
// DDR-219 leaned on the A.10 promotion as a control that was "still enforced,
|
|
9
|
-
// unchanged", the design-stage review ran one command —
|
|
10
|
-
//
|
|
11
|
-
// grep -rn "imported-figma" plugins/ → zero matches
|
|
12
|
-
//
|
|
13
|
-
// — and the whole chain came apart. A decision record cannot assert its way to a
|
|
14
|
-
// control. This test is the cheapest possible thing that would have caught it,
|
|
15
|
-
// and it is deliberately dumb: it checks the string is REACHABLE from the files
|
|
16
|
-
// that must act on it, not that the behaviour is correct.
|
|
17
|
-
|
|
18
|
-
import assert from 'node:assert/strict';
|
|
19
|
-
import { readFileSync } from 'node:fs';
|
|
20
|
-
import { test } from 'node:test';
|
|
21
|
-
|
|
22
|
-
const root = new URL('../../', import.meta.url).pathname;
|
|
23
|
-
const read = (p) => readFileSync(root + p, 'utf8');
|
|
24
|
-
|
|
25
|
-
test('DDR-216 D7 — /design:edit banners an imported canvas before reading it', () => {
|
|
26
|
-
const edit = read('plugins/design/commands/edit.md');
|
|
27
|
-
assert.match(
|
|
28
|
-
edit,
|
|
29
|
-
/imported-figma/,
|
|
30
|
-
"/design:edit must detect an `imported-figma` canvas at pre-flight (DDR-216 D7). Without it, several hundred third-party strings enter a tool-holding agent's context with nothing saying what they are."
|
|
31
|
-
);
|
|
32
|
-
assert.match(
|
|
33
|
-
edit,
|
|
34
|
-
/untrusted content, never instructions/i,
|
|
35
|
-
"The banner must say the content is untrusted and is never instructions — that exact framing is the control (DDR-216 D7, DDR-085's whiteboard trust model)."
|
|
36
|
-
);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
test('DDR-216 D8 — Pass A.10 is promoted to blocker on an imported canvas', () => {
|
|
40
|
-
const keeper = read('plugins/design/agents/design-system-keeper.md');
|
|
41
|
-
const a10 = keeper.slice(keeper.indexOf('## Pass A.10'));
|
|
42
|
-
assert.notEqual(a10, '', 'Pass A.10 section is missing from design-system-keeper.');
|
|
43
|
-
assert.match(
|
|
44
|
-
a10,
|
|
45
|
-
/imported-figma/,
|
|
46
|
-
'Pass A.10 must special-case `imported-figma` (DDR-216 D8). As a plain warning it is not a gate.'
|
|
47
|
-
);
|
|
48
|
-
assert.match(
|
|
49
|
-
a10,
|
|
50
|
-
/blocker/i,
|
|
51
|
-
'A.10 findings must be blockers on an imported canvas — the mass-drift stacking ladder exists to avoid nagging a human over one deliberate overlay, and that reasoning does not survive a machine-authored file.'
|
|
52
|
-
);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
test('A.10 does not let an imported canvas skip via its declared kind', () => {
|
|
56
|
-
// The skip condition is "no kind=\"web\" artboard" — and on an import the
|
|
57
|
-
// TRANSLATOR picks the kind, so the gate would be satisfied by the very code
|
|
58
|
-
// it audits. DDR-216 D8's Round-1 correction named this; the exception closes it.
|
|
59
|
-
const keeper = read('plugins/design/agents/design-system-keeper.md');
|
|
60
|
-
const a10 = keeper.slice(keeper.indexOf('## Pass A.10'), keeper.indexOf('## Pass B'));
|
|
61
|
-
const skipIdx = a10.indexOf('Skip entirely');
|
|
62
|
-
assert.ok(skipIdx > -1, 'A.10 skip condition not found — did the section change shape?');
|
|
63
|
-
assert.match(
|
|
64
|
-
a10.slice(skipIdx, skipIdx + 1200),
|
|
65
|
-
// `[\s\S]` rather than `[^]` — same "any char incl. newline" meaning, but
|
|
66
|
-
// `[^]` is a negated EMPTY class, which biome flags and which reads as a typo.
|
|
67
|
-
/EXCEPTION[\s\S]*imported-figma/,
|
|
68
|
-
'The skip condition must carry an explicit imported-canvas exception, stated next to the skip itself where a reader will actually meet it.'
|
|
69
|
-
);
|
|
70
|
-
});
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
// Phase 11 (flow ⇄ design integration) regression guard.
|
|
2
|
-
//
|
|
3
|
-
// The slash-command orchestration (/flow:plan canvas detection, /flow:done
|
|
4
|
-
// handoff sweep, codebase-intelligence design section, ddr-keeper canvas prompt)
|
|
5
|
-
// is LLM-driven markdown — not unit-testable. What IS deterministic, and what
|
|
6
|
-
// this test locks down, is the *contract* that wiring depends on:
|
|
7
|
-
//
|
|
8
|
-
// 1. The canvas `.meta.json` schema accepts the Phase 11 fields
|
|
9
|
-
// (status enum, handoffCommit, tags, brief_sha) and rejects a bad status.
|
|
10
|
-
// 2. The flow config schema accepts `paths.designRoot`, the real skeleton
|
|
11
|
-
// config validates, and the field stays OPTIONAL (no regression for
|
|
12
|
-
// projects without the design plugin).
|
|
13
|
-
// 3. The /flow:done status round-trip (ready-for-handoff → handed-off +
|
|
14
|
-
// handoffCommit) produces schema-valid output at both ends.
|
|
15
|
-
// 4. The markdown wiring for all four integrations is present (grep guard) —
|
|
16
|
-
// a future edit that deletes a section fails loudly here.
|
|
17
|
-
|
|
18
|
-
import assert from 'node:assert/strict';
|
|
19
|
-
import { readFileSync } from 'node:fs';
|
|
20
|
-
import { resolve } from 'node:path';
|
|
21
|
-
import { test } from 'node:test';
|
|
22
|
-
import Ajv2020 from 'ajv/dist/2020.js';
|
|
23
|
-
import addFormats from 'ajv-formats';
|
|
24
|
-
import { lintConfig } from './config-lint.mjs';
|
|
25
|
-
|
|
26
|
-
const read = (p) => readFileSync(resolve(p), 'utf8');
|
|
27
|
-
const readJson = (p) => JSON.parse(read(p));
|
|
28
|
-
|
|
29
|
-
const META_SCHEMA = readJson('apps/studio/canvas-meta.schema.json');
|
|
30
|
-
const FLOW_SCHEMA = readJson('plugins/flow/.claude-plugin/config.schema.json');
|
|
31
|
-
const SKELETON = readJson('plugins/flow/templates/ai-skeleton/workflows.config.json');
|
|
32
|
-
|
|
33
|
-
const ajv = new Ajv2020({ allErrors: true, strict: false });
|
|
34
|
-
addFormats(ajv);
|
|
35
|
-
const validateMeta = ajv.compile(META_SCHEMA);
|
|
36
|
-
|
|
37
|
-
// ── 1. canvas-meta schema accepts the Phase 11 fields ──────────────────────
|
|
38
|
-
|
|
39
|
-
test('canvas-meta: accepts status + tags (ready-for-handoff)', () => {
|
|
40
|
-
const ok = validateMeta({
|
|
41
|
-
title: 'Dark Mode Toggle',
|
|
42
|
-
sections: [{ id: 'hero', label: 'Hero' }],
|
|
43
|
-
tags: ['dark-mode'],
|
|
44
|
-
status: 'ready-for-handoff',
|
|
45
|
-
});
|
|
46
|
-
assert.equal(ok, true, JSON.stringify(validateMeta.errors));
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
test('canvas-meta: accepts handed-off + handoffCommit + brief_sha', () => {
|
|
50
|
-
const ok = validateMeta({
|
|
51
|
-
title: 'Settings',
|
|
52
|
-
sections: [],
|
|
53
|
-
status: 'handed-off',
|
|
54
|
-
handoffCommit: '8dd832b',
|
|
55
|
-
brief_sha: 'abc123def456',
|
|
56
|
-
});
|
|
57
|
-
assert.equal(ok, true, JSON.stringify(validateMeta.errors));
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
test('canvas-meta: every status enum value is accepted', () => {
|
|
61
|
-
for (const status of ['draft', 'in-review', 'ready-for-handoff', 'handed-off']) {
|
|
62
|
-
const ok = validateMeta({ title: 'X', sections: [], status });
|
|
63
|
-
assert.equal(ok, true, `status=${status}: ${JSON.stringify(validateMeta.errors)}`);
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
test('canvas-meta: a bogus status enum is REJECTED', () => {
|
|
68
|
-
const ok = validateMeta({ title: 'X', sections: [], status: 'shipped' });
|
|
69
|
-
assert.equal(ok, false, 'expected status="shipped" to be rejected by the enum');
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
test('canvas-meta: back-compat — a sidecar without any Phase 11 field still validates', () => {
|
|
73
|
-
const ok = validateMeta({ title: 'Legacy', sections: [{ id: 's', label: 'S' }] });
|
|
74
|
-
assert.equal(ok, true, JSON.stringify(validateMeta.errors));
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
test('canvas-meta: tags must be unique strings', () => {
|
|
78
|
-
assert.equal(validateMeta({ title: 'X', sections: [], tags: ['a', 'a'] }), false);
|
|
79
|
-
assert.equal(validateMeta({ title: 'X', sections: [], tags: [1, 2] }), false);
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
// ── 2. flow config schema: paths.designRoot ────────────────────────────────
|
|
83
|
-
|
|
84
|
-
test('flow config: the real skeleton config (with paths.designRoot) validates', async () => {
|
|
85
|
-
const r = await lintConfig({ config: SKELETON, schema: FLOW_SCHEMA });
|
|
86
|
-
assert.equal(r.ok, true, JSON.stringify(r.errors));
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
test('flow config: skeleton declares paths.designRoot = .design', () => {
|
|
90
|
-
assert.equal(SKELETON.paths.designRoot, '.design');
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
test('flow config: paths.designRoot is OPTIONAL (no-regression for non-design projects)', async () => {
|
|
94
|
-
const r = await lintConfig({
|
|
95
|
-
config: { name: 'x', paths: { prd: '.ai/x-prd.md' } },
|
|
96
|
-
schema: FLOW_SCHEMA,
|
|
97
|
-
});
|
|
98
|
-
assert.equal(r.ok, true, JSON.stringify(r.errors));
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
test('flow config: a non-string paths.designRoot is rejected', async () => {
|
|
102
|
-
const r = await lintConfig({
|
|
103
|
-
config: { name: 'x', paths: { designRoot: 42 } },
|
|
104
|
-
schema: FLOW_SCHEMA,
|
|
105
|
-
});
|
|
106
|
-
assert.equal(r.ok, false);
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
test('flow config: paths.designRoot carries a default of .design', () => {
|
|
110
|
-
assert.equal(FLOW_SCHEMA.properties.paths.properties.designRoot.default, '.design');
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
// ── 3. /flow:done status round-trip stays schema-valid ─────────────────────
|
|
114
|
-
|
|
115
|
-
test('done sweep round-trip: ready-for-handoff → handed-off + handoffCommit both valid', () => {
|
|
116
|
-
const before = { title: 'Canvas', sections: [], status: 'ready-for-handoff', tags: ['feat'] };
|
|
117
|
-
assert.equal(validateMeta(before), true, `before: ${JSON.stringify(validateMeta.errors)}`);
|
|
118
|
-
|
|
119
|
-
// what /flow:done step 5b writes:
|
|
120
|
-
const after = { ...before, status: 'handed-off', handoffCommit: 'deadbeef0123' };
|
|
121
|
-
assert.equal(validateMeta(after), true, `after: ${JSON.stringify(validateMeta.errors)}`);
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
// ── 4. markdown wiring guards (a deleted section fails here) ────────────────
|
|
125
|
-
|
|
126
|
-
const PLAN = read('plugins/flow/commands/plan.md');
|
|
127
|
-
const DONE = read('plugins/flow/commands/done.md');
|
|
128
|
-
const MAP_CMD = read('plugins/flow/commands/setup-codebase-map.md');
|
|
129
|
-
const CI_SKILL = read('plugins/flow/skills/codebase-intelligence/SKILL.md');
|
|
130
|
-
const DDR_SKILL = read('plugins/flow/skills/ddr-keeper/SKILL.md');
|
|
131
|
-
const RECORD_DDR = read('plugins/flow/commands/record-ddr.md');
|
|
132
|
-
|
|
133
|
-
test('wiring: /flow:plan has Design Canvas Detection', () => {
|
|
134
|
-
assert.match(PLAN, /Design Canvas Detection/);
|
|
135
|
-
assert.match(PLAN, /paths\.designRoot/);
|
|
136
|
-
assert.match(PLAN, /### Design canvases/); // the Context References subsection
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
test('wiring: /flow:done has the handoff sweep + soft-gate DDR-066 reference', () => {
|
|
140
|
-
assert.match(DONE, /Design handoff sweep/);
|
|
141
|
-
assert.match(DONE, /ready-for-handoff/);
|
|
142
|
-
assert.match(DONE, /handed-off/);
|
|
143
|
-
assert.match(DONE, /handoffCommit/);
|
|
144
|
-
assert.match(DONE, /DDR-066/);
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
test('wiring: codebase map command + skill have the Design artifacts section', () => {
|
|
148
|
-
assert.match(MAP_CMD, /Map Design Artifacts/);
|
|
149
|
-
assert.match(MAP_CMD, /## Design artifacts/);
|
|
150
|
-
assert.match(CI_SKILL, /Design Artifact Scanning/);
|
|
151
|
-
assert.match(CI_SKILL, /### Design artifacts/);
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
test('wiring: ddr-keeper + record-ddr have the canvas-reference prompt', () => {
|
|
155
|
-
assert.match(DDR_SKILL, /Canvas reference for UI-affecting decisions/);
|
|
156
|
-
assert.match(DDR_SKILL, /Related canvas/);
|
|
157
|
-
assert.match(RECORD_DDR, /Related canvas/);
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
test('wiring: DDR-066 exists and is indexed', () => {
|
|
161
|
-
const ddr = read('.ai/archive/decisions/DDR-066-soft-handoff-prompt-in-flow-done.md');
|
|
162
|
-
assert.match(ddr, /soft prompt/i);
|
|
163
|
-
const index = read('.ai/archive/decisions/README.md');
|
|
164
|
-
assert.match(index, /DDR-066/);
|
|
165
|
-
});
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
// gitignore-block helper tests — Phase 9 Task 9 (DDR-056).
|
|
2
|
-
|
|
3
|
-
import assert from 'node:assert/strict';
|
|
4
|
-
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
5
|
-
import { tmpdir } from 'node:os';
|
|
6
|
-
import { join } from 'node:path';
|
|
7
|
-
import { test } from 'node:test';
|
|
8
|
-
|
|
9
|
-
import {
|
|
10
|
-
applyBlock,
|
|
11
|
-
BEGIN_MARKER,
|
|
12
|
-
buildBlock,
|
|
13
|
-
END_MARKER,
|
|
14
|
-
hasBlock,
|
|
15
|
-
writeGitignoreBlock,
|
|
16
|
-
} from './gitignore-block.mjs';
|
|
17
|
-
|
|
18
|
-
function withRepo(fn) {
|
|
19
|
-
const dir = mkdtempSync(join(tmpdir(), 'maude-gitignore-'));
|
|
20
|
-
try {
|
|
21
|
-
return fn(dir);
|
|
22
|
-
} finally {
|
|
23
|
-
rmSync(dir, { recursive: true, force: true });
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
test('buildBlock includes the runtime paths and is marker-wrapped', () => {
|
|
28
|
-
const block = buildBlock('.design');
|
|
29
|
-
assert.ok(block.startsWith(BEGIN_MARKER));
|
|
30
|
-
assert.ok(block.trimEnd().endsWith(END_MARKER));
|
|
31
|
-
for (const p of [
|
|
32
|
-
'.design/_state/',
|
|
33
|
-
'.design/_server.json',
|
|
34
|
-
'.design/_server.log',
|
|
35
|
-
'.design/_server.lock',
|
|
36
|
-
'.design/_active.json',
|
|
37
|
-
'.design/_sync.json',
|
|
38
|
-
'.design/_preflight.json',
|
|
39
|
-
'.design/_locator.json',
|
|
40
|
-
'.design/_export-history.json',
|
|
41
|
-
'.design/_history/',
|
|
42
|
-
'.design/_trash/',
|
|
43
|
-
'.design/_draw/',
|
|
44
|
-
'.design/_smoke/',
|
|
45
|
-
'.design/_canvas-state/', // covers the DDR-115 `<slug>.view.json` camera
|
|
46
|
-
'.design/_chat/',
|
|
47
|
-
'.design/_untrusted/',
|
|
48
|
-
'.design/_comments/', // hub-sync-only (DDR-115)
|
|
49
|
-
]) {
|
|
50
|
-
assert.ok(block.includes(p), `missing ${p}`);
|
|
51
|
-
}
|
|
52
|
-
// VERSIONED content must NOT be ignored (DDR-115 taxonomy).
|
|
53
|
-
assert.ok(!block.includes('.design/config.json'));
|
|
54
|
-
assert.ok(!/\.design\/\*\.html/.test(block));
|
|
55
|
-
// Annotations are versioned — never in the ignore block.
|
|
56
|
-
assert.ok(!/annotations\.svg/.test(block), 'annotations must stay versioned');
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
test('buildBlock honors a custom design root', () => {
|
|
60
|
-
const block = buildBlock('design');
|
|
61
|
-
assert.ok(block.includes('design/_server.json'));
|
|
62
|
-
assert.ok(!block.includes('.design/_server.json'));
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
test('writeGitignoreBlock creates .gitignore when absent', () => {
|
|
66
|
-
withRepo((dir) => {
|
|
67
|
-
const { action, path } = writeGitignoreBlock(dir);
|
|
68
|
-
assert.equal(action, 'created');
|
|
69
|
-
const text = readFileSync(path, 'utf8');
|
|
70
|
-
assert.ok(hasBlock(text));
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
test('writeGitignoreBlock is idempotent — second run is unchanged', () => {
|
|
75
|
-
withRepo((dir) => {
|
|
76
|
-
writeGitignoreBlock(dir);
|
|
77
|
-
const first = readFileSync(join(dir, '.gitignore'), 'utf8');
|
|
78
|
-
const { action } = writeGitignoreBlock(dir);
|
|
79
|
-
const second = readFileSync(join(dir, '.gitignore'), 'utf8');
|
|
80
|
-
assert.equal(action, 'unchanged');
|
|
81
|
-
assert.equal(first, second);
|
|
82
|
-
// Exactly one block — no duplication.
|
|
83
|
-
assert.equal(first.split(BEGIN_MARKER).length - 1, 1);
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
test('writeGitignoreBlock preserves user content outside the markers', () => {
|
|
88
|
-
withRepo((dir) => {
|
|
89
|
-
const userContent = 'node_modules/\n*.log\n.env\n';
|
|
90
|
-
writeFileSync(join(dir, '.gitignore'), userContent);
|
|
91
|
-
writeGitignoreBlock(dir);
|
|
92
|
-
const text = readFileSync(join(dir, '.gitignore'), 'utf8');
|
|
93
|
-
assert.ok(text.includes('node_modules/'));
|
|
94
|
-
assert.ok(text.includes('.env'));
|
|
95
|
-
assert.ok(hasBlock(text));
|
|
96
|
-
});
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
test('writeGitignoreBlock updates an existing block in place (no duplication)', () => {
|
|
100
|
-
withRepo((dir) => {
|
|
101
|
-
// Seed a stale block with a different design root.
|
|
102
|
-
const stale = `keep-me\n${buildBlock('olddesign')}trailing\n`;
|
|
103
|
-
writeFileSync(join(dir, '.gitignore'), stale);
|
|
104
|
-
const { action } = writeGitignoreBlock(dir, { designRel: '.design' });
|
|
105
|
-
assert.equal(action, 'updated');
|
|
106
|
-
const text = readFileSync(join(dir, '.gitignore'), 'utf8');
|
|
107
|
-
assert.equal(text.split(BEGIN_MARKER).length - 1, 1, 'still exactly one block');
|
|
108
|
-
assert.ok(text.includes('.design/_server.json'));
|
|
109
|
-
assert.ok(!text.includes('olddesign/_server.json'));
|
|
110
|
-
assert.ok(text.includes('keep-me'));
|
|
111
|
-
assert.ok(text.includes('trailing'));
|
|
112
|
-
});
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
test('writeGitignoreBlock --dry-run does not touch disk', () => {
|
|
116
|
-
withRepo((dir) => {
|
|
117
|
-
const { action } = writeGitignoreBlock(dir, { dryRun: true });
|
|
118
|
-
assert.equal(action, 'created');
|
|
119
|
-
// File was not actually written.
|
|
120
|
-
assert.throws(() => readFileSync(join(dir, '.gitignore'), 'utf8'));
|
|
121
|
-
});
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
test('applyBlock appends to a file lacking a trailing newline cleanly', () => {
|
|
125
|
-
const out = applyBlock('a\nb', buildBlock('.design'));
|
|
126
|
-
assert.ok(out.includes('a\nb'));
|
|
127
|
-
assert.ok(hasBlock(out));
|
|
128
|
-
// No run-together: marker starts on its own line.
|
|
129
|
-
assert.ok(out.includes(`\n${BEGIN_MARKER}`));
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
test('hasBlock detects both markers', () => {
|
|
133
|
-
assert.ok(hasBlock(`x\n${BEGIN_MARKER}\ny\n${END_MARKER}\n`));
|
|
134
|
-
assert.ok(!hasBlock('just user content'));
|
|
135
|
-
assert.ok(!hasBlock(BEGIN_MARKER)); // begin without end
|
|
136
|
-
});
|
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
// Gitignore drift — the check that catches git dropping VERSIONED design work.
|
|
2
|
-
//
|
|
3
|
-
// The case that produced this file, verbatim from a real project: a
|
|
4
|
-
// hand-authored pre-markers block carrying `.design/*.annotations.svg`, copied
|
|
5
|
-
// from a v1.0 planning document that predates the DDR-115 correction. Not one
|
|
6
|
-
// annotation sidecar had ever been committed. Both UIs rendered the draw layer;
|
|
7
|
-
// no clone, backup or PR contained it; nothing said so.
|
|
8
|
-
//
|
|
9
|
-
// What is pinned here is mostly the NEGATIVE space. A detector that proposes
|
|
10
|
-
// deleting lines from somebody's hand-written `.gitignore` is only as good as
|
|
11
|
-
// its refusals, so most of these tests assert what it must NOT flag.
|
|
12
|
-
|
|
13
|
-
import assert from 'node:assert/strict';
|
|
14
|
-
import { test } from 'node:test';
|
|
15
|
-
|
|
16
|
-
import {
|
|
17
|
-
describeGitignoreDrift,
|
|
18
|
-
findGitignoreDrift,
|
|
19
|
-
removeGitignoreDrift,
|
|
20
|
-
} from './gitignore-drift.mjs';
|
|
21
|
-
|
|
22
|
-
test('finds the real-world case: annotations ignored outside the markers', () => {
|
|
23
|
-
const gitignore = [
|
|
24
|
-
'node_modules/',
|
|
25
|
-
'',
|
|
26
|
-
'# design plugin dev-server runtime state',
|
|
27
|
-
'.design/_active.json',
|
|
28
|
-
'.design/_history/',
|
|
29
|
-
'.design/*.annotations.svg',
|
|
30
|
-
'.design/_chat/',
|
|
31
|
-
].join('\n');
|
|
32
|
-
const drift = findGitignoreDrift(gitignore, '.design');
|
|
33
|
-
assert.equal(drift.length, 1);
|
|
34
|
-
assert.equal(drift[0].line, 6);
|
|
35
|
-
assert.equal(drift[0].text, '.design/*.annotations.svg');
|
|
36
|
-
assert.match(drift[0].what, /annotations/);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
test('the runtime-state block is NOT drift — those paths are ignored by design', () => {
|
|
40
|
-
// Every line the block writer itself emits must come back clean, or the check
|
|
41
|
-
// would tell people to un-ignore their own `_history/` on every run.
|
|
42
|
-
const gitignore = [
|
|
43
|
-
'.design/_server.json',
|
|
44
|
-
'.design/_active.json',
|
|
45
|
-
'.design/_active.*.json',
|
|
46
|
-
'.design/_sync.json',
|
|
47
|
-
'.design/_history/',
|
|
48
|
-
'.design/_trash/',
|
|
49
|
-
'.design/_comments/',
|
|
50
|
-
'.design/_canvas-state/',
|
|
51
|
-
'.design/_untrusted/',
|
|
52
|
-
'.design/assets/',
|
|
53
|
-
].join('\n');
|
|
54
|
-
assert.deepEqual(findGitignoreDrift(gitignore, '.design'), []);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
test('lines INSIDE the maude block are skipped — a generator bug is fixed by the generator', () => {
|
|
58
|
-
const gitignore = [
|
|
59
|
-
'# maude:begin',
|
|
60
|
-
'.design/*.annotations.svg',
|
|
61
|
-
'# maude:end',
|
|
62
|
-
'.design/_history/',
|
|
63
|
-
].join('\n');
|
|
64
|
-
assert.deepEqual(findGitignoreDrift(gitignore, '.design'), []);
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
test('a negation is the fix, not the fault', () => {
|
|
68
|
-
const gitignore = ['.design/', '!.design/*.annotations.svg'].join('\n');
|
|
69
|
-
assert.deepEqual(findGitignoreDrift(gitignore, '.design'), []);
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
test('comments and blank lines are not rules', () => {
|
|
73
|
-
const gitignore = ['', '# .design/*.annotations.svg', ' ', '#.design/*.tsx'].join('\n');
|
|
74
|
-
assert.deepEqual(findGitignoreDrift(gitignore, '.design'), []);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
test('ignoring the WHOLE design root is a choice we do not second-guess', () => {
|
|
78
|
-
// Somebody who ignores `.design/` outright has decided their design work is
|
|
79
|
-
// not in this repo. That is coherent; flagging it would be nagging.
|
|
80
|
-
for (const line of ['.design', '.design/', '/.design/']) {
|
|
81
|
-
assert.deepEqual(findGitignoreDrift(line, '.design'), [], line);
|
|
82
|
-
}
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
test('a repo-wide rule is out of scope — it is a decision about a whole codebase', () => {
|
|
86
|
-
// `*.tsx` at the repo root is very possibly deliberate and is not ours to
|
|
87
|
-
// reinterpret from inside a design-tool diagnostic.
|
|
88
|
-
const gitignore = ['*.tsx', 'config.json', '*.meta.json'].join('\n');
|
|
89
|
-
assert.deepEqual(findGitignoreDrift(gitignore, '.design'), []);
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
test('a non-default design root is honoured', () => {
|
|
93
|
-
const gitignore = ['design/*.annotations.svg', '.design/*.annotations.svg'].join('\n');
|
|
94
|
-
const drift = findGitignoreDrift(gitignore, 'design');
|
|
95
|
-
assert.equal(drift.length, 1);
|
|
96
|
-
assert.equal(drift[0].line, 1);
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
test('anchors and trailing slashes are the same rule to git', () => {
|
|
100
|
-
const drift = findGitignoreDrift('/.design/system/', '.design');
|
|
101
|
-
assert.equal(drift.length, 1);
|
|
102
|
-
assert.match(drift[0].what, /design system/);
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
test('every versioned shape is covered, none of the runtime ones', () => {
|
|
106
|
-
const versioned = [
|
|
107
|
-
'.design/*.annotations.svg',
|
|
108
|
-
'.design/*.meta.json',
|
|
109
|
-
'.design/*.tsx',
|
|
110
|
-
'.design/config.json',
|
|
111
|
-
'.design/system/',
|
|
112
|
-
// The glob form. Both sides of the comparison must be normalised the same
|
|
113
|
-
// way — normalising only the pattern made this shape report clean while the
|
|
114
|
-
// module listed it as covered.
|
|
115
|
-
'.design/system/**',
|
|
116
|
-
];
|
|
117
|
-
assert.equal(findGitignoreDrift(versioned.join('\n'), '.design').length, versioned.length);
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
test('removal deletes exactly the reported lines, byte-for-byte otherwise', () => {
|
|
121
|
-
const gitignore = [
|
|
122
|
-
'node_modules/',
|
|
123
|
-
'',
|
|
124
|
-
'# my own comment',
|
|
125
|
-
'.design/*.annotations.svg',
|
|
126
|
-
'.design/_history/',
|
|
127
|
-
].join('\n');
|
|
128
|
-
const drift = findGitignoreDrift(gitignore, '.design');
|
|
129
|
-
const next = removeGitignoreDrift(gitignore, drift);
|
|
130
|
-
assert.equal(
|
|
131
|
-
next,
|
|
132
|
-
['node_modules/', '', '# my own comment', '.design/_history/'].join('\n'),
|
|
133
|
-
'the user comment and the blank line survive'
|
|
134
|
-
);
|
|
135
|
-
// And the result is clean on a re-run — the fix converges.
|
|
136
|
-
assert.deepEqual(findGitignoreDrift(next, '.design'), []);
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
test('removal with no drift is a byte-identical no-op', () => {
|
|
140
|
-
const gitignore = 'node_modules/\n.design/_history/\n';
|
|
141
|
-
assert.equal(removeGitignoreDrift(gitignore, []), gitignore);
|
|
142
|
-
assert.equal(removeGitignoreDrift(gitignore, undefined), gitignore);
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
test('an absent or empty gitignore is not drift', () => {
|
|
146
|
-
assert.deepEqual(findGitignoreDrift('', '.design'), []);
|
|
147
|
-
assert.deepEqual(findGitignoreDrift(undefined, '.design'), []);
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
test('the description names the consequence, not just the rule', () => {
|
|
151
|
-
const drift = findGitignoreDrift('.design/*.annotations.svg', '.design');
|
|
152
|
-
const [line] = describeGitignoreDrift(drift);
|
|
153
|
-
assert.match(line, /\.gitignore:1/);
|
|
154
|
-
assert.match(line, /drops/);
|
|
155
|
-
assert.match(line, /DDR-115/);
|
|
156
|
-
});
|