mirror of
https://github.com/nexu-io/open-design.git
synced 2026-10-27 09:51:12 +01:00
chore/codex-exec-path-fix
326
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
5a0f954297 |
fix(daemon): emit tool_use from tool_execution_start in pi-rpc (#186)
* fix(daemon): emit tool_use from tool_execution_start in pi-rpc The pi-rpc adapter emitted tool_use from message_end, which fires before tool execution starts. The web UI pairs tool results to prior tool_use events, so receiving tool_result without a preceding tool_use broke tool card rendering and file auto-open behavior. Move tool_use emission to tool_execution_start, matching the pattern in copilot-stream.ts. Remove redundant tool call extraction from message_end (tool_use is now emitted at execution time, usage is already emitted from turn_end). Extract mapPiRpcEvent as a pure exported function so tests exercise the real event mapping logic instead of an inlined copy that can diverge from production. Ref: mrcfps review comments on PR #117 * docs(daemon): clarify mapPiRpcEvent mutability contract The function mutates ctx.sentFirstToken to track streaming state. Calling it "pure" is misleading; revised the doc comment to say no I/O or child process interaction instead. * fix(pi-rpc): remove redundant status(tool) emission from tool_execution_start Now that tool_use fires inline from tool_execution_start, the accompanying status(tool) event is redundant: tool_use already carries the tool name, and the UI renders running state from the tool card. The extra status pill breaks consecutive tool_use grouping in AssistantMessage.buildBlocks. Aligns with copilot-stream, which emits only tool_use from tool.execution_start with no status event. |
||
|
|
d58b07fdad |
feat(daemon): auto-detect OpenClaude as a fallback for Claude Code (#263)
Today open-design detects code agents by exact PATH binary name (`claude`, `codex`, `gemini`, …). OpenClaude (https://github.com/Gitlawb/openclaude) is an argv-compatible Claude Code fork that ships under the binary name `openclaude`, so users with only `openclaude` installed see "Claude Code: not detected" and have to write a wrapper script (issue #235, "Path B" workaround). This change adds a generic fallback-bin mechanism and uses it to declare `openclaude` as a Claude Code fallback: - `AGENT_DEFS[claude]` gains `fallbackBins: ['openclaude']` — a new optional declarative slot. Agents without a fallback are unchanged. - `resolveAgentExecutable(def)` is a new exported helper that walks `[def.bin, ...def.fallbackBins]` and returns the first PATH hit, or null. The two existing `resolveOnPath(def.bin)` callsites in `probe()` and `resolveAgentBin()` route through this helper instead of reading `def.bin` directly. - `stripFns()` is extended to drop `fallbackBins` from the API response payload — same posture as `helpArgs` / `capabilityFlags` / probe-only metadata that shouldn't bleed into the public agents list. Behavior contract: - If both `claude` and `openclaude` are on PATH, `claude` still wins (the order in the candidate list matters). - If only `openclaude` is on PATH, the agent shows up as "Claude Code" and chat / model-listing / spawning all use the resolved openclaude path. Users don't need wrappers and the agent picker stays a single "Claude Code" entry instead of confusingly splitting into two. - Agents with no `fallbackBins` field (codex / gemini / opencode / …) resolve via `def.bin` exactly as before. Why fallback (not a separate AGENT_DEFS entry): The issue author explicitly preferred the fallback shape over a second top-level "OpenClaude" entry, and OpenClaude is a verbatim Claude Code fork — the buildArgs / fallbackModels / streamFormat / capabilityFlags would all be duplicated. A new `fallbackBins` slot keeps the Claude config single-sourced and lets future drop-in forks be added with one extra string. Test coverage (5 new tests in `tests/agents.test.ts`): 1. `claude.fallbackBins` includes `'openclaude'` — declarative regression guard so the AGENT_DEFS entry can't silently drift back. 2. `resolveAgentExecutable` prefers `def.bin` when both candidates are present (primary always wins). 3. `resolveAgentExecutable` falls back through `fallbackBins` when `def.bin` is missing (the OpenClaude-only install case). 4. `resolveAgentExecutable` returns null when no candidate is on PATH. 5. `resolveAgentExecutable` handles defs with no `fallbackBins` field (no-regression guard for codex / gemini / opencode / …). The 4 filesystem-backed cases skip on Windows because resolveOnPath walks PATHEXT extensions there and the fixture files don't carry them; the declarative AGENT_DEFS assertion runs on every platform. All 230 daemon tests pass locally (was 225 before this PR). Closes #235 |
||
|
|
b9d8bd36b9 |
fix(daemon): treat .py files as previewable code in Design Files (#261)
Python files in Design Files cannot be previewed inline today: the side panel falls back to BinaryViewer and users can only download or open externally, even though `.py` is plain text and reasonable to inspect in-app. Root cause: `kindFor()` in `apps/daemon/src/projects.ts` (line 278) classifies files into coarse buckets the frontend uses to pick a viewer. The `'code'` branch lists `.js / .mjs / .cjs / .ts / .tsx / .json / .css` but not `.py`, so Python files fall through to `'binary'`. The frontend already renders the `'code'` bucket via `TextViewer` in `apps/web/src/components/FileViewer.tsx`, so once a file lands in the `'code'` bucket it gets the existing read-only code preview for free. Fix: add `'.py'` to the `'code'` extension list. No frontend change needed — `TextViewer` handles it on receipt. Scope: this PR keeps the change minimal to match the issue (`.py` only). Other commonly-requested text-like extensions (`.yaml / .yml / .toml / .sh`, plus other code languages) can be added in a follow-up if maintainers want that surface area. Closes #61 |
||
|
|
bb11c68b9f |
fix(i18n): replace hardcoded 'Claude' with '助手' in zh-TW assistant role (#262)
Spotted by @lefarcen in #59 follow-up review: while every other locale file has been switched to a neutral, localized assistant label (`Assistant` / `助手` / `アシスタント` / `Assistent` / `Assistente` / etc.), `zh-TW.ts` still hardcodes `'Claude'` for `'assistant.role'`. That string is the per-message fallback used by `assistantRoleLabel()` in `apps/web/src/components/AssistantMessage.tsx` when no agent metadata is attached to a turn — so on Traditional Chinese installs running Codex / Cursor / Gemini / OpenCode, the older message rows can still render as "Claude" instead of a neutral label. Fix: align zh-TW with zh-CN by setting `'assistant.role': '助手'`. The character `助手` is identical in Simplified and Traditional Chinese, so this matches the rest of the locale file's register without introducing any character-form drift. Refs #59 |
||
|
|
06b1492744 |
Standardize agent communication via stdin and remove Windows-specific shims logic (#258)
This change moves Claude Code and GitHub Copilot CLI to stdin-based prompt delivery, aligning them with other agents. By doing so, we can bypass OS command-line length limits on Windows and set shell: false universally, improving security and robustness. Integration of createCommandInvocation ensures that Windows npm shims (.cmd/.bat) are correctly handled while keeping shell: false, addressing the P1 warning from the automated review and maintaining consistent execution across platforms. |
||
|
|
52677555f7 |
fix(daemon): include package.json in tarball so packaged app reports correct version (#260)
The packaged app's Settings → About page displays version `0.0.0` instead
of the actual release version because the daemon's `package.json` was
excluded from its `pnpm pack` tarball.
Root cause: `apps/daemon/package.json` declares `"files": ["dist"]`, so
`pnpm pack` only includes the `dist/` directory. At runtime,
`readCurrentAppVersionInfo()` in `apps/daemon/src/app-version.ts` resolves
`new URL('../package.json', import.meta.url)` from the compiled
`dist/app-version.js`, which points at the tarball's root `package.json`.
Because that file isn't packed, the read fails silently, falls through
the catch in `readPackageMetadata()`, and the version falls back to the
`APP_VERSION_FALLBACK = '0.0.0'` constant. `/api/version` and
`/api/health` then report `'0.0.0'` for every packaged install.
Fix: add `"package.json"` to the daemon's `files` array so it ships in
the tarball. The package already declares `"./package.json"` as an
exports entry, so consumers expect this file to be available.
Closes #224
|
||
|
|
0e166bb799 | Optimize Electron release artifact size (#249) | ||
|
|
c2b3d737f2 |
fix: make max_tokens configurable (closes #29) (#78)
* 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 |
||
|
|
27ef18b7c0 |
fix(web): suppress hydration warning on <body> (#248)
Browser extensions (e.g. YouMind, Grammarly, ColorZilla) inject attributes onto <body> before React hydrates, producing a "server rendered HTML didn't match client" console error in dev. `<html>` already had suppressHydrationWarning; mirror it on `<body>` so any extension that targets the body element no longer surfaces a false-positive hydration mismatch to end users. Closes #243 |
||
|
|
ee753fa365 | feat(i18n): add Korean (ko) localization (#253) | ||
|
|
f863c484a4 |
fix(web): add scroll to settings language menu when it overflows view… (#247)
* fix(web): add scroll to settings language menu when it overflows viewport The language picker dropdown in the settings dialog opens upward but had no max-height constraint, causing top options to be clipped off-screen. Add max-height with overflow-y: auto and switch from bottom to top + transform positioning so the scrollbar actually activates. * docs(web): add comment explaining language menu max-height magic numbers * fix(web): constrain language menu height to available space above trigger The previous translateY(-100%) approach clipped the menu above the viewport when the trigger was near the top edge. Switch to bottom positioning with a JS-computed CSS variable (--menu-available-h) so the menu height never exceeds the distance to the viewport top. |
||
|
|
3d306cb450 |
Add React artifact output support (#121)
* Add React artifact output support Generated-By: looper 0.2.7 (runner=worker, agent=codex) * Fix React component artifact preview repairs Generated-By: looper 0.2.7 (runner=fixer, agent=codex) * fix: address React preview review feedback Generated-By: looper 0.2.7 (runner=fixer, agent=codex) |
||
|
|
0bafc73d24 |
Add visible conversation timestamps (#120)
* Add visible conversation timestamps Generated-By: looper 0.2.7 (runner=worker, agent=codex) * Fix assistant message timestamps Generated-By: looper 0.2.7 (runner=fixer, agent=codex) |
||
|
|
85032f530c |
fix(web): preserve deck preview pagination per file (#119)
Generated-By: looper 0.2.7 (runner=worker, agent=codex) |
||
|
|
4e3d82cdcd |
Fix deck preview pagination controls (#112)
* fix: correct deck preview pagination controls Generated-By: looper 0.2.7 (runner=worker, agent=codex) * fix: correct deck preview pagination controls Generated-By: looper 0.2.7 (runner=fixer, agent=codex) |
||
|
|
266daf904f |
feat(prompt-templates): add 11 HyperFrames video prompts + media generation README section (#227)
* feat(prompt-templates): add 11 HyperFrames video prompts and surface media generation in README Adds eleven `hyperframes-*` prompt templates under `prompt-templates/video/`, each one a concrete brief with scene-by-scene timing, GSAP eases, palette, and the HyperFrames non-negotiables (deterministic, paused timelines, entrance-only motion, lint/inspect commands). Archetypes covered: - minimal product reveal (5s, 16:9) - SaaS product promo (30s, 16:9, Linear/ClickUp-style) - TikTok karaoke talking-head (9:16, TTS + word-synced captions) - brand sizzle reel (30s, beat-synced kinetic typography) - animated bar-chart race (NYT-style data infographic) - Apple-style flight map route (origin → destination) - 4s cinematic logo outro - $0 → $10K money counter hype (9:16) - 3-phone app showcase - 9:16 social overlay stack (X · Reddit · Spotify · Instagram) - 15s website-to-video pipeline Each template uses `model: "hyperframes-html"`, real catalog-block thumbnails from HeyGen's CDN as previewImageUrl, and source attribution to `heygen-com/hyperframes` (Apache-2.0). README also gets a new **Media generation** section between *Visual directions* and *Beyond chat*, plus a new row in the *At a glance* table. The section documents the three model families currently surfaced as templates (gpt-image-2, Seedance 2.0, HyperFrames) with example galleries — gpt-image-2 thumbnails, Seedance MP4-linked thumbnails, and the 11 HyperFrames tiles — and notes the wider model coverage (Kling, Veo, Sora, MiniMax, Suno, Udio, Lyria, TTS) already wired in `VIDEO_MODELS` / `AUDIO_MODELS_BY_KIND` and open for community templates. * i18n(de): register new HyperFrames templates, categories, tags Adds German titles/summaries for the 11 new hyperframes-* video templates plus the Product/Marketing/Data/Travel/Branding/Short Form categories and hyperframes/title-card/sizzle/etc. tags they introduce, so the German sync guarantees enforced by apps/web/src/i18n/content.test.ts hold. * docs(readme): sync Media generation section to de / ja / ko / zh-CN; bump counts to 93 (43 + 39 + 11) Mirrors the English Media generation row + section into the four locale READMEs (README.de.md, README.ja-JP.md, README.ko.md, README.zh-CN.md), translating prose / table headers / captions while keeping the gpt-image-2, Seedance MP4, and HyperFrames catalog-block thumbnails identical across all five locales so the galleries render the same images. Counts updated to reflect current main (after rebase): 43 gpt-image-2 + 39 Seedance + 11 HyperFrames = 93 prompts total. The English README's At-a-glance row, intro paragraph, and gallery sub-headers now read "sample of 43" / "sample of 39" / "11 ready-to-replicate templates" — locales follow. Resolves the Codex review's German-i18n flag end-to-end: README copy is in sync, and the German content map (DE_PROMPT_TEMPLATE_*) was already extended in the prior commit on this branch. |
||
|
|
56aa985b1a |
feat(design-systems): integrate kami as editorial paper system + deck starter (#226)
* feat(design-systems): integrate kami as editorial paper system + deck starter - Add design-systems/kami/DESIGN.md adapting kami's tokens, ten invariants, and type/color/component rules into the OD DESIGN.md spec. Lands under a new "Editorial & Print" category in the picker. - Add templates/kami-deck.html: a kami-flavored variant of deck-framework.html (parchment canvas, ink-blue accent, single-weight serif) with five demo slides — cover, agenda, metric row, two-column body+pull-quote, closing — so it doubles as a worked example for slide and prototype work. - Update design-systems/README.md and README.md to list and credit kami (MIT, tw93/kami). - Update apps/web/src/i18n/content.ts so the i18n coverage test passes: add the German summary for 'kami' and the 'Editorial & Print' category. * docs(design-systems/kami): address PR #226 review notes Five P3 polish edits from @lefarcen's review (LGTM, non-blocking): 1. Add a "When to swap the stack" subsection in §3 spelling out how the three CJK font stacks combine: set the dominant-language stack on :root, scope per-section overrides for mixed-language artifacts, never chain all three families inside one font-family declaration. 2. Reframe the brand as "kami / 紙 / 纸" so the system reads as co-designed across EN, zh-CN, and ja from the start, not Japan-centric with i18n bolted on. Title and §1 lede updated. 3. Reconcile the pt → px ratios into one table at the top of §3 "Hierarchy": print pt × ~1.33 for page artifacts, × 1.6 for slide macro tokens, × 0.6 for slide micro tokens. Drop the duplicate ratio bullets from §5 "Slides". 4. Keep the soft tag-brush gradient exception but make it real: add the .tag.brush CSS + an inline <span class="tag brush"> example in §4, and surface it once on slide 04 of the kami deck so agents see exactly when the carve-out applies. 5. Add a "Tabular-nums contexts" subsection in §3 enumerating every place numbers should opt into tabular-nums (metrics, footers, section numbers, dates, financial tables, KPI grids, version numbers, side-by-side comparisons) — and the rule for when not to (single numbers in running prose). |
||
|
|
f4ab52d9dd |
feat(skills): integrate lewislulu/html-ppt-skill + 15 per-template Examples cards (#193)
* feat(skills): integrate lewislulu/html-ppt-skill as html-ppt + 15 per-template Examples cards
Bring the MIT-licensed lewislulu/html-ppt-skill upstream into skills/html-ppt/
with its full asset tree (36 themes, 31 single-page layouts, 27 CSS + 20
canvas-FX animations, runtime + presenter mode, all 15 full-deck templates,
and the upstream LICENSE preserved verbatim).
Surface each full-deck template as its own Examples gallery card via thin
wrapper skills under skills/html-ppt-<template>/. Each wrapper ships:
- SKILL.md with `od.mode=deck`, scenario, `featured: 20-34` (slotting after
the existing curated cards), an `od.example_prompt` tuned to the template,
and `od.upstream` pointing at the upstream repo. Clicking "Use this prompt"
on a card now wires up `kind=deck` + `speakerNotes=true` and seeds the
composer with the upstream's authoring flow so the prompt -> output path
matches the upstream demo.
- example.html baked self-contained (fonts/base/animations/style/theme CSS
inlined, runtime <script> stripped) so the gallery srcdoc iframe renders
the upstream look without external paths.
scripts/scaffold-html-ppt-skills.mjs and scripts/bake-html-ppt-examples.mjs
are idempotent generators — re-run after editing skills/html-ppt/ to re-sync
all per-template wrappers and their baked examples.
Add a Credits section + extend the License section in README.md /
README.zh-CN.md / README.ko.md to credit the upstream alongside the
already-cited op7418/guizang-ppt-skill.
* fix(scripts): allowlist html-ppt skill JS for residual-js check
Add scripts/bake-html-ppt-examples.mjs and scripts/scaffold-html-ppt-skills.mjs
to allowedExactPaths, and skills/html-ppt/assets/ to allowedPathPrefixes so
pnpm check:residual-js no longer flags the vendored upstream runtime JS or the
new maintainer-only .mjs scripts.
* fix(skills): keep all slides in baked html-ppt examples + correct asset guidance
The bake script's `STATIC_FALLBACK_CSS` set `.slide+.slide{display:none}`,
which silently truncated every baked `example.html` to slide 1. That artifact
is also served by `/api/skills/:id/example` and reused by the Examples
preview modal's share/export and print-to-PDF, so the rule dropped the rest
of the deck from those flows. Drop the rule — slides now stack in the
print-style flow the surrounding comment already described, the gallery
thumbnail iframe still naturally lands on slide 1 (each `.slide` is `100vh`),
and modal/share/export contains the full deck.
The wrapper SKILL.md authoring instructions told agents to copy
`index.html` + `style.css` into a project while keeping the upstream
`../../../assets/...` links, but those parent-relative URLs only resolve
in-tree (the template sits three folders deep). Once the file lives in a
project artifact, `base.css`, `animations.css`, and `runtime.js` 404 and
the deck never activates. Replace step 3 with two recipes — copy the
shared assets into a project-local `assets/` and rewrite the four tags,
or inline the CSS/JS directly — and re-emit all 15 wrapper SKILL.md
files via the scaffold generator.
|
||
|
|
1edab990bb |
feat(craft): add brand-agnostic craft references + Refero-derived lint rules (#225)
* feat(craft): add brand-agnostic craft references and refero-derived lint rules Introduce `craft/` as a third top-level content axis alongside `skills/` and `design-systems/`, holding universal (brand-agnostic) craft rules that apply on top of any DESIGN.md. Skills opt in via a new `od.craft.requires` front-matter array; the daemon resolves the slug list and injects the matching files between DESIGN.md and the skill body in the system prompt. Initial vendor (MIT, adapted from referodesign/refero_skill): typography craft, color craft, anti-ai-slop. Pilot wired on saas-landing. Extend the existing lint-artifact pass with two refero-derived rules: - P0 ai-default-indigo — solid #6366f1 / #4f46e5 / #4338ca / #8b5cf6 as accent (not just gradients) is the most-reported AI tell. - P1 all-caps-no-tracking — `text-transform: uppercase` rules without ≥0.06em letter-spacing. The craft loader silently drops missing files so a skill can forward-reference future sections (e.g. `motion`) without breaking. * fix(daemon): skip :root token blocks in ai-default-indigo lint The ai-default-indigo P0 check scanned the whole HTML for the raw hex, so brands that intentionally encode indigo as `--accent: #6366f1` in :root and consume it via var(--accent) downstream were flagged as AI-default — a false positive that forced the agent to "fix" valid output. Strip :root token-definition blocks (including attribute-selector theme variants) before scanning, mirroring the existing pattern used by the raw-hex P1 check. Hex still flagged when it appears in component rules or inline styles. * docs(craft): address PR #225 P3 review feedback - craft/README.md: explain why missing craft sections are silently dropped (forward-compatibility) instead of surfacing a warning. - craft/typography.md: ground the 0.06em ALL CAPS tracking floor in Bringhurst-derived typographic practice rather than presenting the threshold as unattributed. - craft/color.md: cover the edge case where a brand's DESIGN.md intentionally encodes indigo as --accent — `var(--accent)` uses remain unflagged because the linter only inspects hardcoded hex. - docs/skills-protocol.md: link the "missing files dropped silently" note back to craft/README.md for the canonical slug list and the rationale behind the choice. * fix(craft): address PR #225 P0 review feedback - tools/pack: copy `craft/` into the packaged resource root alongside `skills`, `design-systems`, and `frames`, so the `od.craft.requires` integration isn't a silent no-op when the daemon resolves `${OD_RESOURCE_ROOT}/craft` in packaged builds. - packages/contracts: add `craftRequires?: string[]` to `SkillSummary` (and therefore `SkillDetail`) so the field that `listSkills()` already returns and `/api/skills(/:id)` already serializes via `...rest` is part of the documented web/daemon contract instead of leaking through as an untyped property. - apps/daemon/lint-artifact: expand the indigo token-strip pass to cover selector lists containing `:root` (e.g. `:root, [data-theme="light"]`) and any rule whose body is custom-property-only (e.g. a `[data-theme="dark"] { --accent: ... }` theme variant). Real component rules with a hardcoded indigo are still preserved so the P0 finding still fires; tests cover the new selector-list and theme-variant cases. * fix(craft): address PR #225 follow-up review feedback - lint-artifact: scope the indigo token-strip to <style> blocks so the rule-shaped regex no longer captures leading `<style>` text into the selector (which broke `:root` recognition for token blocks that mix `color-scheme`/etc. with `--accent`). Run the strip on the extracted CSS instead, with a regression covering `:root { color-scheme: light; --accent: #6366f1 }`. - lint-artifact: tighten the custom-property-only exemption to global theme-scope selectors (`:root`, `html`, `body`, bare attribute selectors like `[data-theme="dark"]`). Component-local rules such as `.cta { --cta-bg: #6366f1 }` are no longer exempted, so an agent cannot launder default indigo through a local var. Regression test added. - craft/anti-ai-slop.md: stop claiming every rule below is enforced by the linter; only several are. The unenforced rules (standard Hero→Features→Pricing→FAQ→CTA flow, decorative blob/wave SVG backgrounds, perfect symmetry) are now flagged inline as "(guidance, not auto-checked)" so the contract with the lint surface stays honest. * fix(daemon): tighten lint-artifact iteration and :root token gating - all-caps-no-tracking: iterate every <style> block. The previous check called `exec` once on a non-global regex, so an artifact whose offending uppercase rule sat in a second <style> block (e.g. a reset block followed by a components block) slipped past. Switch to `matchAll` and break across both loops once a violation is found. Regression test covers a second-block uppercase rule. - ai-default-indigo: stop unconditionally exempting any selector list containing `:root`. The exemption now requires both conditions to hold: every selector in the list is global theme scope AND the body is token-shaped (CSS custom properties or the `color-scheme` keyword). So `:root { background: #6366f1 }` and `:root, .cta { --cta-bg: #6366f1 }` no longer launder a hardcoded indigo through the strip pass. Regression tests cover both bypass shapes. * fix(daemon): scope theme-attr exemption and strip CSS comments in token blocks Address PR #225 review feedback on `ai-default-indigo`: - The bare-attribute branch of `selectorListIsGlobalThemeScope` accepted any `[attr=...]` selector, so a custom-property-only rule on a component/state attribute (e.g. `[data-variant="primary"]`, `[aria-current="page"]`) was treated as a global theme block and stripped before the indigo scan — exactly the component-local indigo laundering this lint is meant to catch. Restrict the exemption to a small allowlist of known theme switches: `data-theme`, `data-color-scheme`, `data-mode`. - `stripTokenBlocksFromCss` split rule bodies on `;` and matched each fragment from the start, so a token block whose body contained a normal CSS comment such as `:root { /* brand accent */ --accent: #6366f1; }` produced a fragment beginning with the comment, failed `isTokenShapedDeclaration`, and the rule was left in scope of the indigo scan — a false P0 on a legitimate token definition. Strip CSS comments before splitting/classifying declarations. Add regression coverage: arbitrary component/state attribute selectors still trip `ai-default-indigo`; `data-color-scheme` theme variants stay exempted; `:root` token blocks with leading, trailing, and between-declaration CSS comments are recognized. * fix(daemon): strip CSS comments and recognize tokens nested in at-rules The all-caps-no-tracking scan ran against raw `<style>` content, so a commented-out rule like `/* .eyebrow { text-transform: uppercase; } */` matched `upperRe` and emitted a P1 for CSS the browser ignores. Strip CSS comments from the style body before structural matching. `stripTokenBlocksFromCss` only matched flat `selector { body }` rules, so a media-query-wrapped token block like `@media (prefers-color-scheme: dark) { :root { --accent: #6366f1 } }` had its outer `@media` rule treated as the selector/body pair and the inner `:root` token block was never stripped, producing a P0 false positive on legitimate responsive theme CSS. Tighten the body alternation to `[^{}]*` so the regex matches innermost rules and recognizes the inner `:root` block directly while preserving the outer at-rule wrapper. * fix(daemon): align ai-default-indigo list with documented cardinal sins The lint's AI_DEFAULT_INDIGO subset omitted #3730a3 and #a855f7, which craft/anti-ai-slop.md lists as P0-blocked solid accents. An artifact could hard-code one of those documented colors as a button fill and slip past the indigo scan unless it happened to be inside a gradient. Bring the lint set to the exact list documented in the craft doc, and tighten the doc's wording from "etc." to an explicit enumeration that points at AI_DEFAULT_INDIGO so the prompt contract and daemon behavior stay in sync. Add regression tests pinning each newly-included hex. * fix(daemon): tighten theme-scope selector and scan inline ALL CAPS The theme-scope exemption used to accept any attribute on `:root`, `html`, or `body` (e.g. `:root[data-variant="primary"]`), letting an agent launder default indigo through a component/state attribute and slip past the `ai-default-indigo` lint. The prefixed branches now require the attribute name to be one of GLOBAL_THEME_ATTRIBUTES, matching the bare-attribute branch. The `all-caps-no-tracking` rule only iterated `<style>` blocks, so inline declarations like `<span style="text-transform: uppercase">` produced no finding even though craft/typography.md treats the ≥0.06em tracking floor as having no exceptions. Added a second scan over `style="..."` attributes that runs the same letter-spacing check and dedupes against the existing `<style>`-block finding so the agent gets a single corrective signal per artifact. * fix(daemon): align uppercase tracking px floor with the 0.06em rule The previous absolute fallback (>=1.5px) was stricter than the craft rule it enforces. `font-size: 12px; letter-spacing: 1px` is 0.083em — above the 0.06em floor — but 1.5px would reject it and trigger an unnecessary correction loop on compliant small-label CSS. Extract `hasAdequateUppercaseTracking`: read `font-size` from the same rule body and compare px tracking against `fontSize * 0.06`; fall back to a conservative >=1px floor when font-size is inherited (covers the default 16px body where 1px ≈ 0.0625em). Apply the helper to both the <style>-block scan and the inline-style scan, and add 12–14px label tests in both branches. * fix(daemon): treat rem letter-spacing as absolute, not per-element em `rem` was previously folded into the same branch as `em` and accepted at the 0.06 threshold. But `rem` is relative to the root font-size (16px default), not the element's own font-size, so on a 48px heading `letter-spacing: 0.06rem` resolves to 0.96px — about 0.02em of the element, well below the 0.06em rule the lint enforces. Convert rem to absolute px through the 16px root assumption and reuse the same px-vs-element-font-size resolution: same-rule `font-size: <n>px` gives an exact `n * 0.06` floor; otherwise the conservative >=1px fallback applies. Add regression tests for 48px headings with 0.06rem tracking (must flag) plus the 16px-element and rem-floor matches that must keep passing, in both <style>-block and inline-style branches. * fix(daemon): resolve var() refs in uppercase tracking lint `hasAdequateUppercaseTracking` only matched literal numeric values, so a tokenized rule like `letter-spacing: var(--caps-tracking)` — exactly the pattern the craft prompt steers artifacts toward — was falsely reported as `all-caps-no-tracking`. Extract `--name: value` declarations from global theme scopes (`:root`, `html`, theme-attribute selectors) once per artifact, then expand simple `var(--name)` (and `var(--name, fallback)`) references in the inspected rule body before applying the existing 0.06em / px-floor / rem-conversion logic. References without a matching token and no fallback stay in place, preserving the conservative "missing tracking" finding. * fix(daemon): resolve rem and var() font-size in uppercase tracking lint Previously the px-vs-element-font-size resolution only matched `font-size: <n>px`. Any rem-based or tokenized display size fell through to the lenient `>= 1px` body-text fallback, so an artifact emitting `.display { font-size: 3rem; text-transform: uppercase; letter-spacing: 1px; }` (a ~48px heading with a 2.88px floor) slipped past the lint that this helper exists to enforce. Resolve `rem` font-size via the same root-font assumption already used for tracking, and treat any explicitly declared but unresolvable unit (`em`, `%`, `calc(...)`, an unresolved `var(...)`) conservatively — refuse the lenient fallback so the rule must use either an `em` letter-spacing or a verifiable px/rem font-size. `var()` font-size declarations resolve through the existing `resolveCssVars` pass before the size scan runs, so the same fix catches the tokenized-display-size pattern (`--display-size: 3rem`). * fix(daemon): parse declarations to ignore custom-prop names in uppercase tracking lint The hasAdequateUppercaseTracking and resolveFontSizePx helpers used substring regexes against the rule body, so a token-name declaration such as `--letter-spacing: 0.08em` or `--display-font-size: 48px` could satisfy the `letter-spacing` / `font-size` checks even though it has no rendered effect — letting actual ALL-CAPS-without-tracking rules slip past the P1 lint. Parse the declaration list, compare exact property names, and skip declarations whose property starts with `--`. Adds regression tests covering token-name letter-spacing (style-block + inline) and a token-name font-size masking the bail-out branch. * fix(daemon): scope indigo token exemption to --accent only Previously stripTokenBlocksFromCss removed every custom-property-only global theme block before the ai-default-indigo scan, which let a laundered indigo token like `:root { --primary: #6366f1 }` consumed via `var(--primary)` slip past the lint. The craft contract is that the only escape hatch is encoding indigo as the design system's `--accent` token; any other token name is still the LLM-default color hidden behind an arbitrary name. Narrow the strip pass so a non-`--accent` token whose value carries an AI-default indigo hex keeps the rule in scope, and add regression tests for `--primary` / `--button-bg` global tokens feeding a CTA, including the at-rule and theme-attribute variants. * fix(daemon): model CSS cascade in tracking lint and detect blue→cyan trust gradients Address PR #225 review feedback (3 comments): - `letter-spacing` / `font-size` selection now picks the LAST matching declaration in the rule body, modeling CSS source-order cascade. `.eyebrow { letter-spacing: 0.08em; letter-spacing: 0.02em }` renders the noncompliant 0.02em the browser actually shows; the previous first-match behaviour silently passed it. - `extractCssTokens` now records every distinct value seen for a token across global theme scopes, and `hasAdequateUppercaseTracking` enumerates each combination so a default-theme value below the floor cannot be rescued by a scoped override that happened to be parsed later (`:root { --caps-tracking: 0.02em }` + `[data-theme="dark"] { --caps-tracking: 0.08em }` now fires). - New `trust-gradient` P0 rule pairs blue/sky tokens against cyan tokens in `linear-gradient(...)` bodies so `blue→cyan` two-stop trust gradients (documented as a cardinal sin in `craft/anti-ai-slop.md`) are actually enforced — both the hex form (`linear-gradient(90deg, #3b82f6, #06b6d4)`) and the keyword form (`linear-gradient(90deg, blue, cyan)`). Adds 11 regression tests covering each path (cascade override in <style> and inline form, font-size cascade shifting the floor, both orderings of the conflicting-token cascade, the don't-over-fire case when every theme value clears the floor, hex / keyword / sky variants of the trust gradient, and the don't-double-fire case when purple-gradient already caught a mixed gradient). * fix(daemon): apply per-scope cascade in extractCssTokens When the same CSS custom property is declared more than once inside a single rule body (e.g. `:root { --caps-tracking: 0.02em; --caps-tracking: 0.08em }`), CSS source-order cascade collapses to the last value; the earlier declaration never reaches any element. `extractCssTokens` was treating intra-scope duplicates as simultaneous theme alternatives, so `hasAdequateUppercaseTracking` enumerated the stale 0.02em and emitted a spurious all-caps-no-tracking finding. Collapse duplicate token declarations within a rule body to the last value before merging into the cross-scope distinct-value map. Cross-scope overrides (separate `:root` and `[data-theme]` rules) remain preserved as distinct values so the conservative theme-cascade check still fires when ANY applicable theme renders below the floor. * fix(daemon): scope tracking lint to innermost rules and per-theme tokens Restrict the upperRe body alternation to [^{}]* so the regex matches innermost CSS rules and skips at-rule wrappers — an outer @media or @supports could otherwise capture as a single rule whose selector was the at-rule and whose body began with the inner selector token, masking the same-rule font-size and letting noncompliant tracking on large headings slip through the lenient inherited-size fallback. Replace the by-name-distinct-values token map with per-scope token records and a buildResolvedThemes pass that materializes one effective map per theme. Paired token declarations now stay paired during evaluation, so theme variants like :root + [data-theme=dark] no longer generate cross-theme cartesian pairings (e.g. default-size + dark-track) that emit false positives on legitimate light/dark themes. --------- Co-authored-by: looper <looper@open-claude.dev> |
||
|
|
bc16a2d5b8 |
Update docs/assets/github-metrics.svg - [Skip GitHub Action] (#241)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
85714d58c8 |
fix: daemon OD_DAEMON_URL uses port 0 instead of actual allocated port (#240)
When tools-dev launches the daemon with OD_PORT=0 (letting the OS pick a free port), app.listen correctly resolves the actual port in its callback, but the enclosing closure still references the original `port` parameter (value 0). This causes OD_DAEMON_URL to be set to http://127.0.0.1:0 in the environment passed to agent subprocesses, breaking media generation and any daemon callback that relies on isLocalSameOrigin. Introduce a mutable `resolvedPort` variable, assigned from `actualPort` inside the listen callback. All downstream consumers (OD_DAEMON_URL, isLocalSameOrigin calls) now read the resolved value. Co-authored-by: yyh <yyh@test.cn> |
||
|
|
c472178e65 |
Create tr.ts (#233)
* Create tr.ts Turkish language support. * Update tr.ts Change from the brown fox testing phrase to a Turkish alternative. * Update tr.ts Add proposed fixes |
||
|
|
a263a9c11e |
fix(daemon): quote agent bin path when spawning with shell:true on Windows (#232)
When `useShell` is true (Windows + .cmd/.bat shim), Node.js spawns the agent via `cmd.exe /d /s /c "<bin> <escaped-args>"`. Node escapes argv items but does NOT quote the bin path itself — that is the caller's responsibility. If `resolvedBin` contains spaces (the common case for npm shims under user directories with a space in the account name, e.g. `C:\Users\First Last\AppData\...\claude.CMD`), cmd.exe parses up to the first space as the command and the rest as arguments, then fails with `The system cannot find the file 'C:\Users\First'` (or the localized equivalent). The agent process exits in ~0.1s with code 1 and the chat surfaces the cmd.exe error verbatim. The Node DEP0190 deprecation warning that fires alongside the original spawn is the same root cause documented from the runtime side. Wrap `resolvedBin` in double quotes when `useShell` is true so the full path stays a single token. The `/s` flag that Node already passes to cmd.exe handles the resulting `cmd /d /s /c ""path with spaces" args"` correctly. |
||
|
|
a4fd4f949f |
fix(tools-dev): use junction instead of dir symlink on Windows (#231)
ensureWebDevNodeModules() called fs.symlink(target, path, "dir") to
link apps/web/node_modules into the web runtime root. On Windows,
"dir" symlinks require either Administrator rights or Developer Mode
(SeCreateSymbolicLinkPrivilege). Standard non-elevated user accounts
without Developer Mode get EPERM and tools-dev exits before web ever
starts.
Junctions ("junction") are functionally equivalent for directory-only
links on the same volume, work for any user without elevation or
Developer Mode, and are silently treated as plain symlinks on POSIX.
The existing isSymbolicLink() check on the next launch still matches
junctions on Node.
Reproduced on Windows 11 + Node 24 with a non-elevated PowerShell
session and Developer Mode off.
|
||
|
|
4510c69ba1 |
feat(tools-dev): add --prod flag and OD_HOST for headless server deployment (#222)
* feat(tools-dev): add --prod flag and OD_HOST for headless server deployment - Lazy-load electronBinaryPath so daemon+web can start without Electron - Add --prod flag to tools-dev start/run that sets NODE_ENV, OD_WEB_PROD, and OD_WEB_OUTPUT_MODE automatically for production Next.js builds - Add OD_HOST env var support to daemon and web sidecar bind addresses (defaults to 127.0.0.1, set to 0.0.0.0 for remote access) - Skip next.config.ts distDir override when OD_WEB_PROD=1 so production builds resolve the default .next directory Closes #221 * fix: address PR review — hardcode daemon bind to 127.0.0.1, cache electron path - Revert OD_HOST from daemon: daemon is a local privileged process and must only bind 127.0.0.1. Remote access goes through the web sidecar proxy. - Web sidecar resolveDaemonOrigin now always uses 127.0.0.1, separated from the web bind address (OD_HOST) so the daemon proxy works correctly even when the web listener binds 0.0.0.0. - Add OD_HOST character validation to reject clearly invalid values early. - Cache electronBinaryPath getter result to avoid repeated require() calls. --------- Co-authored-by: yamsfeer <yamsfeer@users.noreply.github.com> |
||
|
|
8438270f74 |
docs: add Traditional Chinese (繁體中文) README (#194)
Add README.zh-TW.md based on the Simplified Chinese version, converted via OpenCC s2twp and adjusted to use Taiwan-specific terminology (備援, 螢幕, 堆疊, 即時, 動態, 計畫, 色票, etc.). Update language switcher in all existing README variants to include 繁體中文. |
||
|
|
513bd4edea |
feat(web): pick prompt templates (not design systems) for image/video projects (#192)
* feat(web): pick prompt templates (not design systems) for image/video projects
The New Project panel now shows the curated prompt-template gallery in the
image and video tabs instead of the Design System picker. Design systems
only make sense for prototypes, slide decks, templates, and the freeform
"other" canvas — they don't map onto image/video generation.
The picked template's body is editable in-line ("optimize" affordance) and
the (possibly tuned) prompt is snapshotted into ProjectMetadata as
`promptTemplate`. The system-prompt composer surfaces it on every turn as
a stylistic + structural reference for the agent — same shape we already
use for the saved-template flow.
Also rename the right-side gallery tabs from "Image prompts" / "Video
prompts" to "Image templates" / "Video templates" across all locales.
Made-with: Cursor
* fix(prompt-templates): address review — escape fences, error UI, empty hint, tests
Apply the actionable feedback from the code review:
- Security: escape triple-backticks in `metadata.promptTemplate.prompt`
before interpolating it into the system prompt's fenced block. A user
who pasted ``` into the editable template body could otherwise close
the fence and inject free-form instructions for the agent. Apply the
same fix in both the contracts composer and the daemon mirror.
- UX: surface fetchPromptTemplate failures via an inline error banner
outside the popover, with a one-click retry button bound to the last
failed pick. Previously the error toast lived inside the popover and
vanished as soon as the popover closed.
- UX: show a subtle hint below the prompt textarea when the body is
empty, so users who clear it on purpose understand the agent will
have no template reference.
- Defense in depth: gate the `**referenceTemplate**:` metadata bullet
on a non-empty prompt body in both composers, so a stale title can
never appear in the system prompt without the body it claims to
reference.
- Tests: add tests/system-prompt-template.test.ts covering the happy
path (image + video), the backtick escape, the truncation cap, the
empty-prompt skip, the non-media kinds, and the missing-source path.
- i18n: add `promptTemplates.retry` and `newproj.promptTemplateBodyEmpty`
across all 9 locales; backfill the prompt-template picker keys for
ja, es-ES, de which landed on main after this branch.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
|
||
|
|
8df7951cfc |
Update docs/assets/github-metrics.svg - [Skip GitHub Action] (#228)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> |
||
|
|
35c3fe678c |
feat: add design-brief skill with structured I-Lang input format (#184)
* feat: add design-brief skill with structured I-Lang input format
Adds a new skill that accepts structured design briefs (I-Lang protocol
format or natural language) and generates a concrete DESIGN.md with
resolved color, typography, layout, mood, density, and constraint tokens.
Solves the 'make it professional' ambiguity problem by requiring explicit
dimensions. Falls back to sensible defaults for unspecified dimensions
and transparently reports what was assumed.
Outputs: DESIGN.md + optional brief-preview.html showing token swatches.
* fix: add Responsive Behavior and Do's and Don'ts sections to DESIGN.md template
Addresses Codex review: downstream skills (e.g. saas-landing) read
these sections from DESIGN.md. Missing them causes incomplete context.
* fix: address P2 review feedback
- Remove overly broad 'brief' trigger to prevent misfires on
'brief me on X' or 'in brief'. Replaced with 'create a design brief'.
- Add Natural language → I-Lang mapping table (20 common phrases)
so the conversion from vague input to structured dimensions is
explicit, not a black box.
* fix: address all 8 review findings from lefarcen
1. P3 Example values taxonomy: added clarification that values are
representative, not exhaustive. Agent accepts semantically clear
unlisted values, prompts on ambiguous ones.
2. P2 8-dimension justification: added Background section explaining
dimensions derived from analysis of 71 bundled design systems.
Documented why animation/responsive/a11y are excluded at brief level.
3. P2 Symbolic → concrete token resolution: added Section 2.1 with
full mapping table (4 palettes, 3 accents, 3 typography, 3 display,
3 density levels → concrete hex/font/px values).
4. P3 preview.html structure: added 4-section spec (color swatches,
typography specimens, spacing ruler, live component preview).
5. P2 Default resolution logic: added Section 2.2 with mood-aware
default rules for each dimension and static fallback set.
6. P3 design_system.requires inconsistency: changed to requires: true,
generates: true — this skill generates a DESIGN.md from scratch,
and downstream skills require it. Added note about existing
DESIGN.md overwrite/merge prompt.
* fix: clarify typeface limit — mono is utility, exempt from 2-face rule
Resolves contradiction between Do's/Don'ts ('no more than 2') and
DESIGN.md example showing 3 faces (Display + Body + Mono).
* fix: address 3 P3 findings from lefarcen
- Reword 'responsive breakpoints' to 'responsive strategy' in Background,
note DESIGN.md includes sensible breakpoint defaults
- Simplify 'overwrite or merge' to 'overwrite or skip' (merge undefined)
- Add numbering column to 8-dimension table for scannability
* fix: address owner (mrcfps) review — align with OD design-system contract
1. od.mode: prototype → design-system (this skill produces DESIGN.md)
2. design_system.requires: true → false (generates, not consumes)
3. DESIGN.md template uses canonical 9-section OD headings:
- Visual Theme & Atmosphere (NEW)
- Color Palette & Roles (was Color)
- Typography Rules (was Typography)
- Component Stylings (was Components)
- Layout Principles (was Layout)
- Depth & Elevation (unchanged)
- Do's and Don'ts (unchanged)
- Responsive Behavior (unchanged)
- Agent Prompt Guide (unchanged)
4. sections list in frontmatter updated to match
* fix: address 3 contract consistency issues from owner review
1. Remove output_format enum — always generate both DESIGN.md and
brief-preview.html. Prevents manifest advertising a preview file
that may not exist when design_md-only mode is selected.
2. Fix example: typography=inter_for_body → typography=inter.
The example now matches the token resolution table exactly.
3. Make vocabulary closed. Remove 'derive by analogy' instruction
that contradicted Section 3's 'do not invent values outside the
resolution table'. Unknown symbolic values now require user
clarification instead of agent guessing.
* fix: disambiguate mapping table — default to first option when multiple values listed
* fix: add token mappings for all closed vocabulary values
Added concrete tokens for:
- accent=muted_sage (#84A98C) and accent=slate (#64748B)
- typography=dm_sans (DM Sans)
- display=clash_display (Clash Display)
Every value in the vocabulary table now has a corresponding
token-resolution row in Section 2.1. No dead-end paths.
---------
Co-authored-by: adsorgcn <adsorgcn@users.noreply.github.com>
|
||
|
|
abdd4119b2 |
fix(daemon): clamp codex reasoning effort to model-supported values (#223)
* fix(daemon): clamp codex reasoning effort to model-supported values
Codex's CLI accepts `none | minimal | low | medium | high | xhigh`, but
real models support narrower subsets — picking Minimal in OD's settings
made every chat turn fail with `agent exited with code 1` because the
OpenAI Responses API rejects `reasoning.effort=minimal` on the gpt-5.2
through 5.5 family with `unsupported_value`.
Add a client-side clamp that maps the user's pick to one the chosen
model accepts (Minimal -> low for gpt-5.5 family, xhigh -> high for
gpt-5.1, gpt-5.1-codex-mini caps at medium). Default / unknown model
is treated as gpt-5.5 since that's codex's current default. The user's
UI pick stays valid; the wire request gets a level the model can use.
* docs(daemon): clarify clampCodexReasoning unknown-model behavior
Per PR review — make explicit that unknown / future model ids pass
through unclamped on purpose. The server error then surfaces as the
signal that a new model family rule should be added here, rather than
silently downgrading every unrecognized id.
* test(daemon): cover codex reasoning-effort clamp matrix
Adds a table-driven test in apps/daemon/tests/agents.test.ts that drives
clampCodexReasoning through the public buildArgs surface. The 18 cases
cover:
- minimal -> low for default / explicit gpt-5.2-5.5
- low / medium / high pass-through on gpt-5.5
- xhigh -> high for gpt-5.1
- gpt-5.1-codex-mini cap (low/minimal -> medium, high/xhigh -> high)
- unknown / future models pass through unchanged
- 'default' reasoning omits the -c flag entirely
- path-style model ids (vendor/gpt-5.5-foo) clamp correctly
Tests stay at the wire level (asserting on the args array codex.buildArgs
produces), keeping the helper non-exported and matching the rest of the
file's style.
* docs(daemon): clarify gpt-5.1-codex-mini accepts medium / high
Per PR review — the original "caps at `medium`" wording was misleading
because the clamp returns `high` for `high` / `xhigh` inputs, which
contradicts the comment. The model actually accepts `{medium, high}`,
so describing it as "accepts only `medium` / `high`" matches the
function's behavior.
Logic unchanged.
|
||
|
|
06eac21cd8 |
Fix metrics workflow protected branch updates (#219)
* fix github metrics workflow for org repo * fix metrics workflow protected branch updates * fix metrics workflow review notes Generated-By: looper 0.3.0 (runner=fixer, agent=openai/gpt-5.5) |
||
|
|
8c90ef6f55 |
fix(daemon): deliver Claude Code prompt via stdin to avoid spawn E2BIG/ENAMETOOLONG (#143)
Claude Code is the last agent that still embeds the composed prompt in
argv (`-p <prompt>`). Composed prompts (system prompt + design system +
skill body + user message) routinely exceed:
- Linux : MAX_ARG_STRLEN ~128 KB per argv entry → `spawn E2BIG`
- Windows: CreateProcess command-line cap ~32 KB direct, ~8 KB via
`.cmd` shim → `spawn ENAMETOOLONG`
the prompt through `child.stdin` (`promptViaStdin: true`). Claude was
explicitly excluded at the time. #97 mitigated the Windows case for
Claude with a `.od-prompt.md` temp-file fallback, but that path still
leaves a stray file in the project, doesn't trigger on Linux, and is
slower than the stdin route the other agents already use.
This change brings Claude in line with the rest:
- Drop the prompt from argv; keep the bare `-p` print-mode flag
- Set `promptViaStdin: true` so server.ts pipes `composed` on stdin
- Add a regression test that asserts the prompt body never lands in
argv even at 200 KB
Verified locally that `claude -p --output-format stream-json --verbose`
(no positional prompt) reads the prompt from stdin under the default
`--input-format text`, which has no length cap.
Fixes #82
Refs #100, #52
|
||
|
|
0e2085e361 |
feat(prompt-templates): add three Three Kingdoms ARPG Seedance 2.0 video templates (#212)
Adds three curated first-party video prompt templates to `prompt-templates/video/`, each with a matching MP4 preview and a first-frame poster JPG under `assets/prompt-templates/video/`. These are the direct video companions to the three image templates opened in PR #207 (Three Kingdoms ARPG screenshot set). Each video clip is a ~10-12s in-engine cinematic action beat that brings the corresponding still to life; the two surfaces can be served as a pair (still → video). ### New templates 1. `video-seedance-three-kingdoms-lyubu-yuanmen-archery.json` ~10s. Lyu Bu (吕布) at the yuanmen between two armies — draws, holds, releases one gold-qi arrow toward a distant halberd. Companion to image template `game-screenshot-three-kingdoms-lyubu-yuanmen-archery`. 2. `video-seedance-three-kingdoms-guanyu-slaying-yanliang.json` ~10s. Guan Yu (关羽) on Red Hare — charges, raises the Green Dragon Crescent Blade, executes a single clean diagonal cleave past Yan Liang. No blood on-screen (the strike is implied by a short gold-into-jade qi flash). Companion to image template `game-screenshot-three-kingdoms-guanyu-slaying-yanliang`. 3. `video-seedance-three-kingdoms-zhaoyun-cradle-escape.json` ~12s. Zhao Yun (赵云) at Changban — rides with the infant A Dou cradled in a red silk sling on his chest, parries one incoming saber with a clean PERFECT DODGE, vaults a fallen war-chariot and clears a path. Hard safety rail in the prompt: the infant must stay visible, peaceful and obviously unharmed in every frame. Companion to image template `game-screenshot-three-kingdoms-zhaoyun-cradle-escape`. Each template is tuned for `seedance-2.0`, aspect `16:9`, category `Cinematic` (reuses the existing category — 17 templates already live there). Every prompt is explicitly in-engine camera-disciplined (single continuous beat, no cuts, no slow-motion ramps, no whip pans) and HUD-free (the companion image template carries the HUD), so reviewers and downstream users can treat the still + clip as a matched production pair. Each template exposes 5-7 `{argument}` slots (reference_image / environment / hero / weapon / target / mount / qi_color / parry_color / infant / attacker as appropriate) so users can restyle the same shot scaffold for any Three Kingdoms (or, with heavier edits, any historical battlefield) scene. ### Assets | File | Size | | --- | --- | | `video-seedance-three-kingdoms-lyubu-yuanmen-archery.mp4` | 7.6 MB | | `video-seedance-three-kingdoms-guanyu-slaying-yanliang.mp4` | 10.3 MB | | `video-seedance-three-kingdoms-zhaoyun-cradle-escape.mp4` | 11.7 MB | | 3 × first-frame `-poster.jpg` | 445-527 KB each | Total: ~30 MB across 3 MP4s, each well under GitHub's 100 MB single-file limit. Hosted in-repo on `raw.githubusercontent.com` for a fully self-contained first-party contribution — no external CDN dependency. ### Verification - `node -e "JSON.parse(...)"` passes on all three new templates. - Slugs do not collide with any existing video template on `main`. - `previewImageUrl` (poster) and `previewVideoUrl` (mp4) both point at the new in-repo asset paths. - `source.repo = nexu-io/open-design`, `license = Apache-2.0`, `author = open-design contributors`, so the first-party guard in `scripts/import-prompt-templates.mjs` (added in #187) preserves these across importer re-runs. ### Why The companion image PR (#207) gives users a beautiful Three Kingdoms ARPG still they can generate via gpt-image-2; this PR closes the loop by letting them turn that still into a believable ~10s in-engine clip via seedance-2.0 — the exact production flow behind the Black-Myth-Wukong-style ARPG demo reel this workstream is pitching. Paired still + video templates also double as a clean reference for how first-party `open-design` contributors should structure a matched set across the two surfaces (same slug suffix, `companion-to-image` tag, cross-referenced `reference_image` argument, same hero / environment language, no HUD in the video so HUD can be sourced from the still). Co-authored-by: Tuola Ge <gexingli@refly.ai> |
||
|
|
04bf930880 |
feat(prompt-templates): add otaku-dance choreography breakdown infographic (#209)
Adds one curated first-party image prompt template to
`prompt-templates/image/`, with a matching preview JPG under
`assets/prompt-templates/image/`.
### New template
**`infographic-otaku-dance-choreography-breakdown-gokurakujodo-16-panels.json`**
— A single vertical 2:3 poster composed as a 4x4 grid of 16 connected
square panels, forming a full choreography breakdown chart for the
famous Japanese otaku dance song 極楽浄土 (Gokuraku Jodo).
Each panel shows the same cute half-realistic anime idol girl (pink
twin-tails, sailor-collar school-idol uniform, vivid turquoise eyes)
performing one signature pose from the dance, full-body, on a pastel
pink background with:
- a small Japanese caption strip at the bottom ("両手広げ", "指さし天井",
"ハート手", … "フィナーレ"),
- a numbered circle (1–16) at the top-left corner,
- a clean 4x4 grid with thin black separators,
- an overall header reading "極楽浄土 振り付け 16連動" at the top.
The template is explicitly engineered as a POSE REFERENCE SHEET for
downstream AI video generation — every silhouette is crisp and
unambiguous, no motion lines or background clutter, identical
character across all 16 cells.
Five `{argument}` slots expose song title, romaji, character design,
background color and header text so the same chart can be restyled
for any choreographed dance song while keeping the 16-pose grid
scaffold unchanged. Tuned for `gpt-image-2`, aspect `2:3`. Category:
`Infographic` (reuses the existing enum value; no new enum).
Carries `source.repo = nexu-io/open-design`, Apache-2.0, author
`open-design contributors`.
### Verification
- `node -e "JSON.parse(require('fs').readFileSync('prompt-templates/image/<file>.json','utf8'))"` passes on the new template.
- Slug does not collide with any existing template on `main`, in the
companion Three Kingdoms PR (#207), or in the companion anime
fighting-game PR (#208).
- Preview JPG is 396 KB, comparable to the previews landed in #187.
- `aspect = 2:3` matches the underlying 1024x1536 source render and
the reference-chart layout.
### Why
The existing `Infographic` category has strong timeline/evolution
content (e.g. `3d-stone-staircase-evolution-infographic`) but no
entries aimed at **motion reference** — the one niche where a static
infographic is essentially a production tool for video/animation work.
This template plugs that gap. The 4x4 grid of pose-cells is a
genre-defining layout for dance choreography sheets (used widely for
idol dance covers on Bilibili / YouTube / TikTok) and, because every
cell is a clean, identical-character full-body silhouette on a flat
background, the sheet doubles as a **ready-to-use pose reference**
for AI video pipelines (image-to-video, pose-guided control, keyframe
choreography). One template, two jobs: a pretty poster and a working
production asset.
Co-authored-by: Tuola Ge <gexingli@refly.ai>
|
||
|
|
26150c60af |
feat(prompt-templates): add anime fighting game screenshot template (#208)
Adds one curated first-party image prompt template to
`prompt-templates/image/`, with a matching preview JPG under
`assets/prompt-templates/image/`.
### New template
**`game-screenshot-anime-fighting-game-captain-ryuuga-vs-kaze-renshin.json`** —
A cinematic anime fighting-game key-visual / combat screenshot in the
style of *Street Fighter 6* or *Tekken 8* intro art. Two original
anime-styled male warriors face off at the center of a nighttime
Chinese temple courtyard:
- **Captain Ryuuga (P1)** — shirtless straw-hat pirate with a red
battle-scar, shark-tooth necklace, skull-pattern sash and a warm
orange-red fire aura.
- **Kaze Renshin (P2)** — spiky jet-black hair, orange martial-arts gi
with a single black kanji, charging a crackling blue lightning energy
sphere between his hands.
The background, lighting and warm-vs-cool color grading follow the
rival-fighter convention of the genre (orange left half, blue right
half). The template ships with a complete fighting-game HUD exposed as
slot-filled `{argument}` placeholders:
- Two horizontal health bars with round central round-timer and
`ROUND N` label, per-side HP-percent numerals.
- P1 / P2 portrait panels with character name + subtitle + emblem.
- Per-side `HITS COMBO` counters and max gauges (orange-left,
blue-right).
Ten `{argument}` slots in total make it easy to restyle the matchup
(swap the fighters, backdrop, round number, HP percents, combo counts,
names, titles and emblems) without rebuilding the HUD-and-render
boilerplate. Tuned for `gpt-image-2`, aspect `16:9`. Category: `Game UI`
(reuses the existing enum value introduced in #187; no new enum).
Carries `source.repo = nexu-io/open-design`, Apache-2.0, author
`open-design contributors`.
### Verification
- `node -e "JSON.parse(require('fs').readFileSync('prompt-templates/image/<file>.json','utf8'))"` passes on the new template.
- Slug does not collide with any existing template on `main` or in the
companion Three Kingdoms screenshot PR.
- Preview JPG is 679 KB, comparable to the previews landed in #187.
- `aspect = 16:9` matches the underlying 1792x1024 source render.
### Why
#187 anchored the `Game UI` category with a Chinese MMO HUD mockup.
The companion Three Kingdoms PR extends the category with AAA ARPG
combat-moment screenshots in the Black Myth: Wukong style. This PR
adds a third flavor — an **anime fighting game VS screen** — completing
a compact but representative seed set for the category:
- MMO HUD (UI-heavy scenic moment)
- AAA ARPG (character-driven cinematic combat)
- Anime fighting game (head-to-head VS key visual)
Together these cover three very different HUD conventions and three
different render styles, so downstream users approaching the Game UI
category have a real breadth of starting points to remix from — not
just one aesthetic.
Co-authored-by: Tuola Ge <gexingli@refly.ai>
|
||
|
|
975c795827 |
feat(prompt-templates): add three Three Kingdoms ARPG gameplay screenshot templates (#207)
Adds three curated first-party image prompt templates to
`prompt-templates/image/`, each with a matching preview JPG under
`assets/prompt-templates/image/`.
### New templates
1. **`game-screenshot-three-kingdoms-lyubu-yuanmen-archery.json`** —
Lü Bu drawing a massive recurved warbow at Yuanmen gate to shoot
down a distant halberd at ~150 paces. Over-the-shoulder gameplay
framing with a locked-on target marker and distance readout in the
HUD. Three `{argument}` slots: character, qi_color, setting.
2. **`game-screenshot-three-kingdoms-guanyu-slaying-yanliang.json`** —
Guan Yu riding the Red Hare warhorse through a torrential-rain
battlefield, Blue Dragon Crescent Glaive raised, boss-fight HUD with
a crimson Elite HP bar over the distant enemy general. Four
`{argument}` slots: character, mount, weapon, setting.
3. **`game-screenshot-three-kingdoms-zhaoyun-cradle-escape.json`** —
Zhao Yun at Changbanpo cradling the swaddled infant Liu Chan in his
left arm and sweeping enemies back with a spear in his right, with
a dedicated ESCORT protection bar in the HUD and a visible combo
counter. Four `{argument}` slots: character, child_protected,
weapon, setting.
All three follow the same in-game screenshot recipe: AAA next-gen ARPG
in the cinematic photoreal style of Black Myth: Wukong (with Elden Ring
for the Zhao Yun piece), Unreal Engine 5 Nanite/Lumen rendering, third
person over-the-shoulder camera, and a complete semi-transparent HUD
(portrait + HP/qi bars, minimap, skill hotbar, stamina ring, lock-on /
boss / escort widgets as appropriate). Each ships with a negative
prompt block tuned for this genre — no watermark, no gibberish glyphs,
no cutscene framing, no first-person view, no modern clothing.
All JSONs carry `source.repo = nexu-io/open-design`, Apache-2.0, author
`open-design contributors`, and follow the shape introduced in #187 so
the importer's first-party preservation logic applies unchanged.
Category: `Game UI` (reuses the existing enum value from #187; no new
enum introduced).
### Verification
- `node -e "JSON.parse(require('fs').readFileSync('prompt-templates/image/<file>.json','utf8'))"` passes on all three new templates.
- Slugs do not collide with any existing template on `main`.
- Preview JPGs are 445-527 KB each, comparable to the previews landed in #187.
- `aspect = 16:9` matches the underlying 1536x1024 source renders.
### Why
#187 established `Game UI` as a category with a single HUD-heavy MMO
mockup of a female swordswoman in a scenic shrine. This PR extends the
category with three **combat-moment** screenshots centered on specific
Three Kingdoms heroes in their most iconic scenes — giving the library
a clear complement (character-driven action beats) to the existing
HUD-demo anchor. The Three Kingdoms theme also opens a reusable
narrative scaffold: the `{character}` / `{weapon}` / `{setting}` slot
pattern lets downstream users regenerate the same HUD-accurate gameplay
framing for other Chinese historical figures (e.g. Yue Fei, Huo Qubing)
or wholly custom warriors, without having to rebuild the HUD-and-render
boilerplate from scratch.
Co-authored-by: Tuola Ge <gexingli@refly.ai>
|
||
|
|
38bdb59d86 | fix(release-stable): build desktop before typecheck, drop workspace tests (#216) open-design-v0.1.0 | ||
|
|
1d6d86fa69 | fix github metrics workflow for org repo (#217) | ||
|
|
913a6c3ea7 |
fix(release-stable): build daemon before workspace typecheck (#215)
The verify job ran `pnpm typecheck` (root script) which executes `pnpm -r run typecheck` *before* the daemon build. The e2e workspace's typecheck imports types from `apps/daemon/dist/*.js`, so on a fresh clone (every CI run) it fails with TS2307 cannot-find-module. Drive the order explicitly inside the verify job: 1. install deps 2. build daemon (produces dist/*.js + .d.ts) 3. workspace typecheck 4. check:residual-js 5. workspace tests This keeps the root `typecheck` script untouched (which other dev / contributor workflows may depend on) — the workflow simply imposes the correct order itself. The atomic publish job already prevented orphan tags/releases when the first dispatch failed at typecheck. Co-authored-by: Elian <elian@EliandeMacBook-Pro.local> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
451ae983db | release: Open Design 0.1.0 — first public release (#206) | ||
|
|
82a79c8b23 |
Add desktop chrome header (#205)
* feat: add desktop chrome header * fix: address app chrome review feedback Generated-By: looper 0.2.7 (runner=fixer, agent=codex) * fix: address app chrome review feedback Generated-By: looper 0.2.7 (runner=fixer, agent=codex) |
||
|
|
6789dd4c11 |
feat(prompt-templates): add dance storyboard and ancient-china MMO HUD templates (#187)
* feat(prompt-templates): add dance storyboard and ancient-china MMO HUD templates - social-media-post-sensational-girl-dance-storyboard-8-shots: 8-shot storyboard prompt set with shared global style tokens, negative prompt, and character lock, tuned for GPT-Image-2. Produces a continuous dance choreography as a coherent 8-frame sequence. - game-ui-ancient-china-open-world-mmo-hud: HUD mockup for a Black Myth: Wukong style ancient-China open-world MMO, centered on a female swordswoman protagonist. Covers character panel, minimap with bagua frame, skill hotbar, quest tracker, chat window, and world-space nameplates with Chinese typography rules. - scripts/import-prompt-templates.mjs: preserve hand-authored templates on re-run by keeping any JSON whose source.repo is not the upstream CC-BY corpus. Previously clearDir wiped the whole directory, which would delete first-party curated prompts on the next import. Both templates carry source attribution to nexu-io/open-design under Apache-2.0. Categories reuse the existing 'Social Media Post' and 'Game UI' enum values already present in the gallery. * feat(prompt-templates): add preview images for dance and MMO HUD templates - assets/prompt-templates/image/social-media-post-sensational-girl-dance-storyboard-8-shots.jpg: an 8-panel storyboard render produced from the template itself, downscaled to 1024x1536 JPEG for gallery thumbnails. - assets/prompt-templates/image/game-ui-ancient-china-open-world-mmo-hud.jpg: a reference HUD screenshot rendered from the template prompt via gpt-image-2, downscaled to 1536x1024 JPEG. - Both templates now reference these previews via a raw.githubusercontent.com URL pointing at nexu-io/open-design main, matching the pattern used by the existing YouMind-sourced seeds (cms-assets.youmind.com) so every card in the Prompt Gallery carries a thumbnail once the PR merges. --------- Co-authored-by: Joey <joey@open-design.local> |
||
|
|
9969003aa5 | fix web design files upload picker (#199) | ||
|
|
59e4966dda |
feat(version): add app version awareness (#204)
* feat(version): add app version awareness * fix(version): detect packaged sidecars across platforms |
||
|
|
6d268eedde | fix web locale registry test (#202) | ||
|
|
abaae96eb2 |
update: add 57 DESIGN.md files from awesome-design-skills (#92)
* update: add 57 DESIGN.md files from awesome-design-skills * Update i18n coverage for added design systems --------- Co-authored-by: mrcfps <mrc@powerformer.com> |
||
|
|
cbbab86fd0 | fix web design files dropzone copy (#200) | ||
|
|
f604ff1ec2 | Add Windows beta packaging and release assets (#191) | ||
|
|
dd283fa2d3 | fix web design files agent copy (#201) | ||
|
|
ed0b36ed24 |
feat(i18n): add Japanese locale (#197)
Add `ja` locale with full translation of all UI strings to Japanese. Register it in types.ts and index.tsx alongside existing locales. |