@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
|
@@ -86,6 +86,13 @@ function parseEntry(raw: unknown): JournalEntry | null {
|
|
|
86
86
|
* Returns null when the hub is unreachable, refuses, or does not have the
|
|
87
87
|
* route — the `fetchRemoteListing` posture: sync continues either way and we
|
|
88
88
|
* ask again later. A null is never "nothing changed".
|
|
89
|
+
*
|
|
90
|
+
* It is also never "and there is nothing to learn from it". The cursor read
|
|
91
|
+
* shares the hub's per-label read bucket with the file pulls, so during a rate
|
|
92
|
+
* limit THIS is the request that meets the wall first — and collapsing that to
|
|
93
|
+
* a bare null is how issue #109 stayed invisible: a held plane and a
|
|
94
|
+
* quiet, ordinary, do-nothing pass are indistinguishable to the caller.
|
|
95
|
+
* `onRefused` hands the response to whoever can tell the difference.
|
|
89
96
|
*/
|
|
90
97
|
export async function fetchJournal(opts: {
|
|
91
98
|
hubUrl: string;
|
|
@@ -94,6 +101,8 @@ export async function fetchJournal(opts: {
|
|
|
94
101
|
/** Send the epoch a cursor belongs to so a mismatch fails closed hub-side. */
|
|
95
102
|
epoch?: string | null;
|
|
96
103
|
fetchImpl?: typeof fetch;
|
|
104
|
+
/** Called with the response before a non-ok status becomes `null`. */
|
|
105
|
+
onRefused?: (res: Response) => void | Promise<void>;
|
|
97
106
|
}): Promise<JournalPage | null> {
|
|
98
107
|
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
99
108
|
const base = opts.hubUrl.replace(/\/+$/, '');
|
|
@@ -105,7 +114,10 @@ export async function fetchJournal(opts: {
|
|
|
105
114
|
headers: { authorization: `Bearer ${opts.token}` },
|
|
106
115
|
signal: AbortSignal.timeout(JOURNAL_TIMEOUT_MS),
|
|
107
116
|
});
|
|
108
|
-
if (!res.ok)
|
|
117
|
+
if (!res.ok) {
|
|
118
|
+
await opts.onRefused?.(res);
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
109
121
|
const body = (await res.json()) as Record<string, unknown>;
|
|
110
122
|
// The head and the epoch are the anchor the whole cursor protocol rests
|
|
111
123
|
// on, and both arrive from a component DDR-054 calls untrusted. A
|
|
@@ -35,6 +35,7 @@ import path from 'node:path';
|
|
|
35
35
|
import type * as Y from 'yjs';
|
|
36
36
|
|
|
37
37
|
import { Y_TYPES } from '../collab/persistence.ts';
|
|
38
|
+
import { atomicWrite } from './atomic-write.ts';
|
|
38
39
|
import {
|
|
39
40
|
annotationsEditAtFromDoc,
|
|
40
41
|
applyAnnotationsToDoc,
|
|
@@ -49,11 +50,22 @@ import {
|
|
|
49
50
|
Y_SYNC_TYPES,
|
|
50
51
|
} from './codec.ts';
|
|
51
52
|
import type { ColdStartAction } from './cold-start.ts';
|
|
52
|
-
import {
|
|
53
|
-
|
|
53
|
+
import {
|
|
54
|
+
decideAnnotationsColdStart,
|
|
55
|
+
decideColdStart,
|
|
56
|
+
decideCssColdStart,
|
|
57
|
+
isExactRepeat,
|
|
58
|
+
unionCommentsById,
|
|
59
|
+
} from './cold-start.ts';
|
|
60
|
+
import { applyColdStart, type ColdStartSnapshotReason } from './cold-start-apply.ts';
|
|
54
61
|
import { hashBytes } from './echo-guard.ts';
|
|
55
62
|
import type { SyncJournal } from './journal.ts';
|
|
56
63
|
import { ORIGINS } from './origins.ts';
|
|
64
|
+
import { collapseRepeatedModule, collapseRepeatedText } from './repeated-module.ts';
|
|
65
|
+
import { rememberSeed } from './seed-repair.ts';
|
|
66
|
+
import { mergeSource } from './source-merge.ts';
|
|
67
|
+
import { lastValidSource, readRecoveryBody, saveRecoveryBody } from './source-recovery.ts';
|
|
68
|
+
import { sourceError } from './source-validation.ts';
|
|
57
69
|
|
|
58
70
|
export interface MigrateSeedPaths {
|
|
59
71
|
html: string;
|
|
@@ -74,7 +86,7 @@ export interface MigrateSeedOptions {
|
|
|
74
86
|
/** DDR-102 — per-machine journal; gates fast-forward vs conflict. */
|
|
75
87
|
journal?: SyncJournal;
|
|
76
88
|
/** DDR-102 — body snapshot writer (history.ts), same contract as the agent's. */
|
|
77
|
-
snapshot?: (content: string, reason:
|
|
89
|
+
snapshot?: (content: string, reason: ColdStartSnapshotReason) => Promise<string | null>;
|
|
78
90
|
/**
|
|
79
91
|
* Does the HUB hold state for this slug, per its last document listing?
|
|
80
92
|
*
|
|
@@ -92,6 +104,13 @@ export interface MigrateSeedOptions {
|
|
|
92
104
|
* does not have it", which is the pre-existing behaviour.
|
|
93
105
|
*/
|
|
94
106
|
hubHasState?: (slug: string) => boolean;
|
|
107
|
+
/**
|
|
108
|
+
* A local candidate diverged from the hub body and could not be merged from
|
|
109
|
+
* their shared base. Neither side is overwritten: the caller hands `base` to
|
|
110
|
+
* the projection (`adoptBase`) so its write stays blocked with a visible
|
|
111
|
+
* conflict until a later save resolves it (audit 2026-09-13 P0 #1 / T2).
|
|
112
|
+
*/
|
|
113
|
+
onHold?: (base: string) => void;
|
|
95
114
|
/** DDR-102 — divergence notification, same contract as the agent's. */
|
|
96
115
|
onConflict?: (info: {
|
|
97
116
|
slug: string;
|
|
@@ -118,6 +137,10 @@ export type MigrateSeedResult =
|
|
|
118
137
|
/** DDR-102 — divergence resolved newest-wins. */
|
|
119
138
|
| 'conflict-local-wins'
|
|
120
139
|
| 'conflict-hub-wins'
|
|
140
|
+
/** T2 — divergence resolved by a clean three-way merge from the saved base. */
|
|
141
|
+
| 'conflict-merged'
|
|
142
|
+
/** T2 — divergence that no merge could prove independent; both kept, held. */
|
|
143
|
+
| 'conflict-held'
|
|
121
144
|
/** The replica is empty but the HUB is not — its state is still in flight.
|
|
122
145
|
* Seeding here is the F1 collision (see `hubHasState`), so this seed does
|
|
123
146
|
* nothing and lets the document arrive. */
|
|
@@ -141,11 +164,17 @@ export function docIsEmpty(doc: Y.Doc): boolean {
|
|
|
141
164
|
export async function migrateSeed(opts: MigrateSeedOptions): Promise<MigrateSeedResult> {
|
|
142
165
|
const { slug, doc, paths } = opts;
|
|
143
166
|
|
|
144
|
-
|
|
167
|
+
// A file already holding its module k× over (an earlier seed race) enters
|
|
168
|
+
// as ONE copy — adopting it as-is would plant the repeat in the project.
|
|
169
|
+
const readHtml = readLocal(paths.html);
|
|
170
|
+
const diskHtml = readHtml === null ? null : (collapseRepeatedModule(readHtml)?.unit ?? readHtml);
|
|
171
|
+
const localHtml =
|
|
172
|
+
diskHtml !== null && sourceError(paths.html, diskHtml) === null ? diskHtml : null;
|
|
145
173
|
const localComments = readLocal(paths.comments);
|
|
146
174
|
const localAnnotations = readLocal(paths.annotations);
|
|
147
175
|
const localMeta = paths.meta ? readLocal(paths.meta) : null;
|
|
148
|
-
const
|
|
176
|
+
const readCss = paths.css ? readLocal(paths.css) : null;
|
|
177
|
+
const localCss = readCss === null ? null : (collapseRepeatedText(readCss)?.unit ?? readCss);
|
|
149
178
|
|
|
150
179
|
// Hub was empty → adopt local. Build the doc from the local files ONCE, inside
|
|
151
180
|
// a single MIGRATION transaction. The apply* codecs delete-then-insert, so
|
|
@@ -177,6 +206,7 @@ export async function migrateSeed(opts: MigrateSeedOptions): Promise<MigrateSeed
|
|
|
177
206
|
|
|
178
207
|
doc.transact(() => {
|
|
179
208
|
if (localHtml) {
|
|
209
|
+
rememberSeed(doc, localHtml, localCss, ORIGINS.MIGRATION);
|
|
180
210
|
if (applyHtmlToDoc(doc, localHtml, ORIGINS.MIGRATION)) {
|
|
181
211
|
stampBodyEdit(doc, ORIGINS.MIGRATION);
|
|
182
212
|
}
|
|
@@ -214,6 +244,16 @@ export async function migrateSeed(opts: MigrateSeedOptions): Promise<MigrateSeed
|
|
|
214
244
|
// boot — not spam) so non-body files keep their pre-cutover backup too.
|
|
215
245
|
snapshotLocal(opts);
|
|
216
246
|
|
|
247
|
+
// Invalid hub source must reach the projector's quarantine unchanged. Never
|
|
248
|
+
// checkpoint it, elect it by timestamp, or merge a healthy local file into it
|
|
249
|
+
// merely because the connection restarted. A deliberate file edit can repair it.
|
|
250
|
+
if (
|
|
251
|
+
sourceError(paths.html, doc.getText(Y_SYNC_TYPES.html).toString()) !== null &&
|
|
252
|
+
!(localHtml && isExactRepeat(doc.getText(Y_SYNC_TYPES.html).toString(), localHtml))
|
|
253
|
+
) {
|
|
254
|
+
return 'hub-wins';
|
|
255
|
+
}
|
|
256
|
+
|
|
217
257
|
// Body resolution via the DDR-102 decision table.
|
|
218
258
|
const docHtml = doc.getText(Y_SYNC_TYPES.html).toString();
|
|
219
259
|
const decision = decideColdStart({
|
|
@@ -230,6 +270,7 @@ export async function migrateSeed(opts: MigrateSeedOptions): Promise<MigrateSeed
|
|
|
230
270
|
* below (decideAnnotationsColdStart), independent of the body winner. */
|
|
231
271
|
const rebuildBodyFromLocal = (): void => {
|
|
232
272
|
doc.transact(() => {
|
|
273
|
+
if (docHtml === '' && localHtml) rememberSeed(doc, localHtml, localCss, ORIGINS.MIGRATION);
|
|
233
274
|
if (applyHtmlToDoc(doc, localHtml as string, ORIGINS.MIGRATION)) {
|
|
234
275
|
stampBodyEdit(doc, ORIGINS.MIGRATION);
|
|
235
276
|
}
|
|
@@ -248,22 +289,61 @@ export async function migrateSeed(opts: MigrateSeedOptions): Promise<MigrateSeed
|
|
|
248
289
|
// fail-closed refusal, the conflict report, and crucially the
|
|
249
290
|
// `recover-seed-dup` row this switch used to be missing — now lives in
|
|
250
291
|
// exactly one place.
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
292
|
+
// A DIVERGENCE WITH A KNOWN BASE IS NOT A COIN TOSS. Newest-wins keeps one
|
|
293
|
+
// side and snapshots the other — recoverable, but the peer's edit is gone
|
|
294
|
+
// from the canvas. When the projection saved the body both sides last agreed
|
|
295
|
+
// on (and the journal proves it is that body), merge from it exactly as a
|
|
296
|
+
// live save does; if the edits touch, hold both and let the projection keep
|
|
297
|
+
// the conflict visible. No base (older state) keeps DDR-102's table.
|
|
298
|
+
const journalHash = opts.journal?.get(slug)?.bodyHash ?? null;
|
|
299
|
+
const savedBase =
|
|
300
|
+
decision.action === 'conflict' && opts.historyDir && journalHash !== null
|
|
301
|
+
? readRecoveryBody(opts.historyDir, paths.html, 'base')
|
|
302
|
+
: null;
|
|
303
|
+
const base = savedBase !== null && hashBytes(savedBase) === journalHash ? savedBase : null;
|
|
304
|
+
let applied: { action: ColdStartAction; bodyWinner: 'local' | 'hub' };
|
|
305
|
+
let result: MigrateSeedResult;
|
|
306
|
+
if (base !== null && localHtml !== null) {
|
|
307
|
+
const merged = mergeSource(base, localHtml, docHtml);
|
|
308
|
+
if (opts.snapshot) {
|
|
309
|
+
try {
|
|
310
|
+
await opts.snapshot(localHtml, 'pre-sync-local');
|
|
311
|
+
await opts.snapshot(docHtml, 'pre-sync-hub');
|
|
312
|
+
} catch {
|
|
313
|
+
/* best-effort — neither branch below overwrites a side it did not merge */
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
if (merged.ok && sourceError(paths.html, merged.merged) === null) {
|
|
317
|
+
doc.transact(() => {
|
|
318
|
+
if (applyHtmlToDoc(doc, merged.merged, ORIGINS.MIGRATION)) {
|
|
319
|
+
stampBodyEdit(doc, ORIGINS.MIGRATION);
|
|
320
|
+
}
|
|
321
|
+
}, ORIGINS.MIGRATION);
|
|
322
|
+
// The projection writes the merged body and checkpoints it.
|
|
323
|
+
result = 'conflict-merged';
|
|
324
|
+
} else {
|
|
325
|
+
opts.onHold?.(base);
|
|
326
|
+
result = 'conflict-held';
|
|
327
|
+
}
|
|
328
|
+
// The coupled lanes resolve per-lane against the hub, as on a hub-wins boot.
|
|
329
|
+
applied = { action: 'conflict', bodyWinner: 'hub' };
|
|
330
|
+
} else {
|
|
331
|
+
applied = await applyColdStart({
|
|
332
|
+
slug,
|
|
333
|
+
decision,
|
|
334
|
+
localBody: localHtml,
|
|
335
|
+
docBody: docHtml,
|
|
336
|
+
takeHub: () => {
|
|
337
|
+
/* the projection materializes the doc; nothing to do here */
|
|
338
|
+
},
|
|
339
|
+
takeLocal: rebuildBodyFromLocal,
|
|
340
|
+
checkpointIdentity: (body) => opts.journal?.record(slug, { bodyHash: hashBytes(body) }),
|
|
341
|
+
logLabel: 'shared-doc',
|
|
342
|
+
...(opts.snapshot ? { snapshot: opts.snapshot } : {}),
|
|
343
|
+
...(opts.onConflict ? { onConflict: opts.onConflict } : {}),
|
|
344
|
+
});
|
|
345
|
+
result = resultFor(applied.action, applied.bodyWinner);
|
|
346
|
+
}
|
|
267
347
|
|
|
268
348
|
// ---- annotations: PER-LANE newest-wins (the 2026-08-14 eraser fix; the
|
|
269
349
|
// same table as agent.ts reconcile). Under sharedDoc the collab room's
|
|
@@ -298,6 +378,38 @@ export async function migrateSeed(opts: MigrateSeedOptions): Promise<MigrateSeed
|
|
|
298
378
|
// annotations doc→file half and materializes it (persistJson).
|
|
299
379
|
}
|
|
300
380
|
|
|
381
|
+
// ---- css: PER-LANE resolution (issue #114), the same table agent.ts uses.
|
|
382
|
+
// `rebuildBodyFromLocal` above already re-seeds css when the BODY winner was
|
|
383
|
+
// local; this block is what covers every other row — above all the exact-repeat
|
|
384
|
+
// collapse, which is how a `CSS × N` lane from a concurrent cold seed gets
|
|
385
|
+
// back to one copy on a hub-wins boot. It no-ops when the two sides already
|
|
386
|
+
// agree, so running after the body applier costs nothing.
|
|
387
|
+
if (paths.css) {
|
|
388
|
+
const docCssNow = doc.getText(Y_SYNC_TYPES.css).toString();
|
|
389
|
+
const cssDecision = decideCssColdStart({
|
|
390
|
+
local: localCss,
|
|
391
|
+
doc: docCssNow.length > 0 ? docCssNow : null,
|
|
392
|
+
journalHash: opts.journal?.get(slug)?.cssHash ?? null,
|
|
393
|
+
hash: hashBytes,
|
|
394
|
+
bodyWinner: applied.bodyWinner,
|
|
395
|
+
});
|
|
396
|
+
if (cssDecision.recoveredDuplication) {
|
|
397
|
+
// Warn, don't snapshot — see the note on the same branch in agent.ts
|
|
398
|
+
// reconcile. An exact integer repeat carries no unique bytes to recover,
|
|
399
|
+
// and snapshotting it hands a hostile hub an eviction lever against the
|
|
400
|
+
// `_history/` copies that DO.
|
|
401
|
+
console.warn(`[sync/${slug}] shared-doc cold-start css: ${cssDecision.reason}`);
|
|
402
|
+
}
|
|
403
|
+
if (cssDecision.winner === 'local' && localCss !== null) {
|
|
404
|
+
doc.transact(() => {
|
|
405
|
+
applyCssToDoc(doc, localCss, ORIGINS.MIGRATION);
|
|
406
|
+
}, ORIGINS.MIGRATION);
|
|
407
|
+
opts.journal?.record(slug, { cssHash: hashBytes(localCss) });
|
|
408
|
+
}
|
|
409
|
+
// winner 'hub' → nothing to write here: the projection materializes the
|
|
410
|
+
// doc's css to disk, exactly as it does for the body.
|
|
411
|
+
}
|
|
412
|
+
|
|
301
413
|
// Comments id-union (DDR-102): rebuild from merged JSON via the
|
|
302
414
|
// delete-then-insert codec — same-id entries keep the doc's version, so the
|
|
303
415
|
// duplication trap stays closed; local-only comments survive.
|
|
@@ -357,7 +469,23 @@ function snapshotLocal(opts: MigrateSeedOptions): void {
|
|
|
357
469
|
opts.paths.css,
|
|
358
470
|
]) {
|
|
359
471
|
if (p && existsSync(p)) {
|
|
360
|
-
|
|
472
|
+
const target = path.join(dir, path.basename(p));
|
|
473
|
+
if (p === opts.paths.html) {
|
|
474
|
+
const current = readLocal(p);
|
|
475
|
+
// A body holding the same module twice over parses, but it is the
|
|
476
|
+
// corruption this snapshot exists to survive — never its "valid"
|
|
477
|
+
// copy, and never a reason to replace a healthy earlier snapshot.
|
|
478
|
+
const healthy = (body: string | null): body is string =>
|
|
479
|
+
!!body?.trim() &&
|
|
480
|
+
sourceError(p, body) === null &&
|
|
481
|
+
collapseRepeatedModule(body) === null;
|
|
482
|
+
const valid = healthy(current) ? current : lastValidSource(opts.historyDir, p);
|
|
483
|
+
if (valid && healthy(valid)) {
|
|
484
|
+
saveRecoveryBody(opts.historyDir, p, 'last-valid', valid);
|
|
485
|
+
const prior = readLocal(target);
|
|
486
|
+
if (!healthy(prior)) atomicWrite(target, valid);
|
|
487
|
+
}
|
|
488
|
+
} else copyFileSync(p, target);
|
|
361
489
|
}
|
|
362
490
|
}
|
|
363
491
|
} catch {
|
package/apps/studio/sync/poke.ts
CHANGED
|
@@ -22,6 +22,8 @@ const MAX_POKE_BYTES = 512;
|
|
|
22
22
|
export interface Poke {
|
|
23
23
|
/** The hub's journal head at emit time. A hint, never an authority. */
|
|
24
24
|
head: number;
|
|
25
|
+
/** Only document membership changed; do not scan or transfer the file plane. */
|
|
26
|
+
documents?: true;
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
/**
|
|
@@ -42,9 +44,9 @@ export function parsePoke(payload: unknown): Poke | null {
|
|
|
42
44
|
return null;
|
|
43
45
|
}
|
|
44
46
|
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) return null;
|
|
45
|
-
const frame = parsed as { t?: unknown; head?: unknown };
|
|
47
|
+
const frame = parsed as { t?: unknown; head?: unknown; documents?: unknown };
|
|
46
48
|
if (frame.t !== 'files') return null;
|
|
47
49
|
const head = frame.head;
|
|
48
50
|
if (typeof head !== 'number' || !Number.isInteger(head) || head < 0) return null;
|
|
49
|
-
return { head };
|
|
51
|
+
return frame.documents === true ? { head, documents: true } : { head };
|
|
50
52
|
}
|