@1agh/maude 0.29.0 → 0.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/README.md +1 -1
  2. package/apps/studio/ai-banner.tsx +0 -1
  3. package/apps/studio/annotations-align.ts +149 -0
  4. package/apps/studio/annotations-bindings.ts +197 -0
  5. package/apps/studio/annotations-context-toolbar.tsx +436 -186
  6. package/apps/studio/annotations-groups.ts +270 -0
  7. package/apps/studio/annotations-layer.tsx +1708 -1660
  8. package/apps/studio/annotations-model.ts +2077 -0
  9. package/apps/studio/annotations-snap.ts +125 -0
  10. package/apps/studio/api.ts +208 -116
  11. package/apps/studio/bin/_png-playwright.mjs +1 -1
  12. package/apps/studio/bin/annotate.mjs +732 -0
  13. package/apps/studio/bin/annotate.sh +17 -0
  14. package/apps/studio/bin/read-annotations.mjs +152 -17
  15. package/apps/studio/build.ts +1 -1
  16. package/apps/studio/canvas-arrowheads.ts +78 -9
  17. package/apps/studio/canvas-cursors.ts +2 -0
  18. package/apps/studio/canvas-edit.ts +257 -7
  19. package/apps/studio/canvas-icons.tsx +105 -0
  20. package/apps/studio/canvas-shell.tsx +305 -8
  21. package/apps/studio/client/app.jsx +2812 -238
  22. package/apps/studio/client/index.html +1 -1
  23. package/apps/studio/client/styles/3-shell-maude.css +713 -11
  24. package/apps/studio/client/styles/4-components.css +39 -0
  25. package/apps/studio/client/styles/5-maude-overrides.css +16 -2
  26. package/apps/studio/client/tour/overlay.jsx +105 -17
  27. package/apps/studio/client/tour/usage-tour.js +23 -10
  28. package/apps/studio/commands/annotation-strokes-command.ts +1 -1
  29. package/apps/studio/commands/move-artboards-command.ts +1 -1
  30. package/apps/studio/comments-overlay.tsx +7 -5
  31. package/apps/studio/context-menu.tsx +4 -3
  32. package/apps/studio/contextual-toolbar.tsx +14 -0
  33. package/apps/studio/cursors-overlay.tsx +20 -20
  34. package/apps/studio/dist/client.bundle.js +3322 -602
  35. package/apps/studio/dist/comment-mount.js +95 -9
  36. package/apps/studio/dist/styles.css +2490 -167
  37. package/apps/studio/dom-selection.ts +115 -0
  38. package/apps/studio/export-dialog.tsx +3 -3
  39. package/apps/studio/history.ts +20 -3
  40. package/apps/studio/http.ts +124 -5
  41. package/apps/studio/input-router.tsx +7 -0
  42. package/apps/studio/inspect.ts +37 -8
  43. package/apps/studio/participants-chrome.tsx +1 -7
  44. package/apps/studio/server.ts +5 -2
  45. package/apps/studio/sync/agent.ts +231 -57
  46. package/apps/studio/sync/codec.ts +45 -0
  47. package/apps/studio/sync/cold-start.ts +158 -0
  48. package/apps/studio/sync/connection-state.ts +58 -2
  49. package/apps/studio/sync/index.ts +563 -221
  50. package/apps/studio/sync/journal.ts +190 -0
  51. package/apps/studio/sync/migrate-seed.ts +202 -44
  52. package/apps/studio/sync/projection.ts +22 -3
  53. package/apps/studio/sync/status.ts +15 -4
  54. package/apps/studio/test/activity.test.ts +1 -7
  55. package/apps/studio/test/annotate-write.test.ts +184 -0
  56. package/apps/studio/test/annotations-align.test.ts +88 -0
  57. package/apps/studio/test/annotations-bindings.test.ts +124 -0
  58. package/apps/studio/test/annotations-groups.test.ts +231 -0
  59. package/apps/studio/test/annotations-snap.test.ts +79 -0
  60. package/apps/studio/test/canvas-edit.test.ts +181 -1
  61. package/apps/studio/test/canvas-origin-gate.test.ts +8 -0
  62. package/apps/studio/test/collab-bridge.test.ts +0 -2
  63. package/apps/studio/test/collab-room.test.ts +2 -7
  64. package/apps/studio/test/csp-canvas-shell.test.ts +5 -0
  65. package/apps/studio/test/csrf-write-guard.test.ts +52 -0
  66. package/apps/studio/test/figjam-v3-model.test.ts +342 -0
  67. package/apps/studio/test/fixtures/figjam-v3-groups-bindings.svg +1 -0
  68. package/apps/studio/test/shared-doc-migrate.test.ts +224 -14
  69. package/apps/studio/test/sync-agent.test.ts +272 -2
  70. package/apps/studio/test/sync-codec.test.ts +65 -0
  71. package/apps/studio/test/sync-cold-start.test.ts +244 -0
  72. package/apps/studio/test/sync-connection-state.test.ts +68 -0
  73. package/apps/studio/test/sync-hardening.test.ts +0 -8
  74. package/apps/studio/test/sync-hubs-config.test.ts +0 -1
  75. package/apps/studio/test/sync-incident-replay.test.ts +211 -0
  76. package/apps/studio/test/sync-journal.test.ts +176 -0
  77. package/apps/studio/test/sync-runtime.test.ts +360 -5
  78. package/apps/studio/test/sync-status.test.ts +66 -0
  79. package/apps/studio/test/use-annotation-resize.test.ts +159 -0
  80. package/apps/studio/test/use-artboard-drag.test.ts +0 -1
  81. package/apps/studio/test/use-collab.test.ts +0 -0
  82. package/apps/studio/test/use-tool-mode.test.tsx +5 -2
  83. package/apps/studio/tool-palette.tsx +12 -2
  84. package/apps/studio/undo-hud.tsx +0 -1
  85. package/apps/studio/use-agent-presence.tsx +4 -2
  86. package/apps/studio/use-annotation-resize.tsx +484 -54
  87. package/apps/studio/use-annotation-selection.tsx +16 -4
  88. package/apps/studio/use-canvas-activity.tsx +2 -2
  89. package/apps/studio/use-collab.tsx +20 -15
  90. package/apps/studio/use-selection-set.tsx +9 -0
  91. package/apps/studio/use-tool-mode.tsx +5 -1
  92. package/apps/studio/whats-new.json +135 -10
  93. package/apps/studio/whats-new.schema.json +18 -2
  94. package/cli/commands/design-link.test.mjs +84 -0
  95. package/cli/commands/design.mjs +2 -1
  96. package/cli/commands/design.test.mjs +5 -1
  97. package/cli/lib/design-link.mjs +51 -1
  98. package/package.json +8 -8
  99. package/plugins/design/templates/_shell.html +28 -4
@@ -23,11 +23,18 @@
23
23
  export type ProviderStatus = 'connected' | 'connecting' | 'disconnected';
24
24
  export type SyncState = 'online' | 'connecting' | 'offline' | 'offline-long';
25
25
 
26
+ /** DDR-102 — per-document sync state. `pending` until the first handshake
27
+ * settles; `connected` once synced/active; `auth-rejected` when the hub
28
+ * refused auth for this documentName (scope / invalid token / rate limit). */
29
+ export type DocSyncState = 'pending' | 'connected' | 'auth-rejected';
30
+
26
31
  export interface SyncStatusSnapshot {
27
32
  state: SyncState;
28
33
  /** Local edits made since the hub went unreachable (replayed on reconnect). */
29
34
  queuedOps: number;
30
- /** ms epoch of the last successful hub sync, or null if never synced. */
35
+ /** ms epoch of the last successful hub sync, or null if never synced.
36
+ * DDR-102: updated on REAL sync activity (noteSyncActivity), not just on
37
+ * offline→online transitions. */
31
38
  lastSyncAt: number | null;
32
39
  /** ms epoch the current offline streak began, or null when online. */
33
40
  offlineSince: number | null;
@@ -35,6 +42,11 @@ export interface SyncStatusSnapshot {
35
42
  flash: 'synced' | null;
36
43
  /** ms epoch this snapshot was produced. */
37
44
  updatedAt: number;
45
+ /** DDR-102 — per-doc rollup (additive; absent in pre-DDR-102 payloads). */
46
+ docs?: { synced: number; pending: number; rejected: number };
47
+ /** DDR-102 — slugs currently auth-rejected, capped at 20 (see docs.rejected
48
+ * for the true count). Treat as text, never HTML. */
49
+ rejectedSlugs?: string[];
38
50
  }
39
51
 
40
52
  type TimerHandle = ReturnType<typeof setTimeout>;
@@ -58,6 +70,11 @@ export interface ConnectionMonitor {
58
70
  noteProviderStatus(providerId: string, status: ProviderStatus): void;
59
71
  /** A local edit happened — counts toward queuedOps while not online. */
60
72
  noteLocalEdit(): void;
73
+ /** DDR-102 — record a document's sync state (pending/connected/auth-rejected). */
74
+ noteDocState(slug: string, state: DocSyncState): void;
75
+ /** DDR-102 — real sync activity for a slug (reconcile done, hub-pushed flush
76
+ * applied): bumps `lastSyncAt` to now. */
77
+ noteSyncActivity(slug: string): void;
61
78
  /** Current snapshot (defensive copy). */
62
79
  snapshot(): SyncStatusSnapshot;
63
80
  /** Tear down timers. */
@@ -67,6 +84,8 @@ export interface ConnectionMonitor {
67
84
  const DEFAULT_GRACE_MS = 30_000;
68
85
  const DEFAULT_ESCALATE_MS = 24 * 60 * 60 * 1000;
69
86
  const DEFAULT_FLASH_MS = 3_000;
87
+ /** Cap on rejectedSlugs in the snapshot (the rollup carries the true count). */
88
+ export const MAX_REJECTED_SLUGS = 20;
70
89
 
71
90
  export function createConnectionMonitor(opts: ConnectionMonitorOptions = {}): ConnectionMonitor {
72
91
  const graceMs = opts.graceMs ?? DEFAULT_GRACE_MS;
@@ -78,6 +97,8 @@ export function createConnectionMonitor(opts: ConnectionMonitorOptions = {}): Co
78
97
  const onChange = opts.onChange;
79
98
 
80
99
  const providerStatuses = new Map<string, ProviderStatus>();
100
+ // DDR-102 — per-doc states (pending/connected/auth-rejected).
101
+ const docStates = new Map<string, DocSyncState>();
81
102
 
82
103
  let state: SyncState = 'online';
83
104
  let queuedOps = 0;
@@ -91,7 +112,25 @@ export function createConnectionMonitor(opts: ConnectionMonitorOptions = {}): Co
91
112
  let stopped = false;
92
113
 
93
114
  function snapshot(): SyncStatusSnapshot {
94
- return { state, queuedOps, lastSyncAt, offlineSince, flash, updatedAt: now() };
115
+ const docs = { synced: 0, pending: 0, rejected: 0 };
116
+ const rejectedSlugs: string[] = [];
117
+ for (const [slug, st] of docStates) {
118
+ if (st === 'connected') docs.synced++;
119
+ else if (st === 'auth-rejected') {
120
+ docs.rejected++;
121
+ if (rejectedSlugs.length < MAX_REJECTED_SLUGS) rejectedSlugs.push(slug);
122
+ } else docs.pending++;
123
+ }
124
+ return {
125
+ state,
126
+ queuedOps,
127
+ lastSyncAt,
128
+ offlineSince,
129
+ flash,
130
+ updatedAt: now(),
131
+ docs,
132
+ rejectedSlugs,
133
+ };
95
134
  }
96
135
 
97
136
  function emit(): void {
@@ -189,6 +228,23 @@ export function createConnectionMonitor(opts: ConnectionMonitorOptions = {}): Co
189
228
  emit();
190
229
  },
191
230
 
231
+ noteDocState(slug, docState) {
232
+ if (stopped) return;
233
+ if (docStates.get(slug) === docState) return;
234
+ docStates.set(slug, docState);
235
+ emit();
236
+ },
237
+
238
+ noteSyncActivity(slug) {
239
+ if (stopped) return;
240
+ lastSyncAt = now();
241
+ // Real sync traffic for a pending doc proves its handshake settled.
242
+ // An auth-rejected doc stays rejected (activity for it can't happen,
243
+ // but be defensive against ordering races).
244
+ if (docStates.get(slug) === 'pending') docStates.set(slug, 'connected');
245
+ emit();
246
+ },
247
+
192
248
  snapshot,
193
249
 
194
250
  stop() {