Commit graph

44 commits

Author SHA1 Message Date
NotLeaped84
4c15ea45fa
docs: add design system authoring guide (#961)
* fix(i18n): add loom and trading-terminal to FR/RU summaries only

* docs: add design system authoring guide

* fix: remove loom/trading-terminal from locale (missing dirs), fix docs contradictions
2026-05-09 15:34:11 +08:00
lefarcen
13ab430b45
docs: add skills contributing guide (#1035)
* 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.
2026-05-09 15:17:45 +08:00
github-actions[bot]
2f7fbd68d7
Update docs/assets/github-metrics.svg - [Skip GitHub Action] (#998)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-09 10:25:47 +08:00
leprincep35700
2340d38d9d
docs: fix stale internal links (#950)
* docs: fix stale internal links

* docs: fix design sample link label

---------

Co-authored-by: leprincep35700 <leprincep35700@users.noreply.github.com>
2026-05-08 21:20:25 +08:00
Marc Chan
bdd49ebc47
docs: add repository-wide code review guidelines (#927)
* docs: add repository-wide code review guidelines

Introduces docs/code-review-guidelines.md as the operational review
standard layered on top of AGENTS.md, and adds a Code review guide
section to AGENTS.md that points reviewers at it.

The guide codifies the Product relevance test as a pre-implementation
gate, names the canonical list of forbidden surfaces, lists the
ownership areas in scope, and defines five review lanes: default
code/tests, contract and protocol changes, design-system additions,
skill additions, and craft additions. It also captures the secrets,
runtime data, performance, and maintainability checks that previously
lived only as oral conventions, and aligns the approval bar with the
validation rules in AGENTS.md.

AGENTS.md remains the source of truth when the two disagree; the new
doc is the operational guide on top of it.

* docs: tighten review guidelines for governance docs and bugfix discipline

- Reference scripts/guard.ts as source of truth for guard checks
- Add governance documentation as an explicit in-scope category
- Require reviewers to build a module/caller map before commenting
- Add bugfix-specific reproduction and regression-test checks
- Carve out documentation-only exception in the approval bar

* docs: align review guidelines with repository policy

Keep the review scope aligned with maintained workspace surfaces and preserve AGENTS.md as the authoritative validation bar.

Generated-By: looper 0.6.3 (runner=fixer, agent=opencode)
2026-05-08 19:18:39 +08:00
Joey-nexu
9ed4ea1263
feat(skill): add github-dashboard (#666)
* feat(skill): add github-dashboard

* docs(skill): add github-dashboard screenshot

* fix(skill): address github-dashboard review

* fix(i18n): cover github-dashboard skill in de/ru/fr fallback lists

The localized-content coverage test asserts every skills/<id>/SKILL.md
appears in each locale's skills list. Adding github-dashboard to the
EN-fallback id list keeps de/ru/fr CI green.

* fix(i18n): cover mission-control design system in de/ru/fr fallback lists

Same backfill as the one applied on PR #714: mission-control was added
in #858 without locale fallback entries, so the localized-content
coverage test breaks any open PR once GitHub merges current main into
its head ref.

---------

Co-authored-by: joey <joey@joeydeMacBook-Air.local>
Co-authored-by: lefarcen <935902669@qq.com>
2026-05-08 17:21:12 +08:00
github-actions[bot]
915c041545
Update docs/assets/github-metrics.svg - [Skip GitHub Action] (#853)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-08 11:03:44 +08:00
shangxinyu1
7107623ee2
test: expand entry and settings automation coverage (#811)
* test: harden new project panel metadata coverage

* test: add settings and connector sync coverage

* test: expand entry e2e coverage

* test: satisfy exact optional property types in entry connector flow

* test: keep entry Playwright coverage under e2e/ui

* test: tighten coverage docs and settings test cleanup

* test: drop e2e docs from the guarded package

* docs: move automation coverage docs out of e2e

* test: restore clipboard cleanup without delete

* test: match composio save dialog behavior

* test: avoid placeholder assertion after composio save

* test: expect closeModal on settings saves

* test: align settings save assertions with closeModal flags

* test: fix settings save mocks

* test: align composio replacement hint
2026-05-08 09:30:16 +08:00
INFINITY
988fd6db5e
feat: import existing local folder as project (#597) (#624)
* feat(contracts): types for folder-import endpoint

Add ImportFolderRequest, ImportFolderResponse to the public contract
surface. Extend ProjectMetadata with a baseDir field — when set, the
project's files live at this absolute path instead of .od/projects/<id>/.
Stored as the realpath() result so symlinks cannot redirect later writes.

Refs nexu-io/open-design#597

* feat(daemon): support metadata.baseDir for folder-rooted projects

Add resolveProjectDir() and metadata-aware variants of listFiles,
readProjectFile, writeProjectFile, ensureProject so a project's files
can live under metadata.baseDir (the user's chosen folder) instead of
.od/projects/<id>/. metadata.baseDir is opt-in — projects without it
keep the existing .od/projects/<id>/ behavior unchanged.

When listFiles walks a baseDir-rooted project, it skips conventional
build / install dirs (node_modules, .git, dist, build, .next, .nuxt,
.turbo, .cache, .output, out, coverage, __pycache__, .venv, vendor,
target, .od, .tmp) so the file panel stays focused on design content
instead of being dominated by lockfiles and node_modules.

Add detectEntryFile() — best-effort lookup for index.html or any
.html at the folder root, used by the import endpoint to seed the
initial active tab.

Refs nexu-io/open-design#597

* feat(daemon): add POST /api/import/folder endpoint

Creates a project rooted at the submitted local folder. metadata.baseDir
points at that folder and OD reads / writes there directly — no copy,
no shadow tree, mirroring how Cursor / Claude Code / Aider behave. The
user owns the workspace and is responsible for their own version
control.

Safety:
- baseDir is canonicalized via fs.promises.realpath() at import time so
  user-controlled symlinks can't redirect later writes. resolveSafe
  enforces the bounds check against the literal stored path; without
  realpath, a symlink (e.g. ~/sneaky → /etc) would let writeProjectFile
  escape the project tree at every later call because the OS follows
  the symlink at open() time.
- Post-realpath lstat ensures the canonical target is itself a real
  directory (defense-in-depth).
- The data directory (RUNTIME_DATA_DIR) and its descendants are
  refused after symlink resolution so a redirect into the daemon's
  own state can't masquerade as a project import.

The web client wires this through state/projects.ts → App.tsx,
landing the user on the auto-detected entry file when present.

Refs nexu-io/open-design#597

* feat(desktop): expose native folder picker to renderer

Adds an Electron preload script that exposes window.electronAPI.pickFolder
via contextBridge. Wires dialog.showOpenDialog through ipcMain so the
web UI can open a native folder selector for project import. Browser-only
users fall back to a text input for the absolute path (handled in the
web layer); the picker stays an optional convenience on the desktop
binary.

ipcMain.handle() registers handlers in an internal map that is not
exposed via eventNames(), so the natural-looking guard
  if (!ipcMain.eventNames().includes('dialog:pick-folder')) ipcMain.handle(...)
is always true. On a second createDesktopRuntime() call (dev hot-reload,
packaged-vs-electron mode swap) the body re-runs and ipcMain.handle()
throws 'Attempted to register a second handler'. Use removeHandler()
+ handle() unconditionally — removeHandler() is a documented no-op
when nothing is registered, making the pair idempotent.

Includes *.cts in the apps/desktop tsconfig so the preload script is
typechecked.

Refs nexu-io/open-design#597

* feat(web): add 'From existing folder' option to New Project

UI surface for the import flow:
- A new 'Open folder' affordance in NewProjectPanel that uses the
  native picker on Electron (window.electronAPI.pickFolder) and falls
  back to an absolute-path text input in the browser.
- importFolderProject() in state/projects.ts: typed wrapper around
  POST /api/import/folder using @open-design/contracts types.
- App.tsx wires the response: prepend the new project to the list,
  navigate to it, and select the auto-detected entry file as the
  active tab.

Skill / design-system pickers from the existing prototype tab are
reused — folder import is a project-creation flow, not a separate
project type.

Refs nexu-io/open-design#597

* docs(architecture): document folder-import endpoint

Adds POST /api/import/folder to the daemon API table and a 'Folder
import' section explaining the single-mode design (direct read/write
in metadata.baseDir, mirroring Cursor / Claude Code / Aider), the
realpath() canonicalization, the RUNTIME_DATA_DIR refusal, and the
SKIP_DIRS list applied to listFiles for baseDir-rooted projects.

Refs nexu-io/open-design#597

* test(daemon): unit + integration tests for folder import

Two new files:

apps/daemon/tests/folder-import-projects.test.ts (13 unit tests):
- resolveProjectDir behavior under all metadata combinations,
  including the fallback when baseDir is relative and the
  isSafeId-bypass when baseDir is set
- detectEntryFile: index.html priority, .html fallback, null when
  no html, no descent into subdirs
- listFiles with metadata.baseDir: walk, SKIP_DIRS hides node_modules
  / .git / dist, back-compat for projects without baseDir

apps/daemon/tests/folder-import-route.test.ts (10 integration tests):
- Happy path: baseDir stored in metadata, importedFrom='folder',
  conversation created, entry file detected
- Error paths: missing baseDir, empty, relative, non-existent,
  pointing at a file
- Security: realpath canonicalization (the symlink test was the one
  that surfaced the original /var vs /private/var mismatch in
  RUNTIME_DATA_DIR comparison on macOS)
- Security: a symlink that resolves into RUNTIME_DATA_DIR is rejected
  after realpath, not before

Refs nexu-io/open-design#597

* fix(daemon): wire baseDir metadata into chat + deploy reads

Two bugs caught in Codex automated review of #624:

1. chat-route was passing the metadata object directly as the listFiles
   opts argument: `listFiles(PROJECTS_DIR, projectId, chatMeta)`. The
   listFiles contract reads opts.metadata, not opts itself, so this
   silently fell back to .od/projects/<id>/ instead of the imported
   folder. existingProjectFiles was empty for baseDir-rooted projects.
   Wrap as `{ metadata: chatMeta }`.

2. deploy.ts read project files via readProjectFile without the
   metadata third argument, so for baseDir-rooted projects the deploy
   and preflight endpoints would look in .od/projects/<id>/ and fail
   with file-not-found instead of reading the imported folder. Thread
   options.metadata through buildDeployFilePlan → readProjectFile and
   pass project?.metadata at the two server.ts callsites
   (`POST /api/projects/:id/deploy` and the preflight endpoint).

Add a regression test that locks the listFiles contract: passing a
bare metadata object as opts must NOT scan baseDir — it must fall back
to the standard project dir, otherwise callers can leak the wrong
folder by mistake.

Refs nexu-io/open-design#597, #624 (Codex review)

* fix(daemon): ensure correct metadata handling in folder import

Addressed issues with metadata handling in folder import functionality. Updated the listFiles and readProjectFile methods to correctly utilize the metadata.baseDir, ensuring that project files are read from the intended directory. Added regression tests to verify that passing a bare metadata object does not inadvertently scan the baseDir, maintaining the integrity of project file access.

Refs nexu-io/open-design#597

* fix(daemon): security hardening from Codex review of #624

P1 findings from automated review:

1. POST /api/projects + PATCH /api/projects/:id rejected
   client-supplied metadata.baseDir. baseDir is privileged: it lets a
   project root inside the user's filesystem, and the realpath() +
   RUNTIME_DATA_DIR reentry checks live only on /api/import/folder.
   Allowing it on the generic create/patch path lets an attacker
   smuggle e.g. /etc through and bypass every import-time guard.
   Both endpoints now refuse a baseDir field with 400.

2. resolveSafeReal() helper: realpath()s each candidate path (or its
   longest existing prefix for write paths) and re-validates against
   realpath(projectRoot). The original resolveSafe() only did a
   string-prefix check, which was fooled by symlinks *inside* a
   baseDir-rooted project. A repo containing 'assets -> /Users/me/.ssh'
   passed the literal prefix check but readFile() followed the link
   at open() time. resolveSafeReal() is now used by readProjectFile,
   writeProjectFile, and deleteProjectFile.

3. Multer chat-upload destination now resolves to metadata.baseDir for
   imported folder projects via a module-level lookup wired to db at
   startServer() boot. Previously attachments landed in
   .od/projects/<id>/ even for baseDir projects, so the agent (which
   runs with cwd=baseDir) couldn't open them.

P2 findings:

4. searchProjectFiles threads metadata through listFiles +
   resolveProjectDir so /api/projects/:id/search hits the right tree.
5. buildProjectArchive + buildBatchArchive now accept metadata so
   'Download .zip' works for imported folder projects.
6. Watcher subscribe() resolves to baseDir for imported projects so
   live-reload SSE actually fires when the user edits files in their
   own folder. Registry stays keyed by the canonical directory.
7. Template snapshotting reads source-project files with metadata
   so a template can be saved from a baseDir-rooted source.

Tests:

- Regression: POST /api/projects with metadata.baseDir → 400.
- Regression: descendant symlink (assets/leak.txt -> /etc/hosts) is
  refused on the raw read endpoint.

Refs nexu-io/open-design#597, #624 (Codex P1+P2 review)

* fix(daemon): close two regressions found in #624 review round 2

@mrcfps caught two more correctness gaps:

1. Archive root symlink escape — buildProjectArchive accepts an optional
   ?root=<subdir> param to scope the zip to a subdirectory. The path was
   resolved with the string-only resolveSafe(), so a directory symlink
   inside an imported folder (docs -> /Users/me/.ssh) passed the prefix
   check and collectArchiveEntries() then walked outside the project
   tree. Switch to the symlink-aware resolveSafeReal() — the same one
   that already protects raw read/write/delete paths. The walker itself
   already skips dirent symlinks via !isDirectory && !isFile, so
   canonicalizing the root is the only missing piece.

2. PATCH metadata wiped baseDir — updateProject() replaces metadata
   wholesale. The previous guard only blocked an explicit baseDir
   change, but a normal patch that *omits* baseDir (a UI editing
   linkedDirs only sends { metadata: { kind, linkedDirs } }) silently
   detached imported projects from their folder root. Subsequent
   reads/writes/watch/deploy fell back to .od/projects/<id>.

   Re-stamp the immutable folder-import fields (baseDir, importedFrom='folder')
   from the existing project record onto the incoming patch when the
   project is imported. A patch that supplies a *different* baseDir
   still gets rejected as before; a patch that supplies the *same*
   baseDir is accepted as a no-op. A patch on a non-imported project
   that tries to set baseDir is also still rejected (preserves the
   POST /api/projects guard from the previous round).

Tests:

- archive endpoint: ?root=<symlink-to-/etc> → 400.
- patch endpoint: PATCH that omits baseDir on an imported project keeps
  baseDir intact (project still resolves to the user's folder after).

Refs nexu-io/open-design#597, #624 (Codex P1 round 2)

* fix(web): add Indonesian deploy provider copy

---------

Co-authored-by: INFINITY <valentyn.sotov@trendarena.app>
Co-authored-by: Siri-Ray <2667192167@qq.com>
2026-05-07 20:43:31 +08:00
Tom
8630fd380a
feat(daemon): close pi adapter parity gaps
Closes pi adapter parity gaps for image paths, extra allowed dirs, error events, and sendAgentEvent routing.
2026-05-07 20:03:46 +08:00
Tuola-waj
5abca505b1
add FlowAI live dashboard template skill (#801)
* add flowai live dashboard template skill

Introduce a new template-mode skill under the live-artifacts scenario with a default interactive example and seed template so users can generate polished, refresh-ready team dashboards quickly.

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

* add preview screenshot for flowai live dashboard template

Attach the provided dashboard screenshot under docs/screenshots/skills so the template contribution includes a visual preview artifact.

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

* fix(flowai-template): reposition as static prototype dashboard skill

Address review feedback on PR #801:

- SKILL.md: drop `scenario: live-artifacts` and live-related triggers;
  align with peer single-page dashboard skills using
  `mode: prototype` + `scenario: operations` so the four-file
  live-artifact contract no longer applies.
- references/checklist.md: rewrite quality gates around the static
  prototype scope (export-from-DOM, responsive breakpoints, theme-aware
  charts).
- assets/template.html:
  - CSV export now reads every visible row from the table DOM,
    including the Workflow column, instead of a hardcoded fixture.
  - Add 1300px and 720px breakpoints; the main grid stacks to one
    column, stat cards fall back to two then one, tabs wrap, table
    scrolls horizontally on phones.
  - Move chart colors into CSS variables (--chart-stroke,
    --chart-fill, --chart-axis, --chart-bar-label, --chart-bar-value)
    so dark-mode toggling re-derives them; chart canvases are
    re-rendered after theme switch.
  - Hash-sync tabs (#members | #details | #activity), animate the
    role bar chart only on first reveal of the details tab,
    fall back when CanvasRenderingContext2D.roundRect is unavailable,
    add Esc to exit zoom and prevent tooltip clipping.
- example.html: title cleanup to match new skill identity.

Localized content:
- Add `flowai-live-dashboard-template` to DE/FR/RU
  SKILL_IDS_WITH_EN_FALLBACK lists in apps/web/src/i18n so the
  e2e localized-content test passes.

---------

Co-authored-by: tuolaji <tuola@tuolajideMacBook-Air.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Tuola Ge <gexingli@refly.ai>
2026-05-07 19:07:45 +08:00
Joey-nexu
55aa24167b
add live-dashboard skill (#778)
* add live-dashboard skill

Notion-style team dashboard rendered as a Live Artifact.

Wires the OD 0.4.0 connector catalog (#381) end-to-end:

refresh-on-open, manual Refresh tween, auto-refresh, stale state.

Falls back to seeded mock data when no connector is bound.

* address PR #778 review comments

P1 — security and correctness:
- skills/live-dashboard/assets/template.html · skills/live-dashboard/example.html: escape every connector-derived string before innerHTML interpolation. Adds a tiny e() helper and routes feed.who/action/target/suffix/icon, row.title/icon/due/prio, person.name/color/id, KPI label/delta through it. Closes lefarcen #3200122795 + #3200122820.
- skills/live-dashboard/SKILL.md (live behavior section): align connector poll URL with references/connectors.md — POST /api/od/connectors/poll with { project, read } body, not /api/od/connectors/<id>/poll. Closes codex bot #3200100897.
- apps/web/src/i18n/content{,.ru,.fr}.ts: register live-dashboard in DE_/RU_/FR_SKILL_IDS_WITH_EN_FALLBACK so the localized-content e2e check passes. Closes mrcfps #3200122059.
- skills/live-dashboard/references/connectors.md: prepend a Status callout that names skills/live-artifact/ as the canonical file/CLI live-artifact contract and frames the HTTP shape as a forward-looking proposal sitting alongside it (out-of-the-box the artifact runs on seeded data; only seedNextChange() needs swapping when POST /api/od/connectors/poll lands). Closes lefarcen #3200122811.

P2 — quality and honesty:
- skills/live-dashboard/references/connectors.md: rewrite the auth_ref resolution step to match apps/daemon/src/media-config.ts (OD_MEDIA_CONFIG_DIR → OD_DATA_DIR → <projectRoot>/.od/media-config.json, $HOME/~/relative paths handled via expandHomePrefix). Closes codex bot #3200100906.
- skills/live-dashboard/example.html: switch the live-pill to a sticky Sample data state with a grey static dot, rewrite the callout to admit the figures are seeded fixtures, retitle the toast and the refresh tooltip, and refuse to flip to Live · synced inside updateTimes(). Adds a .pill-live.sample CSS variant. Closes lefarcen #3200122823.
- skills/live-dashboard/assets/template.html: hoist <meta name=od:project> from <body> into <head>. Closes lefarcen #3200122832.
- skills/live-dashboard/assets/template.html · example.html: add role=button + tabindex=0 + aria-current to every clickable .ws / .side-search / .nav-item, and wire a single document-level keydown handler that maps Enter/Space to a synthetic click for any role=button div (skipping real buttons / anchors / form controls). Closes lefarcen #3200122837.
- skills/live-dashboard/assets/template.html: implement the KPI tween + flash + snapshotKpi() the SKILL.md prose already promised — first render builds escaped cards, subsequent renderKpi(prev) calls tween numeric values and flash() the cells that actually changed; refresh() now calls snapshotKpi() before mutating state and forwards prev. SKILL.md spells out the wire-up. Closes lefarcen #3200122839.

* gate KPI tween + flash + row/feed highlight on prefers-reduced-motion

Addresses mrcfps's non-blocking review item on PR #778 (comment #3200614137,
template.html:453). The CSS @media (prefers-reduced-motion: reduce) block
already neutralizes CSS animations and transitions, but the new JS-driven
helpers kept moving for opted-out users:

- tweenText() scheduled requestAnimationFrame updates for 600ms
- flash() toggled the .flash highlight class for 700ms
- renderFeed()/renderRows() applied .feed-row.new / .db-row.changed
  classes which carry transient backgrounds even when their CSS
  animations are off

Both runtimes (assets/template.html and example.html) now share a
reduceMotion() helper (window.matchMedia('(prefers-reduced-motion:
reduce)').matches). When it returns true:

- tweenText()/tween() set the final value immediately and return
- flash() returns without touching the class
- renderFeed()/renderRows() pass null as the highlight id so the .new /
  .changed classes are never applied

Normal-motion users see the existing tween + flash + highlight pulse
unchanged. Keeps the P0 prefers-reduced-motion row in
references/checklist.md honest for agents that copy this template
verbatim.

---------

Co-authored-by: joey <joey@joeydeMacBook-Air.local>
Co-authored-by: joeylee12629-star <joeylee12629-star@users.noreply.github.com>
2026-05-07 18:21:22 +08:00
Vedank Vansia
b95ba5e79e
add waitlist-page skill (#555)
* add waitlist-page skill

* fix(waitlist-page): address PR review feedback

- Remove novalidate from example.html form
- Ensure checkValidity() guard present in both template and example
- Remove required from firstname input in template
- Add token escaping rules to SKILL.md workflow (step 9)
- Add token mapping/fallback rules for BORDER/SUCCESS/STRIPE/DECO (step 7)
- Fix mobile quality gate to be measurable (375x667, 390x844)
- Promote hardcoded #fff, rgba(0,0,0,0.9), rgba(255,255,255,0.9) to
  CSS variables (--btn-label, --ticker-bg, --ticker-fg) in template
- Create references/checklist.md with P0/P1/P2 tiers; countdown timer
  is now a hard P0 prohibition; a11y gate split into six specific checks"

* fix: resolve P0 color and accessibility issues

- Add role=status to success messages for screen reader announcement
- Replace all hardcoded hex/rgba colors with template tokens
- Update SKILL.md with comprehensive color token mapping rules
- SVG decorations now use CSS variables instead of hardcoded strokes

* fix: address PR review feedback on scope, scrolling, and font tokens

Fixes:
- Restore pricing-page files accidentally deleted in previous commit
  (skills/pricing-page/SKILL.md and example.html now back on branch)
- Remove temp-original.html scratch file from commit
- Fix mobile viewport scrolling: change 'height: 100vh; overflow: hidden'
  to 'min-height: 100svh; overflow-x: hidden; overflow-y: auto'
  so content doesn't clip on 375×667 and 390×844 screens
- Split font tokens into URL-safe and CSS-safe variants:
  * {{DISPLAY_FONT_URL}} and {{DISPLAY_FONT_CSS}} for display fonts
  * {{BODY_FONT_URL}} and {{BODY_FONT_CSS}} for body fonts
  This fixes encoding: spaces as '+' in Google Fonts URL, literal in CSS
- Update SKILL.md frontmatter with new font input fields
- Update token escaping rules to document the split

* fix: resolve token contract mismatch and remove hardcoded colors from example.html

P0 Fixes:
- Remove all hardcoded colors from example.html (except #2D6A4F for --success)
- Use CSS variables for all color values: --btn-label, --ticker-bg, --ticker-fg, --deco-stroke
- Fix gradient to use var(--deco) instead of hardcoded #D1632B
- Apply consistent color expressions across decorations and text

Token Contract Fixes:
- template.html now uses full CSS expressions for opacity-based colors:
  * {{BORDER_EXPRESSION}} instead of {{BORDER_HEX}} (no # prefix)
  * {{BTN_LABEL_EXPRESSION}} instead of {{BTN_LABEL_HEX}}
  * {{TICKER_BG_EXPRESSION}}, {{TICKER_FG_EXPRESSION}}, {{DECO_STROKE_EXPRESSION}}
- Remove extra quotes from font tokens in template:
  * --font-body: {{BODY_FONT_CSS}} instead of '{{BODY_FONT_CSS}}'
  * Font tokens are already quoted if needed, no wrapping
- Update SKILL.md frontmatter with all color expression inputs and descriptions
- Update token mapping rules to clarify the new contract:
  * Hex tokens: simple six-digit colors
  * Expression tokens: full CSS values (rgba/color-mix), no # prefix
  * Font tokens: CSS font-family values, no extra wrapping
- Update token escaping rules to reflect new contract

This ensures agents can follow SKILL.md instructions without producing invalid CSS.

* fix: remove final hardcoded colors from example.html - P0 complete

- Button text: #fff → var(--btn-label)
- Ticker background: rgba(0,0,0,0.9) → var(--ticker-bg)
- Ticker text: rgba(255,255,255,0.9) → var(--ticker-fg)
- Logo text: fill=white → fill=var(--btn-label)

All colors now derive from design system tokens. Only #2D6A4F (--success) allowed hardcoded exception.

* fix: correct --btn-label contrast for CTA readability

Change --btn-label from #1A1410 (same as button background) to #FDE8DF
(light background color) so button text has proper contrast against
the dark --accent button background.

This resolves the black-text-on-black issue that broke the main
email capture action and satisfies the checklist button contrast gate.

* fix: add visible focus indicator for input accessibility

P1 Accessibility Polish:
- Update .form-row input:focus to include outline and outline-offset
- Before: border-color only, removing default outline (no visible focus)
- After: border-color + 2px outline + 2px offset (clear focus indicator)

This satisfies the checklist P1 focus-style gate and ensures keyboard
users can see which form field has focus. Both example.html and
template.html updated so agents copy complete focus patterns.

* fix: remove hardcoded logo shadow color - P0 compliance

- Add --logo-shadow CSS variable derived from foreground
- example.html: box-shadow 0 2px 8px rgba(0,0,0,0.08) → var(--logo-shadow)
- template.html: add {{LOGO_SHADOW_EXPRESSION}} placeholder
- Update SKILL.md with logo_shadow_expression input and mapping rules

All colors in example.html now derive from design system tokens.
Ensures agents copy compliant reference without hardcoded shadow colors.

* fix: register waitlist-page skill in i18n localized content registry

Add waitlist-page to locale-specific skill fallback lists so the web
content coverage test passes when the new skill is discovered:

- apps/web/src/i18n/content.ts: Add to DE_SKILL_IDS_WITH_EN_FALLBACK
- apps/web/src/i18n/content.fr.ts: Add to FR_SKILL_IDS_WITH_EN_FALLBACK
- apps/web/src/i18n/content.ru.ts: Add to RU_SKILL_IDS_WITH_EN_FALLBACK

The skill falls back to English localization for now; localized
descriptions can be added to each locale file later.

Fixes: web content coverage test now passes (6/6 tests).

* fix: wire template and checklist into skill workflow as mandatory gates

Restructure waitlist-page SKILL.md workflow to enforce the hardened
template-based execution path:

- Add Preflight section: agents MUST read assets/template.html first
- Add explicit token mapping and escaping rules (steps 2-4)
- Add mandatory Validation section: run references/checklist.md P0/P1
  gates BEFORE emitting artifact; fail fast if any P0 gate fails
- Update Quality gates section to emphasize template-based execution
  and reinforce P0/P1 gate hierarchy
- Update Output section: only emit after P0 passes; re-validate on
  iterations

This prevents agents from writing HTML from scratch or skipping the
hardened seed (template) and validation (checklist) that this PR adds.

* refactor(waitlist-page): replace literal logo placeholder with token

- Replaced `[LOGO]` with `{{LOGO_MARK}}` in template.html
- Added `logo_mark` to inputs in SKILL.md
- Updated mapping rules in SKILL.md to handle raw SVG or text for logo
- Updated P0 validation gates in SKILL.md and checklist.md to ensure logo replacement

* fix(waitlist-page): enforce strict escaping and sanitization for logo token

- Mandate HTML-escaping for text initials.
- Enforce strict allowlist-based sanitization for inline SVG (stripping `<script>`, `on*`, `<foreignObject>`, `href`, `xlink:href`, `url()`).
- Add fallback to escaped text initials for invalid/unsafe SVG.

* docs(waitlist-page): sync logo_mark frontmatter description with rules

- Updated the `logo_mark` input description in the SKILL.md frontmatter to explicitly outline the new requirements for HTML-escaped text or strict allowlist-sanitized SVG.

* fix(waitlist-page): add logo_fg_expression to guarantee contrast in logo mark text fallback

- Added `--logo-fg` CSS variable mapped to `{{LOGO_FG_EXPRESSION}}`.
- Updated `.logo-container` in `template.html` to inherit typography styles and apply `--logo-fg` for safe fallback when rendering escaped initials.
- Enforced WCAG AA contrast for logo initials against container background in `checklist.md`.

* refactor(waitlist-page): migrate hex color tokens to full css expressions

* refactor(waitlist-page): strict validation for color expression tokens to prevent CSS injection

* docs(waitlist-page): update validation summary to reflect strict color grammar

---------

Co-authored-by: Siri-Ray <2667192167@qq.com>
2026-05-07 17:39:17 +08:00
github-actions[bot]
71a344f951
Update docs/assets/github-metrics.svg - [Skip GitHub Action] (#718)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-07 10:12:29 +08:00
Mario
2afb002a62
docs: fix broken links to pi-ai (404), split into coding-agent and ai packages (#277)
* docs: fix broken pi-ai links, point to correct pi-mono packages

All links to https://github.com/mariozechner/pi-ai returned 404 after
the project was restructured into the badlogic/pi-mono monorepo.

- "pi" / "Pi" (the CLI tool the daemon scans for) now points to
  packages/coding-agent
- "pi-ai" (the multi-provider LLM API) now points to packages/ai
  via the shared [piai] reference definitions

Closes #275.

* fixup! Merge remote-tracking branch 'upstream/main' into docs/fix-pi-pi-ai-links

Fix [piai] reference in README.ar.md and README.es.md: was incorrectly
pointing to packages/coding-agent (pi CLI) instead of packages/ai (pi-ai
provider library).

* fixup! fix row order in README.uk.md: move Pi after DeepSeek TUI to match English README
2026-05-07 00:41:11 +08:00
mamba
570d06419c
feat[qoder cli] add Qoder CLI agent support (#626)
* chore(agent): 增加对 Qoder CLI 的支持和识别

- 在 QUICKSTART 文档中添加 Qoder CLI 为可选本地 agent CLI
- 更新代码中 agents.ts 注释包含 Qoder CLI 扫描支持
- 修改首次加载时检测的可用 CLI 列表,加入 Qoder CLI
- 在多个语言版本的 README 中增加 Qoder CLI 支持及相关徽章统计
- 更新 agent 适配器与事件解析相关的代码注释和文档,包含 qoder-stream-json 解析器
- 调整 Windows 下 spawn 行为以支持 Qoder CLI 的 stdin 提供 prompt
- 修复多语言文档对支持的 CLI 数量描述错误,确保数据保持同步

Change-Id: I388f2f61c60ce8faa7cef5d84eb407950f8bdbfb
Co-developed-by: Qoder <noreply@qoder.com>

* chore(agent): 增加对 Qoder CLI 的支持和识别

- 在 QUICKSTART 文档中添加 Qoder CLI 为可选本地 agent CLI
- 更新代码中 agents.ts 注释包含 Qoder CLI 扫描支持
- 修改首次加载时检测的可用 CLI 列表,加入 Qoder CLI
- 在多个语言版本的 README 中增加 Qoder CLI 支持及相关徽章统计
- 更新 agent 适配器与事件解析相关的代码注释和文档,包含 qoder-stream-json 解析器
- 调整 Windows 下 spawn 行为以支持 Qoder CLI 的 stdin 提供 prompt
- 修复多语言文档对支持的 CLI 数量描述错误,确保数据保持同步

Change-Id: Id33f125b7c0b1a1c0b0274073da74d1578c324f7
Co-developed-by: Qoder <noreply@qoder.com>

* feat(agent-icon): 添加新的Qoder徽标SVG图形组件

- 新增qoderGlyph函数,返回指定大小的SVG格式图形
- 图形包含多路径定义,颜色使用深灰和绿色填充
- 该组件可用于替代或补充现有AgentIcon图标功能
- 提升应用程序的品牌标识和视觉表现力

Change-Id: I4eca18166b5e33bc6229b40b2531d5a54607a560
Co-developed-by: Qoder <noreply@qoder.com>

* Translate to English:

---

**docs(readme): update to expand CLI agents to 16**

- Increased the number of coding agent CLIs from 11 to 16
- New agents included: Devin for Terminal, Kiro CLI, Kilo, Mistral Vibe CLI, DeepSeek TUI

**docs(readme): update to expand supported coding agents to 16**

- Increased the number of supported code agent CLIs from 11 to 16
- Added support for new CLI tools: Devin for Terminal, Kiro CLI, Kilo, Mistral Vibe CLI, DeepSeek CLI
- Added automatic CLI detection and switching while maintaining support for more agents
- Added BYOK proxy TUI
- Expanded compatibility and support coverage in the README’s multiple language versions
- Reflected changes across all README translations (Arabic, German, French, Japanese, Korean)
- Updated badges and descriptions to reflect CLI count and feature changes
- Added event parsers and protocols for the new CLIs in the agent transport implementation
- Updated the BYOK proxy and tool exploration features to be compatible with the expanded CLIs

Change-Id: I89786b4a0b09bd279fb23265c2177076206fc5af
Co-developed-by: Qoder <noreply@qoder.com>

* feat(daemon): 支持 imagePaths 参数作为附件路径传递给 Qoder

- 修改 buildArgs 函数,添加 --attachment 参数处理 imagePaths 中的绝对路径
- 过滤并忽略空字符串、非字符串及相对路径的 imagePaths 项
- 在单元测试中覆盖 imagePaths 参数支持及无效项过滤逻辑
- 在文档中补充 Qoder 运行时适配器对 --attachment 参数的说明

Change-Id: Ibfc3583ba86c6d258d524912559e97b77bf1dc87
Co-developed-by: Qoder <noreply@qoder.com>

* docs(runtime): 说明Qoder适配器继承用户令牌的环境变量

- 添加文档说明检测代理仅为可用性探针,不进行身份验证
- 说明Qoder CLI账号状态独立,认证通过运行时错误路径反馈
- 详细描述子进程环境继承机制及静态环境变量与用户私密令牌区分
- 明确QODER_PERSONAL_ACCESS_TOKEN通过守护进程环境传递,不写入静态环境
- 解释Qoder验证由Qoder CLI负责,支持持久登录和自动化环境变量注入

test(agent): 添加QODER_PERSONAL_ACCESS_TOKEN环境变量继承测试

- 验证qoder适配器环境继承守护进程中的QODER_PERSONAL_ACCESS_TOKEN
- 确认qoder适配器未在静态环境变量中定义用户令牌
- 保证用户私密令牌不会被写入静态适配器环境配置

Change-Id: Ie61869afbe497df1b16879b4e47b35123f758ed8
Co-developed-by: Qoder <noreply@qoder.com>

* fix(daemon): 改进Qoder模式支持及错误处理机制

- 更新Qoder CLI参数,使用`--yolo`替代`--permission-mode bypass_permissions`
- 将工作目录参数从`--cwd`改为`-w`以符合Qoder文档
- 在agent流事件处理中新增错误捕获并通过SSE错误事件发送
- 运行结束时若检测到agent流错误,则标记运行失败
- 测试中fix(daemon): 优化Qoder代理参数与错误处理

- 调整Qoder启动参数,改用`--yolo`和`-w`替代旧参数,避开argv长度限制
- 增强代理流事件处理,捕获并通过SSE错误通同步更新Qoder参数使用及相应断言
- 新增端到端测试,覆盖Qoder助手错误通过SSE错误通道反馈及运行状态失败处理
- 补充工具函数辅助测试事件流读取与运行状态轮询

Change-Id: I5d933745c3659e093b0d2d807f22726e7f83eb48
Co-developed-by: Qoder <noreply@qoder.com>

* feat(qoder-stream): 识别并报告Qoder运行错误事件

- 新增messageFromResult函数以从结果对象提取错误信息
- 在处理result事件时根据is_error字段触发error事件
- error事件携带具体错误消息和原始数据
- 添加测试验证Qoder运行返回is_error且退出码为0时正确触发错误事件
- 更新qoder流解析测试以校验错误事件映射
- 在聊天路由测试中增加针对Qoder错误运行的端到端场景验证

Change-Id: Ie98ac518135dbec3181c52de5a49afdea993e279
Co-developed-by: Qoder <noreply@qoder.com>
2026-05-06 19:54:03 +08:00
Caprika
8eb9b1b506
Implement manual edit mode (#620) 2026-05-06 16:13:52 +08:00
github-actions[bot]
241846e1ef
Update docs/assets/github-metrics.svg - [Skip GitHub Action] (#592)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-06 09:21:39 +08:00
github-actions[bot]
e9fd616a5a
Update docs/assets/github-metrics.svg - [Skip GitHub Action] (#489)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-05 11:57:47 +08:00
Ajay Satish
ec7dafc007
feat(daemon): add Kilo CLI (ACP) (#480)
* docs(readme): refresh contributors wall

* docs(readme): refresh contributors wall

* feat: kilo cli

* fix: use default model option for kilo

* chore: add  agent_diff id unique test

* chore: add deepseek to docs
2026-05-05 09:17:56 +08:00
Tom Huang
da2b007a43
feat(daemon): add DeepSeek TUI as a code agent adapter (#439)
* feat(daemon): add DeepSeek TUI as a code agent adapter

Register `deepseek` (with `deepseek-tui` cargo-only fallback) in
AGENT_DEFS via `deepseek exec --auto [--model X] <prompt>` and plain-text
streaming. Ships `deepseek-v4-pro` / `deepseek-v4-flash` as fallback
model hints; users can paste any other id (incl. NIM / Fireworks /
SGLang routes) via the custom-model input.

Web UI gets a DeepSeek-blue gradient icon, label/alias mapping, and
docs/agent-adapters.md §5.9 documents the auth state, prompt-as-argv
Windows size limit, and the upstream gap that prevents stdin delivery
today (clap declares `prompt: String` as a required positional).

Adds .deepseek/ to .gitignore alongside the other per-agent runtime
data dirs so first-launch trust files don't leak into git.

* fix(daemon): drop unsupported deepseek-tui fallback bin

The `deepseek` dispatcher owns `exec` / `--auto`; `deepseek-tui` is the
runtime companion it invokes. Listing `deepseek-tui` in fallbackBins
advertised availability for a host that only had the TUI binary, but
buildArgs still emitted `<resolved> exec --auto <prompt>` — which
deepseek-tui itself doesn't accept, so the first /api/chat run would
fail. Upstream documents both binaries as required (npm and cargo paths
install them together), so the fallback didn't correspond to a supported
install. Pin the absence in the agents test and update docs §5.9 + the
adapter table to match.

Generated-By: looper 0.4.0 (runner=fixer, agent=claude-code)

* fix(daemon): pre-flight DeepSeek TUI prompts against argv byte budget

DeepSeek's exec mode requires the prompt as a positional argv arg (no
`-` stdin sentinel upstream), so a fully composed OD prompt — system
text + history + skills + design-system content + the user message —
can blow Windows' ~32 KB CreateProcess limit (or Linux MAX_ARG_STRLEN
on extreme edges) and surface as a generic spawn failure instead of
a DeepSeek-specific, user-actionable message. The adapter now declares
`maxPromptArgBytes = 30_000` (leaves ~2.7 KB argv headroom for `exec
--auto --model <id>` and Windows quoting), and the /api/chat spawn
path checks the composed prompt against that budget before calling
`spawn`. Oversized prompts fail fast with `AGENT_PROMPT_TOO_LARGE`
and guidance to reduce skills/design context or pick an adapter with
stdin support.

Generated-By: looper 0.4.0 (runner=fixer, agent=claude-code)

* test(daemon): pin DeepSeek argv-budget guard with regression tests

The previous spawn-path guard inlined the byte-budget check in the
chat handler, so the only safety net for the DeepSeek argv-only
prompt-delivery shape was a static "the field exists" assertion —
nothing actually exercised the AGENT_PROMPT_TOO_LARGE path or the
short-prompt happy path. Extract the check into a pure
`checkPromptArgvBudget(def, composed)` helper in agents.ts, call it
from /api/chat before bin resolution (so the guard is order-
independent and fires regardless of whether the adapter binary is
on PATH in CI), and add a regression test that exercises both the
oversized-prompt branch (over the conservative under-Windows-
CreateProcess budget) and the short-prompt branch, plus a UTF-8
byte-vs-codepoint case and a stdin-adapter no-op case so the guard
can't silently regress or leak onto adapters that ship the prompt
over stdin.

Generated-By: looper 0.4.0 (runner=fixer, agent=claude-code)

* fix(daemon): pre-flight DeepSeek prompts against Windows .cmd-shim quoting

The first-pass argv-byte guard only inspects the raw composed prompt, so
on Windows an npm-installed `deepseek` resolves to a `.cmd` shim and the
spawn path then wraps the call in `cmd.exe /d /s /c "<inner>"` with
every embedded `"` doubled by `quoteWindowsCommandArg`. A quote-heavy
prompt (code blocks, JSON-shaped skill seeds) under the 30,000-byte
budget can therefore still expand past CreateProcess's 32_767-char
`lpCommandLine` cap and surface as a generic spawn ENAMETOOLONG instead
of the DeepSeek-named, actionable `AGENT_PROMPT_TOO_LARGE` the budget
guard was meant to provide. Add a second pure helper
`checkWindowsCmdShimCommandLineBudget(def, resolvedBin, args)` that
mirrors the platform layer's per-arg quoting and recomputes the would-be
command line length whenever the resolved binary is a `.cmd` / `.bat`
shim, and call it from `/api/chat` after `buildArgs` / `resolveAgentBin`
so the same SSE error fires before `spawn`. Pin the new path with a
quote-heavy regression (prompt is under the byte budget but doubles
past the kernel cap) plus no-op tests for non-`.cmd` resolutions, null
bin, and stdin-only adapters so the guard can't drift back.

Generated-By: looper 0.4.0 (runner=fixer, agent=claude-code)

* fix(daemon): extend DeepSeek argv guard to direct .exe Windows installs

The cmd-shim guard added in 9011361 early-returned for non-`.cmd` /
`.bat` resolutions, so a Windows host that resolved `deepseek` directly
to a `.exe` (cargo-installed CLI, hand-built release, anything outside
the npm shim path) bypassed the post-`buildArgs` budget check entirely.
Direct `.exe` spawns skip the `cmd.exe /d /s /c "<inner>"` wrap, but
Node/libuv still composes a CreateProcess `lpCommandLine` by walking
each argv element through `quote_cmd_arg` — every embedded `"` becomes
`\"`, backslashes adjacent to a quote get doubled. A quote-heavy
prompt (code blocks, JSON-shaped skill seeds) under the 30,000-byte
`maxPromptArgBytes` budget can therefore still expand past the kernel's
32_767-char cap on those installs and surface as a generic spawn
ENAMETOOLONG instead of the actionable `AGENT_PROMPT_TOO_LARGE` the
guard was meant to provide.

Add a sibling pure helper `checkWindowsDirectExeCommandLineBudget(def,
resolvedBin, args)` that mirrors libuv's quoting math (empty -> `""`;
no whitespace/quote -> pass-through; quote-only -> simple wrap;
otherwise per-char escape with backslash-doubling around quotes and
trailing backslashes) and recomputes the would-be command line length
whenever the resolved binary is a non-shim Windows install. The two
Windows guards are mutually exclusive: the cmd-shim guard owns
`.bat` / `.cmd`, the direct-exe guard owns everything else, so a
single oversized prompt never double-emits an SSE error. POSIX paths
on POSIX hosts still skip both guards (no CreateProcess in play), and
stdin-delivered adapters still skip the entire post-buildArgs path.

Wire the new helper into `/api/chat` after the cmd-shim check, pin
the path with a quote-heavy regression on a `C:\Program
Files\DeepSeek\deepseek.exe` resolved bin (prompt under the byte
budget but past the kernel cap once libuv-quoted), plus no-op tests
for ordinary prompts, `.cmd`/`.bat` resolutions, POSIX paths,
null/empty bin, and stdin-only adapters, plus a mutual-exclusivity
assertion so the two guards' division of labour can't drift.

Generated-By: looper 0.4.0 (runner=fixer, agent=claude-code)

* fix(daemon): neutralize cmd.exe %var% expansion in DeepSeek argv

Wrap each `%` in `"^%"` inside `quoteWindowsCommandArg` so cmd.exe's
percent-expansion can't substitute env values into a `.cmd`-shim spawn
when the DeepSeek argv carries a prompt mentioning `%DEEPSEEK_API_KEY%`.
Mirror the change in the agents.ts helper used by the budget guard, add
`AGENT_PROMPT_TOO_LARGE` to the contracts so typed SSE consumers
recognize the existing daemon error code, and pin the literal-prompt
contract with regression tests.

Generated-By: looper 0.4.0 (runner=fixer, agent=claude-code)
2026-05-05 00:08:26 +08:00
Daniel Duma, PhD
cfd359e05a
[codex] Fix Gemini CLI trust handling (#352)
* Fix Gemini CLI trust handling

* Preserve agent spawn env filtering
2026-05-04 21:39:59 +08:00
github-actions[bot]
fcca9fd7c9
Update docs/assets/github-metrics.svg - [Skip GitHub Action] (#406)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-04 09:18:45 +08:00
bezineb5
051d9b890d
feat(daemon): add Mistral Vibe CLI agent adapter (#354) 2026-05-03 16:19:09 +08:00
github-actions[bot]
4f04553948
Update docs/assets/github-metrics.svg - [Skip GitHub Action] (#334)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-05-03 09:32:13 +08:00
Tom Huang
6fa2077651
feat(web): add pet companion with Codex hatch-pet integration (#296)
* feat(web): add pet companion with Codex hatch-pet integration

Introduces a customizable floating pet companion (overlay + entry-view rail
+ composer menu + dedicated Settings → Pets section) that supports built-in
pets, user customization (glyph/image/spritesheet), and one-click adoption
of pets packaged by the upstream Codex `hatch-pet` skill via a new
`/api/codex-pets` daemon endpoint. Vendors the unmodified `hatch-pet`
skill under `skills/hatch-pet/` and adds i18n strings across all locales.

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

* feat(scripts): sync community Codex pets from public catalogs

Adds `pnpm sync:community-pets` which fetches all pets from
codex-pet-share.pages.dev (paginated Supabase Functions API) and
j20.nz/hatchery (single-shot JSON), then writes each one as
`<id>/pet.json` + `<id>/spritesheet.webp` under
`\${CODEX_HOME:-\$HOME/.codex}/pets/`. The existing daemon
`codex-pets` registry already scans that folder, so synced pets
appear under Settings → Pets → Recently hatched and adopt with one
click — no manual upload. Supports --source/--out/--force/--limit
flags and validates magic bytes so HTML error pages never end up
masquerading as `.webp` files.

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

* fix(daemon): tighten codex-pets validation and document vendoring

- sanitizeId now rejects ids that still contain `..` after collapsing,
  closing a defensive gap on the path-traversal guard for the
  `/api/codex-pets/:id/spritesheet` route.
- listCodexPets emits the sanitised folder name as the public id so the
  download route resolves directly against the on-disk folder, even when
  `manifest.id` differs (manual drops, sanitiser-touched manifests).
- Drop `@ts-nocheck` from `codex-pets.ts`; module is now strict-typed
  with explicit interfaces, an unknown-narrowed JSON.parse path, and a
  `pickString` helper guarding manifest fields one by one.
- Restrict the spritesheet response CORS header to sandboxed-iframe
  callers (Origin: null) instead of unconditional `*`, matching the
  existing raw-file route pattern. Same-origin web traffic does not
  need the header (web proxies `/api/*` through the daemon).
- Add `skills/hatch-pet/README.md` explaining the vendoring trade-off,
  provenance, and re-sync procedure.
- Add `docs/codex-pets.md` covering where pets live, how to populate the
  registry without Codex installed, and the manifest contract.

Generated-By: looper 0.4.0 (runner=fixer, agent=claude-code)

* fix(i18n): add pet.* keys to Hungarian locale

Hungarian locale was added on main after this branch diverged, so the new
pet.* dictionary keys never landed there and tsc -b reports hu's Dict as
incomplete once main is merged in.

Generated-By: looper 0.4.0 (runner=fixer, agent=claude-code)

* feat(web): atlas-driven pet animations + bundled community pets

Builds on the existing pet companion (#296) with a richer animation
loop, a curated set of community pets that ship with the repo, and a
one-click sync into ~/.codex/pets/.

- Atlas-mode rendering: PetSpriteFace can now play the full Codex 8x9
  sprite atlas and swap rows from a JS-driven frame index. PetOverlay
  classifies pointer interactions (idle / hover / drag-direction /
  long-idle waiting) and maps them to the matching atlas row, so the
  pet waves on hover, runs on drag, and falls into a waiting pose
  after 6s of stillness. Single-strip pets keep their existing CSS
  steps() animation, with the steps timing fixed to jump-none so frame
  cells line up on cell boundaries.
- Atlas adoption: PetSettings exposes both "Use full atlas (animated)"
  and "Freeze to this row" — full mode keeps every row for the
  interaction state machine, single-row mode crops one strip via the
  existing canvas helper. New prepareCodexAtlas downscales the atlas
  to a localStorage-friendly PNG while preserving the grid layout.
- Settings tabs: pet sources are now split into Built-in / Custom /
  Community tabs so each origin gets its own dedicated surface.
- Bundled pets: scripts/bake-community-pets.ts seeds a curated set
  (clippit, dario, nyako-shigure, slavik, trump, tux, yelling-dario,
  yorha-sit-2b) into assets/community-pets/. The daemon scans this
  alongside the user's ~/.codex/pets/ root, with user pets winning
  when ids collide. CodexPetSummary gains a `bundled` flag so the UI
  can tag those cards with a "Bundled" pill.
- One-click community sync: daemon-side port of sync-community-pets
  exposed via POST /api/codex-pets/sync. Returns the same
  wrote/skipped/failed/total summary the CLI prints. Web Pet settings
  surface this as a "Download community pets" button under the
  Community tab.
- Avatar dropdown + hide rail: EntryView's avatar button is now a
  small menu (mirrors the project-view AvatarMenu) with toggles for
  hiding/showing the pet rail and opening Settings. PetRail gets a
  matching × button for the same hide flow.
- Locales: 7 new pet.* keys for tabs, sync, hide/show, atlas full
  mode, and the Bundled pill — translated into all 13 supported
  locales.

Typechecks pass across all workspace packages; daemon + web vitest
suites stay green.

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

* feat(web): bundled-pets built-in tab, ambient atlas animations, and community sync button

The Built-in tab now sources its catalog from the bundled spritesheets
at `assets/community-pets/` instead of the eight emoji placeholders that
felt boring next to the Codex hatch-pet atlases.

- Daemon: `listCodexPets` flags `bundled: true` by curated-set membership
  in `assets/community-pets/`, not by which folder the sprite happened to
  be read from. Previously a fully-synced user inbox preempted every
  bundled id and left the tab empty.
- Settings → Pets → Built-in renders the same sprite-card grid as
  Community, filtered by `bundled: true`, and reuses the existing
  `adoptCodexPet` flow. Community tab filters to non-bundled so the
  curated set never appears twice.
- Community tab gains the long-promised "Download community pets"
  trigger that calls `/api/codex-pets/sync` and shows an inline status
  line for the run summary. Strings already existed in every locale; we
  just plumbed the button.
- `PetOverlay` gets ambient atlas-row choreography — while idle, the
  overlay occasionally swaps `idle` for a random non-idle row (wave /
  hop / look) so the pet doesn't feel frozen. User gestures cancel the
  beat and take over instantly. `pickAmbientRow` lives next to
  `pickAtlasRow` so both row pickers share the fallback discipline.
- One-shot `migrateCustomPetAtlas` heals configs adopted before the
  overlay learned row switching by re-downloading the full spritesheet
  so hover / drag / ambient variety light up on next launch.
- `BUILT_IN_PETS` is now an empty array (the type stays for backwards
  compat); legacy configs whose `petId` still points at an emoji id
  (`mochi`, `pixel`, …) fall back to the user's custom slot in
  `resolveActivePet` so the overlay never renders blank.
- i18n: refresh `pet.tabBuiltInHint` (drop "emoji companions") and add
  `pet.builtInEmpty` across all locales.

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

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-02 23:45:39 +08:00
Nader Dabit
8c61e43c44
Added Devin for Terminal (#301)
* added Devin for Terminal

* updates based on PR feedback
2026-05-02 22:40:08 +08:00
luo jiyin
96db795d7d
docs: fix spelling mistakes in CLI comment, spec, and video prompt (#300)
* fix: correct cli typo comment

* docs: fix spec typo

* fix: correct video prompt typo
2026-05-02 22:32:26 +08:00
Tom Huang
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>
2026-05-02 11:00:33 +08:00
github-actions[bot]
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>
2026-05-02 10:47:05 +08:00
github-actions[bot]
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>
2026-05-01 23:12:15 +08:00
GeorgePSpark
534349aa4c
feat(daemon): add Kiro CLI agent adapter (#185)
* feat(daemon): add Kiro CLI agent adapter

* docs: add Kiro CLI to README and agent-adapters

* test(daemon): add kiro fetchModels fallback test
2026-05-01 12:25:26 +08:00
Tom Huang
d25a7aaf42
docs(readme): refresh stats, agents, skills and add metrics workflow (#173)
* 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: update next-env.d.ts route types path

Made-with: Cursor

* docs(readme): refresh stats, agents, skills and add metrics workflow

Make all three READMEs (en / zh-CN / ko) tell the truth about what the
project actually ships, and add lightweight community signals at the top
and bottom.

- Hero block: live for-the-badge GitHub stats (stars, forks, issues,
  PRs, contributors, commit activity, last commit) sit directly under
  the banner, with the smaller flat-square project-meta row (License,
  Agents, Design systems, Skills, Quickstart) below them and the
  language switcher below that.
- Counts updated to reality: 31 skills (was 19), 72 design systems
  (was 71), 10 coding-agent CLIs + OpenAI-compatible BYOK (was 7).
- "At a glance", architecture, and prompt-stack tables updated to
  cover /api/templates, /api/import/claude-design, /api/proxy/stream,
  /api/artifacts/lint, sidecar IPC, and per-namespace runtime data.
- New "Beyond chat — what else ships" section covering Claude Design
  ZIP import, BYOK proxy with SSRF block, saved templates, tab
  persistence, artifact lint, sidecar protocol + headless desktop, and
  Windows-friendly spawning.
- Skills tables rebuilt by mode (prototype, deck) and scenario; the
  "template" mode claim is removed.
- Supported coding agents table expanded to all 10 CLIs (Claude Code,
  Codex, Gemini, OpenCode, Cursor Agent, Qwen, Copilot, Hermes, Kimi,
  Pi) plus a BYOK row, with accurate stream formats and argv shapes.
- Roadmap re-flowed to mark shipped vs pending items.
- Contributors wall (contrib.rocks), Repository activity (lowlighter
  metrics SVG), and Star History added to all three READMEs, with
  cache_bust=2026-04-30 on the contrib.rocks and star-history image
  URLs to bypass GitHub camo caching.
- Korean README harmonised end-to-end with the English/Chinese ones.
- New .github/workflows/metrics.yml regenerates
  docs/assets/github-metrics.svg daily; ship a placeholder SVG so the
  image works before the first scheduled run.

Made-with: Cursor

* docs(readme): address PR #173 review feedback

- Replace invalid 0x14 control character in github-metrics.svg with an
  em-dash so the placeholder is well-formed XML and renders as an
  image (P1: was breaking SVG parse before the first metrics run).
- Clarify the placeholder SVG subtitle to spell out the token model:
  GITHUB_TOKEN gives core stats; METRICS_TOKEN unlocks richer plugins
  (traffic, follow-up). Reduces "do I need a secret?" confusion.
- Rewrite the metrics.yml inline auth comment to match: METRICS_TOKEN
  is optional and only enables richer plugins; GITHUB_TOKEN is enough
  for core metrics. Previous comment read as if METRICS_TOKEN was
  mandatory.
- Soften the BYOK fallback row in all three READMEs (EN / zh-CN / ko)
  with a catch-all phrase ("or any other OpenAI-compatible provider")
  so the listed vendors don't read as exhaustive.
2026-04-30 23:57:19 +08:00
PerishFire
c6d11018a0
Refresh desktop integration control plane (#123)
* 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.
2026-04-30 14:23:53 +08:00
Caprika
5c45c3b967
fix sse keepalive behind nginx (#111) 2026-04-30 11:31:18 +08:00
PerishFire
3f1e2cb60e
docs: refresh environment setup guidance (#104) 2026-04-30 10:00:33 +08:00
PerishFire
cfebff9653
Align app directories and isolate e2e tests (#102)
* chore: align app directories

* test: consolidate external suites under e2e
2026-04-30 09:47:03 +08:00
Tom Huang
4db0483721
chore: migrate frontend toolchain from Vite to Next.js 16 App Router (#66)
* 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>
2026-04-29 21:33:21 +08:00
KNIGHTABDO
623444fe48
fix: deliver prompt via stdin for non-Claude agents to avoid spawn ENAMETOOLONG on Windows (#15)
The composed prompt (system instructions + skill body + cwd hint + file
listing + user message) can easily exceed Windows' CreateProcess limit of
~32 KB when passed as a CLI argument via -p <string>.  This causes
spawn ENAMETOOLONG whenever Gemini CLI (or Codex, OpenCode, Cursor
Agent, Qwen) is selected on Windows — even for short user messages,
because the skill / design-system system prompt is folded in.

Fix: add promptViaStdin: true to every plain-text agent definition.
The daemon's /api/chat handler checks this flag, opens stdin as a pipe,
writes the composed prompt to it and closes the stream.  Claude Code is
unaffected — it still uses the -p argv path and a separate stream-json
parser.

docs/agent-adapters.md: update §5.5 Gemini CLI to document the stdin
delivery strategy, and update the Windows open-question note to reflect
the fix.

Co-authored-by: KNIGHTABDO <abdessamad.aabida-etu@etu.univh2c.ma>
Co-authored-by: pftom <1043269994@qq.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: lefarcen <20859779+lefarcen@users.noreply.github.com>
2026-04-29 17:10:20 +08:00
lakatos
9858f496fd
feat(agents): add GitHub Copilot CLI as a code-agent option (#28)
* feat(agents): add GitHub Copilot CLI as a code-agent option

Wire `copilot -p "..." --allow-all-tools` into AGENT_DEFS so the daemon
can spawn it alongside the other CLIs. `--allow-all-tools` is required
in non-interactive mode (same tradeoff as Claude's `-p` and Codex's
`exec`). Add a matching GitHub-dark icon with the Copilot two-eye mark.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(copilot-stream): treat result.success as completed when exitCode missing

Strict `obj.exitCode === 0 ? 'completed' : 'error'` mis-flags turns
where Copilot emits a `result` event with `success: true` but no numeric
exitCode. Switch to `obj.success === true || obj.exitCode === 0`. The
asymmetry argument that applies to other defensive ideas in this file
(raw fallback, stringifyResult cap) doesn't apply here — Claude's
`result` event uses a string `stop_reason`, not exitCode, so this is a
Copilot-specific schema-variance fix rather than a one-sided hardening.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(agent-adapters): list Copilot CLI auth paths in §5.7

Adds a one-line note: detection assumes Copilot is already
authenticated, via either `copilot login` (subcommand, OAuth device
flow) or the interactive `/login` slash command inside `copilot` with
no args. Surfaces the assumption so anyone hitting an undetected /
unversioned Copilot install can trace it back.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 16:54:47 +08:00
Tom Huang
1c942e6cb7
Feat/support star us (#5)
* 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.

* Update README and documentation for deck framework directives

- Clarified DECK_FRAMEWORK_DIRECTIVE description in both English and Chinese README files to specify conditions for deck kind without a skill seed.
- Added detailed workflow instructions in deck-framework.ts to emphasize the importance of copying the framework before adding content.
- Enhanced discovery.ts to reinforce the framework-first approach for deck projects.
- Updated system.ts to ensure proper handling of deck projects with and without bound skills, preventing re-authorship of scaling and navigation logic.

* Update README and documentation for deck framework directives

- Clarified DECK_FRAMEWORK_DIRECTIVE description in both English and Chinese README files to specify conditions for deck kind without a skill seed.
- Added detailed workflow instructions in deck-framework.ts to emphasize the importance of copying the framework before adding content.
- Enhanced discovery.ts to reinforce the framework-first approach for deck projects.
- Updated system.ts to ensure proper handling of deck projects with and without bound skills, preventing re-authorship of scaling and navigation logic.

* Enhance README and add star promotion assets

- Added a "Star us" section in both English and Chinese README files to encourage users to star the project on GitHub.
- Included a new image asset for the star promotion.
- Introduced a new HTML file for a dedicated star promotion page.
- Updated .gitignore to exclude new cursor-related files.
2026-04-28 21:00:33 +08:00
Tom Huang
bc2198103a
Feat/optimize naming (#2)
* 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.

* Update README and documentation for deck framework directives

- Clarified DECK_FRAMEWORK_DIRECTIVE description in both English and Chinese README files to specify conditions for deck kind without a skill seed.
- Added detailed workflow instructions in deck-framework.ts to emphasize the importance of copying the framework before adding content.
- Enhanced discovery.ts to reinforce the framework-first approach for deck projects.
- Updated system.ts to ensure proper handling of deck projects with and without bound skills, preventing re-authorship of scaling and navigation logic.

* Update README and documentation for deck framework directives

- Clarified DECK_FRAMEWORK_DIRECTIVE description in both English and Chinese README files to specify conditions for deck kind without a skill seed.
- Added detailed workflow instructions in deck-framework.ts to emphasize the importance of copying the framework before adding content.
- Enhanced discovery.ts to reinforce the framework-first approach for deck projects.
- Updated system.ts to ensure proper handling of deck projects with and without bound skills, preventing re-authorship of scaling and navigation logic.
2026-04-28 16:28:19 +08:00
Tom Huang
6f6bf31dd2
Refactor project name from "Open Claude Design" to "Open Design" (#1)
* 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.
2026-04-28 16:03:35 +08:00
pftom
a98096a042 Add initial project structure with essential files
- Created .gitignore to exclude build artifacts and dependencies.
- Added index.html as the main entry point for the application.
- Included LICENSE file with Apache 2.0 terms.
- Initialized package.json and package-lock.json for project dependencies.
- Added pnpm-lock.yaml for package management.
- Created QUICKSTART.md for setup instructions.
- Added README.md and README.zh-CN.md for project documentation in English and Chinese.
2026-04-28 12:25:59 +08:00