@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,292 +0,0 @@
|
|
|
1
|
-
// Cloud Phase 3 Task 3 — "Sign in to workspace".
|
|
2
|
-
//
|
|
3
|
-
// The persona is the invited teammate who has never used git. So alongside the
|
|
4
|
-
// mechanics (probe, login, credential custody) these tests assert the WORDS:
|
|
5
|
-
// a flow that says "paste your bearer token" has already told that person the
|
|
6
|
-
// product isn't for them (DDR-193 §5).
|
|
7
|
-
|
|
8
|
-
import { describe, expect, test } from 'bun:test';
|
|
9
|
-
|
|
10
|
-
import {
|
|
11
|
-
type DisclosureItem,
|
|
12
|
-
signInToWorkspace,
|
|
13
|
-
workspaceDisclosure,
|
|
14
|
-
} from '../sync/workspace-signin.ts';
|
|
15
|
-
|
|
16
|
-
/** A fetch stand-in scripted per URL suffix, recording what it was called with. */
|
|
17
|
-
function scriptedFetch(routes: Record<string, () => Response>) {
|
|
18
|
-
const calls: Array<{ url: string; init?: RequestInit }> = [];
|
|
19
|
-
const impl = (async (url: string | URL | Request, init?: RequestInit) => {
|
|
20
|
-
const href = String(url);
|
|
21
|
-
calls.push({ url: href, init });
|
|
22
|
-
for (const [suffix, make] of Object.entries(routes)) {
|
|
23
|
-
if (href.endsWith(suffix)) return make();
|
|
24
|
-
}
|
|
25
|
-
throw new Error(`unrouted ${href}`);
|
|
26
|
-
}) as unknown as typeof fetch;
|
|
27
|
-
return { impl, calls };
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const json = (body: unknown, status = 200) =>
|
|
31
|
-
new Response(JSON.stringify(body), { status, headers: { 'Content-Type': 'application/json' } });
|
|
32
|
-
|
|
33
|
-
const HEALTHY = () => json({ ok: true, version: '0.48.0' });
|
|
34
|
-
const LOGGED_IN = () =>
|
|
35
|
-
json({
|
|
36
|
-
token: 'mau_0123456789abcdef0123456789abcdef',
|
|
37
|
-
label: 'u-abcdef012345',
|
|
38
|
-
expiresAt: 1_800_000_000_000,
|
|
39
|
-
user: { email: 'alice@example.com', role: 'member' },
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
const CREDS = {
|
|
43
|
-
url: 'https://team.example.com',
|
|
44
|
-
email: 'alice@example.com',
|
|
45
|
-
password: 'hunter2222222',
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
describe('input validation speaks to a person, not a developer', () => {
|
|
49
|
-
test('each missing field names what to do next', async () => {
|
|
50
|
-
const saved: string[] = [];
|
|
51
|
-
const save = (u: string) => void saved.push(u);
|
|
52
|
-
for (const [input, expected] of [
|
|
53
|
-
[{}, /address your team sent you/i],
|
|
54
|
-
[{ url: 'https://x.example.com' }, /email address/i],
|
|
55
|
-
[{ url: 'https://x.example.com', email: 'a@b.com' }, /password/i],
|
|
56
|
-
] as const) {
|
|
57
|
-
const res = await signInToWorkspace(input, { save, fetchImpl: scriptedFetch({}).impl });
|
|
58
|
-
expect(res.status).toBe(400);
|
|
59
|
-
expect(res.json.ok).toBe(false);
|
|
60
|
-
expect((res.json as { error: string }).error).toMatch(expected);
|
|
61
|
-
}
|
|
62
|
-
expect(saved).toEqual([]);
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
test('a non-http address is refused before anything is sent', async () => {
|
|
66
|
-
const { impl, calls } = scriptedFetch({});
|
|
67
|
-
const res = await signInToWorkspace(
|
|
68
|
-
{ ...CREDS, url: 'file:///etc/passwd' },
|
|
69
|
-
{ fetchImpl: impl, save: () => {} }
|
|
70
|
-
);
|
|
71
|
-
expect(res.status).toBe(400);
|
|
72
|
-
expect(calls).toEqual([]);
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
describe('credential custody', () => {
|
|
77
|
-
test('the health probe is TOKENLESS and carries no password', async () => {
|
|
78
|
-
// A lookalike address must never receive a credential (phase-29 A2).
|
|
79
|
-
const { impl, calls } = scriptedFetch({ '/health': HEALTHY, '/auth/login': LOGGED_IN });
|
|
80
|
-
await signInToWorkspace(CREDS, { fetchImpl: impl, save: () => {} });
|
|
81
|
-
|
|
82
|
-
const probe = calls.find((c) => c.url.endsWith('/health'));
|
|
83
|
-
expect(probe).toBeDefined();
|
|
84
|
-
expect(probe?.init?.body).toBeUndefined();
|
|
85
|
-
expect(JSON.stringify(probe?.init?.headers ?? {})).not.toContain('Authorization');
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
test('the password goes ONLY to the typed address, once, and is never stored', async () => {
|
|
89
|
-
const stored: Array<{ url: string; token: string }> = [];
|
|
90
|
-
const { impl, calls } = scriptedFetch({ '/health': HEALTHY, '/auth/login': LOGGED_IN });
|
|
91
|
-
await signInToWorkspace(CREDS, {
|
|
92
|
-
fetchImpl: impl,
|
|
93
|
-
save: (url, token) => void stored.push({ url, token }),
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
const withPassword = calls.filter((c) => String(c.init?.body ?? '').includes('hunter2222222'));
|
|
97
|
-
expect(withPassword).toHaveLength(1);
|
|
98
|
-
expect(withPassword[0]?.url).toBe('https://team.example.com/auth/login');
|
|
99
|
-
|
|
100
|
-
// What is persisted is the minted TOKEN — never the password.
|
|
101
|
-
expect(stored).toHaveLength(1);
|
|
102
|
-
expect(stored[0]?.token).toBe('mau_0123456789abcdef0123456789abcdef');
|
|
103
|
-
expect(JSON.stringify(stored)).not.toContain('hunter2222222');
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
test('nothing is saved when sign-in fails', async () => {
|
|
107
|
-
const stored: string[] = [];
|
|
108
|
-
const { impl } = scriptedFetch({
|
|
109
|
-
'/health': HEALTHY,
|
|
110
|
-
'/auth/login': () => json({ error: 'invalid email or password' }, 401),
|
|
111
|
-
});
|
|
112
|
-
const res = await signInToWorkspace(CREDS, {
|
|
113
|
-
fetchImpl: impl,
|
|
114
|
-
save: (u) => void stored.push(u),
|
|
115
|
-
});
|
|
116
|
-
expect(res.status).toBe(401);
|
|
117
|
-
expect(stored).toEqual([]);
|
|
118
|
-
});
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
describe('failure modes are distinguishable and actionable', () => {
|
|
122
|
-
test('an unreachable address says so, and never reaches login', async () => {
|
|
123
|
-
const { impl, calls } = scriptedFetch({
|
|
124
|
-
'/health': () => {
|
|
125
|
-
throw new Error('ECONNREFUSED');
|
|
126
|
-
},
|
|
127
|
-
});
|
|
128
|
-
const res = await signInToWorkspace(CREDS, { fetchImpl: impl, save: () => {} });
|
|
129
|
-
expect((res.json as { reason: string }).reason).toBe('unreachable');
|
|
130
|
-
expect((res.json as { error: string }).error).toMatch(/couldn't reach/i);
|
|
131
|
-
expect(calls.some((c) => c.url.includes('/auth/login'))).toBe(false);
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
test('an address that answers but is not a Maude workspace is named as such', async () => {
|
|
135
|
-
// A typo'd address that lands on someone else's server would otherwise fail
|
|
136
|
-
// later as a mysterious auth error.
|
|
137
|
-
const { impl } = scriptedFetch({ '/health': () => json({ status: 'ok, but not maude' }) });
|
|
138
|
-
const res = await signInToWorkspace(CREDS, { fetchImpl: impl, save: () => {} });
|
|
139
|
-
expect((res.json as { reason: string }).reason).toBe('not-a-maude-workspace');
|
|
140
|
-
expect((res.json as { error: string }).error).toMatch(/isn't a Maude workspace/i);
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
test('bad credentials do not guess WHICH half was wrong', async () => {
|
|
144
|
-
// The hub refuses to be a user-existence oracle, so the client must not
|
|
145
|
-
// invent one by saying "wrong password" when the account may not exist.
|
|
146
|
-
const { impl } = scriptedFetch({
|
|
147
|
-
'/health': HEALTHY,
|
|
148
|
-
'/auth/login': () => json({ error: 'invalid email or password' }, 401),
|
|
149
|
-
});
|
|
150
|
-
const res = await signInToWorkspace(CREDS, { fetchImpl: impl, save: () => {} });
|
|
151
|
-
const error = (res.json as { error: string }).error;
|
|
152
|
-
expect(error).not.toMatch(/no such (user|account)/i);
|
|
153
|
-
expect(error).not.toMatch(/wrong password/i);
|
|
154
|
-
expect(error).toMatch(/not accepted/i);
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
test('rate limiting says to wait rather than to retry', async () => {
|
|
158
|
-
const { impl } = scriptedFetch({
|
|
159
|
-
'/health': HEALTHY,
|
|
160
|
-
'/auth/login': () => json({ error: 'rate limit exceeded' }, 429),
|
|
161
|
-
});
|
|
162
|
-
const res = await signInToWorkspace(CREDS, { fetchImpl: impl, save: () => {} });
|
|
163
|
-
expect((res.json as { reason: string }).reason).toBe('rate-limited');
|
|
164
|
-
expect((res.json as { error: string }).error).toMatch(/wait a minute/i);
|
|
165
|
-
});
|
|
166
|
-
|
|
167
|
-
test("a cloud workspace's 400 message reaches the person verbatim (Phase 23 B3)", async () => {
|
|
168
|
-
// The hub's cloud-identity refusal comes WITH directions ("sign in through
|
|
169
|
-
// Maude Cloud" / what viewing needs). Swallowing it into "try again
|
|
170
|
-
// shortly" turned the most actionable message on this path into a shrug.
|
|
171
|
-
const { impl } = scriptedFetch({
|
|
172
|
-
'/health': HEALTHY,
|
|
173
|
-
'/auth/login': () =>
|
|
174
|
-
json(
|
|
175
|
-
{
|
|
176
|
-
error:
|
|
177
|
-
'This workspace signs in through Maude Cloud — use Sign in to Maude Cloud in the app.',
|
|
178
|
-
},
|
|
179
|
-
400
|
|
180
|
-
),
|
|
181
|
-
});
|
|
182
|
-
const res = await signInToWorkspace(CREDS, { fetchImpl: impl, save: () => {} });
|
|
183
|
-
expect(res.status).toBe(400);
|
|
184
|
-
expect((res.json as { reason: string }).reason).toBe('cloud-identity');
|
|
185
|
-
expect((res.json as { error: string }).error).toMatch(/signs in through Maude Cloud/);
|
|
186
|
-
expect((res.json as { error: string }).error).not.toMatch(/try again shortly/i);
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
test('a failed save is reported instead of pretending success', async () => {
|
|
190
|
-
const { impl } = scriptedFetch({ '/health': HEALTHY, '/auth/login': LOGGED_IN });
|
|
191
|
-
const res = await signInToWorkspace(CREDS, {
|
|
192
|
-
fetchImpl: impl,
|
|
193
|
-
save: () => {
|
|
194
|
-
throw new Error('read-only fs');
|
|
195
|
-
},
|
|
196
|
-
});
|
|
197
|
-
expect((res.json as { reason: string }).reason).toBe('save-failed');
|
|
198
|
-
});
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
describe('success', () => {
|
|
202
|
-
test('returns the person and their session, never the token', async () => {
|
|
203
|
-
const { impl } = scriptedFetch({ '/health': HEALTHY, '/auth/login': LOGGED_IN });
|
|
204
|
-
const res = await signInToWorkspace(CREDS, { fetchImpl: impl, save: () => {} });
|
|
205
|
-
|
|
206
|
-
expect(res.status).toBe(200);
|
|
207
|
-
expect(res.json).toEqual({
|
|
208
|
-
ok: true,
|
|
209
|
-
url: 'https://team.example.com',
|
|
210
|
-
user: { email: 'alice@example.com', role: 'member' },
|
|
211
|
-
expiresAt: 1_800_000_000_000,
|
|
212
|
-
version: '0.48.0',
|
|
213
|
-
});
|
|
214
|
-
// The token must not travel back to the UI layer — it has no use for it and
|
|
215
|
-
// every surface that holds one is a surface that can leak one.
|
|
216
|
-
expect(JSON.stringify(res.json)).not.toContain('mau_');
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
test('a trailing slash or bare host normalizes to the same workspace', async () => {
|
|
220
|
-
const stored: string[] = [];
|
|
221
|
-
for (const url of ['https://team.example.com/', 'https://team.example.com']) {
|
|
222
|
-
const { impl } = scriptedFetch({ '/health': HEALTHY, '/auth/login': LOGGED_IN });
|
|
223
|
-
await signInToWorkspace(
|
|
224
|
-
{ ...CREDS, url },
|
|
225
|
-
{ fetchImpl: impl, save: (u) => void stored.push(u) }
|
|
226
|
-
);
|
|
227
|
-
}
|
|
228
|
-
expect(new Set(stored).size).toBe(1);
|
|
229
|
-
});
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
describe('the disclosure panel — DDR-054 made visible (DDR-192 §6)', () => {
|
|
233
|
-
const text = (items: DisclosureItem[]) => items.map((i) => `${i.title} ${i.detail}`).join(' ');
|
|
234
|
-
|
|
235
|
-
test('it says what the operator CAN see, not only what they cannot', () => {
|
|
236
|
-
// A disclosure that only lists reassurances is marketing. The point is that
|
|
237
|
-
// the person can decide, which requires the uncomfortable half.
|
|
238
|
-
const items = workspaceDisclosure({ operator: 'your team', aiAvailable: true });
|
|
239
|
-
const sees = items.filter((i) => i.kind === 'sees');
|
|
240
|
-
expect(sees.length).toBeGreaterThanOrEqual(3);
|
|
241
|
-
expect(text(sees)).toMatch(/edit history/i);
|
|
242
|
-
expect(text(sees)).toMatch(/when you are editing/i);
|
|
243
|
-
expect(text(sees)).toMatch(/comments/i);
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
test('it names the containment invariant in words a person understands', () => {
|
|
247
|
-
const items = workspaceDisclosure({ operator: 'Maude Cloud', aiAvailable: true });
|
|
248
|
-
expect(text(items)).toMatch(/never executes them/i);
|
|
249
|
-
expect(text(items)).toMatch(/render here, on your machine/i);
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
test('it names the operator, so "who can see this" has an answer', () => {
|
|
253
|
-
const items = workspaceDisclosure({ operator: 'Acme Design Ltd', aiAvailable: true });
|
|
254
|
-
expect(text(items)).toContain('Acme Design Ltd');
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
test('the AI-less state is stated as a fact, not an error', () => {
|
|
258
|
-
// Phase 6's persona: an invitee without a Claude subscription gets a
|
|
259
|
-
// first-class product, not a broken one.
|
|
260
|
-
const off = workspaceDisclosure({ operator: 'your team', aiAvailable: false });
|
|
261
|
-
const ai = off.find((i) => i.title.includes('AI'));
|
|
262
|
-
expect(ai?.detail).toMatch(/Everything else works normally/i);
|
|
263
|
-
expect(ai?.detail).not.toMatch(/error|unavailable|failed|missing/i);
|
|
264
|
-
|
|
265
|
-
const on = workspaceDisclosure({ operator: 'your team', aiAvailable: true });
|
|
266
|
-
expect(on.find((i) => i.title.includes('AI'))?.detail).toMatch(/your own subscription/i);
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
test('it promises the exit, because that is what makes the rest believable', () => {
|
|
270
|
-
const items = workspaceDisclosure({ operator: 'Maude Cloud', aiAvailable: true });
|
|
271
|
-
expect(text(items)).toMatch(/opens without Maude/i);
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
test('no jargon reaches the person', () => {
|
|
275
|
-
// DDR-193 §5 — the product word is "project"/"workspace". These words on an
|
|
276
|
-
// invite path tell a non-developer the product is not for them.
|
|
277
|
-
const items = workspaceDisclosure({ operator: 'your team', aiAvailable: false });
|
|
278
|
-
const all = text(items).toLowerCase();
|
|
279
|
-
for (const word of [
|
|
280
|
-
'token',
|
|
281
|
-
'repository',
|
|
282
|
-
'repo ',
|
|
283
|
-
'oauth',
|
|
284
|
-
'bearer',
|
|
285
|
-
'crdt',
|
|
286
|
-
'yjs',
|
|
287
|
-
'commit',
|
|
288
|
-
]) {
|
|
289
|
-
expect(all).not.toContain(word);
|
|
290
|
-
}
|
|
291
|
-
});
|
|
292
|
-
});
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
// Smoke: WebSocket upgrade against Bun.serve's native handler.
|
|
2
|
-
|
|
3
|
-
import { describe, expect, test } from 'bun:test';
|
|
4
|
-
|
|
5
|
-
import { bootServer, killProc, makeSandbox, nextPort } from './_helpers.ts';
|
|
6
|
-
|
|
7
|
-
describe('ws handshake', () => {
|
|
8
|
-
test('upgrades and receives initial snapshot', async () => {
|
|
9
|
-
const { root } = makeSandbox();
|
|
10
|
-
const port = nextPort();
|
|
11
|
-
const proc = await bootServer(root, port);
|
|
12
|
-
try {
|
|
13
|
-
const ws = new WebSocket(`ws://localhost:${port}/_ws`);
|
|
14
|
-
const first = await new Promise<string>((resolve, reject) => {
|
|
15
|
-
const t = setTimeout(() => reject(new Error('no message')), 2000);
|
|
16
|
-
ws.addEventListener('message', (e) => {
|
|
17
|
-
clearTimeout(t);
|
|
18
|
-
resolve(
|
|
19
|
-
typeof e.data === 'string' ? e.data : new TextDecoder().decode(e.data as ArrayBuffer)
|
|
20
|
-
);
|
|
21
|
-
});
|
|
22
|
-
ws.addEventListener('error', (e) => reject(e));
|
|
23
|
-
});
|
|
24
|
-
const parsed = JSON.parse(first);
|
|
25
|
-
expect(parsed.type).toBe('snapshot');
|
|
26
|
-
expect(parsed.state).toBeDefined();
|
|
27
|
-
expect(parsed.state.session_started).toBeTypeOf('string');
|
|
28
|
-
ws.close();
|
|
29
|
-
} finally {
|
|
30
|
-
await killProc(proc);
|
|
31
|
-
}
|
|
32
|
-
});
|
|
33
|
-
});
|
|
@@ -1,166 +0,0 @@
|
|
|
1
|
-
// `maude cache` CLI end-to-end via spawnSync — seeds a temp cache dir through
|
|
2
|
-
// the cache lib, then exercises list / stats / inspect / clear over the bin.
|
|
3
|
-
|
|
4
|
-
import assert from 'node:assert/strict';
|
|
5
|
-
import { spawnSync } from 'node:child_process';
|
|
6
|
-
import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
7
|
-
import { tmpdir } from 'node:os';
|
|
8
|
-
import { dirname, join, resolve } from 'node:path';
|
|
9
|
-
import { test } from 'node:test';
|
|
10
|
-
import { fileURLToPath } from 'node:url';
|
|
11
|
-
import { getOrCompute, write } from '../lib/cache.mjs';
|
|
12
|
-
|
|
13
|
-
const BIN = resolve(dirname(fileURLToPath(import.meta.url)), '..', 'bin', 'maude.mjs');
|
|
14
|
-
|
|
15
|
-
function runCli(args, cacheDir) {
|
|
16
|
-
return spawnSync(process.execPath, [BIN, 'cache', ...args], {
|
|
17
|
-
encoding: 'utf8',
|
|
18
|
-
env: { ...process.env, MAUDE_CACHE_DIR: cacheDir },
|
|
19
|
-
});
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
async function withCache(fn) {
|
|
23
|
-
const dir = mkdtempSync(join(tmpdir(), 'maude-cli-cache-'));
|
|
24
|
-
try {
|
|
25
|
-
return await fn(dir);
|
|
26
|
-
} finally {
|
|
27
|
-
rmSync(dir, { recursive: true, force: true });
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
test('cache help prints subcommand summary', async () => {
|
|
32
|
-
await withCache((dir) => {
|
|
33
|
-
const res = runCli(['help'], dir);
|
|
34
|
-
assert.equal(res.status, 0, res.stderr);
|
|
35
|
-
assert.match(res.stdout, /maude cache <get\|put\|list\|stats\|inspect\|clear>/);
|
|
36
|
-
});
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
test('cache list reports "empty" before any writes', async () => {
|
|
40
|
-
await withCache((dir) => {
|
|
41
|
-
const res = runCli(['list'], dir);
|
|
42
|
-
assert.equal(res.status, 0, res.stderr);
|
|
43
|
-
assert.match(res.stdout, /cache is empty/);
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
test('cache list shows seeded layers with entry counts', async () => {
|
|
48
|
-
await withCache((dir) => {
|
|
49
|
-
write('research/domain', 'finance.aaa', { mood: 1 }, {}, { cacheDir: dir });
|
|
50
|
-
write('research/domain', 'finance.bbb', { mood: 2 }, {}, { cacheDir: dir });
|
|
51
|
-
write('codebase-intelligence', 'sha123', { files: 9 }, {}, { cacheDir: dir });
|
|
52
|
-
const res = runCli(['list'], dir);
|
|
53
|
-
assert.equal(res.status, 0, res.stderr);
|
|
54
|
-
assert.match(res.stdout, /research\s+2/);
|
|
55
|
-
assert.match(res.stdout, /codebase-intelligence\s+1/);
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
test('cache stats reports hit-rate after getOrCompute activity', async () => {
|
|
60
|
-
await withCache(async (dir) => {
|
|
61
|
-
const base = {
|
|
62
|
-
cacheDir: dir,
|
|
63
|
-
layer: 'codebase-intelligence',
|
|
64
|
-
key: 'k',
|
|
65
|
-
ttlMs: 60_000,
|
|
66
|
-
compute: () => ({ v: 1 }),
|
|
67
|
-
};
|
|
68
|
-
await getOrCompute(base); // miss
|
|
69
|
-
await getOrCompute(base); // hit
|
|
70
|
-
const res = runCli(['stats'], dir);
|
|
71
|
-
assert.equal(res.status, 0, res.stderr);
|
|
72
|
-
assert.match(res.stdout, /codebase-intelligence/);
|
|
73
|
-
assert.match(res.stdout, /50%/);
|
|
74
|
-
});
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
test('cache inspect lists entries, and prints one entry by key', async () => {
|
|
78
|
-
await withCache((dir) => {
|
|
79
|
-
write('design-context', 'ds/tok1', { tokens: 42 }, { dsName: 'ds' }, { cacheDir: dir });
|
|
80
|
-
const listRes = runCli(['inspect', 'design-context'], dir);
|
|
81
|
-
assert.equal(listRes.status, 0, listRes.stderr);
|
|
82
|
-
assert.match(listRes.stdout, /ds\/tok1/);
|
|
83
|
-
|
|
84
|
-
const oneRes = runCli(['inspect', 'design-context', 'ds/tok1'], dir);
|
|
85
|
-
assert.equal(oneRes.status, 0, oneRes.stderr);
|
|
86
|
-
assert.match(oneRes.stdout, /"tokens": 42/);
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
test('cache clear <layer> wipes only that layer', async () => {
|
|
91
|
-
await withCache((dir) => {
|
|
92
|
-
write('research/domain', 'a', { x: 1 }, {}, { cacheDir: dir });
|
|
93
|
-
write('codebase-intelligence', 'b', { x: 2 }, {}, { cacheDir: dir });
|
|
94
|
-
const res = runCli(['clear', 'research/domain'], dir);
|
|
95
|
-
assert.equal(res.status, 0, res.stderr);
|
|
96
|
-
assert.match(res.stdout, /cleared layer "research\/domain"/);
|
|
97
|
-
assert.ok(!existsSync(join(dir, 'research', 'domain')));
|
|
98
|
-
assert.ok(existsSync(join(dir, 'codebase-intelligence')));
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
test('cache clear with no args wipes everything', async () => {
|
|
103
|
-
await withCache((dir) => {
|
|
104
|
-
write('research/domain', 'a', { x: 1 }, {}, { cacheDir: dir });
|
|
105
|
-
const res = runCli(['clear'], dir);
|
|
106
|
-
assert.equal(res.status, 0, res.stderr);
|
|
107
|
-
assert.match(res.stdout, /cleared entire cache/);
|
|
108
|
-
assert.ok(!existsSync(join(dir, 'research')));
|
|
109
|
-
});
|
|
110
|
-
});
|
|
111
|
-
|
|
112
|
-
test('get prints compact JSON on a fresh hit (exit 0), nothing on miss (exit 1)', async () => {
|
|
113
|
-
await withCache((dir) => {
|
|
114
|
-
write('codebase-intelligence', 'sha9', { files: 142 }, {}, { cacheDir: dir });
|
|
115
|
-
const hit = runCli(['get', 'codebase-intelligence', 'sha9'], dir);
|
|
116
|
-
assert.equal(hit.status, 0, hit.stderr);
|
|
117
|
-
assert.equal(hit.stdout.trim(), '{"files":142}');
|
|
118
|
-
|
|
119
|
-
const miss = runCli(['get', 'codebase-intelligence', 'absent'], dir);
|
|
120
|
-
assert.equal(miss.status, 1);
|
|
121
|
-
assert.equal(miss.stdout, '');
|
|
122
|
-
});
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
test('get treats a past-TTL entry as a miss (exit 1)', async () => {
|
|
126
|
-
await withCache((dir) => {
|
|
127
|
-
const { path } = write('security', 'head1', { verdict: 'PASS' }, {}, { cacheDir: dir });
|
|
128
|
-
const stored = JSON.parse(readFileSync(path, 'utf8'));
|
|
129
|
-
stored.writtenAt = Date.now() - 2 * 60 * 60 * 1000; // 2 h old
|
|
130
|
-
writeFileSync(path, JSON.stringify(stored), 'utf8');
|
|
131
|
-
const res = runCli(['get', 'security', 'head1', '--ttl-ms', String(60 * 60 * 1000)], dir);
|
|
132
|
-
assert.equal(res.status, 1, 'past-TTL must be a miss');
|
|
133
|
-
});
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
test('get feeds maude cache stats (hit + miss counters)', async () => {
|
|
137
|
-
await withCache((dir) => {
|
|
138
|
-
write('research/domain', 'k', { v: 1 }, {}, { cacheDir: dir });
|
|
139
|
-
runCli(['get', 'research/domain', 'k'], dir); // hit
|
|
140
|
-
runCli(['get', 'research/domain', 'absent'], dir); // miss
|
|
141
|
-
const res = runCli(['stats'], dir);
|
|
142
|
-
assert.equal(res.status, 0, res.stderr);
|
|
143
|
-
assert.match(res.stdout, /research\/domain/);
|
|
144
|
-
assert.match(res.stdout, /50%/);
|
|
145
|
-
});
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
test('put writes a value (from file) that get then reads back', async () => {
|
|
149
|
-
await withCache((dir) => {
|
|
150
|
-
const f = join(dir, 'payload.json');
|
|
151
|
-
writeFileSync(f, JSON.stringify({ mood: ['calm'], queries: 7 }), 'utf8');
|
|
152
|
-
const put = runCli(['put', 'research/domain', 'finance--discovery', f], dir);
|
|
153
|
-
assert.equal(put.status, 0, put.stderr);
|
|
154
|
-
const get = runCli(['get', 'research/domain', 'finance--discovery'], dir);
|
|
155
|
-
assert.equal(get.status, 0);
|
|
156
|
-
assert.deepEqual(JSON.parse(get.stdout), { mood: ['calm'], queries: 7 });
|
|
157
|
-
});
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
test('unknown subcommand exits non-zero', async () => {
|
|
161
|
-
await withCache((dir) => {
|
|
162
|
-
const res = runCli(['frobnicate'], dir);
|
|
163
|
-
assert.equal(res.status, 2);
|
|
164
|
-
assert.match(res.stderr, /unknown subcommand/);
|
|
165
|
-
});
|
|
166
|
-
});
|