@1agh/maude 0.43.0 → 0.45.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 (126) hide show
  1. package/apps/studio/acp/bridge.ts +44 -10
  2. package/apps/studio/acp/env.ts +23 -0
  3. package/apps/studio/acp/login-state.ts +263 -0
  4. package/apps/studio/acp/plugin-bootstrap.ts +31 -25
  5. package/apps/studio/acp/probe.ts +152 -1
  6. package/apps/studio/annotations-layer.tsx +396 -46
  7. package/apps/studio/api.ts +395 -2
  8. package/apps/studio/bin/_audio-search.mjs +140 -0
  9. package/apps/studio/bin/_import-asset-pdf-worker.mjs +34 -0
  10. package/apps/studio/bin/_import-asset.mjs +815 -0
  11. package/apps/studio/bin/_import-brand.mjs +635 -0
  12. package/apps/studio/bin/_import-tokens-alias-resolver.mjs +95 -0
  13. package/apps/studio/bin/_import-tokens.mjs +1201 -0
  14. package/apps/studio/bin/_transcribe.mjs +419 -0
  15. package/apps/studio/bin/_transcribe.test.mjs +80 -0
  16. package/apps/studio/bin/audio-search.sh +28 -0
  17. package/apps/studio/bin/generate.sh +154 -0
  18. package/apps/studio/bin/import-asset.sh +34 -0
  19. package/apps/studio/bin/import-brand.sh +29 -0
  20. package/apps/studio/bin/import-tokens.sh +33 -0
  21. package/apps/studio/bin/photo-bg-remove.sh +119 -21
  22. package/apps/studio/bin/transcribe.sh +39 -0
  23. package/apps/studio/canvas-edit.ts +197 -2
  24. package/apps/studio/canvas-lib.tsx +115 -6
  25. package/apps/studio/client/app.jsx +1954 -685
  26. package/apps/studio/client/generate-dialog.jsx +352 -0
  27. package/apps/studio/client/github.js +14 -0
  28. package/apps/studio/client/inspector-controls.jsx +781 -0
  29. package/apps/studio/client/panels/BrandUploadPanel.jsx +233 -0
  30. package/apps/studio/client/panels/ChatPanel.jsx +15 -33
  31. package/apps/studio/client/panels/IntroVideoDialog.jsx +44 -0
  32. package/apps/studio/client/panels/OnboardingWizard.jsx +12 -0
  33. package/apps/studio/client/panels/ReadinessList.jsx +227 -7
  34. package/apps/studio/client/panels/SettingsPanel.jsx +828 -0
  35. package/apps/studio/client/panels/SetupChecklist.jsx +223 -0
  36. package/apps/studio/client/photo-knobs.jsx +167 -172
  37. package/apps/studio/client/styles/3-shell-maude.css +334 -28
  38. package/apps/studio/client/styles/4-components.css +223 -0
  39. package/apps/studio/client/styles/6-acp-chat.css +86 -0
  40. package/apps/studio/client/tour/quick-setup-tour.js +39 -0
  41. package/apps/studio/commands/annotation-strokes-command.ts +13 -3
  42. package/apps/studio/config.schema.json +70 -0
  43. package/apps/studio/context-menu.tsx +11 -2
  44. package/apps/studio/context.ts +16 -0
  45. package/apps/studio/design-setup-readiness.ts +115 -0
  46. package/apps/studio/dist/client.bundle.js +2097 -2088
  47. package/apps/studio/dist/styles.css +1 -1
  48. package/apps/studio/draw/palette.ts +34 -0
  49. package/apps/studio/footage/schema.test.ts +92 -0
  50. package/apps/studio/footage/schema.ts +179 -1
  51. package/apps/studio/generation/adapters/elevenlabs.ts +370 -0
  52. package/apps/studio/generation/adapters/gemini.ts +542 -0
  53. package/apps/studio/generation/adapters/groq.test.ts +80 -0
  54. package/apps/studio/generation/adapters/groq.ts +247 -0
  55. package/apps/studio/generation/audio-library.test.ts +95 -0
  56. package/apps/studio/generation/audio-library.ts +156 -0
  57. package/apps/studio/generation/captions.test.ts +78 -0
  58. package/apps/studio/generation/captions.ts +132 -0
  59. package/apps/studio/generation/download.ts +76 -0
  60. package/apps/studio/generation/elevenlabs.test.ts +223 -0
  61. package/apps/studio/generation/gemini.test.ts +350 -0
  62. package/apps/studio/generation/jobs.test.ts +128 -0
  63. package/apps/studio/generation/jobs.ts +243 -0
  64. package/apps/studio/generation/keys.test.ts +75 -0
  65. package/apps/studio/generation/keys.ts +162 -0
  66. package/apps/studio/generation/prefs.test.ts +95 -0
  67. package/apps/studio/generation/prefs.ts +82 -0
  68. package/apps/studio/generation/registry.ts +88 -0
  69. package/apps/studio/generation/types.test.ts +123 -0
  70. package/apps/studio/generation/types.ts +266 -0
  71. package/apps/studio/generation/whisper-models.test.ts +152 -0
  72. package/apps/studio/generation/whisper-models.ts +257 -0
  73. package/apps/studio/generation/whisper-spike-results.md +61 -0
  74. package/apps/studio/git/service.ts +3 -1
  75. package/apps/studio/http.ts +867 -9
  76. package/apps/studio/media/intro.mp4 +0 -0
  77. package/apps/studio/media-commit-chain.ts +119 -0
  78. package/apps/studio/paths.ts +10 -0
  79. package/apps/studio/readiness.ts +108 -20
  80. package/apps/studio/scaffold-design.ts +1145 -0
  81. package/apps/studio/server.ts +13 -1
  82. package/apps/studio/test/_helpers.ts +15 -2
  83. package/apps/studio/test/acp-bridge.test.ts +34 -1
  84. package/apps/studio/test/acp-env.test.ts +30 -0
  85. package/apps/studio/test/acp-plugin-bootstrap.test.ts +23 -57
  86. package/apps/studio/test/acp-session-plugins.test.ts +72 -1
  87. package/apps/studio/test/annotation-strokes-command.test.ts +17 -0
  88. package/apps/studio/test/annotations-layer.test.ts +174 -0
  89. package/apps/studio/test/canvas-origin-gate.test.ts +37 -0
  90. package/apps/studio/test/csp-canvas-shell.test.ts +11 -0
  91. package/apps/studio/test/csrf-write-guard.test.ts +23 -1
  92. package/apps/studio/test/design-setup-readiness.test.ts +155 -0
  93. package/apps/studio/test/element-structural-edit.test.ts +108 -0
  94. package/apps/studio/test/fixtures/fake-claude-auth.mjs +13 -0
  95. package/apps/studio/test/generate-route.test.ts +106 -0
  96. package/apps/studio/test/import-asset-browser.test.ts +64 -0
  97. package/apps/studio/test/import-asset-route.test.ts +71 -0
  98. package/apps/studio/test/import-asset.test.ts +399 -0
  99. package/apps/studio/test/import-brand-browser.test.ts +88 -0
  100. package/apps/studio/test/import-brand-route.test.ts +120 -0
  101. package/apps/studio/test/import-brand.test.ts +206 -0
  102. package/apps/studio/test/import-tokens.test.ts +722 -0
  103. package/apps/studio/test/media-commit-chain.test.ts +210 -0
  104. package/apps/studio/test/photo-bg-remove-validation.test.ts +71 -0
  105. package/apps/studio/test/readiness.test.ts +13 -11
  106. package/apps/studio/test/scaffold-design.test.ts +122 -0
  107. package/apps/studio/test/tour-overlay.test.tsx +16 -0
  108. package/apps/studio/tool-palette.tsx +11 -6
  109. package/apps/studio/ui-prefs.ts +130 -0
  110. package/apps/studio/use-canvas-media-drop.tsx +4 -2
  111. package/apps/studio/use-chrome-visibility.tsx +8 -2
  112. package/apps/studio/whats-new.json +96 -0
  113. package/apps/studio/ws.ts +5 -0
  114. package/cli/bin/maude.mjs +6 -6
  115. package/cli/commands/design.mjs +33 -0
  116. package/cli/commands/init.mjs +7 -1
  117. package/cli/lib/gitignore-block.mjs +1 -0
  118. package/cli/lib/pkg-root.mjs +107 -0
  119. package/cli/lib/pkg-root.test.mjs +79 -0
  120. package/cli/lib/reconstruct-toolset.test.mjs +194 -0
  121. package/cli/lib/update-check.mjs +8 -0
  122. package/package.json +12 -10
  123. package/plugins/design/dependencies.json +18 -0
  124. package/plugins/flow/.claude-plugin/config.schema.json +5 -0
  125. package/plugins/flow/templates/ai-skeleton/scenario-guide.md +39 -0
  126. package/plugins/flow/templates/ai-skeleton/scenarios/README.md +2 -0
@@ -398,6 +398,11 @@ export interface WorldContextValue {
398
398
  rectFor: (id: string) => ArtboardRect | null;
399
399
  /** All artboards in render order, with resolved world-coord positions. */
400
400
  artboards: ArtboardRect[];
401
+ /** Hug-mode artboards report their measured DOM height here so the shared
402
+ * ArtboardRect model (drag hit-test, marquee, fit-to-screen, culling) stays
403
+ * in sync with content that grows/shrinks. Runtime-only — never persisted
404
+ * to meta; a fixed-mode board never calls this. */
405
+ reportMeasuredHeight: (id: string, h: number) => void;
401
406
  /** Current pan/zoom state. `null` until the first useLayoutEffect runs. */
402
407
  viewport: ViewportState | null;
403
408
  /** id of the artboard closest to the viewport center (recomputed on settle). */
@@ -1635,16 +1640,33 @@ function DesignCanvasInner({ children, controls }: DesignCanvasProps) {
1635
1640
  // useLayoutEffect writes the initial transform before first paint.
1636
1641
  const worldStyle: CSSProperties = { visibility: 'hidden' };
1637
1642
 
1643
+ // Hug-mode height feedback (artboard "hug height" default). A hug board's
1644
+ // CSS height is `auto` (content-driven) — the DOM is authoritative, and this
1645
+ // just mirrors the measured height into the shared ArtboardRect model so
1646
+ // OTHER consumers (marquee, distribute, fit-to-screen, off-screen culling)
1647
+ // see the current box. Never touches meta/JSX — purely runtime state, unlike
1648
+ // commitArtboardPositions/applyArtboardLayout which persist. A no-op guard
1649
+ // on <1px delta avoids a ResizeObserver → setState → render → (stable, since
1650
+ // CSS height never reads back rect.h in hug mode) loop.
1651
+ const reportMeasuredHeight = useCallback((id: string, h: number) => {
1652
+ setArtboards((prev) => {
1653
+ const cur = prev.find((r) => r.id === id);
1654
+ if (!cur || Math.abs(cur.h - h) < 1) return prev;
1655
+ return prev.map((r) => (r.id === id ? { ...r, h } : r));
1656
+ });
1657
+ }, []);
1658
+
1638
1659
  const ctxValue = useMemo<WorldContextValue>(
1639
1660
  () => ({
1640
1661
  rectFor,
1641
1662
  artboards,
1663
+ reportMeasuredHeight,
1642
1664
  viewport: controller.viewport,
1643
1665
  activeArtboardId,
1644
1666
  hostRef,
1645
1667
  worldRef,
1646
1668
  }),
1647
- [rectFor, artboards, controller.viewport, activeArtboardId]
1669
+ [rectFor, artboards, reportMeasuredHeight, controller.viewport, activeArtboardId]
1648
1670
  );
1649
1671
 
1650
1672
  const showMiniMap = controls?.minimap !== false;
@@ -1793,12 +1815,30 @@ export function DCArtboard({
1793
1815
  label,
1794
1816
  width,
1795
1817
  height,
1818
+ fixed,
1819
+ background,
1820
+ padding,
1821
+ layout,
1822
+ gap,
1796
1823
  children,
1797
1824
  }: {
1798
1825
  id: string;
1799
1826
  label: string;
1800
1827
  width: number;
1801
1828
  height: number;
1829
+ /** Height sizing mode. Default (omitted/false) = HUG — the board grows to
1830
+ * fit content; `height` becomes a min-height floor rather than an exact
1831
+ * size. `true` = FIXED — today's behavior, `height` is exact and overflow
1832
+ * clips. Width is always exact regardless of this flag. */
1833
+ fixed?: boolean;
1834
+ /** `.dc-artboard-body` background (CSS color/token, e.g. "var(--bg-1)"). */
1835
+ background?: string;
1836
+ /** `.dc-artboard-body` padding, px, all sides. */
1837
+ padding?: number;
1838
+ /** `.dc-artboard-body` layout mode. Default = the engine's plain block flow. */
1839
+ layout?: 'block' | 'flex-col' | 'flex-row' | 'grid';
1840
+ /** `.dc-artboard-body` gap, px — only visible under flex-col/flex-row/grid. */
1841
+ gap?: number;
1802
1842
  children: ReactNode;
1803
1843
  }) {
1804
1844
  const ctx = useWorldContext();
@@ -1860,11 +1900,67 @@ export function DCArtboard({
1860
1900
  }
1861
1901
  }, [dragHook.dragState, dragBus]);
1862
1902
 
1903
+ // Hug default (artboard "hug height") — the authored `height` prop is a
1904
+ // FLOOR (min-height), not an exact size, unless `fixed` pins it. The floor
1905
+ // stays stable across renders (it only changes when the JSX prop itself is
1906
+ // edited), so it never ratchets up from a previously-larger measured value
1907
+ // the way feeding `rect.h` back as the floor would.
1908
+ const heightFloor = typeof height === 'number' ? height : VP_GRID.h;
1909
+ const articleRef = useRef<HTMLElement | null>(null);
1910
+ const measured = useArtboardBounds(articleRef as RefObject<HTMLElement | null>);
1911
+ useEffect(() => {
1912
+ if (!ctx || fixed) return;
1913
+ if (dragHook.dragState.kind !== 'idle') return;
1914
+ if (measured.height <= 0) return;
1915
+ ctx.reportMeasuredHeight(id, Math.round(measured.height));
1916
+ }, [ctx, fixed, dragHook.dragState.kind, measured.height, id]);
1917
+
1918
+ // Phase 2 — background/padding/layout/gap apply to the BODY (content box),
1919
+ // not the frame (label header stays chrome-styled). Undefined keys are
1920
+ // simply absent from the style object — no engine-CSS default is clobbered.
1921
+ const bodyStyle = useMemo<CSSProperties>(() => {
1922
+ const st: CSSProperties = {};
1923
+ if (background) st.background = background;
1924
+ if (typeof padding === 'number') st.padding = padding;
1925
+ if (typeof gap === 'number') st.gap = gap;
1926
+ if (layout === 'flex-col') {
1927
+ st.display = 'flex';
1928
+ st.flexDirection = 'column';
1929
+ } else if (layout === 'flex-row') {
1930
+ st.display = 'flex';
1931
+ st.flexDirection = 'row';
1932
+ } else if (layout === 'grid') {
1933
+ st.display = 'grid';
1934
+ }
1935
+ return st;
1936
+ }, [background, padding, gap, layout]);
1937
+
1938
+ // Read-back surface for the Inspector's ArtboardKnobs panel — the SAME
1939
+ // generic "custom HTML attributes" escape hatch dom-selection.ts already
1940
+ // scrapes off the selected element (styleMapsFor → Selection.attrs), so the
1941
+ // panel pre-fills current state with no new plumbing. React omits an
1942
+ // attribute entirely when its value is `undefined`.
1943
+ const readBackAttrs = {
1944
+ 'data-dc-fixed': fixed ? 'true' : undefined,
1945
+ 'data-dc-bg': background,
1946
+ 'data-dc-padding': typeof padding === 'number' ? String(padding) : undefined,
1947
+ 'data-dc-layout': layout,
1948
+ 'data-dc-gap': typeof gap === 'number' ? String(gap) : undefined,
1949
+ };
1950
+
1863
1951
  if (!ctx || !rect) {
1864
1952
  return (
1865
- <article className="dc-artboard" data-dc-screen={id} style={{ width, height }}>
1953
+ <article
1954
+ className="dc-artboard"
1955
+ data-dc-screen={id}
1956
+ ref={articleRef}
1957
+ style={fixed ? { width, height } : { width, height: 'auto', minHeight: heightFloor }}
1958
+ {...readBackAttrs}
1959
+ >
1866
1960
  <header className="dc-artboard-label sku">{label}</header>
1867
- <div className="dc-artboard-body">{children}</div>
1961
+ <div className="dc-artboard-body" style={bodyStyle}>
1962
+ {children}
1963
+ </div>
1868
1964
  </article>
1869
1965
  );
1870
1966
  }
@@ -1917,11 +2013,16 @@ export function DCArtboard({
1917
2013
  className={`dc-artboard dc-positioned${isInDrag ? ' dc-dragging' : ''}`}
1918
2014
  data-dc-screen={id}
1919
2015
  aria-current={isActive ? 'true' : undefined}
2016
+ ref={articleRef}
2017
+ {...readBackAttrs}
1920
2018
  style={{
1921
2019
  left: liveX,
1922
2020
  top: liveY,
1923
2021
  width: rect.w,
1924
- height: rect.h,
2022
+ // Hug default: height:auto + minHeight floor, content dictates the
2023
+ // box; the ResizeObserver above mirrors the settled size back into
2024
+ // rect.h for other consumers. Fixed: today's exact-height behavior.
2025
+ ...(fixed ? { height: rect.h } : { height: 'auto', minHeight: heightFloor }),
1925
2026
  // Off-screen artboards skip layout+paint. On a large multi-board
1926
2027
  // canvas (e.g. an 18-board moodboard) every board otherwise paints
1927
2028
  // onto one huge .dc-world plane whose device-pixel size exceeds
@@ -1966,7 +2067,9 @@ export function DCArtboard({
1966
2067
  </svg>
1967
2068
  </button>
1968
2069
  ) : null}
1969
- <div className="dc-artboard-body">{children}</div>
2070
+ <div className="dc-artboard-body" style={bodyStyle}>
2071
+ {children}
2072
+ </div>
1970
2073
  </article>
1971
2074
  {showActivity ? (
1972
2075
  <ArtboardActivityOverlay
@@ -2489,7 +2592,13 @@ export function PhotoPreviewBridge() {
2489
2592
  // attribute toggle on the real element, styled by inspect.ts's single CSS
2490
2593
  // injection point (mirrors `.dc-activity-scan`'s sweep language). No
2491
2594
  // separate tracked overlay — see the header comment above `apply()`.
2492
- if (m.dgn === 'photo-busy' && typeof m.asset === 'string') {
2595
+ // `m.asset` must pass the same shape check `extractAssetRef` applies
2596
+ // elsewhere in this file (fix-photo-editor-followup-debt, Task 8) —
2597
+ // an empty string previously matched EVERY photo element via
2598
+ // `findPhotoEl`'s substring-match fallback (`src.includes('')` is always
2599
+ // true), so an empty/malformed `asset` is now a no-op instead of toggling
2600
+ // the busy shimmer on every photo on the canvas.
2601
+ if (m.dgn === 'photo-busy' && typeof m.asset === 'string' && ASSET_REF_RE.test(m.asset)) {
2493
2602
  const el = findPhotoEl(m.asset);
2494
2603
  el?.toggleAttribute('data-photo-busy', !!m.busy);
2495
2604
  return;