From b7c19a509513d2c202c70bef0b258b90e682039e Mon Sep 17 00:00:00 2001 From: Ryan Dombrowski Date: Sat, 8 Aug 2026 14:51:47 -0400 Subject: [PATCH] feat(composer): hosted demo is the shadcn v3 reference project MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit composer.aesthetic-function.com now demonstrates the representation work we shipped, not the v1 Acme sample. The baked demo (demo-data.ts + demo-assets) is the shadcn/ui v3 project: 34 components mapped through the v2-language production profile (T1-T4 + A0), 14 worked surfaces (11 emit, 3 refuse on declared casualties — accordion/breadcrumb/pagination/tooltip, first-class). The Acme project stays in the repo for the agent 'bring your own library' story. Removed the v3 project's surfaces/ dir (it duplicated the contract's 14 examples; recomputeEmit/demo-assets read contract examples directly). Two real v3-compat bugs found by validating the hosted demo, both fixed: 1. **In-browser validation failed on the v3 contract**: rule 48 (rule.form-control-carries-control) uses requiredCategories (dspack-spec 0.4.3+), but Studio's browser validator bundled dspack-spec 0.4.2's v0.4 schema, which rejects it. Bumped @aestheticfunction/dspack-spec ^0.4.2 -> ^0.4.4 (composer + agent); 'contract + surface gates' now PASS. 2. **Mapper crashed (React #31) on any v3 enum prop**: v3 contracts carry enum members as {value, description} objects; the Mapper rendered them as React children and used them as keys. Added enumLabel() and normalised every enum-value use through it (v1 strings and v3 objects both). Rewrote e2e/composer-prod-smoke.spec.ts for the v3 demo (12 specs): load, agent honesty, project checklist, inventory + casualty, mapper fidelity, whole-in-browser validation (catalog A1-A3 + document S1-S3 PASS), preview + casualty refusals, export, reload-safety, acknowledged casualties, rule builder rationale-gate, scenario live gates, bundle hygiene. 12/12 green against the built static export. Live authoring/generation still needs the local agent — asserted, not hidden. Co-Authored-By: Claude Fable 5 --- apps/agent/package.json | 2 +- apps/composer/app/demo-data.ts | 26 +- apps/composer/app/views/mapper-view.tsx | 21 +- apps/composer/package.json | 2 +- apps/composer/scripts/demo-assets.mjs | 6 +- apps/composer/shadcn-v3-project/project.json | 1 - .../customer-context-sheet.dsurface.json | 121 ------- .../delete-account-confirmation.dsurface.json | 53 --- .../delete-project-confirmation.dsurface.json | 128 ------- .../surfaces/docs-article-trail.dsurface.json | 165 --------- .../expense-report-form.dsurface.json | 242 ------------- .../surfaces/import-run-status.dsurface.json | 110 ------ .../invite-teammates-dialog.dsurface.json | 130 ------- .../notification-preferences.dsurface.json | 176 --------- .../order-detail-summary.dsurface.json | 195 ---------- .../orders-table-loading.dsurface.json | 229 ------------ .../project-workspace-panels.dsurface.json | 193 ---------- .../support-ticket-queue.dsurface.json | 132 ------- .../usage-help-affordances.dsurface.json | 148 -------- .../workspace-members-directory.dsurface.json | 333 ------------------ e2e/composer-prod-smoke.spec.ts | 101 +++--- pnpm-lock.yaml | 14 +- 22 files changed, 99 insertions(+), 2429 deletions(-) delete mode 100644 apps/composer/shadcn-v3-project/surfaces/customer-context-sheet.dsurface.json delete mode 100644 apps/composer/shadcn-v3-project/surfaces/delete-account-confirmation.dsurface.json delete mode 100644 apps/composer/shadcn-v3-project/surfaces/delete-project-confirmation.dsurface.json delete mode 100644 apps/composer/shadcn-v3-project/surfaces/docs-article-trail.dsurface.json delete mode 100644 apps/composer/shadcn-v3-project/surfaces/expense-report-form.dsurface.json delete mode 100644 apps/composer/shadcn-v3-project/surfaces/import-run-status.dsurface.json delete mode 100644 apps/composer/shadcn-v3-project/surfaces/invite-teammates-dialog.dsurface.json delete mode 100644 apps/composer/shadcn-v3-project/surfaces/notification-preferences.dsurface.json delete mode 100644 apps/composer/shadcn-v3-project/surfaces/order-detail-summary.dsurface.json delete mode 100644 apps/composer/shadcn-v3-project/surfaces/orders-table-loading.dsurface.json delete mode 100644 apps/composer/shadcn-v3-project/surfaces/project-workspace-panels.dsurface.json delete mode 100644 apps/composer/shadcn-v3-project/surfaces/support-ticket-queue.dsurface.json delete mode 100644 apps/composer/shadcn-v3-project/surfaces/usage-help-affordances.dsurface.json delete mode 100644 apps/composer/shadcn-v3-project/surfaces/workspace-members-directory.dsurface.json diff --git a/apps/agent/package.json b/apps/agent/package.json index 96f77fe..67a4cae 100644 --- a/apps/agent/package.json +++ b/apps/agent/package.json @@ -16,7 +16,7 @@ "@aestheticfunction/dspack-emit": "^0.6.0", "@aestheticfunction/dspack-export": "^0.5.0", "@aestheticfunction/dspack-gen": "^0.3.1", - "@aestheticfunction/dspack-spec": "^0.4.2", + "@aestheticfunction/dspack-spec": "^0.4.4", "@dspack-studio/agui-bridge": "workspace:*", "@dspack-studio/composer-core": "workspace:*", "@dspack-studio/contracts": "workspace:*", diff --git a/apps/composer/app/demo-data.ts b/apps/composer/app/demo-data.ts index 041b9b5..0c50628 100644 --- a/apps/composer/app/demo-data.ts +++ b/apps/composer/app/demo-data.ts @@ -1,15 +1,29 @@ /** * The shipped demo project (honest magic: real files, pre-emitted at build - * time by scripts/demo-assets.mjs — the same published APIs the agent runs). + * time by scripts/demo-assets.mjs — the same published dspack-emit APIs the + * agent runs). + * + * The hosted demo is the **shadcn/ui v3** reference project: the production + * v3 contract (34 components) mapped through a v2-language profile (T1-T4 + + * A0), so composer.aesthetic-function.com demonstrates the representation + * work actually shipped — the T4 dialog/sheet, T1 label donation, T3 joins, + * A0 families — rendered through the wireframe registry. Its 14 worked + * surfaces emit 11 and refuse 3 on *declared casualties* (accordion, + * breadcrumb, pagination, tooltip), surfaced as acknowledged, not failure. + * + * Live authoring — connecting your own React library, saving edits, and AI + * generation — still requires the local agent (`pnpm --filter agent dev`); + * the hosted app states that plainly. */ -import demoContract from "../demo-project/acme-ui.dspack.json"; -import demoProfile from "../demo-project/acme.profile.json"; -import demoManifest from "../demo-project/project.json"; +import demoContract from "../shadcn-v3-project/shadcn-ui.dspack.json"; +import demoProfile from "../shadcn-v3-project/shadcn-v3.profile.json"; +import demoManifest from "../shadcn-v3-project/project.json"; import demoEmit from "./demo/generated/emit.json"; -import usesCasualty from "../demo-project/surfaces/uses-casualty.dsurface.json"; export const DEMO_CONTRACT = demoContract as unknown as Record; export const DEMO_PROFILE = demoProfile as unknown as Record; export const DEMO_MANIFEST = demoManifest as unknown as Record; export const DEMO_EMIT = demoEmit as unknown as Record; -export const DEMO_EXTRA_SURFACES = [{ name: "uses-casualty", surface: usesCasualty as unknown }]; +// The v3 contract's 14 examples ARE the worked surfaces (recomputeEmit emits +// contractSurfaces(doc)); the project carries no extra surfaces beyond them. +export const DEMO_EXTRA_SURFACES: Array<{ name: string; surface: unknown }> = []; diff --git a/apps/composer/app/views/mapper-view.tsx b/apps/composer/app/views/mapper-view.tsx index 53421db..7b4ae66 100644 --- a/apps/composer/app/views/mapper-view.tsx +++ b/apps/composer/app/views/mapper-view.tsx @@ -10,6 +10,15 @@ import { useState } from "react"; import { useComposer } from "../state"; +/** + * A contract enum member is either a plain string (v1) or a + * `{ value, description }` object (v3). Everything that treats an enum value + * as text — labels, valueMap keys, React children — must go through this; + * rendering the object directly is React error #31. + */ +const enumLabel = (v: unknown): string => + typeof v === "string" ? v : v && typeof v === "object" && "value" in v ? String((v as { value: unknown }).value) : String(v); + const field = { fontFamily: "var(--mono)", fontSize: 12, @@ -89,7 +98,7 @@ export function MapperView() { {name} - {cprop.values &&
[{cprop.values.join(", ")}]
} + {cprop.values &&
[{cprop.values.map(enumLabel).join(", ")}]
} {pp ? ( <> @@ -112,7 +121,12 @@ export function MapperView() { {pp.kind === "enum" && cprop.values ? (
- {cprop.values.map((v: string) => ( + {cprop.values.map((raw: unknown) => { + // v3 contracts carry enum members as {value, description}; + // v1 carries plain strings. Normalise to the value string — + // rendering the object directly is React error #31. + const v = enumLabel(raw); + return ( {v} →{" "}