* docs(pr): require user-perspective description and surface area
The previous template asked for Summary + Validation, which encouraged
code-perspective descriptions and let user-visible surface changes slip
past review unnoticed. Replace with:
- "Problem" — issue link + motivation
- "What users will see" — first-person user-visible effect
- "Surface area" — 9-item checklist (UI, shortcut, CLI/env, API/contract,
extension point, i18n, top-level dependency, default behavior change, none)
- "Screenshots" — required when UI surface is checked, focused on the
entry point users discover rather than the feature in isolation
- "Validation" — kept, retitled away from "Summary"
Authoritative rules added to AGENTS.md under a new "Pull request expectations"
section so external contributors' agents (Claude Code, Cursor, etc.) pick up
the requirement when reading the repo. CONTRIBUTING.md gets one pointer line
in "Commits & pull requests"; localized CONTRIBUTING variants (zh-CN, de, fr,
ja-JP, pt-BR) are left for follow-up translation PRs per the existing
docs-update workflow.
The existing "Fixes #" prompt is preserved verbatim — that template addition
from #1263 enforces PR-to-issue auto-linking and stays load-bearing.
* docs(pr): broaden dependency surface to dev deps as well
The "New top-level dependency" checkbox narrowed scope to runtime deps,
but CONTRIBUTING.md L239 says "No new top-level dependencies" without
limiting to runtime, and the AGENTS.md rule uses the same broad phrase.
A new devDependency (tool/test/build package) belongs in the same
bytes-vs-benefit explanation, so the checklist item should match.
* docs(pr): add Why and Bug fix verification; scope deps to root package.json
Three follow-up tweaks from review feedback:
1. Rename `## Problem` to `## Why` with a broader prompt that asks
contributors to cover both their own use case (what made them write this
PR today) and the pain being addressed. The old "Problem" framing only
covered user-facing motivations and left no slot for the contributor's
stake — a key signal for triaging external PRs.
2. New `## Bug fix verification` section between Screenshots and Validation,
conditional on the PR being a bug fix. Surfaces the AGENTS.md
"Bug follow-up workflow" red-spec requirement at PR-authoring time
instead of leaving it implicit; asks for the test path and the
red-on-main / green-on-branch confirmation.
3. Clarify the "New top-level dependency" checkbox to specify the **root**
`package.json`. Without that word, contributors in a monorepo could read
the check as applying to any workspace `package.json` (e.g. adding `react`
to `apps/web/package.json` would be in scope) when CONTRIBUTING.md L239's
"small on purpose" rule clearly meant root-level deps only.
AGENTS.md `## Pull request expectations` and CONTRIBUTING.md's pointer
line are updated to match the new section names and add the bug-fix
red-spec expectation.
* docs: add Windows troubleshooting guide (#478)
Add docs/windows-troubleshooting.md with step-by-step fixes for the
most common native-Windows setup errors:
- Node 24 / nvm-windows gotchas (fake nvm file in System32)
- pnpm not found after installation
- Build scripts blocked by pnpm 10 (better-sqlite3, sharp)
- Visual Studio / gyp build errors
- Starting the dev server
- Optional OpenCode CLI setup
Also update CONTRIBUTING.md and QUICKSTART.md to link to the new
guide instead of the vague "file an issue if it doesn't" note.
* docs: fix Windows guide command accuracy (#1170)
Address all 6 inline review comments from lefarcen:
- Pin npm-global pnpm install to @10.33.2 (matches packageManager field)
- Use where.exe instead of bare where (PowerShell alias conflict)
- Fix OpenCode package: opencode-ai (not opencode), binary is opencode
- Add EPERM fallback note for corepack enable on protected installs
- Add Python check for gyp ERR! find Python
- Expand diagnostic checklist with corepack, python, execution policy
Also remove redundant corepack pnpm --version from checklist.
Adds a public set of rules for the External Maintainer role: who qualifies,
how nominations work, what permissions Maintainers gain, what's expected
of them, and how step-down works.
The Core Team's individual roster is intentionally not enumerated. What's
public is the rules everyone plays by.
- New file: MAINTAINERS.md (English authoritative version) + 5 locale variants
matching the existing CONTRIBUTING.md i18n surface (de, fr, ja-JP, pt-BR,
zh-CN). Non-EN/non-zh-CN variants are machine-translated drafts marked at
the top — native-speaker review is welcome via follow-up PRs.
- CONTRIBUTING.md (and its 5 locale variants): adds a short
Becoming a Maintainer section that points at MAINTAINERS.md, so the
rules live in one place and translation drift is bounded.
Decisions not in this PR (intentional):
- No internal Core Team roster.
- No internal observability dashboards.
- No nomination PR / public voting flow (Core-Team-consensus-driven for now;
to be revisited once External Maintainers exceed 5).
Co-authored-by: Joey Li <lijinwei@open-design.ai>
* docs: add skills contributing guide
External skill PRs are coming in faster than we can write per-PR
acceptance feedback, and the existing skill section in CONTRIBUTING.md
gave contributors the merge bar without showing the dev loop or the
patterns we routinely close on. This adds a dedicated guide that
contributors land on before opening a PR.
- New docs/skills-contributing.md (the how-to): quick start, anatomy,
local dev loop, merge bar checklist, PR description template, and
the eight rejection patterns we've actually used recently.
- CONTRIBUTING.md "Adding a new Skill" shrinks from 73 lines to ~20
and points at the new guide. Skill section was the longest in the
file; trimming it keeps the four i18n variants easier to maintain.
- skills/README.md is new — first thing a contributor sees when they
open the skills/ folder. Routes them to the contributor guide and
the protocol spec.
- docs/skills-protocol.md gets a cross-link at the top so readers who
land on the protocol can find the contributor flow.
Discovery is the point: any path a contributor takes (CONTRIBUTING.md,
skills/ folder, protocol spec) now routes to the same single guide.
* docs(skills-contributing): expand modes to 7, fix broken checklist link
Both flagged by review on #1035:
- The mode enumeration listed 4 modes (prototype | deck | template |
design-system) but apps/daemon/src/skills.ts:24 actually defines 7
(adds image | video | audio), with shipped media skills under
skills/{image-poster,video-shortform,audio-jingle}. Updates every
enumeration in skills-contributing.md (frontmatter cheat sheet, PR
template, running-locally instructions, IS-list) and skills/README.md.
- The merge-bar checklist pointed at skills/dating-web/references/
checklist.md as an example, but that path doesn't exist on this
branch — dating-web ships only SKILL.md + example.html. Repointed
at skills/web-prototype/references/checklist.md, which is the
closest prototype-mode skill that actually ships a checklist.
Adds a "Media skills (image / video / audio)" line to the references
section pointing at the three shipped media skills as imitate-able
starting points.
* docs(skills-contributing): address review — i18n bar, external skills, daemon refresh
Three findings from review on #1035:
P1 — i18n merge-bar mismatch (line 172 of original)
e2e/tests/localized-content.test.ts:144 enforces skills.toEqual(skillIds)
for every locale, so a non-featured skill PR following the previous
guidance ("no edits to apps/web/src/i18n/") would fail CI on the
`skills display copy` assertion.
Fix:
- "Single self-contained folder" item now explicitly carves out the
*_SKILL_IDS_WITH_EN_FALLBACK line as a required outside edit.
- New "i18n coverage (every skill, not just featured)" subsection
directs contributors to add their id to all three fallback arrays
(DE / FR / RU) — bare id, no TODO comment per existing convention.
- "Featured skills" subsection now describes replacing the fallback
with full localized copy, instead of being the only path that
touches i18n.
- PR template Validation list adds the fallback-arrays step as a
required checkbox for every skill PR.
P2 — daemon does not auto-watch skills/ (line 139 of original)
apps/daemon/src/skills.ts:2 explicitly states "No watching in this MVP
— re-scans on every [/api/skills call]". Previous wording about chokidar
was aspirational, not current behavior.
Fix: replaced with "refresh the picker — the daemon re-scans skills/ on
every /api/skills request" + restart escape hatch for parse failures.
P2 — missing alternative for vendor workflows (line 60 of original)
Previous "No" list pointed contributors at heavier daemon/feature paths
for vendor-specific workflows, ignoring that skills-protocol.md §3
supports user-global skills via ~/.claude/skills/. Concrete cases like
payment-provider and regional-marketplace skills (which we've been
closing as out-of-scope) actually fit the external-bundle path.
Fix: added a "Third option: ship as an external skill bundle" paragraph
before the discussions CTA, linking to the protocol's discovery section.
* chore: enforce test directory conventions
Move package, app, and tool tests out of src and add guard enforcement so source directories stay source-only.
* ci: use guard and package-scoped tests
Run the new repository guard in CI and keep test execution aligned with package-scoped commands after removing root aliases.
* ci: align stable release guard check
Use the new repository guard in stable release verification after replacing the residual-JS-only script.
* chore: tighten test layout enforcement
Enforce sibling tests directories, typecheck moved test suites with dedicated configs, and refresh remaining guidance that pointed at src-based tests.
* chore: clarify no-emit test tsconfigs
Explicitly disable declaration-only emit in test tsconfigs so review tooling sees they are no-emit typecheck configs.
* docs: add Brazilian Portuguese (pt-BR) translations
Translate README, CONTRIBUTING, QUICKSTART, and the e2e/cases,
e2e/reports, skills/html-ppt, skills/guizang-ppt READMEs into pt-BR.
Add the pt-BR entry to the language switcher in every existing locale
variant (en, de, fr, ko, ja-JP, ru, uk, zh-CN, zh-TW for README; en,
de, fr, ja-JP, zh-CN for CONTRIBUTING; en, de, fr, ja-JP for
QUICKSTART) so readers in any language can jump to the Portuguese
version. Code blocks, file paths, identifiers, license attribution
links and brand names are kept verbatim with the source.
* docs(pt-BR): use repo-relative links in e2e READMEs
Replace author-local absolute paths (/Users/mac/...) with repo-relative links so the translated docs navigate correctly on GitHub and other checkouts.
* docs(pt-BR): fix README badge anchor and skill reference link
- Update Agents badge href to the Portuguese fragment (#agentes-de-código-suportados) so the badge jumps to the translated heading.
- Restore the [`SKILL.md`][skill] reference-link syntax in the comparison table; the opening bracket was lost in translation, breaking the row.
* fix(web,daemon): make max_tokens configurable (closes#29)
BYOK users on custom Anthropic-compatible providers (e.g. Xiaomi MiMo)
hit the hardcoded 8192 cap and saw artifacts truncated mid-stream.
- AppConfig.maxTokens with Settings input (EN/CN + 8 other locales)
- ProxyStreamRequest.maxTokens contract field
- anthropic, anthropic-compatible, and openai-compatible providers all
forward cfg.maxTokens
- /api/proxy/anthropic/stream and /api/proxy/stream payloads honor it,
defaulting to 8192 when unset so prior clients are unaffected
Original sketch by @mashu in #78 (50a9d14); rebased to the apps/web
layout and extended to the proxy paths actually used when baseUrl is
set, which is where #29's user actually traffics.
* feat(web): per-model max_tokens defaults
Adds a hand-maintained MODEL_MAX_TOKENS table (Claude 4.5 line → 64k,
mimo-v2.5-pro → 32k) and an effectiveMaxTokens helper layered over the
override field added in 6a3ae5f, so #29's user — and others on supported
models — don't have to discover Settings to avoid mid-stream truncation.
- apps/web/src/state/maxTokens.ts: lookup + helpers
- providers/{anthropic,anthropic-compatible,openai-compatible}.ts:
forward effectiveMaxTokens(cfg) instead of cfg.maxTokens ?? 8192
- SettingsDialog: input becomes an optional override (blank = default,
shown as placeholder)
- 10 locale hint strings updated to the new semantics
* feat(web): vendor LiteLLM model metadata for max_tokens defaults
Replaces the 4-entry hand-rolled MODEL_MAX_TOKENS map from 544e67e with
a vendored slice of BerriAI/litellm's model_prices_and_context_window
JSON (1970 chat models, ~97KB raw / ~25KB gzip). Future model launches
land in maxTokens.ts via `pnpm sync-litellm-models` instead of manual
edits.
- scripts/sync-litellm-models.ts: fetches the upstream JSON, filters to
chat-mode entries, projects each entry to its max_output_tokens (or
max_tokens fallback), and writes a sorted, license-attributed JSON
- apps/web/src/state/litellm-models.json: generated artifact, committed
- apps/web/src/state/maxTokens.ts: lookup is now
OVERRIDES → LITELLM_MODELS → FALLBACK_MAX_TOKENS. The OVERRIDES table
shrinks to just `mimo-v2.5-pro` (LiteLLM only ships MiMo via
OpenRouter/Novita aliases, not the canonical id Xiaomi's API uses).
LiteLLM is MIT-licensed (BerriAI/litellm/blob/main/LICENSE); attribution
is preserved in both the script header and the generated JSON's
_license field.
* test(web,docs): cover maxTokens lookup + document sync workflow
- apps/web/src/state/maxTokens.test.ts: six vitest cases pinning the
three-tier lookup (override → LiteLLM → fallback) and the
effectiveMaxTokens user-override path. Guards against a future sync
silently dropping the Anthropic 4.5 entries we rely on.
- CONTRIBUTING.md / CONTRIBUTING.zh-CN.md: new "Updating model
max_tokens metadata" section pointing future maintainers at
scripts/sync-litellm-models.ts and explaining when OVERRIDES is
appropriate (it's the rare exception, not the default).
* fix(web): mark Max tokens label as optional in 10 locales
The Settings field is optional (blank means "use the per-model default")
but the label gave no visual cue, breaking the implicit pattern that
every other API-mode field (key/model/baseUrl) is required. Append
"(optional)" — using the locale's natural parenthetical convention
(Chinese full-width brackets, Japanese 任意, Russian опционально, etc.)
— so the field reads as discretionary at a glance.
* fix(web): validate maxTokens override against advertised UI bounds
Addresses Siri-Ray's review on commit 0d98185. The Settings input
declares min={1024}/max={200000}/step={1024}, but until now
effectiveMaxTokens trusted any defined cfg.maxTokens, so a stale or
hand-edited localStorage value (negative, zero, fractional, billions)
would pass straight to the Anthropic SDK on the direct path while the
daemon proxy quietly clamped it back to 8192 on the proxied path —
same config, divergent behavior depending on route.
- maxTokens.ts: add MIN_MAX_TOKENS / MAX_MAX_TOKENS exports and
isValidOverride helper. effectiveMaxTokens only honors the override
when it is a finite integer in [1024, 200000]; otherwise falls back
to modelMaxTokensDefault.
- SettingsDialog.tsx: input bounds now reference the same constants so
the UI promise can't drift from the runtime check.
- maxTokens.test.ts: six new cases pinning the rejection of negative,
zero, sub-MIN, super-MAX, non-integer (fractional / NaN / Infinity)
overrides plus the inclusive MIN/MAX boundaries.
The daemon proxy's existing `> 0` fallback stays as defense-in-depth.
* docs: add TRANSLATIONS.md i18n contribution guide
Captures the implicit conventions around adding a new locale: which
files to touch (types.ts, locales/, index.tsx, READMEs), how to keep
the language switcher synchronized across all README variants, the
backport policy, and a starter zh-CN ↔ zh-TW glossary extracted from
PR #194.
Resolves the action item from #195. CONTRIBUTING.md cross-links into
this file from its existing "Localization maintenance" section.
The "Open questions" section is intentionally preserved as a signal to
future contributors that translation memory tooling, drift detection,
and freshness badges are live design discussions.
* docs(translations): address review feedback from #196
- Standalone-file rationale: add inline paragraph (lefarcen #196:5)
- Maintained-locales table: add Status column, mark zh-TW README as
in-flight via #194 instead of claiming it exists, clarify ja/ko as
README-only (codex #196:28, lefarcen #196:23)
- Step 4: include the import line + DICTS map example so contributors
don't hit a TS error after copy-paste (lefarcen #196:54)
- Step 6: drop the impossible "order by LOCALES" rule — switcher set is
the union of UI-dict and README-only locales, ordering must just stay
consistent across all READMEs (codex #196:61)
- Backport policy: define a concrete drift threshold (≥20 keys OR
6 months), reference the deferred CI follow-up (lefarcen #196:70)
- Stale-locale signal: add concrete artifacts — table marker +
frontmatter comment (lefarcen #196:77)
- Glossary: split Core (OpenCC-handled) from Idiomatic (judgment calls)
and add the missing rows from #194 — 兜底/活的/計畫/色票/規格文件/介入修正/出包/捆綁→納入
(lefarcen #196:93)
- Native-speaker review: ground "~7 days" as starting point, not hard
policy; move it to Open questions for future tuning (lefarcen #196:128)
- Resolve TM-tooling contradiction by introducing a "Deferred decisions"
section — distinguishes "decided to defer" from "still open"
(lefarcen #196:137)
* feat(dev): add desktop tools-dev control plane
* refactor(sidecar): split Open Design contracts
Move Open Design-specific sidecar protocol definitions into @open-design/contracts so sidecar and platform can remain descriptor-driven primitives.
* refactor(daemon): organize package sources
Keep daemon app code, tests, and sidecar entrypoints in separate package directories so each layer can be built and verified independently.
* chore(repo): streamline maintenance entrypoints
Centralize agent guidance by directory and reduce root command chains while preserving the existing build scope.
* docs: translate agent guidance to English
* fix(sidecar): tolerate stale IPC sockets
Remove stale Unix socket files only after confirming no listener is active, so tools-dev can restart after unclean shutdowns.
* Refactor project name from "Open Claude Design" to "Open Design"
- Updated project name in package.json, package-lock.json, and README files.
- Changed CLI commands and references from "ocd" to "od".
- Adjusted file structure references in documentation and code to reflect new naming conventions.
- Enhanced .gitignore to include new runtime data files.
- Updated metadata in LICENSE file to match new project name.
* chore: migrate frontend toolchain from Vite to Next.js 16 App Router
Replace the Vite SPA scaffold with Next.js 16 App Router while keeping
the existing daemon as the API/SSE/sqlite backend. The whole client
tree now mounts under a single optional catch-all route
(app/[[...slug]]) loaded with ssr:false; static export emits one shell
HTML the daemon serves as the SPA fallback for deep links. Dev uses
next.config rewrites to proxy /api, /artifacts, /frames to the daemon,
matching the previous Vite setup.
Made-with: Cursor
* fix: address Next migration review feedback
* fix: serve static export in preview script
---------
Co-authored-by: mrcfps <mrc@powerformer.com>
* Refactor project name from "Open Claude Design" to "Open Design"
- Updated project name in package.json, package-lock.json, and README files.
- Changed CLI commands and references from "ocd" to "od".
- Adjusted file structure references in documentation and code to reflect new naming conventions.
- Enhanced .gitignore to include new runtime data files.
- Updated metadata in LICENSE file to match new project name.
* Add contributing guidelines in English and Chinese
- Introduced CONTRIBUTING.md and CONTRIBUTING.zh-CN.md to provide clear instructions for contributors.
- Outlined contribution types, local setup instructions, and merging criteria for skills and design systems.
- Enhanced README files to reference the new contributing guidelines.