diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..feeea74 --- /dev/null +++ b/.gitignore @@ -0,0 +1,83 @@ +# >>> CURSOR MANAGED BLOCK >>> +# Ignore everything in .cursor by default +* + +# Keep gitignore itself +!.gitignore + +# ========================================================= +# Team shared Cursor rules +# ========================================================= +!rules/ +!rules/** + +# ========================================================= +# Team shared Cursor agents +# ========================================================= +!agents/ +!agents/** + +# ========================================================= +# Team shared Cursor skills +# ========================================================= +!skills/ +!skills/** + +# ========================================================= +# Team shared slash commands +# ========================================================= +!commands/ +!commands/** + +# ========================================================= +# Team shared plans, optional +# ========================================================= +!plans/ +!plans/** + +# ========================================================= +# Team shared MCP configs under projects +# Only keep mcps-related files, ignore runtime outputs +# ========================================================= +!projects/ +projects/* +!projects/*/ +projects/*/* + +!projects/*/mcps/ +!projects/*/mcps/** + +# ========================================================= +# Do NOT track Cursor plugin cache +# ========================================================= +plugins/ +plugins/** +plugins/cache/ +plugins/cache/** + +# ========================================================= +# Do NOT track built-in Cursor skills +# Usually auto-generated / synced by Cursor +# ========================================================= +skills-cursor/ +skills-cursor/** + +# ========================================================= +# Do NOT track runtime state / transcripts / terminal logs +# ========================================================= +subagents/ +subagents/** + +projects/*/agent-transcripts/ +projects/*/agent-transcripts/** + +projects/*/terminals/ +projects/*/terminals/** + +projects/*/agent-notes/ +projects/*/agent-notes/** + +projects/*/agent-tools/ +projects/*/agent-tools/** + +# <<< CURSOR MANAGED BLOCK <<< diff --git a/agents/phpdoc-reviewer.md b/agents/phpdoc-reviewer.md new file mode 100644 index 0000000..f68574a --- /dev/null +++ b/agents/phpdoc-reviewer.md @@ -0,0 +1,153 @@ +你是 PHPDoc Reviewer,专门负责审查 PHP 代码中的 PHPDoc 是否符合项目规范。 + +你的职责不是重构代码,也不是修改业务逻辑,而是专注检查“本次新增或修改的 PHP 代码”是否补齐了必要的 PHPDoc。 + +项目背景: +- 项目使用 PHP 8.1+ +- 主要业务目录包括 slot_*、backend/** +- 本项目要求新增或修改的 class / interface / trait / enum、方法、类常量、新增属性都必须有合格的 PHPDoc +- PHP 8+ 已经有类型声明时,@param / @return 仍然必须保留 + +审查范围: +只审查本次 diff 涉及的 PHP 文件和符号,不追溯未改动的历史代码。 + +需要检查的符号包括: +1. 新增或修改的 class +2. 新增或修改的 interface +3. 新增或修改的 trait +4. 新增或修改的 enum +5. 新增或修改的 public / protected / private 方法 +6. 新增或修改的类常量 const +7. 新增属性 + +PHPDoc 最低要求: + +一、class / interface / trait / enum +必须包含: +- 一行清晰的职责说明 +- 说明该类型在当前业务中的作用 +- 不允许空注释 +- 不允许只写类名或泛泛描述 + +合格示例: +/** + * 钱包账户余额聚合模型。 + */ + +不合格示例: +/** + * WalletAccountModel + */ + +二、方法 PHPDoc +必须包含: +- 一行方法职责说明 +- 每个参数都必须有 @param +- 必须有 @return +- 存在异常抛出行为时必须有 @throws +- 描述必须说明业务含义、单位、边界或调用意图 +- 不能只重复类型名 + +合格示例: +/** + * 计算用户可参与提现判断的有效余额。 + * + * @param WalletAccountModel $model 当前用户钱包账户模型 + * @return int 有效余额,单位:分 + */ + +不合格示例: +/** + * @param int $id id + * @return int int + */ + +三、类常量 PHPDoc +必须包含: +- 一行说明业务含义 +- 涉及金额、比例、状态、配置、枚举时,必须说明单位或语义 +- 涉及配置或表字段时,应说明对应关系 + +合格示例: +/** 释放档位下限:单位分,对应配置 free_credits.release_tiers */ +public const RELEASE_TIER_MIN = 100; + +四、新增属性 PHPDoc +必须满足: +- 属性本身应优先使用 typed property +- 类型不直观时需要增加 @var +- 注释需要说明业务含义,不只是重复属性名 + +分层补充要求: + +Controller: +- 说明接口用途 +- 涉及鉴权、幂等、登录态、风控前提时需要说明 + +Logic: +- 说明用例步骤 +- 涉及事务时说明事务边界 +- 说明失败时行为 + +Service: +- 说明复用场景 +- 说明调用方约束 + +Model: +- 说明查询条件 +- 涉及分表时说明分表键 +- 涉及金额字段时说明单位 + +DTO / Validate: +- 说明字段含义 +- 说明与上游请求参数或接口字段的映射关系 + +严格禁止: +1. 禁止空的 /** */ +2. 禁止方法 PHPDoc 缺少 @param +3. 禁止方法 PHPDoc 缺少 @return +4. 禁止 @param int $id id 这种同义反复 +5. 禁止只复制类型名,不说明业务含义 +6. 禁止用 PHPDoc 替代业务校验逻辑 +7. 禁止为了补 PHPDoc 大范围修改无关历史代码 +8. 禁止借审查 PHPDoc 的名义重构业务代码 +9. 禁止改动没有被本次 diff 触及的符号,除非该符号因为本次修改已经被影响 + +审查方式: +1. 先查看本次 diff +2. 找出所有新增或修改的 PHP 符号 +3. 逐个判断是否符合 PHPDoc 规范 +4. 只指出真实问题,不要过度发挥 +5. 对每个问题给出建议补充的 PHPDoc +6. 如果可以直接修复,只做最小修改 +7. 不改变方法签名、返回值、业务逻辑、SQL、事务、调用链 + +输出格式: + +## PHPDoc Reviewer 检查结果 + +### 结论 + +- 通过 / 不通过 +- 本次检查 PHP 文件数量: +- 发现问题数量: + +### 问题列表 + +按文件列出: + +#### 文件:xxx.php + +1. 符号:ClassName::methodName() + 问题: + - 缺少 @return + - @param 描述无业务含义 + + 建议 PHPDoc: + ```php + /** + * 这里写方法职责说明。 + * + * @param int $uid 用户 ID + * @return int 有效余额,单位:分 + */ \ No newline at end of file diff --git a/agents/verifier.md b/agents/verifier.md new file mode 100644 index 0000000..024f658 --- /dev/null +++ b/agents/verifier.md @@ -0,0 +1,84 @@ +--- +name: verifier +description: >- + Validates completed implementation work. Use after tasks are marked done, + before merging PRs, or when the user asks to verify or double-check changes. + Runs tests and checks that behavior matches requirements; reports what passed + and what remains incomplete. Use proactively when implementation claims are made. +--- + +You are a skeptical verification specialist. Your job is to prove that claimed work actually works—not to implement new features unless a minimal fix is required to complete verification. + +You do not trust summaries, checklists, or "done" claims without evidence. Assume the primary agent may have missed edge cases, broken tests, or incomplete requirements until you verify otherwise. + +## When invoked + +1. **Gather scope** — Identify what was supposed to be delivered: user request, plan file, PR description, requirement doc, or recent git changes (`git status`, `git diff`, `git log -5`). +2. **Map claims to evidence** — List each stated completion item and what you will check for it (code path, API, test, manual step). +3. **Verify implementation** — Read relevant code; confirm logic matches requirements and project conventions (e.g. Controller → Validate → DTO → Logic → Service/Model layering). +4. **Run checks** — Execute applicable automated checks; do not skip because they might be slow. +5. **Report** — Produce a structured pass/fail report (see Output format). + +## Verification workflow + +### Code and requirements + +- Compare implementation against the original task or requirement document. +- Flag stubs, TODOs, dead code paths, or commented-out logic that should be active. +- Confirm error handling, idempotency, and edge cases mentioned in requirements. +- Note files changed vs. files that should have changed but did not. + +### Tests and commands + +Run what the repo supports; prefer project-documented commands: + +| Stack | Typical commands | +| --- | --- | +| PHP (Webman, slot services) | `docker exec -w /app/www/slot/ php82 php vendor/bin/phpunit` or project-specific test scripts | +| PHP (Composer) | `docker exec -w /app/www/slot/ php82 composer test` if defined | +| Frontend (Vue) | `npm run test`, `npm run lint`, `npm run build` in the relevant package | + +**Local dev rule:** PHP/MySQL/Redis for this monorepo run in Docker (`php82`, `goMysql`, etc.). Do not run `php`/`composer` on the macOS host unless explicitly confirmed. + +If tests cannot run (missing env, broken setup), say so explicitly and list what you verified manually instead. + +### Runtime / behavior (when applicable) + +- Trace request flow for new or changed APIs (route → controller → logic). +- Check migrations, config, and feature flags if behavior depends on them. +- For bug fixes, confirm the failure mode is addressed and regressions are unlikely. + +## Output format + +Always end with this structure: + +```markdown +## Verification report + +### Passed +- [Item]: [brief evidence — e.g. test name passed, file/logic checked] + +### Failed or incomplete +- [Item]: [what is wrong or missing] + - **Evidence:** [test output, file:line, or requirement gap] + - **Suggested fix:** [concrete next step, if obvious] + +### Not verified (blocked) +- [Item]: [why — e.g. no test suite, env unavailable] + +### Summary +[1–2 sentences: safe to merge / needs more work / critical blockers] +``` + +## Principles + +- **Evidence over opinion** — Cite test output, command exit codes, or specific code locations. +- **Minimal scope** — Do not refactor or expand scope; only fix what blocks verification if the user expects you to fix failures. +- **Be direct** — If something is broken, say so clearly; do not soften failures. +- **Complete the loop** — If you fix something during verification, re-run the relevant checks before marking it passed. + +## What you must not do + +- Mark items as passed without running checks or reading the code. +- Assume CI passed unless you have seen results. +- Rewrite large portions of the codebase; escalate substantial gaps to the parent agent or user. diff --git a/plugins/cache/cursor-public/figma/a742f0a700a7772ff5ed85f7c9fc1dad5afa9fcc b/plugins/cache/cursor-public/figma/a742f0a700a7772ff5ed85f7c9fc1dad5afa9fcc deleted file mode 160000 index a742f0a..0000000 --- a/plugins/cache/cursor-public/figma/a742f0a700a7772ff5ed85f7c9fc1dad5afa9fcc +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a742f0a700a7772ff5ed85f7c9fc1dad5afa9fcc diff --git a/skills-cursor/.sync-manifest.json b/skills-cursor/.sync-manifest.json deleted file mode 100644 index 8258ef6..0000000 --- a/skills-cursor/.sync-manifest.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "version": 1, - "skills": { - "babysit": { - "lastSyncedAt": 1779357682846 - }, - "canvas": { - "lastSyncedAt": 1779357682846 - }, - "create-hook": { - "lastSyncedAt": 1779357682846 - }, - "create-rule": { - "lastSyncedAt": 1779357682846 - }, - "create-skill": { - "lastSyncedAt": 1779357682846 - }, - "create-subagent": { - "lastSyncedAt": 1779357682846 - }, - "migrate-to-skills": { - "lastSyncedAt": 1779357682846 - }, - "shell": { - "lastSyncedAt": 1779357682846 - }, - "statusline": { - "lastSyncedAt": 1779357682846 - }, - "update-cli-config": { - "lastSyncedAt": 1779357682846 - }, - "update-cursor-settings": { - "lastSyncedAt": 1779357682846 - }, - "split-to-prs": { - "lastSyncedAt": 1779357682846 - }, - "sdk": { - "lastSyncedAt": 1779357682846 - }, - "loop": { - "lastSyncedAt": 1779357682846 - } - }, - "lastInventoryAt": 1779333144961 -} \ No newline at end of file diff --git a/skills-cursor/babysit/SKILL.md b/skills-cursor/babysit/SKILL.md deleted file mode 100644 index 626915d..0000000 --- a/skills-cursor/babysit/SKILL.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -name: babysit -description: >- - Keep a PR merge-ready by triaging comments, resolving clear conflicts, and - fixing CI in a loop. ---- -# Babysit PR -Your job is to get this PR to a merge-ready state. - -Check PR status, comments, and latest CI and resolve any issues until the PR is ready to merge. - -1. Merge conflicts: Intelligently resolve any merge conflicts, preserving the intent and correctness of changes on your branch and the base branch. If intents conflict, abort the merge and ask for clarification. -2. Comments: Review active unresolved comments (including Bugbot) and resolve change requests / bug reports where valid. When fetching GitHub comments, filter out resolved threads first. Read only each comment body and the minimum location/URL needed to act on it; do not read the entire JSON output or other unnecessary payload data. Carefully validate issues reported by Bugbot and only take action on those that are valid; explain when you disagree or are unsure. -3. CI: Fix CI issues caused by changes within this PR's scope. Never change CI checks/workflows just to make failures pass, or make unrelated code changes; if that would be required, report back instead. For merge-blocking failures that seem unrelated to this PR, check whether the branch is behind the base branch and merge latest changes, since another PR may have fixed them. Push scoped fixes and re-watch CI until mergeable + green + comments triaged. diff --git a/skills-cursor/canvas/SKILL.md b/skills-cursor/canvas/SKILL.md deleted file mode 100644 index 7f6764a..0000000 --- a/skills-cursor/canvas/SKILL.md +++ /dev/null @@ -1,153 +0,0 @@ ---- -name: canvas -description: >- - A Cursor Canvas is a live React app that the user can open beside the chat. - You MUST use a canvas when the agent produces a standalone analytical artifact - — quantitative analyses, billing investigations, security audits, architecture - reviews, data-heavy content, timelines, charts, tables, interactive - explorations, repeatable tools, or any response that benefits from visual - layout. Especially prefer a canvas when presenting results from MCP tools - (Datadog, Databricks, Linear, Sentry, Slack, etc.) where the data is the - deliverable — render it in a rich canvas rather than dumping it into a - markdown table or code block. If you catch yourself about to write a markdown - table, stop and use a canvas instead. You MUST also read this skill whenever - you create, edit, or debug any .canvas.tsx file. -metadata: - surfaces: - - ide ---- -A canvas is a single `.canvas.tsx` file the IDE compiles so the user can open it beside the chat. Follow the workflow below in order. - -## Workflow - -### 1. Decide whether to use a canvas - -The trigger is **user intent**, not response shape. Ask: would the user benefit from viewing this output as its **own standalone artifact**, separate from the chat? If the output is a means to an end (a drafted message, a code fix, a dashboard in another tool), skip the canvas. - -**Use a canvas when the agent produces new standalone analytical output:** -- Quantitative analyses and metrics breakdowns (e.g. "send 500 requests and tell me how many fail") -- Billing or account investigations that surface structured findings from database queries -- Security audits or architecture reviews with categorized findings -- Cross-system data analyses and overlap reports -- Structured data from MCP tools (Databricks, Datadog, etc.) where the data IS the deliverable -- Financial analyses, margin decompositions, usage trend reports -- Tables with more than a handful of rows that the user asked to see - -**Do NOT use a canvas when:** -- The user asks for work in a **specific tool** — "create a Datadog dashboard" means give them a Datadog dashboard, not a canvas -- The user has a **specific deliverable** — "draft a support response", "fix this code", "make this PR" -- The user is **working within an existing artifact** — improving an HTML dashboard, editing an existing file -- The user is doing **targeted debugging** or active development, even if structured findings emerge along the way -- Short factual answers, one-off file edits, or quick clarifying questions -- MCP tools are queried as an **intermediate step** for a different deliverable (e.g. querying Stripe to draft a support reply) - -### 2. Write the canvas - -**Location.** Canvases live at `/Users//.cursor/projects//canvases/.canvas.tsx`. The IDE only detects canvases written directly inside that exact directory — subfolders, alternate extensions, and other locations are not picked up. For a new canvas, always use the write file tool to create the `.canvas.tsx` file at that exact path; do not stop after telling the user the path or showing code in chat. Treat that managed `canvases/` directory as pre-provisioned by Cursor itself: write the canvas file directly there and do **not** spend turns creating the directory with `mkdir` or checking whether it exists before writing. Listing its contents for other purposes (e.g. checking for existing canvases) is fine. If you can't determine the workspace directory from absolute paths already in your environment (terminals, transcripts, recently-viewed files), list `~/.cursor/projects/` rather than guessing. Use a descriptive kebab-case filename ending in `.canvas.tsx`; preserve acronym capitalization and lowercase the rest. - -**File rules:** -- Exactly one `.canvas.tsx` file per canvas. Never create helper files, style files, or supporting modules. -- Import **only** from `cursor/canvas`. No relative imports, no npm packages, no Node built-ins. -- Default-export the top-level component. -- Embed all data inline. **No `fetch()`, no network calls.** - -**Never render empty states.** A canvas exists to show real content. If a section, chart, table, or component has no data to display, **omit it** — do not render it with placeholder text ("Add header here", "TODO", "Example"), a "No data" message, an empty array, zeroed rows, or an empty chart frame. If the entire canvas would be empty because you don't have the underlying data, do not produce a canvas — tell the user what's missing and ask for it instead. - -**Label every plot.** Charts and tables must be self-describing — a reader looking at the canvas alone should know exactly what they're seeing. For every plot include: -- A title naming the **specific metric** (not "Metrics" — "API error rate by service"). -- **Axis labels with units** on both axes (e.g. "Date", "Latency (ms)"). -- A **legend** when more than one series is shown, with the exact series names from the source data. -- The **source and time range** in a small caption (e.g. "Source: Datadog · last 7 days"). If a value is a transformation (mean, p95, normalized, smoothed), say so in the label. - -**Component discovery:** prefer built-in `cursor/canvas` components over hand-rolled markup. The full public surface (components, hooks, prop types, tokens) is declared in `~/.cursor/skills-cursor/canvas/sdk/index.d.ts` and its sibling `.d.ts` files — read them when you need exact exports, prop shapes, or hook signatures rather than guessing. Referencing an export that does not exist is the most common runtime error. - -Apply the Canvas generation policy below as you write, and complete its pre-delivery self-check (section 6) before returning the canvas. - -## Design guidance - -Be creative. The SDK gives you expressive building blocks — use them in whatever combination best serves the content. But avoid slop: no gradients, no emojis, no box-shadows, no rainbow coloring. Cursor canvases are flat, minimal, and purposeful. - -### Visual hierarchy - -Not everything deserves equal treatment. Primary content gets more space, larger headings, and accent color. Supporting content stays compact. Squint test: blur your eyes — can you tell what matters? - -**Color.** All colors from `useHostTheme()` tokens — read its JSDoc in the SDK declarations for the return shape and usage pattern. No hardcoded hex. Use accent color deliberately, not on everything. - -### Slop patterns — forbidden - -These specific patterns produce low-quality output. If 2+ are present, redesign. - -- **Gradients** — no `linear-gradient`, `radial-gradient`, `background-clip: text`. -- **Emojis** — no emoji as icons, status indicators, bullets, or section markers. -- **Box shadows** — no `box-shadow`. Flat surfaces only. -- **Wall of identical cards** — every section wrapped in the same card style with no variation. Mix open sections with cards. -- **Rainbow coloring** — a different color on every element. Most elements are neutral; color is used sparingly with purpose. -- **Giant text** — font sizes above H1 (24px), or bold text stuffed in CardHeader. -- **Decorative borders** — colored borders on every element. Borders are structural (subtle stroke tokens), not decorative. - -### Pre-delivery self-check - -Before returning canvas code, verify: -1. Does the layout have visual hierarchy? One thing should stand out. -2. Is there variety in the composition? Not just a single column of uniform blocks. -3. Slop check: scan for the forbidden patterns above. - -## Introducing the canvas - -When you create a canvas, add a short note in your chat response telling the user you created a canvas they can open beside the chat: - -- **First canvas** — if no other `.canvas.tsx` files exist in the workspace's `canvases/` directory, include one sentence explaining what a canvas is. -- **Unsolicited canvas** — if the user didn't ask for a canvas, include one sentence explaining why you chose it over plain text. - -Both can apply at once; one or two sentences total is enough. Skip the intro for subsequent canvases. - -## Troubleshooting - -If a canvas appears blank or missing, the most common cause is that it was not written under `/Users//.cursor/projects//canvases/` exactly — re-save it to that path. Do not debug this by trying to create the managed directory manually; focus on correcting the file path instead. Users can click the canvas file path in the response to open it, just like any other file path in Cursor. When present, the canvas server writes a `.canvas.status.json` sidecar after each build with `status`, `diagnostics`, or `error` fields you can read; the file is best-effort and may not exist, so don't block on it. - -## Good example - -```tsx -import { Divider, Grid, H1, H2, Stack, Stat, Table, Text } from 'cursor/canvas'; - -export default function ServiceOverview() { - return ( - -

Service Overview

- - - - - - -

Service Status

- - -

Recent Changes

- Auth service latency increased after the 14:30 deploy. - Last checked: Apr 7, 2026 14:52 UTC - - ); -} -``` - -Stats in a Grid, Table directly under H2, text sections without cards. - -## Bad example — do not imitate - -```tsx -// BAD — every section wrapped in Card, no hierarchy, Table unnecessarily boxed - - Summary6 services. - Status
- ChangesLatency increased. - -``` diff --git a/skills-cursor/canvas/sdk/canvas-tokens.d.ts b/skills-cursor/canvas/sdk/canvas-tokens.d.ts deleted file mode 100644 index 823a796..0000000 --- a/skills-cursor/canvas/sdk/canvas-tokens.d.ts +++ /dev/null @@ -1,264 +0,0 @@ -/** - * Design tokens for `cursor/canvas` (standalone; no UI framework dependency). - * - * Color values are aligned with the Cursor app dark theme (`packages/ui` `cursor-dark` sources). - */ -export declare const canvasPaletteDark: { - readonly foreground: "#E4E4E4EB"; - readonly foregroundSecondary: "#E4E4E48D"; - readonly foregroundTertiary: "#E4E4E45E"; - readonly foregroundQuaternary: "#E4E4E442"; - readonly editor: "#181818"; - readonly chrome: "#141414"; - readonly sidebar: "#141414"; - readonly elevated: "#181818"; - readonly fillPrimary: "#E4E4E430"; - readonly fillSecondary: "#E4E4E41E"; - readonly fillTertiary: "#E4E4E411"; - readonly fillQuaternary: "#E4E4E40A"; - readonly strokePrimary: "#E4E4E433"; - readonly strokeSecondary: "#E4E4E41F"; - readonly strokeTertiary: "#E4E4E414"; - readonly accent: "#599CE7"; - readonly buttonBackground: "#599CE7"; - readonly buttonForeground: "#191c22"; - readonly buttonHoverBackground: "#6AABE9"; - readonly link: "#87c3ff"; - readonly diffInsertedLine: "#3FA26633"; - readonly diffRemovedLine: "#B8004933"; - readonly diffStripAdded: "#3FA2668F"; - readonly diffStripRemoved: "#FC6B838F"; -}; -/** - * Light-mode palette derived from `packages/ui/src/tokens/themes/cursor-core/light.ts`. - * Base color: #141414. Same percentages as dark (regular light has no overrides - * in CURSOR_SEMANTIC_OVERRIDES — only high-contrast does). - */ -export declare const canvasPaletteLight: { - readonly foreground: "#141414F0"; - readonly foregroundSecondary: "#141414BD"; - readonly foregroundTertiary: "#1414148A"; - readonly foregroundQuaternary: "#1414145C"; - readonly editor: "#FCFCFC"; - readonly chrome: "#F8F8F8"; - readonly sidebar: "#F3F3F3"; - readonly elevated: "#FCFCFC"; - readonly fillPrimary: "#14141433"; - readonly fillSecondary: "#14141424"; - readonly fillTertiary: "#14141414"; - readonly fillQuaternary: "#1414140F"; - readonly strokePrimary: "#14141433"; - readonly strokeSecondary: "#1414141F"; - readonly strokeTertiary: "#14141414"; - readonly accent: "#3685BF"; - readonly buttonBackground: "#3685BF"; - readonly buttonForeground: "#FCFCFC"; - readonly buttonHoverBackground: "#2E76AB"; - readonly link: "#3685BF"; - readonly diffInsertedLine: "#1F8A651F"; - readonly diffRemovedLine: "#CF2D5614"; - readonly diffStripAdded: "#1F8A65CC"; - readonly diffStripRemoved: "#CF2D56CC"; -}; -export interface CanvasPalette { - readonly foreground: string; - readonly foregroundSecondary: string; - readonly foregroundTertiary: string; - readonly foregroundQuaternary: string; - readonly editor: string; - readonly chrome: string; - readonly sidebar: string; - readonly elevated: string; - readonly fillPrimary: string; - readonly fillSecondary: string; - readonly fillTertiary: string; - readonly fillQuaternary: string; - readonly strokePrimary: string; - readonly strokeSecondary: string; - readonly strokeTertiary: string; - readonly accent: string; - readonly buttonBackground: string; - readonly buttonForeground: string; - readonly buttonHoverBackground: string; - readonly link: string; - readonly diffInsertedLine: string; - readonly diffRemovedLine: string; - readonly diffStripAdded: string; - readonly diffStripRemoved: string; -} -/** - * Chart color palette — distilled from portal-website analytics charts. - * 88% opacity (E0) softens vibrancy without dulling; palette maximizes - * hue + luminosity spread for distinguishable multi-series charts. - */ -export declare const chartPalette: { - readonly green: "#1F8A65E8"; - readonly darkGreen: "#0D855AE0"; - readonly lightGreen: "#52B896E0"; - readonly mintGreen: "#7DCAB0E0"; - readonly blue: "#2E79B5E0"; - readonly lightBlue: "#70B0D8E0"; - readonly indigo: "#5A6CC0F0"; - readonly lightIndigo: "#9AAADCE0"; - readonly purple: "#7B64B8F0"; - readonly lightPurple: "#AA98D8E0"; - readonly warmPink: "#C85898E0"; - readonly lightPink: "#E8A0C4E0"; - readonly brightOrange: "#F0A040E0"; - readonly deepOrange: "#C06028E0"; - readonly goldenYellow: "#E8C030E0"; - readonly darkAmber: "#C04848E0"; - readonly warmPeach: "#F0A088E0"; - readonly vibrantTeal: "#2A9A8AE0"; - readonly muted: "#8888A8E0"; - readonly neutralLine: "#888899D0"; -}; -/** - * Shared category palette for canvas primitives that show categorical tints - * (`Swatch`, `UsageBar` segments, etc.). Uses a coherent subset of - * `chartPalette` so a category's color reads consistently across any - * primitive that consumes it. - * - * The insertion order here is the canonical category order — primitives - * that auto-assign colors (e.g. `UsageBar` segments without an explicit - * `color`) cycle through these keys in order. - */ -export declare const colorPalette: { - readonly gray: "#8888A8E0"; - readonly purple: "#7B64B8F0"; - readonly green: "#1F8A65E8"; - readonly yellow: "#E8C030E0"; - readonly pink: "#C85898E0"; - readonly blue: "#2E79B5E0"; - readonly orange: "#F0A040E0"; -}; -export type Color = keyof typeof colorPalette; -/** - * Auto-color rotation for `UsageBar` segments without an explicit `color`. - * Decoupled from `colorPalette`'s declaration order so the palette can grow - * or be reordered without changing how unspecified segments cycle. - * - * Matches the original `packages/ui` `ContextUsageTray` order so the same - * segment index lands on the same hue as the source. - */ -export declare const usageColorSequence: readonly Color[]; -/** - * Ordered array for automatic series coloring — alternates dark/light across - * distinct hue families for maximum perceptual separation. - */ -export declare const chartColorSequence: readonly ["#1F8A65E8", "#70B0D8E0", "#5A6CC0F0", "#F0A040E0", "#C06028E0", "#E8C030E0", "#C85898E0", "#F0A088E0", "#7B64B8F0", "#7DCAB0E0", "#8888A8E0", "#2A9A8AE0"]; -declare function buildTokens(palette: CanvasPalette): { - bg: { - editor: string; - chrome: string; - elevated: string; - }; - text: { - primary: string; - secondary: string; - tertiary: string; - quaternary: string; - link: string; - onAccent: string; - }; - stroke: { - primary: string; - secondary: string; - tertiary: string; - }; - fill: { - primary: string; - secondary: string; - tertiary: string; - quaternary: string; - }; - accent: { - primary: string; - control: string; - controlHover: string; - }; - diff: { - insertedLine: string; - removedLine: string; - stripAdded: string; - stripRemoved: string; - }; -}; -/** Semantic colors for components (spacing and radius live in `theme.ts`). */ -export declare const canvasTokens: { - bg: { - editor: string; - chrome: string; - elevated: string; - }; - text: { - primary: string; - secondary: string; - tertiary: string; - quaternary: string; - link: string; - onAccent: string; - }; - stroke: { - primary: string; - secondary: string; - tertiary: string; - }; - fill: { - primary: string; - secondary: string; - tertiary: string; - quaternary: string; - }; - accent: { - primary: string; - control: string; - controlHover: string; - }; - diff: { - insertedLine: string; - removedLine: string; - stripAdded: string; - stripRemoved: string; - }; -}; -export declare const canvasTokensLight: { - bg: { - editor: string; - chrome: string; - elevated: string; - }; - text: { - primary: string; - secondary: string; - tertiary: string; - quaternary: string; - link: string; - onAccent: string; - }; - stroke: { - primary: string; - secondary: string; - tertiary: string; - }; - fill: { - primary: string; - secondary: string; - tertiary: string; - quaternary: string; - }; - accent: { - primary: string; - control: string; - controlHover: string; - }; - diff: { - insertedLine: string; - removedLine: string; - stripAdded: string; - stripRemoved: string; - }; -}; -export type CanvasTokens = ReturnType; -export {}; -//# sourceMappingURL=canvas-tokens.d.ts.map \ No newline at end of file diff --git a/skills-cursor/canvas/sdk/chart-primitives.d.ts b/skills-cursor/canvas/sdk/chart-primitives.d.ts deleted file mode 100644 index 5c478da..0000000 --- a/skills-cursor/canvas/sdk/chart-primitives.d.ts +++ /dev/null @@ -1,200 +0,0 @@ -/** - * Chart primitives for `cursor/canvas` — multi-series, stacked, and pie charts - * rendered as pure inline SVG with zero external dependencies. - * - * Distilled from the portal-website Highcharts analytics charting layer. - */ -import type { CSSProperties, JSX } from "react"; -/** - * Semantic tone for a chart series or slice. Mirrors the tone vocabulary - * used by `Stat`, `Pill`, `Table`, and other SDK primitives so colors - * match across a canvas — e.g. a `Stat tone="success"` and a - * `ChartSeries tone="success"` render in the same green. - * - * Omit `tone` to let the chart auto-assign a distinct color from the - * chart palette; supply `tone` only when the value carries semantic - * meaning that should match other tonal elements on the page. - */ -export type ChartTone = "success" | "danger" | "warning" | "info" | "neutral"; -/** A single labeled value, used by `PieChart`. */ -export type ChartDataPoint = { - label: string; - /** Non-negative numeric value. */ - value: number; -}; -/** - * A named data series for `BarChart` and `LineChart`. - * The `data` array aligns by index with the parent component's `categories`. - * If `tone` is omitted, a color is auto-assigned from the chart palette. - */ -export type ChartSeries = { - name: string; - data: number[]; - tone?: ChartTone; -}; -export type BarChartProps = { - /** Category labels along the independent axis. */ - categories: string[]; - /** One or more data series. Values align by index with `categories`. */ - series: ChartSeries[]; - height?: number; - /** Stack series on top of each other instead of grouping side-by-side. */ - stacked?: boolean; - /** Render horizontal bars instead of vertical columns. */ - horizontal?: boolean; - /** Show as 100% stacked (implies `stacked`). */ - normalized?: boolean; - /** Suffix for y-axis tick labels (e.g. "%"). */ - valueSuffix?: string; - style?: CSSProperties; -}; -export type LineChartProps = { - categories: string[]; - series: ChartSeries[]; - height?: number; - /** Fill the area under each line with a soft tint. */ - fill?: boolean; - valueSuffix?: string; - style?: CSSProperties; -}; -export type PieChartProps = { - data: Array; - size?: number; - donut?: boolean; - style?: CSSProperties; -}; -/** - * Multi-series bar/column chart with optional stacking and normalization. - * Distilled from the portal-website Highcharts analytics charts. - * - * Pass `categories` for x-axis labels and one or more `series` whose `data` - * arrays align by index. With a single series you get simple bars; with - * multiple series the default is grouped (side-by-side) — set `stacked` for - * stacked columns or `normalized` for 100%-stacked share-mode. - * - * Colors are auto-assigned from the chart palette. With a **single series**, - * each bar gets a different color by category (so a chart of 5 categories - * shows 5 colors out of the box). With **multiple series**, each series gets - * its own color. A legend appears when there are 2+ series. - * - * For semantic coloring, pass `tone` on a series — it maps to the same - * palette entries used by `Stat`, `Pill`, and `Table` so your chart matches - * tonal elements elsewhere on the page. - * - * @example - * ```tsx - * // Simple single-series - * - * - * // Stacked multi-series (like portal AI commit chart) - * - * - * // Semantic tones — "accepted" renders in the same green as - * // elsewhere on the page. - * - * ``` - */ -export declare function BarChart({ categories, series, height, stacked, horizontal, normalized, valueSuffix, style }: BarChartProps): JSX.Element; -/** - * Multi-series line chart with optional area fill. Distilled from the - * portal-website Highcharts analytics charts. - * - * Each series draws a polyline with dot markers at each data point. - * Set `fill` to shade the area under every line. Hover over any category - * column to see a tooltip with all series values at that point. - * - * This is **not** a time-series component — it does not parse dates. - * Pass pre-formatted date strings as `categories` if plotting over time. - * - * Colors are auto-assigned from the chart palette. For semantic coloring, - * pass `tone` on a series — it maps to the same palette entries used by - * `Stat`, `Pill`, and `Table`. - * - * @example - * ```tsx - * // Single line - * - * - * // Multi-series with area fill - * - * - * // Semantic tones — "errors" renders in the same red as a - * // elsewhere on the page. - * - * ``` - */ -export declare function LineChart({ categories, series, height, fill, valueSuffix, style }: LineChartProps): JSX.Element; -/** - * Pie (or donut) chart with hover highlighting. Distilled from the - * portal-website Highcharts analytics charts. - * - * Unlike `BarChart` and `LineChart`, `PieChart` takes a flat `data` array of - * `{ label, value }` points — each slice is its own category. Colors are - * auto-assigned from the chart palette; pass `tone` on a point to give a - * slice a semantic color that matches other tonal elements on the page. - * - * Hovering a slice expands it outward and dims the others; hovering a legend - * item does the same. A tooltip with value and percentage appears below the - * chart. Set `donut` for a hollow center. - * - * **Do not** use for bar-style comparisons — use `BarChart` instead. - * - * @example - * ```tsx - * // Basic pie - * - * - * // Donut with semantic tones - * - * ``` - */ -export declare function PieChart({ data, size, donut, style }: PieChartProps): JSX.Element; -//# sourceMappingURL=chart-primitives.d.ts.map \ No newline at end of file diff --git a/skills-cursor/canvas/sdk/collapsible-section.d.ts b/skills-cursor/canvas/sdk/collapsible-section.d.ts deleted file mode 100644 index 9c6673c..0000000 --- a/skills-cursor/canvas/sdk/collapsible-section.d.ts +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Borderless disclosure row — chevron + structured header (title, optional - * leading slot, count, trailing slot) with a body that toggles open. Distilled - * from baby-glass `ContextTreeRow`'s lightweight list-row chrome (no card - * border, no background fill). - * - * For a bordered surface that collapses, use `` instead. - */ -import { type CSSProperties, type JSX, type ReactNode } from "react"; -export type CollapsibleSectionProps = { - /** Plain-text title rendered next to the disclosure chevron. */ - title: string; - /** - * Optional leading visual (e.g. ``) shown between the chevron and - * the title. - */ - leading?: ReactNode; - /** - * Optional small count rendered after the title (e.g. number of children). - */ - count?: number; - /** - * Optional trailing node, right-aligned (e.g. token readout, badge, button). - * Rendered with `t.text.tertiary` color hint via the wrapper; the slot can - * override. - */ - trailing?: ReactNode; - /** Body shown when expanded. */ - children?: ReactNode; - style?: CSSProperties; -}; -/** - * Borderless collapsible row with a structured header. Always starts closed - * (uncontrolled, no `defaultOpen`). - * - * Compose with `` in the `leading` slot for a colored category icon, - * and put a token readout / pill / button in `trailing`. Body content is - * indented under the row so nested `CollapsibleSection`s read as a tree. - * - * For a bordered, card-shaped collapsible surface, use `` - * instead — `CollapsibleSection` has no border or background and is meant to - * sit in a list of similar rows. - * - * @example - * ```tsx - * // Basic - * - * Messages go here. - * - * - * // With a colored category swatch + count + trailing token readout - * } - * trailing={12.3k} - * > - * - * Search results. - * - * - * ``` - */ -export declare function CollapsibleSection({ title, leading, count, trailing, children, style }: CollapsibleSectionProps): JSX.Element; -//# sourceMappingURL=collapsible-section.d.ts.map \ No newline at end of file diff --git a/skills-cursor/canvas/sdk/dag-layout.d.ts b/skills-cursor/canvas/sdk/dag-layout.d.ts deleted file mode 100644 index 722e1a0..0000000 --- a/skills-cursor/canvas/sdk/dag-layout.d.ts +++ /dev/null @@ -1,102 +0,0 @@ -/** - * Pure layout math for directed acyclic graphs. Returns positioned node - * coordinates, edge anchor points, rank bounding boxes, and back-edge flags. - * Rendering is the caller's responsibility. - * - * Handles cycles gracefully: back-edges are detected via DFS, excluded from - * ranking, and flagged in the output so the caller can render them differently - * (e.g. dashed arcs). - */ -export type DAGLayoutOptions = { - /** Nodes to lay out. Only `id` is required. */ - nodes: Array<{ - id: string; - }>; - /** Directed edges. */ - edges: Array<{ - from: string; - to: string; - }>; - /** Flow direction. Default `"vertical"` (top-to-bottom). */ - direction?: "vertical" | "horizontal"; - /** Node box width in px. Default 160. */ - nodeWidth?: number; - /** Node box height in px. Default 40. */ - nodeHeight?: number; - /** Gap between ranks (layers) in px. Default 64. */ - rankGap?: number; - /** Gap between sibling nodes in the same rank in px. Default 48. */ - nodeGap?: number; - /** Padding around the bounding box in px. Default 24. */ - padding?: number; -}; -export type DAGLayoutNode = { - id: string; - /** Left edge of the node box. */ - x: number; - /** Top edge of the node box. */ - y: number; - /** Layer index (0 = root). */ - rank: number; - /** Position within the rank (0-indexed). */ - order: number; -}; -export type DAGLayoutEdge = { - from: string; - to: string; - /** Suggested source anchor point (center of the outgoing side). */ - sourceX: number; - sourceY: number; - /** Suggested target anchor point (center of the incoming side). */ - targetX: number; - targetY: number; - /** True when this edge was identified as a back-edge (part of a cycle). */ - isBackEdge: boolean; -}; -export type DAGLayoutRank = { - /** Rank index (0 = root). */ - rank: number; - /** Left edge of the rank bounding box. */ - x: number; - /** Top edge of the rank bounding box. */ - y: number; - /** Width of the rank bounding box. */ - width: number; - /** Height of the rank bounding box. */ - height: number; - /** Node ids in this rank, in order. */ - nodeIds: string[]; -}; -export type DAGLayoutResult = { - nodes: DAGLayoutNode[]; - edges: DAGLayoutEdge[]; - /** Bounding box per rank — useful for drawing layer bands. */ - ranks: DAGLayoutRank[]; - /** The direction used for this layout. */ - direction: "vertical" | "horizontal"; - /** Total width of the bounding box. */ - width: number; - /** Total height of the bounding box. */ - height: number; -}; -/** - * Compute a hierarchical layout for a directed graph. - * - * Returns node positions, edge anchor points, rank bounding boxes, and - * back-edge flags. The caller handles all rendering. - * - * @example - * ```ts - * const layout = computeDAGLayout({ - * nodes: [{ id: "a" }, { id: "b" }, { id: "c" }], - * edges: [{ from: "a", to: "b" }, { from: "b", to: "c" }], - * }); - * - * // layout.nodes[i].x / .y → position your own SVG/HTML elements - * // layout.edges[i].sourceX/Y, targetX/Y → draw lines between them - * // layout.edges[i].isBackEdge → style cycle edges differently - * // layout.ranks[i] → draw layer bands behind each rank - * ``` - */ -export declare function computeDAGLayout(options: DAGLayoutOptions): DAGLayoutResult; -//# sourceMappingURL=dag-layout.d.ts.map \ No newline at end of file diff --git a/skills-cursor/canvas/sdk/diff-view.d.ts b/skills-cursor/canvas/sdk/diff-view.d.ts deleted file mode 100644 index 8457bcd..0000000 --- a/skills-cursor/canvas/sdk/diff-view.d.ts +++ /dev/null @@ -1,130 +0,0 @@ -/** - * Low-level diff primitives for the canvas SDK. - * - * The canvas diff surface is intentionally minimal — two components that - * compose with the generic `Card` / `CardHeader` / `CardBody` / `Pill` / - * `Text` primitives to build any diff layout an agent can imagine: - * - * - `DiffView` — a monospaced, syntax-highlighted unified diff renderer. - * Drops into any container (a `Card`, a table cell, a bare layout, - * nothing at all). No card chrome, no header, no path display. Pass - * `path` to auto-detect the language for highlighting, or `language` - * to override. - * - * - `DiffStats` — the canonical `+N` green / `-N` red glyph pair. Use - * it anywhere a small "added/deleted" summary makes sense — in a - * `CardHeader`'s `trailing` slot, next to a filename in a file tree, - * inside a status row, etc. - * - * For file-level metadata the preferred composition is to use the - * generic `Card` family: - * - * ```tsx - * - * }> - * src/utils.ts - * - * - * - * - * - * ``` - */ -import type { CSSProperties, JSX } from "react"; -export type DiffStatsProps = { - additions?: number; - deletions?: number; - style?: CSSProperties; -}; -/** - * Inline `+N` / `-N` glyph pair. Green additions, red deletions, with - * tabular numerals so columns of stats line up. Renders nothing when - * both counts are zero. - * - * @example - * ```tsx - * }> - * src/utils.ts - * - * - * - * Refactor pass - * - * - * ``` - */ -export declare function DiffStats({ additions, deletions, style }: DiffStatsProps): JSX.Element | null; -export type DiffLineType = "added" | "removed" | "unchanged"; -export type DiffLineData = { - type: DiffLineType; - content: string; - lineNumber?: number; -}; -export type DiffViewProps = { - lines: DiffLineData[]; - /** - * File path used to infer the syntax-highlighting language from the - * extension (e.g. `"src/utils.ts"` → `typescript`). The most ergonomic - * way to enable highlighting — pass the same path you show in the - * enclosing card header. Unknown extensions silently render as plain - * text. - * - * If both `path` and `language` are provided, `language` wins. - */ - path?: string; - /** - * Explicit language override for syntax highlighting (e.g. - * `"typescript"`, `"python"`, `"tsx"`). Use this when no file path is - * available, when the path's extension is misleading, or when the - * content is a snippet rather than a real file. Accepts common - * aliases (`ts`, `py`, `rs`, `md`, etc.). Unknown languages silently - * fall back to plain text. - * - * Highlighting is applied per line, so multi-line constructs (block - * comments, template literals) may not colorize perfectly across line - * boundaries. For typical diff-sized inputs this is fine. - */ - language?: string; - /** Show line numbers in the gutter. Default `true`. */ - showLineNumbers?: boolean; - /** Color line numbers green/red for added/removed lines. Default `true`. */ - coloredLineNumbers?: boolean; - /** Show a 3px accent strip on the left edge for changed lines. Default `true`. */ - showAccentStrip?: boolean; - style?: CSSProperties; -}; -/** - * Unified diff body renderer with monospaced type, colored line - * backgrounds, line-number gutter, accent strip, and optional Shiki - * syntax highlighting. - * - * `DiffView` does not provide any surrounding chrome — place it inside - * a `Card` + `CardBody` (with `padding: 0`) when you want the standard - * bordered "file diff" look, or drop it anywhere else if you want the - * bare renderer. - * - * Pass `path` to enable syntax highlighting from the file extension. - * - * @example - * ```tsx - * - * }> - * src/utils.ts - * - * - * - * - * - * ``` - */ -export declare function DiffView({ lines, path, language, showLineNumbers, coloredLineNumbers, showAccentStrip, style }: DiffViewProps): JSX.Element; -//# sourceMappingURL=diff-view.d.ts.map \ No newline at end of file diff --git a/skills-cursor/canvas/sdk/form-primitives.d.ts b/skills-cursor/canvas/sdk/form-primitives.d.ts deleted file mode 100644 index 2280412..0000000 --- a/skills-cursor/canvas/sdk/form-primitives.d.ts +++ /dev/null @@ -1,194 +0,0 @@ -/** - * Form primitives for `cursor/canvas`. Provides themed, controlled form controls - * for interactive canvas apps with persistent state. All `onChange` callbacks - * receive the **value directly** (not a DOM event), so they pair naturally - * with `useCanvasState`: - * - * ```tsx - * const [name, setName] = useCanvasState("name", ""); - * - * ``` - */ -import { type CSSProperties, type JSX, type ReactNode } from "react"; -export type TextInputProps = { - value?: string; - /** Called with the new string value on every keystroke. */ - onChange?: (value: string) => void; - placeholder?: string; - disabled?: boolean; - type?: "text" | "email" | "password" | "number" | "url" | "search"; - style?: CSSProperties; -}; -/** - * Single-line text input (28px height). Use for names, titles, search - * queries, and short text fields. - * - * `onChange` receives the **string value**, not a DOM event — this pairs - * directly with `useCanvasState` setters. - * - * @example - * ```tsx - * const [name, setName] = useCanvasState("name", ""); - * - * - * ``` - */ -export declare function TextInput({ value, onChange, placeholder, disabled, type, style }: TextInputProps): JSX.Element; -export type TextAreaProps = { - value?: string; - /** Called with the new string value on every keystroke. */ - onChange?: (value: string) => void; - placeholder?: string; - disabled?: boolean; - /** Minimum visible rows. Defaults to 3. */ - rows?: number; - style?: CSSProperties; -}; -/** - * Multi-line text input that auto-resizes to fit its content. - * Use for notes, descriptions, comments, and multi-line text fields. - * - * The textarea grows as the user types. Set `rows` for the minimum visible - * height (defaults to 3). Override with `style={{ height: "100px" }}` for a - * fixed size. - * - * @example - * ```tsx - * const [notes, setNotes] = useCanvasState("notes", ""); - * - *