open-design/scripts
chaoxiaoche e57e028222
feat(daemon): make design-system token channel default-on (PR-D) (#1544)
* feat(daemon): make design-system token channel default-on (PR-D)

Flip `OD_DESIGN_TOKEN_CHANNEL` from default-off to default-on. Every
chat that picks a brand with `tokens.css` + `components.html` siblings
(today: `default`, `kami`) now gets the structured token contract
appended to the system prompt automatically. `OD_DESIGN_TOKEN_CHANNEL=0`
keeps the DESIGN.md-only path as a kill switch.

Adds `scripts/check-design-system-flag-parity.ts`, registered in
`pnpm guard`. The guard walks every brand and asserts:

- 147 prose-only brands produce byte-identical prompts under flag-off
  vs flag-on (PR-D's "no-op for legacy brands" promise)
- 2 structured brands diverge as expected (catches a future regression
  that silently dropped the structured blocks)

Smoke evidence on #1385 (PR-C):
- `default` — 10/10 brand tokens used byte-for-byte in treatment vs
  0/10 invented colors in control
- `kami` — treatment recovers brand name (`Kami · 纸`), the two-tier
  surface (`--bg` parchment + `--surface` ivory), the CN font stack
  override, and the `components.html` card pattern; control invented
  "Replica" as a brand name

Co-authored-by: Cursor <cursoragent@cursor.com>

* review: address @nettee + @lefarcen feedback on parity guard

Two blocking findings from #1544 review:

1. @nettee — guard's inventory walk silently passed on unreadable
   filesystem state. `fileExists` swallowed every `stat` error and the
   bare `readdir` catch returned `[]` for any failure. A renamed
   `design-systems/` tree, a permission-denied DESIGN.md, or a
   directory at the brand path would have left `pnpm guard` happy
   after checking 0 brands — exactly the silent misconfiguration this
   guard exists to catch. Both error paths now treat only ENOENT /
   ENOTDIR as absence and rethrow everything else, mirroring the
   `readFileOptional` fix already applied to PR-C's
   `apps/daemon/src/design-systems.ts`.

2. @nettee — guard exercised `composeSystemPrompt` directly, bypassing
   the `process.env.OD_DESIGN_TOKEN_CHANNEL !== '0'` gate in server.ts
   that PR-D actually flipped. A regression that restored `=== '1'`,
   typo'd the env name, or stopped reading assets when the var is
   unset would still leave the guard green. Extracted the predicate
   into `isDesignTokenChannelEnabled(env)` next to
   `readDesignSystemAssets` and added 6 unit tests pinning every value
   that matters: unset / `'1'` / `'true'` / empty / `'0'` /
   whitespace-padded. server.ts now calls the predicate. Any
   regression on the env-flag semantics fails
   `tests/design-system-assets.test.ts` independently of the
   composer-level coverage.

Verified: pnpm guard (13/13), tsc -p scripts/tsconfig.json (clean),
@open-design/daemon typecheck (clean), 32/32 prompt + asset tests.

Co-authored-by: Cursor <cursoragent@cursor.com>

* review: pin server-layer asset resolution end-to-end (lefarcen P2)

Round-2 review feedback from @lefarcen on #1544: the predicate suite
in tests/design-system-assets.test.ts pinned the env-flag boolean but
did NOT exercise the server prompt-assembly path that PR-D actually
flipped — the seam where the daemon decides whether to read tokens.css
/ components.html from disk and hand them to composeSystemPrompt. A
regression that, say, restored an inline `=== '1'` gate or stopped
calling isDesignTokenChannelEnabled() from server.ts would still leave
the predicate test green.

Extracted that whole seam into `resolveDesignSystemAssets(id,
builtInRoot, userInstalledRoot, env)` on apps/daemon/src/design-systems.ts.
The function combines:
  1. the env-flag gate (kill switch on `OD_DESIGN_TOKEN_CHANNEL=0`)
  2. the built-in → user-installed root fallback chain (per-file)
  3. the DesignSystemAssets result shape consumed by composeSystemPrompt

server.ts at the prompt-assembly site is now a thin caller of this
function. The previous 13-line inline block (env check + per-file
fallback) collapses to one call, so the whole asset-resolution path
now has a single testable seam.

7 new tests in tests/design-system-assets.test.ts run the full pipeline
end-to-end against real disk fixtures:
  - env unset (default-on): returns built-in assets
  - env=`'0'` (kill switch): returns undefined even with files on disk
  - env=`'1'` (legacy opt-in): still works
  - mixed builtin/user-installed: per-file fallback merges correctly
  - both halves built-in: skips user-installed roundtrip verbatim
  - prose-only brand (no files): undefined / undefined
  - nonexistent brand directory: undefined / undefined

Verified: pnpm guard (13/13), tsc -p scripts/tsconfig.json (clean),
@open-design/daemon typecheck (clean), 39/39 prompt + asset tests
(was 32; +7 new server-layer-resolution tests).

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(test): add missing projectKind to FileViewer deck preview test

The deck preview test added in #1556 (086be271) renders <FileViewer/>
without `projectKind`, which became a required prop in #1509. CI on
main is currently red on this; pick up the trivial fix here so PR-D
can land cleanly.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: chaoxiaoche <chaoxiaoche@chaoxiaochedeMacBook-Pro.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-14 14:14:19 +08:00
..
bake-community-pets.ts fix: remove Trump pet from bundled community pets (#1103) 2026-05-10 12:11:00 +08:00
bake-html-ppt-examples.mjs feat(skills): integrate lewislulu/html-ppt-skill + 15 per-template Examples cards (#193) 2026-05-02 11:00:44 +08:00
check-design-system-flag-parity.ts feat(daemon): make design-system token channel default-on (PR-D) (#1544) 2026-05-14 14:14:19 +08:00
check-tokens-fixture-sync.ts feat(design-systems): add structured tokens.css schema (default + kami) (#1231) 2026-05-11 22:23:34 +08:00
guard.ts feat(daemon): make design-system token channel default-on (PR-D) (#1544) 2026-05-14 14:14:19 +08:00
i18n-check.ts Add i18n structure checks (#608) 2026-05-06 11:55:59 +08:00
import-prompt-templates.mjs feat(prompt-templates): add dance storyboard and ancient-china MMO HUD templates (#187) 2026-05-01 17:30:02 +08:00
notebooklm-export-github.ts docs: add NotebookLM GitHub export script (#1062) 2026-05-12 15:47:32 +08:00
postinstall.mjs feat(tools-pr): add maintainer PR-duty workspace (#1259) 2026-05-11 19:17:21 +08:00
release-beta.ts [codex] Add stable nightly promotion gate (#962) 2026-05-08 21:48:54 +08:00
release-stable.ts test: harden e2e smoke and release reports (#1140) 2026-05-11 13:11:16 +08:00
scaffold-html-ppt-skills.mjs feat(skills): integrate lewislulu/html-ppt-skill + 15 per-template Examples cards (#193) 2026-05-02 11:00:44 +08:00
seed-curated-design-skills.ts feat: generic skills + split skills/design-templates + finalize-design API (#955) 2026-05-11 17:48:34 +08:00
seed-test-projects.ts feat(hyperframes): land HTML-in-Canvas across web + skills (#866) 2026-05-11 15:45:12 +08:00
style-policy.test.ts feat(web): Add Tailwind foundation (#1388) 2026-05-12 21:48:16 +08:00
style-policy.ts feat(web): Add Tailwind foundation (#1388) 2026-05-12 21:48:16 +08:00
sync-community-pets.ts feat(web): add pet companion with Codex hatch-pet integration (#296) 2026-05-02 23:45:39 +08:00
sync-design-systems.ts Add shared contracts and migrate project code to TypeScript (#118) 2026-04-30 13:01:15 +08:00
sync-hyperframes-skill.mjs feat(media): port generation workflow onto main (#12) 2026-04-30 22:44:00 +08:00
sync-litellm-models.ts fix: make max_tokens configurable (closes #29) (#78) 2026-05-02 13:52:54 +08:00
tsconfig.json chore: enforce test directory conventions (#496) 2026-05-05 15:34:22 +08:00
verify-media-models.mjs feat(media): port generation workflow onto main (#12) 2026-04-30 22:44:00 +08:00