mirror of
https://github.com/nexu-io/open-design.git
synced 2026-10-27 09:51:12 +01:00
fix/misc-bugs
13
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
16fad1c4d8 |
revert(design-systems): remove structured runtime workflow (#7110)
* revert: remove structured design system runtime * fix: preserve authority boundaries during revert |
||
|
|
f1a0b60c6c |
chore: unify product name display to OpenDesign repo-wide (#6998)
* chore: unify product name display to OpenDesign repo-wide Rename the user-facing product name from "Open Design" to "OpenDesign" across documentation, web/desktop UI strings, i18n locales, prompts, plugin/skill/design-system content, changelogs, and specs, matching the landing-page rename already in flight. Deliberately excluded so installed-app identity stays untouched: - packages/release PRODUCT_NAME and everything derived from it (app bundle names, installer/registry identity, updater feeds) - tools/pack, tools/release, apps/packaged, landing page (PR #6983) - mocks/ recorded traces and LICENSE - test fixtures and comments that encode real on-disk install paths (Open Design.app, Program Files\Open Design, AppData paths) Validated with pnpm guard, pnpm typecheck, and targeted web/desktop/host test runs over the renamed strings. * fix(web): keep two-letter author monogram for CamelCase brand names authorInitials split words on whitespace only, so the renamed single-token author name "OpenDesign" produced a one-letter monogram. Treat lower-to-upper CamelCase boundaries as word breaks so the avatar fallback stays "OD". * fix(release): restore spaced Windows source artifact names in win.ps1 tools/pack still derives builder outputs from the unchanged PRODUCT_NAME ("Open Design"), so the asset script must look for the spaced filenames. Matches the mac/mac-intel/linux asset scripts, which were already kept on the original names. --------- Co-authored-by: Joey <236967869+joeylee12629-star@users.noreply.github.com> |
||
|
|
4908baa4f4 |
feat(design-systems): ship structured runtime workflow (#6805)
* feat(design-systems): add structured runtime contract (#6456) * feat(design-systems): add structured runtime contract * chore: retrigger CI for PR 6456 --------- Co-authored-by: xiaoche-hub <298951296+xiaoche-hub@users.noreply.github.com> Co-authored-by: mrcfps <mrc@powerformer.com> * feat(design-systems): resolve structured runtime intents * fix(design-systems): preserve workspace runtime scope * test(design-systems): cover scoped prompt runtime * fix(design-systems): use one component authority * fix(design-systems): preserve run workspace authority * fix(design-systems): honor runtime rollback gate * fix(design-systems): pin run binding authority * fix(runs): reject client-supplied scopes * fix(design-systems): keep user package assets scoped * feat(design-systems): validate generated UI adherence * test(e2e): assert durable reload authority state * fix(design-systems): reject non-executable adherence evidence * fix: harden design system adherence validation * fix(design-systems): validate JSX selectors structurally * fix(design-systems): close adherence input gaps * chore(nix): refresh pnpm dependency hashes * chore(ci): retrigger design system validation * fix(daemon): bound design system artifact reads * fix(design-systems): bridge Codex runtime tools * docs(codex): clarify shell environment policy --------- Co-authored-by: open-design-crew[bot] <299007234+open-design-crew[bot]@users.noreply.github.com> Co-authored-by: xiaoche-hub <298951296+xiaoche-hub@users.noreply.github.com> Co-authored-by: mrcfps <mrc@powerformer.com> |
||
|
|
99fc8a45bc |
Revert "feat(design-systems): add structured runtime contract (#6456)" (#6520)
This reverts commit
|
||
|
|
2b8aa8c457 |
feat(design-systems): add structured runtime contract (#6456)
* feat(design-systems): add structured runtime contract * chore: retrigger CI for PR 6456 --------- Co-authored-by: xiaoche-hub <298951296+xiaoche-hub@users.noreply.github.com> Co-authored-by: mrcfps <mrc@powerformer.com> |
||
|
|
6b90486c97 |
docs: reconcile stale documentation with current code (#5829)
* fix(docs): align question guidance with form flow * docs: reconcile stale documentation with current code * fix(docs): remove retired template metadata from guides Generated-By: looper 0.10.6 (runner=fixer, agent=codex) * fix(e2e): stabilize visual workspace helper Generated-By: looper 0.10.6 (runner=fixer, agent=codex) * fix(docs): align localized template guide metadata Generated-By: looper 0.10.6 (runner=fixer, agent=codex) |
||
|
|
67a8d7cc8e |
Add derived design-system token outputs (#3734)
* Add derived design system token outputs * Harden derived design token output guards --------- Co-authored-by: chaoxiaoche <chaoxiaoche@chaoxiaochedeMacBook-Pro.local> |
||
|
|
2df76ee0c9 |
Improve design system token import contract (#3719)
Co-authored-by: chaoxiaoche <chaoxiaoche@chaoxiaochedeMacBook-Pro.local> |
||
|
|
fd8159216a |
feat(design-systems): import shadcn registry items as design systems (#3525)
* feat(design-systems): import shadcn registry items as design systems Add a third design-system import source alongside local folders and public GitHub repos: a shadcn registry item, referenced with the shadcn CLI shorthand `<owner>/<repo>/<item>` (resolved against the repo's root registry.json) or a direct https URL to a registry-item document. The item's cssVars theme is materialized into a temporary project and run through the existing local importer, so a shadcn theme yields the same DESIGN.md + tokens.css + manifest.json as every other import. Classic shadcn bare-HSL cssVars (e.g. "222 47% 11%") are wrapped into hsl(...) so brand colors survive instead of falling back to neutrals. Exposed on both surfaces, per the capability dual-track rule: - POST /api/design-systems/import/shadcn, with ImportShadcn* DTOs in packages/contracts and a "shadcn" source in the design-system manifest schema. - `od design-systems import-shadcn <reference> [--name --import-mode --craft --json]`. - Settings -> Design systems: a new "shadcn" import source (placeholder shadcn/ui/theme-zinc), with i18n keys added across all locales. http:// references are accepted only for loopback hosts so a self-hosted local registry can be imported and tests stay deterministic. * fix(design-systems): harden shadcn importer per review - Fail fast in writeShadcnFiles: a declared registry file that 404s, exceeds the size cap, exceeds the file-count cap, or has no safe destination now throws a path-named LocalDesignSystemImportError instead of silently producing a partially-materialized design system. - Resolve the shadcn `include` registry layout recursively; an item's relative file paths now resolve against the registry.json that declared it (so `owner/repo/item` works for registries that use include). - Keep the fetch abort timer armed across response-body consumption so a server that stalls the body cannot hang the import. - Block SSRF: redirect:'error' on the default fetch, plus per-fetch host re-validation (https, or http only for loopback) on every URL we contact - entry point, raw GitHub URLs, include targets, and raw files. Adds regression tests for include resolution, a 404 declared file, an oversized inline file, and a non-loopback http include target. * fix(design-systems): close two shadcn importer review gaps - parseShadcnReference: wrap decodeURIComponent of the URL fragment so malformed percent-encoding (e.g. "#%E0%A4%A") surfaces as a 400 BAD_REQUEST instead of an uncaught 500 from the import route. - writeShadcnFiles: two declared files that collapse to the same sanitized destination (e.g. "@/button.tsx" + "button.tsx") now fail as a BAD_REQUEST naming both sources, instead of silently dropping the later file - the same partial-materialization failure mode this PR avoids. Adds parser + importer regression tests for both. * fix(design-systems): harden shadcn importer (SSRF, resource bounds, fidelity) A deeper hardening pass from an adversarial self-review of the importer. SSRF egress policy (assertFetchableUrl): loopback is allowed over http or https (self-hosted/local registries); private (10/8, 172.16/12, 192.168/16, 100.64/10), link-local (169.254/16, fe80::/10), ULA (fc00::/7), unspecified (0.0.0.0, ::), and IPv4-mapped/integer-encoded internal addresses are refused for BOTH schemes; any other host must be https. Enforced at parse time and on every fetch - entry point, include targets, and raw files - so a direct https://169.254.169.254, or an include/redirect pivot to an internal address, is blocked rather than only the http downgrade. Resource bounds: bodies are read with a running byte cap (no unbounded buffering) plus a Content-Length pre-check; the whole import shares one wall-clock deadline and a max-total-requests budget; include breadth and file count are capped. A stalled/huge body or a large include fan-out can no longer hang or OOM the import. Fidelity / fail-fast: a files[] entry with no usable destination is now a 400 (was silently skipped); registry files are materialized under a subdirectory so a crafted target cannot overwrite the importer's theme.css/package.json/ README.md; cssVars keys/values are validated so a hostile entry cannot inject extra declarations or be silently dropped; slashed git refs are encoded per segment; direct-URL items resolve path-only files relative to the item URL; fetch timeouts surface as a clean BAD_REQUEST. Adds tests for each: https-internal SSRF (entry + include), a no-destination file, a reserved-file overwrite attempt, a slashed ref, a direct-URL path-only file, cssVars injection, and a streaming over-cap body. |
||
|
|
6a08dfe111 |
Add design system package quality guard (#2224)
* Add design system import manifest schema * Generate hybrid design system imports * Read design system usage and cached manifests * Add design system pull-file tool * Show design system package evidence * Wire design system import semantics * Add design system package quality guard --------- Co-authored-by: chaoxiaoche <chaoxiaoche@chaoxiaochedeMacBook-Pro.local> |
||
|
|
f7eb82d7a5 |
feat(design-systems): import design system projects (#2112)
* feat(design-systems): define project manifest contract * feat(design-systems): add default project manifest * feat(daemon): consume design system manifests * feat(design-systems): import local project systems * feat(design-systems): import from github repositories --------- Co-authored-by: chaoxiaoche <chaoxiaoche@chaoxiaochedeMacBook-Pro.local> |
||
|
|
4e38357e7d |
feat(design-systems): add structured tokens for notion, linear, github, figma, slack, discord, openai, shopify, spotify, uber (#1794)
* feat(design-systems): add structured tokens for notion, linear, github, figma, slack, discord, openai, shopify, spotify, uber Hand-authored batch-2 oracle fixtures for 10 high-profile brands. Each brand ships tokens.css (A1/A2/B-slot declarations) + components.html (:root pasted verbatim, no off-token values). pnpm guard reports 12 structured brands (up from 2), all 13 checks pass. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(design-systems): correct elev-ring, focus-ring, and spacing schema drift - slack: rebind --elev-ring to hairline form (0 0 0 1px var(--border)) so cross-brand components expecting a 1px outline get a ring, not a soft drop shadow; the previous value was Slack DESIGN.md "Low" elevation accidentally placed in the wrong slot - linear-app: expand --focus-ring to the DESIGN.md §6/§7 multi-layer stack (accent ring + black blur) so keyboard focus is visible on the near-black #08090a canvas - openai: restore --space-{5,6,8,12} to the shared 4·N px spine and introduce --space-16 (64 px) as a brand extension in BRAND_EXTENSIONS; syncs components.html :root in all three brands Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: chaoxiaoche <chaoxiaoche@chaoxiaochedeMacBook-Pro.local> Co-authored-by: Cursor <cursoragent@cursor.com> |
||
|
|
a75d9938c7 |
feat(design-systems): add structured tokens.css schema (default + kami) (#1231)
* feat(design-systems): add structured tokens.css schema (default + kami) Compile each brand's DESIGN.md prose into a machine-readable :root block agents paste verbatim, removing the "Primary → --accent" translation step where most token misuse happens. Daemon prompt injection lands in a follow-up; lint-artifact already enforces the shared token vocabulary so no rule changes needed. Schema validated across two contrasting aesthetics: - default (sans-serif, cobalt, B2B utility) — stress test the shallow form, 2-level fg / 2-level surface - kami (serif, parchment, ink-blue, print-first) — stress test the rich form, 4-level fg ramp, 3-level surface, ring elevation, i18n font stacks, and solid-hex tag tints (print renderers double-paint alpha) Schema growth from kami's stress test (5 new optional slots, all backward-compatible — default aliases via var() to existing tokens): - --fg-2 / --meta (4-level fg ramp) - --surface-warm (3-level surface) - --border-soft (2-level border) - --elev-ring (ring elevation as first-class level) Brand-specific extensions live in tokens.css with explicit "NOT in shared schema" labels and a documented promotion path (≥2 brands need it → promote to schema slot). components.html in each brand is a self-contained reference fixture that exercises every token through real layouts. Both fixtures lint clean against apps/daemon/src/lint-artifact.ts. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(design-systems): add token-fixture drift guard Each design system in design-systems/<brand>/ ships two files agents consume in tandem: tokens.css (canonical token bindings) and components.html (a self-contained fixture whose first <style> embeds the same :root paste so the file renders standalone). The fixture's :root block is a copy of tokens.css's :root block, kept in sync only by an inline comment. This adds scripts/check-tokens-fixture-sync.ts and registers it in pnpm guard. The check pairs each brand's tokens.css with its components.html and asserts the unscoped :root block is byte-equivalent after canonical normalization (CSS comments stripped, whitespace collapsed, separator spacing normalized). Brands missing one half of the pair, or with no :root rule in either file, fail the guard. Scoped overrides like :root[lang="zh-CN"] are not required to appear in the fixture (per the kami fixture's inline comment they are pasted only when an artifact's <html lang> matches), so the check only compares the unscoped :root block. Verified: pnpm guard passes for default + kami, fails on intentional value drift, fails on missing token, tolerates whitespace-only formatting differences. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(design-systems): point fixture CTAs to real files Both default and kami components.html advertised in-page anchors (#tokens, #spec, #surface, #accent, #type, #components) but defined no matching ids, so every CTA was a no-op when the fixture was opened locally — flagged by mrcfps in #1231. Re-point each link to a real artifact in the same brand directory: - "View tokens" / "Inspect tokens" / "Inspect typography" → ./tokens.css - "Read the spec" / "Read the rule" → ./DESIGN.md Browsers render these as raw source views, which is the desired UX for a reference fixture: clicking the CTA shows the underlying contract instead of jumping to nothing. Agents copying the fixture also learn the pattern of "buttons link to actual sibling resources". The :root token block is unchanged, so the token-fixture drift guard still passes for both brands. Co-authored-by: Cursor <cursoragent@cursor.com> * feat(design-systems): codify token schema (A1/A2/B/C layers) The two-brand pilot (default + kami) settled the shape of the shared token schema; this commit codifies it as a machine-readable contract and enforces it in pnpm guard, addressing lefarcen's review on #1231: > the optional-vs-required split won't generalize cleanly when brand > #3 needs different Layer A tokens or when multiple brands converge > on the same extension (promoting C→B→A). Consider surfacing that > limitation in the PR narrative or in a future SCHEMA.md. Schema lives under design-systems/_schema/ as three files: - tokens.schema.ts — TypeScript declaration of every shared token with its layer (A1-identity / A1-structure / A2 / B-slot), plus per-brand C-extension allowlists and a global C-prefix allowlist - defaults.css — CSS mirror of A2 fallback values, used as the human-readable contract reviewer's-eye copy and the future input to the derive script - AGENTS.md — schema layer model, C → B-slot → A2 promotion rules, when-not-to-add-a-token guidance Layer model: A1-identity 8 tokens — bg/surface/fg/muted/border/accent + font-display/font-body. The brand IS these values; no fallback is defensible. A1-structure 18 tokens — type scale (8), leading (2), tracking (1), section-y (3), container (4). Structural decisions vary per brand by design and have no cross-brand default. A2 26 tokens — accent states, semantic colors, motion, base spacing scale, radius, elevation, focus, font-mono. Required in every tokens.css; fallback lives in defaults.css for the future derive script to inline when DESIGN.md does not specify the value. B-slot 4 tokens — fg-2 / meta / surface-warm / border-soft. Brand may bind independently or alias the named sibling via var(...) for components that target the richer ramp. C-extension n tokens — brand-specific names (kami's tag-bg-*, leading-display, accent-light, etc.). Allowlisted per-brand in BRAND_EXTENSIONS or globally by prefix in BRAND_EXTENSION_PREFIXES. Promote when a second brand adopts the same name. Why A2 fails the guard today: Artifacts are generated by agents pasting one brand's :root block into a single <style>; there is no global stylesheet that supplies fallbacks at runtime. A tokens.css missing an A2 declaration would silently break any var() reference in the fixture. Until the derive script (PR-B) lands and inlines defaults, every brand's tokens.css must declare every A2 token directly. The guard enforces this strictly. Why --font-mono lands in A2 (not A1): 149 brands' DESIGN.md files were surveyed: 87 (58%) declare a monospace stack, 62 (42%) do not — including major brands like bmw / nike / apple / notion / mastercard / meta. Agent paste cannot rely on the brand author having written it down; a defaultable A2 fallback (with CJK brands like kami overriding) is safer than forcing every brand author to add a field they may not realize their kbd / code-block components need. Five guard checks, each registered as its own entry in scripts/guard.ts so failures attribute to a specific contract: 1. token-fixture sync — components.html :root ↔ tokens.css :root byte-equivalent (existing) 2. A1 required tokens — every brand declares every A1 token 3. A2 required tokens — every brand declares every A2 token 4. unknown token allowlist — every declared token is in schema or brand-extension allowlist 5. A2 defaults parity — defaults.css ↔ tokens.schema.ts fallback byte-equivalent Verified on default + kami: - 26 A1 tokens declared in both brands - 26 A2 tokens declared in both brands - 129 total declarations, all match shared schema or brand extensions - defaults.css ↔ tokens.schema.ts parity holds - sanity test: drifting --motion-fast in defaults.css fails check 5 with a clear divergence message The PR description originally listed "Dedicated SCHEMA.md" as explicitly NOT in this PR ("Once 3+ brands ship, extracting a single source of truth becomes worthwhile"). That boundary moves: lefarcen's review surfaced the schema-generalization risk, and the schema must exist as a machine-enforced contract before the derive script can read it. The TS file replaces the markdown that was deferred. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(web/tests): pass missing designTemplates prop to ProjectView Pre-existing typecheck regression on main: PR #955 ( |