@1agh/maude 0.23.0 → 0.24.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 +34 -1
- package/cli/bin/maude.mjs +3 -0
- package/cli/commands/cache.mjs +181 -0
- package/cli/commands/cache.test.mjs +166 -0
- package/cli/commands/design-link.test.mjs +32 -2
- package/cli/commands/design.mjs +95 -4
- package/cli/commands/design.test.mjs +56 -0
- package/cli/commands/help.mjs +34 -0
- package/cli/commands/hub.mjs +255 -30
- package/cli/commands/hub.test.mjs +126 -2
- package/cli/commands/init.mjs +3 -0
- package/cli/commands/preflight.mjs +11 -0
- package/cli/commands/preflight.test.mjs +46 -0
- package/cli/commands/scenario-report.mjs +45 -0
- package/cli/lib/cache.mjs +407 -0
- package/cli/lib/cache.test.mjs +303 -0
- package/cli/lib/design-link.mjs +74 -10
- package/cli/lib/flow-design-integration.test.mjs +165 -0
- package/cli/lib/gitignore-block.mjs +90 -0
- package/cli/lib/gitignore-block.test.mjs +123 -0
- package/cli/lib/plugin-cli-reachability.test.mjs +56 -0
- package/cli/lib/preflight.mjs +41 -10
- package/package.json +8 -8
- package/plugins/design/dev-server/ai-banner.tsx +2 -2
- package/plugins/design/dev-server/annotations-context-toolbar.tsx +349 -112
- package/plugins/design/dev-server/annotations-layer.tsx +906 -137
- package/plugins/design/dev-server/api.ts +109 -4
- package/plugins/design/dev-server/bin/preflight.sh +21 -10
- package/plugins/design/dev-server/bin/prep.sh +211 -0
- package/plugins/design/dev-server/bin/scenario-report.mjs +209 -0
- package/plugins/design/dev-server/bin/screenshot.sh +18 -1
- package/plugins/design/dev-server/bin/smoke.sh +94 -11
- package/plugins/design/dev-server/canvas-cursors.ts +125 -0
- package/plugins/design/dev-server/canvas-icons.tsx +130 -0
- package/plugins/design/dev-server/canvas-lib.tsx +25 -21
- package/plugins/design/dev-server/canvas-meta.schema.json +20 -0
- package/plugins/design/dev-server/canvas-shell.tsx +333 -19
- package/plugins/design/dev-server/client/app.jsx +155 -7
- package/plugins/design/dev-server/client/styles/3-shell.css +10 -0
- package/plugins/design/dev-server/collab/index.ts +87 -9
- package/plugins/design/dev-server/collab/persistence.ts +34 -3
- package/plugins/design/dev-server/collab/registry.ts +80 -2
- package/plugins/design/dev-server/collab/room.ts +21 -8
- package/plugins/design/dev-server/context-menu.tsx +167 -23
- package/plugins/design/dev-server/context.ts +24 -0
- package/plugins/design/dev-server/contextual-toolbar.tsx +7 -7
- package/plugins/design/dev-server/dist/client.bundle.js +126 -13
- package/plugins/design/dev-server/dist/comment-mount.js +78 -11
- package/plugins/design/dev-server/dist/styles.css +16 -0
- package/plugins/design/dev-server/equal-spacing-handles.tsx +1 -1
- package/plugins/design/dev-server/export-dialog.tsx +19 -17
- package/plugins/design/dev-server/fs-watch.ts +1 -0
- package/plugins/design/dev-server/http.ts +260 -20
- package/plugins/design/dev-server/input-router.tsx +26 -3
- package/plugins/design/dev-server/participants-chrome.tsx +10 -10
- package/plugins/design/dev-server/server.ts +123 -1
- package/plugins/design/dev-server/sync/agent.ts +95 -0
- package/plugins/design/dev-server/sync/codec.ts +155 -0
- package/plugins/design/dev-server/sync/connection-state.ts +203 -0
- package/plugins/design/dev-server/sync/index.ts +479 -35
- package/plugins/design/dev-server/sync/materialize.ts +62 -0
- package/plugins/design/dev-server/sync/migrate-seed.ts +163 -0
- package/plugins/design/dev-server/sync/origins.ts +57 -0
- package/plugins/design/dev-server/sync/projection.ts +368 -0
- package/plugins/design/dev-server/sync/status.ts +115 -0
- package/plugins/design/dev-server/sync/untrusted.ts +153 -0
- package/plugins/design/dev-server/test/_helpers.ts +6 -2
- package/plugins/design/dev-server/test/annotations-layer.test.ts +231 -0
- package/plugins/design/dev-server/test/annotations-roundtrip.test.ts +276 -0
- package/plugins/design/dev-server/test/canvas-cursors.test.ts +73 -0
- package/plugins/design/dev-server/test/canvas-origin-gate.test.ts +76 -0
- package/plugins/design/dev-server/test/collab-reseed-guard.test.ts +78 -0
- package/plugins/design/dev-server/test/collab-room.test.ts +21 -10
- package/plugins/design/dev-server/test/csp-canvas-shell.test.ts +46 -0
- package/plugins/design/dev-server/test/fixtures/phase-20-annotations.svg +1 -0
- package/plugins/design/dev-server/test/input-router.test.ts +21 -0
- package/plugins/design/dev-server/test/sanitize-annotation-svg.test.ts +100 -0
- package/plugins/design/dev-server/test/shared-doc-convergence.test.ts +265 -0
- package/plugins/design/dev-server/test/shared-doc-foundation.test.ts +63 -0
- package/plugins/design/dev-server/test/shared-doc-migrate.test.ts +160 -0
- package/plugins/design/dev-server/test/shared-doc-projection.test.ts +238 -0
- package/plugins/design/dev-server/test/sync-connection-state.test.ts +146 -0
- package/plugins/design/dev-server/test/sync-meta-codec.test.ts +123 -0
- package/plugins/design/dev-server/test/sync-runtime.test.ts +531 -4
- package/plugins/design/dev-server/test/sync-status.test.ts +80 -0
- package/plugins/design/dev-server/test/sync-untrusted.test.ts +104 -0
- package/plugins/design/dev-server/test/use-tool-mode.test.tsx +38 -10
- package/plugins/design/dev-server/tool-palette.tsx +18 -16
- package/plugins/design/dev-server/undo-hud.tsx +4 -4
- package/plugins/design/dev-server/undo-stack.ts +20 -4
- package/plugins/design/dev-server/use-annotation-resize.tsx +16 -5
- package/plugins/design/dev-server/use-tool-mode.tsx +15 -12
- package/plugins/design/dev-server/ws.ts +40 -1
- package/plugins/design/templates/_shell.html +49 -1
- package/plugins/design/templates/canvas.tsx.template +13 -0
- package/plugins/design/templates/design-system-inspiration/SUB-AGENT-PROMPTS.md +14 -7
- package/plugins/flow/.claude-plugin/config.schema.json +5 -0
- package/plugins/flow/templates/ai-skeleton/README.md +1 -1
- package/plugins/flow/templates/ai-skeleton/gitignore +10 -0
- package/plugins/flow/templates/ai-skeleton/scenarios/README.md +3 -1
- package/plugins/flow/templates/ai-skeleton/workflows.config.json +2 -1
|
@@ -73,6 +73,14 @@ export function createRoom(slug: string, callbacks: RoomCallbacks): Room {
|
|
|
73
73
|
const awareness = new Awareness(doc);
|
|
74
74
|
|
|
75
75
|
const conns = new Map<string, RoomConn>();
|
|
76
|
+
// clientID → owning conn.id, learned from the origin of each awareness update.
|
|
77
|
+
// Server-authoritative: we do NOT trust a client-supplied `__connId` (awareness
|
|
78
|
+
// is attacker-influenceable through a semi-trusted hub — DDR-054). On disconnect
|
|
79
|
+
// we remove exactly the clientIDs this conn published so other peers drop the
|
|
80
|
+
// avatar immediately, instead of waiting out the ~30s awareness timeout (which
|
|
81
|
+
// let phantom peers pile up on rapid reconnects — the cross-origin repro that
|
|
82
|
+
// surfaced this latent bug).
|
|
83
|
+
const connByClient = new Map<number, string>();
|
|
76
84
|
let dirty = false;
|
|
77
85
|
let flushTimer: ReturnType<typeof setTimeout> | null = null;
|
|
78
86
|
let destroyed = false;
|
|
@@ -138,6 +146,13 @@ export function createRoom(slug: string, callbacks: RoomCallbacks): Room {
|
|
|
138
146
|
if (changed.length === 0) return;
|
|
139
147
|
const except =
|
|
140
148
|
origin && typeof origin === 'object' && 'id' in origin ? (origin as RoomConn) : undefined;
|
|
149
|
+
// Learn which clientIDs belong to which conn from the update origin, so
|
|
150
|
+
// disconnect() can evict them precisely.
|
|
151
|
+
if (except) {
|
|
152
|
+
for (const id of added) connByClient.set(id, except.id);
|
|
153
|
+
for (const id of updated) connByClient.set(id, except.id);
|
|
154
|
+
for (const id of removed) connByClient.delete(id);
|
|
155
|
+
}
|
|
141
156
|
broadcast(encodeAwarenessFrame(awareness, changed), except);
|
|
142
157
|
}
|
|
143
158
|
);
|
|
@@ -161,16 +176,14 @@ export function createRoom(slug: string, callbacks: RoomCallbacks): Room {
|
|
|
161
176
|
|
|
162
177
|
function disconnect(conn: RoomConn): void {
|
|
163
178
|
conns.delete(conn.id);
|
|
164
|
-
//
|
|
165
|
-
// cursor renderers
|
|
166
|
-
|
|
179
|
+
// Remove the awareness states this conn published (tracked by update origin
|
|
180
|
+
// in connByClient) so other peers' cursor renderers drop the avatar now,
|
|
181
|
+
// not after the ~30s awareness timeout.
|
|
167
182
|
const stale: number[] = [];
|
|
168
|
-
for (const clientId of
|
|
169
|
-
|
|
170
|
-
// matching conn.id; remove states whose owning conn just left.
|
|
171
|
-
const state = states.get(clientId) as { __connId?: string } | undefined;
|
|
172
|
-
if (state && state.__connId === conn.id) stale.push(clientId);
|
|
183
|
+
for (const [clientId, connId] of connByClient) {
|
|
184
|
+
if (connId === conn.id) stale.push(clientId);
|
|
173
185
|
}
|
|
186
|
+
for (const clientId of stale) connByClient.delete(clientId);
|
|
174
187
|
if (stale.length) removeAwarenessStates(awareness, stale, conn);
|
|
175
188
|
}
|
|
176
189
|
|
|
@@ -55,6 +55,15 @@ export interface MenuItem {
|
|
|
55
55
|
shortcut?: string;
|
|
56
56
|
destructive?: boolean;
|
|
57
57
|
disabled?: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Optional nested flyout (e.g. `Theme ▸ DS default / Light / Dark / Follow
|
|
60
|
+
* chrome`). When present the row opens a submenu on hover / ArrowRight /
|
|
61
|
+
* click and `onSelect` on THIS item is not invoked — only the chosen leaf's
|
|
62
|
+
* `onSelect` fires. A disabled leaf carries `disabledHint` for its title.
|
|
63
|
+
*/
|
|
64
|
+
submenu?: MenuItem[];
|
|
65
|
+
/** Hover/title hint shown when the item is `disabled` (a11y affordance). */
|
|
66
|
+
disabledHint?: string;
|
|
58
67
|
onSelect: (target: ContextTarget) => void;
|
|
59
68
|
}
|
|
60
69
|
|
|
@@ -158,20 +167,20 @@ const MENU_CSS = `
|
|
|
158
167
|
.dc-context-menu {
|
|
159
168
|
position: fixed;
|
|
160
169
|
z-index: 7;
|
|
161
|
-
background: var(--
|
|
162
|
-
border: 1px solid var(--
|
|
170
|
+
background: var(--maude-chrome-bg-0, #fff);
|
|
171
|
+
border: 1px solid var(--maude-chrome-fg-0, #1c1917);
|
|
163
172
|
border-radius: 8px;
|
|
164
|
-
box-shadow: 0 6px 24px color-mix(in oklab,
|
|
173
|
+
box-shadow: 0 6px 24px var(--maude-chrome-shadow, color-mix(in oklab, #1c1917 10%, transparent));
|
|
165
174
|
padding: 4px;
|
|
166
175
|
min-width: 220px;
|
|
167
|
-
font-family: var(--
|
|
176
|
+
font-family: var(--maude-chrome-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
|
|
168
177
|
font-size: 12px;
|
|
169
|
-
color: var(--
|
|
178
|
+
color: var(--maude-chrome-fg-0, rgba(20,15,10,0.92));
|
|
170
179
|
user-select: none;
|
|
171
180
|
}
|
|
172
181
|
.dc-context-menu .dc-menu-sep {
|
|
173
182
|
height: 1px;
|
|
174
|
-
background: var(--border
|
|
183
|
+
background: var(--maude-chrome-border, rgba(0,0,0,0.08));
|
|
175
184
|
margin: 4px -4px;
|
|
176
185
|
}
|
|
177
186
|
.dc-context-menu .dc-menu-item {
|
|
@@ -191,7 +200,7 @@ const MENU_CSS = `
|
|
|
191
200
|
}
|
|
192
201
|
.dc-context-menu .dc-menu-item:hover,
|
|
193
202
|
.dc-context-menu .dc-menu-item:focus-visible {
|
|
194
|
-
background:
|
|
203
|
+
background: color-mix(in oklab, var(--maude-chrome-fg-0, #1c1917) 8%, transparent);
|
|
195
204
|
outline: none;
|
|
196
205
|
}
|
|
197
206
|
.dc-context-menu .dc-menu-item[disabled] {
|
|
@@ -204,11 +213,28 @@ const MENU_CSS = `
|
|
|
204
213
|
color: var(--accent-fg, #fff);
|
|
205
214
|
}
|
|
206
215
|
.dc-context-menu .dc-menu-shortcut {
|
|
207
|
-
color: var(--fg-
|
|
216
|
+
color: var(--maude-chrome-fg-1, rgba(40,30,20,0.55));
|
|
208
217
|
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
209
218
|
font-size: 10px;
|
|
210
219
|
font-variant-numeric: tabular-nums;
|
|
211
220
|
}
|
|
221
|
+
/* Submenu flyout (Theme ▸ …). Anchored to the right of its parent row; flips
|
|
222
|
+
left near the viewport edge via .is-flip. Reuses .dc-menu-item styling. */
|
|
223
|
+
.dc-context-menu .dc-menu-sub { position: relative; }
|
|
224
|
+
.dc-context-menu .dc-menu-caret { color: var(--maude-chrome-fg-1, rgba(40,30,20,0.55)); font-size: 11px; }
|
|
225
|
+
.dc-context-menu .dc-menu-flyout {
|
|
226
|
+
position: absolute;
|
|
227
|
+
top: -5px;
|
|
228
|
+
left: calc(100% + 3px);
|
|
229
|
+
min-width: 196px;
|
|
230
|
+
padding: 4px;
|
|
231
|
+
background: var(--maude-chrome-bg-0, #fff);
|
|
232
|
+
border: 1px solid var(--maude-chrome-fg-0, #1c1917);
|
|
233
|
+
border-radius: 8px;
|
|
234
|
+
box-shadow: 0 6px 24px var(--maude-chrome-shadow, color-mix(in oklab, #1c1917 10%, transparent));
|
|
235
|
+
z-index: 8;
|
|
236
|
+
}
|
|
237
|
+
.dc-context-menu .dc-menu-flyout.is-flip { left: auto; right: calc(100% + 3px); }
|
|
212
238
|
`.trim();
|
|
213
239
|
|
|
214
240
|
function ensureMenuStyles(): void {
|
|
@@ -346,21 +372,7 @@ function ContextMenuView({
|
|
|
346
372
|
<div key={sectionKey} role="group">
|
|
347
373
|
{si > 0 ? <div className="dc-menu-sep" aria-hidden="true" /> : null}
|
|
348
374
|
{section.map((item) => (
|
|
349
|
-
<
|
|
350
|
-
key={item.id}
|
|
351
|
-
type="button"
|
|
352
|
-
role="menuitem"
|
|
353
|
-
disabled={item.disabled}
|
|
354
|
-
className={`dc-menu-item${item.destructive ? ' is-destructive' : ''}`}
|
|
355
|
-
onClick={() => {
|
|
356
|
-
if (item.disabled) return;
|
|
357
|
-
item.onSelect(target);
|
|
358
|
-
onClose();
|
|
359
|
-
}}
|
|
360
|
-
>
|
|
361
|
-
<span>{item.label}</span>
|
|
362
|
-
{item.shortcut ? <span className="dc-menu-shortcut">{item.shortcut}</span> : null}
|
|
363
|
-
</button>
|
|
375
|
+
<MenuItemRow key={item.id} item={item} target={target} onClose={onClose} />
|
|
364
376
|
))}
|
|
365
377
|
</div>
|
|
366
378
|
);
|
|
@@ -368,3 +380,135 @@ function ContextMenuView({
|
|
|
368
380
|
</div>
|
|
369
381
|
);
|
|
370
382
|
}
|
|
383
|
+
|
|
384
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
385
|
+
// MenuItemRow — a single menu row. Plain rows render a button; rows with a
|
|
386
|
+
// `submenu` render a flyout (opens on hover / ArrowRight / click). Additive:
|
|
387
|
+
// existing flat registries (no `submenu`) take the plain-button path unchanged.
|
|
388
|
+
|
|
389
|
+
function MenuItemRow({
|
|
390
|
+
item,
|
|
391
|
+
target,
|
|
392
|
+
onClose,
|
|
393
|
+
}: {
|
|
394
|
+
item: MenuItem;
|
|
395
|
+
target: ContextTarget;
|
|
396
|
+
onClose: () => void;
|
|
397
|
+
}) {
|
|
398
|
+
const [subOpen, setSubOpen] = useState(false);
|
|
399
|
+
const [flip, setFlip] = useState(false);
|
|
400
|
+
const btnRef = useRef<HTMLButtonElement>(null);
|
|
401
|
+
const flyoutRef = useRef<HTMLDivElement>(null);
|
|
402
|
+
const closeTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
403
|
+
|
|
404
|
+
if (!item.submenu || item.submenu.length === 0) {
|
|
405
|
+
return (
|
|
406
|
+
<button
|
|
407
|
+
type="button"
|
|
408
|
+
role="menuitem"
|
|
409
|
+
disabled={item.disabled}
|
|
410
|
+
title={item.disabled ? item.disabledHint : undefined}
|
|
411
|
+
className={`dc-menu-item${item.destructive ? ' is-destructive' : ''}`}
|
|
412
|
+
onClick={() => {
|
|
413
|
+
if (item.disabled) return;
|
|
414
|
+
item.onSelect(target);
|
|
415
|
+
onClose();
|
|
416
|
+
}}
|
|
417
|
+
>
|
|
418
|
+
<span>{item.label}</span>
|
|
419
|
+
{item.shortcut ? <span className="dc-menu-shortcut">{item.shortcut}</span> : null}
|
|
420
|
+
</button>
|
|
421
|
+
);
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
const cancelClose = () => {
|
|
425
|
+
if (closeTimer.current) {
|
|
426
|
+
clearTimeout(closeTimer.current);
|
|
427
|
+
closeTimer.current = null;
|
|
428
|
+
}
|
|
429
|
+
};
|
|
430
|
+
const open = (focusFirst = false) => {
|
|
431
|
+
cancelClose();
|
|
432
|
+
const r = btnRef.current?.getBoundingClientRect();
|
|
433
|
+
if (r && typeof window !== 'undefined') setFlip(r.right + 200 > window.innerWidth);
|
|
434
|
+
setSubOpen(true);
|
|
435
|
+
if (focusFirst) {
|
|
436
|
+
setTimeout(() => {
|
|
437
|
+
flyoutRef.current
|
|
438
|
+
?.querySelector<HTMLButtonElement>('button.dc-menu-item:not([disabled])')
|
|
439
|
+
?.focus();
|
|
440
|
+
}, 0);
|
|
441
|
+
}
|
|
442
|
+
};
|
|
443
|
+
const scheduleClose = () => {
|
|
444
|
+
cancelClose();
|
|
445
|
+
closeTimer.current = setTimeout(() => setSubOpen(false), 140);
|
|
446
|
+
};
|
|
447
|
+
|
|
448
|
+
return (
|
|
449
|
+
<div className="dc-menu-sub" onMouseEnter={() => open()} onMouseLeave={scheduleClose}>
|
|
450
|
+
<button
|
|
451
|
+
ref={btnRef}
|
|
452
|
+
type="button"
|
|
453
|
+
role="menuitem"
|
|
454
|
+
aria-haspopup="menu"
|
|
455
|
+
aria-expanded={subOpen}
|
|
456
|
+
disabled={item.disabled}
|
|
457
|
+
className="dc-menu-item"
|
|
458
|
+
onClick={() => (subOpen ? setSubOpen(false) : open())}
|
|
459
|
+
onKeyDown={(e) => {
|
|
460
|
+
if (e.key === 'ArrowRight' || e.key === 'Enter' || e.key === ' ') {
|
|
461
|
+
e.preventDefault();
|
|
462
|
+
open(true);
|
|
463
|
+
} else if (e.key === 'ArrowLeft' || e.key === 'Escape') {
|
|
464
|
+
if (subOpen) {
|
|
465
|
+
e.stopPropagation();
|
|
466
|
+
setSubOpen(false);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
}}
|
|
470
|
+
>
|
|
471
|
+
<span>{item.label}</span>
|
|
472
|
+
<span className="dc-menu-caret" aria-hidden="true">
|
|
473
|
+
▸
|
|
474
|
+
</span>
|
|
475
|
+
</button>
|
|
476
|
+
{subOpen ? (
|
|
477
|
+
<div
|
|
478
|
+
ref={flyoutRef}
|
|
479
|
+
className={`dc-menu-flyout${flip ? ' is-flip' : ''}`}
|
|
480
|
+
role="menu"
|
|
481
|
+
onMouseEnter={cancelClose}
|
|
482
|
+
onMouseLeave={scheduleClose}
|
|
483
|
+
>
|
|
484
|
+
{item.submenu.map((sub) => (
|
|
485
|
+
<button
|
|
486
|
+
key={sub.id}
|
|
487
|
+
type="button"
|
|
488
|
+
role="menuitem"
|
|
489
|
+
disabled={sub.disabled}
|
|
490
|
+
title={sub.disabled ? sub.disabledHint : undefined}
|
|
491
|
+
className={`dc-menu-item${sub.destructive ? ' is-destructive' : ''}`}
|
|
492
|
+
onClick={() => {
|
|
493
|
+
if (sub.disabled) return;
|
|
494
|
+
sub.onSelect(target);
|
|
495
|
+
onClose();
|
|
496
|
+
}}
|
|
497
|
+
onKeyDown={(e) => {
|
|
498
|
+
if (e.key === 'ArrowLeft' || e.key === 'Escape') {
|
|
499
|
+
e.preventDefault();
|
|
500
|
+
e.stopPropagation();
|
|
501
|
+
setSubOpen(false);
|
|
502
|
+
btnRef.current?.focus();
|
|
503
|
+
}
|
|
504
|
+
}}
|
|
505
|
+
>
|
|
506
|
+
<span>{sub.label}</span>
|
|
507
|
+
{sub.shortcut ? <span className="dc-menu-shortcut">{sub.shortcut}</span> : null}
|
|
508
|
+
</button>
|
|
509
|
+
))}
|
|
510
|
+
</div>
|
|
511
|
+
) : null}
|
|
512
|
+
</div>
|
|
513
|
+
);
|
|
514
|
+
}
|
|
@@ -117,6 +117,30 @@ export interface Context {
|
|
|
117
117
|
projectLabel: string;
|
|
118
118
|
paths: Paths;
|
|
119
119
|
bus: Bus;
|
|
120
|
+
/**
|
|
121
|
+
* T2 (9.1-A) — origin of the segregated canvas-content server (e.g.
|
|
122
|
+
* `http://localhost:51234`), set by server.ts once the second listener binds.
|
|
123
|
+
* The client reads it via /_config to build absolute, cross-origin iframe
|
|
124
|
+
* URLs. Undefined in tests / before the canvas listener boots.
|
|
125
|
+
*/
|
|
126
|
+
canvasOrigin?: string;
|
|
127
|
+
/**
|
|
128
|
+
* T2 (9.1-A) — origin of the MAIN dev-server listener (e.g.
|
|
129
|
+
* `http://localhost:4399`), set by server.ts once the primary listener binds.
|
|
130
|
+
* Used by `cspForCanvasShell` to allowlist the legit embedder in the canvas
|
|
131
|
+
* origin's `frame-ancestors`. Undefined in tests / before boot.
|
|
132
|
+
*/
|
|
133
|
+
mainOrigin?: string;
|
|
134
|
+
/**
|
|
135
|
+
* Phase 9.2 (DDR-064) — `MAUDE_SHARED_DOC` feature flag. When true, the
|
|
136
|
+
* collab room's Y.Doc becomes the SINGLE shared doc per canvas: the
|
|
137
|
+
* hub-facing HocuspocusProvider attaches to it directly (no second doc, no
|
|
138
|
+
* disk-mediated reconcile). Default `false`/undefined = the proven two-doc
|
|
139
|
+
* path = zero regression. Set by server.ts from the env; tests set it
|
|
140
|
+
* directly on the Context they construct. Threaded through Phase A; the flag
|
|
141
|
+
* gates behavior starting in Phase B.
|
|
142
|
+
*/
|
|
143
|
+
sharedDoc?: boolean;
|
|
120
144
|
}
|
|
121
145
|
|
|
122
146
|
function resolveRepoRoot(): string {
|
|
@@ -41,14 +41,14 @@ const CTX_TOOLBAR_CSS = `
|
|
|
41
41
|
align-items: stretch;
|
|
42
42
|
gap: 2px;
|
|
43
43
|
padding: 4px;
|
|
44
|
-
background: var(--
|
|
45
|
-
border: 1px solid var(--
|
|
44
|
+
background: var(--maude-chrome-bg-0, #ffffff);
|
|
45
|
+
border: 1px solid var(--maude-chrome-fg-0, #1c1917);
|
|
46
46
|
border-radius: 8px;
|
|
47
|
-
box-shadow: 0 6px 24px color-mix(in oklab,
|
|
48
|
-
font-family: var(--
|
|
47
|
+
box-shadow: 0 6px 24px var(--maude-chrome-shadow, color-mix(in oklab, #1c1917 10%, transparent));
|
|
48
|
+
font-family: var(--maude-chrome-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
|
|
49
49
|
font-size: 11px;
|
|
50
50
|
letter-spacing: 0.02em;
|
|
51
|
-
color: var(--
|
|
51
|
+
color: var(--maude-chrome-fg-0, #1a1a1a);
|
|
52
52
|
user-select: none;
|
|
53
53
|
opacity: 0;
|
|
54
54
|
transition: opacity 100ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
@@ -72,8 +72,8 @@ const CTX_TOOLBAR_CSS = `
|
|
|
72
72
|
}
|
|
73
73
|
.dc-elem-ctx-tb .dc-elem-ctx-count {
|
|
74
74
|
padding: 4px 8px 4px 10px;
|
|
75
|
-
color: var(--fg-1, rgba(40,30,20,0.7));
|
|
76
|
-
border-right: 1px solid var(--
|
|
75
|
+
color: var(--maude-chrome-fg-1, rgba(40,30,20,0.7));
|
|
76
|
+
border-right: 1px solid var(--maude-chrome-border, rgba(0,0,0,0.08));
|
|
77
77
|
margin-right: 2px;
|
|
78
78
|
font-variant-numeric: tabular-nums;
|
|
79
79
|
}
|