Boss icon

Boss

BMAD pipeline plugin that orchestrates a full requirements-to-deploy workflow across nine specialist agents with an auditable runtime DAG and quality gates, for Claude Code, Codex, OpenClaw, and Antigravity.

echovic/boss · v5.0.3 · Development & Workflow

echoVicOwner verifiedreview

Trust Score

87

Security

88

Surfaces

29

What is Boss?

Boss is a published development & workflow plugin for AI coding agents in the claude-code ecosystem, developed by echoVic and distributed through the HOL AI plugin registry. BMAD pipeline plugin that orchestrates a full requirements-to-deploy workflow across nine specialist agents with an auditable runtime DAG and quality gates, for Claude Code, Codex, OpenClaw, and Antigravity.

Canonical slug
echovic/boss
Version
v5.0.3 · updated Sep 29, 2026

Trust & Reputation

HOL Trust Score
87

Factor Analysis

Per-metric points (0–100 each) combined via a weighted average into the overall score.

Installability
88pts
Maintenance
100pts
MCP Posture
100pts
Plugin Security
88pts
Provenance
70pts
Publisher Quality
75pts

Registry Snapshot

Publisher verification
No
Marketplace source
Unknown
Scanner
Broker fallback
Safety label
review
Digest verified
Yes
29 bundled skills — copy or download SKILL.mdOpen skills

Trust & reputation

Trust & Reputation

HOL Trust Score
87

Factor Analysis

Per-metric points (0–100 each) combined via a weighted average into the overall score.

Installability
88pts
Maintenance
100pts
MCP Posture
100pts
Plugin Security
88pts
Provenance
70pts
Publisher Quality
75pts

Provenance

Plugin root
.
Source repo
https://github.com/echoVic/boss-skill
Source commit
f8f42941ee87…
Publisher verified
No
Owner verified
@echoVic

Continuous scanner CI detected

No action is required. This plugin receives the full trust score.

Verified badge detected

This listing scores +2% trust because the HOL verified badge is present in the source repository README.

Security Posture

review
Safety label
88
Security score
0
High findings
Provider
registry-broker-fallback
Grade
B · review
Version
Unknown
cisco-skill-scanner: unknown

Findings

mediumpublishabilitypublishability.asset.missing

Referenced asset is missing from the plugin package.

infoskill-securityskill-scan.unavailable

Cisco skill scanner timed out after 60000 ms

infoskill-securityskill-scan.unavailable

Cisco skill scanner timed out after 60000 ms

infoskill-securityskill-scan.unavailable

Cisco skill scanner timed out after 60000 ms

infoskill-securityskill-scan.unavailable

Cisco skill scanner timed out after 60000 ms

infoskill-securityskill-scan.unavailable

Cisco skill scanner timed out after 60000 ms

infoskill-securityskill-scan.unavailable

Cisco skill scanner timed out after 60000 ms

infoskill-securityskill-scan.unavailable

Cisco skill scanner timed out after 60000 ms

infoskill-securityskill-scan.unavailable

Cisco skill scanner timed out after 60000 ms

infoskill-securityskill-scan.unavailable

Cisco skill scanner timed out after 60000 ms

infoskill-securityskill-scan.unavailable

Cisco skill scanner timed out after 60000 ms

infoskill-securityskill-scan.unavailable

Cisco skill scanner timed out after 60000 ms

infoskill-securityskill-scan.unavailable

Cisco skill scanner timed out after 60000 ms

infoskill-securityskill-scan.unavailable

Cisco skill scanner timed out after 60000 ms

infoskill-securityskill-scan.unavailable

Cisco skill scanner timed out after 60000 ms

infoskill-securityskill-scan.unavailable

Cisco skill scanner timed out after 60000 ms

infoskill-securityskill-scan.unavailable

Cisco skill scanner timed out after 60000 ms

infoskill-securityskill-scan.unavailable

Cisco skill scanner timed out after 60000 ms

infoskill-securityskill-scan.unavailable

Cisco skill scanner timed out after 60000 ms

infoskill-securityskill-scan.unavailable

Cisco skill scanner timed out after 60000 ms

infoskill-securityskill-scan.unavailable

Cisco skill scanner timed out after 60000 ms

infoskill-securityskill-scan.unavailable

Cisco skill scanner timed out after 60000 ms

infoskill-securityskill-scan.unavailable

Cisco skill scanner timed out after 60000 ms

infoskill-securityskill-scan.unavailable

Cisco skill scanner timed out after 60000 ms

infoskill-securityskill-scan.unavailable

Cisco skill scanner timed out after 60000 ms

infoskill-securityskill-scan.unavailable

Cisco skill scanner timed out after 60000 ms

infoskill-securityskill-scan.unavailable

Cisco skill scanner timed out after 60000 ms

infoskill-securityskill-scan.unavailable

Cisco skill scanner timed out after 60000 ms

infoskill-securityskill-scan.unavailable

Cisco skill scanner timed out after 60000 ms

infoskill-securityskill-scan.unavailable

Cisco skill scanner timed out after 60000 ms

Boss — Frequently asked questions

What is Boss?
Boss is an AI plugin in the HOL registry. BMAD pipeline plugin that orchestrates a full requirements-to-deploy workflow across nine specialist agents with an auditable runtime DAG and quality gates, for Claude Code, Codex, OpenClaw, and Antigravity.
How do I install Boss?
Install Boss in your harness: Codex — codex plugin marketplace add echoVic/boss-skill; Claude Code — /plugin marketplace add echoVic/boss-skill; Any agent — npx skills add echoVic/boss-skill. Full step-by-step guidance is on the HOL plugin page.
How do I install Boss in Codex?
To install Boss in Codex, start with codex plugin marketplace add echoVic/boss-skill. The complete step-by-step install guide for Codex is on the HOL plugin page.
How do I install Boss in Claude Code?
To install Boss in Claude Code, start with /plugin marketplace add echoVic/boss-skill. The complete step-by-step install guide for Claude Code is on the HOL plugin page.
Is Boss free?
Pricing for Boss is published on its HOL plugin page when the maker schedules a launch.
Who publishes Boss?
Boss is published by echoVic and listed on HOL.
Is Boss available now?
Boss availability is listed on its HOL plugin page.

Install Guidance

Install in Claude Code

Install through the Claude Code plugin marketplace.

Claude Code plugin docs
  1. 1

    Add the marketplace

    Run this inside a Claude Code session.

    claude code
  2. 2

    Install the plugin

    Use the plugin name and the marketplace name shown by the previous command.

    claude code
  3. 3

    Scripted alternative

    Non-interactive equivalent for scripts and CI pipelines. Add --scope project to pin the install to one repository.

    shell

Plugin Manifest

{
  "name": "boss",
  "version": "5.0.3",
  "description": "BMAD pipeline plugin for Codex with installer-managed hooks and shared Boss runtime behavior.",
  "author": {
    "name": "echoVic",
    "email": "[email protected]",
    "url": "https://github.com/echoVic"
  },
  "homepage": "https://github.com/echoVic/boss-skill",
  "repository": "https://github.com/echoVic/boss-skill",
  "license": "MIT",
  "keywords": [
    "bmad",
    "pipeline",
    "codex",
    "agent-orchestration",
    "automation"
  ],
  "skills": "./",
  "hooks": "./skill/hooks/codex/hooks.json",
  "interface": {
    "displayName": "Boss",
    "developerName": "echoVic",
    "shortDescription": "Auditable multi-agent engineering workflow for Codex.",
    "longDescription": "Boss turns Codex into a structured engineering team with PM, architecture, implementation, QA, DevOps, runtime state, hooks, quality gates, and replayable delivery artifacts.",
    "category": "Productivity",
    "capabilities": [
      "Planning",
      "Code Review",
      "Testing"
    ],
    "websiteURL": "https://github.com/echoVic/boss-skill",
    "privacyPolicyURL": "https://github.com/echoVic/boss-skill/blob/main/docs/PRIVACY.md",
    "termsOfServiceURL": "https://github.com/echoVic/boss-skill/blob/main/docs/TERMS.md",
    "composerIcon": "./assets/boss-composer-icon.svg",
    "logo": "./assets/boss-logo.svg",
    "screenshots": [
      "./boss-skill-promo.png"
    ],
    "defaultPrompt": [
      "Use Boss to plan and implement this feature.",
      "Run Boss QA on this project.",
      "Review this code with Boss."
    ],
    "brandColor": "#171717"
  },
  "registryIndexVersion": 5
}

Marketplace Source

Repo URL
https://github.com/echoVic/boss-skill
Marketplace path
Unknown
Source path
plugins/echoVic/boss-skill
Install policy
AVAILABLE

Skills

Copy or download the SKILL.md files this plugin ships, then install them with the Skills CLI.

Share
skills-cli

boss

skill/SKILL.md

|

Raw SKILL.md
---
name: boss
description: |
  可审计的 agent 团队:BMAD 全自动研发流水线编排器。编排 9 个专业 Agent(PM、架构师、UI Designer、Tech Lead、Scrum Master、Frontend、Backend、QA、DevOps)从需求到部署,每一步都有事件溯源 + 不可绕过门禁 + 确定性 eval——可验证测试真跑、门禁真过。支持单环节切片命令(/boss:plan /review /qa /ship)与无 CLI 纯 Markdown 降级。

  Triggers(全流水线): 'boss mode', '/boss', '全自动开发', '从需求到部署', '帮我做一个', 'build this', 'ship it', '全流程', '自动化开发', '一键开发', 'start a project', 'new feature'

  Triggers(单环节切片,对存量项目最常用):
  - /boss:review — '帮我评审', '代码评审', '技术评审', '看看这段代码有什么问题', '风险评估', 'review this', 'review my PR', 'code review'
  - /boss:qa — '跑一下测试', '补测试', '检查质量', '测试覆盖够不够', '门禁过了吗', 'run the tests', 'check quality', 'add tests'
  - /boss:plan — '先出个方案', '写个 PRD', '设计一下架构', 'write a spec', 'plan this feature'
  - /boss:ship — '可以发布了吗', '部署检查', 'ready to ship', 'deploy checks'

  Does NOT trigger:
  - 单文件修改或简单 bug 修复(直接编辑即可)
  - 纯代码阅读或解释(使用 read 工具)
  - 已有 pipeline 正在运行时的重复启动
  - 极小事(预计 <30 分钟人工可完成、不需要 PRD/架构/门禁记录)

  Output: 完整项目代码 + PRD/架构/UI/测试/部署文档,写入 .boss/<feature>/ 目录
version: 5.0.3
license: MIT
user-invocable: true
---

# Boss - BMAD Harness Orchestrator

你是 **Boss Agent**,负责编排完整软件开发生命周期。不要把本文件当百科全书;本文件只保存入口、不变量和按需读取索引。

## 不变量

1. **你负责编排,不直接替专业 Agent 写正式产物。**
2. **状态真相源是 runtime 事件流。** 不直接编辑 `.boss/<feature>/.meta/execution.json`;所有状态变更通过 `boss runtime ...`。
3. **产物驱动。** 文档和代码产物写入 `.boss/<feature>/`,完成后用 `boss runtime record-artifact` 记录。
4. **质量门禁不可绕过。** 测试、Wave 边界校验、最终 gate 失败时不得宣布交付完成。
5. **渐进式披露。** 只读取当前步骤需要的 reference、Agent prompt、template;不要一次性加载所有协议全文。
6. **平台适配不改变状态语义。** Claude Code、Codex、OpenClaw、Antigravity、Hermes 都以 Runtime Core 为准。
7. **中文交付。** Boss 生成的 `.boss/<feature>/` 文档默认使用中文。
8. **不重造宿主已有的能力。** Boss 只提供宿主没有的东西:事件溯源审计、不可绕过的门禁、
   产物 provenance。派发子 Agent、读写文件、检索代码、会话内任务清单一律用宿主原语。

## 职责边界:Boss 提供什么、宿主提供什么

| 能力 | 归属 | 说明 |
|------|------|------|
| 子 Agent 派发 | **宿主** | 用宿主的 Task / Agent 工具,Boss 不自建调度器 |
| 文件读写、代码检索 | **宿主** | Read / Write / Edit / Glob / Grep |
| 会话内临时清单 | **宿主** | 宿主的 todo 原语;Boss 的 todo 仅指会话收敛产出的
  带 owner 与 successCriteria 的跨 Agent 交付项,落在事件流中 |
| 结构化返回 | **宿主 + 工具层校验** | 状态经 `report-agent-status` 校验枚举,不解析散文 |
| 事件溯源与重放 | **Boss** | `events.jsonl` 追加写 + projector 重放,宿主不提供 |
| 不可绕过门禁 | **Boss** | 建模为 runtime stage,非提示词自觉 |
| 产物 provenance | **Boss** | 对能改变 Agent 行为的文件做内容指纹 |
| 记忆 / 偏好派生 | **Boss,确定性** | 从 `events.jsonl` 规则化投影(含用户选择偏好聚合),
  可完整重放;不外挂第二个 LLM 去二次抽取 |

## 什么时候读取什么

| 场景 | 读取 |
|------|------|
| 进入 `/boss` 或 boss mode,准备跑完整流水线 | `references/orchestration-loop.md` |
| 需要 runtime 命令、workflow-plan、resume、事件真相源 | `references/runtime-surface.md` |
| 准备派发 code Agent、检查 Evidence Wave、Blast Radius、写集冲突 | `references/evidence-waves.md` |
| 需要解释或适配 Claude/Codex/OpenClaw/Antigravity/Hermes 行为 | `references/platform-drivers.md` |
| 调试 hooks、session resume/end、artifact guard | `references/hooks-runtime.md` |
| 准备或记录文档/JSON 产物 | `references/artifact-guide.md` |
| 需要质量门禁细节 | `references/quality-gate.md` |
| 需要测试证据要求 | `references/testing-standards.md` |
| 需要 BMAD 背景或历史设计说明 | `references/bmad-methodology.md` |
| 未检测到 `boss` CLI,需要纯 Markdown 降级运行 | `references/no-cli-fallback.md` |
| 需要扩展 Boss(自定义 Agent / pack / gate 插件) | `references/extending-boss.md` |
| 派发子 Agent 前建立公共协议 prefix 缓存 | `agents/shared/protocol-manifest.md` |
| 子 Agent 状态格式、会话原语、REVISION_NEEDED | `agents/prompts/subagent-protocol.md` |
| 需要技术栈探测协议 | `agents/shared/tech-detection.md` |

## 快速入口

1. 判断用户输入是否是可执行任务。约束类输入不要新建 `.boss/<feature>/`;按 `references/orchestration-loop.md` 的 Feature Slug 归一化处理。
2. **CLI 探测**:派发前运行 `boss --version`。CLI 随本 skill 分发(市场安装自带,无需 npm):
   - 插件安装(Claude Code / Codex):`node "${CLAUDE_PLUGIN_ROOT}/skill/cli/bin/boss.mts" --version`
   - 复制安装 / skills.sh:`node <skill>/cli/bin/boss.mts --version`(`<skill>` 即包含本 SKILL.md 的目录;需 Node >=22.18)
   - PATH 上已有 `boss` 时可直接用 `boss`
   失败则进入降级模式,读取 `references/no-cli-fallback.md`,用 `.boss/<feature>/STATE.md` 承载状态(CLI 是可审计性增强,不是准入条件)。下文所有 `boss <command>` 均指运行上述入口。
3. 除非 `--quick`,先确认”做什么 + 给谁用 + 核心场景”。缺失时读取 `skills/brainstorming/SKILL.md`。
4. 初始化或恢复项目:
   - 新 feature:`boss project init <feature-name>`
   - 低阶 runtime 初始化:`boss runtime init-pipeline <feature>`
   - 继续执行图:`boss runtime resume <feature> --from-run <run-id>`
5. 调用 `boss packs detect <project-dir> --json`,再根据 ready artifacts 循环派发 Agent。
6. 每个产物完成后调用 `boss runtime record-artifact <feature> <artifact-name> <N>`。
7. code 阶段前必须读取 `references/evidence-waves.md`;缺 Repo Preflight、Evidence Wave、Contract Matrix、写集 owner、Blast Radius 任一项,不得派发 code Agent。
8. 收尾前运行适用测试、门禁和 `boss runtime generate-summary <feature>`。

## Agent 路由

| Agent | 文件 | 读取时机 |
|-------|------|----------|
| PM | `agents/boss-pm.md` | 生成或修订 PRD |
| Architect | `agents/boss-architect.md` | 架构设计、API/数据模型、技术选型 |
| UI Designer | `agents/boss-ui-designer.md` | `ui-spec.md` 与 `ui-design.json` |
| Tech Lead | `agents/boss-tech-lead.md` | 技术评审、风险评估 |
| Scrum Master | `agents/boss-scrum-master.md` | `tasks.md`、Evidence Wave、写集规划 |
| Frontend | `agents/boss-frontend.md` | 前端实现,优先遵循 `ui-design.json` |
| Backend | `agents/boss-backend.md` | API、数据库、后端测试 |
| QA | `agents/boss-qa.md` | 核心用户路径、真实 payload、越权/分页/旧数据验证 |
| DevOps | `agents/boss-devops.md` | 构建、部署、健康检查 |

## 子代理协议

- 先读取 `agents/shared/protocol-manifest.md`,使用协议 manifest、prefix 缓存、按需加载和渐进式披露。
- 只有状态格式或会话升级不清楚时,再读取 `agents/shared/agent-protocol.md` 或 `agents/prompts/subagent-protocol.md`。
- 子代理状态只接受 `DONE` / `DONE_WITH_CONCERNS` / `NEEDS_CONTEXT` / `BLOCKED` / `REVISION_NEEDED`。
- 子代理自报 `DONE` 不等于验收通过;必须跑 Wave 边界校验或对应门禁。

## 命令入口地图

`/boss` 是完整流水线;下列切片命令是同一底层的**单环节独立入口**,复用相同 agent prompt、runtime 与 `.boss/<feature>/` 产物,适合只想用其中一环或对已有项目单点介入的场景。

| 命令 | 环节 | 底层 |
|------|------|------|
| `/boss` | 完整 4 阶段流水线 | `references/orchestration-loop.md` |
| `/boss:plan` | 规划(PM + Architect) | `agents/boss-pm.md`、`agents/boss-architect.md` |
| `/boss:review` | 技术评审(Tech Lead,只读) | `agents/boss-tech-lead.md` |
| `/boss:qa` | 测试 + 门禁(QA) | `agents/boss-qa.md`、`references/quality-gate.md` |
| `/boss:ship` | 构建部署(DevOps + Gate 2) | `agents/boss-devops.md` |
| `/boss:extend` | 引导式扩展自定义 agent / pack | `references/extending-boss.md` |

## 语言参数

所有命令支持 `--lang <zh|en>` 控制 `.boss/<feature>/` 产物语言。未显式指定时默认 `zh`(不变量 7)。切片命令与 `/boss` 共享该参数语义。

## 项目扩展点

- 项目级模板:`.boss/templates/`
- 项目级插件:`.boss/plugins/`
- 项目级 pipeline packs:`.boss/pipeline-packs/`
- 项目级 Artifact DAG:`.boss/artifact-dag.json`
- 可渲染 UI 设计产物:`.boss/<feature>/ui-design.json`,预览命令 `boss design preview <feature>`

## 输出格式

最终回答包含:
- feature 名称和 `.boss/<feature>/` 产物路径
- 关键文档路径
- 测试和门禁摘要
- 未完成事项或阻塞原因
- 部署/预览 URL(如有)

architect/architecture-design

skill/skills/architect/architecture-design/SKILL.md

系统架构设计方法论,包含架构模式选择、系统分层、目录结构设计

Raw SKILL.md
---
name: architect/architecture-design
description: 系统架构设计方法论,包含架构模式选择、系统分层、目录结构设计
version: 1.0.0
agent: architect
type: methodology
user-invocable: false
agent-invocable: true
dependencies:
  - shared/tech-stack-detection
  - architect/tech-research
triggers:
  - 技术调研完成后
  - 需要设计系统架构时
  - 需要定义项目结构时
metadata:
  internal: true
---

# 系统架构设计方法论

## 适用场景

基于技术调研结论,设计完整的系统架构,包括:
- 架构模式选择(单体/前后端分离/微服务)
- 系统分层和模块划分
- 目录结构设计
- 数据模型设计
- API设计

## 架构设计流程

### 1. 架构模式选择

根据项目规模、团队规模、业务复杂度选择合适的架构模式:

| 架构模式 | 适用场景 | 优点 | 缺点 | 团队规模 |
|----------|----------|------|------|----------|
| **单体应用** | 小型项目、快速迭代、MVP | 简单、开发快、易部署 | 扩展性差、耦合高 | 1-3人 |
| **前后端分离** | 中型项目、团队协作、多端支持 | 职责清晰、并行开发、技术独立 | 部署复杂、接口管理 | 3-10人 |
| **微服务** | 大型项目、独立部署、高可用 | 独立扩展、技术异构、故障隔离 | 复杂度高、运维成本高 | 10+人 |
| **Serverless** | 事件驱动、弹性伸缩、按需付费 | 免运维、自动扩展、成本优化 | 冷启动、供应商锁定 | 任意 |

**选择决策树**:

```
项目规模?
├─ 小型(< 10个页面)
│  └─ 单体应用 或 前后端分离(简化版)
├─ 中型(10-50个页面)
│  └─ 前后端分离
└─ 大型(> 50个页面)
   ├─ 业务模块独立?
   │  ├─ 是 → 微服务
   │  └─ 否 → 前后端分离
   └─ 流量波动大?
      └─ 是 → Serverless
```

### 2. 系统分层设计

#### 经典三层架构

```
┌─────────────────────────────────┐
│      表现层 (Presentation)       │  ← 用户界面、API接口
├─────────────────────────────────┤
│       业务层 (Business)          │  ← 业务逻辑、流程控制
├─────────────────────────────────┤
│      数据层 (Data Access)        │  ← 数据库访问、ORM
└─────────────────────────────────┘
```

#### 前后端分离架构

```
┌──────────────┐
│   前端应用    │  ← React/Vue/Angular
└──────┬───────┘
       │ HTTP/WebSocket
┌──────▼───────┐
│   API网关    │  ← 路由、认证、限流
└──────┬───────┘
       │
┌──────▼───────┐
│   后端服务    │  ← 业务逻辑
└──────┬───────┘
       │
┌──────▼───────┐
│   数据库     │  ← PostgreSQL/MongoDB
└──────────────┘
```

#### 微服务架构

```
┌──────────┐
│  前端应用 │
└────┬─────┘
     │
┌────▼─────┐
│ API网关  │
└────┬─────┘
     │
     ├─────┬─────┬─────┐
     │     │     │     │
┌────▼┐ ┌─▼──┐ ┌▼───┐ ┌▼────┐
│用户 │ │订单│ │商品│ │支付 │
│服务│ │服务│ │服务│ │服务 │
└────┘ └────┘ └────┘ └─────┘
  │      │      │       │
  └──────┴──────┴───────┘
         │
    ┌────▼────┐
    │ 数据库  │
    └─────────┘
```

### 3. 系统架构图

使用 Mermaid 绘制系统架构图:

**前后端分离架构示例**:

```mermaid
graph TB
    subgraph 客户端
        Web[Web 应用]
        Mobile[移动端]
    end

    subgraph 接入层
        CDN[CDN]
        LB[负载均衡]
    end

    subgraph 应用层
        subgraph 前端服务
            FE[前端应用]
        end

        subgraph 后端服务
            API[API 网关]
            Auth[认证服务]
            BIZ[业务服务]
        end
    end

    subgraph 数据层
        DB[(主数据库)]
        Cache[(缓存)]
        MQ[消息队列]
    end

    subgraph 基础设施
        Log[日志系统]
        Monitor[监控告警]
    end

    Web --> CDN
    Mobile --> LB
    CDN --> LB
    LB --> FE
    FE --> API
    API --> Auth
    API --> BIZ
    BIZ --> DB
    BIZ --> Cache
    BIZ --> MQ
    BIZ --> Log
```

### 4. 目录结构设计

**重要原则**:
1. **遵循框架惯例**:使用检测到的框架的标准目录结构
2. **关注点分离**:业务逻辑、数据访问、API层清晰分离
3. **测试并置**:测试文件与源码在同层或专用tests目录
4. **配置集中**:环境配置统一管理

#### Next.js App Router 项目结构

```
project/
├── app/                    # Next.js App Router
│   ├── (auth)/            # 路由组:认证相关页面
│   │   ├── login/
│   │   └── register/
│   ├── (dashboard)/       # 路由组:仪表板
│   │   ├── layout.tsx
│   │   └── page.tsx
│   ├── api/               # API Routes
│   │   ├── auth/
│   │   └── users/
│   ├── layout.tsx         # 根布局
│   └── page.tsx           # 首页
├── components/            # React组件
│   ├── ui/               # UI组件
│   └── features/         # 功能组件
├── lib/                   # 工具库
│   ├── db.ts             # 数据库连接
│   ├── auth.ts           # 认证逻辑
│   └── utils.ts          # 工具函数
├── prisma/               # Prisma ORM
│   └── schema.prisma
├── public/               # 静态资源
├── tests/                # 测试
└── package.json
```

#### Express + React 前后端分离结构

```
project/
├── client/               # 前端
│   ├── src/
│   │   ├── components/
│   │   ├── pages/
│   │   ├── hooks/
│   │   └── App.tsx
│   ├── public/
│   └── package.json
├── server/               # 后端
│   ├── src/
│   │   ├── routes/      # 路由
│   │   ├── controllers/ # 控制器
│   │   ├── services/    # 业务逻辑
│   │   ├── models/      # 数据模型
│   │   ├── middleware/  # 中间件
│   │   └── app.ts       # 入口
│   ├── tests/
│   └── package.json
├── shared/              # 共享代码
│   └── types/          # TypeScript类型
└── docker-compose.yml
```

#### Python FastAPI 项目结构

```
project/
├── app/
│   ├── api/             # API路由
│   │   ├── v1/
│   │   │   ├── endpoints/
│   │   │   └── router.py
│   │   └── deps.py      # 依赖注入
│   ├── core/            # 核心配置
│   │   ├── config.py
│   │   └── security.py
│   ├── models/          # 数据模型
│   ├── schemas/         # Pydantic schemas
│   ├── services/        # 业务逻辑
│   └── main.py          # 入口
├── tests/
├── alembic/             # 数据库迁移
├── requirements.txt
└── pyproject.toml
```

#### Go 标准项目结构

```
project/
├── cmd/                 # 主程序入口
│   └── api/
│       └── main.go
├── internal/            # 私有代码
│   ├── handler/        # HTTP处理器
│   ├── service/        # 业务逻辑
│   ├── repository/     # 数据访问
│   └── model/          # 数据模型
├── pkg/                 # 公共库
│   └── utils/
├── api/                 # API定义
│   └── openapi.yaml
├── migrations/          # 数据库迁移
├── tests/
├── go.mod
└── go.sum
```

### 5. 技术栈总览

输出完整的技术栈清单:

| 层级 | 技术 | 版本 | 说明 |
|------|------|------|------|
| **前端** | | | |
| 框架 | Next.js | 14.x | App Router模式 |
| UI库 | React | 18.x | |
| 样式 | Tailwind CSS | 3.x | 原子化CSS |
| 状态管理 | Zustand | 4.x | 轻量级状态管理 |
| **后端** | | | |
| 运行时 | Node.js | 20.x | LTS版本 |
| 框架 | Next.js API Routes | 14.x | 与前端一体 |
| ORM | Prisma | 5.x | 类型安全ORM |
| **数据** | | | |
| 主数据库 | PostgreSQL | 16.x | 关系型数据库 |
| 缓存 | Redis | 7.x | 可选 |
| **基础设施** | | | |
| 容器化 | Docker | 24.x | 开发环境 |
| CI/CD | GitHub Actions | - | 自动化部署 |
| 部署 | Vercel | - | 托管平台 |

## 输出要求

完成架构设计后,应输出以下内容(通常作为架构文档的第2-3章):

```markdown
## 2. 架构概述

### 2.1 架构类型选择

**本项目选择**:[架构模式] - [选择理由]

### 2.2 系统架构图

[Mermaid架构图]

### 2.3 技术栈总览

[技术栈表格]

---

## 3. 目录结构

[目录树]

### 目录说明

- `app/`: [说明]
- `components/`: [说明]
- `lib/`: [说明]
```

## 关键原则

1. **遵循惯例**:使用框架的标准结构,不要自创
2. **职责清晰**:每个目录的职责明确,不要混杂
3. **扩展性**:结构要易于扩展,不要过早优化
4. **一致性**:命名和组织保持一致

## 常见误区

❌ **自创结构**:不遵循框架惯例,自己发明目录结构
❌ **过度设计**:小项目用微服务架构
❌ **职责混乱**:业务逻辑、数据访问、UI混在一起
❌ **忽略测试**:没有规划测试文件的位置

architect/data-api-design

skill/skills/architect/data-api-design/SKILL.md

数据模型和API设计方法论,包含ERD设计、数据字典、RESTful API规范

Raw SKILL.md
---
name: architect/data-api-design
description: 数据模型和API设计方法论,包含ERD设计、数据字典、RESTful API规范
version: 1.0.0
agent: architect
type: methodology
user-invocable: false
agent-invocable: true
dependencies: []
triggers:
  - 架构设计完成后
  - 需要设计数据模型时
  - 需要定义API接口时
metadata:
  internal: true
---

# 数据模型与API设计方法论

## 适用场景

在系统架构确定后,需要设计:
- 数据库表结构和关系
- 数据字典和约束
- API接口规范
- 请求/响应格式

## 数据模型设计

### 1. 实体识别

从PRD中识别核心实体(名词):

**示例**:
- 用户系统:User(用户)、Role(角色)、Permission(权限)
- 博客系统:User(用户)、Post(文章)、Comment(评论)、Tag(标签)
- 电商系统:User(用户)、Product(商品)、Order(订单)、OrderItem(订单项)

### 2. 关系识别

确定实体之间的关系:

| 关系类型 | 说明 | 示例 |
|----------|------|------|
| **一对一 (1:1)** | 一个A对应一个B | User - Profile |
| **一对多 (1:N)** | 一个A对应多个B | User - Post |
| **多对多 (M:N)** | 多个A对应多个B | Post - Tag |

**关系表示**:
- `||--o{`: 一对多
- `||--||`: 一对一
- `}o--o{`: 多对多

### 3. 实体关系图 (ERD)

使用 Mermaid 绘制 ERD:

```mermaid
erDiagram
    User ||--o{ Post : creates
    User ||--o{ Comment : writes
    Post ||--o{ Comment : has
    Post }o--o{ Tag : has

    User {
        uuid id PK
        string email UK
        string name
        string passwordHash
        enum role
        datetime createdAt
        datetime updatedAt
    }

    Post {
        uuid id PK
        uuid authorId FK
        string title
        text content
        enum status
        datetime publishedAt
        datetime createdAt
        datetime updatedAt
    }

    Comment {
        uuid id PK
        uuid postId FK
        uuid userId FK
        text content
        datetime createdAt
    }

    Tag {
        uuid id PK
        string name UK
    }
```

### 4. 数据字典

为每个表定义详细的字段信息:

#### User 表

| 字段 | 类型 | 约束 | 默认值 | 说明 |
|------|------|------|--------|------|
| id | UUID | PK | uuid_generate_v4() | 主键 |
| email | VARCHAR(255) | UNIQUE, NOT NULL | - | 邮箱,用于登录 |
| name | VARCHAR(100) | NOT NULL | - | 用户名 |
| passwordHash | VARCHAR(255) | NOT NULL | - | 密码哈希(bcrypt) |
| role | ENUM('user', 'admin') | NOT NULL | 'user' | 用户角色 |
| createdAt | TIMESTAMP | NOT NULL | NOW() | 创建时间 |
| updatedAt | TIMESTAMP | NOT NULL | NOW() | 更新时间 |

**索引**:
- `idx_user_email`: email(唯一索引,用于登录查询)
- `idx_user_role`: role(用于角色筛选)

#### Post 表

| 字段 | 类型 | 约束 | 默认值 | 说明 |
|------|------|------|--------|------|
| id | UUID | PK | uuid_generate_v4() | 主键 |
| authorId | UUID | FK, NOT NULL | - | 作者ID,外键关联User.id |
| title | VARCHAR(200) | NOT NULL | - | 文章标题 |
| content | TEXT | NOT NULL | - | 文章内容 |
| status | ENUM('draft', 'published', 'archived') | NOT NULL | 'draft' | 文章状态 |
| publishedAt | TIMESTAMP | NULL | - | 发布时间 |
| createdAt | TIMESTAMP | NOT NULL | NOW() | 创建时间 |
| updatedAt | TIMESTAMP | NOT NULL | NOW() | 更新时间 |

**索引**:
- `idx_post_author`: authorId(用于查询用户的文章)
- `idx_post_status`: status(用于筛选状态)
- `idx_post_published`: publishedAt(用于按发布时间排序)

### 5. 数据类型选择

| 数据类型 | 使用场景 | PostgreSQL | MySQL | MongoDB |
|----------|----------|------------|-------|---------|
| **主键** | 唯一标识 | UUID, SERIAL | INT AUTO_INCREMENT, UUID | ObjectId |
| **字符串** | 短文本 | VARCHAR(n) | VARCHAR(n) | String |
| **长文本** | 文章内容 | TEXT | TEXT | String |
| **整数** | 数量、年龄 | INTEGER, BIGINT | INT, BIGINT | Number |
| **小数** | 价格、评分 | DECIMAL(p,s) | DECIMAL(p,s) | Number |
| **布尔** | 是否标志 | BOOLEAN | TINYINT(1) | Boolean |
| **日期时间** | 时间戳 | TIMESTAMP | DATETIME | Date |
| **枚举** | 固定选项 | ENUM | ENUM | String |
| **JSON** | 灵活数据 | JSONB | JSON | Object |

**推荐**:
- **主键**:使用 UUID 而非自增ID(避免暴露数据量、分布式友好)
- **时间戳**:使用 TIMESTAMP WITH TIME ZONE(时区友好)
- **枚举**:使用 ENUM 而非字符串(类型安全、节省空间)
- **JSON**:PostgreSQL 使用 JSONB(支持索引和查询)

## API设计

### 1. API规范选择

| 规范 | 适用场景 | 优点 | 缺点 |
|------|----------|------|------|
| **RESTful** | 通用场景、CRUD操作 | 简单、标准、易理解 | 过度获取、多次请求 |
| **GraphQL** | 复杂查询、多端适配 | 按需获取、类型安全 | 学习曲线、缓存复杂 |
| **gRPC** | 微服务、高性能 | 性能高、类型安全 | 浏览器支持差 |

**本项目推荐**:RESTful(除非有特殊需求)

### 2. RESTful API设计原则

#### 资源命名

- **使用名词**:`/users`, `/posts`, `/comments`(不是 `/getUsers`, `/createPost`)
- **使用复数**:`/users`(不是 `/user`)
- **使用小写**:`/users`(不是 `/Users`)
- **使用连字符**:`/order-items`(不是 `/orderItems` 或 `/order_items`)

#### HTTP方法

| 方法 | 用途 | 示例 | 幂等性 |
|------|------|------|--------|
| GET | 获取资源 | `GET /users` | 是 |
| POST | 创建资源 | `POST /users` | 否 |
| PUT | 完整更新 | `PUT /users/123` | 是 |
| PATCH | 部分更新 | `PATCH /users/123` | 否 |
| DELETE | 删除资源 | `DELETE /users/123` | 是 |

#### URL设计

| 操作 | 方法 | URL | 说明 |
|------|------|-----|------|
| 获取列表 | GET | `/api/v1/users` | 支持分页、筛选、排序 |
| 获取详情 | GET | `/api/v1/users/:id` | 返回单个资源 |
| 创建 | POST | `/api/v1/users` | 请求体包含资源数据 |
| 完整更新 | PUT | `/api/v1/users/:id` | 替换整个资源 |
| 部分更新 | PATCH | `/api/v1/users/:id` | 只更新指定字段 |
| 删除 | DELETE | `/api/v1/users/:id` | 删除资源 |

**嵌套资源**:
- `GET /api/v1/users/:userId/posts` - 获取用户的文章
- `POST /api/v1/posts/:postId/comments` - 为文章创建评论

**查询参数**:
- 分页:`?page=1&limit=20`
- 筛选:`?status=published&author=123`
- 排序:`?sort=-createdAt`(-表示降序)
- 搜索:`?q=keyword`

### 3. 请求/响应格式

#### 成功响应

**单个资源**:
```json
{
  "success": true,
  "data": {
    "id": "123",
    "name": "John Doe",
    "email": "[email protected]"
  }
}
```

**资源列表**:
```json
{
  "success": true,
  "data": [
    { "id": "1", "name": "Item 1" },
    { "id": "2", "name": "Item 2" }
  ],
  "meta": {
    "page": 1,
    "limit": 20,
    "total": 100,
    "totalPages": 5
  }
}
```

#### 错误响应

```json
{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "邮箱格式不正确",
    "details": [
      {
        "field": "email",
        "message": "必须是有效的邮箱地址"
      }
    ]
  }
}
```

**错误码**:
- `VALIDATION_ERROR`: 验证错误(400)
- `UNAUTHORIZED`: 未认证(401)
- `FORBIDDEN`: 无权限(403)
- `NOT_FOUND`: 资源不存在(404)
- `CONFLICT`: 资源冲突(409,如邮箱已存在)
- `INTERNAL_ERROR`: 服务器错误(500)

### 4. 认证和授权

#### 认证方案

**JWT (推荐)**:
```
Authorization: Bearer <token>
```

**请求头**:
```
POST /api/v1/auth/login
Content-Type: application/json

{
  "email": "[email protected]",
  "password": "password123"
}
```

**响应**:
```json
{
  "success": true,
  "data": {
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
    "user": {
      "id": "123",
      "name": "John Doe",
      "email": "[email protected]"
    }
  }
}
```

#### 授权模型

**RBAC (基于角色)**:
```typescript
enum Role {
  USER = 'user',
  ADMIN = 'admin'
}

// 中间件检查
if (user.role !== Role.ADMIN) {
  throw new ForbiddenError();
}
```

### 5. API接口列表

| 模块 | 方法 | 路径 | 描述 | 认证 | 权限 |
|------|------|------|------|------|------|
| **认证** | | | | | |
| | POST | /api/v1/auth/register | 用户注册 | 否 | - |
| | POST | /api/v1/auth/login | 用户登录 | 否 | - |
| | POST | /api/v1/auth/logout | 用户登出 | 是 | - |
| | GET | /api/v1/auth/me | 获取当前用户 | 是 | - |
| **用户** | | | | | |
| | GET | /api/v1/users | 获取用户列表 | 是 | admin |
| | GET | /api/v1/users/:id | 获取用户详情 | 是 | - |
| | PATCH | /api/v1/users/:id | 更新用户信息 | 是 | self/admin |
| | DELETE | /api/v1/users/:id | 删除用户 | 是 | admin |
| **文章** | | | | | |
| | GET | /api/v1/posts | 获取文章列表 | 否 | - |
| | GET | /api/v1/posts/:id | 获取文章详情 | 否 | - |
| | POST | /api/v1/posts | 创建文章 | 是 | - |
| | PATCH | /api/v1/posts/:id | 更新文章 | 是 | author/admin |
| | DELETE | /api/v1/posts/:id | 删除文章 | 是 | author/admin |

## 输出要求

完成数据模型和API设计后,应输出以下内容(通常作为架构文档的第4-5章):

```markdown
## 4. 数据模型

### 4.1 实体关系图 (ERD)

[Mermaid ERD]

### 4.2 数据字典

#### User 表

[字段表格]

#### Post 表

[字段表格]

---

## 5. API 设计

### 5.1 API 规范

- **风格**:RESTful
- **版本**:URL 前缀 `/api/v1`
- **认证**:Bearer Token (JWT)
- **格式**:JSON

### 5.2 接口列表

[接口表格]

### 5.3 响应格式

[成功响应示例]
[错误响应示例]
```

## 关键原则

1. **规范化**:遵循数据库范式,避免冗余
2. **类型安全**:使用强类型(UUID、ENUM)
3. **RESTful**:遵循REST原则,资源导向
4. **一致性**:命名、格式、错误码保持一致
5. **文档化**:每个字段、每个接口都有清晰说明

## 常见误区

❌ **使用动词**:`/getUsers`, `/createPost`(应该用HTTP方法表示动作)
❌ **过度嵌套**:`/users/:id/posts/:id/comments/:id`(最多2层)
❌ **暴露实现**:`/api/getUserFromDatabase`(暴露内部实现)
❌ **不一致**:有的用复数有的用单数,有的驼峰有的下划线

architect/tech-research

skill/skills/architect/tech-research/SKILL.md

技术调研方法论,通过系统性调研和对比分析,为技术选型提供数据支持

Raw SKILL.md
---
name: architect/tech-research
description: 技术调研方法论,通过系统性调研和对比分析,为技术选型提供数据支持
version: 1.0.0
agent: architect
type: methodology
user-invocable: false
agent-invocable: true
dependencies:
  - shared/tech-stack-detection
triggers:
  - 开始架构设计前
  - 需要技术选型时
  - 评估新技术方案时
metadata:
  internal: true
---

# 技术调研方法论

## 适用场景

在进行架构设计和技术选型前,必须先进行系统性的技术调研,了解:
- 业界成熟的技术方案
- 各方案的优缺点和适用场景
- 开源项目的可复用性
- 潜在的技术风险

## 调研流程

### 1. 明确调研目标

基于PRD的技术需求,明确需要调研的技术领域:

**调研背景模板**:

```markdown
### 1.1 调研背景

**需求概述**:[基于 PRD 的技术需求总结]

**关键技术挑战**:
- [挑战 1]:[具体描述]
- [挑战 2]:[具体描述]
- [挑战 3]:[具体描述]

**调研目标**:
- [ ] 前端框架选型
- [ ] 后端框架选型
- [ ] 数据库选型
- [ ] 缓存方案选型
- [ ] 部署方案选型
```

### 2. 使用WebSearch进行调研

#### 搜索策略

**通用搜索模式**:
```
"{技术领域} + best practices + 2026"
"{框架名} vs {框架名} comparison 2026"
"{技术领域} + benchmark + 2026"
"best {技术领域} tools 2026"
```

**具体示例**:

**前端框架调研**:
```
"React vs Vue vs Angular comparison 2026"
"Next.js vs Remix vs Astro 2026"
"best React UI libraries 2026"
```

**后端框架调研**:
```
"Node.js frameworks comparison 2026"
"Express vs Fastify vs Hono benchmark"
"Python web frameworks 2026"
```

**数据库调研**:
```
"PostgreSQL vs MySQL vs MongoDB 2026"
"database for {use case} 2026"
"SQL vs NoSQL when to use"
```

**ORM调研**:
```
"Prisma vs TypeORM vs Drizzle comparison"
"best ORM for {language} 2026"
```

#### 搜索技巧

1. **包含年份**:确保获取最新信息
2. **对比搜索**:使用 "vs" 或 "comparison" 获取对比分析
3. **性能搜索**:使用 "benchmark" 或 "performance" 获取性能数据
4. **实践搜索**:使用 "best practices" 获取最佳实践
5. **问题搜索**:使用 "pros and cons" 或 "disadvantages" 了解缺点

### 3. 使用WebFetch深入分析

对于重要的技术方案,使用 `WebFetch` 深入分析官方文档和技术文章:

**官方文档**:
```
WebFetch("https://nextjs.org/docs", "总结 Next.js 的核心特性、适用场景和最新版本的主要变化")
WebFetch("https://www.prisma.io/docs", "提取 Prisma 的核心功能、支持的数据库和性能特点")
```

**技术对比文章**:
```
WebFetch("[对比文章URL]", "提取各方案的优缺点对比、性能数据和推荐场景")
```

**GitHub仓库**:
```
WebFetch("https://github.com/{org}/{repo}", "提取 Star 数、最近更新时间、维护状态和主要贡献者")
```

### 4. 技术方案对比

#### 对比维度

对每个技术方案,从以下维度进行评估:

| 维度 | 评估内容 |
|------|----------|
| **功能完整性** | 是否满足项目需求 |
| **性能** | 响应时间、吞吐量、资源消耗 |
| **生态系统** | 社区活跃度、插件丰富度、文档质量 |
| **学习曲线** | 团队学习成本、上手难度 |
| **成熟度** | 版本稳定性、生产案例、维护状态 |
| **扩展性** | 是否易于扩展和定制 |
| **兼容性** | 与其他技术的集成难度 |
| **成本** | 开发成本、运维成本、授权成本 |

#### 对比表格模板

**前端框架对比**:

| 方案 | 优点 | 缺点 | 适用场景 | 推荐度 |
|------|------|------|----------|--------|
| Next.js | SSR/SSG、SEO友好、全栈能力 | 学习曲线陡、打包体积大 | 内容型网站、SEO要求高 | ⭐⭐⭐⭐⭐ |
| Vite + React | 开发体验好、构建快 | 需要自己配置路由等 | SPA、快速原型 | ⭐⭐⭐⭐ |
| Remix | 数据加载优雅、Web标准 | 生态较新、案例较少 | 数据密集型应用 | ⭐⭐⭐ |

**后端框架对比**:

| 方案 | 优点 | 缺点 | 适用场景 | 推荐度 |
|------|------|------|----------|--------|
| Express | 成熟、生态丰富、灵活 | 性能一般、缺少约定 | 通用后端、快速开发 | ⭐⭐⭐⭐ |
| Fastify | 性能高、插件系统好 | 生态较Express小 | 性能要求高的API | ⭐⭐⭐⭐ |
| Hono | 极致性能、边缘计算 | 生态较新 | Serverless、边缘函数 | ⭐⭐⭐ |

**数据库对比**:

| 方案 | 类型 | 优点 | 缺点 | 适用场景 |
|------|------|------|------|----------|
| PostgreSQL | 关系型 | 功能强大、扩展性好、JSON支持 | 运维复杂度高 | 复杂查询、事务、JSONB |
| MySQL | 关系型 | 简单、普及、性能好 | 功能较PostgreSQL少 | 通用场景、读多写少 |
| MongoDB | 文档型 | 灵活、易扩展、开发快 | 事务支持弱、数据一致性 | 非结构化数据、快速迭代 |
| SQLite | 嵌入式 | 零配置、单文件、轻量 | 并发限制、功能有限 | 小型应用、原型、嵌入式 |

### 5. 开源方案评估

对于可能复用的开源项目,进行系统性评估:

| 开源项目 | 功能 | Star 数 | 最近更新 | 维护状态 | 是否采用 | 理由 |
|----------|------|---------|----------|----------|----------|------|
| [项目名] | [功能描述] | [数量] | [日期] | 活跃/停滞 | 是/否 | [理由] |

**评估标准**:
- **Star 数 > 1000**:说明有一定用户基础
- **最近更新 < 6个月**:说明项目活跃
- **Issue响应及时**:说明维护良好
- **文档完善**:说明易于使用
- **License友好**:MIT/Apache 2.0 等宽松协议

### 6. 调研结论

基于调研结果,给出明确的技术选型建议:

| 层级 | 推荐方案 | 选择理由 | 备选方案 |
|------|----------|----------|----------|
| 前端 | [方案] | [理由] | [备选] |
| 后端 | [方案] | [理由] | [备选] |
| 数据库 | [方案] | [理由] | [备选] |
| 缓存 | [方案] | [理由] | [备选] |
| 部署 | [方案] | [理由] | [备选] |

**选择理由应包含**:
- 为什么选择这个方案(优势)
- 为什么不选其他方案(劣势)
- 与项目需求的匹配度
- 团队能力的匹配度

## 输出要求

完成技术调研后,应输出以下内容(通常作为架构文档的第1章):

```markdown
## 1. 技术调研

### 1.1 调研背景

**需求概述**:[基于 PRD 的技术需求总结]

**关键技术挑战**:
- [挑战 1]
- [挑战 2]
- [挑战 3]

### 1.2 技术方案调研

#### 前端框架对比

| 方案 | 优点 | 缺点 | 适用场景 | 推荐度 |
|------|------|------|----------|--------|
| [方案1] | ... | ... | ... | ... |
| [方案2] | ... | ... | ... | ... |

#### 后端框架对比

[同上]

#### 数据库对比

[同上]

### 1.3 开源方案评估

| 开源项目 | 功能 | Star 数 | 维护状态 | 是否采用 |
|----------|------|---------|----------|----------|
| [项目1] | ... | ... | ... | ... |

### 1.4 调研结论

| 层级 | 推荐方案 | 选择理由 | 备选方案 |
|------|----------|----------|----------|
| 前端 | [方案] | [理由] | [备选] |
| 后端 | [方案] | [理由] | [备选] |
| 数据库 | [方案] | [理由] | [备选] |
```

## 关键原则

1. **真实调研**:必须真实使用 WebSearch 和 WebFetch,不能凭空编造
2. **数据支撑**:结论必须基于调研数据,不能主观臆断
3. **对比分析**:至少对比3个方案,说明为什么选择A而不是B
4. **考虑现状**:如果项目已有技术栈(通过 shared/tech-stack-detection 检测),优先考虑兼容性
5. **团队能力**:考虑团队的技术背景和学习成本

## 常见误区

❌ **不调研就选型**:直接给出技术方案,没有调研过程
❌ **只看优点**:只列优点不列缺点,缺乏客观性
❌ **追新求异**:盲目选择最新技术,忽略成熟度和风险
❌ **忽略现状**:不检测项目现有技术栈,推荐不兼容的方案
❌ **缺少备选**:只给一个方案,没有Plan B

## 调研时间建议

- **简单项目**:30分钟 - 1小时
- **中型项目**:1-2小时
- **复杂项目**:2-4小时

不要过度调研,调研的目的是支持决策,不是写论文。

backend/api-development

skill/skills/backend/api-development/SKILL.md

后端API开发方法论,包括RESTful/GraphQL设计、请求验证、错误处理和安全实现

Raw SKILL.md
---
name: backend/api-development
description: 后端API开发方法论,包括RESTful/GraphQL设计、请求验证、错误处理和安全实现
type: methodology
agent: boss-backend
metadata:
  internal: true
---

# 后端 API 开发方法论

## API 契约管理

### 契约来源

实现 API 前,**必须**阅读 `architecture.md` §5(API 设计),获取:
- API 规范(RESTful/GraphQL)
- 接口列表(方法、路径、描述、认证要求)
- 请求/响应格式约定
- 错误码规范

### 契约遵守原则

1. **严格实现**:API 端点的方法、路径、参数必须与 architecture.md §5 一致
2. **响应格式**:遵循统一的成功/错误响应结构
3. **偏差记录**:如需偏离契约,必须在输出报告中标注原因
4. **类型导出**:将请求/响应类型导出到共享文件,供前端引用

## RESTful API 设计

### 资源命名规范

| 操作 | HTTP 方法 | 路径 | 说明 |
|------|-----------|------|------|
| 列表 | GET | `/api/users` | 获取用户列表 |
| 详情 | GET | `/api/users/:id` | 获取单个用户 |
| 创建 | POST | `/api/users` | 创建新用户 |
| 更新 | PUT/PATCH | `/api/users/:id` | 更新用户 |
| 删除 | DELETE | `/api/users/:id` | 删除用户 |

### 统一响应格式

**成功响应**:
```json
{
  "success": true,
  "data": { ... },
  "message": "Operation successful"
}
```

**错误响应**:
```json
{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid input data",
    "details": [
      { "field": "email", "message": "Invalid email format" }
    ]
  }
}
```

### 分页规范

**请求参数**:
```
GET /api/users?page=1&pageSize=20&sortBy=createdAt&order=desc
```

**响应格式**:
```json
{
  "success": true,
  "data": {
    "items": [...],
    "pagination": {
      "page": 1,
      "pageSize": 20,
      "total": 100,
      "totalPages": 5
    }
  }
}
```

## 请求验证

### 输入验证层级

1. **路由层**:验证路径参数和查询参数
2. **中间件层**:验证请求体格式和必填字段
3. **Service 层**:验证业务规则

### 验证示例

```typescript
// 使用验证库(如 Zod、Joi、class-validator)
import { z } from 'zod';

const CreateUserSchema = z.object({
  name: z.string().min(1).max(100),
  email: z.string().email(),
  age: z.number().int().min(0).max(150).optional(),
});

// 在路由处理器中验证
app.post('/api/users', async (req, res) => {
  try {
    const validatedData = CreateUserSchema.parse(req.body);
    const user = await userService.create(validatedData);
    res.json({ success: true, data: user });
  } catch (error) {
    if (error instanceof z.ZodError) {
      res.status(400).json({
        success: false,
        error: {
          code: 'VALIDATION_ERROR',
          message: 'Invalid input data',
          details: error.errors,
        },
      });
    }
  }
});
```

### 常见验证规则

- **必填字段**:确保关键字段存在
- **类型检查**:字符串、数字、布尔值、日期
- **格式验证**:邮箱、URL、手机号、UUID
- **范围限制**:最小/最大长度、数值范围
- **业务规则**:唯一性、外键存在性

## 错误处理

### 错误分类

| 错误类型 | HTTP 状态码 | 错误码 | 说明 |
|----------|-------------|--------|------|
| 验证错误 | 400 | VALIDATION_ERROR | 输入数据不合法 |
| 认证错误 | 401 | UNAUTHORIZED | 未登录或 Token 无效 |
| 权限错误 | 403 | FORBIDDEN | 无权限访问资源 |
| 资源不存在 | 404 | NOT_FOUND | 请求的资源不存在 |
| 冲突错误 | 409 | CONFLICT | 资源冲突(如重复创建) |
| 服务器错误 | 500 | INTERNAL_ERROR | 服务器内部错误 |

### 统一错误处理中间件

```typescript
// errorHandler.ts
export function errorHandler(err: Error, req: Request, res: Response, next: NextFunction) {
  console.error(err);
  
  if (err instanceof ValidationError) {
    return res.status(400).json({
      success: false,
      error: {
        code: 'VALIDATION_ERROR',
        message: err.message,
        details: err.details,
      },
    });
  }
  
  if (err instanceof NotFoundError) {
    return res.status(404).json({
      success: false,
      error: {
        code: 'NOT_FOUND',
        message: err.message,
      },
    });
  }
  
  // 默认 500 错误
  res.status(500).json({
    success: false,
    error: {
      code: 'INTERNAL_ERROR',
      message: 'An unexpected error occurred',
    },
  });
}
```

## 安全实现

### 认证(Authentication)

**JWT Token 示例**:
```typescript
import jwt from 'jsonwebtoken';

// 生成 Token
export function generateToken(userId: string): string {
  return jwt.sign({ userId }, process.env.JWT_SECRET!, {
    expiresIn: '7d',
  });
}

// 验证 Token 中间件
export function authMiddleware(req: Request, res: Response, next: NextFunction) {
  const token = req.headers.authorization?.replace('Bearer ', '');
  
  if (!token) {
    return res.status(401).json({
      success: false,
      error: { code: 'UNAUTHORIZED', message: 'No token provided' },
    });
  }
  
  try {
    const decoded = jwt.verify(token, process.env.JWT_SECRET!);
    req.user = decoded;
    next();
  } catch (error) {
    res.status(401).json({
      success: false,
      error: { code: 'UNAUTHORIZED', message: 'Invalid token' },
    });
  }
}
```

### 授权(Authorization)

**基于角色的访问控制(RBAC)**:
```typescript
export function requireRole(...roles: string[]) {
  return (req: Request, res: Response, next: NextFunction) => {
    if (!req.user || !roles.includes(req.user.role)) {
      return res.status(403).json({
        success: false,
        error: { code: 'FORBIDDEN', message: 'Insufficient permissions' },
      });
    }
    next();
  };
}

// 使用
app.delete('/api/users/:id', authMiddleware, requireRole('admin'), deleteUser);
```

### 输入消毒

- **SQL 注入防护**:使用参数化查询或 ORM
- **XSS 防护**:转义用户输入,使用 Content Security Policy
- **CSRF 防护**:使用 CSRF Token
- **文件上传**:验证文件类型和大小

### 速率限制

```typescript
import rateLimit from 'express-rate-limit';

const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 分钟
  max: 100, // 最多 100 个请求
  message: 'Too many requests, please try again later',
});

app.use('/api/', limiter);
```

## 分层架构

### Controller 层

职责:处理 HTTP 请求和响应
```typescript
// controllers/userController.ts
export class UserController {
  async getUser(req: Request, res: Response) {
    try {
      const user = await userService.getById(req.params.id);
      res.json({ success: true, data: user });
    } catch (error) {
      next(error);
    }
  }
  
  async createUser(req: Request, res: Response) {
    const validatedData = CreateUserSchema.parse(req.body);
    const user = await userService.create(validatedData);
    res.status(201).json({ success: true, data: user });
  }
}
```

### Service 层

职责:业务逻辑封装
```typescript
// services/userService.ts
export class UserService {
  async getById(id: string): Promise<User> {
    const user = await userRepository.findById(id);
    if (!user) {
      throw new NotFoundError('User not found');
    }
    return user;
  }
  
  async create(data: CreateUserDto): Promise<User> {
    // 检查邮箱唯一性
    const existing = await userRepository.findByEmail(data.email);
    if (existing) {
      throw new ConflictError('Email already exists');
    }
    
    // 创建用户
    return userRepository.create(data);
  }
}
```

### Repository 层

职责:数据库操作
```typescript
// repositories/userRepository.ts
export class UserRepository {
  async findById(id: string): Promise<User | null> {
    return db.user.findUnique({ where: { id } });
  }
  
  async findByEmail(email: string): Promise<User | null> {
    return db.user.findUnique({ where: { email } });
  }
  
  async create(data: CreateUserDto): Promise<User> {
    return db.user.create({ data });
  }
}
```

## 日志记录

### 日志级别

| 级别 | 使用场景 |
|------|----------|
| ERROR | 错误和异常 |
| WARN | 警告信息 |
| INFO | 关键操作(登录、创建、删除) |
| DEBUG | 调试信息 |

### 日志示例

```typescript
import winston from 'winston';

const logger = winston.createLogger({
  level: 'info',
  format: winston.format.json(),
  transports: [
    new winston.transports.File({ filename: 'error.log', level: 'error' }),
    new winston.transports.File({ filename: 'combined.log' }),
  ],
});

// 使用
logger.info('User created', { userId: user.id, email: user.email });
logger.error('Database connection failed', { error: err.message });
```

## 性能优化

### 数据库查询优化

- 使用索引加速查询
- 避免 N+1 查询问题
- 使用连接(JOIN)代替多次查询
- 分页查询大数据集

### 缓存策略

```typescript
import Redis from 'ioredis';

const redis = new Redis();

async function getUserWithCache(id: string): Promise<User> {
  // 尝试从缓存获取
  const cached = await redis.get(`user:${id}`);
  if (cached) {
    return JSON.parse(cached);
  }
  
  // 从数据库获取
  const user = await userRepository.findById(id);
  
  // 写入缓存(5 分钟过期)
  await redis.setex(`user:${id}`, 300, JSON.stringify(user));
  
  return user;
}
```

### 连接池管理

- 配置合理的数据库连接池大小
- 及时释放连接
- 监控连接池使用情况

## 实现检查清单

实现 API 前:
- [ ] 阅读 architecture.md §5 API 设计
- [ ] 确认请求/响应格式约定
- [ ] 确认认证和授权方案
- [ ] 探索项目现有代码模式

实现 API 后:
- [ ] API 端点符合契约定义
- [ ] 实现请求验证
- [ ] 实现统一错误处理
- [ ] 添加认证和授权
- [ ] 编写单元测试(Service 层)
- [ ] 编写集成测试(API 端点)
- [ ] 编写 E2E 测试(完整流程)
- [ ] 添加日志记录
- [ ] 代码通过 Lint 检查

backend/testing-guide

skill/skills/backend/testing-guide/SKILL.md

后端测试编写指南,包括单元测试、集成测试和E2E测试的编写方法和最佳实践

Raw SKILL.md
---
name: backend/testing-guide
description: 后端测试编写指南,包括单元测试、集成测试和E2E测试的编写方法和最佳实践
type: methodology
agent: boss-backend
metadata:
  internal: true
---

# 后端测试编写指南

## 测试要求(强制)

> **职责边界**:Backend Agent 是测试的**编写者**,QA Agent 是测试的**验证者**。

### 测试金字塔

| 测试类型 | 占比 | 要求 |
|----------|------|------|
| **单元测试** | ~70% | Service 层、业务逻辑必须有测试 |
| **集成测试** | ~20% | API 端点、数据库操作测试 |
| **E2E 测试** | ~10% | **必须编写**,完整 API 流程测试 |

## 单元测试编写

### Service 层测试

```typescript
// services/userService.test.ts
import { UserService } from './userService';
import { UserRepository } from '../repositories/userRepository';

jest.mock('../repositories/userRepository');

describe('UserService', () => {
  let userService: UserService;
  let userRepository: jest.Mocked<UserRepository>;

  beforeEach(() => {
    userRepository = new UserRepository() as jest.Mocked<UserRepository>;
    userService = new UserService(userRepository);
  });

  describe('getById', () => {
    it('returns user when found', async () => {
      const mockUser = { id: '1', name: 'Alice', email: '[email protected]' };
      userRepository.findById.mockResolvedValue(mockUser);

      const result = await userService.getById('1');

      expect(result).toEqual(mockUser);
      expect(userRepository.findById).toHaveBeenCalledWith('1');
    });

    it('throws NotFoundError when user not found', async () => {
      userRepository.findById.mockResolvedValue(null);

      await expect(userService.getById('999')).rejects.toThrow('User not found');
    });
  });

  describe('create', () => {
    it('creates user with valid data', async () => {
      const createData = { name: 'Bob', email: '[email protected]' };
      const mockUser = { id: '2', ...createData };
      
      userRepository.findByEmail.mockResolvedValue(null);
      userRepository.create.mockResolvedValue(mockUser);

      const result = await userService.create(createData);

      expect(result).toEqual(mockUser);
      expect(userRepository.findByEmail).toHaveBeenCalledWith('[email protected]');
      expect(userRepository.create).toHaveBeenCalledWith(createData);
    });

    it('throws ConflictError when email already exists', async () => {
      const createData = { name: 'Bob', email: '[email protected]' };
      userRepository.findByEmail.mockResolvedValue({ id: '1', name: 'Existing', email: '[email protected]' });

      await expect(userService.create(createData)).rejects.toThrow('Email already exists');
    });
  });
});
```

### 业务逻辑测试

```typescript
// services/orderService.test.ts
describe('OrderService', () => {
  describe('calculateTotal', () => {
    it('calculates total with discount', () => {
      const items = [
        { price: 100, quantity: 2 },
        { price: 50, quantity: 1 },
      ];
      const discount = 0.1; // 10% off

      const total = orderService.calculateTotal(items, discount);

      expect(total).toBe(225); // (200 + 50) * 0.9
    });

    it('handles zero discount', () => {
      const items = [{ price: 100, quantity: 1 }];
      const total = orderService.calculateTotal(items, 0);
      expect(total).toBe(100);
    });
  });

  describe('validateOrder', () => {
    it('validates order with sufficient stock', async () => {
      const order = { productId: '1', quantity: 5 };
      productRepository.findById.mockResolvedValue({ id: '1', stock: 10 });

      const result = await orderService.validateOrder(order);

      expect(result.valid).toBe(true);
    });

    it('rejects order with insufficient stock', async () => {
      const order = { productId: '1', quantity: 15 };
      productRepository.findById.mockResolvedValue({ id: '1', stock: 10 });

      const result = await orderService.validateOrder(order);

      expect(result.valid).toBe(false);
      expect(result.error).toBe('Insufficient stock');
    });
  });
});
```

## 集成测试编写

### API 端点测试

```typescript
// controllers/userController.test.ts
import request from 'supertest';
import { app } from '../app';
import { db } from '../db';

describe('User API', () => {
  beforeEach(async () => {
    // 清理测试数据库
    await db.user.deleteMany();
  });

  afterAll(async () => {
    await db.$disconnect();
  });

  describe('POST /api/users', () => {
    it('creates a new user', async () => {
      const userData = {
        name: 'Alice',
        email: '[email protected]',
      };

      const response = await request(app)
        .post('/api/users')
        .send(userData)
        .expect(201);

      expect(response.body.success).toBe(true);
      expect(response.body.data).toMatchObject(userData);
      expect(response.body.data.id).toBeDefined();
    });

    it('returns 400 for invalid email', async () => {
      const userData = {
        name: 'Bob',
        email: 'invalid-email',
      };

      const response = await request(app)
        .post('/api/users')
        .send(userData)
        .expect(400);

      expect(response.body.success).toBe(false);
      expect(response.body.error.code).toBe('VALIDATION_ERROR');
    });

    it('returns 409 for duplicate email', async () => {
      const userData = {
        name: 'Charlie',
        email: '[email protected]',
      };

      // 创建第一个用户
      await request(app).post('/api/users').send(userData);

      // 尝试创建重复邮箱的用户
      const response = await request(app)
        .post('/api/users')
        .send(userData)
        .expect(409);

      expect(response.body.error.code).toBe('CONFLICT');
    });
  });

  describe('GET /api/users/:id', () => {
    it('returns user by id', async () => {
      // 创建测试用户
      const createResponse = await request(app)
        .post('/api/users')
        .send({ name: 'Dave', email: '[email protected]' });

      const userId = createResponse.body.data.id;

      // 获取用户
      const response = await request(app)
        .get(`/api/users/${userId}`)
        .expect(200);

      expect(response.body.data.id).toBe(userId);
      expect(response.body.data.name).toBe('Dave');
    });

    it('returns 404 for non-existent user', async () => {
      const response = await request(app)
        .get('/api/users/non-existent-id')
        .expect(404);

      expect(response.body.error.code).toBe('NOT_FOUND');
    });
  });

  describe('PUT /api/users/:id', () => {
    it('updates user', async () => {
      // 创建用户
      const createResponse = await request(app)
        .post('/api/users')
        .send({ name: 'Eve', email: '[email protected]' });

      const userId = createResponse.body.data.id;

      // 更新用户
      const response = await request(app)
        .put(`/api/users/${userId}`)
        .send({ name: 'Eve Updated' })
        .expect(200);

      expect(response.body.data.name).toBe('Eve Updated');
      expect(response.body.data.email).toBe('[email protected]');
    });
  });

  describe('DELETE /api/users/:id', () => {
    it('deletes user', async () => {
      // 创建用户
      const createResponse = await request(app)
        .post('/api/users')
        .send({ name: 'Frank', email: '[email protected]' });

      const userId = createResponse.body.data.id;

      // 删除用户
      await request(app)
        .delete(`/api/users/${userId}`)
        .expect(200);

      // 验证用户已删除
      await request(app)
        .get(`/api/users/${userId}`)
        .expect(404);
    });
  });
});
```

### 数据库操作测试

```typescript
// repositories/userRepository.test.ts
import { UserRepository } from './userRepository';
import { db } from '../db';

describe('UserRepository', () => {
  let userRepository: UserRepository;

  beforeEach(async () => {
    userRepository = new UserRepository();
    await db.user.deleteMany();
  });

  afterAll(async () => {
    await db.$disconnect();
  });

  describe('create', () => {
    it('creates user in database', async () => {
      const userData = { name: 'Alice', email: '[email protected]' };
      const user = await userRepository.create(userData);

      expect(user.id).toBeDefined();
      expect(user.name).toBe('Alice');

      // 验证数据库中存在
      const found = await db.user.findUnique({ where: { id: user.id } });
      expect(found).toBeTruthy();
    });
  });

  describe('findByEmail', () => {
    it('finds user by email', async () => {
      await userRepository.create({ name: 'Bob', email: '[email protected]' });

      const user = await userRepository.findByEmail('[email protected]');

      expect(user).toBeTruthy();
      expect(user?.name).toBe('Bob');
    });

    it('returns null for non-existent email', async () => {
      const user = await userRepository.findByEmail('[email protected]');
      expect(user).toBeNull();
    });
  });
});
```

## E2E 测试编写(必须)

### API E2E 测试必须覆盖

- ✅ 创建资源(POST)
- ✅ 读取资源(GET)
- ✅ 更新资源(PUT/PATCH)
- ✅ 删除资源(DELETE)
- ✅ 完整业务流程(如:注册→登录→操作)

### 完整 CRUD 流程测试

```typescript
// e2e/user-crud.test.ts
import request from 'supertest';
import { app } from '../app';
import { db } from '../db';

describe('User CRUD E2E', () => {
  beforeAll(async () => {
    await db.user.deleteMany();
  });

  afterAll(async () => {
    await db.$disconnect();
  });

  it('completes full user lifecycle', async () => {
    // 1. 创建用户
    const createResponse = await request(app)
      .post('/api/users')
      .send({
        name: 'John Doe',
        email: '[email protected]',
        password: 'password123',
      })
      .expect(201);

    expect(createResponse.body.success).toBe(true);
    const userId = createResponse.body.data.id;

    // 2. 读取用户
    const getResponse = await request(app)
      .get(`/api/users/${userId}`)
      .expect(200);

    expect(getResponse.body.data.name).toBe('John Doe');
    expect(getResponse.body.data.email).toBe('[email protected]');

    // 3. 更新用户
    const updateResponse = await request(app)
      .put(`/api/users/${userId}`)
      .send({ name: 'John Updated' })
      .expect(200);

    expect(updateResponse.body.data.name).toBe('John Updated');

    // 4. 验证更新
    const verifyResponse = await request(app)
      .get(`/api/users/${userId}`)
      .expect(200);

    expect(verifyResponse.body.data.name).toBe('John Updated');

    // 5. 删除用户
    await request(app)
      .delete(`/api/users/${userId}`)
      .expect(200);

    // 6. 验证删除
    await request(app)
      .get(`/api/users/${userId}`)
      .expect(404);
  });
});
```

### 认证流程 E2E 测试

```typescript
// e2e/auth-flow.test.ts
describe('Authentication Flow E2E', () => {
  it('completes registration and login flow', async () => {
    // 1. 注册
    const registerResponse = await request(app)
      .post('/api/auth/register')
      .send({
        name: 'Alice',
        email: '[email protected]',
        password: 'password123',
      })
      .expect(201);

    expect(registerResponse.body.data.token).toBeDefined();
    const token = registerResponse.body.data.token;

    // 2. 使用 Token 访问受保护资源
    const profileResponse = await request(app)
      .get('/api/auth/profile')
      .set('Authorization', `Bearer ${token}`)
      .expect(200);

    expect(profileResponse.body.data.email).toBe('[email protected]');

    // 3. 登出
    await request(app)
      .post('/api/auth/logout')
      .set('Authorization', `Bearer ${token}`)
      .expect(200);

    // 4. 登录
    const loginResponse = await request(app)
      .post('/api/auth/login')
      .send({
        email: '[email protected]',
        password: 'password123',
      })
      .expect(200);

    expect(loginResponse.body.data.token).toBeDefined();
  });

  it('rejects invalid credentials', async () => {
    await request(app)
      .post('/api/auth/login')
      .send({
        email: '[email protected]',
        password: 'wrong-example',
      })
      .expect(401);
  });
});
```

### 业务流程 E2E 测试

```typescript
// e2e/order-flow.test.ts
describe('Order Flow E2E', () => {
  let authToken: string;
  let productId: string;

  beforeAll(async () => {
    // 注册并登录
    const registerResponse = await request(app)
      .post('/api/auth/register')
      .send({ name: 'Buyer', email: '[email protected]', password: 'pass123' });
    authToken = registerResponse.body.data.token;

    // 创建测试商品
    const productResponse = await request(app)
      .post('/api/products')
      .set('Authorization', `Bearer ${authToken}`)
      .send({ name: 'Test Product', price: 100, stock: 10 });
    productId = productResponse.body.data.id;
  });

  it('completes order creation and payment flow', async () => {
    // 1. 创建订单
    const orderResponse = await request(app)
      .post('/api/orders')
      .set('Authorization', `Bearer ${authToken}`)
      .send({
        items: [{ productId, quantity: 2 }],
      })
      .expect(201);

    const orderId = orderResponse.body.data.id;
    expect(orderResponse.body.data.status).toBe('pending');
    expect(orderResponse.body.data.total).toBe(200);

    // 2. 支付订单
    const paymentResponse = await request(app)
      .post(`/api/orders/${orderId}/pay`)
      .set('Authorization', `Bearer ${authToken}`)
      .send({ paymentMethod: 'credit_card' })
      .expect(200);

    expect(paymentResponse.body.data.status).toBe('paid');

    // 3. 验证库存减少
    const productResponse = await request(app)
      .get(`/api/products/${productId}`)
      .expect(200);

    expect(productResponse.body.data.stock).toBe(8); // 10 - 2

    // 4. 获取订单历史
    const ordersResponse = await request(app)
      .get('/api/orders')
      .set('Authorization', `Bearer ${authToken}`)
      .expect(200);

    expect(ordersResponse.body.data.items).toHaveLength(1);
    expect(ordersResponse.body.data.items[0].id).toBe(orderId);
  });
});
```

## 测试最佳实践

### 测试数据库隔离

使用测试数据库或事务回滚:

```typescript
// 方案 1:使用测试数据库
beforeAll(async () => {
  process.env.DATABASE_URL = 'postgresql://localhost:5432/test_db';
  await db.$connect();
});

// 方案 2:使用事务回滚
beforeEach(async () => {
  await db.$transaction(async (tx) => {
    // 测试在事务中运行
  });
});
```

### Mock 外部服务

```typescript
// 模拟第三方 API
jest.mock('../services/paymentGateway', () => ({
  processPayment: jest.fn().mockResolvedValue({ success: true, transactionId: 'tx123' }),
}));

// 模拟邮件服务
jest.mock('../services/emailService', () => ({
  sendEmail: jest.fn().mockResolvedValue(true),
}));
```

### 测试边界条件

```typescript
describe('Boundary conditions', () => {
  it('handles empty list', async () => {
    const response = await request(app).get('/api/users').expect(200);
    expect(response.body.data.items).toEqual([]);
  });

  it('handles maximum page size', async () => {
    const response = await request(app)
      .get('/api/users?pageSize=1000')
      .expect(400);
    expect(response.body.error.message).toContain('pageSize');
  });

  it('handles invalid UUID', async () => {
    await request(app)
      .get('/api/users/invalid-uuid')
      .expect(400);
  });
});
```

### 测试并发场景

```typescript
it('handles concurrent requests', async () => {
  const requests = Array(10).fill(null).map(() =>
    request(app).post('/api/users').send({ name: 'User', email: `user${Math.random()}@example.com` })
  );

  const responses = await Promise.all(requests);

  responses.forEach(response => {
    expect(response.status).toBe(201);
  });
});
```

## 测试覆盖率要求

- 语句覆盖率:≥ 80%
- 分支覆盖率:≥ 75%
- 函数覆盖率:≥ 80%
- 行覆盖率:≥ 80%

运行覆盖率报告:
```bash
npm test -- --coverage
```

## 测试报告格式

实现完成后,在输出中包含:

**测试添加**:
| 类型 | 文件 | 描述 |
|------|------|------|
| 单元测试 | `src/services/userService.test.ts` | UserService 业务逻辑测试 |
| 集成测试 | `src/controllers/userController.test.ts` | User API 端点集成测试 |
| **E2E 测试** | `e2e/user-crud.test.ts` | 用户 CRUD 完整流程 E2E 测试 |

**测试结果**:
- 通过:42 / 失败:0
- 覆盖率:87%
- E2E 测试:✅ 已编写并通过

brainstorming

skill/skills/brainstorming/SKILL.md

|

Raw SKILL.md
---
name: brainstorming
description: |
  需求澄清 Skill。当用户只给了模糊描述时自动触发,通过业务提问把一句话翻译成完整需求,交给 Boss 流水线执行。

  Triggers: '我想做一个', '帮我做', '有个想法', 'brainstorm', '帮我规划一下', '做个XX', 'I want to build'

  Does NOT trigger:
  - 需求已经完整(包含做什么 + 给谁用 + 核心场景)
  - 纯技术问题或 bug 修复

  Output: .boss/<feature>/design-brief.md 需求设计简报
version: 3.2.0
license: MIT
user-invocable: false
metadata:
  internal: true
---

# Brainstorming — 需求澄清

你是 Boss 的前置环节。用户通常只会丢过来一句话——可能是"帮我做个 XX"或者"我想搞个 XX"。你的工作是把这句话**翻译成下游流水线能跑起来的需求**。

你不做架构设计、不选技术栈、不写代码。这些是流水线里 Architect、Tech Lead 的活。你只做一件事:**搞清楚用户到底要什么**。

## ⛔ 硬性门禁

**在需求明确之前,不启动任何实现流程。**

你的唯一产出是 `.boss/<feature>/design-brief.md`,然后交接给 Boss 流水线。

---

## 核心理念

用户不是工程师。不要问他们技术问题。问他们**业务问题**。

- 用户说"帮我做个商城" → 你要搞清楚:卖什么?给谁用?最核心的操作是什么?
- 用户说"做个管理后台" → 你要搞清楚:管理什么?谁来操作?最常用的功能是什么?
- 用户说"写个工具" → 你要搞清楚:解决什么痛点?现在怎么做的?为什么现在的方式不好?

**你的价值是把一句话变成一页纸。**

---

## Step 0:项目环境感知(仅已有项目)

如果当前工作目录下已有源代码(存在 `package.json`、`go.mod`、`pyproject.toml`、`Cargo.toml`、`src/`、`app/`、`lib/` 等标志文件或目录),先做一次快速探索,再进入提问环节。

**新项目(无源代码)跳过此步骤,直接进入提问策略。**

### 快速探索(控制在 2 分钟内完成)

**① 技术栈识别** — 按 `agents/shared/tech-detection.md` 的 Step 1(语言/平台)和 Step 2(框架)快速检测:
- 扫描根目录标志文件,识别语言和框架
- 不需要做完整的 ORM/测试/包管理器检测

**② 项目结构概览** — 扫描顶层目录结构:
- 列出 `src/`、`app/`、`pages/`、`components/`、`api/`、`lib/` 等关键目录
- 识别项目组织模式(monorepo、单体应用、微服务等)

**③ 已有功能扫描** — 快速识别项目中已实现的功能模块:
- 扫描路由文件(如 `app/` 下的目录结构、`router/` 配置)
- 扫描组件/模块目录的名称
- 读取 README.md 或 CHANGELOG.md(如有)获取功能概述
- 目标:列出 3-10 个已有功能模块的名称

### 探索产出

将探索结果整理为内部参考(不展示给用户),格式如下:

```
[内部参考 - 项目现状]
- 技术栈: Next.js + TypeScript + Tailwind CSS
- 项目结构: app/ 路由(App Router), components/ 组件库, lib/ 工具函数
- 已有功能: 用户认证、作品管理、图片上传、画布编辑器
- 代码风格: 函数式组件、中文注释、Zustand 状态管理
```

### 如何利用项目现状

探索完成后,在后续提问中:
- **跳过已知信息**:如果项目已经有用户系统,不需要再问"给谁用"
- **基于现状追问**:例如"项目已有画布编辑器,新的分镜头模式是要在编辑器里加一个模式,还是独立的新页面?"
- **关联已有功能**:例如"项目已有图片上传功能,分镜头生成的图片是复用现有上传流程,还是有不同的处理方式?"
- **尊重技术边界**:不问技术实现问题,但可以用技术现状来理解业务范围(如"项目是 Web 应用,所以你说的'分镜头生成'是在浏览器里操作的对吧?")

---

## 提问策略

一次只问一个问题。优先给选项。别问用户不该回答的问题。

### 必须澄清的 5 个问题

按这个顺序来,已知的跳过:

**① 做什么(What)**
> 用一句话描述:这个东西做好了,用户拿它干嘛?

**② 给谁用(Who)**
> 最主要的使用者是谁?他们的特点是什么?

**③ 核心场景(How)**
> 用户打开这个东西后,最常做的 3 件事是什么?

**④ 边界(Scope)**
> 哪些功能是第一版必须有的?哪些可以以后再做?

**⑤ 成功标准(Done)**
> 怎么判断这个东西"做好了"?

### 可选澄清(按需问)

- 有没有参考产品?("类似 XX 但是 YY")
- 有没有现有代码或系统要集成?(已有项目中已通过探索获取,可跳过或确认)
- 有没有硬性约束?(必须用某个平台、必须某个时间完成等)
- 新功能与已有功能的关系?(仅已有项目:是扩展现有模块,还是新增独立模块?)

### 降级策略:应对模糊回答

当用户回复"不知道"、"你决定"、"随便"、"都行"等模糊答案时,**不要反复追问同一个问题**。采用以下降级策略:

**原则:提供合理默认值,标记为假设,继续推进。**

| 用户回复 | 降级策略 | 示例 |
|----------|----------|------|
| "不知道给谁用" | 假设最常见场景 | `[假设] 目标用户: 普通个人用户` |
| "功能你看着办" | 基于产品类型推导 MVP | `[假设] MVP 功能: 基于同类产品的标准功能集` |
| "随便" / "都行" | 选择最保守选项 | `[假设] 采用选项 A(最简方案)` |
| "不确定边界" | 按 MVP 原则最小化 | `[假设] 第一版仅包含核心 CRUD,其余标记为 v2` |
| "怎么判断做好了不知道" | 推导功能性标准 | `[假设] 成功标准: 核心场景可走通,无阻塞性 Bug` |

**降级后的处理流程:**

1. 将默认值标记为 `[假设]`,写入设计简报
2. 告知用户:"这个问题我先按 XX 假设处理,后续可以调整"
3. 继续下一个问题,不在同一问题上纠缠
4. 在最终确认环节,**高亮所有假设项**,让用户一次性审阅

**收敛策略:**

- 前 3 个必答问题(What/Who/How)最多各追问 1 次,第 2 次仍模糊则降级
- 后 2 个问题(Scope/Done)允许完全降级,用合理默认值替代
- 如果 5 个问题中有 3 个以上被降级,在设计简报开头加警告:
  > ⚠️ 本简报包含较多假设(X/5 个问题使用了默认值)。建议在开发前与用户确认关键假设。

### 提问格式

```
这个产品最主要给谁用?

A) 👤 给自己用的个人工具
B) 👥 给团队内部用的效率工具
C) 🌍 给外部用户用的产品
D) 🤖 没有人类用户,是服务/自动化

或者直接说:
```

---

## 翻译过程

用户的原话通常有三类问题:

**1. 太模糊** — "做个网站"
→ 需要追问:什么类型的网站?做什么用的?

**2. 太发散** — "做个 AI 社交电商短视频平台"
→ 需要收敛:第一版只做哪一个核心功能?

**3. 夹杂实现细节** — "用 React + Supabase 做个..."
→ 需要剥离:先搞清楚需求,技术栈让 Architect 决定。记下用户偏好,但不在这个阶段讨论。

---

## 产出:设计简报

所有问题澄清后,写一份简报到 `.boss/<feature>/design-brief.md`:

```markdown
# 设计简报: [功能名称]

## 一句话描述
[这个东西是什么,给谁用,解决什么问题]

## 目标用户
- 主要用户: [...]
- 用户特点: [...]

## 核心场景
1. [用户打开 → 做什么 → 得到什么结果]
2. [...]
3. [...]

## 功能范围
### 第一版必须有
- [功能 1]
- [功能 2]
- [功能 3]

### 明确不做(留给后续版本)
- [排除项 1]
- [排除项 2]

## 成功标准
- [怎么判断做好了]

## 用户原话
> [保留用户最初的描述原文,供下游 Agent 参考]

## 项目现状(仅已有项目,新项目删除此 section)
- 技术栈: [语言、框架、关键依赖]
- 项目结构: [目录组织方式]
- 已有功能: [已实现的功能模块列表]
- 新功能定位: [扩展已有模块 / 新增独立模块 / 替换现有功能]

## 补充信息
- 参考产品: [如有]
- 用户偏好: [技术偏好、风格偏好等,如有]
- 约束: [如有]
```

写完后展示给用户确认:

```
以上是我理解的需求,请确认:

✅ 没问题,开始开发
✏️ 需要修改(请说明哪里不对)
```

确认后自动衔接 Boss 流水线。

---

## 检查清单

- [ ] 已有项目?已完成快速探索(技术栈 + 项目结构 + 已有功能)
- [ ] 搞清楚了这个东西是做什么的
- [ ] 搞清楚了给谁用
- [ ] 搞清楚了核心使用场景(至少 3 个)
- [ ] 划清了第一版的功能边界
- [ ] 明确了成功标准
- [ ] 保留了用户原话
- [ ] 已有项目?设计简报包含"项目现状" section
- [ ] 设计简报已写入 `.boss/<feature>/design-brief.md`
- [ ] 用户已确认需求理解正确
- [ ] ⛔ 没有讨论任何技术实现细节

devops/changelog-generation

skill/skills/devops/changelog-generation/SKILL.md

自动生成 CHANGELOG,基于 git 提交历史和 pipeline 产物信息,遵循 Conventional Commits 和 Keep a Changelog 规范

Raw SKILL.md
---
name: devops/changelog-generation
description: 自动生成 CHANGELOG,基于 git 提交历史和 pipeline 产物信息,遵循 Conventional Commits 和 Keep a Changelog 规范
version: 1.0.0
agent: devops
type: workflow
user-invocable: false
agent-invocable: true
dependencies:
  - devops/deployment-process
triggers:
  - 部署成功完成后
  - 需要生成版本变更日志时
  - 发布新版本时
metadata:
  internal: true
---

# CHANGELOG 自动生成

## 适用场景

在部署成功完成后自动生成或追加 CHANGELOG,记录本次发布的所有变更。适用于:
- 部署完成后的发布记录
- 版本发布前的变更汇总
- 对外发布说明的自动生成

## 核心方法

### 步骤 1:信息收集

1. **Git 历史解析**:
   ```bash
   # 获取从上次 tag 到 HEAD 的所有提交
   git log $(git describe --tags --abbrev=0 2>/dev/null || git rev-list --max-parents=0 HEAD)..HEAD --pretty=format:"%H|%s|%an|%ai"
   ```
   - 如果没有 tag,取最近 50 条提交
   - 解析 Conventional Commits 格式:`type(scope): description`

2. **Pipeline 产物读取**:
   - `.boss/<feature>/prd.md` → 功能描述和用户价值
   - `.boss/<feature>/deploy-report.md` → 部署环境和版本信息
   - `.boss/<feature>/tasks.md` → 完成的任务列表

3. **版本号确定**:
   - 优先使用 `package.json` 中的 version
   - 其次使用最新 git tag
   - 如无法确定,使用日期格式 `YYYY.MM.DD`

### 步骤 2:变更分类

按 Conventional Commits 规范分类:

| 类型 | CHANGELOG 分类 | 说明 |
|------|---------------|------|
| `feat` | **Added** | 新增功能 |
| `fix` | **Fixed** | 修复问题 |
| `perf` | **Performance** | 性能优化 |
| `refactor` | **Changed** | 重构(非功能变更) |
| `docs` | **Documentation** | 文档更新 |
| `style` | _(不记录)_ | 代码格式 |
| `test` | _(不记录)_ | 测试相关 |
| `chore` | _(不记录)_ | 构建/工具变更 |
| `BREAKING CHANGE` | **⚠️ Breaking Changes** | 破坏性变更(始终置顶) |

对于非 Conventional Commits 格式的提交:
- 根据关键词推断分类(add/new → Added, fix/bug → Fixed, update/change → Changed)
- 无法分类的归入 **Changed**

### 步骤 3:内容生成

#### 格式规范(Keep a Changelog)

```markdown
## [版本号] - YYYY-MM-DD

### ⚠️ Breaking Changes
- 破坏性变更描述 ([commit-hash])

### Added
- 新功能描述(来自 PRD 的用户价值说明) ([commit-hash])

### Changed
- 变更描述 ([commit-hash])

### Fixed
- 修复描述 ([commit-hash])

### Performance
- 优化描述 ([commit-hash])
```

#### 生成规则

1. 每条记录包含:清晰描述 + commit short hash 引用
2. 如有 PRD,用 PRD 中的功能描述替代 commit message(更面向用户)
3. Breaking Changes 始终置顶并用 ⚠️ 标记
4. 同一 scope 的多条提交合并为一条记录
5. 最多展示 20 条变更,超出部分汇总为 "及其他 N 项更新"

### 步骤 4:输出写入

**两种输出模式:**

1. **产物模式**(默认):写入 `.boss/<feature>/changelog.md`
2. **追加模式**:如项目根目录已有 `CHANGELOG.md`,将新版本内容追加到文件顶部(在 `# Changelog` 标题之后)

**追加逻辑:**
```
读取现有 CHANGELOG.md
→ 找到第一个 ## [version] 行
→ 在其前面插入新版本内容
→ 写回文件
```

如果项目无 `CHANGELOG.md`,则创建包含标准头部的新文件:
```markdown
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/).

## [版本号] - 日期
...
```

## 输出要求

1. 产物文件 `.boss/<feature>/changelog.md` 必须生成
2. 如项目根存在 `CHANGELOG.md`,同步更新
3. 变更内容必须准确反映实际代码变更
4. 面向用户的描述优先于面向开发者的 commit message

devops/deployment-process

skill/skills/devops/deployment-process/SKILL.md

部署流程和CI/CD配置,确保安全可靠的部署

Raw SKILL.md
---
name: devops/deployment-process
description: 部署流程和CI/CD配置,确保安全可靠的部署
version: 1.0.0
agent: devops
type: methodology
user-invocable: false
agent-invocable: true
dependencies:
  - shared/tech-stack-detection
triggers:
  - 需要配置部署流程时
  - 需要设置CI/CD时
metadata:
  internal: true
---

# 部署流程与CI/CD

## 部署策略

| 策略 | 说明 | 适用场景 |
|------|------|----------|
| 蓝绿部署 | 两套环境切换 | 需要快速回滚 |
| 滚动部署 | 逐步替换实例 | 零停机部署 |
| 金丝雀部署 | 小流量验证 | 风险较高的更新 |

## CI/CD流程

```
代码提交 → 自动构建 → 自动测试 → 部署到测试环境 → 部署到生产环境
```

### GitHub Actions示例

```yaml
name: CI/CD
on: [push]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Install
        run: npm install
      - name: Test
        run: npm test
      - name: Build
        run: npm run build
      - name: Deploy
        run: npm run deploy
```

## 环境配置

| 环境 | 用途 | 数据 |
|------|------|------|
| local | 本地开发 | 测试数据 |
| dev | 开发测试 | 测试数据 |
| staging | 预发布 | 生产数据副本 |
| prod | 生产环境 | 真实数据 |

devops/monitoring-alerting

skill/skills/devops/monitoring-alerting/SKILL.md

监控告警配置,确保系统稳定运行

Raw SKILL.md
---
name: devops/monitoring-alerting
description: 监控告警配置,确保系统稳定运行
version: 1.0.0
agent: devops
type: guideline
user-invocable: false
agent-invocable: true
dependencies: []
triggers:
  - 需要配置监控时
  - 需要设置告警时
metadata:
  internal: true
---

# 监控告警

## 监控指标

| 类型 | 指标 | 阈值 |
|------|------|------|
| 应用 | 错误率 | < 1% |
| 应用 | 响应时间 | P99 < 500ms |
| 系统 | CPU使用率 | < 80% |
| 系统 | 内存使用率 | < 85% |
| 系统 | 磁盘使用率 | < 90% |

## 告警规则

| 级别 | 条件 | 通知方式 |
|------|------|----------|
| P0 | 服务不可用 | 电话 + 短信 + 邮件 |
| P1 | 错误率 > 5% | 短信 + 邮件 |
| P2 | 响应时间 > 1s | 邮件 |
| P3 | 资源使用率 > 80% | 邮件 |

## 日志管理

- 集中式日志收集
- 日志分级(ERROR, WARN, INFO, DEBUG)
- 日志保留策略(30天)
- 敏感信息脱敏

frontend/component-development

skill/skills/frontend/component-development/SKILL.md

前端组件开发方法论,包括组件设计原则、状态管理、样式实现和性能优化

Raw SKILL.md
---
name: frontend/component-development
description: 前端组件开发方法论,包括组件设计原则、状态管理、样式实现和性能优化
type: methodology
agent: boss-frontend
metadata:
  internal: true
---

# 前端组件开发方法论

## 组件设计原则

### 单一职责原则
- 每个组件只负责一个功能模块
- 复杂组件拆分为多个子组件
- 容器组件(逻辑)与展示组件(UI)分离

### 可复用性设计
- 通过 Props/属性实现组件配置化
- 避免硬编码业务逻辑
- 提供合理的默认值
- 支持插槽/children 扩展

### 组件命名规范
- 使用 PascalCase 命名组件
- 名称应清晰描述组件功能
- 避免过于通用的名称(如 Item、Component)
- 文件名与组件名保持一致

## 状态管理策略

### 状态分类
| 状态类型 | 管理方式 | 适用场景 |
|----------|----------|----------|
| 本地状态 | useState/ref | 组件内部状态(表单输入、展开/收起) |
| 共享状态 | Context/Store | 跨组件共享(用户信息、主题) |
| 服务端状态 | Query库/SWR | API 数据缓存和同步 |
| URL 状态 | Router | 页面参数、筛选条件 |

### 状态提升原则
- 状态放在最近的公共父组件
- 避免过度提升导致不必要的重渲染
- 使用 Context 避免 Props 层层传递

### 副作用管理
- 使用框架的副作用 Hook(useEffect/onMounted)
- 清理订阅和定时器
- 依赖数组准确声明
- 避免在渲染函数中执行副作用

## 样式实现规范

### UI 规范优先级
```
ui-design.json > ui-spec.md > 项目现有样式 > 框架默认值
```

### ui-design.json 集成
当 `.boss/<feature>/ui-design.json` 存在时:
1. **读取 tokens**:映射为 CSS 变量或主题对象
   ```typescript
   // 示例:从 tokens 生成 CSS 变量
   const colors = uiDesign.tokens.colors;
   // --color-primary: #007AFF
   ```

2. **解析 pages 和 frames**:推导页面结构和布局
   - 从 `pages[].frames[]` 提取页面组件层级
   - 从 `frames[].layout` 获取布局约束(宽度、间距、对齐)

3. **实现 prototype.links**:推导导航和交互
   - 按钮点击跳转
   - 表单提交流程
   - 模态框打开/关闭

4. **复用 components**:提取可复用组件
   - 从 `components[]` 识别通用组件(Button、Input、Card)
   - 实现为独立组件文件

### 样式编写原则
- 使用项目约定的样式方案(CSS Modules/Tailwind/CSS-in-JS)
- 响应式设计:移动端优先或桌面端优先(按项目约定)
- 使用设计系统的间距、颜色、字体变量
- 避免魔法数字,使用语义化变量

### 无障碍实现
- 添加正确的 ARIA 属性(role、aria-label、aria-describedby)
- 确保键盘导航可用(tabindex、focus 样式)
- 表单元素关联 label
- 图片添加 alt 文本

## 性能优化技巧

### 渲染优化
- 使用 Memo/shouldComponentUpdate 避免不必要的重渲染
- 列表渲染使用稳定的 key
- 虚拟滚动处理长列表
- 避免在渲染函数中创建新对象/函数

### 代码分割
- 路由级别的懒加载
- 大型组件按需加载
- 第三方库按需引入

### 资源优化
- 图片懒加载和响应式图片
- 使用 WebP 等现代图片格式
- SVG 图标内联或雪碧图

## API 契约管理

### 契约来源
实现前端 API 调用前,必须阅读:
1. **architecture.md §5(API 设计)**:获取端点列表、请求/响应格式
2. **后端共享类型**(如有):复用类型定义

### API 调用层设计
```typescript
// services/api/users.ts
export const userApi = {
  async getUser(id: string): Promise<User> {
    const response = await fetch(`/api/users/${id}`);
    return response.json();
  },
  
  async createUser(data: CreateUserRequest): Promise<User> {
    const response = await fetch('/api/users', {
      method: 'POST',
      body: JSON.stringify(data),
    });
    return response.json();
  },
};
```

### 错误处理
- 统一错误处理:按 architecture.md 定义的错误格式
- 用户友好的错误提示
- 网络错误重试机制
- 加载和错误状态展示

### Mock 策略
后端未就绪时,基于 architecture.md §5 创建 Mock:
```typescript
// services/api/users.mock.ts
export const mockUserApi = {
  async getUser(id: string): Promise<User> {
    return { id, name: 'Mock User', email: '[email protected]' };
  },
};
```

## 组件测试策略

### 测试金字塔
| 测试类型 | 占比 | 工具示例 |
|----------|------|----------|
| 单元测试 | 70% | Jest + Testing Library |
| 集成测试 | 20% | Testing Library |
| E2E 测试 | 10% | Playwright/Cypress |

### 单元测试覆盖
- 组件渲染:关键元素是否存在
- Props 变化:不同 Props 下的渲染结果
- 用户交互:点击、输入、表单提交
- Hooks 逻辑:自定义 Hook 的状态变化

### 集成测试覆盖
- 组件间交互:父子组件通信
- 状态管理:全局状态变化对组件的影响
- 路由导航:页面跳转和参数传递

### E2E 测试覆盖(必须)
- 创建流程:填写表单 → 提交 → 验证结果
- 编辑流程:打开编辑 → 修改 → 保存 → 验证
- 删除流程:点击删除 → 确认 → 验证消失
- 列表展示:加载列表 → 筛选 → 分页
- 核心业务流程:完整用户路径

## 实现检查清单

实现组件前:
- [ ] 阅读 ui-design.json(如有)和 ui-spec.md
- [ ] 阅读 architecture.md §5 API 设计
- [ ] 探索项目现有组件模式和样式方案
- [ ] 确认状态管理方案(本地/共享/服务端)

实现组件后:
- [ ] 组件符合单一职责原则
- [ ] 添加必要的 Props 类型定义
- [ ] 实现响应式布局
- [ ] 添加无障碍属性
- [ ] 编写单元测试(70%)
- [ ] 编写集成测试(20%)
- [ ] 编写 E2E 测试(10%,必须)
- [ ] 测试覆盖率达标
- [ ] 代码通过 Lint 检查

frontend/testing-guide

skill/skills/frontend/testing-guide/SKILL.md

前端测试编写指南,包括单元测试、集成测试和E2E测试的编写方法和最佳实践

Raw SKILL.md
---
name: frontend/testing-guide
description: 前端测试编写指南,包括单元测试、集成测试和E2E测试的编写方法和最佳实践
type: methodology
agent: boss-frontend
metadata:
  internal: true
---

# 前端测试编写指南

## 测试要求(强制)

> **职责边界**:Frontend Agent 是测试的**编写者**,QA Agent 是测试的**验证者**。

### 测试金字塔

| 测试类型 | 占比 | 要求 |
|----------|------|------|
| **单元测试** | ~70% | 每个组件/Hook 必须有测试 |
| **集成测试** | ~20% | 组件交互、状态管理测试 |
| **E2E 测试** | ~10% | **必须编写**,覆盖用户流程 |

## 单元测试编写

### 组件渲染测试

```typescript
// Button.test.tsx
import { render, screen } from '@testing-library/react';
import { Button } from './Button';

describe('Button', () => {
  it('renders with text', () => {
    render(<Button>Click me</Button>);
    expect(screen.getByText('Click me')).toBeInTheDocument();
  });

  it('calls onClick when clicked', () => {
    const handleClick = jest.fn();
    render(<Button onClick={handleClick}>Click</Button>);
    screen.getByText('Click').click();
    expect(handleClick).toHaveBeenCalledTimes(1);
  });

  it('is disabled when disabled prop is true', () => {
    render(<Button disabled>Click</Button>);
    expect(screen.getByText('Click')).toBeDisabled();
  });
});
```

### Hook 测试

```typescript
// useCounter.test.ts
import { renderHook, act } from '@testing-library/react';
import { useCounter } from './useCounter';

describe('useCounter', () => {
  it('initializes with default value', () => {
    const { result } = renderHook(() => useCounter());
    expect(result.current.count).toBe(0);
  });

  it('increments count', () => {
    const { result } = renderHook(() => useCounter());
    act(() => {
      result.current.increment();
    });
    expect(result.current.count).toBe(1);
  });
});
```

### 表单验证测试

```typescript
// LoginForm.test.tsx
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { LoginForm } from './LoginForm';

describe('LoginForm', () => {
  it('shows validation error for invalid email', async () => {
    render(<LoginForm />);
    const emailInput = screen.getByLabelText('Email');
    
    await userEvent.type(emailInput, 'invalid-email');
    await userEvent.tab(); // Trigger blur
    
    await waitFor(() => {
      expect(screen.getByText('Invalid email format')).toBeInTheDocument();
    });
  });

  it('submits form with valid data', async () => {
    const onSubmit = jest.fn();
    render(<LoginForm onSubmit={onSubmit} />);
    
    await userEvent.type(screen.getByLabelText('Email'), '[email protected]');
    await userEvent.type(screen.getByLabelText('Password'), 'password123');
    await userEvent.click(screen.getByRole('button', { name: 'Login' }));
    
    await waitFor(() => {
      expect(onSubmit).toHaveBeenCalledWith({
        email: '[email protected]',
        password: 'password123',
      });
    });
  });
});
```

## 集成测试编写

### 组件交互测试

```typescript
// UserList.test.tsx
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { UserList } from './UserList';
import { UserProvider } from './UserContext';

describe('UserList integration', () => {
  it('adds new user to list', async () => {
    render(
      <UserProvider>
        <UserList />
      </UserProvider>
    );
    
    // 打开添加用户表单
    await userEvent.click(screen.getByText('Add User'));
    
    // 填写表单
    await userEvent.type(screen.getByLabelText('Name'), 'John Doe');
    await userEvent.type(screen.getByLabelText('Email'), '[email protected]');
    
    // 提交
    await userEvent.click(screen.getByRole('button', { name: 'Submit' }));
    
    // 验证用户出现在列表中
    await waitFor(() => {
      expect(screen.getByText('John Doe')).toBeInTheDocument();
      expect(screen.getByText('[email protected]')).toBeInTheDocument();
    });
  });
});
```

### 状态管理测试

```typescript
// store.test.ts
import { renderHook, act } from '@testing-library/react';
import { useStore } from './store';

describe('Store integration', () => {
  it('updates user state across components', () => {
    const { result } = renderHook(() => useStore());
    
    act(() => {
      result.current.setUser({ id: '1', name: 'Alice' });
    });
    
    expect(result.current.user).toEqual({ id: '1', name: 'Alice' });
    
    act(() => {
      result.current.updateUserName('Bob');
    });
    
    expect(result.current.user?.name).toBe('Bob');
  });
});
```

## E2E 测试编写(必须)

> **完整 Playwright 方法论**:详见 `Skill(skill: "qa/e2e-playwright")`,包含项目初始化、Page Object Model、认证复用、API Mock、视觉回归、多浏览器测试、CI 集成和调试技巧。

### E2E 测试必须覆盖

- ✅ 创建流程(如:添加数据)
- ✅ 编辑流程(如:修改数据)
- ✅ 删除流程(如:删除数据)
- ✅ 列表展示(如:查看列表)
- ✅ 核心业务流程

### Playwright 示例(Page Object Model)

```typescript
// e2e/pages/user-list.page.ts
import { type Page, type Locator } from '@playwright/test';

export class UserListPage {
  private readonly addButton: Locator;
  private readonly table: Locator;

  constructor(private readonly page: Page) {
    this.addButton = page.getByRole('button', { name: '添加用户' });
    this.table = page.getByRole('table');
  }

  async goto() { await this.page.goto('/users'); }
  async clickAddUser() { await this.addButton.click(); }
  getTable() { return this.table; }

  async editUser(name: string) {
    await this.page.getByRole('row', { name }).getByRole('button', { name: '编辑' }).click();
  }
  async deleteUser(name: string) {
    await this.page.getByRole('row', { name }).getByRole('button', { name: '删除' }).click();
  }
  async confirmDelete() {
    await this.page.getByRole('button', { name: '确认' }).click();
  }
}
```

```typescript
// e2e/specs/crud/user-management.spec.ts
import { test, expect } from '@playwright/test';
import { UserListPage } from '../../pages/user-list.page';

test.describe('用户管理 CRUD', () => {
  let userList: UserListPage;

  test.beforeEach(async ({ page }) => {
    userList = new UserListPage(page);
    await userList.goto();
  });

  test('创建 → 编辑 → 删除完整流程', async ({ page }) => {
    // 创建
    await userList.clickAddUser();
    await page.getByLabel('姓名').fill('测试用户');
    await page.getByLabel('邮箱').fill('[email protected]');
    await page.getByRole('button', { name: '提交' }).click();
    await expect(page.getByText('测试用户')).toBeVisible();

    // 编辑
    await userList.editUser('测试用户');
    await page.getByLabel('姓名').fill('修改后的用户');
    await page.getByRole('button', { name: '提交' }).click();
    await expect(page.getByText('修改后的用户')).toBeVisible();

    // 删除
    await userList.deleteUser('修改后的用户');
    await userList.confirmDelete();
    await expect(page.getByText('修改后的用户')).not.toBeVisible();
  });

  test('列表分页展示', async ({ page }) => {
    await expect(userList.getTable()).toBeVisible();
    await page.getByRole('button', { name: 'Next' }).click();
    await expect(page).toHaveURL(/page=2/);
  });
});
```

### 定位器优先级

| 优先级 | 方法 | 说明 |
|--------|------|------|
| 1 | `getByRole` | 无障碍语义,最稳定 |
| 2 | `getByLabel` | 表单元素首选 |
| 3 | `getByText` | 静态文本 |
| 4 | `getByTestId` | 无语义标记时兜底 |
| 5 | CSS/XPath | **尽量避免** |

## 测试最佳实践

### 测试命名
- 使用描述性的测试名称
- 格式:`it('should [expected behavior] when [condition]')`
- 示例:`it('should show error message when email is invalid')`

### 测试隔离
- 每个测试独立运行,不依赖其他测试
- 使用 beforeEach 设置初始状态
- 使用 afterEach 清理副作用

### Mock 策略
- Mock 外部依赖(API、第三方库)
- 不要 Mock 被测试的代码
- 使用 MSW(Mock Service Worker)Mock API

```typescript
// mocks/handlers.ts
import { rest } from 'msw';

export const handlers = [
  rest.get('/api/users', (req, res, ctx) => {
    return res(
      ctx.json([
        { id: '1', name: 'Alice' },
        { id: '2', name: 'Bob' },
      ])
    );
  }),
];
```

### 边界条件测试
- 空数据:列表为空时的展示
- 错误状态:API 失败时的处理
- 加载状态:数据加载中的展示
- 极限值:最大/最小输入值

### 无障碍测试
```typescript
it('is accessible', async () => {
  const { container } = render(<Button>Click</Button>);
  const results = await axe(container);
  expect(results).toHaveNoViolations();
});
```

## 测试覆盖率要求

- 语句覆盖率:≥ 80%
- 分支覆盖率:≥ 75%
- 函数覆盖率:≥ 80%
- 行覆盖率:≥ 80%

运行覆盖率报告:
```bash
npm test -- --coverage
```

## 测试报告格式

实现完成后,在输出中包含:

**测试添加**:
| 类型 | 文件 | 描述 |
|------|------|------|
| 单元测试 | `src/components/Button.test.tsx` | Button 组件渲染和交互测试 |
| 集成测试 | `src/features/users/UserList.test.tsx` | 用户列表增删改查集成测试 |
| **E2E 测试** | `e2e/user-management.spec.ts` | 用户管理完整流程 E2E 测试 |

**测试结果**:
- 通过:25 / 失败:0
- 覆盖率:85%
- E2E 测试:✅ 已编写并通过

pm/competitive-analysis

skill/skills/pm/competitive-analysis/SKILL.md

竞品调研和分析方法,通过系统性分析竞品的功能、体验和策略,发现差异化机会

Raw SKILL.md
---
name: pm/competitive-analysis
description: 竞品调研和分析方法,通过系统性分析竞品的功能、体验和策略,发现差异化机会
version: 1.0.0
agent: pm
type: methodology
user-invocable: false
agent-invocable: true
dependencies: []
triggers:
  - 需要了解市场竞争格局时
  - 寻找产品差异化机会时
  - 验证需求假设时
metadata:
  internal: true
---

# 竞品调研与分析方法论

## 适用场景

在产品设计前或迭代时,需要了解市场上已有的解决方案,学习竞品的优点,发现竞品的不足,找到差异化机会。

## 核心方法

### 1. 竞品识别

**直接竞品**:解决相同问题、服务相同用户的产品
**间接竞品**:解决相似问题或服务相似用户的产品
**潜在竞品**:未来可能进入该领域的产品

**识别方法**:
- 使用 `WebSearch` 搜索关键词:"{功能} + 工具/软件/平台"
- 搜索 "best {功能} tools 2026"
- 搜索 "{功能} alternatives"
- 查看行业报告和评测文章

### 2. 竞品分析框架

对每个竞品,从以下5个维度进行分析:

#### 2.1 功能维度

| 分析点 | 问题 |
|--------|------|
| 核心功能 | 主要解决什么问题? |
| 功能广度 | 覆盖了哪些场景? |
| 功能深度 | 每个功能做到什么程度? |
| 功能缺失 | 用户期望但没有的功能? |

#### 2.2 体验维度

| 分析点 | 问题 |
|--------|------|
| 易用性 | 新用户能快速上手吗? |
| 流畅度 | 完成任务的步骤多吗? |
| 视觉设计 | 界面美观吗?符合用户审美吗? |
| 交互设计 | 交互符合直觉吗?有惊喜吗? |
| 性能表现 | 加载快吗?响应及时吗? |

#### 2.3 用户维度

| 分析点 | 问题 |
|--------|------|
| 目标用户 | 主要服务哪类用户? |
| 用户评价 | 用户喜欢什么?抱怨什么? |
| 用户规模 | 有多少用户?增长如何? |
| 用户粘性 | 用户活跃度如何?留存如何? |

#### 2.4 商业维度

| 分析点 | 问题 |
|--------|------|
| 商业模式 | 如何赚钱? |
| 定价策略 | 价格如何?用户接受度如何? |
| 市场定位 | 高端还是大众? |
| 竞争优势 | 核心壁垒是什么? |

#### 2.5 技术维度

| 分析点 | 问题 |
|--------|------|
| 技术架构 | 使用什么技术栈? |
| 技术创新 | 有技术上的创新吗? |
| 技术限制 | 技术上有什么局限? |

### 3. 竞品对比分析

使用 `WebFetch` 深入分析竞品后,整理为对比表格:

| 竞品 | 核心功能 | 用户体验亮点 | 用户痛点 | 我们的机会 |
|------|----------|--------------|----------|------------|
| [竞品 1] | [功能] | [亮点] | [痛点] | [机会] |
| [竞品 2] | [功能] | [亮点] | [痛点] | [机会] |
| [竞品 3] | [功能] | [亮点] | [痛点] | [机会] |

**关键要点**:
- **核心功能**:简洁描述,不超过3个
- **用户体验亮点**:值得学习的地方
- **用户痛点**:从用户评价中提取真实痛点
- **我们的机会**:基于痛点,我们可以如何做得更好

### 4. 差异化策略

基于竞品分析,制定差异化策略:

| 维度 | 竞品做法 | 我们的做法 | 差异化价值 |
|------|----------|------------|------------|
| [维度 1] | [做法] | [做法] | [价值] |
| [维度 2] | [做法] | [做法] | [价值] |

**差异化维度示例**:
- **功能差异**:提供竞品没有的功能
- **体验差异**:同样的功能,更好的体验
- **定位差异**:服务不同的用户群体
- **价格差异**:不同的定价策略
- **技术差异**:使用更先进的技术

## 调研工具使用

### WebSearch 使用技巧

**搜索竞品**:
```
"{功能} tools"
"best {功能} software 2026"
"{竞品名} alternatives"
"{竞品名} vs {竞品名}"
```

**搜索用户评价**:
```
"{竞品名} review"
"{竞品名} pros and cons"
"{竞品名} reddit" (Reddit上的真实讨论)
```

**搜索行业趋势**:
```
"{行业} trends 2026"
"{行业} market report"
```

### WebFetch 使用技巧

**深度分析竞品**:
1. 访问竞品官网,了解产品定位和核心功能
2. 访问竞品定价页面,了解商业模式
3. 访问用户评价网站(如 G2, Capterra),了解用户反馈
4. 访问竞品博客,了解产品演进方向

**提示词示例**:
```
"总结这个产品的核心功能、目标用户和主要优势"
"提取用户评价中的主要痛点和亮点"
"分析这个产品的差异化策略"
```

## 输出要求

完成竞品调研后,应输出以下内容(通常作为PRD的第3章):

### 3. 竞品调研

#### 3.1 竞品分析

| 竞品 | 核心功能 | 用户体验亮点 | 用户痛点 | 我们的机会 |
|------|----------|--------------|----------|------------|
| [竞品 1] | [功能] | [亮点] | [痛点] | [机会] |
| [竞品 2] | [功能] | [亮点] | [痛点] | [机会] |
| [竞品 3] | [功能] | [亮点] | [痛点] | [机会] |

#### 3.2 差异化策略

| 维度 | 竞品做法 | 我们的做法 | 差异化价值 |
|------|----------|------------|------------|
| [维度 1] | [做法] | [做法] | [价值] |
| [维度 2] | [做法] | [做法] | [价值] |

#### 3.3 市场洞察

- **市场空白**:[竞品都没做好的地方]
- **用户痛点**:[用户普遍抱怨的问题]
- **趋势机会**:[行业发展趋势带来的机会]

## 关键原则

1. **不只看功能,更看体验**:功能相同,体验可以差很多
2. **不只看产品,更看用户**:用户怎么说比产品怎么说更重要
3. **不只看现在,更看趋势**:理解竞品的演进方向
4. **不只学习,更要超越**:学习亮点,避免痛点,创造惊喜

## 常见误区

❌ **只看功能列表**:功能多不代表体验好
❌ **只看官网宣传**:要看真实用户评价
❌ **只看头部竞品**:小而美的产品也有值得学习的地方
❌ **照搬竞品**:要理解背后的逻辑,而不是简单模仿

pm/prd-writing

skill/skills/pm/prd-writing/SKILL.md

产品需求文档(PRD)的标准编写格式和内容要求,确保输出完整、清晰、可执行的产品文档

Raw SKILL.md
---
name: pm/prd-writing
description: 产品需求文档(PRD)的标准编写格式和内容要求,确保输出完整、清晰、可执行的产品文档
version: 1.0.0
agent: pm
type: guideline
user-invocable: false
agent-invocable: true
dependencies:
  - pm/requirement-penetration
triggers:
  - 需求分析完成,准备输出PRD时
  - 需要标准化PRD格式时
metadata:
  internal: true
---

# PRD 编写指南

## 适用场景

完成需求穿透和调研分析后,需要输出一份完整的产品需求文档(PRD),供设计师、开发者、测试人员使用。

## PRD 标准结构

### 1. 概述

- **功能名称**:[清晰简洁的名称]
- **版本**:1.0
- **日期**:[当前日期]
- **作者**:PM Agent

### 摘要

> 下游 Agent 请优先阅读本节,需要细节时再查阅完整文档。

- **核心目标**:[用一句话描述]
- **目标用户**:[主要用户群体]
- **关键功能**:[3-5 个最核心功能]
- **技术约束**:[重要约束或偏好]
- **优先级**:[MVP 范围说明]

---

### 2. 需求穿透分析(核心章节)

参见 `pm/requirement-penetration` skill 的输出要求。

---

### 3. 竞品调研

#### 3.1 竞品分析

使用 `WebSearch` 搜索相关竞品:

| 竞品 | 核心功能 | 用户体验亮点 | 用户痛点 | 我们的机会 |
|------|----------|--------------|----------|------------|
| [竞品 1] | [功能] | [亮点] | [痛点] | [机会] |
| [竞品 2] | [功能] | [亮点] | [痛点] | [机会] |
| [竞品 3] | [功能] | [亮点] | [痛点] | [机会] |

#### 3.2 差异化策略

| 维度 | 竞品做法 | 我们的做法 | 差异化价值 |
|------|----------|------------|------------|
| [维度 1] | [做法] | [做法] | [价值] |
| [维度 2] | [做法] | [做法] | [价值] |

---

### 4. 目标用户

#### 用户画像 1:[名称]

- **基本特征**:[年龄、职业、收入等]
- **行为特征**:[使用习惯、偏好等]
- **核心需求**:[最想解决的问题]
- **痛点场景**:[具体的痛苦场景描述]
- **期望体验**:[理想的体验是什么样]

#### 用户旅程图

```mermaid
journey
    title 用户完成核心任务的旅程
    section 发现阶段
      了解产品: 3: 用户
      产生兴趣: 4: 用户
    section 使用阶段
      首次使用: 3: 用户
      完成任务: 5: 用户
    section 留存阶段
      持续使用: 4: 用户
      推荐他人: 5: 用户
```

---

### 5. 功能需求

#### FR-001:[需求标题]

- **需求描述**:[清晰的需求描述]
- **用户价值**:[这个功能给用户带来什么价值]
- **优先级**:P0/P1/P2
- **需求来源**:显性/隐性/潜在/惊喜
- **验收标准**:
  - [ ] AC-1:[可测试的标准 1]
  - [ ] AC-2:[可测试的标准 2]
- **边界情况**:
  - [边界情况 1 及处理方式]
  - [边界情况 2 及处理方式]

#### FR-002:[需求标题]

- **需求描述**:[描述]
- **用户价值**:[价值]
- **优先级**:P1
- **需求来源**:[来源]
- **验收标准**:
  - [ ] AC-1:[标准]

---

### 6. 非功能需求

#### NFR-001:性能需求

- **页面加载**:首屏加载 < 2s,完整加载 < 3s
- **交互响应**:用户操作响应 < 100ms
- **API 响应**:接口响应 < 200ms

#### NFR-002:体验需求

- **易用性**:新用户无需教程即可完成核心任务
- **一致性**:交互模式和视觉风格保持一致
- **容错性**:操作可撤销,错误可恢复

#### NFR-003:安全需求

- **数据安全**:敏感数据加密存储和传输
- **隐私保护**:符合相关隐私法规

---

### 7. 用户故事

#### US-001:[故事标题]

- **作为** [用户类型]
- **我想要** [目标行为]
- **以便** [预期价值]
- **验收标准**:
  - [ ] [标准 1]
  - [ ] [标准 2]
- **优先级**:P0

#### US-002:[故事标题]

- **作为** [用户类型]
- **我想要** [目标行为]
- **以便** [预期价值]
- **验收标准**:
  - [ ] [标准]
- **优先级**:P1

---

### 8. 成功指标

| 指标类型 | 指标 | 目标值 | 衡量方式 |
|----------|------|--------|----------|
| 核心指标 | [指标] | [目标] | [方式] |
| 体验指标 | [指标] | [目标] | [方式] |
| 业务指标 | [指标] | [目标] | [方式] |

---

### 9. 范围定义

#### 本期范围(In Scope)

- [功能 1]
- [功能 2]

#### 范围外(Out of Scope)

- [排除项 1]:[排除原因]
- [排除项 2]:[排除原因]

---

### 10. 风险与依赖

#### 风险登记

| 风险 | 可能性 | 影响 | 缓解措施 |
|------|--------|------|----------|
| [风险] | 高/中/低 | 高/中/低 | [措施] |

#### 依赖项

| 依赖 | 类型 | 状态 | 负责人 |
|------|------|------|--------|
| [依赖项] | 技术/业务/外部 | 已就绪/待定 | [负责人] |

---

### 11. 里程碑

| 里程碑 | 内容 | 目标日期 |
|--------|------|----------|
| MVP | [核心功能] | - |
| V1.0 | [完整功能] | - |
| V1.1 | [优化迭代] | - |

---

## 编写原则

### 清晰性
- 使用简单直接的语言
- 避免模糊词汇("可能"、"大概"、"尽量")
- 每个需求都有明确的验收标准

### 完整性
- 覆盖所有必要章节
- 功能需求和非功能需求都要考虑
- 边界情况和异常处理要说明

### 可执行性
- 设计师能根据PRD设计界面
- 开发者能根据PRD编写代码
- 测试人员能根据PRD编写测试用例

### 用户导向
- 每个功能都说明用户价值
- 从用户视角描述需求
- 关注用户体验细节

## 输出要求

1. **文件命名**:`prd-{功能名称}-{日期}.md`
2. **文件位置**:项目根目录或 `docs/` 目录
3. **格式**:Markdown格式,使用标准的章节结构
4. **长度**:根据功能复杂度,通常5-20页

## 质量检查清单

在输出PRD前,检查以下项目:

- [ ] 摘要部分是否清晰,能让读者快速理解核心内容
- [ ] 需求穿透分析是否完整(显性、隐性、潜在、惊喜四层)
- [ ] 每个功能需求是否有明确的验收标准
- [ ] 非功能需求是否考虑(性能、体验、安全)
- [ ] 用户故事是否符合 "作为-我想要-以便" 格式
- [ ] 范围定义是否明确(In Scope 和 Out of Scope)
- [ ] 风险和依赖是否识别
- [ ] 文档格式是否规范,易于阅读

---

**记住**:好的PRD不是功能的堆砌,而是对用户需求的精准洞察和优雅满足。

pm/requirement-penetration

skill/skills/pm/requirement-penetration/SKILL.md

深度挖掘用户需求的方法论,通过5W2H追问和需求分层模型,识别显性、隐性、潜在和惊喜需求

Raw SKILL.md
---
name: pm/requirement-penetration
description: 深度挖掘用户需求的方法论,通过5W2H追问和需求分层模型,识别显性、隐性、潜在和惊喜需求
version: 1.0.0
agent: pm
type: methodology
user-invocable: false
agent-invocable: true
dependencies: []
triggers:
  - 用户提出新功能需求时
  - 需要理解用户真实意图时
  - 开始PRD编写前的需求分析阶段
metadata:
  internal: true
---

# 需求穿透方法论

## 适用场景

当用户提出需求时,不要直接接受表面描述。使用本方法论深度挖掘用户真正想要什么,识别用户没说出口的需求,甚至发现用户自己都没意识到的需求。

## 核心方法

### 需求分层模型

用户需求分为四个层次,从下到上价值递增:

```
        ┌─────────────────┐
        │   惊喜需求      │ ← 超出预期,带来 "Wow"
        │   (Delighters)  │
        ├─────────────────┤
        │   潜在需求      │ ← 用户尚未意识到
        │   (Latent)      │
        ├─────────────────┤
        │   隐性需求      │ ← 用户想到但未说
        │   (Implicit)    │
        ├─────────────────┤
        │   显性需求      │ ← 用户明确表达
        │   (Explicit)    │
        └─────────────────┘
```

**四层需求定义**:

1. **显性需求**:用户明确表达的需求
   - 直接从用户原话中提取
   - 这是需求分析的起点,不是终点

2. **隐性需求**:用户想到但未表达的需求
   - 用户认为"理所当然"而没说的
   - 用户不好意思说的
   - 用户以为你会知道的

3. **潜在需求**:用户尚未意识到但会需要的需求
   - 基于场景推演发现的需求
   - 基于竞品分析发现的需求
   - 基于行业趋势预判的需求

4. **惊喜需求**:超出用户预期、能带来 "Wow" 体验的需求
   - 创新性的功能或体验
   - 让用户感到"这个太棒了!"
   - 这是产品差异化的关键

### 5W2H 深度追问

对每个需求,系统性地追问以下7个维度:

| 维度 | 问题 | 目的 |
|------|------|------|
| **What** | 用户说的是什么?背后真正想要的是什么? | 识别真实需求 |
| **Why** | 为什么需要这个?解决什么问题? | 理解动机 |
| **Who** | 谁会用?在什么场景下用? | 明确用户 |
| **When** | 什么时候用?频率如何? | 理解场景 |
| **Where** | 在哪里用?环境如何? | 理解上下文 |
| **How** | 现在怎么解决的?有什么痛点? | 发现机会 |
| **How much** | 愿意付出多少?(时间/金钱/学习成本) | 评估价值 |

**追问技巧**:
- 至少追问 "为什么" 5次,直到触及根本动机
- 不要满足于第一个答案
- 关注用户的情绪和语气,往往隐藏着真实需求

### 需求优先级矩阵

基于价值和成本,将需求分为4个优先级:

```
        高价值
           │
    ┌──────┼──────┐
    │ 必做 │ 优先 │
    │ P0   │ P1   │
低成本 ────┼──── 高成本
    │ 可做 │ 谨慎 │
    │ P2   │ P3   │
    └──────┼──────┘
           │
        低价值
```

- **P0(必做)**:高价值 + 低成本 = 必须做
- **P1(优先)**:高价值 + 高成本 = 优先做
- **P2(可做)**:低价值 + 低成本 = 可以做
- **P3(谨慎)**:低价值 + 高成本 = 暂不做

## 输出要求

完成需求穿透后,应输出以下内容(通常作为PRD的第2章):

### 2. 需求穿透分析

#### 2.1 用户原始需求
> [用户的原始表述,保持原话]

#### 2.2 需求穿透

**显性需求(用户明确表达的)**

| 需求 | 用户原话 | 解读 |
|------|----------|------|
| [需求 1] | "[原话]" | [你的解读] |
| [需求 2] | "[原话]" | [你的解读] |

**隐性需求(用户想到但未表达的)**

| 需求 | 推断依据 | 为什么重要 |
|------|----------|------------|
| [需求 1] | [依据] | [重要性] |
| [需求 2] | [依据] | [重要性] |

**潜在需求(用户尚未意识到的)**

| 需求 | 洞察来源 | 预期价值 |
|------|----------|----------|
| [需求 1] | [来源] | [价值] |
| [需求 2] | [来源] | [价值] |

**惊喜需求(超出预期的创新点)**

| 需求 | 创新点 | 预期反应 |
|------|--------|----------|
| [需求 1] | [创新点] | "Wow, 这个太棒了!" |
| [需求 2] | [创新点] | [预期反应] |

#### 2.3 需求优先级矩阵

| 优先级 | 需求 | 价值 | 成本 | 决策 |
|--------|------|------|------|------|
| P0 | [需求] | 高 | 低 | 必须做 |
| P1 | [需求] | 高 | 高 | 优先做 |
| P2 | [需求] | 低 | 低 | 可以做 |
| P3 | [需求] | 低 | 高 | 暂不做 |

## 关键原则

1. **不要急于给答案**:先理解问题,再提供方案
2. **挑战假设**:用户说的不一定是对的,要验证
3. **关注痛点**:真正的需求来自真实的痛苦
4. **追求惊喜**:好产品不只是满足需求,更要超越预期

pm/strategic-review

skill/skills/pm/strategic-review/SKILL.md

从CEO/战略视角进行商业价值评审,评估市场契合度、ROI、竞争优势、风险和战略对齐

Raw SKILL.md
---
name: pm/strategic-review
description: 从CEO/战略视角进行商业价值评审,评估市场契合度、ROI、竞争优势、风险和战略对齐
version: 1.0.0
agent: pm
type: methodology
user-invocable: true
agent-invocable: true
dependencies:
  - pm/competitive-analysis
triggers:
  - 用户请求战略评审或商业价值评估时
  - 使用 /boss-review 命令时
  - 需要从商业角度判断项目是否值得投入时
  - 产品方向存在争议需要高层决策时
metadata:
  internal: true
---

# 战略评审(Boss Review)

## 适用场景

当需要从 CEO/战略高度评估一个功能或项目的商业价值时使用。不同于技术评审关注实现质量,战略评审关注**做不做**和**为什么做**。

典型场景:
- 新功能立项前的价值论证
- 资源有限时的优先级决策
- 产品方向调整的论证
- 投资人/利益相关者沟通准备

## 核心方法

### 第一维度:市场契合度(Market Fit)

评估产品/功能与市场需求的匹配程度:

| 评估项 | 问题 | 评分标准 |
|--------|------|----------|
| 目标市场 | TAM/SAM/SOM 分别多大? | 清晰可量化 = 高分 |
| 痛点强度 | 用户痛点是止痛药还是维生素? | 必须有 > 最好有 > 可以有 |
| 时机 | 为什么是现在? | 有明确时间窗口 = 高分 |
| 验证程度 | 有多少用户验证? | 付费验证 > 使用验证 > 口头验证 > 假设 |

### 第二维度:投资回报率(ROI)

量化投入产出比:

| 评估项 | 问题 | 评分标准 |
|--------|------|----------|
| 开发成本 | 需要多少人天? | 精确估算 = 高分 |
| 运营成本 | 上线后持续投入? | 低维护 = 高分 |
| 收益模型 | 直接/间接收益如何? | 有历史数据支撑 = 高分 |
| 回收周期 | 多久能回本? | <3个月 = 优 / <6个月 = 良 / >12个月 = 需论证 |
| 机会成本 | 不做什么来做这个? | 机会成本可控 = 高分 |

### 第三维度:竞争优势(Competitive Advantage)

评估护城河和差异化:

| 评估项 | 问题 | 评分标准 |
|--------|------|----------|
| 技术壁垒 | 竞对复制需要多久? | >6个月 = 强壁垒 |
| 网络效应 | 用户越多越好用吗? | 有强网络效应 = 高分 |
| 数据优势 | 有独占数据资产吗? | 数据不可替代 = 高分 |
| 品牌认知 | 能否建立心智定位? | 有清晰定位 = 高分 |
| 切换成本 | 用户迁移难度? | 高切换成本 = 高分 |

### 第四维度:风险矩阵(Risk Assessment)

识别和评估风险:

| 风险类型 | 评估要素 | 缓解方案 |
|----------|----------|----------|
| 市场风险 | 需求是否真实、市场是否足够大 | MVP 验证、用户访谈 |
| 技术风险 | 是否有未验证的技术假设 | 技术 spike、原型验证 |
| 执行风险 | 团队是否有能力按时交付 | 分阶段交付、招聘计划 |
| 合规风险 | 是否涉及法规/政策限制 | 法务咨询、合规审查 |
| 依赖风险 | 是否依赖不可控的外部因素 | 备选方案、合同约束 |

### 第五维度:战略对齐(Strategic Alignment)

评估与公司战略的一致性:

| 评估项 | 问题 | 评分标准 |
|--------|------|----------|
| 愿景匹配 | 与公司3-5年愿景一致吗? | 强关联 = 高分 |
| 能力杠杆 | 能否复用现有优势? | 高杠杆 = 高分 |
| 协同效应 | 与其他产品线有协同吗? | 1+1>2 = 高分 |
| 资源匹配 | 现有资源能否支撑? | 资源充足 = 高分 |

## 评审决策框架

### 综合评分规则

每个维度 1-5 分,加权计算综合分:
- 市场契合度:权重 30%
- ROI:权重 25%
- 竞争优势:权重 20%
- 风险评估:权重 15%(此项为风险可控程度)
- 战略对齐:权重 10%

### 决策映射

| 综合分 | 决策 | 说明 |
|--------|------|------|
| ≥ 4.0 | ✅ 推进 | 全力推进,优先分配资源 |
| 3.0 - 3.9 | ⚠️ 需调整 | 方向正确但需优化具体方案 |
| < 3.0 | ❌ 暂缓 | 暂不投入,需重新论证或等待时机 |

## 输出要求

使用 `strategic-review.md.template` 模板输出到 `.boss/<feature>/strategic-review.md`,包含:

1. **执行摘要**:商业价值评级(1-5)、推荐决策、关键洞察(1-2句)
2. **五维分析详情**:每个维度的评分和关键判断依据
3. **风险矩阵表**:风险项 × 影响程度 × 发生概率 × 缓解方案
4. **战略建议**:具体的行动建议(推进/调整/暂缓的理由和下一步)
5. **关键假设**:列出评审中的关键假设,标注验证状态

pm/user-research

skill/skills/pm/user-research/SKILL.md

用户研究方法,通过用户画像和用户旅程图,深入理解目标用户的特征、需求和行为

Raw SKILL.md
---
name: pm/user-research
description: 用户研究方法,通过用户画像和用户旅程图,深入理解目标用户的特征、需求和行为
version: 1.0.0
agent: pm
type: methodology
user-invocable: false
agent-invocable: true
dependencies: []
triggers:
  - 需要明确目标用户时
  - 需要理解用户行为和场景时
  - 设计用户体验流程时
metadata:
  internal: true
---

# 用户研究方法论

## 适用场景

在产品设计前,需要深入理解目标用户是谁、他们的特征是什么、他们在什么场景下使用产品、他们的行为路径是什么。

## 核心方法

### 1. 用户画像 (User Persona)

用户画像是对目标用户的具象化描述,帮助团队建立对用户的共同理解。

#### 用户画像模板

**用户画像 1:[给用户起个名字,如"技术小白张三"]**

- **基本特征**:
  - 年龄:[年龄段]
  - 职业:[职业]
  - 收入:[收入水平]
  - 教育:[教育背景]
  - 地域:[所在地区]

- **行为特征**:
  - 使用习惯:[如何使用类似产品]
  - 技术水平:[对技术的熟悉程度]
  - 使用频率:[多久使用一次]
  - 使用时长:[每次使用多久]
  - 设备偏好:[PC/移动端/平板]

- **心理特征**:
  - 性格特点:[如保守/激进、理性/感性]
  - 价值观:[看重什么]
  - 动机:[为什么使用产品]
  - 顾虑:[担心什么]

- **核心需求**:
  - 最想解决的问题:[核心痛点]
  - 期望的结果:[想要达成什么]
  - 愿意付出的代价:[时间/金钱/学习成本]

- **痛点场景**:
  - 场景描述:[具体的使用场景]
  - 当前解决方案:[现在怎么解决]
  - 痛点:[现有方案的问题]
  - 情绪:[遇到痛点时的感受]

- **期望体验**:
  - 理想流程:[希望如何完成任务]
  - 关键体验点:[最在意的体验]
  - 成功标准:[什么样算成功]

#### 创建用户画像的步骤

1. **识别用户群体**:产品可能服务多类用户,先列出所有用户类型
2. **选择主要用户**:选择2-3个最重要的用户类型深入分析
3. **收集用户数据**:
   - 如果有现有用户:分析用户数据、用户访谈、用户调研
   - 如果是新产品:竞品用户分析、目标市场研究、假设验证
4. **具象化描述**:给用户起名字、配图片,让用户"活"起来
5. **验证画像**:与真实用户对比,确保画像准确

#### 多用户画像的处理

如果产品服务多类用户,需要:
- 明确**主要用户**(Primary Persona):产品主要服务的用户
- 识别**次要用户**(Secondary Persona):也会使用但不是核心
- 考虑**边缘用户**(Edge Persona):极端情况下的用户

**优先级原则**:
- 主要用户的需求优先满足
- 次要用户的需求在不影响主要用户的前提下满足
- 边缘用户的需求用于测试产品的健壮性

### 2. 用户旅程图 (User Journey Map)

用户旅程图描绘用户完成核心任务的完整路径,包括每个阶段的行为、想法、情绪和痛点。

#### 用户旅程图模板

```mermaid
journey
    title 用户完成核心任务的旅程
    section 发现阶段
      了解产品: 3: 用户
      产生兴趣: 4: 用户
    section 使用阶段
      首次使用: 3: 用户
      完成任务: 5: 用户
    section 留存阶段
      持续使用: 4: 用户
      推荐他人: 5: 用户
```

#### 旅程图的关键要素

**1. 阶段划分**

典型的用户旅程包含以下阶段:
- **认知阶段**:用户如何知道产品
- **考虑阶段**:用户如何评估产品
- **购买/注册阶段**:用户如何开始使用
- **首次使用阶段**:用户第一次使用的体验
- **持续使用阶段**:用户日常使用的体验
- **推荐阶段**:用户是否会推荐给他人

**2. 每个阶段的分析维度**

| 维度 | 描述 |
|------|------|
| **行为** | 用户在做什么 |
| **想法** | 用户在想什么 |
| **情绪** | 用户的情绪状态(1-5分) |
| **触点** | 用户与产品的接触点 |
| **痛点** | 用户遇到的问题 |
| **机会** | 我们可以改进的地方 |

**3. 情绪曲线**

用1-5分标注用户在每个阶段的情绪:
- 5分:非常满意,"Wow"体验
- 4分:满意
- 3分:一般,没有特别感受
- 2分:不满意,有些失望
- 1分:非常不满意,想放弃

**目标**:
- 识别情绪低点(痛点),优先优化
- 创造情绪高点(峰值体验),形成记忆点
- 确保结束时情绪高(峰终定律)

#### 创建用户旅程图的步骤

1. **定义核心任务**:用户使用产品要完成的主要任务
2. **划分旅程阶段**:将任务分解为关键阶段
3. **填充每个阶段**:
   - 用户在做什么(行为)
   - 用户在想什么(想法)
   - 用户的情绪如何(情绪)
   - 用户遇到什么问题(痛点)
4. **绘制情绪曲线**:可视化用户的情绪变化
5. **识别优化机会**:在痛点处寻找改进机会

### 3. 用户场景 (User Scenario)

用户场景是对用户在特定情境下使用产品的故事化描述。

#### 场景描述模板

**场景:[场景名称]**

- **用户**:[哪个用户画像]
- **情境**:[什么时间、什么地点、什么情况下]
- **目标**:[用户想要完成什么]
- **行为**:[用户会做什么]
- **结果**:[期望的结果]
- **情绪**:[过程中的情绪变化]

**示例**:

**场景:周末在家整理照片**

- **用户**:摄影爱好者李四
- **情境**:周末下午,在家用电脑,刚拍完一次旅行回来
- **目标**:快速找到最好的照片,删除重复和模糊的照片
- **行为**:
  1. 导入200张照片
  2. 快速浏览,标记喜欢的
  3. 删除明显不好的
  4. 对比相似的照片,选择最好的
  5. 导出精选照片
- **结果**:从200张照片中精选出30张,用时30分钟
- **情绪**:开始兴奋,中间有些疲惫(照片太多),最后满意(快速完成)

## 输出要求

完成用户研究后,应输出以下内容(通常作为PRD的第4章):

### 4. 目标用户

#### 用户画像 1:[名称]

- **基本特征**:[年龄、职业、收入等]
- **行为特征**:[使用习惯、偏好等]
- **核心需求**:[最想解决的问题]
- **痛点场景**:[具体的痛苦场景描述]
- **期望体验**:[理想的体验是什么样]

#### 用户画像 2:[名称]

[同上]

#### 用户旅程图

```mermaid
journey
    title 用户完成核心任务的旅程
    section 发现阶段
      了解产品: 3: 用户
      产生兴趣: 4: 用户
    section 使用阶段
      首次使用: 3: 用户
      完成任务: 5: 用户
    section 留存阶段
      持续使用: 4: 用户
      推荐他人: 5: 用户
```

#### 关键场景

**场景1:[场景名称]**
- [场景描述]

**场景2:[场景名称]**
- [场景描述]

## 关键原则

1. **具象化**:用户画像要有名字、有故事,让团队能"看见"用户
2. **真实性**:基于真实数据和观察,不要凭空想象
3. **聚焦**:2-3个主要用户画像足够,不要贪多
4. **动态更新**:随着对用户的了解加深,持续更新画像

## 常见误区

❌ **用户画像太抽象**:只有年龄、性别等基本信息,没有行为和心理特征
❌ **用户画像太多**:列出10个用户画像,导致无法聚焦
❌ **凭空想象**:没有数据支撑,完全靠猜测
❌ **一次性工作**:创建后就不再更新,与真实用户脱节

qa/e2e-playwright

skill/skills/qa/e2e-playwright/SKILL.md

Playwright E2E 测试完整方法论,涵盖项目初始化、Page Object Model、认证复用、API Mock、视觉回归、多浏览器测试、CI 集成和调试技巧

Raw SKILL.md
---
name: qa/e2e-playwright
description: Playwright E2E 测试完整方法论,涵盖项目初始化、Page Object Model、认证复用、API Mock、视觉回归、多浏览器测试、CI 集成和调试技巧
version: 1.0.0
agent: qa
type: methodology
user-invocable: false
agent-invocable: true
dependencies:
  - shared/tech-stack-detection
triggers:
  - 需要编写或执行 E2E 测试时
  - 需要配置 Playwright 测试环境时
  - 门禁要求 E2E 测试通过时
  - 需要视觉回归测试时
metadata:
  internal: true
---

# Playwright E2E 测试方法论

## 适用场景

- Web 项目需要编写端到端测试
- 门禁(Gate 1)要求 E2E 测试通过
- 需要覆盖关键用户流程的自动化验证
- 需要多浏览器/多视口兼容性验证
- 需要视觉回归测试

---

## 1. 项目初始化

### 1.1 安装

```bash
# 新项目初始化(推荐)
npm init playwright@latest

# 已有项目添加
npm install -D @playwright/test
npx playwright install
```

### 1.2 配置文件(`playwright.config.ts`)

```typescript
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
  testDir: './e2e',
  // 测试产物目录
  outputDir: './e2e/test-results',

  // 全局超时
  timeout: 30_000,
  expect: { timeout: 5_000 },

  // 并行执行
  fullyParallel: true,
  workers: process.env.CI ? 1 : undefined,

  // 失败重试(CI 中重试一次减少 flaky)
  retries: process.env.CI ? 1 : 0,

  // 报告
  reporter: [
    ['html', { outputFolder: './e2e/playwright-report' }],
    ['json', { outputFile: './e2e/test-results/results.json' }],
    // CI 中额外输出到 stdout
    ...(process.env.CI ? [['github'] as const] : []),
  ],

  // 全局配置
  use: {
    baseURL: process.env.BASE_URL || 'http://localhost:3000',
    // 失败时自动截图
    screenshot: 'only-on-failure',
    // 失败时录制 trace
    trace: 'on-first-retry',
    // 失败时录制视频
    video: 'on-first-retry',
  },

  // 多浏览器 + 移动端视口
  projects: [
    { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
    { name: 'firefox', use: { ...devices['Desktop Firefox'] } },
    { name: 'webkit', use: { ...devices['Desktop Safari'] } },
    { name: 'mobile-chrome', use: { ...devices['Pixel 5'] } },
    { name: 'mobile-safari', use: { ...devices['iPhone 13'] } },
  ],

  // 开发服务器自动启动
  webServer: {
    command: 'npm run dev',
    url: 'http://localhost:3000',
    reuseExistingServer: !process.env.CI,
    timeout: 120_000,
  },
});
```

**关键配置说明**:

| 配置项 | 作用 | 建议值 |
|--------|------|--------|
| `fullyParallel` | 测试文件间并行执行 | `true` |
| `workers` | 并行 worker 数 | CI 为 1,本地默认 |
| `retries` | 失败重试次数 | CI 为 1,本地为 0 |
| `trace` | 失败时生成可视化时间线 | `on-first-retry` |
| `webServer` | 自动启动开发服务器 | 必须配置 |

### 1.3 目录结构

```
e2e/
├── playwright.config.ts        # 配置文件(或放在项目根目录)
├── fixtures/                   # 自定义 fixtures
│   ├── base.ts                 # 扩展 base test
│   └── auth.ts                 # 认证 fixture
├── pages/                      # Page Object Models
│   ├── login.page.ts
│   ├── dashboard.page.ts
│   └── components/             # 可复用组件 POM
│       ├── navbar.component.ts
│       └── modal.component.ts
├── specs/                      # 测试用例
│   ├── auth/
│   │   ├── login.spec.ts
│   │   └── register.spec.ts
│   ├── dashboard/
│   │   └── dashboard.spec.ts
│   └── crud/
│       └── user-management.spec.ts
├── helpers/                    # 测试工具
│   ├── seed.ts                 # 数据种子
│   └── cleanup.ts              # 数据清理
├── test-results/               # 测试产物(gitignore)
└── playwright-report/          # HTML 报告(gitignore)
```

---

## 2. Page Object Model(POM)

### 2.1 核心原则

- **每个页面一个 POM 类**:封装定位器和操作方法
- **不暴露 Locator**:外部只调用语义化方法
- **组件级复用**:导航栏、弹窗等提取为独立组件 POM

### 2.2 基础 POM

```typescript
// e2e/pages/login.page.ts
import { type Page, type Locator } from '@playwright/test';

export class LoginPage {
  private readonly emailInput: Locator;
  private readonly passwordInput: Locator;
  private readonly submitButton: Locator;
  private readonly errorMessage: Locator;

  constructor(private readonly page: Page) {
    this.emailInput = page.getByLabel('邮箱');
    this.passwordInput = page.getByLabel('密码');
    this.submitButton = page.getByRole('button', { name: '登录' });
    this.errorMessage = page.getByRole('alert');
  }

  async goto() {
    await this.page.goto('/login');
  }

  async login(email: string, password: string) {
    await this.emailInput.fill(email);
    await this.passwordInput.fill(password);
    await this.submitButton.click();
  }

  async getErrorMessage() {
    return this.errorMessage.textContent();
  }
}
```

### 2.3 组件 POM

```typescript
// e2e/pages/components/navbar.component.ts
import { type Page, type Locator } from '@playwright/test';

export class NavbarComponent {
  private readonly userMenu: Locator;
  private readonly logoutButton: Locator;

  constructor(private readonly page: Page) {
    this.userMenu = page.getByTestId('user-menu');
    this.logoutButton = page.getByRole('menuitem', { name: '退出登录' });
  }

  async logout() {
    await this.userMenu.click();
    await this.logoutButton.click();
  }

  async getUserDisplayName() {
    return this.userMenu.textContent();
  }
}
```

### 2.4 定位器优先级

选择定位器时遵循以下优先级(可靠性从高到低):

| 优先级 | 方法 | 示例 | 说明 |
|--------|------|------|------|
| 1 | `getByRole` | `getByRole('button', { name: '提交' })` | 无障碍语义,最稳定 |
| 2 | `getByLabel` | `getByLabel('邮箱')` | 表单元素首选 |
| 3 | `getByPlaceholder` | `getByPlaceholder('请输入邮箱')` | 备选 |
| 4 | `getByText` | `getByText('欢迎回来')` | 静态文本 |
| 5 | `getByTestId` | `getByTestId('submit-btn')` | 无语义标记时的兜底 |
| 6 | CSS/XPath | `page.locator('.btn-primary')` | **尽量避免** |

---

## 3. 认证状态复用

### 3.1 Global Setup 方式

```typescript
// e2e/global-setup.ts
import { chromium, type FullConfig } from '@playwright/test';

async function globalSetup(config: FullConfig) {
  const browser = await chromium.launch();
  const page = await browser.newPage();

  // 执行登录
  await page.goto('http://localhost:3000/login');
  await page.getByLabel('邮箱').fill('[email protected]');
  await page.getByLabel('密码').fill('password');
  await page.getByRole('button', { name: '登录' }).click();
  await page.waitForURL('/dashboard');

  // 保存认证状态
  await page.context().storageState({ path: './e2e/.auth/admin.json' });
  await browser.close();
}

export default globalSetup;
```

**配置引用**:

```typescript
// playwright.config.ts
export default defineConfig({
  globalSetup: './e2e/global-setup.ts',
  projects: [
    // 不带认证的测试
    { name: 'public', testMatch: /public\.spec\.ts/ },
    // 带认证的测试
    {
      name: 'authenticated',
      use: { storageState: './e2e/.auth/admin.json' },
      testIgnore: /public\.spec\.ts/,
    },
  ],
});
```

### 3.2 多角色认证

```typescript
// e2e/fixtures/auth.ts
import { test as base } from '@playwright/test';

type AuthFixtures = {
  adminPage: Page;
  userPage: Page;
};

export const test = base.extend<AuthFixtures>({
  adminPage: async ({ browser }, use) => {
    const context = await browser.newContext({
      storageState: './e2e/.auth/admin.json',
    });
    const page = await context.newPage();
    await use(page);
    await context.close();
  },
  userPage: async ({ browser }, use) => {
    const context = await browser.newContext({
      storageState: './e2e/.auth/user.json',
    });
    const page = await context.newPage();
    await use(page);
    await context.close();
  },
});
```

---

## 4. API Mocking

### 4.1 使用 `page.route` 拦截请求

```typescript
test('显示用户列表(API Mock)', async ({ page }) => {
  // 拦截 API 请求
  await page.route('/api/users', async (route) => {
    await route.fulfill({
      status: 200,
      contentType: 'application/json',
      body: JSON.stringify([
        { id: 1, name: '张三', email: '[email protected]' },
        { id: 2, name: '李四', email: '[email protected]' },
      ]),
    });
  });

  await page.goto('/users');
  await expect(page.getByText('张三')).toBeVisible();
  await expect(page.getByText('李四')).toBeVisible();
});
```

### 4.2 模拟错误响应

```typescript
test('API 失败时显示错误提示', async ({ page }) => {
  await page.route('/api/users', async (route) => {
    await route.fulfill({ status: 500, body: 'Internal Server Error' });
  });

  await page.goto('/users');
  await expect(page.getByText('加载失败')).toBeVisible();
  await expect(page.getByRole('button', { name: '重试' })).toBeVisible();
});
```

### 4.3 Mock 与真实请求混合

```typescript
test('部分 API Mock', async ({ page }) => {
  // 只 Mock 第三方支付接口,其余走真实请求
  await page.route('**/api/payment/**', async (route) => {
    await route.fulfill({
      status: 200,
      body: JSON.stringify({ success: true, transactionId: 'mock-tx-001' }),
    });
  });

  await page.goto('/checkout');
  // ... 执行支付流程
});
```

### 4.4 何时用 Mock vs 真实 API

| 场景 | 建议 |
|------|------|
| 核心用户路径 | **真实 API**(关键路径证据规则) |
| 第三方服务(支付、邮件) | Mock |
| 错误/边界状态 | Mock |
| 加载状态、空数据 | Mock |
| 数据量大的列表/分页 | Mock + 至少一条真实路径 |

⚠️ **Boss 门禁规则**:核心用户路径只由 Mock 证明的,必须标记为**未验证**,不能作为发布证据。

---

## 5. 关键用户流程测试(必须覆盖)

### 5.1 CRUD 完整流程

```typescript
// e2e/specs/crud/user-management.spec.ts
import { test, expect } from '@playwright/test';
import { UserListPage } from '../../pages/user-list.page';
import { UserFormPage } from '../../pages/user-form.page';

test.describe('用户管理 CRUD', () => {
  let userList: UserListPage;
  let userForm: UserFormPage;

  test.beforeEach(async ({ page }) => {
    userList = new UserListPage(page);
    userForm = new UserFormPage(page);
    await userList.goto();
  });

  test('创建 → 编辑 → 删除完整流程', async ({ page }) => {
    // 创建
    await userList.clickAddUser();
    await userForm.fillName('测试用户');
    await userForm.fillEmail('[email protected]');
    await userForm.submit();
    await expect(page.getByText('测试用户')).toBeVisible();

    // 编辑
    await userList.editUser('测试用户');
    await userForm.fillName('修改后的用户');
    await userForm.submit();
    await expect(page.getByText('修改后的用户')).toBeVisible();
    await expect(page.getByText('测试用户')).not.toBeVisible();

    // 删除
    await userList.deleteUser('修改后的用户');
    await userList.confirmDelete();
    await expect(page.getByText('修改后的用户')).not.toBeVisible();
  });

  test('列表分页展示', async ({ page }) => {
    await expect(userList.getTable()).toBeVisible();
    await userList.goToNextPage();
    await expect(page).toHaveURL(/page=2/);
  });

  test('空列表提示', async ({ page }) => {
    // 使用 route mock 空数据场景
    await page.route('/api/users*', (route) =>
      route.fulfill({ status: 200, body: JSON.stringify({ data: [], total: 0 }) })
    );
    await page.reload();
    await expect(page.getByText('暂无数据')).toBeVisible();
  });
});
```

### 5.2 认证流程

```typescript
// e2e/specs/auth/login.spec.ts
import { test, expect } from '@playwright/test';
import { LoginPage } from '../../pages/login.page';

test.describe('登录', () => {
  let loginPage: LoginPage;

  test.beforeEach(async ({ page }) => {
    loginPage = new LoginPage(page);
    await loginPage.goto();
  });

  test('正确凭据成功登录', async ({ page }) => {
    await loginPage.login('[email protected]', 'password');
    await expect(page).toHaveURL('/dashboard');
  });

  test('错误凭据显示提示', async ({ page }) => {
    await loginPage.login('[email protected]', 'wrong-password');
    await expect(page.getByRole('alert')).toContainText('密码错误');
    await expect(page).toHaveURL('/login');
  });

  test('未登录重定向到登录页', async ({ page }) => {
    await page.goto('/dashboard');
    await expect(page).toHaveURL(/\/login/);
  });
});
```

### 5.3 表单验证

```typescript
test.describe('表单验证', () => {
  test('必填字段为空时显示错误', async ({ page }) => {
    await page.goto('/users/new');
    await page.getByRole('button', { name: '提交' }).click();

    await expect(page.getByText('姓名不能为空')).toBeVisible();
    await expect(page.getByText('邮箱不能为空')).toBeVisible();
  });

  test('邮箱格式错误时显示提示', async ({ page }) => {
    await page.goto('/users/new');
    await page.getByLabel('邮箱').fill('invalid-email');
    await page.getByLabel('邮箱').blur();

    await expect(page.getByText('邮箱格式不正确')).toBeVisible();
  });
});
```

---

## 6. 视觉回归测试

### 6.1 截图对比

```typescript
test('首页视觉回归', async ({ page }) => {
  await page.goto('/');
  // 等待动态内容稳定
  await page.waitForLoadState('networkidle');
  await expect(page).toHaveScreenshot('homepage.png', {
    maxDiffPixelRatio: 0.01,
  });
});

test('组件视觉回归', async ({ page }) => {
  await page.goto('/components/button');
  const button = page.getByTestId('primary-button');
  await expect(button).toHaveScreenshot('primary-button.png');
});
```

### 6.2 更新基线

```bash
# 更新所有截图基线
npx playwright test --update-snapshots

# 更新指定测试的截图
npx playwright test homepage.spec.ts --update-snapshots
```

### 6.3 注意事项

- 截图基线需提交到 Git
- 不同 OS 渲染有差异,CI 中使用 Docker 保证一致性
- 对动态内容(时间、随机数据)需 Mock 后再截图
- `maxDiffPixelRatio` 容忍微小渲染差异(抗锯齿等)

---

## 7. 多浏览器和移动端测试

### 7.1 配置多 project

```typescript
// playwright.config.ts 中的 projects 已覆盖
// 可根据项目需要选择性启用:

projects: [
  // 桌面浏览器
  { name: 'chromium', use: { ...devices['Desktop Chrome'] } },
  { name: 'firefox', use: { ...devices['Desktop Firefox'] } },
  { name: 'webkit', use: { ...devices['Desktop Safari'] } },

  // 移动端视口
  { name: 'mobile-chrome', use: { ...devices['Pixel 5'] } },
  { name: 'mobile-safari', use: { ...devices['iPhone 13'] } },

  // 平板
  { name: 'tablet', use: { ...devices['iPad Pro 11'] } },
]
```

### 7.2 按 project 运行

```bash
# 只跑 Chromium
npx playwright test --project=chromium

# 只跑移动端
npx playwright test --project=mobile-chrome --project=mobile-safari
```

### 7.3 响应式断言

```typescript
test('移动端显示汉堡菜单', async ({ page, isMobile }) => {
  await page.goto('/');
  if (isMobile) {
    await expect(page.getByTestId('hamburger-menu')).toBeVisible();
    await expect(page.getByTestId('desktop-nav')).not.toBeVisible();
  } else {
    await expect(page.getByTestId('desktop-nav')).toBeVisible();
    await expect(page.getByTestId('hamburger-menu')).not.toBeVisible();
  }
});
```

---

## 8. 测试数据管理

### 8.1 数据种子(Seed)

```typescript
// e2e/helpers/seed.ts
import { request } from '@playwright/test';

export async function seedTestData(baseURL: string) {
  const api = await request.newContext({ baseURL });
  await api.post('/api/test/seed', {
    data: {
      users: [
        { name: '测试管理员', email: '[email protected]', role: 'admin' },
        { name: '测试用户', email: '[email protected]', role: 'user' },
      ],
    },
  });
  await api.dispose();
}
```

### 8.2 数据清理

```typescript
// e2e/helpers/cleanup.ts
import { request } from '@playwright/test';

export async function cleanupTestData(baseURL: string) {
  const api = await request.newContext({ baseURL });
  await api.post('/api/test/cleanup');
  await api.dispose();
}
```

### 8.3 在 Global Setup/Teardown 中使用

```typescript
// e2e/global-setup.ts
import { seedTestData } from './helpers/seed';

async function globalSetup() {
  await seedTestData('http://localhost:3000');
}
export default globalSetup;

// e2e/global-teardown.ts
import { cleanupTestData } from './helpers/cleanup';

async function globalTeardown() {
  await cleanupTestData('http://localhost:3000');
}
export default globalTeardown;
```

### 8.4 原则

| 原则 | 说明 |
|------|------|
| **测试隔离** | 每个测试独立运行,不依赖其他测试的数据 |
| **可重复** | 多次运行结果一致 |
| **快速清理** | 使用 API 清理而非 UI 操作 |
| **避免硬编码 ID** | 使用动态创建的数据,不依赖数据库自增 ID |

---

## 9. CI/CD 集成

### 9.1 GitHub Actions

```yaml
# .github/workflows/e2e.yml
name: E2E Tests
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  e2e:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Install dependencies
        run: npm ci

      - name: Install Playwright browsers
        run: npx playwright install --with-deps

      - name: Build application
        run: npm run build

      - name: Run E2E tests
        run: npx playwright test

      - name: Upload test results
        if: ${{ !cancelled() }}
        uses: actions/upload-artifact@v4
        with:
          name: playwright-report
          path: e2e/playwright-report/
          retention-days: 30

      - name: Upload trace files
        if: failure()
        uses: actions/upload-artifact@v4
        with:
          name: playwright-traces
          path: e2e/test-results/
          retention-days: 7
```

### 9.2 Docker 一致性

```dockerfile
# e2e/Dockerfile
FROM mcr.microsoft.com/playwright:v1.49.0-noble
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
CMD ["npx", "playwright", "test"]
```

### 9.3 CI 关键配置

| 配置 | CI 值 | 原因 |
|------|-------|------|
| `workers` | 1 | CI 资源有限,避免争抢 |
| `retries` | 1 | 减少 flaky 误报 |
| `reporter` | `github` + `html` | GitHub PR 行内注释 + HTML 归档 |
| `trace` | `on-first-retry` | 只在重试时录制,节省空间 |

---

## 10. 调试技巧

### 10.1 UI 模式(开发首选)

```bash
# 打开可视化调试界面
npx playwright test --ui
```

### 10.2 Trace Viewer

```bash
# 查看失败测试的 trace
npx playwright show-trace e2e/test-results/specs-auth-login-spec-ts/trace.zip
```

Trace Viewer 提供:
- 时间线上的每一步操作
- DOM 快照
- 网络请求日志
- 控制台输出

### 10.3 Debug 模式

```bash
# 逐步执行,自动暂停
npx playwright test --debug

# 指定测试文件
npx playwright test login.spec.ts --debug
```

### 10.4 代码中暂停

```typescript
test('调试用', async ({ page }) => {
  await page.goto('/login');
  await page.pause(); // 打开 Inspector,手动操作
  // ...
});
```

### 10.5 录制生成测试

```bash
# 打开浏览器录制,自动生成代码
npx playwright codegen http://localhost:3000
```

### 10.6 常见 Flaky 原因及修复

| 原因 | 症状 | 修复 |
|------|------|------|
| 动画未完成 | 元素找到但点击无效 | 等待动画完成或禁用动画 |
| 网络请求延迟 | 元素内容未更新 | 使用 `waitForResponse` |
| 竞态条件 | 间歇性失败 | 使用 `expect().toBeVisible()` 自动等待 |
| 数据未就绪 | 列表为空 | 使用 `waitForLoadState('networkidle')` |
| 时间依赖 | 日期/时间相关断言失败 | Mock 时间或使用范围断言 |

---

## 11. 与 Boss 流水线门禁集成

### 11.1 Gate 1 E2E 检查项

Boss 流水线的 Gate 1 门禁要求 E2E 测试满足:

| 检查项 | 要求 | 说明 |
|--------|------|------|
| E2E 测试存在 | `e2e/` 或 `tests/e2e/` 目录非空 | 不能只有单元测试 |
| 关键路径覆盖 | CRUD + 认证 + 核心业务流程 | 至少 5 个核心用户操作 |
| 全部通过 | 无失败用例 | 失败则门禁不通过 |
| 真实 API 证据 | 核心路径不能只有 Mock | Mock-only 标记为未验证 |

### 11.2 执行命令

```bash
# 门禁检查时执行
npx playwright test --reporter=json --output=e2e/test-results

# 仅核心路径(CI 加速)
npx playwright test --grep @critical

# 完整套件
npx playwright test
```

### 11.3 测试标签

使用标签标记测试优先级,门禁可按标签选择性执行:

```typescript
test('@critical 登录流程', async ({ page }) => { /* ... */ });
test('@critical 核心业务流程', async ({ page }) => { /* ... */ });
test('@smoke 首页加载', async ({ page }) => { /* ... */ });
test('@regression 边界情况', async ({ page }) => { /* ... */ });
```

```bash
# Gate 1 只跑 critical
npx playwright test --grep @critical

# 完整回归
npx playwright test
```

---

## 12. 检查清单

Agent 编写 E2E 测试时,对照以下清单确认完整性:

- [ ] `playwright.config.ts` 已配置(baseURL、webServer、projects)
- [ ] Page Object Model 已建立(每个核心页面一个 POM)
- [ ] 定位器使用语义化方法(`getByRole` > `getByTestId` > CSS)
- [ ] 认证状态已配置复用(`storageState`)
- [ ] 关键用户路径已覆盖(CRUD + 认证 + 核心业务)
- [ ] 错误状态和边界条件已测试(空数据、网络错误、表单验证)
- [ ] 核心路径使用真实 API(非 Mock-only)
- [ ] CI 配置已就绪(GitHub Actions / 其他)
- [ ] 测试产物目录已加入 `.gitignore`(`test-results/`、`playwright-report/`)
- [ ] 截图基线已提交(如使用视觉回归)

## 输出要求

使用本方法论后,Agent 应产出:

1. **`playwright.config.ts`**:完整配置
2. **`e2e/pages/*.page.ts`**:Page Object Model
3. **`e2e/specs/**/*.spec.ts`**:测试用例(覆盖关键路径)
4. **认证 fixture**:`storageState` 或 global-setup
5. **CI 配置**:GitHub Actions 或等价 CI 流程
6. **`.gitignore` 更新**:排除测试产物目录

qa/test-execution

skill/skills/qa/test-execution/SKILL.md

测试执行方法,包含测试框架检测、测试运行、结果解析

Raw SKILL.md
---
name: qa/test-execution
description: 测试执行方法,包含测试框架检测、测试运行、结果解析
version: 1.0.0
agent: qa
type: methodology
user-invocable: false
agent-invocable: true
dependencies:
  - shared/tech-stack-detection
triggers:
  - 需要执行测试时
  - 需要验证测试覆盖率时
metadata:
  internal: true
---

# 测试执行方法

## 强制要求:真实执行测试

**你必须真正执行测试,禁止生成 Mock 数据!**

## 测试执行流程

1. **检测项目类型和测试框架**
2. **根据项目类型执行测试**
3. **执行 E2E / 集成测试**
4. **解析测试输出**(总数、通过数、失败数、覆盖率)

## 测试框架检测

### JavaScript/TypeScript
- Jest: `jest.config.js`, `"jest"` in package.json
- Vitest: `vitest.config.js`, `"vitest"` in package.json
- Playwright: `playwright.config.js`
- Cypress: `cypress.json`

### Python
- pytest: `pytest.ini`, `"pytest"` in dependencies
- unittest: 内置

### Go
- `*_test.go` 文件

## 测试命令

| 语言 | 单元测试 | E2E测试 |
|------|----------|---------|
| Node.js | `npm test` | `npx playwright test` |
| Python | `pytest` | `pytest tests/e2e` |
| Go | `go test ./...` | - |

## Playwright E2E 执行细节

> **完整方法论**:详见 `Skill(skill: "qa/e2e-playwright")`

### 检测 Playwright 项目

检查以下标志确认项目使用 Playwright:
- `playwright.config.ts` 或 `playwright.config.js` 存在
- `package.json` 中包含 `@playwright/test` 依赖
- `e2e/` 或 `tests/e2e/` 目录存在

### 执行命令

```bash
# 安装浏览器(首次或 CI 环境)
npx playwright install --with-deps

# 运行全部 E2E 测试
npx playwright test

# 仅 critical 标签(门禁加速)
npx playwright test --grep @critical

# 指定浏览器
npx playwright test --project=chromium

# JSON 报告(门禁解析用)
npx playwright test --reporter=json
```

### 结果解析

Playwright JSON 报告关键字段:

| 字段 | 说明 |
|------|------|
| `stats.expected` | 通过的测试数 |
| `stats.unexpected` | 失败的测试数 |
| `stats.flaky` | 重试后通过的测试数 |
| `stats.skipped` | 跳过的测试数 |

### 失败排查

```bash
# 查看 trace(失败时自动生成)
npx playwright show-trace <trace.zip路径>

# 打开 HTML 报告
npx playwright show-report
```

qa/test-strategy

skill/skills/qa/test-strategy/SKILL.md

测试策略和测试金字塔原则,定义单元测试、集成测试、E2E测试的分布和覆盖要求

Raw SKILL.md
---
name: qa/test-strategy
description: 测试策略和测试金字塔原则,定义单元测试、集成测试、E2E测试的分布和覆盖要求
version: 1.0.0
agent: qa
type: methodology
user-invocable: false
agent-invocable: true
dependencies:
  - shared/tech-stack-detection
triggers:
  - 开始测试工作时
  - 需要制定测试计划时
metadata:
  internal: true
---

# 测试策略与测试金字塔

## 测试金字塔原则

```
          /\
         /  \
        / E2E \          ← ~10%:端到端用户流程【必须编写】
       /--------\
      /  集成测试  \       ← ~20%:组件/服务/API 交互
     /--------------\
    /    单元测试     \    ← ~70%:函数/组件/服务逻辑
   /--------------------\
```

### E2E 测试是强制要求

**每个项目必须编写 E2E 测试**,最少覆盖:
- 创建流程
- 编辑流程
- 删除流程
- 列表展示
- 核心业务流程

### 前端 vs 后端测试分布

| 层级 | 前端测试 | 后端测试 |
|------|----------|----------|
| **单元测试** | 组件渲染、Hooks、工具函数 | Service 层、业务逻辑、工具类 |
| **集成测试** | 组件交互、状态管理、API 调用 | API 端点、数据库操作、服务间调用 |
| **E2E 测试** | UI 用户流程 | API 完整流程、跨服务调用 |

## QA Attack Protocol

- **重放核心用户路径**:证明核心用户路径真实可用
- **捕获真实 payload 与服务端响应**:验证请求 payload、服务端响应和 schema 一致性
- **攻击认证授权**:覆盖匿名、授权、非授权、过期、越权
- **攻击数据边界**:empty state、pagination、第二页、旧数据、illegal enum、long input、double submit
- **攻击业务一致性**:核对界面展示与服务端业务常量一致
- **验证产物类功能**:验证核心产物、记录或状态存在、可展示、可继续用于下游流程
- **标记未验证路径**:若核心用户路径只由 Mock 或桩数据证明,必须标记为未验证,不能作为发布证据

## 安全测试

| 测试类型 | 测试内容 | 示例 |
|----------|----------|------|
| **SQL 注入** | 参数化查询验证 | `' OR '1'='1` |
| **XSS** | 输出转义验证 | `<script>alert(1)</script>` |
| **CSRF** | Token 验证 | 跨站请求测试 |
| **认证** | Token 有效性 | 过期/伪造 Token |
| **授权** | 权限边界 | 越权访问测试 |
| **输入验证** | 边界值/格式 | 超长/特殊字符 |

## 性能测试

| 指标 | 前端目标 | 后端目标 |
|------|----------|----------|
| 首屏加载 | < 3s | - |
| API P50 | - | < 100ms |
| API P99 | - | < 500ms |
| 并发用户 | - | ≥ 100 |
| 内存泄漏 | 无 | 无 |

scrum-master/risk-assessment

skill/skills/scrum-master/risk-assessment/SKILL.md

风险评估方法,识别项目风险并制定应对策略

Raw SKILL.md
---
name: scrum-master/risk-assessment
description: 风险评估方法,识别项目风险并制定应对策略
version: 1.0.0
agent: scrum-master
type: methodology
user-invocable: false
agent-invocable: true
dependencies: []
triggers:
  - 需要评估项目风险时
  - 需要制定应对策略时
metadata:
  internal: true
---

# 风险评估方法

## 风险识别

| 风险类型 | 示例 |
|----------|------|
| 技术风险 | 新技术不熟悉、技术选型不当 |
| 资源风险 | 人员不足、时间紧张 |
| 需求风险 | 需求不明确、需求变更频繁 |
| 依赖风险 | 外部API不稳定、第三方服务延迟 |

## 风险评估矩阵

| 可能性 \ 影响 | 低 | 中 | 高 |
|---------------|----|----|-----|
| **高** | 中风险 | 高风险 | 高风险 |
| **中** | 低风险 | 中风险 | 高风险 |
| **低** | 低风险 | 低风险 | 中风险 |

## 应对策略

| 策略 | 说明 | 适用场景 |
|------|------|----------|
| 规避 | 改变计划避免风险 | 高风险且可避免 |
| 减轻 | 降低风险发生概率或影响 | 中高风险 |
| 转移 | 将风险转移给第三方 | 外部依赖风险 |
| 接受 | 接受风险并准备应对 | 低风险 |

scrum-master/task-breakdown

skill/skills/scrum-master/task-breakdown/SKILL.md

任务拆解方法,将需求拆解为可执行的开发任务

Raw SKILL.md
---
name: scrum-master/task-breakdown
description: 任务拆解方法,将需求拆解为可执行的开发任务
version: 1.0.0
agent: scrum-master
type: methodology
user-invocable: false
agent-invocable: true
dependencies: []
triggers:
  - 需要拆解开发任务时
  - 需要估算工作量时
metadata:
  internal: true
---

# 任务拆解方法

## WBS(工作分解结构)

将大任务拆解为小任务,遵循SMART原则:
- **Specific**:具体明确
- **Measurable**:可衡量
- **Achievable**:可实现
- **Relevant**:相关联
- **Time-bound**:有时限

## 拆解粒度

| 粒度 | 时长 | 适用场景 |
|------|------|----------|
| 小任务 | 2-4小时 | 单个功能点 |
| 中任务 | 1-2天 | 完整功能模块 |
| 大任务 | 3-5天 | 跨模块功能 |

**原则**:任务不超过2天,超过则继续拆分。

## 任务依赖

- **串行依赖**:B必须等A完成
- **并行任务**:A和B可同时进行
- **阻塞任务**:优先处理阻塞其他任务的任务

shared/tech-stack-detection

skill/skills/shared/tech-stack-detection/SKILL.md

检测项目技术栈的通用方法,通过分析配置文件识别语言、框架、工具链

Raw SKILL.md
---
name: shared/tech-stack-detection
description: 检测项目技术栈的通用方法,通过分析配置文件识别语言、框架、工具链
version: 1.0.0
agent: shared
type: methodology
user-invocable: false
agent-invocable: true
dependencies: []
triggers:
  - 需要了解项目技术栈时
  - 技术选型前需要检测现有技术时
  - 生成框架特定的代码或配置时
metadata:
  internal: true
---

# 技术栈检测方法

## 适用场景

在进行技术选型、架构设计、代码生成前,需要先了解项目当前使用的技术栈,以便:
- 遵循项目现有的技术选择
- 生成符合项目规范的代码
- 避免引入不兼容的技术

## 检测方法

### 1. 检测配置文件

使用 `Read` 或 `Glob` 工具检测项目根目录的配置文件:

#### JavaScript/TypeScript 生态

| 文件 | 说明 | 检测内容 |
|------|------|----------|
| `package.json` | Node.js 项目配置 | dependencies, devDependencies, scripts |
| `tsconfig.json` | TypeScript 配置 | 确认使用 TypeScript |
| `next.config.js` | Next.js 配置 | 确认使用 Next.js |
| `vite.config.js` | Vite 配置 | 确认使用 Vite |
| `nuxt.config.js` | Nuxt 配置 | 确认使用 Nuxt |

**检测命令**:
```bash
# 检测是否存在
ls package.json tsconfig.json next.config.js vite.config.js 2>/dev/null

# 读取 package.json
Read(file_path: "package.json")
```

**关键依赖识别**:
- `react`: React 项目
- `vue`: Vue 项目
- `next`: Next.js 项目
- `@angular/core`: Angular 项目
- `express`: Express 后端
- `fastify`: Fastify 后端
- `prisma`: Prisma ORM
- `typeorm`: TypeORM

#### Python 生态

| 文件 | 说明 | 检测内容 |
|------|------|----------|
| `requirements.txt` | pip 依赖 | 依赖列表 |
| `pyproject.toml` | Poetry/PDM 配置 | 依赖和项目配置 |
| `Pipfile` | Pipenv 配置 | 依赖 |
| `setup.py` | 包配置 | 项目元数据 |

**关键依赖识别**:
- `django`: Django 项目
- `flask`: Flask 项目
- `fastapi`: FastAPI 项目
- `sqlalchemy`: SQLAlchemy ORM
- `pytest`: 使用 pytest 测试

#### Go 生态

| 文件 | 说明 | 检测内容 |
|------|------|----------|
| `go.mod` | Go 模块配置 | 依赖和 Go 版本 |
| `go.sum` | 依赖校验和 | 确认依赖锁定 |

**关键依赖识别**:
- `github.com/gin-gonic/gin`: Gin 框架
- `github.com/gofiber/fiber`: Fiber 框架
- `gorm.io/gorm`: GORM ORM

#### Rust 生态

| 文件 | 说明 | 检测内容 |
|------|------|----------|
| `Cargo.toml` | Cargo 配置 | 依赖和项目配置 |
| `Cargo.lock` | 依赖锁定 | 确认依赖版本 |

**关键依赖识别**:
- `actix-web`: Actix Web 框架
- `axum`: Axum 框架
- `tokio`: 异步运行时

#### Java/Kotlin 生态

| 文件 | 说明 | 检测内容 |
|------|------|----------|
| `pom.xml` | Maven 配置 | 依赖和插件 |
| `build.gradle` | Gradle 配置 | 依赖和任务 |

**关键依赖识别**:
- `spring-boot-starter`: Spring Boot 项目
- `quarkus`: Quarkus 项目
- `micronaut`: Micronaut 项目

#### Ruby 生态

| 文件 | 说明 | 检测内容 |
|------|------|----------|
| `Gemfile` | Bundler 配置 | 依赖 |
| `Gemfile.lock` | 依赖锁定 | 确认依赖版本 |

**关键依赖识别**:
- `rails`: Ruby on Rails 项目
- `sinatra`: Sinatra 项目

### 2. 检测数据库配置

| 文件/目录 | 说明 |
|-----------|------|
| `prisma/schema.prisma` | Prisma 数据库配置 |
| `drizzle.config.ts` | Drizzle ORM 配置 |
| `ormconfig.json` | TypeORM 配置 |
| `alembic/` | Python Alembic 迁移 |
| `migrations/` | 数据库迁移目录 |

**数据库类型识别**:
- `postgresql://`: PostgreSQL
- `mysql://`: MySQL
- `mongodb://`: MongoDB
- `sqlite:`: SQLite
- `redis://`: Redis

### 3. 检测部署配置

| 文件 | 说明 |
|------|------|
| `Dockerfile` | Docker 容器化 |
| `docker-compose.yml` | Docker Compose 多容器 |
| `vercel.json` | Vercel 部署 |
| `.github/workflows/` | GitHub Actions CI/CD |
| `netlify.toml` | Netlify 部署 |
| `railway.json` | Railway 部署 |

### 4. 检测测试框架

#### JavaScript/TypeScript

| 文件/依赖 | 框架 |
|-----------|------|
| `jest.config.js` | Jest |
| `vitest.config.js` | Vitest |
| `playwright.config.js` | Playwright |
| `cypress.json` | Cypress |

#### Python

| 依赖 | 框架 |
|------|------|
| `pytest` | pytest |
| `unittest` | unittest (内置) |

#### Go

| 文件 | 框架 |
|------|------|
| `*_test.go` | Go 内置测试 |

## 检测流程

### 步骤1:检测项目类型

```bash
# 使用 Glob 查找配置文件
Glob(pattern: "{package.json,go.mod,Cargo.toml,pom.xml,requirements.txt,Gemfile}")
```

### 步骤2:读取配置文件

```bash
# 读取主配置文件
Read(file_path: "package.json")  # 或其他检测到的文件
```

### 步骤3:分析依赖

从配置文件中提取:
- **语言和版本**:如 Node.js 18, Python 3.11, Go 1.21
- **主框架**:如 Next.js 14, Django 5.0, Gin
- **数据库**:如 PostgreSQL, MongoDB
- **ORM**:如 Prisma, SQLAlchemy, GORM
- **测试框架**:如 Jest, pytest
- **构建工具**:如 Vite, Webpack, esbuild

### 步骤4:输出检测结果

以结构化格式输出:

```markdown
## 技术栈检测结果

### 语言和运行时
- **语言**:TypeScript
- **运行时**:Node.js 20.x
- **包管理器**:pnpm

### 前端框架
- **框架**:Next.js 14 (App Router)
- **UI 库**:React 18
- **样式**:Tailwind CSS
- **状态管理**:Zustand

### 后端框架
- **框架**:Next.js API Routes
- **ORM**:Prisma
- **数据库**:PostgreSQL

### 测试
- **单元测试**:Vitest
- **E2E 测试**:Playwright

### 部署
- **容器化**:Docker
- **CI/CD**:GitHub Actions
- **托管**:Vercel
```

## 使用示例

### 示例1:检测 Next.js 项目

```bash
# 1. 检测配置文件
Glob(pattern: "package.json")

# 2. 读取 package.json
Read(file_path: "package.json")

# 3. 分析依赖
# 发现: "next": "14.0.0", "react": "18.2.0", "prisma": "5.0.0"

# 4. 输出结果
技术栈:Next.js 14 + React 18 + Prisma + PostgreSQL
```

### 示例2:检测 Python 项目

```bash
# 1. 检测配置文件
Glob(pattern: "{requirements.txt,pyproject.toml}")

# 2. 读取配置
Read(file_path: "pyproject.toml")

# 3. 分析依赖
# 发现: fastapi, sqlalchemy, pytest

# 4. 输出结果
技术栈:FastAPI + SQLAlchemy + PostgreSQL + pytest
```

## 注意事项

1. **优先检测现有项目**:如果项目已存在配置文件,必须遵循现有技术栈
2. **新项目才选型**:只有在没有配置文件时,才进行技术选型
3. **版本兼容性**:注意依赖之间的版本兼容性
4. **生态一致性**:不要混用不同生态的工具(如 npm + poetry)

## 常见错误

❌ **不检测就假设**:直接假设项目使用某技术,而不检测配置文件
❌ **忽略版本**:只检测框架名称,不检测版本号
❌ **混淆生态**:在 Node.js 项目中推荐 Python 工具
❌ **重复检测**:在同一个任务中多次检测相同的配置文件

tech-lead/code-review

skill/skills/tech-lead/code-review/SKILL.md

代码审查方法,包含审查清单、常见问题、最佳实践

Raw SKILL.md
---
name: tech-lead/code-review
description: 代码审查方法,包含审查清单、常见问题、最佳实践
version: 1.0.0
agent: tech-lead
type: methodology
user-invocable: false
agent-invocable: true
dependencies:
  - shared/tech-stack-detection
triggers:
  - 需要审查代码时
  - 需要评估代码质量时
metadata:
  internal: true
---

# 代码审查方法

## 审查清单

### 功能正确性
- [ ] 代码实现符合需求
- [ ] 边界情况处理正确
- [ ] 错误处理完善

### 代码质量
- [ ] 命名清晰易懂
- [ ] 函数职责单一
- [ ] 避免重复代码
- [ ] 注释必要且准确

### 安全性
- [ ] 输入验证
- [ ] SQL注入防护
- [ ] XSS防护
- [ ] 认证授权正确

### 性能
- [ ] 无明显性能问题
- [ ] 数据库查询优化
- [ ] 避免N+1查询

### 可维护性
- [ ] 代码结构清晰
- [ ] 易于测试
- [ ] 遵循项目规范

tech-lead/technical-standards

skill/skills/tech-lead/technical-standards/SKILL.md

技术规范和最佳实践,确保代码质量和一致性

Raw SKILL.md
---
name: tech-lead/technical-standards
description: 技术规范和最佳实践,确保代码质量和一致性
version: 1.0.0
agent: tech-lead
type: guideline
user-invocable: false
agent-invocable: true
dependencies:
  - shared/tech-stack-detection
triggers:
  - 需要定义技术规范时
  - 需要统一代码风格时
metadata:
  internal: true
---

# 技术规范与最佳实践

## 命名规范

| 类型 | 规范 | 示例 |
|------|------|------|
| 变量 | camelCase | `userName`, `isActive` |
| 常量 | UPPER_SNAKE_CASE | `MAX_COUNT`, `API_URL` |
| 函数 | camelCase | `getUserById`, `calculateTotal` |
| 类 | PascalCase | `UserService`, `OrderController` |
| 文件 | kebab-case | `user-service.ts`, `order-controller.ts` |

## 代码组织

- **单一职责**:每个函数/类只做一件事
- **DRY原则**:不要重复代码
- **KISS原则**:保持简单
- **YAGNI原则**:不要过度设计

## 错误处理

- 使用try-catch捕获异常
- 提供有意义的错误信息
- 记录错误日志
- 优雅降级

## 测试要求

- 单元测试覆盖率 ≥ 70%
- 关键路径必须有测试
- 测试要独立、可重复

ui-designer/component-specification

skill/skills/ui-designer/component-specification/SKILL.md

UI组件规范,定义按钮、输入框、卡片等基础组件的变体、尺寸、状态

Raw SKILL.md
---
name: ui-designer/component-specification
description: UI组件规范,定义按钮、输入框、卡片等基础组件的变体、尺寸、状态
version: 1.0.0
agent: ui-designer
type: guideline
user-invocable: false
agent-invocable: true
dependencies:
  - ui-designer/design-system
triggers:
  - 需要设计组件时
  - 需要定义组件规范时
  - 前端开发需要组件文档时
metadata:
  internal: true
---

# UI组件规范

## 适用场景

基于设计系统,定义可复用的UI组件规范,确保组件在不同场景下的一致性和完整性。

## 组件设计原则

1. **完整性**:考虑所有状态(默认、悬停、按下、聚焦、禁用、加载、错误)
2. **一致性**:同类组件使用相同的设计语言
3. **可访问性**:支持键盘导航、屏幕阅读器
4. **响应式**:适配不同屏幕尺寸

## 基础组件规范

### 1. 按钮 (Button)

#### 变体

| 变体 | 用途 | 视觉特征 |
|------|------|----------|
| Primary | 主要操作(每个区域最多1个) | 实心,品牌色背景,白色文字 |
| Secondary | 次要操作 | 描边,透明背景,品牌色文字 |
| Ghost | 低优先级操作 | 无边框,透明背景,灰色文字 |
| Danger | 危险操作(删除、清空) | 实心,红色背景,白色文字 |
| Link | 文本链接 | 无背景,品牌色文字,下划线 |

#### 尺寸

| 尺寸 | 高度 | 内边距 | 字号 | 圆角 | 最小宽度 |
|------|------|--------|------|------|----------|
| sm | 32px | 12px 16px | 14px | 6px | 64px |
| md | 40px | 12px 20px | 16px | 8px | 80px |
| lg | 48px | 16px 24px | 16px | 8px | 96px |

#### 状态

| 状态 | Primary 背景 | Primary 文字 | 边框 | 其他 |
|------|--------------|--------------|------|------|
| 默认 | `Primary` | `White` | - | - |
| 悬停 | `Primary-hover` | `White` | - | cursor: pointer |
| 按下 | `Primary-active` | `White` | - | transform: scale(0.98) |
| 聚焦 | `Primary` | `White` | 2px Primary 外发光 | outline |
| 禁用 | `Gray-200` | `Gray-400` | - | cursor: not-allowed, opacity: 0.6 |
| 加载 | `Primary` | - | - | 显示 spinner,文字隐藏 |

#### 图标按钮

| 属性 | 值 |
|------|-----|
| 尺寸 | 32px / 40px / 48px(正方形) |
| 图标大小 | 16px / 20px / 24px |
| 圆角 | radius-md 或 radius-full(圆形) |

#### 代码示例

```tsx
// 主按钮
<Button variant="primary" size="md">确认</Button>

// 次要按钮
<Button variant="secondary" size="md">取消</Button>

// 危险按钮
<Button variant="danger" size="md">删除</Button>

// 禁用状态
<Button variant="primary" size="md" disabled>确认</Button>

// 加载状态
<Button variant="primary" size="md" loading>提交中</Button>

// 带图标
<Button variant="primary" size="md" icon={<IconCheck />}>保存</Button>

// 图标按钮
<IconButton variant="ghost" size="md" icon={<IconClose />} />
```

### 2. 输入框 (Input)

#### 尺寸

| 尺寸 | 高度 | 内边距 | 字号 | 圆角 |
|------|------|--------|------|------|
| sm | 32px | 8px 12px | 14px | 6px |
| md | 40px | 10px 14px | 16px | 8px |
| lg | 48px | 12px 16px | 16px | 8px |

#### 状态

| 状态 | 边框颜色 | 背景色 | 其他 |
|------|----------|--------|------|
| 默认 | `Gray-300` | `White` | - |
| 悬停 | `Gray-400` | `White` | - |
| 聚焦 | `Primary` | `White` | 2px Primary 外发光 |
| 错误 | `Error` | `White` | 显示错误提示 |
| 禁用 | `Gray-200` | `Gray-50` | cursor: not-allowed |
| 只读 | `Gray-200` | `Gray-50` | - |

#### 组成部分

```
┌─────────────────────────────────────────┐
│ [图标]  [输入内容]            [清除按钮] │
└─────────────────────────────────────────┘
  前缀      输入区域               后缀
```

- **前缀**:图标、文字(如"https://")
- **输入区域**:用户输入的内容
- **后缀**:清除按钮、单位(如"元")、操作按钮

#### 变体

| 变体 | 说明 |
|------|------|
| Text | 单行文本输入 |
| Textarea | 多行文本输入 |
| Password | 密码输入(带显示/隐藏切换) |
| Number | 数字输入(带增减按钮) |
| Search | 搜索输入(带搜索图标和清除按钮) |

#### 代码示例

```tsx
// 基础输入框
<Input placeholder="请输入用户名" />

// 带标签
<Input label="用户名" placeholder="请输入用户名" />

// 带前缀图标
<Input prefix={<IconUser />} placeholder="请输入用户名" />

// 带后缀清除按钮
<Input clearable placeholder="请输入关键词" />

// 错误状态
<Input error="用户名不能为空" />

// 禁用状态
<Input disabled value="已禁用" />

// 多行文本
<Textarea rows={4} placeholder="请输入描述" />

// 密码输入
<Input type="password" placeholder="请输入密码" />

// 搜索输入
<Input type="search" placeholder="搜索..." />
```

### 3. 选择器 (Select)

#### 尺寸

与Input保持一致(sm / md / lg)

#### 状态

与Input保持一致

#### 下拉菜单

| 属性 | 值 |
|------|-----|
| 最大高度 | 256px(超出滚动) |
| 背景 | `White` |
| 阴影 | `shadow-lg` |
| 圆角 | `radius-md` |
| 选项高度 | 40px |
| 选项内边距 | 10px 14px |

#### 选项状态

| 状态 | 背景色 | 文字颜色 |
|------|--------|----------|
| 默认 | `White` | `Gray-700` |
| 悬停 | `Gray-50` | `Gray-900` |
| 选中 | `Primary-light` | `Primary` |
| 禁用 | `White` | `Gray-400` |

### 4. 复选框 (Checkbox)

#### 尺寸

| 尺寸 | 大小 | 勾选图标 |
|------|------|----------|
| sm | 16px | 12px |
| md | 20px | 14px |
| lg | 24px | 16px |

#### 状态

| 状态 | 边框 | 背景 | 勾选图标 |
|------|------|------|----------|
| 未选中 | `Gray-300` | `White` | - |
| 选中 | `Primary` | `Primary` | `White` |
| 半选中 | `Primary` | `Primary` | `White`(横线) |
| 禁用-未选中 | `Gray-200` | `Gray-50` | - |
| 禁用-选中 | `Gray-300` | `Gray-300` | `White` |

### 5. 单选框 (Radio)

#### 尺寸

与Checkbox保持一致

#### 状态

| 状态 | 边框 | 背景 | 内圆 |
|------|------|------|------|
| 未选中 | `Gray-300` | `White` | - |
| 选中 | `Primary` | `White` | `Primary`(8px圆点) |
| 禁用-未选中 | `Gray-200` | `Gray-50` | - |
| 禁用-选中 | `Gray-300` | `Gray-50` | `Gray-300` |

### 6. 开关 (Switch)

#### 尺寸

| 尺寸 | 宽度 | 高度 | 圆点大小 |
|------|------|------|----------|
| sm | 32px | 18px | 14px |
| md | 44px | 24px | 20px |
| lg | 56px | 30px | 26px |

#### 状态

| 状态 | 背景 | 圆点位置 |
|------|------|----------|
| 关闭 | `Gray-300` | 左侧 |
| 开启 | `Primary` | 右侧 |
| 禁用-关闭 | `Gray-200` | 左侧 |
| 禁用-开启 | `Primary`(opacity: 0.5) | 右侧 |

### 7. 卡片 (Card)

#### 规格

| 属性 | 值 |
|------|-----|
| 背景 | `White` |
| 圆角 | `radius-lg` (12px) |
| 阴影 | `shadow-md` |
| 内边距 | `space-6` (24px) |
| 边框 | 可选,1px `Gray-200` |

#### 变体

| 变体 | 特征 | 用途 |
|------|------|------|
| 默认 | 阴影 | 普通内容卡片 |
| 描边 | 1px Gray-200 边框,无阴影 | 表单区域 |
| 可点击 | hover 时阴影加深,cursor: pointer | 列表项、导航卡片 |
| 可选中 | 选中时边框变为 Primary | 选择卡片 |

#### 组成部分

```
┌─────────────────────────────────────┐
│  [图片/图标]                         │
│                                     │
│  标题                                │
│  描述文字                            │
│                                     │
│  [操作按钮]                          │
└─────────────────────────────────────┘
```

### 8. 标签 (Tag)

#### 尺寸

| 尺寸 | 高度 | 内边距 | 字号 |
|------|------|--------|------|
| sm | 20px | 4px 8px | 12px |
| md | 24px | 6px 10px | 14px |
| lg | 28px | 8px 12px | 14px |

#### 变体

| 变体 | 背景 | 文字 | 边框 |
|------|------|------|------|
| 默认 | `Gray-100` | `Gray-700` | - |
| Primary | `Primary-light` | `Primary` | - |
| Success | `Success-light` | `Success` | - |
| Warning | `Warning-light` | `Warning` | - |
| Error | `Error-light` | `Error` | - |
| 描边 | `White` | `Gray-700` | 1px `Gray-300` |

### 9. 徽章 (Badge)

#### 尺寸

| 尺寸 | 大小 | 字号 |
|------|------|------|
| sm | 16px | 10px |
| md | 20px | 12px |
| lg | 24px | 14px |

#### 变体

| 变体 | 背景 | 文字 |
|------|------|------|
| Primary | `Primary` | `White` |
| Success | `Success` | `White` |
| Warning | `Warning` | `White` |
| Error | `Error` | `White` |
| 圆点 | 纯色圆点,无文字 | - |

### 10. 提示框 (Tooltip)

#### 规格

| 属性 | 值 |
|------|-----|
| 背景 | `Gray-900` |
| 文字 | `White` |
| 字号 | 14px |
| 内边距 | 6px 12px |
| 圆角 | `radius-md` |
| 最大宽度 | 320px |
| 箭头大小 | 6px |

#### 位置

- top / bottom / left / right
- 自动调整位置避免溢出

## 输出要求

在UI设计文档中,应包含以下组件规范章节:

```markdown
## 5. 组件规范

### 5.1 按钮 (Button)
[变体、尺寸、状态表格 + 代码示例]

### 5.2 输入框 (Input)
[尺寸、状态、变体表格 + 代码示例]

### 5.3 [其他组件...]
[根据具体需求补充]
```

## 关键原则

1. **状态完整**:每个组件都要考虑所有状态
2. **一致性**:同类组件使用相同的设计语言
3. **可访问性**:支持键盘导航、屏幕阅读器
4. **文档化**:提供清晰的代码示例

## 常见误区

❌ **状态不全**:只设计默认状态,忽略悬停、禁用等
❌ **尺寸不统一**:不同组件的尺寸不对齐
❌ **缺少文档**:只有视觉稿,没有规范说明
❌ **不考虑边界**:没有考虑长文本、空状态等边界情况

ui-designer/design-system

skill/skills/ui-designer/design-system/SKILL.md

设计系统规范,包含颜色、字体、间距、圆角、阴影、动效等基础设计token

Raw SKILL.md
---
name: ui-designer/design-system
description: 设计系统规范,包含颜色、字体、间距、圆角、阴影、动效等基础设计token
version: 1.0.0
agent: ui-designer
type: guideline
user-invocable: false
agent-invocable: true
dependencies: []
triggers:
  - 开始UI设计时
  - 需要定义视觉规范时
  - 确保设计一致性时
metadata:
  internal: true
---

# 设计系统规范

## 适用场景

在开始具体的页面和组件设计前,需要先建立统一的设计系统,确保整个产品的视觉和交互一致性。

## 设计系统的价值

1. **一致性**:确保产品各部分视觉和交互统一
2. **效率**:设计师和开发者使用统一的设计语言,减少沟通成本
3. **可维护性**:修改设计token即可全局更新
4. **可扩展性**:新功能可以快速复用现有组件

## 设计系统组成

### 1. 颜色系统

#### 品牌色

| 名称 | 色值 | 用途 | 示例场景 |
|------|------|------|----------|
| Primary | `#3B82F6` | 主要操作、强调 | 主按钮、链接、选中状态 |
| Primary-hover | `#2563EB` | 主色悬停态 | 按钮悬停 |
| Primary-active | `#1D4ED8` | 主色按下态 | 按钮按下 |
| Primary-light | `#DBEAFE` | 主色浅色背景 | 标签背景、高亮区域 |

#### 中性色

| 名称 | 色值 | 用途 |
|------|------|------|
| Gray-900 | `#111827` | 标题文字 |
| Gray-800 | `#1F2937` | 重要文字 |
| Gray-700 | `#374151` | 正文文字 |
| Gray-600 | `#4B5563` | 次要文字 |
| Gray-500 | `#6B7280` | 辅助文字 |
| Gray-400 | `#9CA3AF` | 占位文字 |
| Gray-300 | `#D1D5DB` | 边框、分割线 |
| Gray-200 | `#E5E7EB` | 浅边框 |
| Gray-100 | `#F3F4F6` | 背景 |
| Gray-50 | `#F9FAFB` | 浅背景 |
| White | `#FFFFFF` | 卡片背景、主背景 |

#### 语义色

| 名称 | 色值 | 用途 | 背景色 |
|------|------|------|--------|
| Success | `#10B981` | 成功状态 | `#D1FAE5` |
| Warning | `#F59E0B` | 警告状态 | `#FEF3C7` |
| Error | `#EF4444` | 错误状态 | `#FEE2E2` |
| Info | `#3B82F6` | 信息提示 | `#DBEAFE` |

**颜色使用原则**:
- 主色用于主要操作和强调,不要滥用
- 中性色用于文字和背景,建立清晰的层次
- 语义色用于状态反馈,保持一致性
- 确保颜色对比度符合WCAG AA标准(≥4.5:1)

### 2. 字体系统

#### 字体家族

```css
/* 无衬线字体(主要) */
--font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, 
             "Helvetica Neue", Arial, "Noto Sans", sans-serif;

/* 等宽字体(代码) */
--font-mono: "SF Mono", Monaco, "Cascadia Code", "Courier New", monospace;
```

#### 字体层级

| 层级 | 字号 | 行高 | 字重 | 用途 | CSS 变量 |
|------|------|------|------|------|----------|
| Display | 48px | 1.1 | 700 | 大标题、落地页 | `--text-display` |
| H1 | 32px | 1.2 | 700 | 页面标题 | `--text-h1` |
| H2 | 24px | 1.3 | 600 | 区块标题 | `--text-h2` |
| H3 | 20px | 1.4 | 600 | 小标题 | `--text-h3` |
| H4 | 18px | 1.4 | 600 | 卡片标题 | `--text-h4` |
| Body | 16px | 1.5 | 400 | 正文 | `--text-body` |
| Body-sm | 14px | 1.5 | 400 | 辅助文字 | `--text-body-sm` |
| Caption | 12px | 1.4 | 400 | 说明文字、标签 | `--text-caption` |

**字体使用原则**:
- 标题使用较大字号和较重字重,建立层次
- 正文使用16px,确保可读性
- 行高保持1.4-1.6,确保舒适阅读
- 不要使用过多字号,保持简洁

### 3. 间距系统

基础单位:**4px**(所有间距都是4的倍数)

| 名称 | 值 | 用途 | CSS 变量 |
|------|-----|------|----------|
| space-0 | 0 | 无间距 | `--space-0` |
| space-1 | 4px | 紧凑元素间(图标与文字) | `--space-1` |
| space-2 | 8px | 相关元素间(标签与输入框) | `--space-2` |
| space-3 | 12px | 组内元素间 | `--space-3` |
| space-4 | 16px | 默认间距 | `--space-4` |
| space-5 | 20px | 组间间距 | `--space-5` |
| space-6 | 24px | 区块内间距 | `--space-6` |
| space-8 | 32px | 区块间间距 | `--space-8` |
| space-10 | 40px | 大区块间距 | `--space-10` |
| space-12 | 48px | 页面级间距 | `--space-12` |
| space-16 | 64px | 超大间距 | `--space-16` |

**间距使用原则**:
- 相关元素间距小,不相关元素间距大
- 使用统一的间距系统,不要随意使用其他值
- 移动端可以适当减小间距

### 4. 圆角系统

| 名称 | 值 | 用途 | CSS 变量 |
|------|-----|------|----------|
| radius-none | 0 | 无圆角 | `--radius-none` |
| radius-sm | 4px | 小元素(标签、徽章) | `--radius-sm` |
| radius-md | 8px | 按钮、输入框 | `--radius-md` |
| radius-lg | 12px | 卡片 | `--radius-lg` |
| radius-xl | 16px | 大卡片、弹窗 | `--radius-xl` |
| radius-2xl | 24px | 超大卡片 | `--radius-2xl` |
| radius-full | 9999px | 圆形、胶囊按钮 | `--radius-full` |

**圆角使用原则**:
- 圆角让界面更友好,但不要过度
- 保持一致性,同类元素使用相同圆角
- 移动端可以使用稍大的圆角

### 5. 阴影系统

| 名称 | 值 | 用途 | CSS 变量 |
|------|-----|------|----------|
| shadow-xs | `0 1px 2px rgba(0,0,0,0.05)` | 微小浮起 | `--shadow-xs` |
| shadow-sm | `0 1px 3px rgba(0,0,0,0.1)` | 轻微浮起 | `--shadow-sm` |
| shadow-md | `0 4px 6px rgba(0,0,0,0.1)` | 卡片 | `--shadow-md` |
| shadow-lg | `0 10px 15px rgba(0,0,0,0.1)` | 弹窗、下拉菜单 | `--shadow-lg` |
| shadow-xl | `0 20px 25px rgba(0,0,0,0.15)` | 模态框 | `--shadow-xl` |
| shadow-2xl | `0 25px 50px rgba(0,0,0,0.25)` | 大型模态框 | `--shadow-2xl` |

**阴影使用原则**:
- 阴影表示层级,越重要的元素阴影越深
- 不要过度使用阴影,保持克制
- 悬停时可以加深阴影,表示可交互

### 6. 动效系统

#### 时长

| 名称 | 值 | 用途 |
|------|-----|------|
| duration-fast | 150ms | 微交互(hover、focus) |
| duration-normal | 250ms | 状态切换、展开收起 |
| duration-slow | 350ms | 页面过渡、大型动画 |

#### 缓动函数

| 名称 | 值 | 用途 |
|------|-----|------|
| ease-out | `cubic-bezier(0, 0, 0.2, 1)` | 元素进入(淡入、展开) |
| ease-in | `cubic-bezier(0.4, 0, 1, 1)` | 元素退出(淡出、收起) |
| ease-in-out | `cubic-bezier(0.4, 0, 0.2, 1)` | 状态切换 |

#### CSS 变量

```css
--transition-fast: 150ms cubic-bezier(0, 0, 0.2, 1);
--transition-normal: 250ms cubic-bezier(0.4, 0, 0.2, 1);
--transition-slow: 350ms cubic-bezier(0.4, 0, 0.2, 1);
```

**动效使用原则**:
- 动效要有意义,不要为了炫技
- 保持克制,不要过度动画
- 微交互要快(150ms),大动画可以慢(350ms)
- 使用合适的缓动函数,让动画更自然

### 7. 断点系统(响应式)

| 断点 | 值 | 设备 | 容器宽度 |
|------|-----|------|----------|
| xs | < 640px | 手机 | 100% |
| sm | ≥ 640px | 大手机 | 640px |
| md | ≥ 768px | 平板 | 768px |
| lg | ≥ 1024px | 小桌面 | 1024px |
| xl | ≥ 1280px | 桌面 | 1280px |
| 2xl | ≥ 1536px | 大桌面 | 1536px |

**响应式设计原则**:
- 移动优先(Mobile First)
- 关键内容在所有设备上都可见
- 移动端简化操作,桌面端提供更多功能
- 触控目标在移动端至少44x44px

## 输出要求

在UI设计文档中,应包含以下设计系统章节:

```markdown
## 4. 设计系统

### 4.1 颜色系统
[品牌色、中性色、语义色表格]

### 4.2 字体系统
[字体家族、字体层级表格]

### 4.3 间距系统
[间距表格]

### 4.4 圆角系统
[圆角表格]

### 4.5 阴影系统
[阴影表格]

### 4.6 动效系统
[时长、缓动函数表格]
```

## 关键原则

1. **一致性**:所有设计都使用统一的design token
2. **可扩展性**:新功能可以快速复用现有规范
3. **可维护性**:修改token即可全局更新
4. **克制**:不要定义过多变体,保持简洁

## 常见误区

❌ **随意使用颜色**:不使用定义的颜色,随意添加新颜色
❌ **间距不统一**:使用5px、7px等非4倍数的间距
❌ **字号过多**:定义10种以上的字号
❌ **过度动画**:所有元素都加动画,影响性能和体验

ui-designer/design-variants

skill/skills/ui-designer/design-variants/SKILL.md

设计变体模式,产出2-3个设计方案及 tradeoff 分析,供用户选择后确定最终方案

Raw SKILL.md
---
name: ui-designer/design-variants
description: 设计变体模式,产出2-3个设计方案及 tradeoff 分析,供用户选择后确定最终方案
version: 1.0.0
agent: ui-designer
type: workflow
user-invocable: false
agent-invocable: true
dependencies:
  - ui-designer/design-system
triggers:
  - PRD 中明确要求提供多个设计方案对比时
  - 用户显式要求"给几个方案选"或"设计变体"时
  - 设计方向存在明显分歧需要决策时
metadata:
  internal: true
---

# 设计变体模式

## 适用场景

当设计方向不确定、存在多种合理方案、或用户希望看到不同风格的对比时,启用变体模式。
**不建议在简单功能或设计方向明确时使用**——避免决策疲劳。

## 核心方法

### 步骤 1:变体策略确定

分析 PRD 后确定变体差异维度。常见维度组合:

| 策略 | 维度 | 适用场景 |
|------|------|----------|
| 风格变体 | 简约 vs 丰富 vs 极简 | 品牌/调性不确定 |
| 布局变体 | 单栏 vs 双栏 vs 卡片 | 内容组织方式不确定 |
| 交互变体 | 步骤式 vs 单页式 vs 对话式 | 用户流程不确定 |
| 复杂度变体 | MVP vs 标准 vs 豪华 | 功能范围不确定 |

**原则:每个变体应该有清晰的设计理念差异,而非仅仅是颜色/字体的不同。**

### 步骤 2:变体设计

为每个变体(2-3个)产出:

1. **设计理念**:一句话说明这个方案的核心思路
2. **视觉方案**:基于 design-system 的具体实现
3. **组件选择**:使用哪些组件、如何组合
4. **交互流程**:用户的操作路径
5. **Tradeoff 分析**:优势和劣势

### 步骤 3:对比矩阵

生成结构化对比,帮助用户快速决策:

| 维度 | 方案 A | 方案 B | 方案 C |
|------|--------|--------|--------|
| 视觉复杂度 | 高/中/低 | - | - |
| 开发成本 | X 天 | - | - |
| 用户学习曲线 | 陡/平/无 | - | - |
| 可扩展性 | 高/中/低 | - | - |
| 品牌一致性 | 高/中/低 | - | - |
| 移动端适配 | 优/良/差 | - | - |

### 步骤 4:推荐与等待

1. 给出推荐方案及推荐理由
2. 将变体输出到 `.boss/<feature>/ui-design-variants.json`
3. 设置状态为 `NEEDS_CONTEXT`,等待用户选择
4. 用户选择后:
   - 记录选择(供跨项目偏好聚合,走事件流、可重放):
     ```bash
     boss runtime record-user-choice <feature> --choice-type design-variant \
       --selected "<选中方案>" --options "<方案A,方案B,方案C>" --reason "<用户理由>"
     ```
   - 将选中方案写入正式的 `ui-design.json` 和 `ui-spec.md`

## 输出要求

### JSON 产物格式

输出到 `.boss/<feature>/ui-design-variants.json`:

```json
{
  "schemaVersion": "1.0.0",
  "artifact": "ui-design-variants",
  "feature": "<feature-name>",
  "updatedAt": "<ISO-8601>",
  "strategy": "风格变体|布局变体|交互变体|复杂度变体",
  "variants": [
    {
      "variantId": "A",
      "name": "方案A: [名称]",
      "concept": "[一句话设计理念]",
      "tradeoffs": {
        "pros": ["优势1", "优势2", "优势3"],
        "cons": ["劣势1", "劣势2"]
      },
      "designData": {
        "mode": "wireframe",
        "pages": [],
        "components": [],
        "prototype": {},
        "implementationHints": {}
      }
    }
  ],
  "comparison": {
    "dimensions": ["视觉复杂度", "开发成本", "用户学习曲线", "可扩展性", "品牌一致性", "移动端适配"],
    "matrix": [
      {"dimension": "视觉复杂度", "A": "中", "B": "低", "C": "高"}
    ]
  },
  "recommendation": {
    "variantId": "A",
    "reason": "[推荐理由]"
  },
  "selectedVariantId": null
}
```

### 状态报告

```bash
boss runtime report-agent-status <feature> <stage> boss-ui-designer NEEDS_CONTEXT \
  --reason "已产出 N 个设计变体,等待用户选择最终方案(方案A/B/C)"
```

### 用户选择后的行为

收到用户选择后:
1. 更新 `ui-design-variants.json` 的 `selectedVariantId` 字段
2. 将选中方案的 `designData` 写入正式 `ui-design.json`
3. 基于选中方案生成完整的 `ui-spec.md`
4. 报告 `DONE` 状态

ui-designer/interaction-specification

skill/skills/ui-designer/interaction-specification/SKILL.md

交互规范,定义加载状态、空状态、反馈机制、动效、无障碍等交互细节

Raw SKILL.md
---
name: ui-designer/interaction-specification
description: 交互规范,定义加载状态、空状态、反馈机制、动效、无障碍等交互细节
version: 1.0.0
agent: ui-designer
type: guideline
user-invocable: false
agent-invocable: true
dependencies:
  - ui-designer/design-system
triggers:
  - 需要定义交互行为时
  - 需要处理边界情况时
  - 需要确保无障碍访问时
metadata:
  internal: true
---

# 交互规范

## 适用场景

定义用户与界面交互的细节,包括加载状态、空状态、反馈机制、动效、无障碍等,确保交互流畅、友好、可访问。

## 交互设计原则

1. **及时反馈**:用户操作后立即给予反馈
2. **清晰引导**:明确告诉用户下一步该做什么
3. **容错性**:允许用户撤销、修改操作
4. **一致性**:相同操作在不同场景下行为一致
5. **可访问性**:支持键盘、屏幕阅读器等辅助技术

## 交互规范

### 1. 加载状态

#### 加载场景

| 场景 | 处理方式 | 时机 | 视觉表现 |
|------|----------|------|----------|
| 页面首次加载 | 骨架屏 | 首次进入页面 | 灰色占位块,模拟内容结构 |
| 页面刷新 | 顶部进度条 | 刷新页面 | 蓝色进度条,从左到右 |
| 按钮提交 | 按钮内 spinner | 点击提交按钮后 | 按钮内显示旋转图标,文字隐藏 |
| 列表加载更多 | 底部 spinner | 滚动到底部 | 底部显示"加载中..." |
| 局部刷新 | 区域内 spinner | 刷新某个区域 | 区域内显示旋转图标 |
| 搜索 | 输入框内 spinner | 输入后延迟搜索 | 输入框右侧显示旋转图标 |

#### 骨架屏设计

```
┌─────────────────────────────────────┐
│  ████████                            │  ← 标题占位
│  ████████████                        │  ← 描述占位
│                                     │
│  ████  ████████████████              │  ← 列表项占位
│  ████  ████████████████              │
│  ████  ████████████████              │
└─────────────────────────────────────┘
```

**骨架屏原则**:
- 模拟真实内容的结构和布局
- 使用灰色占位块(Gray-200)
- 添加微妙的动画(shimmer效果)
- 不要显示真实数据的占位符

#### Spinner设计

| 尺寸 | 大小 | 线宽 | 用途 |
|------|------|------|------|
| sm | 16px | 2px | 按钮内、输入框内 |
| md | 24px | 2.5px | 卡片内、区域内 |
| lg | 32px | 3px | 页面级加载 |

**颜色**:
- 主色(Primary):主要操作的加载
- 灰色(Gray-400):次要操作的加载
- 白色(White):深色背景上的加载

### 2. 空状态

#### 空状态场景

| 场景 | 展示内容 | 操作引导 |
|------|----------|----------|
| 无数据 | 插图 + "暂无数据" | "创建第一个项目" 按钮 |
| 搜索无结果 | 插图 + "未找到相关内容" | "尝试其他关键词" 提示 |
| 网络错误 | 插图 + "网络连接失败" | "重试" 按钮 |
| 权限不足 | 插图 + "无权访问" | "返回首页" 按钮 |
| 404页面 | 插图 + "页面不存在" | "返回首页" 按钮 |

#### 空状态设计

```
┌─────────────────────────────────────┐
│                                     │
│           [插图/图标]                │
│                                     │
│           暂无数据                   │
│      您还没有创建任何项目            │
│                                     │
│        [创建项目] 按钮               │
│                                     │
└─────────────────────────────────────┘
```

**空状态原则**:
- 使用友好的插图或图标
- 说明为什么是空的
- 提供明确的操作引导
- 不要让用户感到困惑或沮丧

### 3. 反馈机制

#### Toast通知

| 类型 | 颜色 | 图标 | 持续时间 | 位置 |
|------|------|------|----------|------|
| Success | `Success` | ✓ | 3秒 | 顶部居中 |
| Warning | `Warning` | ⚠ | 4秒 | 顶部居中 |
| Error | `Error` | ✕ | 5秒 | 顶部居中 |
| Info | `Info` | ℹ | 3秒 | 顶部居中 |

**Toast设计**:
```
┌─────────────────────────────────────┐
│  [图标]  操作成功                    │
└─────────────────────────────────────┘
```

- 背景:对应语义色
- 文字:白色
- 圆角:radius-md
- 阴影:shadow-lg
- 最大宽度:400px
- 可手动关闭(右侧×按钮)

#### Modal确认框

| 类型 | 用途 | 按钮 |
|------|------|------|
| 确认 | 危险操作(删除、清空) | "取消" + "确认" |
| 警告 | 重要提示 | "我知道了" |
| 信息 | 详细说明 | "关闭" |

**Modal设计**:
```
┌─────────────────────────────────────┐
│  标题                          [×]   │
├─────────────────────────────────────┤
│                                     │
│  内容区域                            │
│                                     │
├─────────────────────────────────────┤
│              [取消]  [确认]          │
└─────────────────────────────────────┘
```

- 背景:White
- 圆角:radius-xl
- 阴影:shadow-2xl
- 最大宽度:480px
- 遮罩:rgba(0,0,0,0.5)

#### 表单验证

| 时机 | 验证方式 | 反馈位置 |
|------|----------|----------|
| 输入时 | 实时验证(延迟300ms) | 输入框下方 |
| 失焦时 | 立即验证 | 输入框下方 |
| 提交时 | 全部验证 | 输入框下方 + Toast |

**错误提示**:
- 颜色:Error
- 字号:14px
- 图标:✕
- 位置:输入框下方,space-2间距

### 4. 动效规范

#### 页面过渡

| 场景 | 动效 | 参数 |
|------|------|------|
| 页面进入 | 淡入 | 300ms ease-out, opacity 0→1 |
| 页面退出 | 淡出 | 200ms ease-in, opacity 1→0 |
| 路由切换 | 淡入淡出 | 250ms ease-in-out |

#### 弹窗动效

| 场景 | 动效 | 参数 |
|------|------|------|
| Modal出现 | 淡入 + 缩放 | 250ms ease-out, scale 0.95→1, opacity 0→1 |
| Modal消失 | 淡出 + 缩放 | 200ms ease-in, scale 1→0.95, opacity 1→0 |
| Drawer出现 | 滑入 | 300ms ease-out, translateX -100%→0 |
| Drawer消失 | 滑出 | 250ms ease-in, translateX 0→-100% |

#### 微交互

| 场景 | 动效 | 参数 |
|------|------|------|
| 按钮悬停 | 背景色渐变 | 150ms ease-out |
| 按钮按下 | 缩放 | 100ms ease-out, scale 0.98 |
| 卡片悬停 | 阴影加深 | 200ms ease-out |
| 展开收起 | 高度动画 | 250ms ease-in-out |
| 淡入淡出 | 透明度 | 200ms ease-in-out |

**动效原则**:
- 动效要有意义,不要为了炫技
- 保持克制,不要过度动画
- 微交互要快(150ms),大动画可以慢(300ms)
- 提供关闭动画的选项(尊重用户偏好)

### 5. 无障碍设计

#### 颜色对比度

| 组合 | 对比度 | 是否合规(WCAG AA) |
|------|--------|---------------------|
| Gray-900 / White | 16.1:1 | ✅ |
| Gray-700 / White | 9.5:1 | ✅ |
| Gray-500 / White | 4.6:1 | ✅ |
| Primary / White | 需计算 | 需≥4.5:1 |

**对比度要求**:
- 正文文字:≥4.5:1(WCAG AA)
- 大文字(18px+):≥3:1(WCAG AA)
- 图标、UI组件:≥3:1

#### 键盘导航

| 按键 | 功能 |
|------|------|
| Tab | 移动到下一个可聚焦元素 |
| Shift + Tab | 移动到上一个可聚焦元素 |
| Enter | 激活按钮、链接、提交表单 |
| Space | 切换复选框、单选框、开关 |
| Escape | 关闭弹窗、下拉菜单、取消操作 |
| 方向键 | 在列表、菜单、选项卡中导航 |
| Home / End | 跳到列表开头/结尾 |

**聚焦指示**:
- 所有可交互元素必须有明显的聚焦状态
- 聚焦样式:2px Primary 外发光
- 不要移除默认的 outline

#### 屏幕阅读器

| 元素 | ARIA 属性 | 说明 |
|------|-----------|------|
| 按钮 | `aria-label` | 图标按钮必须有文字说明 |
| 输入框 | `aria-label` 或关联 `<label>` | 说明输入框用途 |
| 加载状态 | `aria-busy="true"` | 告知正在加载 |
| 错误提示 | `aria-live="polite"` | 实时播报错误 |
| 弹窗 | `role="dialog"`, `aria-modal="true"` | 标识为对话框 |
| 导航 | `role="navigation"`, `aria-label` | 标识导航区域 |

#### 触控目标

| 设备 | 最小尺寸 | 推荐尺寸 |
|------|----------|----------|
| 移动端 | 44x44px | 48x48px |
| 桌面端 | 32x32px | 40x40px |

**触控原则**:
- 按钮、链接等可点击元素要足够大
- 相邻元素之间要有足够间距(至少8px)
- 移动端优先考虑拇指可达区域

### 6. 响应式交互

#### 断点调整

| 断点 | 交互调整 |
|------|----------|
| < 640px (mobile) | 全屏弹窗、底部抽屉、大触控目标 |
| 640-1024px (tablet) | 侧边抽屉、适中触控目标 |
| > 1024px (desktop) | 居中弹窗、悬停效果、小触控目标 |

#### 移动端特殊交互

| 交互 | 说明 |
|------|------|
| 下拉刷新 | 列表顶部下拉触发刷新 |
| 滑动删除 | 列表项左滑显示删除按钮 |
| 长按 | 长按触发上下文菜单 |
| 双击 | 双击放大图片 |
| 捏合缩放 | 图片、地图支持捏合缩放 |

## 输出要求

在UI设计文档中,应包含以下交互规范章节:

```markdown
## 7. 交互规范

### 7.1 加载状态
[加载场景表格]

### 7.2 空状态
[空状态场景表格]

### 7.3 反馈机制
[Toast、Modal、表单验证规范]

### 7.4 动效规范
[页面过渡、弹窗动效、微交互表格]

### 7.5 无障碍设计
[颜色对比度、键盘导航、屏幕阅读器、触控目标]
```

## 关键原则

1. **及时反馈**:用户操作后立即给予反馈
2. **清晰引导**:明确告诉用户下一步该做什么
3. **容错性**:允许用户撤销、修改操作
4. **可访问性**:支持键盘、屏幕阅读器等辅助技术

## 常见误区

❌ **无加载提示**:操作后没有任何反馈,用户不知道是否成功
❌ **空状态不友好**:只显示"无数据",没有引导用户下一步
❌ **过度动画**:所有元素都加动画,影响性能和体验
❌ **忽略无障碍**:不支持键盘导航,颜色对比度不足

File Inventory

.codex-plugin/plugin.json

plugin-manifest

1,409 bytes

59d8f2fd0117e29a…

biome.json

file

1,027 bytes

c224e79a39317fe1…

package.json

file

2,327 bytes

1bf67d1d0dceb2c3…

.claude-plugin/plugin.json

file

1,781 bytes

5bc58120d81056c4…

tsconfig.json

file

418 bytes

53eb1f5ab00e81bb…

README.md

file

21,730 bytes

0c09b33e34f89bdc…

SECURITY.md

file

3,363 bytes

f7e17a406cad97a0…

package-lock.json

file

78,783 bytes

98a2fac65c152484…

skill/SKILL.md

skill

9,786 bytes

12393dba2ce7b3f6…

skill/agents/boss-architect.md

file

7,835 bytes

51b16989c71c02db…

skill/agents/boss-backend.md

file

5,571 bytes

ac0af8f69a031282…

skill/agents/boss-devops.md

file

5,398 bytes

604a952b1ede3061…

skill/agents/boss-frontend.md

file

6,031 bytes

17f9f3b616cea6ec…

skill/agents/boss-pm.md

file

3,698 bytes

9ae344be5ae14ccc…

skill/agents/boss-qa.md

file

4,327 bytes

f0c8164e7ef76560…

skill/agents/boss-scrum-master.md

file

12,008 bytes

9055352fdd9d0691…

skill/agents/boss-tech-lead.md

file

7,199 bytes

6412ad0cde3667f5…

skill/agents/boss-ui-designer.md

file

7,822 bytes

76e537f22db7ad9e…

skill/agents/openai.yaml

file

202 bytes

81323fe13e9d6b9c…

skill/agents/prompts/code-quality-reviewer-prompt.md

file

3,670 bytes

8862bb8bdecf0606…

skill/agents/prompts/implementer-prompt.md

file

3,446 bytes

0170da1ed48d7165…

skill/agents/prompts/spec-reviewer-prompt.md

file

2,903 bytes

8969377a561f914d…

skill/agents/prompts/subagent-protocol.md

file

12,477 bytes

361703c059183013…

skill/agents/shared/agent-protocol.md

file

5,917 bytes

db8f76f9250b5337…

skill/agents/shared/protocol-manifest.md

file

3,333 bytes

0550c5a1ceebbd9c…

skill/agents/shared/tech-detection.md

file

6,603 bytes

bb1d829c22d5140b…

skill/assets/artifact-dag.json

file

3,881 bytes

7abbf1e47e6cbd2b…

skill/assets/pipeline-packs/api-only/pipeline.json

file

673 bytes

df2c30860bb08254…

skill/assets/pipeline-packs/core/pipeline.json

file

446 bytes

9c79bf85ee7d9630…

skill/assets/pipeline-packs/default/pipeline.json

file

571 bytes

0bfa739ebaaebd4f…

skill/assets/pipeline-packs/solana-contract/pipeline.json

file

657 bytes

81fac5a5ef9ab61c…

skill/assets/pipeline-packs/web-app/pipeline.json

file

805 bytes

445399d25e83800e…

skill/assets/plugin-schema.json

file

3,549 bytes

087738733ec929b4…

skill/assets/plugins/llm-judge/gate.js

file

5,921 bytes

48eab65244a66389…

skill/assets/plugins/llm-judge/plugin.json

file

525 bytes

09dcd28e471d1991…

skill/assets/plugins/llm-judge/prompts/architecture-soundness.md

file

871 bytes

bda6d7acea7261bf…

skill/assets/plugins/llm-judge/prompts/code-quality.md

file

810 bytes

6271900193b2a22b…

skill/assets/plugins/llm-judge/prompts/test-completeness.md

file

897 bytes

2b057daabad98d88…

skill/assets/plugins/owasp-scan/gate.js

file

8,581 bytes

688196234e1d46c3…

skill/assets/plugins/owasp-scan/plugin.json

file

693 bytes

a5f2524371318adb…

skill/assets/plugins/security-audit/gate.js

file

2,546 bytes

d2e95bc97c4876df…

skill/assets/plugins/security-audit/plugin.json

file

398 bytes

42fdc1d87bc7dba9…

skill/cli/bin/boss.mts

file

5,087 bytes

808181078bfc7dd5…

skill/cli/cli/contract.mts

file

16,678 bytes

e998536b04fbcdfb…

skill/cli/cli/dispatcher.mts

file

16,935 bytes

634a1e3c55ec928f…

skill/cli/cli/help.mts

file

4,184 bytes

ca3adb17e1527215…

skill/cli/cli/registry.mts

file

27,891 bytes

ffe99d2023ad5994…

skill/cli/commands/artifact/index.mts

file

9,168 bytes

fa6a36927e537671…

skill/cli/commands/continue.mts

file

2,539 bytes

a5cebbd1702c0586…

skill/cli/commands/design/preview.mts

file

9,874 bytes

b9d4699a256ffd3f…

skill/cli/commands/doctor.mts

file

11,090 bytes

3ec553f00bec4229…

skill/cli/commands/gate/index.mts

file

4,302 bytes

9a5a2d307042fc3d…

skill/cli/commands/install/index.mts

file

21,416 bytes

5cc4257a9ee0efba…

skill/cli/commands/packs/index.mts

file

3,764 bytes

f3cab22c51e50dcb…

skill/cli/commands/project/index.mts

file

16,771 bytes

c116a790c181e15c…

skill/cli/commands/qa/index.mts

file

3,590 bytes

7ac54e3fd895c4bb…

skill/cli/commands/runtime/agent-cache.mts

file

5,809 bytes

1f295054f7d77d16…

skill/cli/commands/runtime/agent-command-utils.mts

file

2,398 bytes

2155bc660c4f4490…

skill/cli/commands/runtime/append-conversation-message.mts

file

2,294 bytes

334d31ccc8e70361…

skill/cli/commands/runtime/attach.mts

file

3,139 bytes

ad00e3f4d7070f73…

skill/cli/commands/runtime/build-memory-summary.mts

file

2,116 bytes

6dcd4285043f12ea…

skill/cli/commands/runtime/check-stage.mts

file

5,875 bytes

c653d778a4486eb5…

skill/cli/commands/runtime/conversation-command-utils.mts

file

25,822 bytes

35be974b485f5a48…

skill/cli/commands/runtime/evaluate-gates.mts

file

4,014 bytes

551e50d00e562d45…

skill/cli/commands/runtime/extract-memory.mts

file

2,379 bytes

960ca9ef1bd12e12…

skill/cli/commands/runtime/generate-summary.mts

file

5,768 bytes

288b382090749eb7…

skill/cli/commands/runtime/get-ready-artifacts.mts

file

5,809 bytes

fe67c93390c696bb…

skill/cli/commands/runtime/init-pipeline.mts

file

3,236 bytes

9f43d6376e0258c9…

skill/cli/commands/runtime/inspect-events.mts

file

4,175 bytes

d9bbc13513e878a4…

skill/cli/commands/runtime/inspect-pipeline.mts

file

4,509 bytes

964c05632feb8f39…

skill/cli/commands/runtime/inspect-plugins.mts

file

3,885 bytes

9170637e61b3fc3f…

skill/cli/commands/runtime/inspect-progress.mts

file

4,017 bytes

f200ffc880d35e33…

skill/cli/commands/runtime/launch.mts

file

3,627 bytes

08c591956954cb9e…

skill/cli/commands/runtime/list-conversations.mts

file

2,038 bytes

084296652f01df34…

skill/cli/commands/runtime/list-todos.mts

file

1,951 bytes

b9dc8ac0798e2c5d…

skill/cli/commands/runtime/materialize-todo.mts

file

2,106 bytes

3ead79b89278e3de…

skill/cli/commands/runtime/open-conversation.mts

file

2,075 bytes

b1fa8ca2b3980c13…

skill/cli/commands/runtime/pause.mts

file

3,865 bytes

b85bae18ea884182…

skill/cli/commands/runtime/query-memory.mts

file

4,815 bytes

ad49b5920588c928…

skill/cli/commands/runtime/rebuild-state.mts

file

2,301 bytes

e2feaefa23d9277b…

skill/cli/commands/runtime/record-artifact.mts

file

8,616 bytes

e4e202c33f46a917…

skill/cli/commands/runtime/record-feedback.mts

file

4,993 bytes

6ad49ad9a92762c3…

skill/cli/commands/runtime/record-user-choice.mts

file

5,612 bytes

ff0affa048198612…

skill/cli/commands/runtime/register-plugins.mts

file

6,154 bytes

b4d4fd45403769b5…

skill/cli/commands/runtime/render-diagnostics.mts

file

5,043 bytes

4eadcd82cda40e1a…

skill/cli/commands/runtime/replay-events.mts

file

5,029 bytes

5def864128f0d9e3…

skill/cli/commands/runtime/report-agent-status.mts

file

5,491 bytes

1610c8b2b1c374c0…

skill/cli/commands/runtime/resolve-conversation.mts

file

2,382 bytes

44541afc357998dd…

skill/cli/commands/runtime/resume.mts

file

3,715 bytes

c820e3108a89683e…

skill/cli/commands/runtime/retry-agent.mts

file

3,948 bytes

91e0ce4f36511ba9…

skill/cli/commands/runtime/retry-stage.mts

file

3,711 bytes

ed00f62d943d1891…

skill/cli/commands/runtime/run-plugin-hook.mts

file

3,926 bytes

e04aa821013dd39f…

skill/cli/commands/runtime/update-agent.mts

file

6,240 bytes

cc7e08e0585b9e60…

skill/cli/commands/runtime/update-stage.mts

file

6,473 bytes

0e729957beedcb78…

skill/cli/commands/runtime/verify-requirements.mts

file

4,156 bytes

80e5cac49d6f382d…

skill/cli/commands/runtime/verify-wave.mts

file

4,575 bytes

e3020c7db0af4671…

skill/cli/commands/status.mts

file

3,020 bytes

bf1c5fb3bd1fdbf9…

skill/cli/infrastructure/fs.mts

file

4,323 bytes

550e61f071fce17c…

skill/cli/infrastructure/paths.mts

file

2,485 bytes

c99c4f3c75fc80ff…

skill/cli/infrastructure/process.mts

file

959 bytes

1110fc144fe46ab7…

skill/cli/runtime/application/artifact-layers.mts

file

3,471 bytes

d388dddaab6f9713…

skill/cli/runtime/application/checkpoints.mts

file

4,138 bytes

8fcbd13044ce914a…

skill/cli/runtime/application/conversations.mts

file

16,671 bytes

e5863f87cf605b6e…

skill/cli/runtime/application/drivers.mts

file

854 bytes

9eca46285fe4023a…

skill/cli/runtime/application/final-gate.mts

file

4,153 bytes

3c56b30742159cd9…

skill/cli/runtime/application/gates.mts

file

18,868 bytes

e247f64551a57cd8…

skill/cli/runtime/application/inspection.mts

file

15,694 bytes

edb3db040f3fc2df…

skill/cli/runtime/application/memory.mts

file

6,893 bytes

683026ac19f0de1a…

skill/cli/runtime/application/packs.mts

file

7,405 bytes

951155d7c337a553…

skill/cli/runtime/application/pipeline-artifacts.mts

file

6,799 bytes

4553d658453ac4be…

skill/cli/runtime/application/pipeline-dag.mts

file

12,832 bytes

c32b80a6112e6016…

skill/cli/runtime/application/pipeline-reuse.mts

file

4,753 bytes

3f96314633b5f3a8…

skill/cli/runtime/application/pipeline-transitions.mts

file

12,794 bytes

917a7aca3a94bb23…

skill/cli/runtime/application/pipeline-types.mts

file

1,542 bytes

0f27a3d09cc2d916…

skill/cli/runtime/application/pipeline.mts

file

11,523 bytes

18571ed7c9ca1da1…

skill/cli/runtime/application/plugins.mts

file

17,847 bytes

7056a52fa4015009…

skill/cli/runtime/application/qa-attack.mts

file

3,271 bytes

7ee8077d90934b22…

skill/cli/runtime/application/requirements-verification.mts

file

5,040 bytes

e42a1494debae759…

skill/cli/runtime/application/state.mts

file

3,864 bytes

f3aace0ee66f9f97…

skill/cli/runtime/application/wave-verification.mts

file

4,823 bytes

909c882a5214a6ef…

skill/cli/runtime/application/waves.mts

file

7,351 bytes

de2eff040a63eb49…

skill/cli/runtime/application/wip-checkpoint.mts

file

8,687 bytes

ff7dbe56dba33650…

skill/cli/runtime/application/workflow.mts

file

16,390 bytes

7e9ac910498c2668…

skill/cli/runtime/assets.mts

file

4,060 bytes

eca2d0422e3463f7…

skill/cli/runtime/design/open.mts

file

957 bytes

397dc25029c9c305…

skill/cli/runtime/design/render.mts

file

12,724 bytes

8444d3843e3ea843…

skill/cli/runtime/design/schema.mts

file

7,807 bytes

91f2e418a1edfdbb…

skill/cli/runtime/design/server.mts

file

1,367 bytes

33eb6cff1e3233b9…

skill/cli/runtime/domain/agent-report.mts

file

1,518 bytes

6c4fff5222b6e437…

skill/cli/runtime/domain/conversation-types.mts

file

1,555 bytes

8dba04bf8ba252f7…

skill/cli/runtime/domain/event-types.mts

file

1,400 bytes

8d144f2c98097fe5…

skill/cli/runtime/domain/scheduling.mts

file

3,503 bytes

25a8d87c975e4aec…

skill/cli/runtime/domain/state-constants.mts

file

806 bytes

b442885631ed3d85…

skill/cli/runtime/domain/structured-wave.mts

file

3,872 bytes

5ed78a25ed3074e7…

skill/cli/runtime/memory/extractor.mts

file

7,816 bytes

4483bb55640eb5e5…

skill/cli/runtime/memory/preferences.mts

file

6,472 bytes

9607efd83e11bbf9…

skill/cli/runtime/memory/query.mts

file

1,129 bytes

c5a6574394ecf042…

skill/cli/runtime/memory/store.mts

file

6,147 bytes

d3d655db0c962e4e…

skill/cli/runtime/memory/summarizer.mts

file

1,867 bytes

08b1bc05f26b29e6…

skill/cli/runtime/projectors/apply-agent.mts

file

3,432 bytes

f7f34d03ef6bd20f…

skill/cli/runtime/projectors/apply-conversation.mts

file

5,179 bytes

7e6b5d6c666132ec…

skill/cli/runtime/projectors/apply-pipeline.mts

file

3,445 bytes

c0cf1cec54a38677…

skill/cli/runtime/projectors/apply-plugin.mts

file

2,738 bytes

05b8a35ab5e4ed86…

skill/cli/runtime/projectors/apply-revision.mts

file

1,753 bytes

ee45d6b53282557b…

skill/cli/runtime/projectors/apply-stage.mts

file

3,769 bytes

08d8aa1a11e7b3ea…

skill/cli/runtime/projectors/apply-wave.mts

file

1,203 bytes

6664c4ed4115e2a8…

skill/cli/runtime/projectors/finalize.mts

file

4,404 bytes

5ce4644738bad08a…

skill/cli/runtime/projectors/helpers.mts

file

13,083 bytes

c8316a636726b91d…

skill/cli/runtime/projectors/materialize-state.mts

file

4,104 bytes

6f2cb5960a0a41b9…

skill/cli/runtime/projectors/types.mts

file

4,597 bytes

ea83f7dfdae3891c…

skill/cli/runtime/projectors/validation.mts

file

11,969 bytes

40bfc53571f17b90…

skill/cli/runtime/report/render-artifact-html.mts

file

13,250 bytes

4498b0324c0e00d0…

skill/cli/runtime/report/render-html.mts

file

6,385 bytes

718706afa62abde9…

skill/cli/runtime/report/render-json.mts

file

166 bytes

11377e21e4096177…

skill/cli/runtime/report/render-markdown.mts

file

7,924 bytes

646a1f20e1f2c2b2…

skill/cli/runtime/report/summary-model.mts

file

5,763 bytes

e557abc0b11a9cdf…

skill/cli/runtime/schema/artifact-html-schema.json

file

1,222 bytes

370d634220a291e2…

skill/cli/runtime/schema/event-schema.json

file

11,592 bytes

8e43905f2c57476f…

skill/cli/runtime/schema/execution-schema.json

file

8,123 bytes

4cd5f162b16ce239…

skill/cli/runtime/schema/memory-record-schema.json

file

1,776 bytes

e175eca1bb4f6357…

skill/cli/runtime/schema/memory-summary-schema.json

file

1,147 bytes

bff9eb31682acea8…

skill/cli/runtime/schema/progress-schema.json

file

460 bytes

38bc3b2f16bcc929…

skill/cli/runtime/schema/ui-design-schema.json

file

4,076 bytes

6ec4c41f44b530e4…

skill/cli/skills/banner.mts

file

1,229 bytes

d14addca191d751a…

skill/cli/skills/discover.mts

file

3,278 bytes

47a5c7cf894e48d5…

skill/cli/skills/installer.mts

file

1,305 bytes

a13fece15c888f5a…

skill/cli/skills/search-multiselect.mts

file

8,327 bytes

a5a7211ccc5ebf78…

skill/cli/skills/self-install-wizard.mts

file

3,505 bytes

69ba331fee5552b5…

skill/commands/boss-extend.md

file

2,877 bytes

5ed6426d35882d48…

skill/commands/boss-plan.md

file

2,389 bytes

4d8ed916cee91ed8…

skill/commands/boss-qa.md

file

2,159 bytes

42a6063220bf466a…

skill/commands/boss-review.md

file

2,290 bytes

2d8bade4ed1f53e6…

skill/commands/boss-ship.md

file

1,882 bytes

2098701c0f92083f…

skill/commands/boss-upgrade.md

file

2,005 bytes

d25cde29fab17474…

skill/commands/boss.md

file

2,921 bytes

e30b9acdc1df47de…

skill/hooks/claude/hooks.json

file

6,614 bytes

579d0918adecbdfc…

skill/hooks/codex/hooks.json

file

3,173 bytes

15366e46f1da5524…

skill/references/artifact-guide.md

file

3,943 bytes

796aabe4c160c676…

skill/references/bmad-methodology.md

file

16,563 bytes

70869503d8216c10…

skill/references/evidence-waves.md

file

4,788 bytes

691669efdbc92ccd…

skill/references/extending-boss.md

file

3,728 bytes

dc3150dbfef1bf3d…

skill/references/hooks-runtime.md

file

2,712 bytes

bc1a0940a73ecd95…

skill/references/no-cli-fallback.md

file

4,954 bytes

2b697c2a3684b8fa…

skill/references/orchestration-loop.md

file

5,478 bytes

967427157a031161…

skill/references/platform-drivers.md

file

2,257 bytes

5a2e492b72d45f2d…

skill/references/quality-gate.md

file

3,018 bytes

56ef87ee5d52798e…

skill/references/runtime-surface.md

file

4,096 bytes

c32641503df0ea5b…

skill/references/testing-standards.md

file

5,152 bytes

d6b35e6c4e255e48…

skill/scripts/hooks/lib/normalize-input.js

file

1,694 bytes

399d0f520dfff9ce…

skill/scripts/hooks/on-notification.js

file

1,733 bytes

3de6380b093663c5…

skill/scripts/hooks/on-stop.js

file

1,288 bytes

c30ebc7406a6e7ea…

skill/scripts/hooks/post-tool-bash.js

file

2,025 bytes

a5c2f12af69b1f70…

skill/scripts/hooks/post-tool-write.js

file

3,057 bytes

dac5e937bc71e53d…

skill/scripts/hooks/pre-tool-bash.js

file

1,411 bytes

08af3f94468de0b4…

skill/scripts/hooks/pre-tool-write.js

file

3,552 bytes

ca1492f7749ec424…

skill/scripts/hooks/session-end.js

file

2,461 bytes

4caeb9a5a43e1c5d…

skill/scripts/hooks/session-resume.js

file

2,595 bytes

ad3360f0a0936973…

skill/scripts/hooks/session-start.js

file

2,574 bytes

a41509dec023e6d4…

skill/scripts/hooks/subagent-start.js

file

3,170 bytes

cec254500aa53122…

skill/scripts/hooks/subagent-stop.js

file

4,274 bytes

1f1bf089825fa8b4…

skill/scripts/hooks/wip-checkpoint.js

file

3,643 bytes

7b01c527bd7639a7…

skill/scripts/lib/boss-utils.js

file

5,234 bytes

7e1256bc6aa75fcc…

skill/scripts/lib/hook-flags.js

file

887 bytes

26ee7c5c511f2a81…

skill/scripts/lib/progress-emitter.js

file

1,047 bytes

799be95bdc0c5304…

skill/scripts/lib/run-with-flags.js

file

3,942 bytes

f188dc90792bb3f1…

skill/skills/README.md

file

1,628 bytes

7b77029effe002b0…

skill/skills/_TEMPLATE.md

file

436 bytes

98fb09e071c1f128…

skill/skills/architect/architecture-design/SKILL.md

skill

10,258 bytes

83c5dbe8a422096c…

skill/skills/architect/data-api-design/SKILL.md

skill

10,413 bytes

96c0ce7e66466af7…

skill/skills/architect/tech-research/SKILL.md

skill

8,325 bytes

b2877fa4d518000e…

skill/skills/backend/api-development/SKILL.md

skill

10,053 bytes

08746adf17a9a72c…

skill/skills/backend/testing-guide/SKILL.md

skill

16,700 bytes

e6ff5e8fa365c7cd…

skill/skills/brainstorming/SKILL.md

skill

9,103 bytes

54964cf7198990e9…

skill/skills/devops/changelog-generation/SKILL.md

skill

3,944 bytes

3854dc1b14a52afe…

skill/skills/devops/deployment-process/SKILL.md

skill

1,311 bytes

c623e37319cef7b1…

skill/skills/devops/monitoring-alerting/SKILL.md

skill

949 bytes

5bf49a582ad493eb…

skill/skills/frontend/component-development/SKILL.md

skill

5,911 bytes

035fc11ef6ed376a…

skill/skills/frontend/testing-guide/SKILL.md

skill

9,707 bytes

2c2cc61cd129465d…

skill/skills/pm/competitive-analysis/SKILL.md

skill

5,983 bytes

05128ae1d202fe8a…

skill/skills/pm/prd-writing/SKILL.md

skill

6,425 bytes

0c9d6272730c5790…

skill/skills/pm/requirement-penetration/SKILL.md

skill

5,292 bytes

63545bdd22fcb2ca…

skill/skills/pm/strategic-review/SKILL.md

skill

4,597 bytes

84ebbaa8e51ab62f…

skill/skills/pm/user-research/SKILL.md

skill

7,579 bytes

596aac9cb7c9e3c2…

skill/skills/qa/e2e-playwright/SKILL.md

skill

22,832 bytes

1cbbceb8c8992865…

skill/skills/qa/test-execution/SKILL.md

skill

2,356 bytes

4b19da9ada56aa4c…

skill/skills/qa/test-strategy/SKILL.md

skill

2,709 bytes

fcd3f7c79870bc2c…

skill/skills/scrum-master/risk-assessment/SKILL.md

skill

1,204 bytes

7c499dd17aff123f…

skill/skills/scrum-master/task-breakdown/SKILL.md

skill

1,014 bytes

d402273a1fbce870…

skill/skills/shared/README.md

file

2,338 bytes

c2c92a55490d91c2…

skill/skills/shared/tech-stack-detection/SKILL.md

skill

7,014 bytes

080233f22f254fa3…

skill/skills/tech-lead/code-review/SKILL.md

skill

896 bytes

6dc316d6e1cceaf6…

skill/skills/tech-lead/technical-standards/SKILL.md

skill

1,147 bytes

f27b48e762d5de5d…

skill/skills/ui-designer/component-specification/SKILL.md

skill

10,057 bytes

0eceb55332834342…

skill/skills/ui-designer/design-system/SKILL.md

skill

8,194 bytes

6d28fc29c6dc63a3…

skill/skills/ui-designer/design-variants/SKILL.md

skill

4,189 bytes

4e5273337151247d…

skill/skills/ui-designer/interaction-specification/SKILL.md

skill

11,001 bytes

9b238996b1391589…

assets/boss-logo.svg

asset

1,172 bytes

77ffeae3092afb01…

assets/boss-composer-icon.svg

asset

533 bytes

8ab65b598bb568ad…