@1agh/maude 0.23.0 → 0.25.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 (127) hide show
  1. package/README.md +34 -1
  2. package/cli/bin/maude.mjs +3 -0
  3. package/cli/commands/cache.mjs +181 -0
  4. package/cli/commands/cache.test.mjs +166 -0
  5. package/cli/commands/design-link.test.mjs +32 -2
  6. package/cli/commands/design.mjs +95 -4
  7. package/cli/commands/design.test.mjs +56 -0
  8. package/cli/commands/help.mjs +34 -0
  9. package/cli/commands/hub.mjs +255 -30
  10. package/cli/commands/hub.test.mjs +126 -2
  11. package/cli/commands/init.mjs +3 -0
  12. package/cli/commands/preflight.mjs +11 -0
  13. package/cli/commands/preflight.test.mjs +46 -0
  14. package/cli/commands/scenario-report.mjs +45 -0
  15. package/cli/lib/cache.mjs +407 -0
  16. package/cli/lib/cache.test.mjs +303 -0
  17. package/cli/lib/design-link.mjs +74 -10
  18. package/cli/lib/flow-design-integration.test.mjs +165 -0
  19. package/cli/lib/gitignore-block.mjs +90 -0
  20. package/cli/lib/gitignore-block.test.mjs +123 -0
  21. package/cli/lib/plugin-cli-reachability.test.mjs +56 -0
  22. package/cli/lib/preflight.mjs +41 -10
  23. package/package.json +8 -8
  24. package/plugins/design/dependencies.json +30 -2
  25. package/plugins/design/dev-server/ai-banner.tsx +2 -2
  26. package/plugins/design/dev-server/annotations-context-toolbar.tsx +763 -123
  27. package/plugins/design/dev-server/annotations-layer.tsx +1624 -208
  28. package/plugins/design/dev-server/api.ts +123 -4
  29. package/plugins/design/dev-server/bin/_enumerate-artboards-playwright.mjs +2 -2
  30. package/plugins/design/dev-server/bin/_html-playwright.mjs +2 -2
  31. package/plugins/design/dev-server/bin/_pdf-playwright.mjs +25 -8
  32. package/plugins/design/dev-server/bin/_png-playwright.mjs +20 -20
  33. package/plugins/design/dev-server/bin/_pptx-playwright.mjs +2 -2
  34. package/plugins/design/dev-server/bin/_pw-launch.mjs +61 -0
  35. package/plugins/design/dev-server/bin/_screenshot-playwright.mjs +2 -2
  36. package/plugins/design/dev-server/bin/_svg-playwright.mjs +125 -19
  37. package/plugins/design/dev-server/bin/preflight.sh +21 -10
  38. package/plugins/design/dev-server/bin/prep.sh +211 -0
  39. package/plugins/design/dev-server/bin/scenario-report.mjs +209 -0
  40. package/plugins/design/dev-server/bin/screenshot.sh +18 -1
  41. package/plugins/design/dev-server/bin/smoke.sh +208 -23
  42. package/plugins/design/dev-server/canvas-arrowheads.ts +220 -0
  43. package/plugins/design/dev-server/canvas-comment-mount.tsx +8 -24
  44. package/plugins/design/dev-server/canvas-cursors.ts +173 -0
  45. package/plugins/design/dev-server/canvas-icons.tsx +299 -0
  46. package/plugins/design/dev-server/canvas-lib.tsx +25 -21
  47. package/plugins/design/dev-server/canvas-meta.schema.json +20 -0
  48. package/plugins/design/dev-server/canvas-shell.tsx +404 -66
  49. package/plugins/design/dev-server/client/app.jsx +1231 -416
  50. package/plugins/design/dev-server/client/styles/3-shell.css +10 -0
  51. package/plugins/design/dev-server/collab/index.ts +87 -9
  52. package/plugins/design/dev-server/collab/persistence.ts +34 -3
  53. package/plugins/design/dev-server/collab/registry.ts +80 -2
  54. package/plugins/design/dev-server/collab/room.ts +21 -8
  55. package/plugins/design/dev-server/context-menu.tsx +167 -23
  56. package/plugins/design/dev-server/context.ts +24 -0
  57. package/plugins/design/dev-server/contextual-toolbar.tsx +7 -7
  58. package/plugins/design/dev-server/dist/client.bundle.js +364 -29
  59. package/plugins/design/dev-server/dist/comment-mount.js +78 -33
  60. package/plugins/design/dev-server/dist/styles.css +16 -0
  61. package/plugins/design/dev-server/equal-spacing-handles.tsx +1 -1
  62. package/plugins/design/dev-server/export-dialog.tsx +208 -18
  63. package/plugins/design/dev-server/exporters/html.ts +4 -1
  64. package/plugins/design/dev-server/exporters/index.ts +4 -1
  65. package/plugins/design/dev-server/exporters/pdf.ts +7 -1
  66. package/plugins/design/dev-server/exporters/png.ts +21 -2
  67. package/plugins/design/dev-server/exporters/pptx.ts +330 -201
  68. package/plugins/design/dev-server/exporters/scope.ts +107 -11
  69. package/plugins/design/dev-server/exporters/svg.ts +4 -1
  70. package/plugins/design/dev-server/fs-watch.ts +1 -0
  71. package/plugins/design/dev-server/http.ts +299 -28
  72. package/plugins/design/dev-server/input-router.tsx +35 -5
  73. package/plugins/design/dev-server/participants-chrome.tsx +10 -10
  74. package/plugins/design/dev-server/server.ts +123 -1
  75. package/plugins/design/dev-server/sync/agent.ts +95 -0
  76. package/plugins/design/dev-server/sync/codec.ts +155 -0
  77. package/plugins/design/dev-server/sync/connection-state.ts +203 -0
  78. package/plugins/design/dev-server/sync/index.ts +479 -35
  79. package/plugins/design/dev-server/sync/materialize.ts +62 -0
  80. package/plugins/design/dev-server/sync/migrate-seed.ts +163 -0
  81. package/plugins/design/dev-server/sync/origins.ts +57 -0
  82. package/plugins/design/dev-server/sync/projection.ts +368 -0
  83. package/plugins/design/dev-server/sync/status.ts +115 -0
  84. package/plugins/design/dev-server/sync/untrusted.ts +153 -0
  85. package/plugins/design/dev-server/test/_helpers.ts +6 -2
  86. package/plugins/design/dev-server/test/annotations-draw-modifiers.test.ts +206 -0
  87. package/plugins/design/dev-server/test/annotations-layer.test.ts +311 -0
  88. package/plugins/design/dev-server/test/annotations-roundtrip.test.ts +519 -0
  89. package/plugins/design/dev-server/test/canvas-cursors.test.ts +162 -0
  90. package/plugins/design/dev-server/test/canvas-origin-gate.test.ts +76 -0
  91. package/plugins/design/dev-server/test/canvas-route.test.ts +4 -1
  92. package/plugins/design/dev-server/test/collab-reseed-guard.test.ts +78 -0
  93. package/plugins/design/dev-server/test/collab-room.test.ts +21 -10
  94. package/plugins/design/dev-server/test/csp-canvas-shell.test.ts +46 -0
  95. package/plugins/design/dev-server/test/exporters/png.test.ts +24 -1
  96. package/plugins/design/dev-server/test/exporters/pptx-deck.test.ts +112 -0
  97. package/plugins/design/dev-server/test/exporters/pw-launch.test.ts +49 -0
  98. package/plugins/design/dev-server/test/exporters/scope.test.ts +0 -0
  99. package/plugins/design/dev-server/test/fixtures/phase-20-annotations.svg +1 -0
  100. package/plugins/design/dev-server/test/fixtures/phase-21-annotations.svg +1 -0
  101. package/plugins/design/dev-server/test/input-router.test.ts +32 -4
  102. package/plugins/design/dev-server/test/sanitize-annotation-svg.test.ts +132 -0
  103. package/plugins/design/dev-server/test/shared-doc-convergence.test.ts +265 -0
  104. package/plugins/design/dev-server/test/shared-doc-foundation.test.ts +63 -0
  105. package/plugins/design/dev-server/test/shared-doc-migrate.test.ts +160 -0
  106. package/plugins/design/dev-server/test/shared-doc-projection.test.ts +238 -0
  107. package/plugins/design/dev-server/test/sync-connection-state.test.ts +146 -0
  108. package/plugins/design/dev-server/test/sync-meta-codec.test.ts +123 -0
  109. package/plugins/design/dev-server/test/sync-runtime.test.ts +531 -4
  110. package/plugins/design/dev-server/test/sync-status.test.ts +80 -0
  111. package/plugins/design/dev-server/test/sync-untrusted.test.ts +104 -0
  112. package/plugins/design/dev-server/test/use-annotation-resize.test.ts +200 -0
  113. package/plugins/design/dev-server/test/use-tool-mode.test.tsx +39 -13
  114. package/plugins/design/dev-server/tool-palette.tsx +155 -24
  115. package/plugins/design/dev-server/undo-hud.tsx +4 -4
  116. package/plugins/design/dev-server/undo-stack.ts +20 -4
  117. package/plugins/design/dev-server/use-annotation-resize.tsx +219 -61
  118. package/plugins/design/dev-server/use-tool-mode.tsx +68 -19
  119. package/plugins/design/dev-server/ws.ts +40 -1
  120. package/plugins/design/templates/_shell.html +85 -10
  121. package/plugins/design/templates/canvas.tsx.template +13 -0
  122. package/plugins/design/templates/design-system-inspiration/SUB-AGENT-PROMPTS.md +14 -7
  123. package/plugins/flow/.claude-plugin/config.schema.json +5 -0
  124. package/plugins/flow/templates/ai-skeleton/README.md +1 -1
  125. package/plugins/flow/templates/ai-skeleton/gitignore +10 -0
  126. package/plugins/flow/templates/ai-skeleton/scenarios/README.md +3 -1
  127. package/plugins/flow/templates/ai-skeleton/workflows.config.json +2 -1
@@ -28,6 +28,26 @@
28
28
  <meta charset="utf-8" />
29
29
  <meta name="viewport" content="width=device-width,initial-scale=1" />
30
30
  <title>Canvas</title>
31
+ <script>
32
+ // T2 (9.1 / DDR-060 F1 re-audit) — best-effort WebRTC denial in the canvas
33
+ // iframe. CSP `webrtc 'block'` is specified but UNIMPLEMENTED in shipping
34
+ // Chrome/Firefox as of 2026 (Chromium #40188662, Firefox bug 1783489), so
35
+ // it is currently a no-op, and `connect-src 'self'` does NOT cover WebRTC
36
+ // (it is not Fetch). Hub-pushed canvas JS could otherwise exfil via
37
+ // ICE/STUN. Locking these to undefined raises the bar against the naive
38
+ // case before any canvas module loads. NOT bulletproof — a nested
39
+ // same-origin (about:blank) frame can re-acquire them — so WebRTC exfil
40
+ // stays a DOCUMENTED residual of opt-in linked mode (see the linked-mode
41
+ // README banner). `webrtc 'block'` stays in the CSP for when browsers
42
+ // enforce it. The canvas runtime itself uses zero WebRTC.
43
+ for (var __k of ['RTCPeerConnection', 'webkitRTCPeerConnection', 'RTCDataChannel']) {
44
+ try {
45
+ Object.defineProperty(window, __k, { value: undefined, configurable: false, writable: false });
46
+ } catch (_) {
47
+ /* already locked / not present */
48
+ }
49
+ }
50
+ </script>
31
51
  <style>
32
52
  :root {
33
53
  color-scheme: light dark;
@@ -45,27 +65,54 @@
45
65
  </style>
46
66
  <!-- Phase 6.5 export — when the shell is loaded with `&hide-chrome=1`
47
67
  (the exporters set this), suppress every dev-server overlay so the
48
- capture only carries the artboard content. The runtime chrome —
49
- tool palette, mini-world-map, comment pins, draw layer, snap guides,
50
- selection halos, the artboard label button — is not part of the
51
- design and would otherwise show up in PNG / PDF / SVG exports. -->
68
+ capture only carries the artboard content. The runtime chrome — tool
69
+ palette, mini-map, presence avatars + cursors, comment pins, draw
70
+ layer, snap guides, selection halos, toolbars, the artboard label
71
+ button — is not part of the design and would otherwise leak into PNG /
72
+ PDF / SVG exports. The selector list MUST track the live class names:
73
+ the previous list referenced `.dc-mini-map` / `.dc-world-map`, which
74
+ never existed (the real minimap is `.dc-mm`), and omitted the presence
75
+ avatars `.dc-participants`, so both leaked — see export-pipeline-fixes
76
+ Task 2. The bootstrap below flips this block's `media` from `not all`
77
+ to `all` only when `?hide-chrome=1`, so the live editor keeps chrome. -->
52
78
  <style id="canvas-hide-chrome" media="not all">
79
+ /* Minimap + zoom + tool palette (and its portaled popovers) */
80
+ .dc-mm,
81
+ .dc-zoom-tb,
53
82
  .dc-tool-palette,
83
+ .dc-tp-popover,
84
+ .dc-tp-shape-popover,
85
+ .dc-context-menu,
86
+ /* Presence — avatars (top-right) + live cursors */
87
+ .dc-participants,
88
+ .dc-cursor-overlay,
89
+ /* Selection + manipulation chrome */
54
90
  .dc-cv-halo,
55
91
  .dc-cv-group-bbox,
56
- .dc-mini-map,
57
- .dc-mini-world-map,
58
- .dc-world-map,
92
+ .dc-cv-eq-spacing-layer,
93
+ .dc-multi-artboard-tb,
94
+ .dc-elem-ctx-tb,
59
95
  .dc-snap-guide,
60
- .dc-annot-overlay,
96
+ .dc-snap-pill,
97
+ /* Annotations (FigJam-style draw layer) */
61
98
  .dc-annot-svg,
62
- .dc-annot-chrome,
63
99
  .dc-annot-ctx,
100
+ .dc-annot-resize-handle,
101
+ /* Comments — pins, threads, composer, @mention popup */
64
102
  .cm-layer,
65
103
  .cm-pin,
66
104
  .cm-thread,
67
105
  .cm-composer,
106
+ .cm-mention-popup,
107
+ /* Inspector pin overlay injected into every served shell (inspect.ts) */
108
+ .dgn-pin,
109
+ #dgn-pin-layer,
110
+ /* HUDs + banners */
111
+ .dc-ai-banner,
112
+ .dc-undo-hud,
113
+ /* Artboard title/label button (editor affordance, not design content) */
68
114
  .dc-artboard-label,
115
+ /* Generic opt-in hooks for any future floating overlay */
69
116
  [data-dc-overlay],
70
117
  [data-mdcc-annotations] { display: none !important; }
71
118
  </style>
@@ -150,13 +197,28 @@
150
197
  const v = msg.version || Date.now();
151
198
  // Match by exact filename when we have one; otherwise refresh all.
152
199
  const targetFile = (msg.file || '').split('/').pop();
200
+ let matched = false;
153
201
  for (const link of document.querySelectorAll('link[rel="stylesheet"]')) {
154
202
  const href = link.getAttribute('href') || '';
155
203
  if (!targetFile || href.includes(targetFile)) {
156
204
  const base = href.split('?')[0];
157
205
  link.setAttribute('href', base + '?v=' + v);
206
+ matched = true;
158
207
  }
159
208
  }
209
+ // A per-canvas `<slug>.css` imported by the TSX is INLINED into the
210
+ // canvas module as a <style> by Bun.build — there is no <link> to
211
+ // swap, so the loop above matches nothing and the edit is silently
212
+ // dropped until a manual hard-reload (RCA hmr-inlined-css-dropped).
213
+ // When nothing matched AND the changed CSS lives in THIS canvas's
214
+ // directory, reload so the rebuilt module re-inlines the fresh CSS.
215
+ // Scoped to same-dir so an unrelated specimen's CSS write doesn't
216
+ // reload every open tab.
217
+ if (!matched && msg.file && canvasRel) {
218
+ const cssDir = msg.file.replace(/[^/]+$/, '');
219
+ const canvasDir = canvasRel.replace(/[^/]+$/, '');
220
+ if (cssDir === canvasDir) location.reload();
221
+ }
160
222
  } else if (msg.mode === 'module' || msg.mode === 'hard') {
161
223
  // Only reload when the change touches *this* canvas (or `_lib`).
162
224
  if (msg.mode === 'hard' || !msg.file || (canvasRel && msg.file === canvasRel)) {
@@ -253,11 +315,24 @@
253
315
  'Canvas module at ' + canvasUrl + ' has no default export (or it is not a component).'
254
316
  );
255
317
  }
318
+ const rootEl = document.getElementById('canvas-root');
256
319
  mountCanvas(Canvas, {
257
- rootEl: document.getElementById('canvas-root'),
320
+ rootEl,
258
321
  file: designRel + '/' + canvasRel,
259
322
  commentsEnabled,
260
323
  });
324
+ // T2 (9.1-A) diagnostic — tell the parent the canvas mounted + how many
325
+ // root children it rendered. Lets the shell (and tooling) confirm a
326
+ // cross-origin canvas actually rendered, which a parent-page screenshot
327
+ // of an OOPIF cannot show. Harmless heartbeat; ignored if unhandled.
328
+ setTimeout(() => {
329
+ try {
330
+ window.parent.postMessage(
331
+ { dgn: 'canvas-mounted', file: designRel + '/' + canvasRel, children: rootEl ? rootEl.children.length : 0 },
332
+ '*'
333
+ );
334
+ } catch (e) { /* parent gone */ }
335
+ }, 800);
261
336
  } catch (err) {
262
337
  showError((err && err.stack) || String(err));
263
338
  }
@@ -29,6 +29,19 @@
29
29
  * server (canvas-pipeline.ts pass 1). Don't author them by hand — they'd be
30
30
  * stripped + replaced. `/design:handoff` strips them again before the registry
31
31
  * sidecar leaves dev (production has no business with dev-time scaffolding).
32
+ *
33
+ * Theme model (two ISOLATED layers — system-review D9):
34
+ * • Canvas-shell CHROME (workspace plane, floating toolbar, minimap, zoom
35
+ * HUD, halos) auto-follows the Maude dev-server theme via `data-maude-theme`
36
+ * on the iframe <html> — the dev-server sets it; never theme the chrome
37
+ * from canvas code.
38
+ * • ARTBOARDS keep THEIR design system's theme. The `data-theme` on the
39
+ * `{{ROOT_CLASS}}` wrapper pins this artboard to a specific DS theme block;
40
+ * leave it at the DS default ({{THEME_DEFAULT}}). Do NOT hardcode a theme
41
+ * the DS doesn't intend — a reviewer flips an individual artboard at will
42
+ * via right-click → Theme ▸ Light / Dark / Follow chrome (enabled when the
43
+ * DS ships both light + dark token blocks). Only pin a non-default theme
44
+ * when the canvas is intentionally single-theme.
32
45
  */
33
46
 
34
47
  import { useState } from "react";
@@ -25,9 +25,9 @@ The three MANDATORY safety blocks (ANIMATION SAFETY, RELATIVE-URL SAFETY, PLACEH
25
25
  ### RELATIVE-URL SAFETY (mandatory — applies to any specimen referencing assets, logos, glyphs)
26
26
 
27
27
  - The dev-server serves canvases via `/_canvas-shell.html?canvas=<rel-path>`. **Relative URLs (`../foo.svg`, `./assets/logo.svg`) resolve against the SHELL's URL, not the canvas file's location.** Result: 404 / broken-image icon. Studyfi imprint retro D-4 was caught by the user mid-flow because of exactly this.
28
- - **Always inline SVGs** in JSX. Use `useId()` for any `<filter id>` / `<linearGradient id>` so multiple instances of the same component don't collide on a single page. OR
29
- - **Always use absolute paths rooted at `/assets/...`** served from the dev-server's static mount. The `system/<ds>/assets/` directory is mounted at `/assets/<ds>/` in production-handoff mode.
30
- - **Forbidden:** `<img src="../foo.svg">`, `<image href="./logo.svg">`, `url('../bg.png')` inside inline `<style>` blocks. Any of these surviving in a specimen is a graphic-design-critic blocker.
28
+ - **Always inline SVGs** in JSX. Use `useId()` for any `<filter id>` / `<linearGradient id>` so multiple instances of the same component don't collide on a single page. This is the **strongly-preferred** default. OR
29
+ - **Use an absolute path that mirrors the real on-disk location under the repo root** — the ONE correct form is `/<designRoot>/system/<ds>/assets/<file>`, e.g. `/.design/system/<ds>/assets/logo.svg` (with the default `designRoot` of `.design`). The dev-server's fall-through serves any file by its real path under the repo root (`http.ts` `safePathUnderRoot`); there is **no `/assets/<ds>/` alias** that earlier wording was wrong and 404s. Substitute the project's actual `designRoot` (read `config.json` `designRoot`) if it isn't `.design`.
30
+ - **Forbidden:** `<img src="../foo.svg">`, `<image href="./logo.svg">`, `url('../bg.png')` inside inline `<style>` blocks, AND the bogus `/assets/<ds>/…` alias. Any of these surviving in a specimen is a graphic-design-critic blocker.
31
31
 
32
32
  ### PLACEHOLDER POLICY (mandatory — applies to logo / mark / wordmark / mascot / glyph / illustration claims)
33
33
 
@@ -134,7 +134,8 @@ SAFETY BLOCKS — apply to every file in your slice:
134
134
  + compositor-only + reduced-motion + no-bouncy-springs.
135
135
  - **RELATIVE-URL SAFETY** (see SUB-AGENT-PROMPTS.md). Mandatory if your slice
136
136
  references ANY asset (logo, glyph, illustration, background image). Inline
137
- SVG with `useId()`, OR absolute `/assets/<ds>/...` path. NEVER relative.
137
+ SVG with `useId()`, OR absolute `/<designRoot>/system/<ds>/assets/...` path
138
+ (e.g. `/.design/system/<ds>/assets/...`). NEVER relative, NEVER `/assets/<ds>/`.
138
139
  - **PLACEHOLDER POLICY** (see SUB-AGENT-PROMPTS.md). Mandatory if your slice
139
140
  scaffolds the `logo` / `empty-state` specimen or any brand-asset surface.
140
141
  Read the roster `assets:` block FIRST. If `source:` is populated, copy the
@@ -212,13 +213,17 @@ The base template above applies to every slice. Each slice gets a small addendum
212
213
 
213
214
  **Apply RELATIVE-URL SAFETY in full.** The `iconography` specimen tends to reference glyph SVGs; the `focus` specimen sometimes references focus-ring fixtures. Inline ALL SVGs.
214
215
 
216
+ **Restraint-default type ladder (D-8).** The `type-scale` specimen demonstrates the scale the tokens already encode — do NOT reintroduce drama the tokens deliberately held back. The default ceiling is **type-scale ratio ≤ 1.2, optical-size ≤ 72, display weight ≤ semibold, tracking ≥ -0.02em**. If `colors_and_type.css` already carries a more dramatic ladder (a high-confidence research recommendation explicitly asked for maximalism), mirror what the tokens declare — never push *beyond* the tokens on your own initiative. Restraint is the default; the user opts UP via `/design:edit`, not the sub-agent.
217
+
218
+ **Research type-fidelity (D-7).** Read the research payload's type recommendation (in the discovery payload / DS README). **Mirror its PRIMARY display-face ROLE exactly.** A "grotesque" direction yields a grotesque display face even when an open-source serif is more convenient to wire up — do NOT let font availability flip the role. Distinguish the **display role** from the **body-accent role**: a recommendation like `display-grotesque-editorial-serif` means a grotesque sans for the DISPLAY face *with* an editorial serif for BODY accents — it does NOT mean the serif is the display face. If the named face is unavailable, substitute within the SAME classification (grotesque → grotesque, not grotesque → serif) and note the substitution so it lands in the bypass-log. (Studyfi read "serif" off `display-grotesque-editorial-serif` and picked Fraunces as the display face — inverting the roles.)
219
+
215
220
  ### Slice: `brand + voice` (empty-state, logo)
216
221
 
217
222
  **Apply PLACEHOLDER POLICY in full.** This slice is the highest-risk for placeholder-bleed. The `logo` specimen MUST start by reading the roster's `assets:` block:
218
223
  - If `assets.logo.source` is a real path, the specimen `<img>`s / inlines the real asset.
219
224
  - If `assets.logo.source` is empty, fall back to a `-placeholder` SVG with the rationale in the JSX comment block. Set `source: placeholder` on roster update.
220
225
 
221
- **Apply RELATIVE-URL SAFETY in full.** Logo specimens are 100% asset-bound. Inline SVG is the default; absolute `/assets/<ds>/logo.svg` is the alternative.
226
+ **Apply RELATIVE-URL SAFETY in full.** Logo specimens are 100% asset-bound. Inline SVG is the default; absolute `/<designRoot>/system/<ds>/assets/logo.svg` (e.g. `/.design/system/<ds>/assets/logo.svg`) is the alternative — never the bogus `/assets/<ds>/` alias.
222
227
 
223
228
  ### Slice: `core components` (components-buttons, components-cards, components-inputs)
224
229
 
@@ -230,6 +235,8 @@ No slice-specific addenda — the base template covers them.
230
235
 
231
236
  ### Slice: `ui_kits-*-showcase` (main agent OR signature sub-agent)
232
237
 
238
+ **Showcase-from-real-app (D-6) — read the real layout BEFORE composing, for existing products.** If the prompt injects real layout paths (the orchestrator passes the app's `AppLayout` + primary-nav component paths when the DS is for a shipped product), you MUST **read those files first and mirror that UX, restyling only** — apply the DS tokens + signature treatment to the *real* screen anatomy. Do NOT invent a plausible-but-fictional product UX when a real one was handed to you; inventing it is the studyfi D-6 regression that forced a ~5500-LOC rebuild. If NO real layout paths are injected (greenfield DS), compose a project-specific mock from `domain_nouns` per the creativity rubric — that path is unchanged.
239
+
233
240
  **Apply ANIMATION SAFETY.** Showcase is the highest-density "DS in use" artifact; presence cursors, route transitions, and panel slides all show up here. Every animation must be bounded + reduced-motion-safe + token-derived.
234
241
 
235
242
  **Apply RELATIVE-URL SAFETY.** Showcase often references domain product imagery. Inline SVG mocks, never `<img src="../assets/...">`.
@@ -242,5 +249,5 @@ No slice-specific addenda — the base template covers them.
242
249
  - Discovery probe templates (sibling): `plugins/design/skills/design-system/_pastier-probe-templates.md`
243
250
  - Motion library decision: `.ai/decisions/DDR-049-motion-one-as-canonical-motion-library.md`
244
251
  - Imprint-bootstrap retro (source of D-1 … D-5): `.ai/logs/system-reviews/imprint-bootstrap-review-2026-05-26.md`
245
- - Asset sweep helper: `plugins/design/dev-server/bin/asset-sweep.sh`
246
- - Visual sanity helper: `plugins/design/dev-server/bin/visual-sanity.sh`
252
+ - Asset sweep helper: `maude design asset-sweep` (on-PATH `maude` dispatches to the bundled helper — DDR-062)
253
+ - Visual sanity helper: `maude design visual-sanity` (on-PATH `maude` dispatches to the bundled helper — DDR-062)
@@ -42,6 +42,11 @@
42
42
  "type": "string",
43
43
  "description": "Living codebase snapshot. Default: `.ai/context/codebase-map.md`.",
44
44
  "default": ".ai/context/codebase-map.md"
45
+ },
46
+ "designRoot": {
47
+ "type": "string",
48
+ "description": "Root of the design plugin's canvas workspace, relative to repo root. Where flow looks for `.meta.json` sidecars + canvases when bridging to design (`/flow:plan` canvas detection, `/flow:done` handoff sweep, `codebase-intelligence` design-artifacts section). Mirrors the design plugin's own default. Flow reads this directory read-only — it never writes into the design root except the `/flow:done` handoff sweep's meta status update. Default: `.design`.",
49
+ "default": ".design"
45
50
  }
46
51
  }
47
52
  },
@@ -27,7 +27,7 @@ These live at the root of `.ai/` (not in subfolders) and are referenced by `work
27
27
 
28
28
  - `<name>-prd.md` — product requirements / brief
29
29
  - `<name>-design-system.md` — design system reference (look & feel, tokens, density)
30
- - `workflows.config.json` — config consumed by all flow commands and skills
30
+ - `workflows.config.json` — config consumed by all flow commands and skills. The optional top-level `quality` map (lint / format / typecheck / tests / build → shell command) is **not** scaffolded here — run `maude doctor --fix` once your `package.json` scripts exist and it detects + adds them (additive, never overwrites your edits).
31
31
 
32
32
  ## Conventions
33
33
 
@@ -0,0 +1,10 @@
1
+ # Sidecar cache — Phase C / DDR-061 (cli/lib/cache.mjs).
2
+ # Commit the shareable, content-addressed layers (research/domain + codebase-
3
+ # intelligence are SHA-keyed and reusable across collaborators); keep the
4
+ # brief/run/HEAD-specific layers (research/project, design-context, scenario,
5
+ # security) and the local telemetry (_stats.json, README.md) out of git.
6
+ cache/*
7
+ !cache/codebase-intelligence/
8
+ !cache/research/
9
+ cache/research/*
10
+ !cache/research/domain/
@@ -9,6 +9,7 @@ scenarios/
9
9
  ├── _lib/ — shared helpers (selectors, fixtures, env)
10
10
  └── <scenario-slug>/
11
11
  ├── spec.md — what the flow does, success criteria, platform matrix
12
+ ├── covers.json — OPTIONAL: { web/native/shared git pathspecs } the scenario exercises
12
13
  └── <YYYY-MM-DD-HHMM>/
13
14
  ├── report.md — TL;DR + per-platform pivot table + counter deltas
14
15
  ├── web-desktop/ — screenshots, logs
@@ -21,6 +22,7 @@ scenarios/
21
22
 
22
23
  - **Scenario slug:** kebab-case, action-oriented (`coach-creates-recurring-practice`, `signup-via-invite`).
23
24
  - **Run timestamp:** local time of the run start. Latest run = lexicographically last folder.
24
- - **Report format:** owned by the `scenario` skill — see plugin docs.
25
+ - **Report format:** owned by the `scenario` skill — `maude scenario-report <run-dir>` generates the mechanical tables; the LLM authors only the prose sections.
26
+ - **`covers.json`** (optional): declares the source globs the scenario exercises, split into `web` / `native` / `shared` git pathspecs. Enables the route-aware skip (re-run only when covered files changed) and the web-only scope skip (no sim boot for web-only diffs). Example: `{"web":["app/(video)/**"],"native":["expo-app/**"],"shared":["packages/api-client/**"]}`. Absent → the scenario always runs the full platform matrix.
25
27
 
26
28
  Run with `/flow:scenario <slug>` (registered scenarios) or `/flow:scenario <ad-hoc description>` (one-off).
@@ -6,7 +6,8 @@
6
6
  "paths": {
7
7
  "prd": ".ai/PROJECT_NAME-prd.md",
8
8
  "designSystem": ".ai/PROJECT_NAME-design-system.md",
9
- "codebaseMap": ".ai/context/codebase-map.md"
9
+ "codebaseMap": ".ai/context/codebase-map.md",
10
+ "designRoot": ".design"
10
11
  },
11
12
  "platforms": ["web-desktop"],
12
13
  "stack": {