mirror of
https://github.com/nexu-io/open-design.git
synced 2026-10-27 09:51:12 +01:00
4c3423a500088dc02729de8e2fb4ac4d337836f7
63
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
4c3423a500 |
docs(plugins): record S-series landing in living plan + CHANGELOG
Plan S3 — sync docs/plans/plugins-implementation.md and CHANGELOG.md with the S-series shipped this turn: S1. runHandoffAtom() pipeline-driven promotion-ladder bridge S2. Full code-migration pipeline e2e smoke test Living plan now records: Phase 7 \u2705 + 'full pipeline e2e covered by smoke test' Phase 8 \u2705 + 'handoff promotion ladder bridge landed' Co-authored-by: Tom Huang <1043269994@qq.com> |
||
|
|
c1f6d1f02d |
docs(plugins): record R-series landing in living plan + CHANGELOG
Plan R2 — sync docs/plans/plugins-implementation.md and CHANGELOG.md
with the R-series shipped this turn:
R1. diff-review GenUI \u2192 review/decision.json bridge
Living plan now reads:
Phase 8 → \u2705 COMPLETE end-to-end. Patch substrate +
diff-review atom + auto-surface + native UI mount + GenUI \u2192
runDiffReview bridge all landed.
Phase 6 → \u2705 COMPLETE.
Phase 7 → \u2705 COMPLETE.
Remaining backlog:
- Promote OD_BUNDLED_ATOM_PROMPTS=1 to default (audit-blocked)
- AWS SDK wiring inside S3ProjectStorage
- Postgres adapter wiring inside DaemonDb resolver
Changelog names every shipped surface so a reviewer can audit the
delta without reading the plan.
Co-authored-by: Tom Huang <1043269994@qq.com>
|
||
|
|
72ec5fb176 |
docs(plugins): record Q-series landing in living plan + CHANGELOG
Plan Q3 — sync docs/plans/plugins-implementation.md and CHANGELOG.md
with the Q-series shipped this turn:
Q1. Native diff-review UI on GenUISurfaceRenderer (Phase 8 entry slice)
Q2. figma-extract asset rasterisation second pass (Phase 6 entry slice)
Living plan now reads:
Phase 6 → COMPLETE: figma-extract REST + token-map crosswalk +
asset rasterisation second pass via GET /v1/images.
Phase 8 → patch + review + auto-surface + native review UI all
landed. The remaining slice is wiring the GenUI response back
through runDiffReview() to auto-update review/decision.json
(today the daemon stores the response on the run; the
diff-review runner reads it on next invocation).
Changelog names every shipped surface so a reviewer can audit the
delta without reading the plan.
Co-authored-by: Tom Huang <1043269994@qq.com>
|
||
|
|
e135739f99 |
docs(plugins): record P-series landing in living plan + CHANGELOG
Plan P4 — sync docs/plans/plugins-implementation.md and CHANGELOG.md
with the P-series shipped this turn:
P1. token-map atom impl (Phase 6/7 entry slice)
P2. figma-extract atom impl (Phase 6 entry slice)
P3. Auto-derived choice surface for diff-review (Phase 8 entry slice)
Living plan now reads:
Phase 6 → COMPLETE: figma-extract REST shell-out + token-map
crosswalk both implemented. Bundled scenario plugin
od-figma-migration ships the canonical pipeline. Asset
rasterisation second pass (offlineAssets=false) stays
scheduled.
Phase 7 → COMPLETE (continued from O-series): all six atom impls.
Phase 8 → patch + review + auto-surface substrate landed; native
UI mount in the web composer stays scheduled.
Changelog names every shipped surface so a reviewer can audit the
delta without reading the plan.
Co-authored-by: Tom Huang <1043269994@qq.com>
|
||
|
|
01e94a92be |
docs(plugins): record O-series landing in living plan + CHANGELOG
Plan O6 — sync docs/plans/plugins-implementation.md and CHANGELOG.md
with the O-series shipped this turn:
O1. Bundled-scenario pipeline fallback resolver (spec §23.3.3)
O2. design-extract atom impl (Phase 6/7 entry slice)
O3. rewrite-plan atom impl (Phase 7 entry slice)
O4. patch-edit atom impl (Phase 7 entry slice)
O5. diff-review atom impl (Phase 7-8 entry slice)
Living plan now reads:
Phase 7 → ALL SIX atoms IMPLEMENTED (build-test + code-import +
design-extract + rewrite-plan + patch-edit + diff-review).
Bundled scenario plugin od-code-migration ships the canonical
pipeline. Live HTTP wiring for the per-stage runner stays
scheduled.
Phase 8 → patch + review substrate landed; native review-and-apply
UI mounting diff-review through a GenUI choice surface stays
scheduled.
Phase 6 → SKILL.md substrate + scenario plugin registered;
design-extract impl is reused under the figma-migration
flow as well.
Changelog names every shipped surface so a reviewer can audit the
delta without reading the plan.
Co-authored-by: Tom Huang <1043269994@qq.com>
|
||
|
|
1d142b4214 |
docs(plugins): record N-series landing in living plan + CHANGELOG
Plan §3.N5 — sync docs/plans/plugins-implementation.md and
CHANGELOG.md with the N-series shipped this turn:
N1. build-test atom shell-out runner (Phase 7 entry slice)
N2. code-import atom repo walker (Phase 7 entry slice)
N3. handoff helper + ArtifactManifest provenance fields
(Phase 7-8 entry slice)
N4. Bundled scenario plugins (spec §23.3.3)
Living plan now reads:
Phase 7 → build-test + code-import IMPLEMENTED; design-extract +
rewrite-plan + patch-edit + diff-review remain SKILL.md
substrate.
Phase 8 → handoff helper + provenance fields IMPLEMENTED; native
review-and-apply UI remains scheduled.
Phase 6 → SKILL.md substrate + scenario plugin registered;
Figma REST + token-map heuristic remain scheduled.
Changelog names every shipped surface so a reviewer can audit the
delta without reading the plan.
Co-authored-by: Tom Huang <1043269994@qq.com>
|
||
|
|
4aec507cd3 |
docs(plugins): record M-series — retention TTL + atom prompt rewiring + Phase 6/7/8 substrate
CHANGELOG.md ## Unreleased gets a new bullet block summarising:
- OD_SNAPSHOT_RETENTION_DAYS referenced-row TTL (PB2 closed).
- OD_BUNDLED_ATOM_PROMPTS=1 activates composeDaemonSystemPrompt's
atom-block branch (default off; byte-equal to today's prompt).
- Nine new bundled atom SKILL.md fragments under
plugins/_official/atoms/ for Phases 6, 7, and 8.
docs/plans/plugins-implementation.md §6 Phase 6 / 7 / 8 deliverables
record their substrate-shipped state; the actual implementations
remain scheduled. §9 Status snapshot updated; next-planned-PR cell
moves the AWS SDK / postgres adapter wiring + Phase 6 / 7 / 8
shell-out implementations + the OD_BUNDLED_ATOM_PROMPTS default
flip to the head of the queue.
Final gates: pnpm guard ✓, daemon 1521 tests ✓, web 586 tests ✓,
contracts 12 tests ✓, agui-adapter 9 tests ✓, plugin-runtime 21.
Co-authored-by: Tom Huang <1043269994@qq.com>
|
||
|
|
35b4030834 |
docs(plugins): record L-series — Helm overrides + activeStageBlocks + asset route + storage substrate
CHANGELOG.md ## Unreleased gets a new bullet block summarising:
- Per-cloud Helm value overrides (AWS / GCP / Azure / Aliyun /
Tencent / Huawei / self-hosted).
- composeSystemPrompt accepts activeStageBlocks so a future PR can
swap inline DISCOVERY_AND_PHILOSOPHY for SKILL.md fragments.
- Plugin-bundled component surface (sandboxed iframe) +
GET /api/plugins/:id/asset/* with §9.2 CSP.
- ProjectStorage + DaemonDb adapter substrate (Local impl wired,
S3 + postgres stubs interface-locked).
docs/plans/plugins-implementation.md §3 / §6 / §9 flipped:
- Phase 5 deliverables: chart templates + per-cloud overrides +
bound-API-token guard + ghcr CI + ProjectStorage + DaemonDb all
record their landed shipped state.
- §6 Phase 4 absorbs the activeStageBlocks composer field +
surface.component sandbox loader as shipped slices.
- §9 Status snapshot updated; head of the queue is now the live
composeSystemPrompt rewiring + AWS SDK / postgres adapter
wiring + OD_SNAPSHOT_RETENTION_DAYS referenced-row TTL +
Phase 6/7/8 native scenarios.
Final gates: pnpm guard ✓, daemon 1516 tests ✓, web 586 tests ✓,
contracts 12 tests ✓, agui-adapter 9 tests ✓, plugin-runtime 21.
Co-authored-by: Tom Huang <1043269994@qq.com>
|
||
|
|
d0dbc7314f |
docs(plugins): record K-series — bound-API-token + Helm + surface.component + ghcr CI
CHANGELOG.md ## Unreleased gets a new bullet block summarising:
- Phase 5 bound-API-token guard (startServer refusal + bearer
middleware on /api/*).
- Helm chart templates (Deployment / Service / Secret / ConfigMap /
PVCs / Ingress / NOTES).
- od.genui.surfaces[].component manifest field + capability gate.
- GitHub Actions multi-arch image push to ghcr.io.
docs/plans/plugins-implementation.md §6 / §9 flipped:
- Phase 5 bound-API-token guard, CI push, Helm templates → shipped.
- Phase 4 surface.component manifest upgrade → shipped (substrate;
web sandbox loader stays scheduled).
- §9 Status snapshot updated; head of the queue is now the
composeSystemPrompt rewiring + the web custom-component sandbox
loader + ProjectStorage S3 adapter + DaemonDb Postgres adapter +
per-cloud values-<cloud>.yaml override files + Phase 6 / 7 / 8.
Final gates: pnpm guard ✓, daemon 1496 tests ✓, web 586 tests ✓,
contracts 12 tests ✓, agui-adapter 9 tests ✓, plugin-runtime 21 tests ✓.
Co-authored-by: Tom Huang <1043269994@qq.com>
|
||
|
|
735b7bdffb |
docs(plugins): record J-series — AG-UI adapter + atom-block + Phase 5 entry slice
CHANGELOG.md ## Unreleased gets a new bullet block summarising:
- @open-design/agui-adapter package + GET /api/runs/:runId/agui
(spec §10.3.5).
- renderActiveStageBlock + loadAtomBodies (spec §23.3.2 substrate).
- Phase 5 Dockerfile bundles plugins/_official/, plus
tools/pack/docker-compose.yml and tools/pack/helm/open-design/
parameter surface.
docs/plans/plugins-implementation.md §3 / §6 / §9 flipped:
- Architecture-state table records agui-adapter, atom-bodies,
atom-block, docker-compose, Helm values.
- HTTP route table marks /api/runs/:runId/agui shipped.
- §6 Phase 4 'AG-UI adapter package' deliverable flips. The
'plugins/_official/atoms/<atom>/SKILL.md extraction' deliverable
is recorded as substrate-shipped; the composeSystemPrompt
rewiring stays as the next planned PR.
- §6 Phase 5 deliverable list flips Dockerfile + docker-compose +
Helm + snapshot retention worker; the bound-API-token guard +
pluggable storage / Postgres adapters stay open.
- §9 Status snapshot updated; head of the queue is now the
composeSystemPrompt rewiring + od.genui.surfaces[].component
upgrade + CI pushing :edge / :<version> + bound-API-token guard
+ Postgres / S3 adapters.
Final gates: pnpm guard ✓, daemon 1486 tests ✓, web 586 tests ✓,
contracts 12 tests ✓, agui-adapter 9 tests ✓.
Co-authored-by: Tom Huang <1043269994@qq.com>
|
||
|
|
d06c1b4905 |
docs(plugins): record I-series — pipeline-into-startChatRun + doctor/config + bundled atoms
CHANGELOG.md ## Unreleased gets a new bullet block summarising:
- Pipeline runner wired into POST /api/runs (e2e-3 full §8 contract).
- od doctor (repo-wide diagnostics) + od config get/set/list/unset.
- Phase 4 §23 entry slice — bundled atom plugins + boot walker.
docs/plans/plugins-implementation.md §3 / §6 / §8 / §9 flipped:
- Architecture-state table records scaffold / export / publish /
bundled / plugins/_official/atoms as shipped.
- §6 Phase 4 deliverable list flips bundled atom extraction +
full CLI parity remainder; the system.ts → SKILL.md prompt
rewiring stays open as the next planned PR.
- §8 e2e-3 row flips from entry-slice to full §8 contract:
plugins-headless-run.test.ts asserts the first SSE event on a
pipeline-bearing run is pipeline_stage_started.
- §9 Status snapshot updated; head of the queue is now
composeSystemPrompt() reading atom fragments from
plugins/_official/atoms/<atom>/SKILL.md, then the AG-UI adapter,
then Phase 5 Docker image.
Final gates: pnpm guard ✓, daemon 1481 tests ✓, web 586 tests ✓.
Co-authored-by: Tom Huang <1043269994@qq.com>
|
||
|
|
26c5a27cf9 |
docs(plugins): record Phase 4 publish + CLI parity remainder
CHANGELOG.md ## Unreleased gets a new bullet block summarising:
- Phase 4 publish CLI (od plugin publish --to <catalog> [--open]).
- CLI parity remainder (od atoms / skills / design-systems / craft /
status / version).
- od marketplace search across configured catalogs.
docs/plans/plugins-implementation.md §3 / §6 / §9 flipped:
- The CLI table records publish + atoms + skills + design-systems +
craft + status + version + marketplace search as shipped, with the
only remaining open verbs being od doctor + od config get/set/list.
- Phase 4 deliverable list flips publish to shipped.
- Status snapshot moves marketplace search and library CLI parity
out of next-planned and into shipped; head of the queue is now the
pipeline-runner-into-startChatRun integration plus Phase 4 atom
migration into plugins/_official/ and the AG-UI adapter package.
Final gates: pnpm guard ✓, daemon 1475 tests ✓, web 586 tests ✓.
Co-authored-by: Tom Huang <1043269994@qq.com>
|
||
|
|
a1798ba47d |
docs(plugins): record Phase 4 author tooling + Phase 2B marketplace UI
CHANGELOG.md ## Unreleased gets a new bullet block summarising:
- Phase 4 author tooling: od plugin scaffold + od plugin export with
provenance README + claude-plugin / agent-skill targets.
- Phase 2B marketplace deep UI: /marketplace + /marketplace/:id
routes, MarketplaceView grid + filters + configured catalogs panel,
PluginDetailView with capability + connector + GenUI surface
summaries plus a 'Use this plugin' button.
- Phase 2B ChatComposer mount of PluginsSection.
- docs/atoms.md as the canonical first-party atom catalog reference.
docs/plans/plugins-implementation.md §3 / §6 / §9 flipped:
- The web component table now records MarketplaceView + PluginDetailView
as shipped (with the routes attached) and the ChatComposer rail mount
flipped from absent → shipped.
- The CLI table records od plugin scaffold + od plugin export as
shipped Phase 4 deliverables; od plugin publish stays absent.
- The Phase 4 deliverable list flips: docs/atoms.md, scaffold, export,
and run shorthand are all checked. Atom migration into
plugins/_official/, AG-UI adapter, plugin manifest .component
capability, and CLI parity remainder stay open.
- §9 Status snapshot updated; next-planned-PR cell moves the
pipeline-runner-into-startChatRun integration to the head of the
queue and points at the remaining Phase 4 / 5 backlog.
Final gates: pnpm guard ✓, daemon 1465 tests ✓, web 586 tests ✓.
Co-authored-by: Tom Huang <1043269994@qq.com>
|
||
|
|
e0840697ed |
docs(plugins): add docs/atoms.md (first-party atom catalog reference)
Plan G5 / spec §10 / §21 / §23.
A user / plugin author / reviewer asking 'what atoms can I reference?'
now has one canonical document with:
- the full id list (implemented + planned, with task kinds),
- how the daemon resolves an atom at run time
(pipeline.ts → pipeline-runner.ts → system prompt fragment),
- the v1 until-signal vocabulary (critique.score / iterations /
user.confirmed / preview.ok) and how to encode a build-test
pass/fail signal until Phase 7 promotes named signals,
- the spec §22.5 'community plugin → first-party atom' promotion
path so future PRs that flip a planned id to implemented have a
documented landing route.
Source of truth remains apps/daemon/src/plugins/atoms.ts; this doc
points at it. `GET /api/atoms` already returns the same list and
the future `od atoms list` CLI verb (Phase 4 follow-up) will be a
thin wrapper around it.
Co-authored-by: Tom Huang <1043269994@qq.com>
|
||
|
|
0e92952ac7 |
docs(plugins): record Phase 1 follow-up + 1.5 + 2B mount + 3 install resolution
CHANGELOG.md gets a new bullet block summarising:
- Phase 1 follow-up CLI (od project / run / files / conversation).
- Phase 1.5 headless lifecycle (od daemon start --headless / --serve-web /
status / stop) with backing /api/daemon/status + /api/daemon/shutdown.
- Phase 3 'od plugin install <name>' resolution through configured
marketplaces.
- Web composer mount: PluginsSection + NewProjectPanel integration.
docs/plans/plugins-implementation.md §3 / §6 / §8 / §9 flipped:
- The Phase 1.5 deliverable list moves from open boxes to shipped
rows.
- The CLI table moves od project / run / files / conversation /
daemon to shipped, with the lone remaining deferrals (od files
diff, od project import, od conversation new, od marketplace
search) called out explicitly.
- The web component table records PluginsSection + the
NewProjectPanel mount as shipped, with the deeper ChatComposer
mount + MarketplaceView + PluginDetailView still scheduled for
Phase 2B.
- Phase 3 marks 'od plugin install <name>' as shipped; the Phase 3
items still open are: trust UI, bundle-plugin installer, full
doctor expansion.
- §8 e2e-3 flips to entry-slice complete (HTTP-layer walkthrough);
the live-agent-loop integration moves to the next-planned-PR cell.
- §9 Status snapshot updated.
Final gates green: pnpm guard ✓, daemon 1455 tests ✓, web 579 tests ✓.
Co-authored-by: Tom Huang <1043269994@qq.com>
|
||
|
|
20285c9959 |
docs(plugins): flip Phase 2A boxes + record Phase 3/5 entry slices
Plan §3 architecture state, §6 phase deliverables, §8 definition of done,
§9 status snapshot all updated to reflect the work that landed in this
branch.
CHANGELOG.md gets a new ## Unreleased bullet summarising the daemon /
CLI / web slice, with explicit pointers to the e2e test paths that
anchor each §8 row.
Phases / slices that flipped to shipped:
- All Phase 2A daemon deliverables (pipeline, pipeline-runner,
connector-gate, GenUI registry/store/events, snapshot resolver,
SQLite migrations, HTTP routes, SSE / ND-JSON event emission, PB1
renderer in contracts).
- Phase 2A CLI: trust mutation, --grant-caps, --input k=v, recoverable
exit codes 64–73, ui list/show/respond/revoke/prefill, plugin
replay, plugin run shorthand, plugin snapshots prune.
- Phase 2A web: applyPlugin() helper, InlinePluginsRail,
ContextChipStrip, PluginInputsForm, GenUISurfaceRenderer
(confirmation + oauth-prompt first-class), GenUIInbox.
- Phase 3 entry slice: marketplace registry + od marketplace add /
list / info / refresh / remove / trust + matching HTTP routes.
Plugin-name resolution + trust UI stay scheduled.
- Phase 5 (early): snapshot GC worker + applied-plugins audit
routes + od plugin snapshots prune.
§8 Definition of Done: e2e-1, e2e-2, e2e-4, e2e-5, e2e-6, e2e-7, e2e-8
all anchored to specific daemon test paths. e2e-3 (headless run) stays
TBD pending Phase 1.5.
Status snapshot: Phase 2A finished + entry slices of Phase 2B/2C/3 +
early Phase 5; next planned PRs: Phase 1.5 headless flag (e2e-3
unblock), Phase 2B marketplace deep UI, Phase 3 `od plugin install
<name>` resolution + trust UI.
Co-authored-by: Tom Huang <1043269994@qq.com>
|
||
|
|
4c7cd5d9f2 |
feat(plugins): introduce plugin system with installation and management capabilities
- Added support for a new plugin system, allowing users to install, uninstall, and manage plugins through the daemon. - Implemented API endpoints for listing installed plugins, retrieving plugin details, and applying plugins with input validation. - Introduced a plugin doctor feature to validate plugin manifests and check for issues before application. - Established a plugin persistence layer with SQLite migrations for managing installed plugins and their metadata. - Enhanced the CLI with commands for plugin operations, improving user interaction with the plugin ecosystem. |
||
|
|
8d7f914b55 |
docs(plugins): enhance plugin specification and introduce implementation roadmap
- Added a new section detailing the implementation plan for the Open Design Plugin & Marketplace, serving as a living roadmap for future development. - Updated the plugin specification to include the `expires_at` column in the `applied_plugin_snapshots` table, clarifying its role in snapshot retention and garbage collection. - Revised the structure of the plugin block renderer, lifting it into the contracts layer to eliminate byte-equality drift and streamline plugin support across different consumption modes. - Documented the phased approach to plugin functionality, ensuring clarity on the current capabilities and future enhancements within the plugin ecosystem. |
||
|
|
8becf00a34 |
docs(plugins): add scenario coverage matrix and delivery roadmap section
- Introduced a new section detailing the scenario coverage matrix and delivery roadmap, consolidating the four product scenarios and their implementation status. - Provided a comprehensive analysis of what v1 delivers for each scenario, highlighting gaps and future requirements for full native support. - Enhanced clarity for future implementers by summarizing key contracts and dependencies across the scenarios, ensuring a clear understanding of the current capabilities and limitations of v1. |
||
|
|
ce84e9a419 |
docs(plugins): add section on post-v1 extensibility and artifact taxonomy
- Introduced a new section detailing post-v1 extensibility, focusing on artifact taxonomy, evaluators, and production handoff. - Defined optional fields in the ArtifactManifest interface, including artifactKind, renderKind, and handoffKind, to enhance artifact categorization and downstream delivery. - Outlined future evaluator capabilities and their integration into the plugin pipeline, ensuring a structured approach to evaluation and production workflows. - Emphasized the importance of maintaining stable data models for future enhancements without forking existing logic. |
||
|
|
8e464007a9 |
docs(plugins): update Plugins & Marketplace specification and add Chinese translation
- Renamed the document to "Open Design Plugin & Marketplace Spec" and added a summary to clarify the purpose of Open Design plugins. - Expanded the specification with detailed explanations of the agent-era plugin system, including core interaction sequences and mode-specific query examples. - Introduced a new Chinese translation of the specification to enhance accessibility for Chinese-speaking users. - The updates aim to provide a comprehensive understanding of the plugin architecture and its operational context within the Open Design ecosystem. |
||
|
|
ea787b4b7d |
docs(plugins): introduce comprehensive Plugins & Marketplace specification
- Added a new document detailing the structure, compatibility, and implementation of plugins within the Open Design ecosystem. - Outlines the relationship between plugins and skills, emphasizing the additive nature of the `open-design.json` file. - Includes a table of contents for easy navigation through various sections such as goals, compatibility matrix, and deployment strategies. - Establishes a vision for Open Design as a server + CLI + atomic core engine + plugin/marketplace system, highlighting the headless operation and Docker deployment capabilities. - Document is currently in draft status, awaiting review. |
||
|
|
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> |
||
|
|
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) |
||
|
|
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> |
||
|
|
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> |
||
|
|
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 |
||
|
|
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>
|
||
|
|
8630fd380a |
feat(daemon): close pi adapter parity gaps
Closes pi adapter parity gaps for image paths, extra allowed dirs, error events, and sendAgentEvent routing. |
||
|
|
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> |
||
|
|
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> |
||
|
|
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>
|
||
|
|
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> |
||
|
|
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 |
||
|
|
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> |
||
|
|
8eb9b1b506 | Implement manual edit mode (#620) | ||
|
|
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> |
||
|
|
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> |
||
|
|
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 |
||
|
|
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
|
||
|
|
cfd359e05a |
[codex] Fix Gemini CLI trust handling (#352)
* Fix Gemini CLI trust handling * Preserve agent spawn env filtering |
||
|
|
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> |
||
|
|
051d9b890d | feat(daemon): add Mistral Vibe CLI agent adapter (#354) | ||
|
|
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> |
||
|
|
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> |
||
|
|
8c61e43c44 |
Added Devin for Terminal (#301)
* added Devin for Terminal * updates based on PR feedback |
||
|
|
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 |
||
|
|
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> |
||
|
|
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> |