Compare commits
31
Commits
b43235db40
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aa66d846df | ||
|
|
dd6071e81f | ||
|
|
5e465faa7b | ||
|
|
018bc2e914 | ||
|
|
199a14daea | ||
|
|
127bc4e7c1 | ||
|
|
381308e04a | ||
|
|
f7ea0dcd86 | ||
|
|
e2d29f6005 | ||
|
|
8cdb91c225 | ||
|
|
9060fe5222 | ||
|
|
0eaccca7cf | ||
|
|
72a6f71dd0 | ||
|
|
7026f249d0 | ||
|
|
a426ea13ec | ||
|
|
c6c88b8bee | ||
|
|
9b84ebf036 | ||
|
|
6e43bd9460 | ||
|
|
aa87b8cf0b | ||
|
|
a6bd0fddcf | ||
|
|
b15164975a | ||
|
|
64b97386c1 | ||
|
|
b12d9061d8 | ||
|
|
da5046447b | ||
|
|
9c1fb956e4 | ||
|
|
e82eb4e857 | ||
|
|
426b6cea2a | ||
|
|
5d7a77b8ba | ||
|
|
485e65dfd9 | ||
|
|
1520daa683 | ||
|
|
9979a7c038 |
@@ -63,6 +63,42 @@
|
||||
"authentication": "ON_INSTALL"
|
||||
},
|
||||
"category": "Productivity"
|
||||
},
|
||||
{
|
||||
"name": "profile",
|
||||
"source": {
|
||||
"source": "local",
|
||||
"path": "./plugins/profile"
|
||||
},
|
||||
"policy": {
|
||||
"installation": "AVAILABLE",
|
||||
"authentication": "ON_INSTALL"
|
||||
},
|
||||
"category": "Productivity"
|
||||
},
|
||||
{
|
||||
"name": "java",
|
||||
"source": {
|
||||
"source": "local",
|
||||
"path": "./plugins/java"
|
||||
},
|
||||
"policy": {
|
||||
"installation": "AVAILABLE",
|
||||
"authentication": "ON_INSTALL"
|
||||
},
|
||||
"category": "Productivity"
|
||||
},
|
||||
{
|
||||
"name": "python",
|
||||
"source": {
|
||||
"source": "local",
|
||||
"path": "./plugins/python"
|
||||
},
|
||||
"policy": {
|
||||
"installation": "AVAILABLE",
|
||||
"authentication": "ON_INSTALL"
|
||||
},
|
||||
"category": "Productivity"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# Local CraftKit data
|
||||
/local/
|
||||
/cache/
|
||||
@@ -0,0 +1,15 @@
|
||||
# CraftKit 项目资料
|
||||
|
||||
本目录保存当前项目可供 Agent 使用的配置、规范、知识和交接内容。
|
||||
|
||||
- `project.json`:项目类型、技术栈、代码边界、依赖标识、命令和文档生命周期默认策略。
|
||||
- `agents/`:项目对 Agent 的补充指令。
|
||||
- `standards/`:项目自身的开发、测试、文档与 Git 规范。
|
||||
- `standards/document-maintenance.md`:长期文档的审核、持续更新、替代和关闭约定。
|
||||
- `knowledge/`:经过验证的技术决策和可复用经验。
|
||||
- `designs/`:用户明确要求共享或正式交付的设计文档。
|
||||
- `handoff/`:用户明确选择共享的任务交接。
|
||||
- `local/`:当前工作副本的过程文档、任务记录和本地上下文,不进入 Git;其中个人配置不属于任务清理范围。
|
||||
- `cache/`:可重新生成的缓存,不进入 Git。
|
||||
|
||||
共享资料不得包含凭据、个人机器绝对路径或无必要的业务数据。
|
||||
@@ -0,0 +1,3 @@
|
||||
# Agent 补充说明索引
|
||||
|
||||
当前没有项目专属 Agent 补充说明。新增说明时记录适用目录、触发条件和文件路径。
|
||||
@@ -0,0 +1,894 @@
|
||||
---
|
||||
reviewStatus: pending
|
||||
reviewedAt: null
|
||||
replacedBy: null
|
||||
---
|
||||
|
||||
# 多语言插件架构设计与实施方案
|
||||
|
||||
## 1. 设计目标
|
||||
|
||||
本设计将 CraftKit 建设为可扩展的多语言插件体系。现有 `dev`、`knowledge` 和 `skill` 插件继续提供通用工作流,新增 Profile 工厂和技术能力插件,使初始化、规范检索、后端设计、实现、测试和审查能够按项目真实技术栈加载 Java、Python 或前端专项知识。
|
||||
|
||||
本文是多语言插件架构的唯一设计依据。[《多语言插件架构改造计划》](MULTI-LANGUAGE-PLUGIN-ARCHITECTURE-PLAN.md)只跟踪实施批次、依赖和验证状态,不重复定义架构。首期建立独立插件骨架并保留旧 Skill 入口,但只有经过安装组合验证后才声明插件可独立交付。
|
||||
|
||||
首期交付范围:
|
||||
|
||||
- 建立统一的 Profile 能力契约。
|
||||
- 新增 Profile 工厂插件。
|
||||
- 新增 Java 和 Python 技术能力插件。
|
||||
- 改造项目初始化和规范检索入口。
|
||||
- 让 `design-backend`、`implement-backend`、`test-backend` 和专项审查接入 Profile。
|
||||
- 使用 Spring Boot 与 FastAPI 项目验证完整路由。
|
||||
|
||||
首期不包含:
|
||||
|
||||
- 自动安装 JDK、Python、Maven、uv 或项目依赖。
|
||||
- 自动修改业务项目的依赖版本。
|
||||
- 数据库、HTTP 和前端详细设计规则的全面重写。
|
||||
- Go、Rust、C# 等后续语言能力包。
|
||||
- 运行时插件下载、动态代码加载或远程配置中心。
|
||||
|
||||
## 2. 现状与约束
|
||||
|
||||
### 2.1 已有能力
|
||||
|
||||
| 能力 | 当前入口 | 可复用内容 |
|
||||
| --- | --- | --- |
|
||||
| 项目初始化 | `knowledge:init` | 构建文件探测、项目画像、保守合并和安全边界 |
|
||||
| 项目画像 | `.craftkit/project.json` | 技术栈、代码边界、命令和知识入口 |
|
||||
| 规范检索 | `skill:guidance` | 来源优先级、渐进加载和版本 Profile 路由 |
|
||||
| 后端设计 | `dev:design-backend` | 中性设计流程和统一设计输出 |
|
||||
| 后端实现 | `dev:implement-backend` | 基于项目证据实施和验证 |
|
||||
| 后端测试 | `dev:test-backend` | 按项目测试框架选择测试层级 |
|
||||
| Java 审查 | `dev:review-java` | Java 语言专项审查基线 |
|
||||
| 插件市场 | `.agents/plugins/marketplace.json` | 独立插件注册和安装入口 |
|
||||
|
||||
### 2.2 主要缺口
|
||||
|
||||
- `profile` 只有概念和路由原则,没有机器可检查的统一契约。
|
||||
- 公共语言知识缺少独立插件边界,难以单独安装、发布和维护。
|
||||
- 初始化 Skill 同时承担通用扫描和技术识别,继续扩展会形成语言条件分支集合。
|
||||
- 核心 Skill 只能手工寻找资料,无法稳定判断能力是否安装、版本是否匹配。
|
||||
- `.craftkit/project.json` 只能给框架记录单个 `profile` 字符串,不能表达模块级语言和多个能力提供方。
|
||||
- 跨插件相对路径会受到安装位置和插件版本目录影响,不能作为稳定依赖接口。
|
||||
|
||||
### 2.3 平台约束
|
||||
|
||||
- Skill 是由 Agent 按描述和指令选择的能力,不假设存在传统依赖注入容器。
|
||||
- 插件可以独立安装,核心工作流必须在语言插件缺失时继续执行通用部分。
|
||||
- 不依赖用户目录中的固定插件缓存路径。
|
||||
- 公共插件不能直接写入业务项目;项目文件统一由当前获得授权的核心 Skill 修改。
|
||||
- 未确认精确版本时不能默认最新版本,也不能跨主版本混用规则。
|
||||
|
||||
### 2.4 已验证的平台能力
|
||||
|
||||
本设计基于本机 Codex CLI 0.130.0、内置 `plugin-creator` 和 `skill-creator` 规范进行验证,结论如下:
|
||||
|
||||
- 插件清单可以暴露插件内的 Skill 目录。
|
||||
- `agents/openai.yaml` 当前只支持声明 MCP 工具依赖,没有 Skill 依赖声明。
|
||||
- 当前没有标准接口让一个 Skill 在运行时枚举其他已安装插件、读取其物理目录或像函数一样调用另一个 Skill。
|
||||
- 当前会话可用 Skill 由 Codex 在会话开始时发现;新增或更新插件需要后续安装组合和新会话验证。
|
||||
|
||||
因此,本文中的“请求能力”是 Agent 协作语义,不是 RPC 或函数调用。消费者根据当前会话已发现的提供方 Skill 获取专项资料;提供方读取自身资料并返回标准能力上下文。Profile 插件维护契约、匹配规则和校验器,不承担运行时扫描插件缓存。
|
||||
|
||||
### 2.5 待验证边界
|
||||
|
||||
- Repo marketplace 安装后,三个新插件能否在新会话中按名称稳定发现。
|
||||
- 多个版本的同一提供方同时存在时,Codex 暴露哪个版本。
|
||||
- 缺少提供方时,消费者对通用工作流的真实行为是否符合设计。
|
||||
- 提供方 Skill 返回的标准能力上下文能否在真实设计、测试和审查请求中保持一致。
|
||||
|
||||
上述边界分别在插件安装组合和真实场景阶段验证;验证完成前不把静态清单通过等同于运行行为通过。
|
||||
|
||||
## 3. 总体设计
|
||||
|
||||
Profile 工厂负责“识别需求并选择能力”,技术插件负责“提供能力”,核心 Skill 负责“执行业务工作流”。项目知识库提供当前项目的覆盖规则。
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
U[用户任务] --> C[核心 Skill]
|
||||
C --> PJ[读取 project.json]
|
||||
PJ --> R[profile:resolve]
|
||||
R --> M{目标模块技术栈}
|
||||
M -->|Java| J[java:profile]
|
||||
M -->|Python| P[python:profile]
|
||||
M -->|Frontend| F[frontend:profile]
|
||||
J --> B[标准能力上下文]
|
||||
P --> B
|
||||
F --> B
|
||||
K[项目 standards 与 knowledge] --> B
|
||||
B --> C
|
||||
C --> O[统一产物]
|
||||
```
|
||||
|
||||
### 3.1 插件职责
|
||||
|
||||
| 插件 | 类型 | 职责 |
|
||||
| --- | --- | --- |
|
||||
| `profile` | 工厂 | 技术栈基础探测、目标模块选择、能力匹配、冲突检查和回退决策 |
|
||||
| `java` | 提供方 | Java、JDK、Maven、Gradle、Spring、测试和审查知识 |
|
||||
| `python` | 提供方 | Python、包管理、FastAPI、Django、Flask、测试和审查知识 |
|
||||
| `frontend` | 提供方 | TypeScript、React、Vue、Next.js、Nuxt、构建和测试知识 |
|
||||
| `knowledge` | 核心消费者 | 初始化并维护项目画像和项目知识入口 |
|
||||
| `skill` | 核心消费者 | 按优先级检索项目规则和公共技术知识 |
|
||||
| `dev` | 核心消费者 | 执行通用设计、实现、测试和审查工作流 |
|
||||
|
||||
`doc` 和 `git` 首期不接入语言 Profile。后续只有在命令、生成物或发布规则确实依赖技术栈时,才通过 `command-resolution` 能力读取 Profile。
|
||||
|
||||
### 3.2 依赖方向
|
||||
|
||||
```text
|
||||
dev ──────────┐
|
||||
knowledge ────┼──> profile contract <── java
|
||||
skill ────────┘ <── python
|
||||
<── frontend
|
||||
|
||||
项目 standards/knowledge ──> 覆盖公共 Profile
|
||||
```
|
||||
|
||||
依赖必须保持单向:
|
||||
|
||||
- 核心插件依赖 Profile 契约,不依赖技术插件内部目录。
|
||||
- 技术插件实现契约,不反向调用 `dev` 或修改项目画像。
|
||||
- Profile 工厂只做解析,不执行设计、编码、测试或审查任务。
|
||||
- 技术插件之间不能相互引用内部资料;跨技术协作通过统一契约完成。
|
||||
|
||||
## 4. 插件和目录设计
|
||||
|
||||
### 4.1 Profile 工厂插件
|
||||
|
||||
```text
|
||||
plugins/profile/
|
||||
├─ .codex-plugin/
|
||||
│ └─ plugin.json
|
||||
└─ skills/
|
||||
└─ resolve/
|
||||
├─ SKILL.md
|
||||
├─ agents/openai.yaml
|
||||
├─ references/
|
||||
│ ├─ contract.md
|
||||
│ ├─ detection.md
|
||||
│ ├─ resolution.md
|
||||
│ └─ fallback.md
|
||||
└─ scripts/
|
||||
└─ validate_profile.py
|
||||
```
|
||||
|
||||
`profile:resolve` 是契约和解析规则入口。消费者可在该 Skill 已发现时使用其匹配规则,但不能假设它能枚举或调用其他插件。它承担以下职责:
|
||||
|
||||
1. 接收目标目录、任务所需能力和项目画像。
|
||||
2. 确认目标属于哪个模块。
|
||||
3. 从项目文件识别语言、框架、版本和工具证据。
|
||||
4. 根据当前会话已经发现的能力提供方返回信息完成匹配。
|
||||
5. 合并项目覆盖规则并输出标准能力上下文。
|
||||
6. 在缺失、冲突或版本不匹配时返回明确的回退结果。
|
||||
|
||||
`validate_profile.py` 只校验确定性的契约结构、标识、版本范围格式和引用文件存在性,不负责执行 Agent 路由。
|
||||
|
||||
### 4.2 Java 技术插件
|
||||
|
||||
```text
|
||||
plugins/java/
|
||||
├─ .codex-plugin/
|
||||
│ └─ plugin.json
|
||||
└─ skills/
|
||||
└─ profile/
|
||||
├─ SKILL.md
|
||||
├─ agents/openai.yaml
|
||||
└─ references/
|
||||
├─ manifest.json
|
||||
├─ index.md
|
||||
├─ language/
|
||||
├─ build/
|
||||
├─ frameworks/
|
||||
│ └─ spring/
|
||||
├─ persistence/
|
||||
├─ testing/
|
||||
└─ review/
|
||||
```
|
||||
|
||||
Java 插件首期吸收现有 `review-java` 的公共资料,但 `dev:review-java` 的入口暂时保留。它通过 `java:profile` 获取专项知识,避免首期同时引入用户入口迁移。
|
||||
|
||||
### 4.3 Python 技术插件
|
||||
|
||||
```text
|
||||
plugins/python/
|
||||
├─ .codex-plugin/
|
||||
│ └─ plugin.json
|
||||
└─ skills/
|
||||
├─ profile/
|
||||
│ ├─ SKILL.md
|
||||
│ ├─ agents/openai.yaml
|
||||
│ └─ references/
|
||||
│ ├─ manifest.json
|
||||
│ ├─ index.md
|
||||
│ ├─ language/
|
||||
│ ├─ packaging/
|
||||
│ ├─ frameworks/
|
||||
│ │ ├─ fastapi/
|
||||
│ │ ├─ django/
|
||||
│ │ └─ flask/
|
||||
│ ├─ persistence/
|
||||
│ ├─ testing/
|
||||
│ └─ review/
|
||||
└─ review-python/
|
||||
├─ SKILL.md
|
||||
└─ agents/openai.yaml
|
||||
```
|
||||
|
||||
`python:profile` 提供公共知识和能力上下文,`python:review-python` 执行 Python 专项审查。专项审查保持独立,是因为语言问题、触发边界和输出证据与通用代码审查存在明确差异。
|
||||
|
||||
### 4.4 Frontend 技术插件
|
||||
|
||||
Frontend 插件在 Java/Python 闭环稳定后实施。它遵循同一契约,不把前端框架内容放入 Java 或 Python 插件。
|
||||
|
||||
```text
|
||||
plugins/frontend/
|
||||
├─ .codex-plugin/plugin.json
|
||||
└─ skills/
|
||||
├─ profile/
|
||||
├─ review-typescript/
|
||||
└─ test-frontend/
|
||||
```
|
||||
|
||||
## 5. Profile 契约设计
|
||||
|
||||
### 5.1 提供方清单
|
||||
|
||||
每个技术插件以 `references/manifest.json` 作为能力清单的唯一权威来源。清单只记录路由元数据,详细规则通过相对路径指向同一插件内的 Markdown 资料。JSON 可由 Python 标准库直接校验,不为契约校验器增加第三方 YAML 解析依赖。
|
||||
|
||||
```json
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"provider": {
|
||||
"id": "python",
|
||||
"kind": "language",
|
||||
"displayName": "Python"
|
||||
},
|
||||
"profiles": [
|
||||
{
|
||||
"id": "python/default",
|
||||
"versionRange": "*",
|
||||
"detect": {
|
||||
"manifests": ["pyproject.toml", "requirements.txt"],
|
||||
"lockFiles": ["uv.lock", "poetry.lock", "pdm.lock", "Pipfile.lock"]
|
||||
},
|
||||
"capabilities": {
|
||||
"backend-design": "references/backend/design.md",
|
||||
"backend-implementation": "references/backend/implementation.md",
|
||||
"backend-testing": "references/testing/index.md",
|
||||
"language-review": "references/review/index.md",
|
||||
"command-resolution": "references/packaging/commands.md"
|
||||
},
|
||||
"fallback": "references/fallback.md"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
清单规则:
|
||||
|
||||
- `schemaVersion` 控制契约结构兼容性,与插件版本分开管理。
|
||||
- `provider.id` 与插件标识一致,不能使用项目名或公司名。
|
||||
- `profile.id` 使用 `<provider>/<variant>` 格式,并在发布后保持稳定。
|
||||
- `versionRange` 必须显式声明;无法确定时只提供版本中性 Profile。
|
||||
- `detect` 只声明非敏感、可验证的项目证据。
|
||||
- `capabilities` 的键来自统一能力表,值只能引用当前插件内文件。
|
||||
- 缺少某项能力表示“不提供”,不能用空文件占位。
|
||||
|
||||
### 5.2 能力标识
|
||||
|
||||
| 能力标识 | 消费者 | 输出用途 |
|
||||
| --- | --- | --- |
|
||||
| `project-detection` | `knowledge:init` | 补充语言、框架和工具识别规则 |
|
||||
| `knowledge-routing` | `skill:guidance` | 提供公共知识索引入口 |
|
||||
| `backend-design` | `dev:design-backend` | 提供语言与框架设计约束 |
|
||||
| `backend-implementation` | `dev:implement-backend` | 提供实现结构和验证规则 |
|
||||
| `backend-testing` | `dev:test-backend` | 提供测试层级、工具和命令规则 |
|
||||
| `language-review` | 专项审查 Skill | 提供语言问题分类和证据要求 |
|
||||
| `framework-review` | 专项或通用审查 | 提供框架生命周期、事务等规则 |
|
||||
| `command-resolution` | 实现、测试及后续系统插件 | 提供项目工具命令选择规则 |
|
||||
|
||||
能力标识首期使用固定枚举。新增标识必须先更新契约,再由提供方实现,不能由单个技术插件私自扩展相近名称。
|
||||
|
||||
### 5.3 标准能力请求
|
||||
|
||||
核心 Skill 向 Profile 工厂提供以下语义输入:
|
||||
|
||||
```yaml
|
||||
target: services/order
|
||||
capabilities:
|
||||
- backend-design
|
||||
task: 为订单服务设计幂等创建流程
|
||||
projectProfile: .craftkit/project.json
|
||||
```
|
||||
|
||||
这不是外部 HTTP 接口。它定义 Skill 协作时必须具备的信息,实际内容由 Agent 从用户任务和项目文件构造。
|
||||
|
||||
### 5.4 标准能力上下文
|
||||
|
||||
Profile 工厂返回的结果必须区分事实、选择结果、规则入口和缺口:
|
||||
|
||||
```yaml
|
||||
schemaVersion: 1
|
||||
targetModule: order-service
|
||||
detected:
|
||||
language:
|
||||
name: python
|
||||
version: "3.12"
|
||||
evidence: pyproject.toml
|
||||
framework:
|
||||
name: fastapi
|
||||
version: "0.115.0"
|
||||
evidence: uv.lock
|
||||
resolvedProfiles:
|
||||
- id: python/default
|
||||
provider: python
|
||||
- id: python/fastapi-0
|
||||
provider: python
|
||||
capabilities:
|
||||
backend-design:
|
||||
status: available
|
||||
references:
|
||||
- python:profile/references/backend/design.md
|
||||
- python:profile/references/frameworks/fastapi/design.md
|
||||
overrides:
|
||||
- .craftkit/standards/backend/index.md
|
||||
gaps: []
|
||||
```
|
||||
|
||||
标准能力上下文默认只存在于当前任务上下文中,不写入项目文件。只有初始化或用户明确要求更新项目画像时,才持久化稳定的识别结果。
|
||||
|
||||
### 5.5 路径标识
|
||||
|
||||
跨插件引用使用逻辑标识:
|
||||
|
||||
```text
|
||||
<plugin>:<skill>/<skill 内相对路径>
|
||||
```
|
||||
|
||||
例如:
|
||||
|
||||
```text
|
||||
python:profile/references/testing/index.md
|
||||
```
|
||||
|
||||
该标识只用于诊断和交接,不能作为可直接打开的物理路径。提供方 Skill 负责读取自身资料,消费者不拼接用户缓存目录或其他插件安装路径。
|
||||
|
||||
### 5.6 能力发现协议
|
||||
|
||||
1. 消费者从当前会话公开的 Skill 清单判断提供方是否可用。
|
||||
2. 已发现对应提供方时,由 Agent 使用其 Profile Skill 获取能力上下文。
|
||||
3. 未发现提供方时返回 `missing`,继续执行核心通用流程。
|
||||
4. 提供方只读取自身 `references/manifest.json` 和资料,不读取其他插件目录。
|
||||
5. Profile 契约校验器在仓库开发和发布阶段校验提供方,不充当运行时注册中心。
|
||||
6. 逻辑标识出现在诊断结果中时,同时携带提供方、Skill 和资料用途;消费者不得把它转换为本机绝对路径。
|
||||
|
||||
该协议避免核心插件依赖缓存目录,也避免把 Agent 的 Skill 选择描述成确定性代码调用。
|
||||
|
||||
## 6. 项目画像设计
|
||||
|
||||
### 6.1 Schema 版本
|
||||
|
||||
`.craftkit/project.json` 从 `schemaVersion: 1` 兼容演进至 `schemaVersion: 2`。版本 2 增加模块级技术栈和 Profile 绑定,保留版本 1 的顶层字段。
|
||||
|
||||
建议结构:
|
||||
|
||||
```json
|
||||
{
|
||||
"schemaVersion": 2,
|
||||
"initialization": {
|
||||
"mode": "existing",
|
||||
"references": []
|
||||
},
|
||||
"project": {
|
||||
"name": "sample",
|
||||
"description": "",
|
||||
"type": "multi-module"
|
||||
},
|
||||
"technology": {
|
||||
"languages": ["Python"],
|
||||
"frameworks": [
|
||||
{
|
||||
"name": "fastapi",
|
||||
"version": "0.115.0",
|
||||
"profile": "python/fastapi-0"
|
||||
}
|
||||
],
|
||||
"buildTools": [],
|
||||
"databases": []
|
||||
},
|
||||
"modules": [
|
||||
{
|
||||
"id": "api",
|
||||
"root": ".",
|
||||
"kind": "backend",
|
||||
"technology": {
|
||||
"languages": [
|
||||
{
|
||||
"name": "python",
|
||||
"version": "3.12",
|
||||
"evidence": ["pyproject.toml"]
|
||||
}
|
||||
],
|
||||
"frameworks": [
|
||||
{
|
||||
"name": "fastapi",
|
||||
"version": "0.115.0",
|
||||
"evidence": ["uv.lock"]
|
||||
}
|
||||
],
|
||||
"preferredProfiles": ["python/default", "python/fastapi-0"]
|
||||
}
|
||||
}
|
||||
],
|
||||
"commands": {
|
||||
"build": [],
|
||||
"test": ["uv run pytest"],
|
||||
"check": ["uv run ruff check ."]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 6.2 字段规则
|
||||
|
||||
- 顶层 `technology` 保持 Schema 1 的字段类型,作为旧消费者可读取的仓库概要。
|
||||
- `modules[].technology` 记录模块级语言、框架、精确版本、证据和 Profile 偏好。
|
||||
- `modules` 描述多模块仓库中的技术边界;单模块项目仍生成一个根模块。
|
||||
- `modules[].preferredProfiles` 记录项目确认的 Profile 偏好,不代表当前机器已经安装对应插件。
|
||||
- `commands` 继续记录项目文件或用户确认的真实命令,不由公共 Profile 直接覆盖。
|
||||
- 识别证据使用项目相对路径;运行时输出和用户机器绝对路径不进入共享画像。
|
||||
|
||||
### 6.3 兼容读取
|
||||
|
||||
| 输入状态 | 读取行为 |
|
||||
| --- | --- |
|
||||
| `schemaVersion: 1` | 将顶层技术栈视为根模块候选,不自动改写文件 |
|
||||
| 语言仍是字符串 | 解析名称,版本和 Profile 保持未知 |
|
||||
| 没有 `modules` | 根据代码根和目标路径临时推导根模块 |
|
||||
| Profile 不存在 | 保留技术事实,将 Profile 标记为未解析 |
|
||||
| 新旧证据冲突 | 保留原值并展示差异,确认后更新 |
|
||||
|
||||
Schema 升级只由 `knowledge:init` 或后续明确的迁移能力执行。普通设计、实现和审查 Skill 不修改项目画像。
|
||||
|
||||
## 7. 核心流程设计
|
||||
|
||||
### 7.1 初始化流程
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant U as 用户
|
||||
participant I as knowledge:init
|
||||
participant R as profile:resolve
|
||||
participant P as 技术能力提供方
|
||||
participant J as project.json
|
||||
|
||||
I->>I: 通用扫描项目文件与模块
|
||||
I->>R: 请求 project-detection
|
||||
R->>P: 按证据匹配已安装提供方
|
||||
P-->>R: 返回探测规则与候选 Profile
|
||||
R-->>I: 返回已识别、冲突和待确认项
|
||||
I-->>U: 展示证据与拟写入内容
|
||||
U-->>I: 确认或修正
|
||||
I->>J: 保守合并项目画像
|
||||
I->>R: 验证持久化后的解析结果
|
||||
R-->>I: 返回验证结果
|
||||
```
|
||||
|
||||
状态变化:
|
||||
|
||||
- 写入前:项目扫描结果只存在于任务上下文。
|
||||
- 用户确认后:`knowledge:init` 单点写入或合并 `.craftkit/project.json`。
|
||||
- 写入失败:保留原文件,不允许语言插件继续部分写入。
|
||||
- 验证失败:报告已写入内容和失败原因,由初始化 Skill决定回滚或修正。
|
||||
|
||||
### 7.2 后端设计流程
|
||||
|
||||
`dev:design-backend` 接入后执行以下步骤:
|
||||
|
||||
1. 读取需求、目标模块、项目画像和现有实现。
|
||||
2. 请求 `backend-design` 能力。
|
||||
3. Profile 工厂解析语言、框架、版本和项目覆盖规则。
|
||||
4. 技术插件提供当前版本适用的设计资料入口。
|
||||
5. `design-backend` 合并通用边界与专项约束。
|
||||
6. 输出统一的模块、依赖、数据、事务、错误、权限和测试设计。
|
||||
7. 输出中标明使用的 Profile、项目覆盖规则和未覆盖能力。
|
||||
|
||||
语言插件不生成最终设计文档。最终责任仍属于 `design-backend`,从而保证不同语言的设计产物结构一致。
|
||||
|
||||
### 7.3 实现和测试流程
|
||||
|
||||
- `implement-backend` 请求 `backend-implementation` 和 `command-resolution`。
|
||||
- `test-backend` 请求 `backend-testing` 和 `command-resolution`。
|
||||
- Profile 提供命令选择规则,最终命令必须由项目文件或用户确认支持。
|
||||
- 写代码和测试的权限、范围控制及 Git 边界继续由原核心 Skill 负责。
|
||||
- 技术插件不能因提供某种工具规则而自动安装工具或新增项目依赖。
|
||||
|
||||
### 7.4 知识检索流程
|
||||
|
||||
`skill:guidance` 保留现有来源优先级,并在公共基线之前增加 Profile 解析:
|
||||
|
||||
1. 用户要求与目标目录 `AGENTS.md`。
|
||||
2. `.craftkit/project.json` 和目标模块。
|
||||
3. 项目 `.craftkit/standards/` 与 `.craftkit/knowledge/`。
|
||||
4. 已解析技术 Profile 的 `knowledge-routing` 入口。
|
||||
5. CraftKit 中性公共基线。
|
||||
6. 现有代码观察结果。
|
||||
|
||||
项目规则与 Profile 冲突时采用项目规则,并在输出中同时给出两者来源。
|
||||
|
||||
## 8. 版本与冲突处理
|
||||
|
||||
### 8.1 Profile 选择
|
||||
|
||||
Profile 选择按以下顺序执行:
|
||||
|
||||
1. 使用项目画像中已确认的 Profile 偏好,并检查当前会话是否发现对应提供方。
|
||||
2. Profile 未记录时,根据精确版本匹配唯一候选。
|
||||
3. 多个候选同时匹配时,优先选择范围更窄且框架证据更具体的候选。
|
||||
4. 仍不能唯一确定时,不自动选择,返回候选和差异。
|
||||
5. 没有版本匹配时,只加载版本中性资料。
|
||||
|
||||
### 8.2 多模块仓库
|
||||
|
||||
- 先用目标路径匹配 `modules[].root`,最长路径匹配优先。
|
||||
- 同一目标同时命中多个同长度模块时视为配置冲突。
|
||||
- 跨模块任务分别解析各模块 Profile,不合并为单一技术栈。
|
||||
- 前后端联调通过 API 契约协作,不将后端语言规则加载到前端实现。
|
||||
|
||||
### 8.3 能力状态
|
||||
|
||||
| 状态 | 含义 | 消费者行为 |
|
||||
| --- | --- | --- |
|
||||
| `available` | 已安装、版本匹配且资料完整 | 正常加载 |
|
||||
| `generic` | 只有版本中性资料 | 使用通用规则并说明范围 |
|
||||
| `missing` | 提供方或能力不存在 | 核心流程继续,报告缺口 |
|
||||
| `incompatible` | Profile 与项目版本不匹配 | 禁止加载冲突资料 |
|
||||
| `ambiguous` | 多个候选无法唯一选择 | 请求最小必要确认 |
|
||||
| `invalid` | 清单或引用校验失败 | 隔离该提供方并报告错误 |
|
||||
|
||||
## 9. 可靠性、安全与可观测性
|
||||
|
||||
### 9.1 一致性
|
||||
|
||||
- 只有 `knowledge:init` 可以在初始化流程中写项目画像,防止多个提供方并发覆盖。
|
||||
- Profile 解析是只读、可重复执行的过程,相同项目事实和能力版本应得到相同结果。
|
||||
- 写入项目画像前保留原内容,采用完整 JSON 校验后再替换目标文件。
|
||||
- 数组按语义标识去重,不能因路径分隔符或大小写产生重复模块和证据。
|
||||
|
||||
### 9.2 安全边界
|
||||
|
||||
- 探测器只读取依赖名称、版本、脚本和非敏感元数据。
|
||||
- `.env`、凭据文件、令牌、私钥和完整仓库认证信息不作为 Profile 证据。
|
||||
- 公共能力包不得保存内部包源码、公司规范或业务项目内容。
|
||||
- Profile 提供的命令是选择规则,不构成执行授权。
|
||||
- 实现、测试、提交和发布仍遵循对应核心 Skill 的权限规则。
|
||||
|
||||
### 9.3 诊断输出
|
||||
|
||||
每次 Profile 解析至少能够报告:
|
||||
|
||||
- 目标模块及匹配依据。
|
||||
- 语言、框架、版本和证据路径。
|
||||
- 命中的 Profile 与能力状态。
|
||||
- 项目规则覆盖情况。
|
||||
- 缺失、冲突、无效和版本不匹配项。
|
||||
- 当前核心 Skill 可以继续执行的范围。
|
||||
|
||||
诊断信息默认在任务中输出,不在项目中生成运行日志。
|
||||
|
||||
## 10. 迁移设计
|
||||
|
||||
### 10.1 迁移原则
|
||||
|
||||
- 先增加契约和提供方,再改造消费者。
|
||||
- 先逻辑分层,再迁移目录和用户入口。
|
||||
- 每个消费者独立接入并验证,不一次修改所有 Skill。
|
||||
- 旧项目画像只读兼容,新字段在明确初始化或迁移时写入。
|
||||
- 旧 Skill 入口至少保留一个兼容发布周期,避免用户已保存的调用失效。
|
||||
|
||||
### 10.2 存量内容迁移
|
||||
|
||||
| 存量内容 | 首期处理 | 后续处理 |
|
||||
| --- | --- | --- |
|
||||
| `dev:review-java` | 保留入口,改为读取 Java Profile | 稳定后评估迁入 Java 插件 |
|
||||
| `guidance` 公共后端规则 | 保留中性规则 | Java/Python 专项内容迁入对应插件 |
|
||||
| `guidance` 版本路由 | 按目标模块读取当前会话已发现的提供方 | 旧文档改为契约说明入口 |
|
||||
| `knowledge:init` 探测规则 | 保留通用扫描 | 技术专项识别由提供方补充 |
|
||||
| `project.json` 模板 | 保留 Schema 1 兼容读取 | 初始化确认后写 Schema 2 |
|
||||
| `dev` 后端 Skill | 逐个接入 Profile | 完成后移除重复专项资料 |
|
||||
|
||||
### 10.3 回滚
|
||||
|
||||
- 新插件尚未发布时,删除 marketplace 新增项即可恢复原安装集合。
|
||||
- 消费者接入必须保留“未找到 Profile 时执行原通用流程”的分支。
|
||||
- Schema 2 画像不能直接降级覆盖为 Schema 1;回滚核心插件时保留文件,并按已知顶层字段读取。
|
||||
- 技术资料迁移前保留 Git 历史,完成所有消费者切换后才能删除原位置。
|
||||
|
||||
## 11. 实施方案
|
||||
|
||||
### 11.1 批次 A:Profile 契约和工厂骨架
|
||||
|
||||
**新增文件**
|
||||
|
||||
```text
|
||||
plugins/profile/.codex-plugin/plugin.json
|
||||
plugins/profile/skills/resolve/SKILL.md
|
||||
plugins/profile/skills/resolve/agents/openai.yaml
|
||||
plugins/profile/skills/resolve/references/contract.md
|
||||
plugins/profile/skills/resolve/references/detection.md
|
||||
plugins/profile/skills/resolve/references/resolution.md
|
||||
plugins/profile/skills/resolve/references/fallback.md
|
||||
plugins/profile/skills/resolve/scripts/validate_profile.py
|
||||
```
|
||||
|
||||
**修改文件**
|
||||
|
||||
```text
|
||||
.agents/plugins/marketplace.json
|
||||
README.md
|
||||
CHANGELOG.md
|
||||
```
|
||||
|
||||
**任务**
|
||||
|
||||
1. 定义提供方清单和标准能力上下文。
|
||||
2. 实现契约静态校验器。
|
||||
3. 编写模块匹配、版本选择、能力状态和回退规则。
|
||||
4. 注册 `profile` 插件并补充安装说明。
|
||||
|
||||
**验收**
|
||||
|
||||
- 有效、缺字段、重复标识、无效版本范围和失效引用五类样例均有确定结果。
|
||||
- `profile` 单独安装时能够解释缺少技术提供方并返回 `missing`。
|
||||
|
||||
### 11.2 批次 B:Java 基准提供方
|
||||
|
||||
**新增文件**
|
||||
|
||||
```text
|
||||
plugins/java/.codex-plugin/plugin.json
|
||||
plugins/java/skills/profile/SKILL.md
|
||||
plugins/java/skills/profile/agents/openai.yaml
|
||||
plugins/java/skills/profile/references/manifest.json
|
||||
plugins/java/skills/profile/references/index.md
|
||||
plugins/java/skills/profile/references/language/index.md
|
||||
plugins/java/skills/profile/references/build/index.md
|
||||
plugins/java/skills/profile/references/frameworks/spring/index.md
|
||||
plugins/java/skills/profile/references/testing/index.md
|
||||
plugins/java/skills/profile/references/review/index.md
|
||||
```
|
||||
|
||||
**修改文件**
|
||||
|
||||
```text
|
||||
.agents/plugins/marketplace.json
|
||||
plugins/dev/skills/review-java/SKILL.md
|
||||
plugins/dev/skills/review-java/references/sources.md
|
||||
README.md
|
||||
CHANGELOG.md
|
||||
```
|
||||
|
||||
**任务**
|
||||
|
||||
1. 将现有 Java 规则映射到能力清单。
|
||||
2. 建立 JDK、Maven/Gradle 和 Spring 的渐进加载入口。
|
||||
3. 让 `dev:review-java` 读取 Java Profile;未安装时使用现有最小基线。
|
||||
4. 使用现有 Java 项目验证路由和回退。
|
||||
|
||||
**验收**
|
||||
|
||||
- Java 版本和构建工具有项目证据。
|
||||
- Spring 资料只在依赖和版本匹配时加载。
|
||||
- `review-java` 的现有触发范围和审查输出不退化。
|
||||
|
||||
### 11.3 批次 C:Python 最小提供方
|
||||
|
||||
**新增文件**
|
||||
|
||||
```text
|
||||
plugins/python/.codex-plugin/plugin.json
|
||||
plugins/python/skills/profile/SKILL.md
|
||||
plugins/python/skills/profile/agents/openai.yaml
|
||||
plugins/python/skills/profile/references/manifest.json
|
||||
plugins/python/skills/profile/references/index.md
|
||||
plugins/python/skills/profile/references/language/index.md
|
||||
plugins/python/skills/profile/references/packaging/index.md
|
||||
plugins/python/skills/profile/references/frameworks/fastapi/index.md
|
||||
plugins/python/skills/profile/references/persistence/index.md
|
||||
plugins/python/skills/profile/references/testing/index.md
|
||||
plugins/python/skills/profile/references/review/index.md
|
||||
plugins/python/skills/review-python/SKILL.md
|
||||
plugins/python/skills/review-python/agents/openai.yaml
|
||||
```
|
||||
|
||||
**修改文件**
|
||||
|
||||
```text
|
||||
.agents/plugins/marketplace.json
|
||||
README.md
|
||||
CHANGELOG.md
|
||||
```
|
||||
|
||||
**任务**
|
||||
|
||||
1. 支持 `pyproject.toml`、依赖文件、锁文件和 Python 版本证据。
|
||||
2. 支持 pip、uv、Poetry、PDM 和 Pipenv 的项目内选择。
|
||||
3. 建立 Python 通用、FastAPI、pytest、Ruff 和类型检查资料入口。
|
||||
4. 新增 Python 专项审查 Skill。
|
||||
5. 使用 FastAPI 项目验证语言、框架、测试和审查能力。
|
||||
|
||||
**验收**
|
||||
|
||||
- 不配置 Ruff、mypy 或 pyright 的项目不会被假定具备对应命令。
|
||||
- 同步与异步规则按真实代码和框架配置选择。
|
||||
- Python 版本未知时不输出版本专属语法升级建议。
|
||||
|
||||
### 11.4 批次 D:初始化和画像 Schema 2
|
||||
|
||||
**修改文件**
|
||||
|
||||
```text
|
||||
plugins/knowledge/skills/init/SKILL.md
|
||||
plugins/knowledge/skills/init/references/existing.md
|
||||
plugins/knowledge/skills/init/references/new.md
|
||||
plugins/knowledge/skills/init/references/project-config.md
|
||||
plugins/knowledge/skills/init/assets/project.json
|
||||
plugins/knowledge/skills/init/assets/AGENTS.md
|
||||
```
|
||||
|
||||
**新增文件**
|
||||
|
||||
```text
|
||||
plugins/knowledge/skills/init/references/profile-resolution.md
|
||||
plugins/knowledge/skills/init/references/project-schema-v2.md
|
||||
```
|
||||
|
||||
**任务**
|
||||
|
||||
1. 将通用扫描与技术提供方探测分离。
|
||||
2. 增加模块级技术栈和识别证据。
|
||||
3. 定义 Schema 1 到 Schema 2 的保守合并规则。
|
||||
4. 初始化结束后调用 Profile 解析做一致性验证。
|
||||
|
||||
**验收**
|
||||
|
||||
- Java、Python、前后端混合和旧版画像四类项目均能完成初始化。
|
||||
- 未安装语言插件时仍能记录技术事实,但 Profile 保持未解析。
|
||||
- 已有未知字段和用户章节不会被删除。
|
||||
|
||||
### 11.5 批次 E:规范检索和核心后端消费者
|
||||
|
||||
**修改文件**
|
||||
|
||||
```text
|
||||
plugins/skill/skills/guidance/SKILL.md
|
||||
plugins/skill/skills/guidance/references/profile-routing.md
|
||||
plugins/dev/skills/design-backend/SKILL.md
|
||||
plugins/dev/skills/implement-backend/SKILL.md
|
||||
plugins/dev/skills/test-backend/SKILL.md
|
||||
```
|
||||
|
||||
**任务**
|
||||
|
||||
1. `guidance` 将 Profile 知识入口纳入渐进加载顺序。
|
||||
2. `design-backend` 请求 `backend-design` 能力。
|
||||
3. `implement-backend` 请求 `backend-implementation` 和 `command-resolution`。
|
||||
4. `test-backend` 请求 `backend-testing` 和 `command-resolution`。
|
||||
5. 三个核心 Skill 统一报告命中 Profile、覆盖规则和能力缺口。
|
||||
|
||||
**验收**
|
||||
|
||||
- 相同后端需求在 Spring Boot 和 FastAPI 项目中使用不同专项知识,但输出结构一致。
|
||||
- 目标模块技术栈不明确时不会加载仓库中其他模块的 Profile。
|
||||
- 语言插件缺失时核心 Skill 可按原中性流程完成可确认部分。
|
||||
|
||||
### 11.6 批次 F:框架补全和前端接入
|
||||
|
||||
**任务**
|
||||
|
||||
- 补充 Django、Flask、SQLAlchemy、Alembic 和 Django ORM。
|
||||
- 建立 Frontend Profile、`review-typescript` 和 `test-frontend`。
|
||||
- 通过 `design-api` 与 `prepare-api` 验证不同后端语言到前端的统一契约。
|
||||
- 根据实际维护成本决定是否迁移 `review-java` 到 Java 插件。
|
||||
|
||||
**验收**
|
||||
|
||||
- 框架 Profile 可以独立演进,不修改核心工作流步骤。
|
||||
- 前端消费者只读取 API 契约和前端 Profile,不加载后端语言实现规则。
|
||||
|
||||
## 12. 测试方案
|
||||
|
||||
### 12.1 静态校验
|
||||
|
||||
- 校验插件目录、`plugin.json`、Skill frontmatter 和 `agents/openai.yaml`。
|
||||
- 校验 Profile 清单 Schema、能力枚举、版本范围和引用路径。
|
||||
- 扫描跨插件物理路径和用户缓存绝对路径。
|
||||
- 检查空资料、占位符、重复 Profile 标识和失效链接。
|
||||
|
||||
### 12.2 路由场景
|
||||
|
||||
| 编号 | 场景 | 预期能力状态 |
|
||||
| --- | --- | --- |
|
||||
| R1 | Java 17、Spring Boot 3、Maven Wrapper | Java 与 Spring `available` |
|
||||
| R2 | Python 3.12、FastAPI、uv | Python 与 FastAPI `available` |
|
||||
| R3 | Python 项目无质量工具 | 语言能力可用,未配置工具不进入命令 |
|
||||
| R4 | Python 版本未知 | Python `generic`,版本专属规则不加载 |
|
||||
| R5 | 项目版本超出 Profile 范围 | 对应能力 `incompatible` |
|
||||
| R6 | 未安装 Python 插件 | Python 专项能力 `missing`,核心流程继续 |
|
||||
| R7 | Java/Python 混合仓库 | 根据目标模块分别解析 |
|
||||
| R8 | 两个同长度模块同时匹配 | 解析结果 `ambiguous` |
|
||||
| R9 | Profile 引用文件缺失 | 提供方 `invalid` 并被隔离 |
|
||||
| R10 | 项目规范覆盖公共规则 | 返回覆盖来源并采用项目规则 |
|
||||
|
||||
### 12.3 端到端场景
|
||||
|
||||
分别准备一个最小 Spring Boot 项目和一个最小 FastAPI 项目,对两者执行相同任务:
|
||||
|
||||
1. 初始化项目画像。
|
||||
2. 查询后端规范。
|
||||
3. 设计一个包含事务和外部调用的后端功能。
|
||||
4. 给出最小实现变更。
|
||||
5. 生成并运行聚焦测试。
|
||||
6. 执行语言专项审查。
|
||||
|
||||
验证重点:
|
||||
|
||||
- 每一步使用了正确模块和 Profile。
|
||||
- 项目已有命令优先于公共建议。
|
||||
- 设计产物结构一致,语言实现规则不同。
|
||||
- 缺失工具不会被隐式安装或写入项目。
|
||||
- 失败结果能够区分项目缺陷、环境问题和 Profile 缺口。
|
||||
|
||||
## 13. 发布方案
|
||||
|
||||
### 13.1 发布顺序
|
||||
|
||||
1. 发布 `profile` 插件及契约。
|
||||
2. 发布 Java 基准插件。
|
||||
3. 发布 Python 最小插件。
|
||||
4. 发布接入新版契约的 `knowledge` 和 `skill` 插件。
|
||||
5. 发布接入新版契约的 `dev` 插件。
|
||||
6. 完成一轮双语言端到端回归后,再补充 Frontend 插件。
|
||||
|
||||
### 13.2 版本影响
|
||||
|
||||
- 新增独立插件使用 `0.1.0` 起始版本。
|
||||
- 核心插件新增可回退的 Profile 增强时升级次版本。
|
||||
- 删除或移动已有 Skill 入口属于不兼容变更,必须单独规划主版本。
|
||||
- `.craftkit/project.json` Schema 2 在保留 Schema 1 读取能力时属于向后兼容能力;停止读取 Schema 1 才属于不兼容变化。
|
||||
|
||||
### 13.3 安装组合
|
||||
|
||||
| 使用场景 | 建议安装 |
|
||||
| --- | --- |
|
||||
| 通用项目管理 | `knowledge`、`skill`、`profile` |
|
||||
| Java 后端 | 通用组合 + `dev` + `java` |
|
||||
| Python 后端 | 通用组合 + `dev` + `python` |
|
||||
| 前后端项目 | 对应后端组合 + `frontend` |
|
||||
| 仅使用通用开发流程 | `dev`,Profile 缺失时按中性流程回退 |
|
||||
|
||||
## 14. 实现交接清单
|
||||
|
||||
编码按以下已定口径执行:
|
||||
|
||||
- Profile 清单采用 JSON,校验器仅依赖 Python 标准库。
|
||||
- 插件之间不要求平台提供可选依赖声明,通过能力契约、安装说明和回退状态协作。
|
||||
- `.craftkit/project.json` 采用兼容的 Schema 2,对 Schema 1 保持只读兼容。
|
||||
- `dev:review-java` 首期保留一个兼容发布周期,只把公共知识来源切换到 Java Profile。
|
||||
- Python 先提供版本中性 Profile;版本专项 Profile 必须依据纳入支持范围的真实项目和官方资料另行建立。
|
||||
- 双语言验证优先使用仓库内无业务数据的最小夹具;引入外部项目时另行确认扫描范围和命令。
|
||||
|
||||
实施按 A 到 F 顺序进行。每个批次独立提交、独立验证;前一批次契约或回退未通过时,不进入下一个消费者改造批次。
|
||||
|
||||
## 15. 设计自检结论
|
||||
|
||||
- 职责明确:工厂只解析,技术插件只提供能力,核心 Skill 负责最终工作流。
|
||||
- 依赖单向:消费者依赖契约,不依赖技术插件物理目录。
|
||||
- 数据所有权明确:项目画像由 `knowledge:init` 写入,技术插件只读。
|
||||
- 失败状态明确:缺失、不兼容、歧义和无效清单均有独立状态和回退。
|
||||
- 兼容策略明确:保留 Schema 1 读取、现有 Skill 入口和无 Profile 通用流程。
|
||||
- 安全边界明确:Profile 探测不读取凭据,命令建议不构成执行授权。
|
||||
- 验证完整:覆盖静态契约、路由组合和 Java/Python 端到端场景。
|
||||
- 实施可拆分:六个批次均有文件范围、任务和验收标准。
|
||||
@@ -0,0 +1,60 @@
|
||||
---
|
||||
reviewStatus: pending
|
||||
reviewedAt: null
|
||||
replacedBy: null
|
||||
---
|
||||
|
||||
# 多语言插件架构改造计划
|
||||
|
||||
## 1. 文档职责
|
||||
|
||||
本文只跟踪多语言插件架构的实施批次、前置依赖、验证门禁和完成状态。架构、契约、项目画像及运行机制以[《多语言插件架构设计与实施方案》](MULTI-LANGUAGE-PLUGIN-ARCHITECTURE-DESIGN.md)为唯一依据。
|
||||
|
||||
详细执行记录位于 `.craftkit/local/tasks/multi-language-plugin/`,不在本文复制过程步骤。
|
||||
|
||||
## 2. 当前决策
|
||||
|
||||
- 首期建立 `profile`、`java` 和 `python` 独立插件骨架,但在安装组合通过前不声明可独立交付。
|
||||
- Profile 插件维护静态契约、匹配规则和校验器,不扫描插件缓存,也不把 Skill 协作描述为函数调用。
|
||||
- 消费者从当前会话已发现的提供方 Skill 获取专项能力;提供方缺失时执行通用回退。
|
||||
- `knowledge:init` 是项目画像的唯一写入者,`guidance` 是项目规则与公共规则的合并入口。
|
||||
- Schema 2 先由消费者双读,再由初始化入口写入。
|
||||
- 插件安装状态不进入共享项目画像。
|
||||
|
||||
## 3. 实施批次
|
||||
|
||||
| 批次 | 目标 | 前置依赖 | 核心产物 | 状态 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| P0 | 收敛文档并验证平台机制 | 无 | 架构决策、最小插件骨架、验证记录 | 已完成(运行时验证转 P6) |
|
||||
| P1 | 建立 Profile 静态契约 | P0 | JSON Schema、解析规则、校验器 | 已完成 |
|
||||
| P2 | 建立 Java/Python 最小提供方 | P1 | 双提供方 manifest 和专项资料 | 已完成静态实现 |
|
||||
| P3 | 接入首个核心消费者 | P2 | `design-backend` 双语言路由 | 已完成实现,待新会话验证 |
|
||||
| P4 | 建立 Schema 1/2 双读 | P3 | 模块级画像、迁移与回滚规则 | 已完成实现 |
|
||||
| P5 | 逐个接入核心消费者 | P4 | 设计、实现、测试、审查闭环 | 已完成实现,待新会话验证 |
|
||||
| P6 | 验证独立安装和发布 | P5 | 安装矩阵、兼容矩阵、发布材料 | 部分完成,运行时验证待处理 |
|
||||
| P7 | 按需求扩展框架和前端 | P6 | 可独立验证的增量能力 | 待执行 |
|
||||
|
||||
## 4. 阶段门禁
|
||||
|
||||
每个批次必须分别记录:
|
||||
|
||||
1. 实际修改范围。
|
||||
2. 静态校验结果。
|
||||
3. 真实或最小可运行场景验证结果。
|
||||
4. 未验证边界。
|
||||
5. 停止条件检查。
|
||||
6. 是否允许进入下一批次。
|
||||
|
||||
静态清单或脚本校验通过不代表 Codex 运行时行为已经验证。跨插件发现、Skill 激活和缺失回退必须在安装后的新会话中验证。
|
||||
|
||||
## 5. 总体验收
|
||||
|
||||
- Java 与 Python 提供方遵循同一契约。
|
||||
- 核心 Skill 不复制语言专属工作流。
|
||||
- Schema 1 和 Schema 2 均可读取。
|
||||
- 多模块仓库按目标路径解析技术栈。
|
||||
- 缺少提供方、版本未知和版本不兼容都有确定回退。
|
||||
- 项目规范覆盖公共 Profile 时保留双方来源。
|
||||
- Spring Boot 和 FastAPI 完成同一请求的端到端对照。
|
||||
- 核心、Profile、Java 和 Python 的安装组合全部验证。
|
||||
- 现有 Java 与通用工作流没有回归。
|
||||
@@ -0,0 +1,9 @@
|
||||
# 项目知识索引
|
||||
|
||||
当前没有已验证的项目知识。只收录有证据、适用范围明确且能够复用的技术决策与经验。
|
||||
|
||||
长期知识按 `.craftkit/standards/document-maintenance.md` 保存审核状态并持续更新;过时或历史材料不得作为当前有效依据。
|
||||
|
||||
- 问题经验按需建立在 `pitfalls/`,不预建空分类。
|
||||
- 重要技术决策按需建立在 `decisions/`。
|
||||
- 其他长期知识应优先并入已有主题,避免同义平行文档。
|
||||
@@ -0,0 +1,71 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"initialization": {
|
||||
"mode": "existing",
|
||||
"references": []
|
||||
},
|
||||
"project": {
|
||||
"name": "CraftKit",
|
||||
"description": "面向 Codex 插件市场的通用插件工具集,提供可独立安装和维护的 Skill。",
|
||||
"type": "codex-plugin-collection"
|
||||
},
|
||||
"technology": {
|
||||
"languages": [
|
||||
"Markdown",
|
||||
"JSON",
|
||||
"YAML",
|
||||
"Python"
|
||||
],
|
||||
"frameworks": [],
|
||||
"buildTools": [],
|
||||
"databases": []
|
||||
},
|
||||
"code": {
|
||||
"sourceRoots": [
|
||||
"plugins"
|
||||
],
|
||||
"packageRoots": [],
|
||||
"modules": [
|
||||
"plugins/dev",
|
||||
"plugins/doc",
|
||||
"plugins/git",
|
||||
"plugins/knowledge",
|
||||
"plugins/skill",
|
||||
"plugins/profile",
|
||||
"plugins/java",
|
||||
"plugins/python"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"internal": [],
|
||||
"public": []
|
||||
},
|
||||
"frontend": {
|
||||
"framework": "",
|
||||
"componentLibraries": [],
|
||||
"componentRoots": [],
|
||||
"documentation": []
|
||||
},
|
||||
"commands": {
|
||||
"build": [],
|
||||
"test": [],
|
||||
"check": []
|
||||
},
|
||||
"documents": {
|
||||
"workRoot": ".craftkit/local/tasks",
|
||||
"designRoot": ".craftkit/designs",
|
||||
"archiveRoot": "docs/archive",
|
||||
"archiveRules": [],
|
||||
"lifecycle": {
|
||||
"onTaskComplete": "preview",
|
||||
"localRetentionDays": 7,
|
||||
"trackedFiles": "review-required",
|
||||
"personalConfig": "retain"
|
||||
}
|
||||
},
|
||||
"guidance": {
|
||||
"agentIndex": ".craftkit/agents/index.md",
|
||||
"standardsIndex": ".craftkit/standards/index.md",
|
||||
"knowledgeIndex": ".craftkit/knowledge/index.md"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
reviewStatus: approved
|
||||
reviewedAt: 2026-09-03
|
||||
replacedBy: null
|
||||
---
|
||||
|
||||
# 文档维护规范
|
||||
|
||||
## 适用范围
|
||||
|
||||
本规范适用于项目正式需求、生效设计、项目规范和长期知识。过程草稿按任务需要维护,不强制逐份审核;历史归档保留当时快照,不作为当前依据。
|
||||
|
||||
## 创建与更新
|
||||
|
||||
- 任务开始时查找相关已有文档,优先更新现有权威内容,不创建同义平行版本。
|
||||
- 新建或实质修改长期文档后,将文档自身的 `reviewStatus` 标为 `pending`。
|
||||
- 项目已有审批结果可以直接作为审核依据;通过后标为 `approved`。
|
||||
- 已知文档与需求、实现或新证据不一致时标为 `outdated`;更新后回到 `pending` 并重新审核。
|
||||
- 排版、错字、链接修复和不改变含义的调整不改变审核状态。
|
||||
|
||||
## 状态与替代
|
||||
|
||||
项目没有既有元数据格式时,在文档 Frontmatter 使用 `reviewStatus`、`reviewedAt` 和 `replacedBy`。旧文档缺少状态时视为尚未确认,只在实际使用或修改时补齐。
|
||||
|
||||
新版替代旧版时更新索引和引用,并通过 `replacedBy` 指向当前版本。旧版根据历史价值归档或删除;归档发现错误时补充勘误和新版链接,不改写历史事实。
|
||||
|
||||
## 任务关联与关闭
|
||||
|
||||
本地 `task.json` 记录本次创建、更新或引用的文档。关联旧文档不转移所有权,也不产生删除权限。
|
||||
|
||||
任务关闭前检查本次实现影响的长期文档已经同步。需要作为当前依据的文档必须为 `approved`;`pending` 或 `outdated` 文档应完成处理,无法处理时列入延后清单并说明影响。
|
||||
@@ -0,0 +1,5 @@
|
||||
# 项目规范索引
|
||||
|
||||
- [文档维护规范](document-maintenance.md):正式需求、设计、规范和长期知识的创建、审核、更新、替代及任务关闭规则。
|
||||
|
||||
新增规范时记录主题、适用范围、规则文件和优先级;未覆盖主题可由 `guidance` 查询中性公共基线。
|
||||
@@ -4,7 +4,15 @@
|
||||
|
||||
## 项目目标
|
||||
|
||||
CraftKit 面向 Codex 插件市场,提供简洁、中性、可独立安装的 Skill。所有能力必须能够脱离来源项目独立理解、验证和维护。
|
||||
CraftKit 面向 Codex 插件市场,提供简洁、中性、可独立安装和维护的 Skill。每项能力都应具备清晰边界,并能够独立理解与验证。
|
||||
|
||||
## 项目资料
|
||||
|
||||
- 结构化项目配置:`.craftkit/project.json`
|
||||
- Agent 补充说明:`.craftkit/agents/index.md`
|
||||
- 项目规范索引:`.craftkit/standards/index.md`
|
||||
- 项目知识索引:`.craftkit/knowledge/index.md`
|
||||
- 文档目录配置:`.craftkit/project.json` 的 `documents`;过程文档、共享设计和归档目录必须分开使用。
|
||||
|
||||
## 沟通与改动
|
||||
|
||||
@@ -23,8 +31,7 @@ CraftKit 面向 Codex 插件市场,提供简洁、中性、可独立安装的
|
||||
| `plugins/doc/` | 文档转换、整理与写作 Skill |
|
||||
| `plugins/git/` | Git 操作与交付 Skill |
|
||||
| `plugins/knowledge/` | 交接、复盘与知识维护 Skill |
|
||||
| `plugins/skill/` | Skill 创建、迁移、检查与同步工具 |
|
||||
| `migration/` | 来源指纹、迁移计划和状态追踪,不进入插件发布内容 |
|
||||
| `plugins/skill/` | Skill 与项目规范辅助工具 |
|
||||
|
||||
## Skill 设计规则
|
||||
|
||||
@@ -44,143 +51,52 @@ plugins/<plugin>/skills/<skill>/
|
||||
├─ SKILL.md
|
||||
├─ agents/openai.yaml # 有 UI 元数据时使用
|
||||
├─ scripts/ # 有确定性自动化时使用
|
||||
├─ references/ # 有条件加载的详细资料时使用
|
||||
├─ references/ # 有条件加载的详细资料
|
||||
└─ assets/ # 生成产物需要的素材
|
||||
```
|
||||
|
||||
## 维护原则
|
||||
|
||||
- 以当前 Codex 能力、项目实际情况、公开标准和用户需求为依据设计 Skill。
|
||||
- 技术规则应注明适用版本;依赖外部资料时记录资料入口和验证日期。
|
||||
- 新增内容应具备明确用途,避免重复能力、过期说明和仅用于记录开发过程的文档。
|
||||
|
||||
## 新增与修改流程
|
||||
|
||||
1. 阅读目标插件、相邻 Skill、适用的 `AGENTS.md` 和当前 Git 状态,确认职责边界与已有改动。
|
||||
2. 明确用户目标、输入、输出、触发条件、副作用、权限和不包含事项。
|
||||
3. 检查是否应复用或扩展已有 Skill,避免名称不同但职责重复的实现。
|
||||
4. 修改前向用户说明目标文件、实现方式、风险和验证方法;高风险或范围不明确时等待确认。
|
||||
5. 按最小必要结构实现,优先使用项目证据和官方资料,不猜测接口、版本或运行行为。
|
||||
6. 完成结构、引用、插件清单及必要行为验证,并分别记录通过项和未验证边界。
|
||||
7. 展示实际变更、验证结果、剩余风险和建议提交信息;只有用户明确授权后才执行本地提交。
|
||||
|
||||
## CraftKit 项目目录
|
||||
|
||||
- `.craftkit/` 是项目级 Agent 配置、规范、知识和运行状态的统一目录,目录名固定为全小写;不能把整个目录视为本地缓存或整体排除。
|
||||
- 可共享内容包括 `project.json`、`agents/`、`standards/`、`knowledge/` 和 `handoff/`,可以根据用户确认正常提交和同步。
|
||||
- `project.json` 记录项目类型、技术栈、源码与包边界、内部依赖标识、常用命令和规范入口;不得记录凭据、完整连接信息或个人机器绝对路径。
|
||||
- 项目初始化区分成熟项目与空项目:成熟项目优先延续当前项目已有且有充分证据的风格;空项目根据需求、用户选择和已授权的参考项目建立最小上下文,不自行猜测框架、包名或内部依赖。
|
||||
- 开发中的需求、计划、设计和验证记录默认放入 `documents.workRoot`;用户明确要求共享或正式交付时使用 `documents.designRoot`,历史归档使用 `documents.archiveRoot`。没有字段时分别回退到 `.craftkit/local/tasks/`、`.craftkit/designs/` 和项目已配置的归档根。
|
||||
- 成熟项目优先延续已有且有充分证据的风格;空项目根据需求、用户选择和已授权参考建立最小上下文,不自行猜测框架、包名或内部依赖。
|
||||
- 引用其他项目时先确认参考范围,只提炼结构、依赖、命名、测试、规范或工具约定;共享配置优先记录相对路径,不能共享的本地位置放入 `local/`。
|
||||
- 公开框架版本差异由 CraftKit 公共 profile 基于官方资料独立维护;项目只在 `project.json` 选择实际版本和 profile,并在 `standards/` 保存内部框架与覆盖规则。普通任务不得跨 profile 混读,升级或版本比较除外。
|
||||
- 公共框架版本差异由 CraftKit 公共 profile 维护;项目在 `project.json` 选择实际版本和 profile,并在 `standards/` 保存项目补充规则。
|
||||
- `agents/` 保存项目对特定 Agent 的补充说明;`standards/` 保存项目开发规范;`knowledge/pitfalls/` 保存经验证且可复用的问题经验;`knowledge/decisions/` 保存重要技术决策。
|
||||
- 本地内容统一放入 `local/`,缓存统一放入 `cache/`。`.craftkit/.gitignore` 必须排除 `/local/` 和 `/cache/`,但不得排除整个 `.craftkit/`。
|
||||
- 本地交接默认位于 `.craftkit/local/handoff/current.md`;只有用户明确选择共享时才写入 `.craftkit/handoff/current.md`。
|
||||
- 只在实际需要时创建目录,不一次生成空的 `agents/`、`standards/`、`knowledge/`、`handoff/`、`local/` 或 `cache/`。
|
||||
- Git Skill 默认排除 `.craftkit/local/**` 和 `.craftkit/cache/**`;其他 `.craftkit` 内容按普通项目资产评估,并在提交建议中单独标识为 Agent、规范或知识变更。
|
||||
- Git 交付或变更导出默认排除环境配置、本地配置和机器配置。只有适用的 `AGENTS.md`、`.craftkit/agents/` 或 `.craftkit/standards/` 明确要求交付,并经用户查看预览后再次确认,才可纳入;私钥、真实密钥和检测到的凭据始终禁止导出。
|
||||
- Git Skill 默认排除 `.craftkit/local/**` 和 `.craftkit/cache/**`;其他 `.craftkit` 内容按普通项目资产评估,并在提交建议中单独标识。
|
||||
- 如果本地目录已经被 Git 跟踪,或整个 `.craftkit/` 被全局规则、`.git/info/exclude` 或项目规则忽略,应提示冲突并停止自动处理;不得自动修改索引或历史。
|
||||
- `.craftkit/` 不得保存凭据、令牌、私钥、个人机器绝对路径或无必要的个人信息。
|
||||
|
||||
## 迁移与知识产权边界
|
||||
|
||||
- 迁移采用“分析能力 → 编写中性规格 → 脱离原文独立实现”的方式,不做目录复制、批量替词或近义改写。
|
||||
- 不复制来源 Skill 的正文、脚本、提示词、模板、示例、规则库、注释或独特文档结构。
|
||||
- 不写入公司名称、产品名称、内部域名、内部包名、项目名、人员信息、业务规则或环境路径。
|
||||
- 公司框架 API、组件契约、审批流程、版本矩阵和内部消息格式不得直接迁移;评估时应先抽象其通用问题,并优先设计基于项目配置、公开标准或用户显式输入的中性平替。只有不存在独立通用价值、无法安全替代或与 Codex 场景不成立时才排除。
|
||||
- 通用技术规范必须根据公开标准或官方资料重新设计;需要引用时记录来源和许可证。
|
||||
- 来源文件只用于人工分析和哈希追踪,不得进入 `plugins/` 发布目录。
|
||||
- 上游变化只触发复核,不自动覆盖已迁移 Skill。
|
||||
|
||||
详细顺序和门禁见 [迁移计划](migration/MIGRATION_PLAN.md)。
|
||||
|
||||
## Skill 迁移工作流
|
||||
|
||||
所有新增迁移、来源更新和已迁移 Skill 的重新评估,都必须按以下顺序处理。用户未明确确认前,只能进行只读分析,不得创建、复制、改写或删除目标 Skill 文件。
|
||||
|
||||
### 批次策略
|
||||
|
||||
- 迁移前期采用“特殊样本”方式,不以固定数量为目标,而是优先覆盖不同结构、依赖、权限和风险类型。
|
||||
- 特殊样本至少覆盖纯指令、脚本与生成物、只读 Git、有副作用 Git、模板化文档、大型参考资料和复合工作流;缺少某一类型时不得宣告样本阶段完成。
|
||||
- 每个特殊样本原则上单独完成迁移前确认、实现验证和提交确认,以便及时修正规则。
|
||||
- 特殊样本全部通过后,应先总结可复用的命名、目录、改写、验证和状态同步规则,再进入批量阶段。
|
||||
- 批量阶段按同一插件、相近能力和相同风险类型组织,每批建议 6~12 个 Skill;高度同质时可整组处理,但不得跨越不同权限边界强行合批。
|
||||
- 批量迁移仍执行完整的两次确认。任何样本失败或出现新类型,都应暂停扩批并补充对应特殊样本。
|
||||
|
||||
### 连续迁移波次
|
||||
|
||||
当用户明确要求将一组已完整列明的剩余来源“按顺序一次迁移完,再统一确认提交”时,可以建立连续迁移波次:
|
||||
|
||||
- 迁移前必须一次性展示全部来源、目标映射、合并或排除关系、执行顺序、写入范围和总体验收门禁,并取得用户明确确认。
|
||||
- 确认后可以按既定阶段连续实现,不再逐阶段请求迁移确认;不得加入方案外来源、目标 Skill 或新权限。
|
||||
- 每个阶段仍须独立运行对应测试和敏感内容扫描。阶段失败时先在既定范围内修复;出现需扩大范围、改变目标或无法安全替代的情况时暂停并重新确认。
|
||||
- 波次执行期间不创建 Git 提交。全部阶段完成后统一展示来源状态、目标文件、测试证据、未验证边界和建议提交序列,等待一次最终确认。
|
||||
- 最终一次“确认提交”可以授权按已展示顺序创建多个逻辑清晰的本地提交;不得因此推送、发布、创建标签或修改远端历史。
|
||||
|
||||
### 1. 阅读迁移计划和现状
|
||||
|
||||
- 完整阅读 `migration/MIGRATION_PLAN.md`、`migration/README.md` 和 `migration/source-lock.json`。
|
||||
- 检查 Git 状态、目标插件目录和现有 Skill,避免覆盖未提交改动或重复实现。
|
||||
- 只读检查相关来源 Skill 及其辅助资源,确认来源提交、文件哈希、依赖关系和变化范围。
|
||||
- 区分首次迁移、上游更新、目标重构和排除项复核,不把不同类型混为一次迁移。
|
||||
|
||||
### 2. 列出来源 Skill 和作用
|
||||
|
||||
在任何写入前,向用户列出本批计划处理的来源 Skill:
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 来源标识 | 使用本地迁移标识,不在发布目录写入公司品牌 |
|
||||
| 来源 Skill | 原始名称和相对路径 |
|
||||
| 当前作用 | 根据源码确认的能力、输入、输出和关键边界 |
|
||||
| 迁移类型 | 新增、更新、合并、中性平替、公开资料重建或排除 |
|
||||
| 风险 | 公司专属知识、内部依赖、重复能力和兼容性问题 |
|
||||
|
||||
来源作用必须有文件依据;无法从静态内容确认的运行行为应明确标记为未验证。
|
||||
|
||||
同一目标能力存在多个来源时,应在一个迁移方案中共同评估,明确合并、取舍、中性平替或排除关系,不按来源机械创建多个目标 Skill。来源含有大量专有规则时,不得只罗列删除项;必须说明通用问题如何由配置、标准接口、用户输入或项目资料替代。
|
||||
|
||||
### 3. 给出目标名称、作用和组织结构
|
||||
|
||||
针对每个来源 Skill,先给出建议方案:
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 目标插件 | `dev`、`doc`、`git`、`knowledge` 或 `skill` |
|
||||
| 目标名称 | 简短、中性、动作或明确领域导向的名称 |
|
||||
| 目标作用 | 迁移后保留的通用能力和明确排除的内容 |
|
||||
| 组织结构 | `SKILL.md` 及确有需要的 `agents/`、`scripts/`、`references/`、`assets/` |
|
||||
| 合并关系 | 独立 Skill、合并到已有 Skill、替代旧 Skill 或排除 |
|
||||
| 验证方案 | 静态校验、脚本测试、真实请求和敏感内容扫描 |
|
||||
|
||||
此阶段只输出设计,不创建目标目录。若多个来源能力可以合并,应优先给出合并方案,避免一一照搬来源结构。
|
||||
|
||||
### 4. 与用户确认迁移方案
|
||||
|
||||
- 展示本批范围、目标映射、组织结构、排除内容和验证方式后,明确请求用户确认。
|
||||
- 用户可以确认全部方案,也可以调整名称、拆分或合并方式、迁移顺序和排除项。
|
||||
- 只有“确认执行”“按此方案迁移”等明确授权才允许进入写入阶段。
|
||||
- 用户仅要求评估、查看方案或继续讨论时,不视为迁移授权。
|
||||
- 确认后的授权只覆盖已展示范围;新增 Skill、扩大来源范围或改变组织方式必须重新确认。
|
||||
|
||||
### 5. 执行迁移并更新文档
|
||||
|
||||
获得确认后:
|
||||
|
||||
1. 按中性能力规格独立实现目标 Skill,不复制来源目录或正文。
|
||||
2. 运行 `AGENTS.md` 中规定的全部验证,并记录真实结果和未验证边界。
|
||||
3. 更新 `migration/source-lock.json` 的来源哈希、目标路径、状态和复核日期。
|
||||
4. 更新 `migration/MIGRATION_PLAN.md` 的执行清单和批次进度。
|
||||
5. 更新根 `README.md`、所属插件说明或其他确实受影响的文档;不得创建重复状态文档。
|
||||
6. 向用户报告新增、更新、合并和排除结果,以及测试、扫描和剩余风险。
|
||||
7. 展示本批待提交文件清单和建议的 Conventional Commit 提交信息,进入第二次确认。
|
||||
|
||||
### 6. 与用户确认并提交到本地
|
||||
|
||||
- 迁移前确认只授权执行迁移,不自动授权 Git 提交。
|
||||
- 迁移和文档同步完成后,必须再次等待用户明确确认;“确认提交”“提交到本地”等表述才视为提交授权。
|
||||
- 用户要求调整、补测或继续检查时,先完成相应工作并重新展示结果,不得沿用此前的提交确认。
|
||||
- 获得确认后,只暂存本批迁移方案中已展示且验证通过的文件,不使用会混入其他改动的宽泛暂存命令。
|
||||
- 暂存后执行 `git diff --cached --check`,并复核暂存文件清单;发现额外文件或敏感内容时停止提交并报告。
|
||||
- 使用中文 Conventional Commit 信息创建本地提交,然后检查提交内容和工作区状态。
|
||||
- 本地提交成功后向用户报告提交哈希、提交信息、文件范围和剩余未提交改动。
|
||||
- 第二次确认只授权本地提交,不包含推送、创建标签、发布插件或修改远端历史;这些操作必须另行获得明确授权。
|
||||
- 连续迁移波次按“连续迁移波次”约定执行一次最终确认;若计划创建多个本地提交,必须在确认前展示每个提交的范围和建议信息。
|
||||
|
||||
## 验证要求
|
||||
|
||||
每个新增或修改的 Skill 至少完成:
|
||||
|
||||
1. 检查目录名、frontmatter 和引用路径。
|
||||
2. 运行 Skill 校验器。
|
||||
3. 运行所属插件 manifest 校验器。
|
||||
4. 执行公司标识、内部路径、凭据和占位符扫描。
|
||||
5. 有脚本时运行核心行为测试;有生成物时检查实际产物。
|
||||
6. 用一个真实请求验证触发边界和输出结果。
|
||||
7. 更新 `migration/source-lock.json` 中的状态、目标路径和复核日期。
|
||||
1. 检查目录名、frontmatter、引用路径和工具名称。
|
||||
2. 运行仓库现有的 Skill 校验器及所属插件校验器。
|
||||
3. 检查凭据、无效路径、未替换占位符和无效工具名称。
|
||||
4. 有脚本时运行核心行为测试;有生成物时检查实际产物。
|
||||
5. 以真实请求检查触发边界、权限边界和输出是否符合描述。
|
||||
|
||||
静态检查通过不代表真实行为已经验证,交付时应分别说明静态校验、脚本测试和实际场景验证结果。
|
||||
|
||||
@@ -189,5 +105,16 @@ plugins/<plugin>/skills/<skill>/
|
||||
- 使用 Conventional Commits,提交说明使用中文。
|
||||
- 推荐类型:`feat`、`fix`、`docs`、`refactor`、`test`、`chore`。
|
||||
- 提交前执行 `git status --short`、`git diff --cached --check` 并检查暂存文件清单。
|
||||
- 不提交本地来源配置、凭据、缓存、运行产物和 IDE 私有状态。
|
||||
- 不提交本地配置、凭据、缓存、运行产物和 IDE 私有状态。
|
||||
- 不使用破坏性历史改写,也不推送,除非用户明确授权。
|
||||
|
||||
## 分支与发布约定
|
||||
|
||||
- 一个完整主题使用一个短生命周期开发分支;分支只包含同一能力闭环,不为凑版本混入无关变更。
|
||||
- 分支命名优先遵循仓库现有约定;没有更具体规则时使用 `feature/<short-name>`、`fix/<short-name>`、`docs/<short-name>` 或 `chore/<short-name>`。
|
||||
- 工作区不干净、当前 checkout 被 IDE/服务/测试占用,或用户要求不影响主工作区时,使用独立 Worktree。分支任务完成后必须通过安全清理门禁移除额外 Worktree,保留分支和提交。
|
||||
- 已验证的开发分支合入 `master` 后,先在 `CHANGELOG.md` 的 `Unreleased` 累计;形成一组相关、完整、可交付的能力后再发布,不因每次普通修改单独发版。
|
||||
- 阻断性缺陷、安全问题或已发布能力的明确回归可以单独发布修订版本;不得为等待批次延迟必要修复。
|
||||
- 仓库整体版本遵循 SemVer:不兼容变化升级主版本,向后兼容的新能力升级次版本,向后兼容的问题修复升级修订版本。
|
||||
- `dev`、`doc`、`git`、`knowledge` 和 `skill` 插件清单版本按实际变化独立维护;修改某个插件的可见能力时同步评估其 `plugin.json` 版本。
|
||||
- 发布前必须确认工作区、发布范围、版本号、验证证据、`CHANGELOG.md`、插件清单版本、标签目标和远程地址。版本提交、标签和推送分别按用户授权执行。
|
||||
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
# 更新日志
|
||||
|
||||
本文档记录 CraftKit 对使用者有明显影响的功能、工作流和兼容性变化。版本号遵循 [Semantic Versioning 2.0.0](https://semver.org/lang/zh-CN/):主版本表示不兼容变化,次版本表示向后兼容的新能力,修订版本表示向后兼容的问题修复。
|
||||
|
||||
历史版本根据 Git 提交倒推,只保留重要里程碑,不逐条复述全部提交。各版本对应的 Git 历史通过 `v<版本号>` 标签标记。
|
||||
|
||||
这里的版本号表示 CraftKit 仓库整体发布版本。`dev`、`doc`、`git`、`knowledge` 和 `skill` 的插件清单版本仍按各插件实际变化独立维护,不要求与仓库版本保持一致。
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
- `knowledge:document-output` 增加 `register` 与 `close` 模式,使用 `workRoot/<task>/task.json` 记录任务状态、文件归属、可见性和关闭处置。
|
||||
- 增加“保留、沉淀、归档、删除、延后”五类关闭清单,以及共享文件逐项评审、断链检查和精确路径删除门禁。
|
||||
- 增加长期文档 `pending`、`approved`、`outdated` 审核状态,以及项目级文档持续维护规范。
|
||||
- 增加 `profile`、`java` 和 `python` 插件骨架,以统一契约提供多语言技术能力。
|
||||
- 增加 Profile manifest、版本范围、能力状态、引用安全规则和标准库校验器。
|
||||
- 增加 `python:review-python`,按项目版本审查类型、异常、资源、异步、事务和测试隔离问题。
|
||||
|
||||
### Planned
|
||||
|
||||
- 建设 Skill 评测基线,支持固定场景、验收规则和更新前后回归比较。
|
||||
- 保持 `dev` 插件的通用设计、实现、测试和审查核心,不按 Java、Python、React 或 Vue 复制整套工作流;仅当专项能力具备独立安装、发布或维护需求时再评估拆分插件。
|
||||
- 补充前端工程质量专项支持,增加 `test-frontend` 和 `review-typescript`,分别覆盖单元、组件与集成测试,以及 TypeScript 类型安全与模块契约。
|
||||
- 增加命令环境探测与指令适配辅助 Skill:识别操作系统、Shell/终端类型及版本、Codex 可用功能工具、命令行工具来源与版本,生成当前任务的环境能力快照,并按探测结果选择经过验证的默认指令;覆盖 PowerShell、Windows PowerShell、CMD、Bash、Zsh 等环境中的路径、引号、转义、编码、管道、退出码和标准输出/错误流差异。
|
||||
- 为 Git 建立版本与仓库状态 profile:根据 Git 版本选择 `checkout`、`switch`、`restore`、Worktree、分支跟踪和安全目录等命令形式,固定参数顺序并兼容含空格或非 ASCII 字符的路径与引用;复合操作按步骤检查退出码,区分“无输出的正常状态”、部分成功和真正失败,避免前置 `fetch` 失败后继续使用陈旧远端引用,也避免后置只读检查的非零退出码掩盖已经成功的写操作。
|
||||
- 为 Maven、JDK 和项目构建工具建立版本 profile:优先识别 Maven Wrapper、Maven/JDK 实际版本、`JAVA_HOME`、Toolchains、父 POM、模块结构、激活 profile、`settings.xml` 入口及仓库镜像,再选择全量或 `-pl`/`-am` 等聚焦构建命令;将 Maven 版本不兼容、JDK 不匹配、插件或父 POM 无法解析、缓存问题、编译失败和测试失败分类处理,不用重复执行同一命令代替诊断。
|
||||
- 增加私有 Git/Maven 仓库访问诊断与安全降级:区分沙箱或工具权限、VPN/内网、DNS、代理、TLS/证书、HTTP/HTTPS/SSH 协议、凭据助手、仓库镜像和服务端不可用等原因;只读取完成诊断所需的非敏感配置,不输出令牌、密码或完整凭据,访问受限时保留本地证据并明确远端引用或依赖缓存的新鲜度,获得既有授权后在正确执行环境重试。所有命令失败均输出已执行步骤、实际副作用、失败分类、可安全重试点、替代指令和验证结果。
|
||||
|
||||
### Changed
|
||||
|
||||
- `knowledge` 插件增加项目文档落盘配置能力;项目初始化写入 `documents.workRoot`、`documents.designRoot` 与 `documents.archiveRoot`,区分本地过程文档、共享设计和历史归档。
|
||||
- 需求、变更计划、技术设计与 Bug 分析 Skill 统一按项目文档配置选择任务目录;缺少配置时,过程文档回退到 `.craftkit/local/tasks/`,不再根据根目录说明文件推断落点。
|
||||
- 项目初始化增加文档生命周期默认策略;本地保留天数只用于提示,任务完成默认生成关闭预览,不自动删除文件。
|
||||
- 需求、计划、设计和分析 Skill 写入文档后登记本地任务记录;沉淀、交接、归档和 Worktree 清理按任务状态联动。
|
||||
- 需求与设计 Skill 优先更新已有权威文档;实现、升级和代码审核流程检查留存文档是否因代码或契约变化而需要同步。
|
||||
- `task.json` 使用 `created`、`updated`、`referenced` 区分任务关系,关联旧文档不转移所有权,也不产生删除权限。
|
||||
- README 的 Skill 说明同步覆盖文档创建、审核、持续更新、历史归档和关闭职责。
|
||||
- `design-backend`、`implement-backend`、`test-backend` 和 `review-java` 接入可选语言 Profile,并在提供方缺失时保留通用回退。
|
||||
- 项目画像模板升级到 Schema 2,保留顶层兼容概要并支持模块级技术栈;插件安装状态不写入共享画像。
|
||||
- 多语言架构文档收敛为单一设计依据和阶段跟踪计划,并记录 Codex 当前没有 Skill 运行时依赖接口的约束。
|
||||
|
||||
## [1.3.0] - 2026-08-31
|
||||
|
||||
### Added
|
||||
|
||||
- 增加 `.craftkit/project.json`、项目资料索引和本地内容忽略规则,为 Agent 提供可共享的项目上下文入口。
|
||||
- 为 `branch` 增加当前工作区与独立 Worktree 两种分支创建方式,以及任务结束后的 `close` 清理模式。
|
||||
- 为 `integrate` 增加预集成 Worktree 的 `cleanup` 阶段和完整生命周期状态。
|
||||
- 增加 Worktree 分支占用诊断、安全移除门禁和清理后分支、提交及主工作区验证规则。
|
||||
|
||||
### Changed
|
||||
|
||||
- 脏工作区、当前 checkout 被占用或用户要求隔离时,优先在独立 Worktree 创建需求或预集成分支。
|
||||
- 预集成交付范围统一以目标分支到预集成 HEAD 的真实差异判断,不再以 merge 输出、分支名、提交数量或测试结果代替纯度检查。
|
||||
- 全流程自动化在独立 Worktree 的分支任务完成后进入清理门禁,释放分支占用后再结束任务。
|
||||
- 增加短生命周期开发分支和批量发布约定:相关完整变更累计发布,阻断性修复可单独发布修订版本。
|
||||
- 所有 Skill 的界面显示名增加完整模块调用名,例如 `代码审查(dev:review-code)`,便于在插件列表中识别并直接调用。
|
||||
|
||||
## [1.2.0] - 2026-08-31
|
||||
|
||||
### Added
|
||||
|
||||
- 增加项目初始化到应用拆分的共同工作流,明确应用边界、拆分判据、审批门和交付基线。
|
||||
- 分别增加新项目与已有项目两种执行口径。
|
||||
- 新项目流程覆盖项目上下文、需求基线、业务能力地图、应用拆分、契约设计和建设计划。
|
||||
- 已有项目流程覆盖现状建模、耦合识别、目标与过渡架构、数据权威、渐进迁移和回滚。
|
||||
|
||||
### Changed
|
||||
|
||||
- 明确应用拆分不等于强制微服务化,允许模块化单体或暂不拆分成为评审结论。
|
||||
- README 增加项目初始化与应用拆分工作流入口。
|
||||
|
||||
## [1.1.1] - 2026-08-31
|
||||
|
||||
### Fixed
|
||||
|
||||
- 文档转换脚本改为按需加载 `python-docx` 和 `openpyxl`,缺少依赖时返回明确提示,不再影响帮助和参数探测。
|
||||
- 缺少转换依赖时不创建输出目录或半成品。
|
||||
- 为后端设计、后端实现和前端实现补充 `guidance` 未安装时的规范检索回退路径,降低插件间隐式耦合。
|
||||
|
||||
## [1.1.0] - 2026-08-28
|
||||
|
||||
### Added
|
||||
|
||||
- 增加从需求归集、技术设计、代码实现、测试审核到本地提交的全流程自动化指南。
|
||||
- 建立 S0 至 S9 阶段状态机、G1 至 G5 人工审批门、验证矩阵、回退规则和任务台账。
|
||||
- 提供可直接交给 Codex 或其他兼容智能体的总控提示词。
|
||||
|
||||
## [1.0.0] - 2026-08-26
|
||||
|
||||
### Added
|
||||
|
||||
- 建立由 `dev`、`doc`、`git`、`knowledge` 和 `skill` 组成的完整 CraftKit 插件体系。
|
||||
- 提供 44 个可独立发现的 Skill,覆盖软件设计与实现、文档处理、Git 交付、项目知识和规范维护。
|
||||
- README 增加完整 Skill 目录、插件用途和本地使用说明。
|
||||
|
||||
### Changed
|
||||
|
||||
- 收敛插件元数据和能力描述,使 CraftKit 具备稳定、可理解的首个正式版本基线。
|
||||
- 清理仅服务早期建设过程的资料,保留实际运行、维护和发布所需内容。
|
||||
|
||||
## [0.3.0] - 2026-08-26
|
||||
|
||||
### Added
|
||||
|
||||
- Skill 数量扩展到 44 个,形成首个完整能力集合。
|
||||
- 补齐代码实现、审查、测试、升级、工作量评估和专项技术设计能力。
|
||||
- 补齐版本发布、需求整理、报告和消息编写能力。
|
||||
|
||||
## [0.2.0] - 2026-08-25
|
||||
|
||||
### Added
|
||||
|
||||
- Skill 数量扩展到 25 个,形成可用的开发、文档、Git、知识和规范能力基础。
|
||||
- 增加变更计划、后端设计和前端设计等开发分析能力。
|
||||
- 建立项目初始化、规范检索、交接、复盘和经验维护的基础结构。
|
||||
|
||||
## [0.1.0] - 2026-08-25
|
||||
|
||||
### Added
|
||||
|
||||
- 初始化 CraftKit 仓库和 Codex 插件市场骨架。
|
||||
- 建立 `dev`、`doc`、`git`、`knowledge` 和 `skill` 五个插件区域。
|
||||
- 建立插件清单、仓库说明和基础维护结构。
|
||||
@@ -0,0 +1,141 @@
|
||||
# 已有项目初始化与应用拆分工作流
|
||||
|
||||
## 1. 适用范围
|
||||
|
||||
适用于已经存在源码、构建文件、模块、接口、数据库对象、任务或部署配置的项目。目标是在保护现有工作区的前提下建立可信项目上下文,识别真实运行与依赖边界,再形成可渐进实施、可回滚的应用拆分方案。
|
||||
|
||||
已有目录或模块名称不能直接视为正确应用边界;代码引用也不等于业务所有权。静态源码只能证明当前实现,运行拓扑、流量、数据规模和生产行为仍需配置、日志、部署资料或用户确认支持。
|
||||
|
||||
## 2. 输入与保护措施
|
||||
|
||||
开始时记录:
|
||||
|
||||
- 当前分支、HEAD、staged、unstaged 和 untracked 状态;
|
||||
- 适用的 `AGENTS.md`、`.craftkit/`、项目说明和贡献规范;
|
||||
- 构建清单、锁文件、源码根、模块、测试和自动化配置;
|
||||
- 数据库、消息、缓存、文件、定时任务和外部系统的非秘密元数据;
|
||||
- 制品、部署单元、环境配置入口和运行依赖;
|
||||
- 已知问题、迁移限制、兼容窗口和不能变更的范围。
|
||||
|
||||
不得读取或记录凭据、完整连接串和生产敏感数据。不能为了扫描而构建、启动、迁移或连接外部环境。
|
||||
|
||||
## 3. 执行阶段
|
||||
|
||||
### E0:确认成熟项目模式
|
||||
|
||||
1. 使用 `init` 只读探测有效源码、构建文件、现有项目资料和代表性入口。
|
||||
2. 展示“成熟项目”判断、项目根、工作区状态和拟扫描范围。
|
||||
3. 多仓或多根目录时,先确认本次拆分主体及关联仓库只读范围。
|
||||
4. 到达 G0,等待用户确认模式、范围和可使用的运行资料。
|
||||
|
||||
### E1:保守初始化项目资料
|
||||
|
||||
1. 完整读取现有 `AGENTS.md` 与 `.craftkit/`,禁止覆盖未知用户章节。
|
||||
2. 从构建和锁文件提取语言、框架、精确版本、模块和依赖证据。
|
||||
3. 读取少量代表性的入口、接口、服务、数据访问和测试文件;多种风格并存时不按数量自动裁决。
|
||||
4. 展示当前项目事实、冲突、疑似历史结构和待确认项。
|
||||
5. 用户确认后由 `init` 保守合并项目资料,并验证 JSON、索引和忽略规则。
|
||||
6. 使用 `guidance` 或手工入口顺序验证一项真实项目规则。
|
||||
|
||||
### E2:建立现状基线
|
||||
|
||||
从源码和可用运行资料分别建立视图:
|
||||
|
||||
- 构建视图:模块、依赖方向、公共库和循环依赖;
|
||||
- 调用视图:入口、同步调用、异步消息、批处理和人工步骤;
|
||||
- 数据视图:表、文件、缓存、主数据、写入方和共享访问;
|
||||
- 部署视图:制品、进程、配置、扩缩容、故障域和发布方式;
|
||||
- 组织视图:维护团队、变更频率、审批和支持责任;
|
||||
- 质量视图:测试边界、发布验证、已知风险和观测能力。
|
||||
|
||||
每项结论注明证据来源和置信度。无法验证的生产拓扑与流量必须标为待验证。
|
||||
|
||||
### E3:建立目标需求基线
|
||||
|
||||
1. 使用 `requirements` 区分当前行为、目标行为、必须保持的兼容和范围外事项。
|
||||
2. 明确拆分动因,例如独立发布、团队自治、容量、故障隔离、安全边界或技术替换。
|
||||
3. 为拆分目标设置可测指标,例如依赖减少、发布独立性、故障影响范围或迁移窗口,而不是只写“解耦”。
|
||||
4. 记录必须继续兼容的调用方、数据格式、作业、报表和运维流程。
|
||||
5. 到达 G1,由用户确认目标、约束、验收和允许改变的边界。
|
||||
|
||||
### E4:识别候选边界与阻塞耦合
|
||||
|
||||
1. 从业务能力和数据所有权出发提出候选边界,再映射当前模块,而不是按目录直接切分。
|
||||
2. 为每个候选应用列出入口、核心职责、不负责事项、依赖、数据、任务和部署现状。
|
||||
3. 识别阻塞拆分的耦合:共享写库、跨模块事务、循环调用、共享会话、共享缓存键、文件约定、定时任务、硬编码配置和公共类中的业务逻辑。
|
||||
4. 区分必须拆除的耦合、迁移期允许的兼容桥和可以长期保留的公共基础能力。
|
||||
5. 对证据不足的动态调用、反射、配置路由和外部任务安排专项验证。
|
||||
|
||||
### E5:设计目标应用和过渡架构
|
||||
|
||||
至少比较以下方案:
|
||||
|
||||
- 保持现状,仅加强模块边界;
|
||||
- 模块化单体并清理依赖;
|
||||
- 抽取少量高收益独立应用;
|
||||
- 按多个业务能力逐步形成独立应用。
|
||||
|
||||
对推荐方案逐项说明业务收益、数据和事务变化、接口成本、部署与观测成本、团队影响、迁移风险和不采用其他方案的理由。应用拆分清单必须包含职责、不负责事项、契约、数据所有权、运行和安全边界。
|
||||
|
||||
过渡架构应明确:
|
||||
|
||||
- 旧入口与新入口的流量切换方式;
|
||||
- 同步接口、事件、批处理或文件交换的适用范围;
|
||||
- 数据迁移、复制、校验、回放和最终切换责任;
|
||||
- 迁移期读写权威、兼容适配层和弃用条件;
|
||||
- 跨边界事务的幂等、补偿、重试和对账方式;
|
||||
- 发生失败时回到旧路径的条件和数据处置方法。
|
||||
|
||||
到达 G2,由用户确认目标边界、过渡架构和明确不拆分的部分。
|
||||
|
||||
### E6:细化专项设计
|
||||
|
||||
根据批准方案按需执行:
|
||||
|
||||
- `design-backend`:目标应用内部模块、服务、事务、异常和观测边界;
|
||||
- `design-frontend`:前端应用、路由、状态、共享组件和渐进切换边界;
|
||||
- `design-api`、`prepare-api`:新旧接口、适配层、版本、字段映射和弃用计划;
|
||||
- `design-db`:数据所有权、结构、双读双写风险、迁移、校验和回滚;
|
||||
- `design-workflow`:跨应用状态、任务、超时、撤回、补偿和审计。
|
||||
|
||||
所有专项设计必须映射回现有调用方和测试,不得只描述目标结构。
|
||||
|
||||
### E7:制定渐进迁移计划
|
||||
|
||||
使用 `plan-change` 将迁移拆为可独立验证的批次。通常按以下顺序评估,但不得机械套用:
|
||||
|
||||
1. 增加观测、契约测试和现状回归基线;
|
||||
2. 收紧原系统内部模块边界并消除高风险循环依赖;
|
||||
3. 建立目标应用骨架和兼容适配层;
|
||||
4. 迁移低风险读取或旁路能力;
|
||||
5. 迁移写入、任务和数据权威;
|
||||
6. 分批切换调用方和流量;
|
||||
7. 完成对账、稳定观察、旧路径下线和资料更新。
|
||||
|
||||
每个批次必须记录:前置条件、涉及应用、代码与数据范围、兼容方式、验证、观测窗口、停止条件、回滚步骤和不可逆点。未经额外授权,不执行数据库迁移、环境部署或流量切换。
|
||||
|
||||
### E8:形成交付基线
|
||||
|
||||
汇总并冻结本轮已批准的:现状事实、目标应用边界、决策记录、专项契约、迁移批次、验证矩阵、风险台账和待确认项。需要后续任务接续时使用 `handoff` 生成交接材料,不把未验证运行行为写成已完成结论。
|
||||
|
||||
## 4. 已有项目交付物
|
||||
|
||||
- 保守合并并验证的 `AGENTS.md` 与 `.craftkit/` 项目资料;
|
||||
- 当前模块、调用、数据、部署、组织和质量视图;
|
||||
- 拆分目标、兼容范围和可测验收指标;
|
||||
- 候选应用、阻塞耦合和目标应用职责矩阵;
|
||||
- 目标架构、过渡架构、数据权威和契约清单;
|
||||
- 分批迁移、验证、观测、停止和回滚计划;
|
||||
- 未验证运行事实、外部协调项和不可逆操作清单。
|
||||
|
||||
## 5. 停止条件
|
||||
|
||||
遇到以下情况时暂停:无法区分既有改动与本次产物、关键调用或数据写入方未知、生产运行资料与源码冲突、迁移需要未授权的外部系统访问、存在无法回滚的数据变更、关键调用方未纳入范围,或用户尚未批准对应审批门。
|
||||
|
||||
## 6. 可直接复制的总控提示词
|
||||
|
||||
```text
|
||||
请按《已有项目初始化与应用拆分工作流》推进当前项目。先保护现有工作区,使用 init 只读判断成熟项目模式,展示项目根、分支、已有改动、拟扫描范围和运行资料边界,在 G0 等待我确认。确认后保守合并 AGENTS.md 与 .craftkit 项目资料,建立构建、调用、数据、部署、组织和质量现状视图,再使用 requirements 确认拆分动因、兼容范围和可测目标。
|
||||
|
||||
基于真实业务能力、调用链、数据写入方和部署单元提出候选应用,识别共享写库、跨模块事务、循环调用、共享会话、缓存、文件和任务耦合。比较保持现状、模块化单体、抽取少量应用和多应用渐进拆分方案,形成目标架构、过渡架构、数据权威、契约、迁移批次、验证、观测、停止和回滚计划。全过程区分源码事实、运行事实、用户确认、项目规则、设计建议和待验证项;不把目录名称直接视为业务边界。只在 G0、G1、G2、G3、业务决策、权限扩大或高风险副作用处暂停。未经我另行授权,不修改业务代码,不连接外部环境,不迁移数据,不部署,不提交,不推送。
|
||||
```
|
||||
@@ -0,0 +1,124 @@
|
||||
# 新项目初始化与应用拆分工作流
|
||||
|
||||
## 1. 适用范围
|
||||
|
||||
适用于空目录、新建仓库,或只有需求、原型和少量说明材料、尚未形成有效源码与构建结构的项目。目标是先建立可信项目上下文,再从已确认需求推导应用边界和实施计划。
|
||||
|
||||
本流程不默认选择微服务、前后端框架、数据库、消息系统、云平台或最新版本。`init` 只创建 Agent 与项目知识资料;代码工程初始化属于后续实施任务。
|
||||
|
||||
## 2. 输入与前置确认
|
||||
|
||||
开始时收集并确认:
|
||||
|
||||
- 项目根目录和 Git 状态;
|
||||
- 项目用途、目标用户、交付形态和预期运行环境;
|
||||
- 需求、原型、会议材料和验收要求;
|
||||
- 已确定的语言、框架、数据库、构建工具及精确版本;
|
||||
- 组织标识、包名或 npm scope 等必须提前确定的标识;
|
||||
- 允许参考的项目,以及只允许借鉴的架构、依赖、命名、测试、规范或工具范围;
|
||||
- 安全、合规、容量、可用性、交付期限和团队边界。
|
||||
|
||||
未知信息保持为空或标记待确认,不能用流行方案自动补齐。
|
||||
|
||||
## 3. 执行阶段
|
||||
|
||||
### N0:确认空项目模式
|
||||
|
||||
1. 使用 `init` 只读检查源码、构建文件、`AGENTS.md` 和 `.craftkit/`。
|
||||
2. 展示“空项目”判断、证据、项目根和允许扫描的参考材料。
|
||||
3. 到达 G0,等待用户确认模式和参考范围。
|
||||
|
||||
### N1:建立项目上下文
|
||||
|
||||
1. 确认项目类型、交付形态、技术选型的已决项和未决项。
|
||||
2. 如存在参考项目,分别记录当前项目输入事实、参考项目做法和建议采用项。
|
||||
3. 预览拟创建的 `AGENTS.md`、`.craftkit/project.json`、`.craftkit/README.md`、必要索引与 `.craftkit/.gitignore`。
|
||||
4. 用户确认后由 `init` 创建最小资料骨架,不提前生成空业务目录。
|
||||
5. 校验 JSON、索引链接,以及 `/local/`、`/cache/` 的忽略规则;用 `guidance` 或手工入口顺序验证一次真实规则查询。
|
||||
|
||||
### N2:建立需求基线
|
||||
|
||||
1. 使用 `requirements` 整理角色、场景、触发条件、主流程、异常流程、数据、权限、兼容和范围外事项。
|
||||
2. 为需求分配稳定编号,并为关键场景编写可测试验收标准。
|
||||
3. 将技术偏好与业务约束分开;只有影响目标或验收的技术条件才进入需求基线。
|
||||
4. 到达 G1,由用户确认需求、范围和暂时保留的业务待决项。
|
||||
|
||||
### N3:形成业务能力地图
|
||||
|
||||
按业务目标而不是技术分层拆解能力:
|
||||
|
||||
1. 识别核心域、支撑能力、通用能力和外部系统责任。
|
||||
2. 为每项能力记录使用者、业务不变量、输入输出、关键数据、变化节奏和责任主体。
|
||||
3. 标出必须强一致、允许最终一致、可离线处理和必须人工确认的流程。
|
||||
4. 识别共享概念中的同名异义与不同上下文,避免直接建立全局统一数据模型。
|
||||
|
||||
产物至少包括能力清单、能力关系和待确认边界。
|
||||
|
||||
### N4:提出应用拆分候选
|
||||
|
||||
1. 先形成最小可行边界:模块化单体、少量独立应用或其他适合交付形态的结构。
|
||||
2. 只有在业务所有权、数据、发布节奏、隔离或扩缩容需求明确时才增加独立应用。
|
||||
3. 对每个候选应用填写职责、不负责事项、调用方、数据所有权、上下游、运行和安全边界。
|
||||
4. 至少比较以下方案:维持单一应用、按主要业务能力拆分、按独立运行要求进一步拆分。
|
||||
5. 计算拆分引入的契约治理、分布式一致性、测试、部署、观测和团队协作成本。
|
||||
6. 到达 G2,由用户确认目标应用清单、保留模块和不拆分项。
|
||||
|
||||
### N5:细化应用契约
|
||||
|
||||
根据已批准边界按需执行:
|
||||
|
||||
- 使用 `design-backend` 设计应用内部模块、服务、事务和错误边界。
|
||||
- 使用 `design-frontend` 设计前端应用、页面、状态和复用边界。
|
||||
- 使用 `design-api` 设计跨应用同步接口,使用 `prepare-api` 整理调用方字段映射。
|
||||
- 使用 `design-db` 明确数据所有权、表结构、索引和未来迁移边界。
|
||||
- 使用 `design-workflow` 设计跨应用状态、任务、补偿、幂等和审计。
|
||||
|
||||
跨应用共享代码只保留稳定、无业务所有权争议的基础能力。共享数据库、跨库事务和双向同步必须显式记录风险,不能作为无说明默认方案。
|
||||
|
||||
### N6:设计工程和运行结构
|
||||
|
||||
在不创建代码的前提下给出建议结构:
|
||||
|
||||
- 仓库组织:单仓、多仓或混合方式及选择依据;
|
||||
- 每个应用的源码、测试、契约和配置边界;
|
||||
- 公共库的准入条件、版本和兼容策略;
|
||||
- 本地开发、持续集成、制品、部署和环境配置方式;
|
||||
- 日志、指标、追踪、健康检查和故障隔离要求;
|
||||
- 认证授权、密钥管理和敏感数据处理边界。
|
||||
|
||||
无法从需求确定的平台决策继续作为待确认项,不把目录草案写成已创建结构。
|
||||
|
||||
### N7:形成建设计划
|
||||
|
||||
使用 `plan-change` 按以下依赖顺序制定计划:
|
||||
|
||||
1. 建立项目与契约基线;
|
||||
2. 搭建最小工程和验证链路;
|
||||
3. 优先实现能纵向验证核心场景的应用切片;
|
||||
4. 建设公共能力和外部集成;
|
||||
5. 完成跨应用契约、失败恢复和安全验证;
|
||||
6. 补齐部署、可观测性、容量和验收验证。
|
||||
|
||||
每个批次记录输入、应用范围、产物、依赖、测试、停止条件和回退方式。到达 G3,由用户确认后续是否进入工程创建与代码实现。
|
||||
|
||||
## 4. 新项目交付物
|
||||
|
||||
- 已验证的 `AGENTS.md` 与 `.craftkit/` 项目资料;
|
||||
- 已确认需求基线和待确认清单;
|
||||
- 业务能力地图及能力关系;
|
||||
- 应用拆分方案、替代方案和决策依据;
|
||||
- 应用职责矩阵、契约清单、数据所有权矩阵和依赖关系;
|
||||
- 工程与运行结构建议;
|
||||
- 分阶段建设计划、验证矩阵和回退边界。
|
||||
|
||||
## 5. 停止条件
|
||||
|
||||
出现以下情况时暂停,不继续推导:核心业务目标冲突、数据所有权无法确定、关键外部契约未知、技术选型会实质改变交付边界、参考项目授权范围不清,或用户尚未批准对应审批门。
|
||||
|
||||
## 6. 可直接复制的总控提示词
|
||||
|
||||
```text
|
||||
请按《新项目初始化与应用拆分工作流》推进当前项目。先使用 init 只读判断项目模式,展示项目根、Git 状态、输入材料、参考范围和待确认项,在 G0 等待我确认。确认后保守初始化 AGENTS.md 与 .craftkit 项目资料,使用 requirements 建立需求基线,再依次完成业务能力地图、应用拆分候选、方案比较、应用职责与数据所有权矩阵、跨应用契约、工程与运行结构建议以及分阶段建设计划。
|
||||
|
||||
全过程区分用户已确认目标、输入事实、参考项目做法、项目规则、设计建议、待确认项和待验证项。不要默认微服务、框架、数据库、云平台或最新版本;允许“不拆分”或“模块化单体”成为最终建议。只在 G0、G1、G2、G3、业务决策、权限扩大或高风险副作用处暂停。未经我另行授权,不创建业务代码,不安装依赖,不执行数据库、部署、提交或发布操作。
|
||||
```
|
||||
@@ -0,0 +1,94 @@
|
||||
# 项目初始化到应用拆分工作流
|
||||
|
||||
## 1. 文档用途
|
||||
|
||||
本工作流用于把项目从“缺少稳定上下文”推进到“形成可执行、可验证的应用拆分基线”。这里的应用是具有明确职责、所有权、接口、数据边界和运行形态的交付单元;应用内部仍可继续划分模块。应用不必等同于微服务,也不要求每个业务能力都独立部署。
|
||||
|
||||
本工作流只完成项目资料初始化、需求基线、现状或目标架构分析、应用拆分设计和实施规划。除非用户另行明确授权,不创建业务代码,不迁移数据,不调整部署环境,也不执行 Git 提交或发布。
|
||||
|
||||
## 2. 两种执行口径
|
||||
|
||||
- 仓库为空、只有少量说明文件,或尚未形成有效源码与构建结构时,使用[新项目初始化与应用拆分工作流](NEW-PROJECT-INITIALIZATION-AND-APPLICATION-SPLIT.md)。
|
||||
- 已存在有效源码、构建文件、模块、接口、数据库对象或部署配置时,使用[已有项目初始化与应用拆分工作流](EXISTING-PROJECT-INITIALIZATION-AND-APPLICATION-SPLIT.md)。
|
||||
- 情况混合时,以待拆分主体为准:新建独立产品按新项目口径;从现有系统剥离能力按已有项目口径。
|
||||
- 执行 `init` 探测后必须展示模式判断及证据,用户可以覆盖建议模式。
|
||||
|
||||
## 3. 共同原则
|
||||
|
||||
### 3.1 证据分层
|
||||
|
||||
所有结论区分为:用户已确认目标、当前项目事实、参考项目做法、项目明确规则、设计建议、待确认项和待验证项。不能把相似系统、单个代码样本或行业惯例直接写成当前项目事实。
|
||||
|
||||
### 3.2 拆分判据
|
||||
|
||||
候选应用至少从以下方面评估:
|
||||
|
||||
- 业务能力与变化节奏;
|
||||
- 团队或责任主体;
|
||||
- 数据所有权和一致性要求;
|
||||
- 对外接口与上下游依赖;
|
||||
- 安全、权限、审计和合规边界;
|
||||
- 性能、容量、可用性和故障隔离要求;
|
||||
- 构建、部署、扩缩容和发布节奏;
|
||||
- 迁移、测试、运维和认知成本。
|
||||
|
||||
只有拆分收益大于新增的分布式事务、接口治理、数据同步、部署和运维成本时,才建议形成独立应用。证据不足时可以输出模块化单体、逻辑分区或暂不拆分方案。
|
||||
|
||||
### 3.3 Skill 使用边界
|
||||
|
||||
- `init`:只初始化或合并 `AGENTS.md` 与 `.craftkit/` 项目资料,不生成业务工程。
|
||||
- `guidance`:检索项目规则;未安装时按 `AGENTS.md`、`.craftkit/agents/index.md`、`.craftkit/standards/index.md` 和命中正文的顺序手工读取。
|
||||
- `requirements`:建立业务需求与验收基线。
|
||||
- `design-backend`、`design-frontend`:形成应用内部的后端和前端边界。
|
||||
- `design-api`、`prepare-api`:细化跨应用和前后端契约。
|
||||
- `design-db`:细化数据所有权、结构、迁移和回滚。
|
||||
- `design-workflow`:处理跨状态、跨角色或跨事务的业务流程。
|
||||
- `plan-change`:把批准的拆分设计转成按依赖排序的实施计划。
|
||||
|
||||
## 4. 共同阶段与审批门
|
||||
|
||||
| 阶段 | 目标 | 主要产物 | 完成后动作 |
|
||||
| --- | --- | --- | --- |
|
||||
| P0 模式判断 | 确认新项目或已有项目口径 | 模式判断、扫描范围、风险 | 进入 G0 |
|
||||
| P1 项目初始化 | 建立可持续读取的项目上下文 | `AGENTS.md`、`.craftkit/project.json`、必要索引 | 进入 P2 |
|
||||
| P2 需求基线 | 明确目标、范围、角色、流程和验收 | 需求基线、疑问清单 | 进入 G1 |
|
||||
| P3 边界分析 | 识别业务能力、数据、接口、团队和运行约束 | 能力地图、依赖图、拆分判据 | 进入 P4 |
|
||||
| P4 应用拆分 | 形成候选方案并完成权衡 | 应用清单、职责、契约、数据和部署边界 | 进入 G2 |
|
||||
| P5 细化设计 | 细化接口、数据、流程、前后端和非功能要求 | 专项设计与验证矩阵 | 进入 P6 |
|
||||
| P6 实施规划 | 确定建设或迁移批次、兼容和回滚 | 分阶段计划、停止条件、回滚方案 | 进入 G3 |
|
||||
| P7 交付基线 | 汇总批准结论和后续执行入口 | 架构基线、决策记录、任务清单 | 流程完成 |
|
||||
|
||||
审批门:
|
||||
|
||||
- G0:确认模式、项目根、参考资料和允许扫描范围。
|
||||
- G1:确认需求基线以及仍需保留的业务待决项。
|
||||
- G2:确认应用边界、保留的替代方案和不拆分项。
|
||||
- G3:确认实施批次、外部依赖、数据迁移、兼容策略和回滚边界。
|
||||
|
||||
## 5. 应用拆分基线格式
|
||||
|
||||
每个候选应用至少记录:
|
||||
|
||||
| 字段 | 内容 |
|
||||
| --- | --- |
|
||||
| 应用名称 | 中性候选名;未确认时标记为暂定 |
|
||||
| 核心职责 | 应用负责的业务能力和业务不变量 |
|
||||
| 不负责事项 | 明确排除的能力,防止边界回流 |
|
||||
| 使用者 | 用户角色、调用方和运维主体 |
|
||||
| 对外契约 | API、事件、文件、任务或人工交互 |
|
||||
| 数据所有权 | 主数据、写入责任、读取方式和一致性要求 |
|
||||
| 上下游依赖 | 同步、异步、批处理及不可用时的行为 |
|
||||
| 运行边界 | 构建、部署、配置、扩缩容和可用性要求 |
|
||||
| 安全边界 | 认证、授权、审计、敏感数据和网络限制 |
|
||||
| 验证方式 | 契约、集成、迁移、回归和运行验证 |
|
||||
| 拆分理由 | 收益、成本、风险及未采用替代方案 |
|
||||
|
||||
## 6. 完成标准
|
||||
|
||||
- 项目模式和项目根已确认,初始化产物通过 JSON、索引和忽略规则检查。
|
||||
- 需求、当前事实、参考做法和设计建议保持可追溯分离。
|
||||
- 每个应用都有职责、不负责事项、接口、数据、依赖和运行边界。
|
||||
- 跨应用事务、数据同步、失败恢复、兼容和回滚已有明确处理方式或阻塞项。
|
||||
- 拆分方案包含至少一个替代方案,并说明为什么不选择过度拆分或维持现状。
|
||||
- 实施计划具有依赖顺序、验证方式、停止条件和可恢复路径。
|
||||
- 未经授权的编码、数据库、部署、提交和发布操作均未执行。
|
||||
@@ -1,48 +1,164 @@
|
||||
# CraftKit
|
||||
|
||||
CraftKit 是一组面向 Codex 插件市场的中性 Skill 工具。项目从通用问题出发独立实现能力,不携带任何公司的品牌、内部框架、业务规则、源码、模板或环境信息。
|
||||
CraftKit 是面向 Codex 的通用插件工具集,覆盖软件开发、文档处理、Git 交付、项目知识维护和 Skill 管理。每个插件的核心能力均可独立安装;同时安装相关插件时可以获得跨 Skill 增强,缺少增强插件时按各 Skill 声明的回退流程执行。能力描述保持简洁、中性,并以当前 Codex 能力和公开标准为基础维护。
|
||||
|
||||
## 文档导航
|
||||
版本发布与重要变更记录见 [CHANGELOG.md](CHANGELOG.md)。
|
||||
|
||||
- [协作约定](AGENTS.md):项目范围、Skill 设计、迁移边界、验证和 Git 规则。
|
||||
- [迁移计划](migration/MIGRATION_PLAN.md):迁移批次、依赖顺序、合并原则和验收门禁。
|
||||
- [迁移追踪说明](migration/README.md):来源指纹和状态维护方式。
|
||||
## 全流程自动化
|
||||
|
||||
需要根据原始需求和项目代码,串联需求分析、技术设计、开发分支、代码实现、测试审核与本地提交时,请使用 [CraftKit 全流程自动化使用指南](WORKFLOW.md)。该指南提供阶段状态机、人工审批门、自动推进规则和可直接交给 Codex 或其他已安装 CraftKit 工具的总控提示词。
|
||||
|
||||
需要从项目上下文初始化推进到应用边界识别、拆分设计和实施规划时,请使用[项目初始化到应用拆分工作流](PROJECT-INITIALIZATION-AND-APPLICATION-SPLIT.md),并根据项目现状选择:
|
||||
|
||||
- [新项目初始化与应用拆分工作流](NEW-PROJECT-INITIALIZATION-AND-APPLICATION-SPLIT.md):适用于空目录、新仓库或尚未形成有效源码结构的项目。
|
||||
- [已有项目初始化与应用拆分工作流](EXISTING-PROJECT-INITIALIZATION-AND-APPLICATION-SPLIT.md):适用于已有源码、数据、接口和部署形态,需要基于现状渐进拆分的项目。
|
||||
|
||||
## 文档维护流程
|
||||
|
||||
CraftKit 按“初始化约定 → 创建或更新 → 审核生效 → 随实现持续维护 → 关闭时分类处置”管理项目文档。过程材料默认保存在本地任务目录;正式需求、生效设计、项目规范和长期知识保存审核状态,后续任务优先更新已有权威文档。
|
||||
|
||||
长期文档使用 `pending`、`approved`、`outdated` 表示待审核、当前有效和已知过期。任务关闭不结束文档维护;实现、接口、数据模型或业务行为变化时,需要检查并同步相关留存文档。详细规则由项目 `.craftkit/standards/document-maintenance.md` 维护。
|
||||
|
||||
## 插件组成
|
||||
|
||||
| 插件 | 用途 | 当前状态 |
|
||||
| --- | --- | --- |
|
||||
| `dev` | 软件设计、实现、审查、测试、升级与估算 | 已迁移 22 个 Skill,覆盖完整通用开发流程 |
|
||||
| `doc` | 文档转换、整理与写作 | 已迁移 8 个 Skill,新增报告、消息与需求整理 |
|
||||
| `git` | 分支、提交、变更提取、集成与发布 | 已迁移 6 个 Skill,发布操作按阶段分别授权 |
|
||||
| `knowledge` | 项目初始化、交接、复盘与经验 | 已迁移 `handoff`、`init`、`trace`、`distill`、`lessons`、`worklog` |
|
||||
| `skill` | 项目规范及 Skill 创建、迁移与维护 | 已迁移 `guidance`、`guidance-edit` |
|
||||
| 插件 | 用途 |
|
||||
| --- | --- |
|
||||
| `dev` | 软件需求分析、设计、实现、审查、测试、升级与估算 |
|
||||
| `doc` | 文档转换、整理、归档与写作 |
|
||||
| `git` | 分支、提交、变更提取、集成与发布准备 |
|
||||
| `knowledge` | 项目初始化、任务交接、问题复盘与经验维护 |
|
||||
| `skill` | 项目规范检索、维护与 Skill 辅助工具 |
|
||||
| `profile` | 多语言技术能力契约、匹配规则与静态校验 |
|
||||
| `java` | Java、构建工具与 Spring 技术能力资料 |
|
||||
| `python` | Python、包管理、FastAPI、测试与专项审查资料 |
|
||||
|
||||
## Skill 介绍
|
||||
|
||||
### Dev
|
||||
|
||||
`dev` 插件覆盖从变更规划、技术设计、代码实现到专项审查和测试的软件开发流程。
|
||||
|
||||
| Skill | 用途 |
|
||||
| --- | --- |
|
||||
| `plan-change` | 分析影响范围并创建或更新可执行的变更计划,登记关联文档。 |
|
||||
| `design-backend` | 创建或更新后端设计,覆盖模块边界、事务、错误处理及数据影响。 |
|
||||
| `design-frontend` | 创建或更新前端设计,覆盖页面、路由、状态、交互和数据流。 |
|
||||
| `design-api` | 创建、更新或评审 HTTP API 契约,并维护其审核状态。 |
|
||||
| `design-db` | 创建、更新或评审数据设计及变更与回滚方案。 |
|
||||
| `design-frontend-data` | 设计前端请求边界、视图模型、状态所有权、缓存和并发处理。 |
|
||||
| `design-workflow` | 设计业务流程的任务、状态转换、权限、回退、撤回和审计规则。 |
|
||||
| `prepare-api` | 整理前后端接口清单、字段映射、类型转换、缺失项和联调风险。 |
|
||||
| `component` | 根据项目依赖和现有用法选择组件,查证 props、events 和 slots。 |
|
||||
| `form` | 设计或检查表单分组、布局、条件字段、错误展示和可访问性。 |
|
||||
| `style` | 根据项目视觉基线设计颜色、排版、间距、主题和响应式样式。 |
|
||||
| `implement-backend` | 修改后端代码,并同步检查受影响的需求、设计、规范和知识。 |
|
||||
| `implement-frontend` | 修改前端代码,并同步检查受影响的需求、设计、规范和知识。 |
|
||||
| `review-code` | 审查代码质量,以及实现与当前有效文档的一致性。 |
|
||||
| `review-java` | 专项评审 Java 代码的资源管理、并发、异常和可维护性。 |
|
||||
| `review-mybatis` | 专项评审 Mapper、动态 SQL、参数映射、事务边界和查询性能。 |
|
||||
| `review-frontend` | 专项评审前端组件边界、状态、渲染、交互、可访问性和性能。 |
|
||||
| `test-backend` | 设计、生成、修改或运行后端聚焦测试,覆盖正常、边界和失败路径。 |
|
||||
| `test-ui` | 设计 UI 测试计划,并在具备条件时执行真实浏览器测试。 |
|
||||
| `analyze-bugs` | 整理结构化 Bug 清单,完成去重、分类、趋势和风险分析。 |
|
||||
| `upgrade` | 规划并实施前端、后端或依赖的大版本升级。 |
|
||||
| `estimate` | 根据范围、依赖、未知项和验证成本给出工作量区间与假设。 |
|
||||
|
||||
### Doc
|
||||
|
||||
`doc` 插件用于常见办公文档转换、Markdown 整理和项目写作。
|
||||
|
||||
| Skill | 用途 |
|
||||
| --- | --- |
|
||||
| `docx-to-md` | 将 Word `.docx` 转换为 Markdown,并提取表格、链接和图片。 |
|
||||
| `md-to-docx` | 将 Markdown 转换为可编辑的 Word `.docx` 文档。 |
|
||||
| `xlsx-to-md` | 将 Excel `.xlsx` 工作簿按工作表转换为 Markdown 表格。 |
|
||||
| `format-md` | 修正 Markdown 的标题、空行、列表、代码块、表格和链接格式。 |
|
||||
| `archive` | 按明确规则归档历史快照,保留勘误和当前版本链接。 |
|
||||
| `requirements` | 创建或更新可审核的需求说明,避免产生冲突的平行文档。 |
|
||||
| `report` | 根据事实、Git 记录和任务状态撰写工作汇报或阶段总结。 |
|
||||
| `message` | 根据事件、受众和行动要求起草通知、提醒、确认或故障沟通消息。 |
|
||||
|
||||
### Git
|
||||
|
||||
`git` 插件提供可预览、可确认的版本控制与交付操作。
|
||||
|
||||
| Skill | 用途 |
|
||||
| --- | --- |
|
||||
| `branch` | 按仓库约定创建本地分支,并管理独立 Worktree 的创建与安全关闭。 |
|
||||
| `commit-msg` | 根据工作区或暂存区的真实变更生成 Conventional Commit 信息。 |
|
||||
| `identity` | 查看或设置 Git 提交用户名和邮箱及其作用域。 |
|
||||
| `export` | 按提交、时间或工作区范围导出变更文件并生成分类清单。 |
|
||||
| `integrate` | 评估分支集成风险,通过隔离 Worktree 准备、验证、发布和清理预集成分支。 |
|
||||
| `release` | 准备版本号、变更摘要和发布检查,并按授权执行版本提交、标签或发布。 |
|
||||
|
||||
### Knowledge
|
||||
|
||||
`knowledge` 插件通过项目内 `.craftkit/` 目录维护上下文、交接和可复用经验。
|
||||
|
||||
| Skill | 用途 |
|
||||
| --- | --- |
|
||||
| `init` | 初始化或更新项目上下文、文档目录和持续维护约定。 |
|
||||
| `document-output` | 管理文档落盘、任务关联、审核状态、持续更新和关闭处置。 |
|
||||
| `handoff` | 生成可持续更新的任务交接文档和新任务接续提示词。 |
|
||||
| `distill` | 从任务证据提炼知识,并更新、替代或标记已有结论。 |
|
||||
| `lessons` | 初始化、修订、标记过时和审计项目问题经验库。 |
|
||||
| `trace` | 复盘 Agent 的偏离、漏读或规则失效,并提出改进建议。 |
|
||||
| `worklog` | 根据指定日期、时区和作者的 Git 提交生成工作日志。 |
|
||||
|
||||
### Skill
|
||||
|
||||
`skill` 插件负责项目规范的查询和维护。
|
||||
|
||||
| Skill | 用途 |
|
||||
| --- | --- |
|
||||
| `guidance` | 检索当前有效的项目规则和知识,区分待审核、过时与历史材料。 |
|
||||
| `guidance-edit` | 建立、检查和维护 `.craftkit/standards/` 规范索引。 |
|
||||
|
||||
### Profile、Java 与 Python
|
||||
|
||||
- `profile:resolve`:根据目标模块、项目事实和当前会话已发现的提供方解析技术能力;缺失时返回明确回退。
|
||||
- `java:profile`:提供 Java、Maven/Gradle、Spring 设计、命令和审查资料。
|
||||
- `python:profile`:提供 Python、包管理、FastAPI、实现、测试和审查资料。
|
||||
- `python:review-python`:按项目版本专项审查 Python 类型、异常、资源、异步、事务和测试隔离问题。
|
||||
|
||||
跨插件逻辑标识只用于诊断。各提供方读取自身资料,核心 Skill 不扫描用户插件缓存;项目规范仍由 `guidance` 合并。
|
||||
|
||||
## 目录结构
|
||||
|
||||
```text
|
||||
CraftKit/
|
||||
├─ .agents/plugins/marketplace.json # 仓库级 Codex 市场清单
|
||||
├─ AGENTS.md # Codex 与贡献者协作约定
|
||||
├─ migration/ # 迁移计划、来源指纹与状态追踪
|
||||
├─ .agents/plugins/marketplace.json # 仓库级 Codex 插件市场清单
|
||||
├─ AGENTS.md # 项目协作与维护约定
|
||||
├─ CHANGELOG.md # SemVer 版本与重要变更记录
|
||||
├─ WORKFLOW.md # 需求到本地提交的研发交付工作流
|
||||
├─ PROJECT-INITIALIZATION-AND-APPLICATION-SPLIT.md
|
||||
│ # 项目初始化到应用拆分的共同入口
|
||||
├─ NEW-PROJECT-INITIALIZATION-AND-APPLICATION-SPLIT.md
|
||||
│ # 新项目口径
|
||||
├─ EXISTING-PROJECT-INITIALIZATION-AND-APPLICATION-SPLIT.md
|
||||
│ # 已有项目口径
|
||||
├─ plugins/ # 可独立安装的插件
|
||||
│ ├─ dev/
|
||||
│ ├─ doc/
|
||||
│ ├─ git/
|
||||
│ ├─ knowledge/
|
||||
│ └─ skill/
|
||||
│ ├─ skill/
|
||||
│ ├─ profile/
|
||||
│ ├─ java/
|
||||
│ └─ python/
|
||||
└─ README.md
|
||||
```
|
||||
|
||||
## 开发约束
|
||||
## 设计原则
|
||||
|
||||
- Skill 必须独立重写,不复制公司插件的正文、脚本、模板、示例或规则库。
|
||||
- 专有能力应先抽象为可配置、基于公开标准或用户显式输入的中性平替;不能仅因专有内容较多就整体排除。
|
||||
- 发布内容不得出现公司名称、产品名称、内部域名、内部包名、项目名或人员信息。
|
||||
- 每个 Skill 文件夹名必须与 `SKILL.md` frontmatter 的 `name` 一致。
|
||||
- 新增或修改插件后必须执行 Skill 校验、插件校验和去公司化扫描。
|
||||
- 上游变化只用于触发人工复核,不得自动覆盖已迁移内容。
|
||||
- 每个 Skill 聚焦一个清晰能力,名称与触发描述准确,避免宽泛兜底或重复功能。
|
||||
- 优先读取当前项目的代码、配置、规范和用户输入,使建议与实际环境保持一致。
|
||||
- 公共技术规则基于适用版本的官方资料维护;项目专属规则保存在项目自己的 `.craftkit/standards/` 中。
|
||||
- 涉及写文件、Git 状态、外部系统或发布的操作必须明确边界,并按风险取得用户授权。
|
||||
- 静态检查、脚本测试和真实场景验证分别记录,不用其中一种替代另一种。
|
||||
|
||||
## 本地使用
|
||||
|
||||
这是仓库级 marketplace。安装前先将本仓库注册为本地 marketplace,再按需安装其中的插件。正式发布前还需要补充许可证、公开仓库地址、作者信息、隐私政策及市场素材。
|
||||
本仓库提供仓库级 marketplace。将仓库注册为本地 marketplace 后,可按需安装 `dev`、`doc`、`git`、`knowledge`、`skill`、`profile`、`java` 或 `python` 插件。
|
||||
|
||||
正式公开发布前,还需补充许可证、公开仓库地址、作者信息、隐私政策和市场素材。
|
||||
|
||||
+453
@@ -0,0 +1,453 @@
|
||||
# CraftKit 全流程自动化使用指南
|
||||
|
||||
## 1. 文档用途
|
||||
|
||||
本文档是一份可直接交给 Codex 或其他已安装 CraftKit 的智能体执行的流程契约。它用于把原始需求、零散对话、会议纪要、问题描述和项目源码,逐步转化为:
|
||||
|
||||
1. 可确认的需求分析文档;
|
||||
2. 基于项目事实的技术设计文档;
|
||||
3. 符合仓库约定的开发分支;
|
||||
4. 经过验证的代码与测试;
|
||||
5. 可复核的代码审核结论;
|
||||
6. 范围准确的本地 Git 提交。
|
||||
|
||||
流程采用“自动执行到审批门”的方式推进。智能体负责取证、分析、编写、验证、修正和阶段衔接;人只负责批准阶段基线、选择无法从证据确定的业务决策,以及确认具有 Git 或外部环境副作用的操作。
|
||||
|
||||
本文档不授予推送、合并、发布、生产数据库变更、生产环境操作或明文凭据访问权限。若需要这些操作,必须由用户另行明确授权。
|
||||
|
||||
## 2. 适用前提
|
||||
|
||||
执行环境应满足以下条件:
|
||||
|
||||
- 已安装 CraftKit 中任务所需的 `doc`、`dev`、`git`、`knowledge` 和 `skill` 插件;
|
||||
- 智能体能够读取目标项目的需求材料、源码、Git 状态和项目内说明文件;
|
||||
- 目标项目是 Git 仓库,且用户已经给出或允许智能体识别项目根目录;
|
||||
- 项目使用的构建、测试或格式化工具在本地可用,或允许智能体如实记录环境阻塞;
|
||||
- 用户允许智能体在已批准范围内修改项目文件并运行非破坏性验证命令。
|
||||
|
||||
如果项目尚未建立 `AGENTS.md` 或 `.craftkit/project.json`,智能体可以建议使用 `init` 初始化项目上下文,但必须遵循该 Skill 的确认要求,不能隐式覆盖现有配置。
|
||||
|
||||
## 3. 核心执行原则
|
||||
|
||||
### 3.1 证据优先
|
||||
|
||||
每项结论必须标记为以下类型之一:
|
||||
|
||||
- **输入事实**:来自用户原始材料或已确认对话;
|
||||
- **源码事实**:来自当前分支的代码、配置、测试、数据库脚本或接口契约;
|
||||
- **项目规则**:来自适用的 `AGENTS.md`、`.craftkit/` 或仓库明确约定;
|
||||
- **设计建议**:尚未实施、但有依据的技术方案;
|
||||
- **待确认项**:无法从现有证据可靠确定的业务或技术决策;
|
||||
- **待验证项**:静态证据不足以证明的运行时行为。
|
||||
|
||||
不能从当前代码行为反推业务意图,也不能把相似模块的实现直接当作本需求规则。代码只能说明当前系统如何实现,不能替代用户对目标行为的确认。
|
||||
|
||||
### 3.2 最小充分读取
|
||||
|
||||
先读取项目入口、适用规则、构建文件和最相关调用链,再按证据需要扩大范围。禁止无目的加载整个仓库、整个知识库或与任务无关的业务数据。
|
||||
|
||||
### 3.3 自动推进
|
||||
|
||||
每个阶段完成且满足质量门后,智能体必须自动进入下一个阶段,不要求用户重复发送“继续”。只有到达审批门、发生阻塞或需要新增权限时才暂停。
|
||||
|
||||
用户批准某一审批门后,该批准同时表示允许智能体继续执行到下一审批门,但不扩大文件范围、外部系统范围或破坏性操作权限。
|
||||
|
||||
### 3.4 保留工作区
|
||||
|
||||
任何阶段都必须保护用户已有改动:
|
||||
|
||||
- 开始时记录 staged、unstaged 和 untracked 状态;
|
||||
- 不覆盖、还原、清理或暂存无关改动;
|
||||
- 不自动使用 `git reset --hard`、强制切换、强制删除或历史改写;
|
||||
- 无法区分本次改动与既有改动时暂停并请求用户确认;
|
||||
- `.craftkit/local/**` 和 `.craftkit/cache/**` 不纳入提交范围。
|
||||
|
||||
### 3.5 验证分层
|
||||
|
||||
验证结果必须区分:
|
||||
|
||||
- 静态检查;
|
||||
- 编译或构建;
|
||||
- 单元测试;
|
||||
- 集成测试;
|
||||
- 浏览器或真实环境验证;
|
||||
- 未执行或受环境阻塞的验证。
|
||||
|
||||
一种验证通过不能替代另一种,也不能把“计划已生成”写成“功能已验收”。
|
||||
|
||||
## 4. 流程状态机
|
||||
|
||||
| 阶段 | 主要 Skill | 核心产物 | 完成后动作 |
|
||||
| --- | --- | --- | --- |
|
||||
| S0 项目接入 | `init`、`guidance` | 项目上下文、适用规则、初始 Git 快照 | 自动进入 S1 |
|
||||
| S1 原始需求归集 | `requirements` | 需求分析文档草案、疑问清单、验收标准 | 进入审批门 G1 |
|
||||
| S2 变更规划 | `plan-change` | 影响范围、依赖顺序、验证计划 | 自动进入 S3 |
|
||||
| S3 技术设计 | `design-db`、`design-api`、`design-backend`、`design-frontend`、`design-frontend-data`、`design-workflow`、`prepare-api` | 按需生成的设计文档集合 | 进入审批门 G2 |
|
||||
| S4 分支准备 | `branch` | 分支名、基准、创建命令及风险预览 | 进入审批门 G3 |
|
||||
| S5 代码实现 | `implement-backend`、`implement-frontend` | 业务代码、配置内的非敏感必要变更、测试代码 | 自动进入 S6 |
|
||||
| S6 验证与自修复 | `test-backend`、`test-ui` | 分层验证记录、失败分类、修复结果 | 自动进入 S7 |
|
||||
| S7 代码审核 | `review-code`,按需叠加 `review-java`、`review-mybatis`、`review-frontend` | 审核报告、问题清单、未验证边界 | 自动修复明确问题后复审,进入 G4 |
|
||||
| S8 提交准备 | `commit-msg` | 精确文件范围、提交拆分与提交信息 | 进入审批门 G5 |
|
||||
| S9 本地提交与收尾 | Git 原生命令、`document-output close`、`branch close` | 本地提交、文档关闭清单、Worktree 清理结果 | 完成文档关闭门禁并释放额外 Worktree 后输出最终交付报告 |
|
||||
|
||||
阶段不得仅凭名称跳过。确实不适用时,应记录“不适用”的证据和原因,再继续推进。
|
||||
|
||||
## 5. 审批门
|
||||
|
||||
### G1 需求基线审批
|
||||
|
||||
智能体必须展示:
|
||||
|
||||
- 目标、范围内和范围外事项;
|
||||
- 用户角色、主流程、异常流程和业务规则;
|
||||
- 可测试的验收标准;
|
||||
- 输入冲突、模糊表述、缺失规则和建议默认值;
|
||||
- 拟落盘路径及将创建或修改的需求文档。
|
||||
|
||||
用户批准后,需求文档成为后续设计和验收的基线。后续发现需求级冲突时,必须回到 G1 做增量审批。
|
||||
|
||||
### G2 技术设计审批
|
||||
|
||||
智能体必须展示:
|
||||
|
||||
- 当前实现与目标实现的差距;
|
||||
- 前端、后端、数据库、API、工作流等适用设计;
|
||||
- 关键技术决策、备选方案及选择依据;
|
||||
- 数据迁移、兼容、回滚、安全和性能风险;
|
||||
- 实施步骤、文件影响范围和验证矩阵;
|
||||
- 仍需业务或外部系统确认的事项。
|
||||
|
||||
用户批准后,智能体不得自行扩大设计范围。实现过程中若必须改变已批准的核心契约,应暂停并返回 G2。
|
||||
|
||||
### G3 分支创建审批
|
||||
|
||||
按照 `branch` Skill 的要求,智能体必须在执行前展示:
|
||||
|
||||
- 当前分支和工作区状态;
|
||||
- 目标分支名;
|
||||
- 基准引用及提交短哈希;
|
||||
- 在当前工作区还是独立 Worktree 创建,以及是否影响未提交修改;
|
||||
- 使用独立 Worktree 时的准确绝对路径;
|
||||
- 唯一的分支创建命令。
|
||||
|
||||
只有用户明确批准这组最终信息后才能创建本地分支。`fetch`、创建分支、移除 Worktree 和推送分支是彼此独立的授权;本流程默认不执行 fetch 和 push。
|
||||
|
||||
### G4 代码效果审批
|
||||
|
||||
智能体必须展示:
|
||||
|
||||
- 已实现的需求条目及对应文件;
|
||||
- 需求验收标准与验证证据的映射;
|
||||
- 构建、测试、静态检查和浏览器验证结果;
|
||||
- 已自动修复的审核问题;
|
||||
- 尚未修复的问题、环境阻塞、待验证行为和残余风险;
|
||||
- 实际 Git 差异摘要。
|
||||
|
||||
只有用户确认代码效果可接受后,才能进入提交准备。用户要求调整时,流程返回 S5,并重新执行 S6、S7 和 G4。
|
||||
|
||||
### G5 提交审批
|
||||
|
||||
智能体必须展示:
|
||||
|
||||
- 每个拟提交逻辑分组及其精确文件清单;
|
||||
- staged、unstaged、untracked 和排除项;
|
||||
- Conventional Commit 提交信息;
|
||||
- 敏感文件、本地配置、缓存、二进制文件和无关改动检查结果;
|
||||
- 将执行的 `git add -- <明确路径>` 和 `git commit` 命令。
|
||||
|
||||
用户批准后,只允许暂存展示过的精确路径并创建本地提交。不得使用 `git add .`、`git add -A` 或包含未确认文件的通配符。提交完成后不得自动 push、合并、打标签或发布。
|
||||
|
||||
## 6. 各阶段执行要求
|
||||
|
||||
### S0:项目接入与基线检查
|
||||
|
||||
1. 确定项目根目录和需求材料范围。
|
||||
2. 读取所有适用的 `AGENTS.md`。
|
||||
3. 检查 `.craftkit/project.json`、规范索引、文档维护规范、构建文件、依赖锁文件和主要源码目录。
|
||||
4. 使用 `guidance` 获取本任务适用的项目规则,并区分明确规则、公共建议和代码现状。
|
||||
5. 执行只读 Git 检查,记录当前分支、HEAD、工作树状态、远程引用现状和 worktree 占用情况。
|
||||
6. 若项目上下文缺失,只在确有必要时提出 `init`;初始化写入仍遵守该 Skill 的确认步骤。
|
||||
7. 建立任务台账,至少记录任务编号、当前状态、输入、产物、审批记录、风险和下一动作。
|
||||
|
||||
推荐将本次任务的本地运行状态保存到 `documents.workRoot/<task>/task.json`;除非用户明确要求共享,不把运行状态写入可提交目录。任务记录至少登记状态、过程或共享产物、可见性、用途和关闭处置。
|
||||
|
||||
### S1:需求归集与落表
|
||||
|
||||
使用 `requirements` 处理原始需求。先检索同主题的现有需求并更新权威文档;只有不存在可维护的当前文档时才新建。输入可以是完整需求文档,也可以是聊天记录、口头描述转写、邮件、会议纪要、Bug 描述、截图文字或零散技术说明。
|
||||
|
||||
需求文档至少包含:
|
||||
|
||||
1. 背景与目标;
|
||||
2. 输入来源和证据索引;
|
||||
3. 术语与角色;
|
||||
4. 当前行为;
|
||||
5. 目标行为;
|
||||
6. 功能范围;
|
||||
7. 主流程与异常流程;
|
||||
8. 业务规则和状态规则;
|
||||
9. 数据、权限、兼容和审计要求;
|
||||
10. 非功能要求;
|
||||
11. 范围外事项;
|
||||
12. 可测试验收标准;
|
||||
13. 冲突、假设、待确认项和待验证项;
|
||||
14. 需求追踪编号。
|
||||
|
||||
需求追踪编号建议使用 `REQ-001`、`REQ-002`。后续设计、代码、测试和审核都引用这些编号,形成端到端追踪。
|
||||
|
||||
对于模糊输入,智能体应优先用源码确认“当前行为”,用用户材料提取“目标方向”,但不能替用户决定金额、时点、角色权限、状态跳转、合规要求、数据口径或其他会改变业务结果的规则。
|
||||
|
||||
### S2:变更计划
|
||||
|
||||
使用 `plan-change` 将批准的需求基线映射到项目实际代码。计划至少说明:
|
||||
|
||||
- 需求类型:新功能、增量修改、缺陷修复或重构;
|
||||
- 真实入口、调用链、数据流和相邻稳定实现;
|
||||
- 可能修改的模块和文件;
|
||||
- 前后置依赖及执行顺序;
|
||||
- 每一步的输入、产物、验证和停止条件;
|
||||
- 数据库、接口、前端、后端、工作流、部署和外部系统影响;
|
||||
- 对已有行为、版本兼容和脏工作区的保护方式。
|
||||
|
||||
变更计划是设计编排依据,不替代详细设计,也不执行代码修改。
|
||||
|
||||
### S3:技术设计
|
||||
|
||||
只调用实际适用的设计 Skill:
|
||||
|
||||
| 场景 | 使用 Skill | 重点输出 |
|
||||
| --- | --- | --- |
|
||||
| 后端模块、事务、异常、权限 | `design-backend` | 模块职责、调用关系、事务与错误语义 |
|
||||
| 表结构、约束、索引、迁移 | `design-db` | 数据模型、DDL 方案、迁移与回滚 |
|
||||
| HTTP 契约 | `design-api` | 路径、方法、请求响应、错误与兼容 |
|
||||
| 页面、路由、交互、状态 | `design-frontend` | 页面级契约和交互流程 |
|
||||
| 请求状态、缓存、竞态 | `design-frontend-data` | 状态所有权、转换和并发策略 |
|
||||
| 审批、任务、状态流转 | `design-workflow` | 状态转换、权限、幂等和补偿 |
|
||||
| 前后端字段对接 | `prepare-api` | 接口清单、字段映射和联调风险 |
|
||||
| 组件、表单、样式 | `component`、`form`、`style` | 基于项目证据的专项设计 |
|
||||
|
||||
设计产物应使用 `REQ-*` 关联需求,并为关键方案使用 `DES-*` 编号。数据库、API、前端和后端设计相互引用,不能产生字段、枚举、状态或错误语义冲突。
|
||||
|
||||
设计前检索相关已有文档,优先更新当前权威设计。共享长期文档的新建或实质修改应进入 `pending`;G2 批准可作为审核依据,将其更新为 `approved`。旧文档被替代时同步索引、引用和替代关系。
|
||||
|
||||
落盘前读取 `.craftkit/project.json` 的 `documents`:开发中的需求、计划、设计和验证记录使用 `workRoot`,用户明确要求共享或正式交付时使用 `designRoot`。缺少 `workRoot` 时回退到 `.craftkit/local/tasks/`;共享目录缺失或规则冲突时,在 G2 前提出建议路径并取得确认。`archiveRoot` 只用于另行授权的归档。
|
||||
|
||||
### S4:创建开发分支
|
||||
|
||||
需求与设计批准后,使用 `branch`:
|
||||
|
||||
1. 检查当前分支、所有本地和远程分支、Git worktree 及工作区状态;
|
||||
2. 从仓库约定识别分支格式,无约定时再建议 `feature/<short-name>`、`fix/<short-name>` 等名称;
|
||||
3. 不默认基准分支,不默认远端为最新;
|
||||
4. 验证分支名、基准提交和同名引用;
|
||||
5. 到达 G3,等待用户对最终命令的明确批准;
|
||||
6. 创建后验证实际工作目录中的分支、起点和状态;使用独立 Worktree 时,还要确认主工作区未变化并记录分支占用路径。
|
||||
|
||||
若工作区不干净,不能自动 stash、提交、还原或清理。必须说明直接切换会携带哪些修改,并优先建议在经 G3 批准的独立 Worktree 中创建分支。独立 Worktree 在开发期间保持使用,任务完成后必须通过 `branch close` 清理门禁释放分支占用。
|
||||
|
||||
### S5:代码实现
|
||||
|
||||
根据设计分别使用 `implement-backend` 和 `implement-frontend`。实现过程必须:
|
||||
|
||||
- 从当前项目确认语言、框架和精确版本;
|
||||
- 延续现有目录、命名、注释、异常、日志、事务、组件、请求和测试风格;
|
||||
- 追踪真实入口、调用方和数据落点;
|
||||
- 只实现批准范围内的最小完整变更;
|
||||
- 检查接口、数据模型、业务行为和验证结论变化是否影响已有需求、设计、规范或知识,同步更新受影响的权威文档;
|
||||
- 在代码和测试映射中引用相关 `REQ-*`、`DES-*`,但不为追踪编号制造不符合项目风格的代码注释;
|
||||
- 不虚构内部依赖、组件属性、接口、数据库行为或业务校验;
|
||||
- 不修改凭据、部署参数和生产配置;
|
||||
- 新增依赖、执行数据迁移或触达外部系统前单独申请权限。
|
||||
|
||||
前后端可独立实现时可以并行分析,但共享契约必须先稳定。任何并行工作都不能让多个执行者同时修改同一文件或同一职责边界。
|
||||
|
||||
### S6:验证与自动修复
|
||||
|
||||
智能体根据项目已有命令执行与风险匹配的验证:
|
||||
|
||||
1. 格式化和静态检查;
|
||||
2. 类型检查或编译;
|
||||
3. 聚焦单元测试;
|
||||
4. 必要的模块级或集成测试;
|
||||
5. 在具备可访问系统、授权账号和数据清理策略时,使用 `test-ui` 执行浏览器测试。
|
||||
|
||||
失败后按以下类别处理:
|
||||
|
||||
- **本次实现缺陷**:自动修复,并重新执行受影响验证;
|
||||
- **既有失败**:保留原始证据,确认与本次变更的关系,不擅自修复范围外代码;
|
||||
- **环境或依赖阻塞**:记录命令、错误摘要和未验证范围;
|
||||
- **需求或设计冲突**:返回 G1 或 G2;
|
||||
- **需要新权限**:暂停并申请最小权限。
|
||||
|
||||
不得删除测试、降低断言、屏蔽错误或伪造结果来取得通过状态。
|
||||
|
||||
### S7:代码审核与闭环
|
||||
|
||||
使用 `review-code` 审查最终工作区差异;Java、MyBatis 或前端变更存在专项风险时,叠加相应专项审核 Skill。
|
||||
|
||||
审核范围必须包含:
|
||||
|
||||
- 基线提交和最终差异;
|
||||
- 需求与设计追踪;
|
||||
- 正确性、兼容、安全、性能、并发、事务、权限和数据风险;
|
||||
- 测试充分性和未验证边界;
|
||||
- staged、unstaged 和 untracked 的准确区分。
|
||||
- 实现与当前有效文档的一致性,以及本次影响的长期文档是否已经同步;待审核、过时和历史材料不能冒充当前基线。
|
||||
|
||||
对于审核发现:
|
||||
|
||||
- 明确属于已批准范围、修复方式唯一且低风险的问题,智能体可自动返回 S5 修复并重新验证、复审;
|
||||
- 会改变业务行为、公共契约、数据库结构、依赖或范围的问题,返回相应审批门;
|
||||
- 范围外问题只记录,不擅自修改。
|
||||
|
||||
只有不存在阻塞级问题,或用户明确接受残余风险时,才能进入 G4。
|
||||
|
||||
### S8:提交准备
|
||||
|
||||
代码效果经 G4 批准后,使用 `commit-msg` 只读分析真实变更,生成一个或多个逻辑提交建议。然后由总控智能体补充精确暂存和提交命令,进入 G5。
|
||||
|
||||
提交拆分以业务目的和依赖关系为准,不按文件类型机械拆分。需求与设计文档如果是本功能交付的一部分,可以和实现一起提交,也可以按项目惯例单独提交,但必须在 G5 明确展示。
|
||||
|
||||
### S9:本地提交和交付
|
||||
|
||||
G5 批准后:
|
||||
|
||||
1. 再次检查 Git 状态;
|
||||
2. 使用精确路径暂存每个已批准分组;
|
||||
3. 检查 `git diff --cached --name-status`、`git diff --cached --check` 和暂存差异;
|
||||
4. 确认无敏感文件、缓存、本地配置和无关改动;
|
||||
5. 使用批准的提交信息创建本地提交;
|
||||
6. 验证提交哈希、提交内容、当前分支和提交后工作区状态;
|
||||
7. 将任务状态更新为 `ready_to_close`,使用 `document-output close` 生成“保留、沉淀、归档、删除、延后”清单;默认只预览,删除只处理用户确认的精确文件;
|
||||
8. 执行已确认的知识沉淀和文档归档,校验目标及引用,再完成已授权清理;存在延后项时保持未关闭状态并说明原因;
|
||||
9. 如果本次使用独立 Worktree,确认文档任务已经 `closed`,再检查 Worktree 干净、无进行中的 Git 操作且 HEAD 已被本地分支引用;
|
||||
10. 展示准确清理路径、分支、HEAD 和 `git worktree remove` 命令,取得独立确认后使用 `branch close` 移除额外 Worktree;
|
||||
11. 验证 Worktree 目录和占用记录已移除、分支与提交仍存在、主工作区未变化;
|
||||
12. 输出最终交付报告。
|
||||
|
||||
最终报告至少包含:需求与设计产物路径、分支、提交哈希、实现摘要、验证结果、审核结论、文档关闭状态、未提交文件、未验证边界和后续建议。
|
||||
|
||||
## 7. 阻塞与回退规则
|
||||
|
||||
出现下列任一情况时,智能体必须暂停自动推进:
|
||||
|
||||
- 用户输入之间存在会改变业务结果的冲突;
|
||||
- 无法确定项目根目录、基准分支或目标仓库;
|
||||
- 关键业务规则、权限、状态、金额、时间或数据口径缺失;
|
||||
- 项目规则要求人工确认或禁止当前操作;
|
||||
- 工作区已有改动与本次改动重叠且无法安全区分;
|
||||
- 需要新增依赖、联网下载、访问外部系统、执行数据库变更或使用凭据;
|
||||
- 需要 fetch、push、合并、标签、发布或历史改写;
|
||||
- 验证失败表明需求或设计基线需要变化;
|
||||
- 发现疑似密钥、令牌、私钥、生产配置或个人敏感信息;
|
||||
- 工具或权限不足,继续执行会让结果无法验证。
|
||||
|
||||
暂停时只提出完成决策所需的最少问题,并同时给出已有证据、推荐选项、影响和默认不执行的安全状态。
|
||||
|
||||
## 8. 任务台账格式
|
||||
|
||||
智能体应维护如下状态,避免长流程丢失上下文:
|
||||
|
||||
```markdown
|
||||
## 当前任务状态
|
||||
|
||||
- 任务:<名称>
|
||||
- 项目根目录:<路径>
|
||||
- 当前分支:<分支>
|
||||
- 基准提交:<哈希>
|
||||
- 当前阶段:S0-S9
|
||||
- 当前状态:执行中 / 等待审批 / 阻塞 / 已完成
|
||||
- 已批准审批门:G1、G2……
|
||||
- 本阶段输入:<文件或对话>
|
||||
- 本阶段产物:<路径或结论>
|
||||
- 已修改文件:<精确列表>
|
||||
- 已执行验证:<命令与结果>
|
||||
- 待确认项:<列表>
|
||||
- 风险与未验证项:<列表>
|
||||
- 下一动作:<唯一明确动作>
|
||||
```
|
||||
|
||||
如果环境支持任务计划或交接文件,可以把上述台账保存在 `.craftkit/local/handoff/current.md`;默认不提交该文件。
|
||||
|
||||
## 9. 可直接复制的总控提示词
|
||||
|
||||
将以下提示词与原始需求材料一起输入 Codex 或其他已安装 CraftKit 的工具。方括号中的内容按实际情况替换;不知道的内容可以保留为空,由智能体从项目中探测。
|
||||
|
||||
```text
|
||||
你是本次研发任务的总控智能体。请严格遵循项目内 AGENTS.md、CraftKit 各 Skill 的边界,以及《CraftKit 全流程自动化使用指南》。
|
||||
|
||||
项目根目录:[项目绝对路径]
|
||||
原始需求材料:[文件路径、对话内容、会议纪要或问题描述]
|
||||
期望交付:[功能目标]
|
||||
明确范围外事项:[可为空]
|
||||
期望基准分支或引用:[不知道时不要猜测]
|
||||
文档期望目录:[不知道时先识别项目约定]
|
||||
|
||||
执行目标:
|
||||
根据原始需求和当前项目代码,自动完成需求分析文档落盘、变更规划、适用的技术设计文档、开发分支创建、代码实现、测试验证、代码审核和本地 Git 提交。流程中由你统一维护状态并自动推进;人只负责审批阶段基线、无法从证据确定的业务决策和具有副作用的操作。
|
||||
|
||||
执行规则:
|
||||
1. 开始时读取适用的 AGENTS.md,检查 .craftkit 项目资料、构建文件、Git 状态和相关源码。先保存只读基线,保护现有工作区。
|
||||
2. 使用 CraftKit 的 requirements 整理原始需求,明确区分输入事实、源码事实、建议、待确认项和待验证项。生成 REQ 编号与可测试验收标准。
|
||||
3. 到达 G1 时一次性展示需求基线、疑问、建议决策和拟落盘路径,等待我批准。批准后自动执行到下一审批门,不再要求我发送“继续”。
|
||||
4. 使用 plan-change 和实际适用的设计 Skill 完成设计。只调用与需求有关的 design-db、design-api、design-backend、design-frontend、design-frontend-data、design-workflow、prepare-api、component、form、style,不为不适用领域制造空文档。
|
||||
5. 到达 G2 时展示设计、影响范围、风险、实施步骤、验证矩阵和文档路径,等待批准。
|
||||
6. 设计批准后使用 branch 检查并规划本地开发分支。严格按照该 Skill 展示当前状态、分支名、基准提交、创建位置、工作区影响和唯一创建命令,在 G3 等待明确批准。工作区不干净或要求不影响当前 checkout 时使用独立 Worktree。不要自动 fetch、stash、清理、提交或 push。
|
||||
7. 分支创建后,使用 implement-backend 和/或 implement-frontend 在批准范围内完成最小完整实现。保持项目现有语言、框架版本、目录、注释和测试风格,不虚构接口、组件、业务规则或内部依赖。
|
||||
8. 自动运行格式化、静态检查、编译、聚焦测试和具备条件的真实验证。本次实现缺陷可自动修复并重跑;需求或设计变化必须回到对应审批门。
|
||||
9. 使用 review-code 审查最终差异,并按需叠加 review-java、review-mybatis、review-frontend。已批准范围内、低风险且修复方式明确的问题自动修复、复测和复审;范围外或改变契约的问题只报告并等待决策。
|
||||
10. 到达 G4 时展示实现、REQ 验收映射、验证证据、审核结论、实际差异和残余风险,等待效果审批。
|
||||
11. 效果批准后使用 commit-msg 生成提交建议,展示精确文件分组、排除项、提交信息以及将执行的 git add -- <明确路径> 和 git commit 命令,在 G5 等待批准。
|
||||
12. G5 批准后只暂存已展示的精确路径,执行暂存检查并创建本地提交。禁止 git add .、git add -A、push、合并、打标签、发布和历史改写。
|
||||
13. 每阶段满足质量门后自动进入下一阶段。只有审批门、证据不足、权限缺失、脏工作区冲突、敏感信息或高风险外部操作可以暂停。
|
||||
14. 每次等待审批时,给出:已完成事项、产物、关键证据、需要批准的明确内容、批准后的自动动作。不要只问“是否继续”。
|
||||
15. 本地提交核对完成后,如果使用了独立 Worktree,确认生命周期已经结束并进入 branch close:展示准确路径、分支、HEAD、干净状态和唯一移除命令,取得确认后移除,验证分支与提交仍存在且主工作区未变化。
|
||||
16. 最终报告必须包含文档路径、分支、提交哈希、变更文件、验证结果、审核结论、未提交内容、未验证边界、Worktree 清理结果和后续建议。
|
||||
|
||||
现在从 S0 开始执行,并自动推进到 G1。
|
||||
```
|
||||
|
||||
## 10. 审批回复建议
|
||||
|
||||
为减少歧义,用户可以使用以下简短格式审批:
|
||||
|
||||
```text
|
||||
批准 G1。需求基线按当前版本执行;待确认项 2 采用方案 B,其余保持范围外。自动推进到 G2。
|
||||
```
|
||||
|
||||
```text
|
||||
批准 G2。允许按展示的设计和文件范围实现;不允许新增依赖或修改部署配置。自动推进到 G3。
|
||||
```
|
||||
|
||||
```text
|
||||
批准 G3。执行展示的唯一分支创建命令,随后自动推进到 G4。
|
||||
```
|
||||
|
||||
```text
|
||||
批准 G4。接受列明的未验证边界,按当前差异准备提交并推进到 G5。
|
||||
```
|
||||
|
||||
```text
|
||||
批准 G5。只暂存展示的精确文件并创建本地提交;不要 push。
|
||||
```
|
||||
|
||||
如果用户只回复“批准”,智能体只能把它解释为对当前唯一审批门中已完整展示内容的批准,不能扩展为后续审批门、外部系统或高风险操作的预授权。
|
||||
|
||||
## 11. 流程完成标准
|
||||
|
||||
仅当以下条件全部满足时,任务状态才能标记为“已完成”:
|
||||
|
||||
- 需求基线已经批准并落盘;
|
||||
- 所有适用设计已经批准并落盘;
|
||||
- 本地开发分支已按批准命令创建;
|
||||
- 批准范围内的代码已实现;
|
||||
- 所有可执行验证已完成,阻塞与未验证项已如实记录;
|
||||
- 代码审核不存在未接受的阻塞问题;
|
||||
- 代码效果已通过 G4;
|
||||
- 提交范围与信息已通过 G5;
|
||||
- 本地提交已创建并核对内容;
|
||||
- 本次影响的长期文档已同步,需要作为当前依据的文档审核状态为 `approved`;
|
||||
- 任务文档已生成关闭预览;已确认的沉淀、归档和删除均已验证,延后项已明确记录;
|
||||
- 使用独立 Worktree 时,其生命周期已经结束并安全移除;若用户明确要求保留现场,则任务状态应说明生命周期尚未结束及分支占用路径;
|
||||
- 未发生未经授权的 push、合并、发布、生产操作或历史改写。
|
||||
|
||||
如果由于环境或外部依赖无法完成某项验证,任务只能标记为“本地实现完成,等待外部验证”,不能声称全流程验收通过。
|
||||
@@ -1,305 +0,0 @@
|
||||
# Skill 迁移计划
|
||||
|
||||
## 1. 目标
|
||||
|
||||
将两个本地来源中的通用能力整理为 CraftKit Skill。迁移结果必须适用于 Codex 插件市场,并与来源项目的品牌、内部框架、业务知识和运行环境解耦。
|
||||
|
||||
迁移不追求来源 Skill 与目标 Skill 一一对应。重复能力应合并;公司专属实现不得迁移,但应优先将其解决的通用问题重建为中性平替,确无独立价值或无法安全替代时才排除。目标数量以职责清晰和实际复用价值为准。
|
||||
|
||||
## 2. 迁移路径
|
||||
|
||||
```text
|
||||
来源发现
|
||||
→ 风险分类
|
||||
→ 重复能力合并
|
||||
→ 中性能力规格
|
||||
→ 独立实现
|
||||
→ 行为验证
|
||||
→ 敏感内容扫描
|
||||
→ Codex 与插件校验
|
||||
→ 更新迁移状态
|
||||
```
|
||||
|
||||
禁止采用“完整复制来源目录后批量替换名称”的方式。中性能力规格形成后,目标实现应基于该规格、当前 Codex 能力和公开资料完成。
|
||||
|
||||
## 3. 状态模型
|
||||
|
||||
| 状态 | 含义 | 进入条件 |
|
||||
| --- | --- | --- |
|
||||
| `pending` | 待评估 | 已发现来源 Skill |
|
||||
| `specified` | 已完成中性规格 | 已明确目标、边界、依赖和排除内容 |
|
||||
| `rewriting` | 独立实现中 | 已创建目标 Skill |
|
||||
| `review` | 待复核 | 功能完成,但版权、依赖或行为仍需确认 |
|
||||
| `migrated` | 已迁移 | 全部门禁通过 |
|
||||
| `excluded` | 不迁移 | 公司专属或没有独立价值 |
|
||||
| `superseded` | 已合并 | 能力已由另一个目标 Skill 覆盖 |
|
||||
|
||||
## 4. 迁移批次
|
||||
|
||||
迁移分为“特殊样本”和“同质批量”两个阶段。前者用于覆盖迁移机制的不同风险类型,后者在规则稳定后提高吞吐量。批次数量不固定:特殊样本原则上逐个迁移,批量阶段每批建议 6~12 个同质 Skill。
|
||||
|
||||
### 第 0 批:迁移基础设施
|
||||
|
||||
第 0 批属于仓库内部维护工具,不发布为市场 Skill:
|
||||
|
||||
1. `migration/scripts/scan_sources.py`:只读发现来源 Skill、辅助资源和文件哈希。
|
||||
2. `AGENTS.md` 迁移工作流:完成分类、目标设计和用户确认。
|
||||
3. `migration/scripts/check_skill.py`:检查结构、引用、占位符、敏感内容和凭据风险。
|
||||
4. `migration/scripts/update_lock.py`:预览或更新来源指纹和迁移状态。
|
||||
|
||||
完成门槛:能够对全部来源 Skill 生成稳定清单,并在不复制来源内容的情况下更新状态。
|
||||
|
||||
### 第 1 阶段:特殊样本
|
||||
|
||||
特殊样本不追求模块连续性,而是覆盖不同迁移机制:
|
||||
|
||||
1. `doc/format-md`:纯指令型样本,已完成。
|
||||
2. `doc/docx-to-md`:多来源合并、脚本、依赖和生成物样本,已完成。
|
||||
3. `git/commit-msg`:只读 Git 状态分析样本,已完成。
|
||||
4. `git/branch`:修改仓库状态和二次授权边界样本,已完成。
|
||||
5. `knowledge/handoff`:模板化文档与项目上下文样本,已完成。
|
||||
6. `skill/guidance`:大型参考资料、索引和渐进式加载样本,已完成;只检索项目资料和基于公开一级资料独立重建的中性公共基线。
|
||||
7. `knowledge/init`:成熟项目与空项目双模式初始化、参考项目提炼和共享/本地信息边界样本,已完成。
|
||||
8. `skill/migrate`:不迁移。来源能力用于把 Claude Code Skill 转换为 Codex Skill;CraftKit 自始按 Codex 规范开发,不存在平台转换需求。来源扫描、目标检查和状态追踪继续由 `migration/scripts/` 作为仓库维护设施承担。
|
||||
|
||||
完成门槛:适用样本均通过对应验证,不适用样本记录排除依据,并形成可复用的命名、目录、独立实现、测试、扫描和状态同步规则。出现未覆盖的新结构或权限类型时,应补充样本,不直接扩批。当前特殊样本阶段已完成,可以进入同质批量迁移。
|
||||
|
||||
### 第 2 阶段:同质批量迁移
|
||||
|
||||
特殊样本完成后,按同一插件、相近能力和相同风险类型组织批量迁移:
|
||||
|
||||
- 每批建议 6~12 个 Skill,高度同质时可以整组处理。
|
||||
- 不把只读能力与有副作用能力、纯指令与复杂脚本、普通迁移与公开资料重建强行合为一批。
|
||||
- 每批仍需迁移前确认和提交前确认,并统一更新 README、迁移计划和来源状态。
|
||||
- 任一验收门禁失败时暂停该批,不继续扩大范围。
|
||||
|
||||
### 文档转换批次
|
||||
|
||||
所属插件:`doc`
|
||||
|
||||
1. `docx-to-md`
|
||||
2. `md-to-docx`(已完成)
|
||||
3. `xlsx-to-md`(已完成)
|
||||
4. `archive`(已完成,以可配置规则平替固定目录、业务文件名、专有章节拆分和内部系统校验)
|
||||
|
||||
重点验证图片、表格、合并单元格、编码、覆盖策略和路径安全。脚本及测试数据必须独立创建。
|
||||
|
||||
### Git 工作流批次
|
||||
|
||||
所属插件:`git`
|
||||
|
||||
1. `branch`(已完成)
|
||||
2. `identity`(已完成,只管理 Git 提交用户名和邮箱)
|
||||
3. `export`(已完成,环境配置默认排除,规范明确要求并再次确认后才可导出)
|
||||
4. `integrate`(已完成,按项目规范通过隔离 worktree 评估、准备和发布预集成分支)
|
||||
|
||||
`commit-msg` 将作为只读 Git 特殊样本先行完成。涉及提交、合并和远端操作的 Skill 必须保留明确授权边界,并保护脏工作区。
|
||||
|
||||
### 知识管理批次
|
||||
|
||||
所属插件:`knowledge`
|
||||
|
||||
1. `trace`(已完成)
|
||||
2. `distill`(已完成)
|
||||
3. `lessons`(已完成,合并初始化、维护、审计和提升)
|
||||
4. `worklog`(已完成)
|
||||
5. `init`(已完成)
|
||||
|
||||
来源中与经验初始化、提升和回扫相关的多个能力统一合并为 `maintain-lessons`,通过模式区分具体工作。
|
||||
|
||||
### 开发主流程批次
|
||||
|
||||
所属插件:`dev`
|
||||
|
||||
```text
|
||||
plan-change
|
||||
├─ design-backend → implement-backend → test-backend
|
||||
└─ design-frontend → implement-frontend → test-ui
|
||||
↓
|
||||
review-code
|
||||
```
|
||||
|
||||
建议顺序:
|
||||
|
||||
1. `plan-change`(已完成)
|
||||
2. `design-backend`(已完成)
|
||||
3. `design-frontend`(已完成)
|
||||
4. `prepare-api`(已完成)
|
||||
5. `implement-backend`(已完成)
|
||||
6. `implement-frontend`(已完成)
|
||||
7. `review-code`(已完成)
|
||||
8. `test-backend`(已完成)
|
||||
9. `test-ui`(已完成)
|
||||
10. `analyze-bugs`(已完成)
|
||||
|
||||
多个来源中的代码检查、代码审查能力合并为 `review-code`,通过工作区、提交和分支三种模式覆盖。
|
||||
|
||||
### 项目规范与前端辅助批次
|
||||
|
||||
1. `dev/component`(已完成,基于项目证据完成组件选型与契约查证)
|
||||
2. `dev/style`(已完成,基于项目视觉基线设计样式)
|
||||
3. `dev/form`(已完成,设计表单结构、响应布局和可访问性)
|
||||
4. `skill/guidance`(特殊样本已完成)
|
||||
5. `skill/guidance-edit`(已完成,建立、检查和维护项目规范索引)
|
||||
|
||||
这里只实现读取和维护“当前项目自身规范”的机制,不随 CraftKit 提供任何来源项目规范。
|
||||
原前端导航能力由上述 Skill 的精确触发描述和 Codex 自动发现替代,不再维护独立路由 Skill。混合任务按 `style` → `component` → `form` → 前端设计或实现的依赖顺序处理。
|
||||
|
||||
### 基于公开资料重建批次
|
||||
|
||||
以下能力不从来源文本改写,而是根据官方资料重新设计:
|
||||
|
||||
1. `dev/design-api`(已完成)
|
||||
2. `dev/design-db`(已完成)
|
||||
3. `dev/review-java`(已完成)
|
||||
4. `dev/review-frontend`(已完成)
|
||||
5. `dev/design-frontend-data`(已完成)
|
||||
6. `dev/review-mybatis`(已完成)
|
||||
7. `dev/design-workflow`(已完成)
|
||||
|
||||
中性规格必须记录所采用的公开标准、官方文档和许可证信息。
|
||||
|
||||
### 平替或排除结果
|
||||
|
||||
- 公司框架知识与专属规范由 `skill/guidance`、项目源码和 `.craftkit/standards/` 平替。
|
||||
- 内部组件契约、审批规则和消息格式不迁移,目标 Skill 只读取项目证据和用户输入。
|
||||
- 升级、估算与发布已重建为通用能力,不携带内部版本矩阵和仓库流程。
|
||||
- 浏览器代理配置由 Codex 浏览器或计算机操作能力平替。
|
||||
- Skill 路由依靠精确触发描述和 Codex 自动发现,不增加独立路由器。
|
||||
- 非 Codex 平台转换能力保持排除。
|
||||
|
||||
### 剩余迁移波次
|
||||
|
||||
截至 2026-08-26,原有 29 个 `pending` 来源已在一个连续波次内全部处理完成。所有来源均已闭合为 `migrated`、`superseded` 或 `excluded`;本波次完成验证后统一等待本地提交确认。
|
||||
|
||||
#### 阶段 1:公开基线与专项设计
|
||||
|
||||
| 来源能力 | 目标 Skill | 处理方式 |
|
||||
| --- | --- | --- |
|
||||
| API 约定 | `dev/design-api` | 基于 HTTP、OpenAPI 等官方资料独立重建 |
|
||||
| 数据库约定 | `dev/design-db` | 基于目标数据库官方资料和项目证据独立重建 |
|
||||
| Java 约定 | `dev/review-java` | 基于 Java 与所用框架对应版本官方资料独立重建 |
|
||||
| 前端约定 | `dev/review-frontend` | 基于当前框架版本官方资料独立重建 |
|
||||
| 前端数据约定 | `dev/design-frontend-data` | 建立请求、状态与视图模型的通用设计边界 |
|
||||
| MyBatis 约定 | `dev/review-mybatis` | 基于 MyBatis 官方资料独立重建 |
|
||||
| 工作流约定 | `dev/design-workflow` | 以项目工作流契约和用户输入平替内部审批规则 |
|
||||
|
||||
公开资料只采用一级官方来源,记录适用版本、重建日期和许可证或引用边界;不得改写来源规范正文。
|
||||
|
||||
#### 阶段 2:代码实现
|
||||
|
||||
| 来源 Skill | 目标 Skill | 状态关系 |
|
||||
| --- | --- | --- |
|
||||
| `back-code`、同类后端编码来源 | `dev/implement-backend` | 两个来源合并,一个迁移、一个 `superseded` |
|
||||
| `front-code`、同类前端编码来源 | `dev/implement-frontend` | 两个来源合并,一个迁移、一个 `superseded` |
|
||||
|
||||
实现 Skill 直接修改业务源码,必须保护脏工作区、使用项目真实版本与规范、执行风险相称的验证,且不自动提交或推送。
|
||||
|
||||
#### 阶段 3:审查、测试与问题分析
|
||||
|
||||
| 来源能力 | 目标 Skill | 处理方式 |
|
||||
| --- | --- | --- |
|
||||
| 两套代码检查与一套代码审查 | `dev/review-code` | 合并为工作区、提交和分支审查模式 |
|
||||
| 后端单元测试 | `dev/test-backend` | 按当前测试框架和项目模式生成或修改测试 |
|
||||
| UI 测试 | `dev/test-ui` | 按用户可观察行为设计并执行浏览器测试 |
|
||||
| Bug 列表分析 | `dev/analyze-bugs` | 解析通用结构化问题清单并形成证据化报告 |
|
||||
|
||||
本阶段不得把静态检查、单元测试、浏览器测试和真实环境验收混为同一结论。
|
||||
|
||||
#### 阶段 4:交付、升级与估算
|
||||
|
||||
| 来源能力 | 目标 Skill 或处理结果 | 处理方式 |
|
||||
| --- | --- | --- |
|
||||
| 后端升级、前端升级 | `dev/upgrade` | 合并为基于源版本、目标版本和官方迁移资料的通用升级流程 |
|
||||
| 版本发布 | `git/release` | 只准备版本、变更摘要、标签和发布检查;远端动作单独授权 |
|
||||
| 工作量评估 | `dev/estimate` | 基于范围、依赖、风险和假设输出区间估算 |
|
||||
| 框架约定 | `skill/guidance` | `superseded`,内部规则由项目 `.craftkit/standards/` 提供 |
|
||||
| 框架知识查询 | `skill/guidance` | `superseded`,改为检索项目证据和公开官方资料 |
|
||||
|
||||
#### 阶段 5:写作与平台工具收尾
|
||||
|
||||
| 来源能力 | 目标 Skill 或处理结果 | 处理方式 |
|
||||
| --- | --- | --- |
|
||||
| 领导汇报 | `doc/report` | 中性化为面向不同受众的事实型工作汇报 |
|
||||
| 消息模板 | `doc/message` | 中性化为项目消息与通知草稿 |
|
||||
| 技术内容转需求 | `doc/requirements` | 将技术输入转换为可确认的需求说明 |
|
||||
| 能力创建器 | 官方 `skill-creator` | `superseded`,不重复发布同类 CraftKit Skill |
|
||||
| 浏览器代理配置 | Codex 浏览器或计算机操作能力 | `superseded`,不迁移宿主专属代理配置 |
|
||||
| Skill 转 Cursor | 无 | `excluded`,CraftKit 只面向 Codex |
|
||||
|
||||
#### 波次总门禁
|
||||
|
||||
1. 29 个来源全部更新为 `migrated`、`superseded` 或 `excluded`,不得遗留 `pending`。
|
||||
2. 所有目标 Skill 通过结构、引用、敏感内容和真实请求边界测试。
|
||||
3. 公开基线记录官方来源、适用版本和重建边界。
|
||||
4. 有脚本的 Skill 完成隔离行为测试;有外部工具的 Skill 明确权限和未验证边界。
|
||||
5. README、插件版本、迁移计划和来源锁同步一致。
|
||||
6. 全量测试、JSON 校验和 `git diff --check` 通过。
|
||||
7. 波次完成后只展示提交方案,不创建提交;用户统一确认后按逻辑范围创建本地提交。
|
||||
|
||||
## 5. 合并原则
|
||||
|
||||
来源数量不等于目标数量。优先执行以下合并:
|
||||
|
||||
| 来源能力类型 | 目标 Skill |
|
||||
| --- | --- |
|
||||
| 代码检查、提交审查、分支审查 | `review-code` |
|
||||
| 多套开发计划 | `plan-change` |
|
||||
| 多套后端设计 | `design-backend` |
|
||||
| 多套前端设计 | `design-frontend` |
|
||||
| 多套后端实现 | `implement-backend` |
|
||||
| 多套前端实现 | `implement-frontend` |
|
||||
| 多套 Word 转 Markdown | `docx-to-md` |
|
||||
| 经验初始化、提升、回扫 | `maintain-lessons` |
|
||||
| 规范检索和索引维护 | `guidance`、`guidance-edit` |
|
||||
|
||||
目标 Skill 总量不设硬指标,预期控制在约 30 个,避免细碎能力和重复触发。
|
||||
|
||||
## 6. 单个 Skill 的迁移步骤
|
||||
|
||||
1. 记录来源相对路径、提交和 SHA-256。
|
||||
2. 判断该能力是迁移、合并、重建还是排除。
|
||||
3. 只提炼目标、输入、输出、关键边界和真实用例,形成中性规格。
|
||||
4. 确定目标插件和简短 Skill 名称。
|
||||
5. 基于中性规格和公开资料独立实现。
|
||||
6. 对脚本执行单元或行为测试,对文档型 Skill 执行真实请求测试。
|
||||
7. 扫描敏感内容、来源残留、无效工具名和宿主绑定表达。
|
||||
8. 运行 Skill 与插件校验。
|
||||
9. 将状态更新为 `migrated`,记录目标路径、目标版本和复核日期。
|
||||
10. 展示迁移结果、验证证据、待提交文件和建议提交信息,等待用户再次确认。
|
||||
11. 用户确认后精确暂存本批文件并创建本地提交;推送和发布仍需独立授权。
|
||||
|
||||
## 7. 每批验收门禁
|
||||
|
||||
- Skill 名称简洁,目录名与 frontmatter 一致。
|
||||
- `description` 能准确触发,不是大而全的能力描述。
|
||||
- 不存在来源正文、脚本、模板、示例或独特结构的直接复制。
|
||||
- 公司标识、内部域名、包名、路径和人员信息扫描为零。
|
||||
- 所有引用文件存在,脚本和生成物经过实际验证。
|
||||
- Skill 校验和所属插件校验通过。
|
||||
- 至少一个真实请求用例通过。
|
||||
- `source-lock.json` 已更新。
|
||||
|
||||
任一门禁未通过时,不进入下一批的大规模迁移。
|
||||
|
||||
## 8. 当前执行顺序
|
||||
|
||||
- [x] 扩展 `source-lock.json` 的 Skill 级记录结构。
|
||||
- [x] 实现来源只读扫描脚本。
|
||||
- [x] 在 `AGENTS.md` 中固化分类、设计和确认流程。
|
||||
- [x] 实现 Skill 与敏感内容检查脚本。
|
||||
- [x] 实现迁移台账预览和更新脚本。
|
||||
- [x] 迁移并验证首个样板 `doc/format-md`。
|
||||
- [x] 迁移并验证脚本型特殊样本 `doc/docx-to-md`。
|
||||
- [x] 迁移并验证只读 Git 特殊样本 `git/commit-msg`。
|
||||
- [x] 迁移并验证有副作用 Git 特殊样本 `git/branch`。
|
||||
- [x] 迁移并验证模板化交接特殊样本 `knowledge/handoff`。
|
||||
- [x] 完成其余特殊样本并总结批量迁移规则。
|
||||
- [ ] 按插件和风险类型继续推进同质批量迁移。
|
||||
- [x] 完成首个同质批量:`md-to-docx`、`xlsx-to-md`、`archive`。
|
||||
- [x] 完成 Git 本地操作批次:`identity`、`export`。
|
||||
- [x] 完成 Git 高风险隔离集成样本:`integrate`。
|
||||
- [x] 完成知识管理批次:`trace`、`distill`、`lessons`、`worklog`。
|
||||
- [x] 完成前端辅助批次:`component`、`style`、`form`,并以精确触发替代独立路由。
|
||||
- [x] 完成项目规范维护能力:`guidance-edit`。
|
||||
- [x] 完成开发分析与设计批次:`plan-change`、`design-backend`、`design-frontend`、`prepare-api`。
|
||||
@@ -1,23 +0,0 @@
|
||||
# 迁移追踪说明
|
||||
|
||||
本目录只记录来源指纹、迁移状态和人工复核结果,不存放或打包公司插件内容。
|
||||
|
||||
- [迁移计划](MIGRATION_PLAN.md):批次顺序、依赖、合并策略与验收门禁。
|
||||
- `source-lock.json`:可提交的来源指纹和迁移状态。
|
||||
- `local-sources.json`:本地来源路径,不提交;结构参考 `local-sources.example.json`。
|
||||
- `scripts/scan_sources.py`:只读生成来源 Skill 指纹清单。
|
||||
- `scripts/check_skill.py`:检查迁移后 Skill 的结构、引用和敏感内容。
|
||||
- `scripts/update_lock.py`:根据扫描报告预览或更新迁移台账。
|
||||
- `tests/`:迁移脚本的隔离行为测试。
|
||||
|
||||
扫描报告可能包含来源 Skill 名称和相对路径,应写入本地临时目录或忽略文件,不进入插件发布内容。
|
||||
|
||||
同步流程:
|
||||
|
||||
1. 读取来源仓库当前提交与 Skill 文件哈希。
|
||||
2. 与 `source-lock.json` 比较,生成新增、修改、删除清单。
|
||||
3. 人工判断变化是否属于可公开迁移的通用能力。
|
||||
4. 在 CraftKit 中独立重写并完成验证。
|
||||
5. 更新来源指纹、目标路径、状态和复核日期。
|
||||
|
||||
允许的状态:`pending`、`specified`、`rewriting`、`review`、`migrated`、`excluded`、`superseded`。
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"source-a": "D:/path/to/local/source-a",
|
||||
"source-b": "D:/path/to/local/source-b"
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""检查 CraftKit Skill 的基础结构、引用和敏感内容。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import re
|
||||
from pathlib import Path
|
||||
|
||||
NAME_RE = re.compile(r"^[a-z0-9]+(?:-[a-z0-9]+)*$")
|
||||
LINK_RE = re.compile(r"\[[^]]+]\((?!https?://|#)([^)]+)\)")
|
||||
SECRET_RE = re.compile(
|
||||
r"(?i)(api[_-]?key|password|private[_-]?key|access[_-]?token)\s*[:=]\s*[^\s]+"
|
||||
)
|
||||
|
||||
|
||||
def frontmatter(text: str) -> dict[str, str]:
|
||||
"""解析当前校验所需的简单顶层 frontmatter 字段。"""
|
||||
if not text.startswith("---\n"):
|
||||
return {}
|
||||
end = text.find("\n---", 4)
|
||||
if end < 0:
|
||||
return {}
|
||||
values: dict[str, str] = {}
|
||||
for line in text[4:end].splitlines():
|
||||
if ":" in line and not line.startswith((" ", "\t")):
|
||||
key, value = line.split(":", 1)
|
||||
values[key.strip()] = value.strip().strip("'\"")
|
||||
return values
|
||||
|
||||
|
||||
def check_skill(root: Path, forbidden: list[str]) -> dict:
|
||||
"""返回结构化问题列表,不修改被检查目录。"""
|
||||
issues: list[dict[str, str]] = []
|
||||
skill_md = root / "SKILL.md"
|
||||
if not skill_md.is_file():
|
||||
return {"skill": root.name, "issues": [{"code": "missing-skill-md", "path": "SKILL.md"}]}
|
||||
text = skill_md.read_text(encoding="utf-8-sig")
|
||||
metadata = frontmatter(text)
|
||||
name = metadata.get("name", "")
|
||||
if not NAME_RE.fullmatch(name):
|
||||
issues.append({"code": "invalid-name", "path": "SKILL.md"})
|
||||
if name != root.name:
|
||||
issues.append({"code": "name-path-mismatch", "path": "SKILL.md"})
|
||||
if not metadata.get("description"):
|
||||
issues.append({"code": "missing-description", "path": "SKILL.md"})
|
||||
|
||||
for path in sorted(item for item in root.rglob("*") if item.is_file()):
|
||||
relative = path.relative_to(root).as_posix()
|
||||
content = path.read_text(encoding="utf-8-sig", errors="replace")
|
||||
if "[TODO:" in content:
|
||||
issues.append({"code": "todo-placeholder", "path": relative})
|
||||
if SECRET_RE.search(content):
|
||||
issues.append({"code": "possible-secret", "path": relative})
|
||||
lowered = content.casefold()
|
||||
for term in forbidden:
|
||||
if term.casefold() in lowered:
|
||||
issues.append({"code": f"forbidden:{term}", "path": relative})
|
||||
if path.suffix.lower() == ".md":
|
||||
for link in LINK_RE.findall(content):
|
||||
target = link.split("#", 1)[0]
|
||||
if target and not (path.parent / target).resolve().is_file():
|
||||
issues.append({"code": "broken-link", "path": f"{relative}:{link}"})
|
||||
return {"skill": root.name, "issues": issues}
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(description="检查 CraftKit Skill")
|
||||
parser.add_argument("skill", nargs="+", type=Path)
|
||||
parser.add_argument("--forbid", action="append", default=[])
|
||||
args = parser.parse_args()
|
||||
results = [check_skill(path.resolve(), args.forbid) for path in args.skill]
|
||||
print(json.dumps({"results": results}, ensure_ascii=False, indent=2))
|
||||
raise SystemExit(1 if any(item["issues"] for item in results) else 0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,111 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""只读扫描来源目录中的 Skill,并输出稳定的 JSON 清单。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import subprocess
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def file_hash(path: Path) -> str:
|
||||
"""按二进制内容计算单文件 SHA-256。"""
|
||||
digest = hashlib.sha256()
|
||||
with path.open("rb") as stream:
|
||||
for block in iter(lambda: stream.read(65536), b""):
|
||||
digest.update(block)
|
||||
return digest.hexdigest()
|
||||
|
||||
|
||||
def directory_hash(root: Path) -> tuple[str, int]:
|
||||
"""把相对路径和文件内容共同纳入哈希,确保结构变化也可被识别。"""
|
||||
digest = hashlib.sha256()
|
||||
files = sorted(path for path in root.rglob("*") if path.is_file())
|
||||
for path in files:
|
||||
relative = path.relative_to(root).as_posix()
|
||||
digest.update(relative.encode("utf-8"))
|
||||
digest.update(b"\0")
|
||||
digest.update(bytes.fromhex(file_hash(path)))
|
||||
return digest.hexdigest(), len(files)
|
||||
|
||||
|
||||
def read_skill_name(skill_md: Path) -> str:
|
||||
"""从 YAML frontmatter 中读取 name;解析失败时回退为目录名。"""
|
||||
for line in skill_md.read_text(encoding="utf-8-sig").splitlines():
|
||||
if line.startswith("name:"):
|
||||
return line.split(":", 1)[1].strip().strip("'\"") or skill_md.parent.name
|
||||
return skill_md.parent.name
|
||||
|
||||
|
||||
def git_commit(root: Path) -> str | None:
|
||||
"""尽力读取来源提交;非 Git 目录时返回空值,不阻塞文件扫描。"""
|
||||
result = subprocess.run(
|
||||
["git", "-c", f"safe.directory={root.as_posix()}", "-C", str(root), "rev-parse", "HEAD"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=False,
|
||||
)
|
||||
return result.stdout.strip() if result.returncode == 0 else None
|
||||
|
||||
|
||||
def scan_source(source_id: str, root: Path) -> dict:
|
||||
"""扫描单个来源,结果仅包含相对路径和指纹,不包含本地绝对路径。"""
|
||||
if not root.is_dir():
|
||||
raise ValueError(f"来源目录不存在:{root}")
|
||||
skills = []
|
||||
for skill_md in sorted(root.rglob("SKILL.md")):
|
||||
skill_root = skill_md.parent
|
||||
digest, file_count = directory_hash(skill_root)
|
||||
children = sorted(
|
||||
child.name for child in skill_root.iterdir() if child.is_dir()
|
||||
)
|
||||
skills.append(
|
||||
{
|
||||
"name": read_skill_name(skill_md),
|
||||
"relativePath": skill_root.relative_to(root).as_posix(),
|
||||
"sha256": digest,
|
||||
"fileCount": file_count,
|
||||
"resources": children,
|
||||
}
|
||||
)
|
||||
return {
|
||||
"id": source_id,
|
||||
"commit": git_commit(root),
|
||||
"skillCount": len(skills),
|
||||
"skills": skills,
|
||||
}
|
||||
|
||||
|
||||
def parse_source(value: str) -> tuple[str, Path]:
|
||||
"""解析 id=path 参数,避免把本地路径写入输出文件。"""
|
||||
if "=" not in value:
|
||||
raise argparse.ArgumentTypeError("来源参数必须使用 id=path 格式")
|
||||
source_id, raw_path = value.split("=", 1)
|
||||
if not source_id.strip() or not raw_path.strip():
|
||||
raise argparse.ArgumentTypeError("来源标识和路径均不能为空")
|
||||
return source_id.strip(), Path(raw_path).expanduser().resolve()
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(description="只读扫描 Skill 来源目录")
|
||||
parser.add_argument("--source", action="append", required=True, type=parse_source)
|
||||
parser.add_argument("--output", type=Path, help="可选 JSON 输出路径;省略时输出到终端")
|
||||
args = parser.parse_args()
|
||||
payload = {
|
||||
"schemaVersion": 1,
|
||||
"generatedAt": datetime.now(timezone.utc).isoformat(),
|
||||
"sources": [scan_source(source_id, root) for source_id, root in args.source],
|
||||
}
|
||||
content = json.dumps(payload, ensure_ascii=False, indent=2) + "\n"
|
||||
if args.output:
|
||||
args.output.parent.mkdir(parents=True, exist_ok=True)
|
||||
args.output.write_text(content, encoding="utf-8")
|
||||
else:
|
||||
print(content, end="")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,65 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""根据扫描报告更新迁移台账;默认预览,显式 --apply 才写入。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
from datetime import date
|
||||
from pathlib import Path
|
||||
|
||||
VALID_STATUS = {
|
||||
"pending", "specified", "rewriting", "review",
|
||||
"migrated", "excluded", "superseded",
|
||||
}
|
||||
|
||||
|
||||
def merge(lock: dict, report: dict) -> dict:
|
||||
"""保留人工维护字段,仅同步来源提交、数量和 Skill 指纹。"""
|
||||
lock.setdefault("schemaVersion", 1)
|
||||
lock["updatedAt"] = date.today().isoformat()
|
||||
lock.setdefault("sources", {})
|
||||
lock.setdefault("skills", {})
|
||||
for source in report.get("sources", []):
|
||||
source_id = source["id"]
|
||||
lock["sources"][source_id] = {
|
||||
"commit": source.get("commit"),
|
||||
"skillCount": source["skillCount"],
|
||||
}
|
||||
for skill in source["skills"]:
|
||||
# 发布台账不保存来源名称和路径;本地扫描报告负责提供可读映射。
|
||||
path_hash = hashlib.sha256(skill["relativePath"].encode("utf-8")).hexdigest()
|
||||
key = f"{source_id}:{path_hash[:16]}"
|
||||
current = lock["skills"].get(key, {})
|
||||
status = current.get("status", "pending")
|
||||
if status not in VALID_STATUS:
|
||||
raise ValueError(f"非法迁移状态:{key}={status}")
|
||||
lock["skills"][key] = {
|
||||
**current,
|
||||
"sourcePathHash": path_hash,
|
||||
"sourceSha256": skill["sha256"],
|
||||
"status": status,
|
||||
}
|
||||
return lock
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(description="更新 Skill 迁移台账")
|
||||
parser.add_argument("--lock", required=True, type=Path)
|
||||
parser.add_argument("--report", required=True, type=Path)
|
||||
parser.add_argument("--apply", action="store_true", help="确认写入台账")
|
||||
args = parser.parse_args()
|
||||
lock = json.loads(args.lock.read_text(encoding="utf-8"))
|
||||
report = json.loads(args.report.read_text(encoding="utf-8"))
|
||||
content = json.dumps(merge(lock, report), ensure_ascii=False, indent=2) + "\n"
|
||||
if args.apply:
|
||||
temporary = args.lock.with_suffix(args.lock.suffix + ".tmp")
|
||||
temporary.write_text(content, encoding="utf-8")
|
||||
temporary.replace(args.lock)
|
||||
else:
|
||||
print(content, end="")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,538 +0,0 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"updatedAt": "2026-08-26",
|
||||
"sources": {
|
||||
"source-a": {
|
||||
"commit": "31883f7e81c2bdb19505e591ba9db8a3d9fd4352",
|
||||
"skillCount": 12
|
||||
},
|
||||
"source-b": {
|
||||
"commit": "2947a163538cd119a4e241c9d36f061d6dcae841",
|
||||
"skillCount": 52
|
||||
}
|
||||
},
|
||||
"skills": {
|
||||
"source-a:2c317f4ba8859f5e": {
|
||||
"sourcePathHash": "2c317f4ba8859f5e210c18e69e99e8e472d38d97e193c5f213508d4afb672c11",
|
||||
"sourceSha256": "ed08a64bf0f5004d43a9c09a40087aebec8f52323c5a47d8fc73f9f9aca9be0e",
|
||||
"status": "migrated",
|
||||
"target": "plugins/dev/skills/review-code",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-26"
|
||||
},
|
||||
"source-a:1b7843684955ce5a": {
|
||||
"sourcePathHash": "1b7843684955ce5a0beb3ef16c6e751c5e9eb5a17409084fed806b74ec0c522f",
|
||||
"sourceSha256": "eabf9fabba7b751a0b85547b141d92821f461e8d904f4fb15d5746eca1965769",
|
||||
"status": "migrated",
|
||||
"target": "plugins/dev/skills/plan-change",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-a:5d76364c580248a5": {
|
||||
"sourcePathHash": "5d76364c580248a54449e5ec7ede0079f19df21fef95922d3538fb82c095b181",
|
||||
"sourceSha256": "9a664d17f276b01311f661aa6e8fd40063708550c97cc3340246922194d8390b",
|
||||
"status": "migrated",
|
||||
"target": "plugins/dev/skills/implement-backend",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-26"
|
||||
},
|
||||
"source-a:a0b791b6dac96b81": {
|
||||
"sourcePathHash": "a0b791b6dac96b8180df558278b5c7ef643b4806cc4e534ffe6395b9236666d3",
|
||||
"sourceSha256": "603b4fd6e4b52c9b5d368c5ba6bdff333d32f3e03e9b5393686b0729eb4ffc7c",
|
||||
"status": "migrated",
|
||||
"target": "plugins/dev/skills/design-backend",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-a:0124493991019160": {
|
||||
"sourcePathHash": "0124493991019160a06c65d6200db0a50abb212a79bcefab4be4631be85c07c8",
|
||||
"sourceSha256": "eca051fb929c5bd74c34564631872c2d6755b4427a7c4fbb4d6240eeb6331ee3",
|
||||
"status": "migrated",
|
||||
"target": "plugins/dev/skills/prepare-api",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-a:b80c5913e146321c": {
|
||||
"sourcePathHash": "b80c5913e146321ca5efef5e45f11172e79c542855c2ae65478fe253414e66ea",
|
||||
"sourceSha256": "5e33d979bb08fdcc47b2dee2e0d5cb39c24825b391f8bbf5606e57cbd4c2ef2c",
|
||||
"status": "migrated",
|
||||
"target": "plugins/dev/skills/implement-frontend",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-26"
|
||||
},
|
||||
"source-a:cd36505dd718e889": {
|
||||
"sourcePathHash": "cd36505dd718e88966ad74421c65e6c7cccd71a1436f2843eb8cfa7a4f1534c5",
|
||||
"sourceSha256": "a0137bd615988c49a8967b4e0129618858268b90391ab2ed912cc72f338f41f8",
|
||||
"status": "migrated",
|
||||
"target": "plugins/dev/skills/design-frontend",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-a:e14c1a3cd3b041f6": {
|
||||
"sourcePathHash": "e14c1a3cd3b041f650d71eb5701c71c0de76cb7a909e9a419f1d277159cd763a",
|
||||
"sourceSha256": "7780de4d979a6bafd1f5f503f08261858907f110acddb630dfab36d32e54c6a8",
|
||||
"status": "superseded",
|
||||
"target": "official:skill-creator",
|
||||
"reason": "Codex 官方 skill-creator 已覆盖通用 Skill 创建与更新能力",
|
||||
"reviewedAt": "2026-08-26"
|
||||
},
|
||||
"source-a:fdde0da43c1ec4c7": {
|
||||
"sourcePathHash": "fdde0da43c1ec4c7fddad96b9172435af6be96ceafa2cc824f70e04a3cf11085",
|
||||
"sourceSha256": "46a02dbff9c3fff57a0802853e2424983927f53c7f1cc3d8a42542403e62a161",
|
||||
"status": "migrated",
|
||||
"target": "plugins/doc/skills/docx-to-md",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-a:4efb6f9dd0f39dff": {
|
||||
"sourcePathHash": "4efb6f9dd0f39dff13339e62ff24b672552efcbcedb007e9ea86fe41950adbb0",
|
||||
"sourceSha256": "a914823bdf50d9e5c8ee70d6363c5c0e7aea341ed390587a9285c70a7047558e",
|
||||
"status": "migrated",
|
||||
"target": "plugins/doc/skills/xlsx-to-md",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-a:32e7cfc21d252985": {
|
||||
"sourcePathHash": "32e7cfc21d25298559bffbe7f0918f0f6e7d2aac29e3eca39d1f43d8226cf934",
|
||||
"sourceSha256": "0f0486e3f25279a1a1cb8cecfef4dc01830471b5d31b52a9d17a425919997bc2",
|
||||
"status": "excluded",
|
||||
"reason": "CraftKit 原生面向 Codex,不需要 Claude Code 到 Codex 的平台转换能力",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-a:bc91b57fa2a50049": {
|
||||
"sourcePathHash": "bc91b57fa2a500498b31b0f1a87dfa8ab83c32e4b361b4ea1614ea6721234b7c",
|
||||
"sourceSha256": "1436c7e25325c927d55d1dfc2a3117ec8e30845d66e06d2e6d7cc75abe4e0792",
|
||||
"status": "excluded",
|
||||
"reason": "CraftKit 仅面向 Codex,不增加 Cursor 平台转换能力",
|
||||
"reviewedAt": "2026-08-26"
|
||||
},
|
||||
"source-b:3fb4282b0b034d52": {
|
||||
"sourcePathHash": "3fb4282b0b034d5286bccd9924c37bedbe857c4673798aa844f540fe0ee5186a",
|
||||
"sourceSha256": "196cd701c67d06fce4ee3b9894cbed95e6bc9101cc2089f83ae8f35b61a11332",
|
||||
"status": "migrated",
|
||||
"target": "plugins/git/skills/release",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-26"
|
||||
},
|
||||
"source-b:0dedfcd01cd89e28": {
|
||||
"sourcePathHash": "0dedfcd01cd89e28e83d841f78c270b1210399cc867fd3e1865c14acf1ea865a",
|
||||
"sourceSha256": "be6a694d4de9b8a792e19e1ed116e2fdd54d91731d9efcadfca1b0055a4a3145",
|
||||
"status": "superseded",
|
||||
"target": "plugins/dev/skills/implement-backend",
|
||||
"targetVersion": "0.1.0",
|
||||
"reason": "后端实现能力已与另一来源合并并按项目证据中性重建",
|
||||
"reviewedAt": "2026-08-26"
|
||||
},
|
||||
"source-b:3f05784a0a86ba5f": {
|
||||
"sourcePathHash": "3f05784a0a86ba5fb8f268797ca1ceabe8ca237b3c9d3c4396e622c1ef421cc6",
|
||||
"sourceSha256": "9a39cd7af138519fe3de3f7a3cb031ea5da1243ff5779504a13215fa03a5a3c2",
|
||||
"status": "superseded",
|
||||
"target": "plugins/dev/skills/design-backend",
|
||||
"targetVersion": "0.1.0",
|
||||
"reason": "后端设计能力已与另一来源合并并按项目证据中性重建",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-b:41934e94a1922a1b": {
|
||||
"sourcePathHash": "41934e94a1922a1bbccec4377246e67bd84f1ffbd2b9d1bf4027c1ed15d12260",
|
||||
"sourceSha256": "a0db48d88dab0537e061146edf6dbdeb4b7f8a935febd1556f798ef234b29e5b",
|
||||
"status": "migrated",
|
||||
"target": "plugins/dev/skills/test-backend",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-26"
|
||||
},
|
||||
"source-b:0cfb12fd60357a34": {
|
||||
"sourcePathHash": "0cfb12fd60357a346c8e0079536540fba81e406d58205098f1a5162c6ce7e9d1",
|
||||
"sourceSha256": "aa722e0dbcb613748b75bc2f5c81b8a97cbff07905b1fcee6d58cb176135fc08",
|
||||
"status": "superseded",
|
||||
"target": "plugins/dev/skills/review-code",
|
||||
"targetVersion": "0.1.0",
|
||||
"reason": "代码检查能力已合并到统一代码审查入口",
|
||||
"reviewedAt": "2026-08-26"
|
||||
},
|
||||
"source-b:f171b05e239c2e2c": {
|
||||
"sourcePathHash": "f171b05e239c2e2c5f2a0c636dfac0c2456b9d3b5215fdaa7fb86a33be1ee188",
|
||||
"sourceSha256": "cd16d17204009509e6798badab786b9bd4d3969117b3ad4b9005337b76a4791b",
|
||||
"status": "superseded",
|
||||
"target": "plugins/dev/skills/plan-change",
|
||||
"targetVersion": "0.1.0",
|
||||
"reason": "开发计划能力已与另一来源合并为通用变更计划",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-b:3b29e4441f642e65": {
|
||||
"sourcePathHash": "3b29e4441f642e65d442fd284f37a45364cebb7a6c53446c354d15c70e532410",
|
||||
"sourceSha256": "d2689d3ac45070389473cb8cc414df44e82ad267915d8cd7c53c023f5b8f3696",
|
||||
"status": "superseded",
|
||||
"target": "plugins/dev/skills/implement-frontend",
|
||||
"targetVersion": "0.1.0",
|
||||
"reason": "前端实现能力已与另一来源合并并按项目证据中性重建",
|
||||
"reviewedAt": "2026-08-26"
|
||||
},
|
||||
"source-b:f6ec7bd5501e6ea5": {
|
||||
"sourcePathHash": "f6ec7bd5501e6ea5f6e907a586a8d7cbe5fbbeebd3e5c8efead9b250742a148e",
|
||||
"sourceSha256": "25905b3b294b0be2e245099acb1a557793215f157b96b9e964e78170838652f0",
|
||||
"status": "migrated",
|
||||
"target": "plugins/dev/skills/component",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-b:c49d1db42acd7220": {
|
||||
"sourcePathHash": "c49d1db42acd722071d61420be58ba8ccbc54f5370bdf951abfb5981914271cf",
|
||||
"sourceSha256": "20875df87fb84c7d5830d6eaaff544c9e32e3f9a2359ed099de5f3a4a36eaa7d",
|
||||
"status": "superseded",
|
||||
"target": "plugins/dev/skills/design-frontend",
|
||||
"targetVersion": "0.1.0",
|
||||
"reason": "前端设计能力已与另一来源合并并移除内部组件与固定版本约束",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-b:9a3f3d3c43d9017a": {
|
||||
"sourcePathHash": "9a3f3d3c43d9017a080a9832df5b975e6ddd3f8c39947ee768aeb973fc23974e",
|
||||
"sourceSha256": "47c072e792d1cf80ddcc69536236ccb525d21e7d5408ed41cca55483556e8acb",
|
||||
"status": "superseded",
|
||||
"target": "plugins/dev/skills",
|
||||
"reason": "前端导航能力已由 component、style、form 的精确触发描述和 Codex 自动发现替代",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-b:eb730c56bc7a4a15": {
|
||||
"sourcePathHash": "eb730c56bc7a4a158ddec74c7497a10fdea2d0b628783b968e3ee9ee4572b15c",
|
||||
"sourceSha256": "89aa46526fa7531958df46be4b162a9f7b9ea597e3e9121991cf25e9f25158f5",
|
||||
"status": "migrated",
|
||||
"target": "plugins/skill/skills/guidance",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-b:422174b0c00bbd65": {
|
||||
"sourcePathHash": "422174b0c00bbd657f4c08415d4a722584556cfa5f3edc997b11e8ab0ef8656a",
|
||||
"sourceSha256": "017a4ca0b7648ed91003deeb97a3757e8f17acd6963c6019140389a907f1345a",
|
||||
"status": "migrated",
|
||||
"target": "plugins/dev/skills/style",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-b:742ba3611bee4e34": {
|
||||
"sourcePathHash": "742ba3611bee4e34dfee6dadbe192dd8be677c4b9f49108e2f04d9e22dc8801f",
|
||||
"sourceSha256": "7582e333966b45ee2d145601831449d75c4f3159670c31df25e5d18e6a357bbe",
|
||||
"status": "migrated",
|
||||
"target": "plugins/dev/skills/test-ui",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-26"
|
||||
},
|
||||
"source-b:d6d4166800584a61": {
|
||||
"sourcePathHash": "d6d4166800584a61ad6cbf96af57bb8ee269a16babba753f267b48efd66f6d2d",
|
||||
"sourceSha256": "60f8708db24f368ecec55bd3f326683fac60bd6776ac69e0fafaf4c77333e703",
|
||||
"status": "migrated",
|
||||
"target": "plugins/doc/skills/docx-to-md",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-b:023767d9c7be6295": {
|
||||
"sourcePathHash": "023767d9c7be62956d12fd01c94ac676b9fe6719741acd6f412c8b446efa2760",
|
||||
"sourceSha256": "ba579f8d6a62b4745d8d3922b33e3c20974d8081ae4d1c87727d1a9e4b609945",
|
||||
"status": "migrated",
|
||||
"target": "plugins/doc/skills/format-md",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-b:b127c47139270a7f": {
|
||||
"sourcePathHash": "b127c47139270a7f9157e18ad6a0c975b99caf07b9a0874daeac86d9a99ce48c",
|
||||
"sourceSha256": "0214b80071f07beaff4f5837b983546ff71dbaa65bc29e34a5a23c9d946b683b",
|
||||
"status": "migrated",
|
||||
"target": "plugins/doc/skills/md-to-docx",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-b:34ab291ce3cfed2e": {
|
||||
"sourcePathHash": "34ab291ce3cfed2e69cc6f08309b1a41142be91235b9a573daf98639b4a001cc",
|
||||
"sourceSha256": "239d7efb1f9a53fc1b40f367954a6f6eaaf9d7a56cdf712128dcf393dc5a5067",
|
||||
"status": "migrated",
|
||||
"target": "plugins/dev/skills/design-api",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-26"
|
||||
},
|
||||
"source-b:3c8596a5d95de214": {
|
||||
"sourcePathHash": "3c8596a5d95de214d381b2f04898dd7042a266aa7889569981a97a1cf50045d1",
|
||||
"sourceSha256": "cc19258fcf63018ce2dac4d7253e23fbfb71596ee27235871ad78aae743b57e6",
|
||||
"status": "migrated",
|
||||
"target": "plugins/dev/skills/design-db",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-26"
|
||||
},
|
||||
"source-b:a388287911bc39cb": {
|
||||
"sourcePathHash": "a388287911bc39cb3f88824044426782df3c3e6450c4db9e4948c28a47dbf9f1",
|
||||
"sourceSha256": "20e13c3458f6af8d0b131f650f573eb824978438b52475a2f480a67c2f846cd6",
|
||||
"status": "superseded",
|
||||
"target": "plugins/skill/skills/guidance",
|
||||
"targetVersion": "0.1.0",
|
||||
"reason": "框架约定改由通用规范检索结合项目真实依赖解析",
|
||||
"reviewedAt": "2026-08-26"
|
||||
},
|
||||
"source-b:ca08ee8839bccc15": {
|
||||
"sourcePathHash": "ca08ee8839bccc1504c253cdb9bfc09803ddf77f948605f8563d04e0466a2ce7",
|
||||
"sourceSha256": "0086c8da048d94303e9d5765b91b7eff9a10a798ffa73de9f245be5422cf3255",
|
||||
"status": "superseded",
|
||||
"target": "plugins/dev/skills/component",
|
||||
"targetVersion": "0.1.0",
|
||||
"reason": "组件约定与契约查证能力已合并到 component",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-b:1b4cee54060ef399": {
|
||||
"sourcePathHash": "1b4cee54060ef3995d6c98e99dee3c3200ab2e90dd62136cef07b9b09e31364d",
|
||||
"sourceSha256": "24df169fbb18f39be5ec4046cc8d33535b1b86d2114673ee35d1a2a0324c1b25",
|
||||
"status": "migrated",
|
||||
"target": "plugins/dev/skills/review-frontend",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-26"
|
||||
},
|
||||
"source-b:7b7552c8c6e1b5f5": {
|
||||
"sourcePathHash": "7b7552c8c6e1b5f56a283db304272da8cd63210aaf7327231a7b26f3cf903082",
|
||||
"sourceSha256": "9c373fe6bb955d4431e92bba66239cb707a6179082a624b74bc77fa36663fc61",
|
||||
"status": "migrated",
|
||||
"target": "plugins/dev/skills/design-frontend-data",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-26"
|
||||
},
|
||||
"source-b:5f525e6aeda55dd8": {
|
||||
"sourcePathHash": "5f525e6aeda55dd81c26d38cf59097cb52abbcfc5b05e35fe7e8101a1a3353b5",
|
||||
"sourceSha256": "8068a6137951e94a01bc68cf9011db69f3d759304a3167291afa4c238531e34a",
|
||||
"status": "migrated",
|
||||
"target": "plugins/dev/skills/form",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-b:f2079362cf82e719": {
|
||||
"sourcePathHash": "f2079362cf82e719e2dde6098c55ce984709a97446a7f66113f8b5f317f1f55b",
|
||||
"sourceSha256": "f57f3c0d5175c3c1700b74e8489d820eed4ef36d10e79ab14e096cb2a20a0cec",
|
||||
"status": "migrated",
|
||||
"target": "plugins/dev/skills/review-java",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-26"
|
||||
},
|
||||
"source-b:b78122ad4813e9ba": {
|
||||
"sourcePathHash": "b78122ad4813e9baef0ee5281bddb910b01fd89bdbbd2753011ac3deb52a8ce5",
|
||||
"sourceSha256": "c06d7eb2674dcbb4bad01a8c65c6d372dffd95c585a16ab2c3f1bba19df199e0",
|
||||
"status": "superseded",
|
||||
"target": "plugins/skill/skills/guidance",
|
||||
"targetVersion": "0.1.0",
|
||||
"reason": "框架知识查询改由通用规范检索与项目源码证据完成",
|
||||
"reviewedAt": "2026-08-26"
|
||||
},
|
||||
"source-b:7fd143975b0071c3": {
|
||||
"sourcePathHash": "7fd143975b0071c3efa271a9ad19c3d7e422f64d3e23aa08d7a091c805cb9467",
|
||||
"sourceSha256": "33582dcda068247a5c56238134dad308d1f66b03abbfdc7bc282a9ac9ff918a2",
|
||||
"status": "migrated",
|
||||
"target": "plugins/dev/skills/review-mybatis",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-26"
|
||||
},
|
||||
"source-b:affd0805467646c1": {
|
||||
"sourcePathHash": "affd0805467646c1fcb4c196776e9cb610fcec721e1a44df3bc02f5c08b84aeb",
|
||||
"sourceSha256": "c7f565da3a1f412d3f15642fc9ad44733adee73c4d13cdebffaff1de4ca5652c",
|
||||
"status": "migrated",
|
||||
"target": "plugins/dev/skills/design-workflow",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-26"
|
||||
},
|
||||
"source-b:2a64acb63e8b2030": {
|
||||
"sourcePathHash": "2a64acb63e8b203031c4ef292f957c0fe0d3722e079dc9a299730015b9e3359c",
|
||||
"sourceSha256": "580da97b2fb16543db9aef62359f153fe5aca382d88987f10f233289bc02790d",
|
||||
"status": "migrated",
|
||||
"target": "plugins/git/skills/commit-msg",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-b:3a5d583c511959b3": {
|
||||
"sourcePathHash": "3a5d583c511959b3d1934d15eaa9b0cd0590c558535b6a8307f870d7ce0c8dd0",
|
||||
"sourceSha256": "6b69964b6e65ddc6eefa857fa1016587d3b2d2fac22d2bda4196762233fb025b",
|
||||
"status": "migrated",
|
||||
"target": "plugins/git/skills/branch",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-b:13bb77c66fee0964": {
|
||||
"sourcePathHash": "13bb77c66fee09641fe61781ffbba4c51ed47b14ce225972ea35219e489405a3",
|
||||
"sourceSha256": "abe529dcc85b1ac88791c95cf7be12cf5b1f545988b515f10edb55f0a8c94fb1",
|
||||
"status": "migrated",
|
||||
"target": "plugins/git/skills/export",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-b:fd03e996181699d9": {
|
||||
"sourcePathHash": "fd03e996181699d95a09c1940f685ac366daeeda1aa901175d26dcf153f755fb",
|
||||
"sourceSha256": "b4ef1f7847dd9081fdacaecae8853b2946e22c899b08bbe48ef280d21546e044",
|
||||
"status": "migrated",
|
||||
"target": "plugins/git/skills/identity",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-b:4ca0940d73b4b626": {
|
||||
"sourcePathHash": "4ca0940d73b4b6264a37e1a344d669367dc313364a0077abf8bcaf97cfed42a1",
|
||||
"sourceSha256": "92b3cea563f544806493245bdf099e2357112ccbce15007593c94d62c26c258c",
|
||||
"status": "migrated",
|
||||
"target": "plugins/git/skills/integrate",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-b:0b917cc63232dff3": {
|
||||
"sourcePathHash": "0b917cc63232dff38c375d3bec3fabe57390201c34c3ce96f7885eb23bca91d7",
|
||||
"sourceSha256": "5ecfa8040f5d71f347cfcfb89040a5cbfdb96f71867fb11b750b78d4aa17d66a",
|
||||
"status": "migrated",
|
||||
"target": "plugins/knowledge/skills/init",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-b:905e74ea51281da1": {
|
||||
"sourcePathHash": "905e74ea51281da179c1eb31677af71569a95139a74fb139d39dadd52db2ce62",
|
||||
"sourceSha256": "cfc1eb3fafb15dc51b730dd36d3ad507b5ae415d5f1a5da5138471170afdde38",
|
||||
"status": "migrated",
|
||||
"target": "plugins/knowledge/skills/trace",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-b:274c4aac900a23c3": {
|
||||
"sourcePathHash": "274c4aac900a23c3ca0506807c4df8e09c95e21b84fd633951bae146f6c41028",
|
||||
"sourceSha256": "b4beacdc745cd06ee4be20694d60bae0c9c6122fb61b917b12b66451497651e9",
|
||||
"status": "migrated",
|
||||
"target": "plugins/knowledge/skills/lessons",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-b:6e1a4d182b2e41fd": {
|
||||
"sourcePathHash": "6e1a4d182b2e41fddd28051c20d7170821a87b518e49684cc4f12b731789831d",
|
||||
"sourceSha256": "cf106df97100aabf260db7c8d45c2d6d499c643b4898d7e46c98852a90b7134d",
|
||||
"status": "superseded",
|
||||
"target": "plugins/knowledge/skills/lessons",
|
||||
"targetVersion": "0.1.0",
|
||||
"reason": "经验提升能力已合并到 lessons 的 promote 模式",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-b:cd4c15d66d5cfba0": {
|
||||
"sourcePathHash": "cd4c15d66d5cfba0c568b6f3ac4ceac9a7cea797eca8c6bf5eab81187e70f7d7",
|
||||
"sourceSha256": "a9b109dc659e8e65645b6507ab2a39a04598d0c0ed63feaef0985765d3ff9f3f",
|
||||
"status": "superseded",
|
||||
"target": "plugins/knowledge/skills/lessons",
|
||||
"targetVersion": "0.1.0",
|
||||
"reason": "经验回扫能力已合并到 lessons 的 audit 模式",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-b:a6062c4036828615": {
|
||||
"sourcePathHash": "a6062c4036828615945db311cf68c2ac886feef91c79b53d882bbe41fd71143f",
|
||||
"sourceSha256": "94b7e58d4c4903498cf29365fe466aaba8bfdf4675754f65cd30bad37c99e02f",
|
||||
"status": "migrated",
|
||||
"target": "plugins/knowledge/skills/distill",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-b:f58c6cd52bc983e8": {
|
||||
"sourcePathHash": "f58c6cd52bc983e87d265308ade0da8d89bd74d5d4f1e96fc463ef299a9fe94a",
|
||||
"sourceSha256": "98392eb0fe65dab6877495e6863a6722cd2777f5767dfd95b3a829ed7798a5e7",
|
||||
"status": "migrated",
|
||||
"target": "plugins/knowledge/skills/handoff",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-b:258ee10299925494": {
|
||||
"sourcePathHash": "258ee1029992549420c8465c8de2d63c1bfaf9334b812d6b79a07a9823b49733",
|
||||
"sourceSha256": "b4958d4aee3c06b778273d87a07dd423cf15fc8fbfdde27e00552ff60138795e",
|
||||
"status": "migrated",
|
||||
"target": "plugins/dev/skills/analyze-bugs",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-26"
|
||||
},
|
||||
"source-b:52592d4a59314c74": {
|
||||
"sourcePathHash": "52592d4a59314c74de9b58cfb4cda6e9f5d9514bb05c9b586044c12754982d52",
|
||||
"sourceSha256": "e8be1b2c17ab3aaccbb5559a07b64da8a7c718293e83cb8dd685c87708c7cbdc",
|
||||
"status": "migrated",
|
||||
"target": "plugins/dev/skills/upgrade",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-26"
|
||||
},
|
||||
"source-b:f478193705d1d02d": {
|
||||
"sourcePathHash": "f478193705d1d02d6bb6375728dc10d34487e3f67ab8d164a80104f6a71fccdc",
|
||||
"sourceSha256": "218eb591d1944b2280853bbf39cb028f9a41e55dee01218838b14f87755fad72",
|
||||
"status": "superseded",
|
||||
"target": "official:browser-computer-use",
|
||||
"reason": "Codex 浏览器与计算机操作能力已覆盖宿主浏览器代理配置",
|
||||
"reviewedAt": "2026-08-26"
|
||||
},
|
||||
"source-b:e4b14f4b2719e28b": {
|
||||
"sourcePathHash": "e4b14f4b2719e28b409bc66980b3698588684dde81a0c627e862262e76c34b2f",
|
||||
"sourceSha256": "de185022a0cf8bfce340709f47052578ec761664c96723172c48bdd4f10e71f1",
|
||||
"status": "superseded",
|
||||
"target": "plugins/dev/skills/review-code",
|
||||
"targetVersion": "0.1.0",
|
||||
"reason": "分支、提交与目录审查已合并到统一代码审查入口",
|
||||
"reviewedAt": "2026-08-26"
|
||||
},
|
||||
"source-b:aa42f7c1a045bb49": {
|
||||
"sourcePathHash": "aa42f7c1a045bb496bbc9e62beb7a7b74544153ed9551492f5b801ca4c9df098",
|
||||
"sourceSha256": "aff6fad01afa2a15756a36d210c67b229a1eb2155981292450f0487c3005125d",
|
||||
"status": "migrated",
|
||||
"target": "plugins/knowledge/skills/worklog",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-b:3763e17cff825df6": {
|
||||
"sourcePathHash": "3763e17cff825df6920f57d84736093082014f2a0316d9e84ee18ac8078ff6e5",
|
||||
"sourceSha256": "bd2e4ae7f8a9bded1f7a983289fb49556f30cd5d6c6382500dd8c464fdd66e02",
|
||||
"status": "migrated",
|
||||
"target": "plugins/doc/skills/archive",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-b:9e3e75840a46af96": {
|
||||
"sourcePathHash": "9e3e75840a46af96c33a1885f192813239b511eb972a4962b30b76de7392c88c",
|
||||
"sourceSha256": "379c41e41d833880653ce065a63380e9cf29d2b7663f7ee91a3d77594202d042",
|
||||
"status": "superseded",
|
||||
"target": "plugins/dev/skills/upgrade",
|
||||
"targetVersion": "0.1.0",
|
||||
"reason": "前后端升级合并为按真实版本与官方迁移资料执行的统一能力",
|
||||
"reviewedAt": "2026-08-26"
|
||||
},
|
||||
"source-b:766516f82e8e9be3": {
|
||||
"sourcePathHash": "766516f82e8e9be32e1ff3f29123202b6bad85bf9a88e36f87f256446ea31eaf",
|
||||
"sourceSha256": "c66ca1651923b20cd62395ba2cc6b8532093d5df10f420c1673a103a88dbf5aa",
|
||||
"status": "migrated",
|
||||
"target": "plugins/doc/skills/message",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-26"
|
||||
},
|
||||
"source-b:31dec2fa162b06d3": {
|
||||
"sourcePathHash": "31dec2fa162b06d379aa676d426d2de01c3b082061ff15adb7a8c721cd5635af",
|
||||
"sourceSha256": "a146d79ccfec7b1f9275cda8e6cf3ab1190430d0c3bc11886a722ce1d6fabc90",
|
||||
"status": "migrated",
|
||||
"target": "plugins/skill/skills/guidance-edit",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-b:988b200efd0b8be0": {
|
||||
"sourcePathHash": "988b200efd0b8be024060e0785da2f864bf7ee30d7c7b434fde7ab1e4cdcc9d8",
|
||||
"sourceSha256": "e7fa073d592167c07b06698d664192baafb126afa1a6bfdc50a056e1ea13e56f",
|
||||
"status": "excluded",
|
||||
"reason": "CraftKit 原生面向 Codex,不需要 Claude Code 到 Codex 的平台转换能力",
|
||||
"reviewedAt": "2026-08-25"
|
||||
},
|
||||
"source-b:8a7cdf719d8f8a3e": {
|
||||
"sourcePathHash": "8a7cdf719d8f8a3e0200781a82062cc5a839e4d2c2fd400982771968245d62dd",
|
||||
"sourceSha256": "3461485ba35dceffc5fc0e9266793003a0355d412aa8a609c93709745226d00a",
|
||||
"status": "migrated",
|
||||
"target": "plugins/dev/skills/estimate",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-26"
|
||||
},
|
||||
"source-b:6e5eb2b9ab9273cf": {
|
||||
"sourcePathHash": "6e5eb2b9ab9273cf889bd908ff446eda59cc3e121ee7a1861fb2664d7fa049e9",
|
||||
"sourceSha256": "31eef261e6e3e930cd88b18c938176c3ef1d3e8d039986712ee6c3191481872d",
|
||||
"status": "migrated",
|
||||
"target": "plugins/doc/skills/report",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-26"
|
||||
},
|
||||
"source-b:a985b2c0fb927117": {
|
||||
"sourcePathHash": "a985b2c0fb9271174d9d46425eb6792d2483ebcd6da89ecc1cbfb61407259499",
|
||||
"sourceSha256": "e2f92df8dc489e79bfdd74de8817abf742f425422765c76c4a46263d1fbd7a9e",
|
||||
"status": "migrated",
|
||||
"target": "plugins/doc/skills/requirements",
|
||||
"targetVersion": "0.1.0",
|
||||
"reviewedAt": "2026-08-26"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
"""开发分析与设计批次的职责边界测试。"""
|
||||
|
||||
from pathlib import Path
|
||||
import unittest
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
SKILLS = ROOT / "plugins" / "dev" / "skills"
|
||||
|
||||
|
||||
def read_skill(name: str) -> str:
|
||||
"""合并读取 Skill 入口及引用文件。"""
|
||||
folder = SKILLS / name
|
||||
files = [folder / "SKILL.md", *sorted((folder / "references").glob("*.md"))]
|
||||
return "\n".join(path.read_text(encoding="utf-8") for path in files)
|
||||
|
||||
|
||||
class DevDesignBatchTest(unittest.TestCase):
|
||||
"""验证四个 Skill 的通用化设计和相互边界。"""
|
||||
|
||||
def test_plan_is_evidence_based_and_does_not_implement(self) -> None:
|
||||
content = read_skill("plan-change")
|
||||
self.assertIn("不执行设计或编码", content)
|
||||
self.assertIn("验收标准", content)
|
||||
self.assertIn("运行行为标为待验证", content)
|
||||
self.assertNotIn("docs/{moduleCode}", content)
|
||||
|
||||
def test_backend_design_uses_project_version(self) -> None:
|
||||
content = read_skill("design-backend")
|
||||
self.assertIn("精确版本", content)
|
||||
self.assertIn("guidance", content)
|
||||
self.assertIn("事务边界", content)
|
||||
self.assertIn("不生成业务代码", content)
|
||||
|
||||
def test_frontend_design_composes_existing_helpers(self) -> None:
|
||||
content = read_skill("design-frontend")
|
||||
for helper in ("component", "style", "form", "prepare-api"):
|
||||
self.assertIn(helper, content)
|
||||
self.assertIn("不编造组件", content)
|
||||
self.assertIn("不跨版本混用", content)
|
||||
|
||||
def test_prepare_api_does_not_assume_contract(self) -> None:
|
||||
content = read_skill("prepare-api")
|
||||
self.assertIn("不预设请求客户端", content)
|
||||
self.assertIn("未匹配字段", content)
|
||||
self.assertIn("不发起真实请求", content)
|
||||
self.assertIn("不能反向覆盖", content)
|
||||
|
||||
def test_descriptions_are_distinct(self) -> None:
|
||||
descriptions = []
|
||||
for name in ("plan-change", "design-backend", "design-frontend", "prepare-api"):
|
||||
text = (SKILLS / name / "SKILL.md").read_text(encoding="utf-8")
|
||||
descriptions.append(text.split("---", 2)[1])
|
||||
self.assertEqual(4, len(set(descriptions)))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -1,78 +0,0 @@
|
||||
"""验证文档批次三个独立实现的核心行为和安全边界。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import subprocess
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
from docx import Document
|
||||
from openpyxl import Workbook
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
MD_SCRIPT = ROOT / "plugins/doc/skills/md-to-docx/scripts/convert.py"
|
||||
XLSX_SCRIPT = ROOT / "plugins/doc/skills/xlsx-to-md/scripts/convert.py"
|
||||
ARCHIVE_SCRIPT = ROOT / "plugins/doc/skills/archive/scripts/archive.py"
|
||||
|
||||
|
||||
class DocumentBatchTests(unittest.TestCase):
|
||||
"""使用临时目录执行真实转换,不依赖仓库外测试材料。"""
|
||||
|
||||
def run_script(self, script: Path, *args: object) -> subprocess.CompletedProcess[str]:
|
||||
"""使用当前受控 Python 运行时执行目标脚本。"""
|
||||
|
||||
return subprocess.run(
|
||||
[str(Path(__import__("sys").executable)), str(script), *(str(value) for value in args)],
|
||||
capture_output=True, text=True, encoding="utf-8", check=False,
|
||||
)
|
||||
|
||||
def test_markdown_to_docx_preserves_common_blocks(self) -> None:
|
||||
"""标题、列表、表格和代码块应生成可重新打开的 DOCX。"""
|
||||
|
||||
with tempfile.TemporaryDirectory() as temp:
|
||||
folder = Path(temp); source = folder / "sample.md"; output = folder / "sample.docx"
|
||||
source.write_text("# 标题\n\n- 项目\n\n| 名称 | 值 |\n| --- | --- |\n| A | 1 |\n\n```py\nprint('ok')\n```\n", encoding="utf-8")
|
||||
result = self.run_script(MD_SCRIPT, source)
|
||||
self.assertEqual(0, result.returncode, result.stderr)
|
||||
document = Document(output)
|
||||
self.assertEqual("标题", document.paragraphs[0].text)
|
||||
self.assertEqual(1, len(document.tables))
|
||||
self.assertNotEqual(0, self.run_script(MD_SCRIPT, source).returncode)
|
||||
|
||||
def test_xlsx_to_markdown_handles_merges_and_escaping(self) -> None:
|
||||
"""合并区域应填充值,表格特殊字符应安全转义。"""
|
||||
|
||||
with tempfile.TemporaryDirectory() as temp:
|
||||
folder = Path(temp); source = folder / "sample.xlsx"
|
||||
workbook = Workbook(); sheet = workbook.active; sheet.title = "数据"
|
||||
sheet.append(["名称", "值"]); sheet.append(["A|B", "=1+1"])
|
||||
sheet.merge_cells("A3:B3"); sheet["A3"] = "合并"
|
||||
workbook.create_sheet("空表"); workbook.save(source)
|
||||
result = self.run_script(XLSX_SCRIPT, source)
|
||||
self.assertEqual(0, result.returncode, result.stderr)
|
||||
markdown = source.with_suffix(".md").read_text(encoding="utf-8")
|
||||
self.assertIn(r"A\|B", markdown)
|
||||
self.assertIn("| 合并 | 合并 |", markdown)
|
||||
self.assertIn("_空工作表_", markdown)
|
||||
|
||||
def test_archive_is_dry_run_first_and_keeps_source(self) -> None:
|
||||
"""预演不得写目标,执行后仍须保留来源并只抽取指定章节。"""
|
||||
|
||||
with tempfile.TemporaryDirectory() as temp:
|
||||
root = Path(temp); source = root / "specs/api.md"; source.parent.mkdir()
|
||||
source.write_text("---\nowner: team\n---\n# 概述\n正文\n## API\n接口\n## 其他\n忽略\n", encoding="utf-8")
|
||||
config = root / "rules.json"
|
||||
config.write_text(json.dumps({"version": 1, "archiveRoot": "archive", "rules": [{"match": "specs/*.md", "target": "{stem}.md", "section": "API", "stripFrontmatter": True, "requiredText": ["接口"]}]}, ensure_ascii=False), encoding="utf-8")
|
||||
target = root / "archive/api.md"
|
||||
preview = self.run_script(ARCHIVE_SCRIPT, "--root", root, "--config", config)
|
||||
self.assertEqual(0, preview.returncode, preview.stderr); self.assertFalse(target.exists())
|
||||
applied = self.run_script(ARCHIVE_SCRIPT, "--root", root, "--config", config, "--apply")
|
||||
self.assertEqual(0, applied.returncode, applied.stderr)
|
||||
self.assertTrue(source.exists()); self.assertEqual("## API\n接口\n", target.read_text(encoding="utf-8"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -1,117 +0,0 @@
|
||||
import importlib.util
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
SCRIPT = (
|
||||
Path(__file__).parents[2]
|
||||
/ "plugins"
|
||||
/ "doc"
|
||||
/ "skills"
|
||||
/ "docx-to-md"
|
||||
/ "scripts"
|
||||
/ "convert.py"
|
||||
)
|
||||
SPEC = importlib.util.spec_from_file_location("docx_to_md_convert", SCRIPT)
|
||||
MODULE = importlib.util.module_from_spec(SPEC)
|
||||
assert SPEC.loader is not None
|
||||
sys.modules[SPEC.name] = MODULE
|
||||
SPEC.loader.exec_module(MODULE)
|
||||
|
||||
|
||||
class DocxToMarkdownTest(unittest.TestCase):
|
||||
"""验证转换器的核心内容、覆盖保护和输入边界。"""
|
||||
|
||||
def make_docx(self, path: Path) -> None:
|
||||
"""创建只包含公开 OOXML 结构的最小测试文档。"""
|
||||
|
||||
document = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main"
|
||||
xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships"
|
||||
xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
|
||||
<w:body>
|
||||
<w:p><w:pPr><w:pStyle w:val="Heading1"/></w:pPr><w:r><w:t>测试标题</w:t></w:r></w:p>
|
||||
<w:p><w:r><w:rPr><w:b/></w:rPr><w:t>加粗正文</w:t></w:r>
|
||||
<w:hyperlink r:id="rLink"><w:r><w:t>示例链接</w:t></w:r></w:hyperlink></w:p>
|
||||
<w:p><w:pPr><w:numPr><w:ilvl w:val="0"/><w:numId w:val="1"/></w:numPr></w:pPr>
|
||||
<w:r><w:t>列表项目</w:t></w:r></w:p>
|
||||
<w:p><w:r><w:drawing><a:blip r:embed="rImage"/></w:drawing></w:r></w:p>
|
||||
<w:tbl>
|
||||
<w:tr><w:tc><w:p><w:r><w:t>名称</w:t></w:r></w:p></w:tc><w:tc><w:p><w:r><w:t>值</w:t></w:r></w:p></w:tc></w:tr>
|
||||
<w:tr><w:tc><w:p><w:r><w:t>A</w:t></w:r></w:p></w:tc><w:tc><w:p><w:r><w:t>1</w:t></w:r></w:p></w:tc></w:tr>
|
||||
</w:tbl>
|
||||
</w:body>
|
||||
</w:document>"""
|
||||
styles = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<w:styles xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
|
||||
<w:style w:type="paragraph" w:styleId="Heading1"><w:name w:val="heading 1"/></w:style>
|
||||
</w:styles>"""
|
||||
numbering = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<w:numbering xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
|
||||
<w:abstractNum w:abstractNumId="0"><w:lvl w:ilvl="0"><w:numFmt w:val="bullet"/></w:lvl></w:abstractNum>
|
||||
<w:num w:numId="1"><w:abstractNumId w:val="0"/></w:num>
|
||||
</w:numbering>"""
|
||||
relationships = """<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
|
||||
<Relationship Id="rLink" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" Target="https://example.com" TargetMode="External"/>
|
||||
<Relationship Id="rImage" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" Target="media/test.png"/>
|
||||
</Relationships>"""
|
||||
with zipfile.ZipFile(path, "w") as archive:
|
||||
archive.writestr("word/document.xml", document)
|
||||
archive.writestr("word/styles.xml", styles)
|
||||
archive.writestr("word/numbering.xml", numbering)
|
||||
archive.writestr("word/_rels/document.xml.rels", relationships)
|
||||
archive.writestr("word/media/test.png", b"\x89PNG\r\n\x1a\n")
|
||||
archive.writestr("word/comments.xml", "<comments/>")
|
||||
|
||||
def test_convert_common_content_and_report_warning(self) -> None:
|
||||
"""常见结构应转换,无法处理的批注应明确告警。"""
|
||||
|
||||
with tempfile.TemporaryDirectory() as temp:
|
||||
root = Path(temp)
|
||||
source = root / "sample.docx"
|
||||
output = root / "result"
|
||||
self.make_docx(source)
|
||||
|
||||
result = MODULE.DocxConverter(source, output).convert()
|
||||
markdown = result.output_file.read_text(encoding="utf-8")
|
||||
|
||||
self.assertIn("# 测试标题", markdown)
|
||||
self.assertIn("**加粗正文**", markdown)
|
||||
self.assertIn("[示例链接](https://example.com)", markdown)
|
||||
self.assertIn("- 列表项目", markdown)
|
||||
self.assertIn("| 名称 | 值 |", markdown)
|
||||
self.assertIn("
|
||||
self.assertEqual(result.images, 1)
|
||||
self.assertTrue(any("批注" in warning for warning in result.warnings))
|
||||
|
||||
def test_existing_output_requires_force(self) -> None:
|
||||
"""默认不得写入已有输出目录,显式覆盖后才可继续。"""
|
||||
|
||||
with tempfile.TemporaryDirectory() as temp:
|
||||
root = Path(temp)
|
||||
source = root / "sample.docx"
|
||||
output = root / "result"
|
||||
self.make_docx(source)
|
||||
output.mkdir()
|
||||
|
||||
with self.assertRaises(FileExistsError):
|
||||
MODULE.DocxConverter(source, output).convert()
|
||||
|
||||
result = MODULE.DocxConverter(source, output, force=True).convert()
|
||||
self.assertTrue(result.output_file.exists())
|
||||
|
||||
def test_cli_rejects_non_docx(self) -> None:
|
||||
"""命令行入口应拒绝扩展名不正确的文件。"""
|
||||
|
||||
with tempfile.TemporaryDirectory() as temp:
|
||||
source = Path(temp) / "sample.txt"
|
||||
source.write_text("not docx", encoding="utf-8")
|
||||
self.assertEqual(MODULE.main([str(source)]), 2)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -1,51 +0,0 @@
|
||||
"""前端辅助 Skill 的结构与行为边界测试。"""
|
||||
|
||||
from pathlib import Path
|
||||
import unittest
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
DEV_SKILLS = ROOT / "plugins" / "dev" / "skills"
|
||||
|
||||
|
||||
def read_skill(name: str) -> str:
|
||||
"""读取指定 Skill 的入口及引用文档。"""
|
||||
folder = DEV_SKILLS / name
|
||||
files = [folder / "SKILL.md", *sorted((folder / "references").glob("*.md"))]
|
||||
return "\n".join(path.read_text(encoding="utf-8") for path in files)
|
||||
|
||||
|
||||
class FrontendHelpersTest(unittest.TestCase):
|
||||
"""验证三个 Skill 能互补协作且不恢复来源专有规则。"""
|
||||
|
||||
def test_component_requires_project_evidence(self) -> None:
|
||||
content = read_skill("component")
|
||||
self.assertIn(".craftkit/project.json", content)
|
||||
self.assertIn(".craftkit/standards/frontend/components.md", content)
|
||||
self.assertIn("不编造结论", content)
|
||||
self.assertIn("官方文档", content)
|
||||
self.assertIn("不复制依赖库文档", content)
|
||||
|
||||
def test_style_uses_existing_visual_authority(self) -> None:
|
||||
content = read_skill("style")
|
||||
self.assertIn("设计令牌", content)
|
||||
self.assertIn("经用户确认后再修改", content)
|
||||
self.assertIn("不内置固定矩阵", content)
|
||||
|
||||
def test_form_does_not_invent_business_rules(self) -> None:
|
||||
content = read_skill("form")
|
||||
self.assertIn("不自行确定字段必填", content)
|
||||
self.assertIn("不设计接口", content)
|
||||
self.assertIn("component", content)
|
||||
|
||||
def test_precise_skills_replace_router(self) -> None:
|
||||
self.assertFalse((DEV_SKILLS / "guide").exists())
|
||||
descriptions = {
|
||||
name: (DEV_SKILLS / name / "SKILL.md").read_text(encoding="utf-8").split("---", 2)[1]
|
||||
for name in ("component", "style", "form")
|
||||
}
|
||||
self.assertEqual(3, len(set(descriptions.values())))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -1,102 +0,0 @@
|
||||
"""验证 Git 变更导出的选择、配置保护和写入边界。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
SCRIPT = ROOT / "plugins/git/skills/export/scripts/export.py"
|
||||
|
||||
|
||||
class GitExportTests(unittest.TestCase):
|
||||
"""在临时 Git 仓库中验证真实命令行为。"""
|
||||
|
||||
def git(self, repo: Path, *args: str) -> str:
|
||||
"""执行测试仓库内的 Git 命令。"""
|
||||
|
||||
result = subprocess.run(["git", "-C", str(repo), *args], capture_output=True, text=True, encoding="utf-8", check=True)
|
||||
return result.stdout.strip()
|
||||
|
||||
def run_export(self, repo: Path, target: Path, *args: str) -> subprocess.CompletedProcess[str]:
|
||||
"""使用当前受控 Python 运行导出脚本。"""
|
||||
|
||||
return subprocess.run([sys.executable, str(SCRIPT), "--repo", str(repo), "--target", str(target), *args], capture_output=True, text=True, encoding="utf-8", check=False)
|
||||
|
||||
def make_repo(self, folder: Path) -> Path:
|
||||
"""创建具有稳定身份和首个提交的隔离仓库。"""
|
||||
|
||||
repo = folder / "repo"; repo.mkdir()
|
||||
self.git(repo, "init", "-q"); self.git(repo, "config", "user.name", "Test User"); self.git(repo, "config", "user.email", "test@example.invalid")
|
||||
(repo / "src").mkdir(); (repo / "src/app.txt").write_text("v1\n", encoding="utf-8")
|
||||
self.git(repo, "add", "src/app.txt"); self.git(repo, "commit", "-q", "-m", "init")
|
||||
return repo
|
||||
|
||||
def test_worktree_preview_classifies_shared_and_protected_files(self) -> None:
|
||||
"""共享 CraftKit 文档可导出,环境配置默认受保护,私钥永久阻断。"""
|
||||
|
||||
with tempfile.TemporaryDirectory() as temp:
|
||||
root = Path(temp); repo = self.make_repo(root); target = root / "out"
|
||||
(repo / "src/app.txt").write_text("v2\n", encoding="utf-8")
|
||||
(repo / "application-dev.yml").write_text("server: local\n", encoding="utf-8")
|
||||
(repo / "private.pem").write_text("-----BEGIN PRIVATE KEY-----\nabc\n", encoding="utf-8")
|
||||
standard = repo / ".craftkit/standards/export.md"; standard.parent.mkdir(parents=True); standard.write_text("规范\n", encoding="utf-8")
|
||||
result = self.run_export(repo, target, "--mode", "worktree", "--snapshot", "worktree", "--include-untracked")
|
||||
self.assertEqual(2, result.returncode)
|
||||
manifest = json.loads(result.stdout)
|
||||
self.assertIn("src/app.txt", manifest["exported"])
|
||||
self.assertIn(".craftkit/standards/export.md", manifest["exported"])
|
||||
self.assertIn("application-dev.yml", manifest["protected"])
|
||||
self.assertIn("private.pem", manifest["blocked"])
|
||||
self.assertFalse(target.exists())
|
||||
|
||||
def test_protected_file_requires_matching_project_evidence(self) -> None:
|
||||
"""环境配置只有在项目规范明确点名且执行确认后才写入。"""
|
||||
|
||||
with tempfile.TemporaryDirectory() as temp:
|
||||
root = Path(temp); repo = self.make_repo(root); target = root / "out"
|
||||
(repo / "application-dev.yml").write_text("server: local\n", encoding="utf-8")
|
||||
evidence = repo / ".craftkit/standards/delivery.md"; evidence.parent.mkdir(parents=True)
|
||||
evidence.write_text("交付必须包含 application-dev.yml。\n", encoding="utf-8")
|
||||
result = self.run_export(repo, target, "--mode", "worktree", "--snapshot", "worktree", "--include-untracked",
|
||||
"--allow-protected", "--policy-evidence", ".craftkit/standards/delivery.md", "--apply")
|
||||
self.assertEqual(0, result.returncode, result.stderr)
|
||||
self.assertTrue((target / "application-dev.yml").is_file())
|
||||
manifest = json.loads((target / "export-manifest.json").read_text(encoding="utf-8"))
|
||||
self.assertEqual(".craftkit/standards/delivery.md", manifest["policyEvidence"])
|
||||
|
||||
def test_range_uses_explicit_snapshot_and_records_deleted_file(self) -> None:
|
||||
"""范围负责选路径,快照负责取内容;快照中删除的文件只进入清单。"""
|
||||
|
||||
with tempfile.TemporaryDirectory() as temp:
|
||||
root = Path(temp); repo = self.make_repo(root); target = root / "out"
|
||||
base = self.git(repo, "rev-parse", "HEAD")
|
||||
(repo / "src/app.txt").unlink(); (repo / "src/new.txt").write_text("new\n", encoding="utf-8")
|
||||
self.git(repo, "add", "-A"); self.git(repo, "commit", "-q", "-m", "change")
|
||||
head = self.git(repo, "rev-parse", "HEAD")
|
||||
result = self.run_export(repo, target, "--mode", "range", "--base", base, "--head", head, "--snapshot", head)
|
||||
self.assertEqual(0, result.returncode, result.stderr)
|
||||
manifest = json.loads(result.stdout)
|
||||
self.assertIn("src/app.txt", manifest["deleted"])
|
||||
self.assertIn("src/new.txt", manifest["exported"])
|
||||
|
||||
def test_time_mode_selects_committed_paths_without_writing(self) -> None:
|
||||
"""时间模式应选择提交中出现的路径,并保持预演只读。"""
|
||||
|
||||
with tempfile.TemporaryDirectory() as temp:
|
||||
root = Path(temp); repo = self.make_repo(root); target = root / "out"
|
||||
(repo / "src/app.txt").write_text("v2\n", encoding="utf-8")
|
||||
self.git(repo, "add", "src/app.txt"); self.git(repo, "commit", "-q", "-m", "update")
|
||||
result = self.run_export(repo, target, "--mode", "time", "--since", "2000-01-01", "--snapshot", "HEAD")
|
||||
self.assertEqual(0, result.returncode, result.stderr)
|
||||
self.assertIn("src/app.txt", json.loads(result.stdout)["exported"])
|
||||
self.assertFalse(target.exists())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -1,79 +0,0 @@
|
||||
"""验证预集成 Skill 的文档契约和隔离 Git 行为。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import subprocess
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
SKILL = ROOT / "plugins/git/skills/integrate/SKILL.md"
|
||||
|
||||
|
||||
class GitIntegrateTests(unittest.TestCase):
|
||||
"""在临时仓库中验证 worktree 集成不会移动输入引用。"""
|
||||
|
||||
def git(self, repo: Path, *args: str, check: bool = True) -> subprocess.CompletedProcess[str]:
|
||||
"""执行测试仓库中的 Git 命令并保留失败状态供冲突断言。"""
|
||||
|
||||
return subprocess.run(["git", "-C", str(repo), *args], capture_output=True, text=True, encoding="utf-8", check=check)
|
||||
|
||||
def make_repo(self, root: Path, conflict: bool = False) -> tuple[Path, str, str]:
|
||||
"""创建具有源、目标分叉的隔离仓库。"""
|
||||
|
||||
repo = root / "repo"; repo.mkdir(); self.git(repo, "init", "-q")
|
||||
self.git(repo, "config", "user.name", "Test User"); self.git(repo, "config", "user.email", "test@example.invalid")
|
||||
(repo / "base.txt").write_text("base\n", encoding="utf-8")
|
||||
self.git(repo, "add", "base.txt"); self.git(repo, "commit", "-q", "-m", "base")
|
||||
self.git(repo, "branch", "target"); self.git(repo, "switch", "-q", "-c", "source")
|
||||
source_file = repo / ("base.txt" if conflict else "source.txt")
|
||||
source_file.write_text("source\n", encoding="utf-8")
|
||||
self.git(repo, "add", "-A"); self.git(repo, "commit", "-q", "-m", "source")
|
||||
source_hash = self.git(repo, "rev-parse", "source").stdout.strip()
|
||||
self.git(repo, "switch", "-q", "target")
|
||||
target_file = repo / ("base.txt" if conflict else "target.txt")
|
||||
target_file.write_text("target\n", encoding="utf-8")
|
||||
self.git(repo, "add", "-A"); self.git(repo, "commit", "-q", "-m", "target")
|
||||
target_hash = self.git(repo, "rev-parse", "target").stdout.strip()
|
||||
return repo, source_hash, target_hash
|
||||
|
||||
def test_isolated_merge_preserves_source_and_target_refs(self) -> None:
|
||||
"""预集成分支发生 merge 后,源和目标引用必须保持原哈希。"""
|
||||
|
||||
with tempfile.TemporaryDirectory() as temp:
|
||||
root = Path(temp); repo, source_hash, target_hash = self.make_repo(root)
|
||||
worktree = root / "integration"
|
||||
self.git(repo, "worktree", "add", "-q", "-b", "pre/integration", str(worktree), "target")
|
||||
self.git(worktree, "merge", "--no-edit", "source")
|
||||
self.assertEqual(source_hash, self.git(repo, "rev-parse", "source").stdout.strip())
|
||||
self.assertEqual(target_hash, self.git(repo, "rev-parse", "target").stdout.strip())
|
||||
self.assertTrue((worktree / "source.txt").is_file())
|
||||
self.assertTrue((worktree / "target.txt").is_file())
|
||||
|
||||
def test_conflict_stops_before_automatic_resolution(self) -> None:
|
||||
"""真实冲突应停留在未合并状态,不移动源或目标引用。"""
|
||||
|
||||
with tempfile.TemporaryDirectory() as temp:
|
||||
root = Path(temp); repo, source_hash, target_hash = self.make_repo(root, conflict=True)
|
||||
worktree = root / "integration"
|
||||
self.git(repo, "worktree", "add", "-q", "-b", "pre/conflict", str(worktree), "target")
|
||||
result = self.git(worktree, "merge", "--no-edit", "source", check=False)
|
||||
self.assertNotEqual(0, result.returncode)
|
||||
self.assertIn("UU base.txt", self.git(worktree, "status", "--short").stdout)
|
||||
self.assertEqual(source_hash, self.git(repo, "rev-parse", "source").stdout.strip())
|
||||
self.assertEqual(target_hash, self.git(repo, "rev-parse", "target").stdout.strip())
|
||||
|
||||
def test_skill_separates_stages_and_protects_delivery(self) -> None:
|
||||
"""Skill 必须保留阶段授权、环境配置阻断和强推禁用边界。"""
|
||||
|
||||
text = SKILL.read_text(encoding="utf-8")
|
||||
for value in ("assess", "prepare", "publish", "独立 worktree", "环境配置", "私钥"):
|
||||
self.assertIn(value, text)
|
||||
publish = (SKILL.parent / "references/publish.md").read_text(encoding="utf-8")
|
||||
self.assertIn("默认不改用 `--force`", publish)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -1,83 +0,0 @@
|
||||
"""规范索引维护 Skill 的确定性行为测试。"""
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
SKILL = ROOT / "plugins" / "skill" / "skills" / "guidance-edit"
|
||||
SCRIPT = SKILL / "scripts" / "check_index.py"
|
||||
|
||||
|
||||
class GuidanceEditTest(unittest.TestCase):
|
||||
"""验证索引检查器和读写职责边界。"""
|
||||
|
||||
def run_check(self, standards: Path) -> subprocess.CompletedProcess[str]:
|
||||
"""以 JSON 模式执行检查器。"""
|
||||
return subprocess.run(
|
||||
[sys.executable, str(SCRIPT), str(standards), "--json"],
|
||||
check=False,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
def test_clean_index_is_reachable(self) -> None:
|
||||
"""根索引能够逐级访问所有规范时应检查通过。"""
|
||||
with tempfile.TemporaryDirectory() as temp:
|
||||
standards = Path(temp)
|
||||
(standards / "frontend").mkdir()
|
||||
(standards / "index.md").write_text(
|
||||
"[前端](frontend/index.md)\n", encoding="utf-8"
|
||||
)
|
||||
(standards / "frontend" / "index.md").write_text(
|
||||
"[组件](components.md)\n", encoding="utf-8"
|
||||
)
|
||||
(standards / "frontend" / "components.md").write_text(
|
||||
"# 组件\n", encoding="utf-8"
|
||||
)
|
||||
result = self.run_check(standards)
|
||||
self.assertEqual(0, result.returncode, result.stderr)
|
||||
report = json.loads(result.stdout)
|
||||
self.assertEqual([], report["unindexed"])
|
||||
self.assertEqual([], report["broken"])
|
||||
|
||||
def test_reports_unindexed_broken_and_cycle(self) -> None:
|
||||
"""未索引文件、失效链接和循环引用应同时报告。"""
|
||||
with tempfile.TemporaryDirectory() as temp:
|
||||
standards = Path(temp)
|
||||
(standards / "index.md").write_text(
|
||||
"[主题](topic.md)\n[缺失](missing.md)\n", encoding="utf-8"
|
||||
)
|
||||
(standards / "topic.md").write_text(
|
||||
"[返回](index.md)\n", encoding="utf-8"
|
||||
)
|
||||
(standards / "orphan.md").write_text("# 未索引\n", encoding="utf-8")
|
||||
result = self.run_check(standards)
|
||||
self.assertEqual(1, result.returncode)
|
||||
report = json.loads(result.stdout)
|
||||
self.assertEqual(["orphan.md"], report["unindexed"])
|
||||
self.assertEqual("missing.md", report["broken"][0]["target"])
|
||||
self.assertTrue(report["cycles"])
|
||||
|
||||
def test_missing_entry_is_input_error(self) -> None:
|
||||
"""入口不存在时应返回输入错误,而不是覆盖问题。"""
|
||||
with tempfile.TemporaryDirectory() as temp:
|
||||
result = self.run_check(Path(temp))
|
||||
self.assertEqual(2, result.returncode)
|
||||
self.assertIn("索引入口不存在", result.stderr)
|
||||
|
||||
def test_skill_separates_read_and_write_modes(self) -> None:
|
||||
"""检查默认只读,所有写入均需预览与确认。"""
|
||||
content = (SKILL / "SKILL.md").read_text(encoding="utf-8")
|
||||
self.assertIn("检查默认只读", content)
|
||||
self.assertIn("经用户确认后写入", content)
|
||||
self.assertIn("不强制创建固定层级", content)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -1,112 +0,0 @@
|
||||
import json
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).parents[2]
|
||||
GUIDANCE = ROOT / "plugins" / "skill" / "skills" / "guidance"
|
||||
INIT = ROOT / "plugins" / "knowledge" / "skills" / "init"
|
||||
|
||||
|
||||
class GuidanceInitTest(unittest.TestCase):
|
||||
"""验证规范检索和项目初始化之间的职责边界。"""
|
||||
|
||||
def test_guidance_is_read_only_and_uses_progressive_sources(self) -> None:
|
||||
"""检索 Skill 应声明项目优先、渐进读取且不隐式初始化。"""
|
||||
|
||||
content = (GUIDANCE / "SKILL.md").read_text(encoding="utf-8")
|
||||
self.assertIn("以只读方式", content)
|
||||
self.assertIn("不得先递归加载整个知识库", content)
|
||||
self.assertIn("不得在检索过程中隐式初始化", content)
|
||||
self.assertIn(".craftkit/project.json", content)
|
||||
|
||||
def test_public_baseline_routes_frontend_and_backend(self) -> None:
|
||||
"""公共基线应提供前后端入口,并让索引引用实际规则文件。"""
|
||||
|
||||
root = GUIDANCE / "references" / "guidance"
|
||||
index = (root / "index.md").read_text(encoding="utf-8")
|
||||
self.assertIn("frontend/index.md", index)
|
||||
self.assertIn("backend/index.md", index)
|
||||
self.assertEqual(6, len(list((root / "frontend").glob("*.md"))))
|
||||
self.assertEqual(6, len(list((root / "backend").glob("*.md"))))
|
||||
|
||||
sources = (root / "sources.md").read_text(encoding="utf-8")
|
||||
for authority in ("RFC 9110", "WCAG 2.2", "OWASP", "MDN Fetch API"):
|
||||
self.assertIn(authority, sources)
|
||||
|
||||
def test_framework_profiles_are_selected_by_project_version(self) -> None:
|
||||
"""普通任务只能使用当前 profile,且不存在的 profile 不得被猜测。"""
|
||||
|
||||
routing = (GUIDANCE / "references" / "profile-routing.md").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
self.assertIn("普通开发任务只加载当前 profile", routing)
|
||||
self.assertIn("升级、迁移或版本比较", routing)
|
||||
self.assertIn("不默认最新版本", routing)
|
||||
self.assertIn("不创建空目录", routing)
|
||||
|
||||
init = (INIT / "SKILL.md").read_text(encoding="utf-8")
|
||||
config = (INIT / "references" / "project-config.md").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
self.assertIn("精确版本、公共 profile", init)
|
||||
for field in ('"name"', '"version"', '"profile"'):
|
||||
self.assertIn(field, config)
|
||||
|
||||
def test_init_supports_existing_and_new_projects(self) -> None:
|
||||
"""初始化 Skill 应同时包含成熟项目与空项目流程。"""
|
||||
|
||||
content = (INIT / "SKILL.md").read_text(encoding="utf-8")
|
||||
self.assertIn("成熟项目", content)
|
||||
self.assertIn("空项目", content)
|
||||
self.assertIn("参考项目", content)
|
||||
self.assertTrue((INIT / "references" / "existing.md").is_file())
|
||||
self.assertTrue((INIT / "references" / "new.md").is_file())
|
||||
|
||||
def test_project_template_has_safe_shared_fields(self) -> None:
|
||||
"""项目模板应包含检索入口,且不得预置内部标识或机器路径。"""
|
||||
|
||||
path = INIT / "assets" / "project.json"
|
||||
payload = json.loads(path.read_text(encoding="utf-8"))
|
||||
self.assertEqual(1, payload["schemaVersion"])
|
||||
self.assertIn(payload["initialization"]["mode"], {"existing", "new"})
|
||||
self.assertEqual([], payload["dependencies"]["internal"])
|
||||
self.assertEqual([], payload["frontend"]["componentLibraries"])
|
||||
self.assertEqual([], payload["frontend"]["componentRoots"])
|
||||
self.assertEqual([], payload["frontend"]["documentation"])
|
||||
self.assertEqual(
|
||||
".craftkit/standards/index.md",
|
||||
payload["guidance"]["standardsIndex"],
|
||||
)
|
||||
serialized = json.dumps(payload, ensure_ascii=False)
|
||||
self.assertNotIn(":\\", serialized)
|
||||
|
||||
def test_init_collects_frontend_component_metadata(self) -> None:
|
||||
"""初始化应记录组件库证据和入口,但不能默认选择组件库。"""
|
||||
|
||||
content = "\n".join(
|
||||
path.read_text(encoding="utf-8")
|
||||
for path in (
|
||||
INIT / "SKILL.md",
|
||||
INIT / "references" / "project-config.md",
|
||||
INIT / "references" / "existing.md",
|
||||
INIT / "references" / "new.md",
|
||||
)
|
||||
)
|
||||
self.assertIn("componentLibraries", content)
|
||||
self.assertIn("组件根", content)
|
||||
self.assertIn("不默认选择流行方案", content)
|
||||
self.assertTrue((INIT / "assets" / "frontend-components.md").is_file())
|
||||
|
||||
def test_local_directories_are_the_only_nested_ignores(self) -> None:
|
||||
"""初始化模板只排除本地状态和缓存,不得排除共享资料。"""
|
||||
|
||||
rules = (INIT / "assets" / "craftkit.gitignore").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
active = [line for line in rules.splitlines() if line and not line.startswith("#")]
|
||||
self.assertEqual(["/local/", "/cache/"], active)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -1,59 +0,0 @@
|
||||
"""验证知识管理批次的职责边界、中性模板和模式路由。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
KNOWLEDGE = ROOT / "plugins/knowledge/skills"
|
||||
|
||||
|
||||
class KnowledgeBatchTests(unittest.TestCase):
|
||||
"""检查四个 Skill 不重叠,并保持项目知识目录一致。"""
|
||||
|
||||
def read(self, relative: str) -> str:
|
||||
"""读取待验证的 Skill 资源。"""
|
||||
|
||||
return (KNOWLEDGE / relative).read_text(encoding="utf-8")
|
||||
|
||||
def test_trace_is_evidence_based_and_does_not_auto_write(self) -> None:
|
||||
"""偏离复盘应使用中性失效分类,不能自动修改规则。"""
|
||||
|
||||
text = self.read("trace/SKILL.md")
|
||||
for value in ("missing", "unread", "mismatch", "misapplied", "insufficient", "尚未执行"):
|
||||
self.assertIn(value, text)
|
||||
self.assertNotIn("七问", text)
|
||||
|
||||
def test_distill_routes_long_term_knowledge_and_excludes_handoff(self) -> None:
|
||||
"""知识提炼和任务交接必须具有不同产物边界。"""
|
||||
|
||||
text = self.read("distill/SKILL.md")
|
||||
routing = self.read("distill/references/routing.md")
|
||||
self.assertIn("不生成接续提示词", text)
|
||||
for path in (".craftkit/knowledge/pitfalls/", ".craftkit/knowledge/decisions/", ".craftkit/standards/"):
|
||||
self.assertIn(path, routing)
|
||||
|
||||
def test_lessons_merges_full_lifecycle_without_fixed_categories(self) -> None:
|
||||
"""经验初始化、维护、审计和提升应共享一个目录与中性模板。"""
|
||||
|
||||
text = self.read("lessons/SKILL.md")
|
||||
for mode in ("`init`", "`curate`", "`audit`", "`promote`"):
|
||||
self.assertIn(mode, text)
|
||||
self.assertIn(".craftkit/knowledge/pitfalls/", text)
|
||||
index = self.read("lessons/assets/index.md")
|
||||
self.assertIn("当前尚未建立分类", index)
|
||||
self.assertNotIn("lowcode", index.casefold())
|
||||
|
||||
def test_worklog_requires_git_evidence_and_separate_write_permission(self) -> None:
|
||||
"""工作日志不能推测工作量或自动写入日报文件。"""
|
||||
|
||||
text = self.read("worklog/SKILL.md")
|
||||
self.assertIn("不把提交数量当作工作量", text)
|
||||
self.assertIn("范围内确实没有提交时如实说明", text)
|
||||
self.assertIn("需要新的明确授权", text)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -1,76 +0,0 @@
|
||||
import subprocess
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class LocalStateTest(unittest.TestCase):
|
||||
"""验证 `.craftkit/` 能同时承载共享资料和本地状态。"""
|
||||
|
||||
def run_git(self, root: Path, *args: str) -> subprocess.CompletedProcess[str]:
|
||||
"""在隔离仓库执行 Git,并保留输出供断言使用。"""
|
||||
|
||||
return subprocess.run(
|
||||
["git", "-C", str(root), *args],
|
||||
check=False,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
def test_nested_gitignore_separates_shared_and_local_content(self) -> None:
|
||||
"""共享资料应可提交,本地目录和缓存应由嵌套规则排除。"""
|
||||
|
||||
with tempfile.TemporaryDirectory() as temp:
|
||||
root = Path(temp)
|
||||
initialized = self.run_git(root, "init")
|
||||
self.assertEqual(initialized.returncode, 0, initialized.stderr)
|
||||
|
||||
craftkit = root / ".craftkit"
|
||||
craftkit.mkdir()
|
||||
(craftkit / ".gitignore").write_text(
|
||||
"# Local CraftKit data\n/local/\n/cache/\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
(craftkit / "README.md").write_text("# 项目资料\n", encoding="utf-8")
|
||||
shared = craftkit / "standards" / "coding" / "rules.md"
|
||||
shared.parent.mkdir(parents=True)
|
||||
shared.write_text("# 编码规范\n", encoding="utf-8")
|
||||
local = craftkit / "local" / "handoff" / "current.md"
|
||||
local.parent.mkdir(parents=True)
|
||||
local.write_text("# 本地交接\n", encoding="utf-8")
|
||||
cache = craftkit / "cache" / "result.json"
|
||||
cache.parent.mkdir(parents=True)
|
||||
cache.write_text("{}\n", encoding="utf-8")
|
||||
|
||||
ignored = self.run_git(
|
||||
root,
|
||||
"check-ignore",
|
||||
"--no-index",
|
||||
"-v",
|
||||
".craftkit/local/handoff/current.md",
|
||||
)
|
||||
self.assertEqual(ignored.returncode, 0, ignored.stderr)
|
||||
self.assertIn(".craftkit/.gitignore", ignored.stdout.replace("\\", "/"))
|
||||
|
||||
cache_ignored = self.run_git(
|
||||
root,
|
||||
"check-ignore",
|
||||
"--no-index",
|
||||
".craftkit/cache/result.json",
|
||||
)
|
||||
self.assertEqual(cache_ignored.returncode, 0, cache_ignored.stderr)
|
||||
|
||||
status = self.run_git(root, "status", "--short", "--untracked-files=all")
|
||||
self.assertEqual(status.returncode, 0, status.stderr)
|
||||
normalized = status.stdout.replace("\\", "/")
|
||||
self.assertIn(".craftkit/.gitignore", normalized)
|
||||
self.assertIn(".craftkit/README.md", normalized)
|
||||
self.assertIn(".craftkit/standards/coding/rules.md", normalized)
|
||||
self.assertNotIn(".craftkit/local", normalized)
|
||||
self.assertNotIn(".craftkit/cache", normalized)
|
||||
self.assertFalse((root / ".gitignore").exists())
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -1,95 +0,0 @@
|
||||
"""迁移内部脚本的最小行为测试。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib.util
|
||||
import hashlib
|
||||
import json
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
SCRIPT_ROOT = Path(__file__).parents[1] / "scripts"
|
||||
|
||||
|
||||
def load_module(name: str):
|
||||
"""从脚本路径加载模块,避免要求项目安装为 Python 包。"""
|
||||
spec = importlib.util.spec_from_file_location(name, SCRIPT_ROOT / f"{name}.py")
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
assert spec.loader
|
||||
spec.loader.exec_module(module)
|
||||
return module
|
||||
|
||||
|
||||
scan_sources = load_module("scan_sources")
|
||||
check_skill = load_module("check_skill")
|
||||
update_lock = load_module("update_lock")
|
||||
|
||||
|
||||
class MigrationScriptTests(unittest.TestCase):
|
||||
def test_scan_uses_relative_paths_and_stable_hash(self):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
root = Path(directory)
|
||||
skill = root / "group" / "demo"
|
||||
skill.mkdir(parents=True)
|
||||
(skill / "SKILL.md").write_text(
|
||||
"---\nname: demo\ndescription: 示例\n---\n", encoding="utf-8"
|
||||
)
|
||||
first = scan_sources.scan_source("source-a", root)
|
||||
second = scan_sources.scan_source("source-a", root)
|
||||
self.assertEqual("group/demo", first["skills"][0]["relativePath"])
|
||||
self.assertEqual(first["skills"][0]["sha256"], second["skills"][0]["sha256"])
|
||||
self.assertNotIn(str(root), json.dumps(first, ensure_ascii=False))
|
||||
|
||||
def test_check_reports_name_mismatch_and_forbidden_term(self):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
root = Path(directory) / "expected"
|
||||
root.mkdir()
|
||||
(root / "SKILL.md").write_text(
|
||||
"---\nname: other\ndescription: 示例\n---\n内部标识",
|
||||
encoding="utf-8",
|
||||
)
|
||||
result = check_skill.check_skill(root, ["内部标识"])
|
||||
codes = {issue["code"] for issue in result["issues"]}
|
||||
self.assertIn("name-path-mismatch", codes)
|
||||
self.assertIn("forbidden:内部标识", codes)
|
||||
|
||||
def test_update_lock_preserves_manual_fields(self):
|
||||
path_hash = hashlib.sha256("group/demo".encode("utf-8")).hexdigest()
|
||||
key = f"source-a:{path_hash[:16]}"
|
||||
lock = {
|
||||
"schemaVersion": 1,
|
||||
"sources": {},
|
||||
"skills": {
|
||||
key: {
|
||||
"status": "specified",
|
||||
"target": "plugins/skill/skills/demo",
|
||||
}
|
||||
},
|
||||
}
|
||||
report = {
|
||||
"sources": [
|
||||
{
|
||||
"id": "source-a",
|
||||
"commit": "abc",
|
||||
"skillCount": 1,
|
||||
"skills": [
|
||||
{
|
||||
"name": "demo",
|
||||
"relativePath": "group/demo",
|
||||
"sha256": "123",
|
||||
}
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
merged = update_lock.merge(lock, report)
|
||||
entry = merged["skills"][key]
|
||||
self.assertEqual("specified", entry["status"])
|
||||
self.assertEqual("plugins/skill/skills/demo", entry["target"])
|
||||
self.assertEqual("123", entry["sourceSha256"])
|
||||
self.assertNotIn("name", entry)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -1,39 +0,0 @@
|
||||
"""公开基线与专项设计 Skill 测试。"""
|
||||
|
||||
from pathlib import Path
|
||||
import unittest
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
SKILLS = ROOT / "plugins" / "dev" / "skills"
|
||||
NAMES = (
|
||||
"design-api", "design-db", "review-java", "review-frontend",
|
||||
"design-frontend-data", "review-mybatis", "design-workflow",
|
||||
)
|
||||
|
||||
|
||||
class PublicBaselineBatchTest(unittest.TestCase):
|
||||
"""验证公开来源登记和版本边界。"""
|
||||
|
||||
def test_sources_are_official_and_dated(self) -> None:
|
||||
for name in NAMES:
|
||||
source = (SKILLS / name / "references" / "sources.md").read_text(encoding="utf-8")
|
||||
self.assertIn("重建日期:2026-08-25", source)
|
||||
self.assertIn("https://", source)
|
||||
|
||||
def test_project_version_is_not_replaced_by_latest(self) -> None:
|
||||
content = "\n".join(
|
||||
(SKILLS / name / "SKILL.md").read_text(encoding="utf-8") for name in NAMES
|
||||
)
|
||||
self.assertIn("不得默认最新", content)
|
||||
self.assertIn("规则混用", content)
|
||||
self.assertIn("精确版本", content)
|
||||
|
||||
def test_workflow_does_not_embed_approval_rules(self) -> None:
|
||||
content = (SKILLS / "design-workflow" / "SKILL.md").read_text(encoding="utf-8")
|
||||
self.assertIn("不内置审批节点", content)
|
||||
self.assertIn("项目实际流程引擎", content)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -1,87 +0,0 @@
|
||||
"""剩余来源连续迁移波次验收测试。"""
|
||||
|
||||
from pathlib import Path
|
||||
import json
|
||||
import unittest
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
DEV = ROOT / "plugins" / "dev" / "skills"
|
||||
DOC = ROOT / "plugins" / "doc" / "skills"
|
||||
GIT = ROOT / "plugins" / "git" / "skills"
|
||||
|
||||
TARGETS = {
|
||||
DEV: (
|
||||
"design-api", "design-db", "review-java", "review-frontend",
|
||||
"design-frontend-data", "review-mybatis", "design-workflow",
|
||||
"implement-backend", "implement-frontend", "review-code",
|
||||
"test-backend", "test-ui", "analyze-bugs", "upgrade", "estimate",
|
||||
),
|
||||
DOC: ("report", "message", "requirements"),
|
||||
GIT: ("release",),
|
||||
}
|
||||
|
||||
|
||||
class RemainingWaveTest(unittest.TestCase):
|
||||
"""验证目标完整性、操作边界和来源状态闭合。"""
|
||||
|
||||
def read_skill(self, root: Path, name: str) -> str:
|
||||
return (root / name / "SKILL.md").read_text(encoding="utf-8")
|
||||
|
||||
def test_all_targets_have_skill_and_ui_metadata(self) -> None:
|
||||
names = []
|
||||
for root, targets in TARGETS.items():
|
||||
for name in targets:
|
||||
names.append(name)
|
||||
self.assertTrue((root / name / "SKILL.md").is_file(), name)
|
||||
self.assertTrue((root / name / "agents" / "openai.yaml").is_file(), name)
|
||||
self.assertEqual(19, len(names))
|
||||
self.assertEqual(len(names), len(set(names)))
|
||||
|
||||
def test_implementation_preserves_workspace_and_authorization(self) -> None:
|
||||
content = "\n".join(
|
||||
self.read_skill(DEV, name)
|
||||
for name in ("implement-backend", "implement-frontend")
|
||||
)
|
||||
self.assertIn("保留用户已有改动", content)
|
||||
self.assertIn("精确版本", content)
|
||||
self.assertIn("不自动暂存", content)
|
||||
self.assertIn("环境配置", content)
|
||||
|
||||
def test_review_and_test_results_are_separated(self) -> None:
|
||||
review = self.read_skill(DEV, "review-code")
|
||||
backend = self.read_skill(DEV, "test-backend")
|
||||
ui = self.read_skill(DEV, "test-ui")
|
||||
self.assertIn("只读", review)
|
||||
self.assertIn("不启动完整应用", backend)
|
||||
self.assertIn("授权后", ui)
|
||||
self.assertIn("不能替代浏览器结果", ui)
|
||||
|
||||
def test_delivery_actions_are_independently_authorized(self) -> None:
|
||||
upgrade = self.read_skill(DEV, "upgrade")
|
||||
estimate = self.read_skill(DEV, "estimate")
|
||||
release = self.read_skill(GIT, "release")
|
||||
self.assertIn("源版本", upgrade)
|
||||
self.assertIn("目标版本", upgrade)
|
||||
self.assertIn("区间", estimate)
|
||||
self.assertIn("假设", estimate)
|
||||
self.assertIn("分阶段授权", release)
|
||||
|
||||
def test_writing_skills_do_not_send_or_invent(self) -> None:
|
||||
content = "\n".join(self.read_skill(DOC, name) for name in TARGETS[DOC])
|
||||
self.assertIn("不得虚构", content)
|
||||
self.assertIn("默认只生成草稿", content)
|
||||
|
||||
def test_source_lock_has_no_pending_items(self) -> None:
|
||||
data = json.loads((ROOT / "migration" / "source-lock.json").read_text(encoding="utf-8"))
|
||||
skills = data["skills"]
|
||||
self.assertEqual(64, len(skills))
|
||||
self.assertNotIn("pending", {item["status"] for item in skills.values()})
|
||||
self.assertEqual(
|
||||
{"migrated", "superseded", "excluded"},
|
||||
{item["status"] for item in skills.values()},
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "dev",
|
||||
"version": "0.4.0",
|
||||
"version": "0.6.0",
|
||||
"description": "通用软件设计、编码、审查与测试工作流。",
|
||||
"author": {
|
||||
"name": "CraftKit"
|
||||
@@ -9,7 +9,7 @@
|
||||
"interface": {
|
||||
"displayName": "Dev",
|
||||
"shortDescription": "软件设计、编码、审查与测试工具",
|
||||
"longDescription": "提供不绑定公司框架的设计、实现、审查、测试、升级与估算工作流。",
|
||||
"longDescription": "提供基于项目实际技术栈的设计、实现、文档同步、审查、测试、升级与估算工作流。",
|
||||
"developerName": "CraftKit",
|
||||
"category": "Productivity",
|
||||
"capabilities": ["Read", "Write"],
|
||||
|
||||
@@ -7,4 +7,6 @@ description: 分析 CSV、表格或结构化 Bug 清单,规范化字段、去
|
||||
|
||||
以原始数据为证据,先识别编码、分隔符、字段含义和缺失值,再建立不改变原始文件的规范化视图。
|
||||
|
||||
输出总量、状态、严重度、模块、时间和重复项统计,并区分数据事实、合理推断和待确认项。分类规则和时间范围必须透明;样本不足时不外推。默认只生成对话报告,用户要求落盘时确认格式与路径;不得自动修改 Bug 状态、分派人员或修复代码。
|
||||
输出总量、状态、严重度、模块、时间和重复项统计,并区分数据事实、合理推断和待确认项。分类规则和时间范围必须透明;样本不足时不外推。默认只生成对话报告;用户要求保存时读取 `.craftkit/project.json` 的 `documents` 配置,过程报告使用 `workRoot`,共享报告使用 `designRoot`。不得自动修改 Bug 状态、分派人员或修复代码。
|
||||
|
||||
落盘前检索同主题的需求、设计、规范或知识,优先更新已有权威文档。共享长期文档新建或实质修改后按 `.craftkit/standards/document-maintenance.md` 更新审核状态;排版和错字修正不改变状态。`r`n`r`n写入后在 `workRoot/<task>/task.json` 登记本次创建、更新或引用的文档及 `relationship`;已有记录时保守合并。关联旧文档不转移所有权,也不产生删除权限;不修改项目级默认配置。
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "Bug 分析"
|
||||
display_name: "Bug 分析(dev:analyze-bugs)"
|
||||
short_description: "分析结构化 Bug 清单和质量风险"
|
||||
default_prompt: "使用 $analyze-bugs 分析这份 Bug 清单并给出证据化结论。"
|
||||
|
||||
@@ -13,7 +13,7 @@ description: 根据当前项目的真实依赖、已有用法和可验证契约
|
||||
2. 按 [选型规则](references/selection.md) 比较复用、扩展和新建方案。
|
||||
3. 按 [证据规则](references/evidence.md) 查证组件契约及版本兼容性。
|
||||
4. 输出推荐组件、适用理由、契约摘要、替代方案、缺口和风险。
|
||||
5. 用户需要持续复用扫描结果时,按 [组件索引](references/index.md) 展示拟新增或更新内容;确认后写入 `.craftkit/standards/frontend/components.md`。
|
||||
5. 用户需要持续复用扫描结果时,按 [组件索引](references/index.md) 展示拟新增或更新内容;确认后更新已有 `.craftkit/standards/frontend/components.md`,并按项目文档维护规范处理审核状态。
|
||||
6. 如证据不足,说明缺少的材料并询问用户,不代替后续页面实现 Skill 编写完整页面。
|
||||
|
||||
项目没有 `.craftkit/project.json` 时,继续检查真实依赖和现有代码;只有缺失信息会改变结论时才询问用户。
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "组件选型"
|
||||
display_name: "组件选型(dev:component)"
|
||||
short_description: "基于项目证据选择并查证前端组件"
|
||||
default_prompt: "使用 $component 为当前场景选择组件,并列出契约证据和风险。"
|
||||
|
||||
@@ -13,6 +13,9 @@ description: 基于项目需求、现有契约和对应版本官方规范设计
|
||||
2. 明确资源、动作、幂等性、认证授权、输入、输出和错误语义。
|
||||
3. 方法、状态码、缓存、条件请求和重试语义以 [官方来源](references/sources.md) 及项目版本为依据。
|
||||
4. 输出路径与方法、参数位置、请求响应模型、错误、兼容、弃用和测试清单。
|
||||
5. 未确认的业务规则和框架封装列为待确认,不生成实现代码。
|
||||
5. 默认在对话中输出;用户要求保存设计文档时读取 `.craftkit/project.json` 的 `documents` 配置,过程设计使用 `workRoot`,共享设计使用 `designRoot`,不改变接口自身的路径设计。
|
||||
|
||||
落盘前检索同主题的需求、设计、规范或知识,优先更新已有权威文档。共享长期文档新建或实质修改后按 `.craftkit/standards/document-maintenance.md` 更新审核状态;排版和错字修正不改变状态。`r`n`r`n写入后在 `workRoot/<task>/task.json` 登记本次创建、更新或引用的文档及 `relationship`;已有记录时保守合并。关联旧文档不转移所有权,也不产生删除权限;不修改项目级默认配置。
|
||||
6. 未确认的业务规则和框架封装列为待确认,不生成实现代码。
|
||||
|
||||
项目规则高于公共建议;不得默认最新 OpenAPI 版本或把内部接口模式写成通用规则。
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "API 设计"
|
||||
display_name: "API 设计(dev:design-api)"
|
||||
short_description: "设计和评审可验证的 HTTP API 契约"
|
||||
default_prompt: "使用 $design-api 为当前需求设计 HTTP API 契约。"
|
||||
|
||||
@@ -10,15 +10,21 @@ description: 基于需求、现有后端代码和项目规范设计模块边界
|
||||
## 工作流
|
||||
|
||||
1. 读取需求、项目元数据、适用规范、依赖清单和相关后端实现,确认语言、框架及精确版本。
|
||||
2. 按 [范围分析](references/scope.md) 明确现状、边界、参与者和约束。
|
||||
3. 设计模块职责、调用关系、数据所有权、事务边界、并发策略、错误语义、权限和可观测性。
|
||||
4. 数据库或 HTTP 契约需要详细设计时,记录输入和待决项,交由相应专项 Skill;本 Skill 保持整体一致性。
|
||||
5. 按 [设计输出](references/output.md) 展示方案、备选项和风险,并用 [评审清单](references/review.md) 自检。
|
||||
6. 默认在对话中输出;用户要求落盘时,先确认项目约定路径并保守写入。
|
||||
2. 按 [Profile 消费规则](references/profile-consumption.md) 确定目标模块和 `backend-design` 能力;提供方缺失时继续使用中性流程并报告缺口。
|
||||
3. 按 [范围分析](references/scope.md) 明确现状、边界、参与者和约束。
|
||||
4. 设计模块职责、调用关系、数据所有权、事务边界、并发策略、错误语义、权限和可观测性。
|
||||
5. 数据库或 HTTP 契约需要详细设计时,记录输入和待决项,交由相应专项 Skill;本 Skill 保持整体一致性。
|
||||
6. 按 [设计输出](references/output.md) 展示方案、备选项和风险,并用 [评审清单](references/review.md) 自检。
|
||||
7. 默认在对话中输出;用户要求落盘时读取 `.craftkit/project.json` 的 `documents` 配置,过程设计使用 `workRoot`,共享设计使用 `designRoot`,并保守写入。
|
||||
|
||||
落盘前检索同主题的需求、设计、规范或知识,优先更新已有权威文档。共享长期文档新建或实质修改后按 `.craftkit/standards/document-maintenance.md` 更新审核状态;排版和错字修正不改变状态。
|
||||
|
||||
写入后在 `workRoot/<task>/task.json` 登记本次创建、更新或引用的文档及 `relationship`;已有记录时保守合并。关联旧文档不转移所有权,也不产生删除权限;不修改项目级默认配置。
|
||||
|
||||
## 边界
|
||||
|
||||
- 项目规则通过 `guidance` 获取;不存在的规范、框架能力和依赖接口不得猜测。
|
||||
- 已安装 `guidance` 时用它获取项目规则;未安装时按“目标目录适用的 `AGENTS.md` → `.craftkit/agents/index.md` → `.craftkit/standards/index.md` → 命中正文”的顺序手工读取。不存在的规范、框架能力和依赖接口不得猜测。
|
||||
- 版本从 `.craftkit/project.json`、构建文件、锁文件或源码证据确认,不默认最新版本。
|
||||
- 当前会话没有发现语言提供方时,不扫描插件缓存或猜测物理路径。
|
||||
- 对现有系统的设计先追踪真实调用链和数据流,区分已验证事实与建议。
|
||||
- 不把接口示例、表结构草案或伪代码视为已实施行为。
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "后端设计"
|
||||
display_name: "后端设计(dev:design-backend)"
|
||||
short_description: "设计后端边界、数据影响和运行约束"
|
||||
default_prompt: "使用 $design-backend 为当前需求制定后端技术设计。"
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
# Profile 消费规则
|
||||
|
||||
1. 使用目标路径匹配项目画像中的模块;Schema 1 或没有模块时,将顶层技术栈作为根模块候选。
|
||||
2. 从项目画像、构建文件和锁文件确认语言、框架及精确版本。
|
||||
3. 当前会话发现对应语言的 Profile Skill 时,请求 `backend-design` 能力,由提供方读取自身资料。
|
||||
4. 没有发现提供方时,将能力标记为 `missing`,继续执行中性后端设计流程。
|
||||
5. Profile 逻辑资料标识只用于诊断,不转换为用户插件缓存路径。
|
||||
6. 项目规则由 `guidance` 合并;Profile 只提供公共技术资料。
|
||||
|
||||
输出中报告目标模块、版本证据、提供方、能力状态、项目覆盖和未覆盖范围。版本不匹配时不得加载冲突资料。
|
||||
@@ -13,6 +13,9 @@ description: 根据业务数据、访问模式和目标数据库版本设计或
|
||||
2. 设计实体、关系、主键、约束、类型、索引和数据生命周期。
|
||||
3. 按 [官方来源](references/sources.md) 核实目标版本语法及行为,不跨数据库复制 DDL。
|
||||
4. 输出结构、约束、索引依据、迁移顺序、兼容、回滚和验证查询。
|
||||
5. 默认只给方案;执行 DDL、迁移存量数据或连接数据库需要单独授权。
|
||||
5. 用户要求保存设计说明时,读取 `.craftkit/project.json` 的 `documents` 配置选择过程或共享目录;先检索并更新已有权威数据设计,实质修改共享文档后按项目文档维护规范更新审核状态。
|
||||
6. 默认只给方案;执行 DDL、迁移存量数据或连接数据库需要单独授权。
|
||||
|
||||
写入后在 `workRoot/<task>/task.json` 登记创建、更新或引用关系。已有文档属于其他任务时只登记关联,不取得删除权限;可执行迁移文件仍沿用项目迁移工具约定。
|
||||
|
||||
未知容量、并发和查询模式应标为假设,不凭惯例制造审计字段或业务枚举。
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "数据库设计"
|
||||
display_name: "数据库设计(dev:design-db)"
|
||||
short_description: "设计表结构、约束、索引和迁移方案"
|
||||
default_prompt: "使用 $design-db 为当前需求设计数据库结构和迁移方案。"
|
||||
|
||||
@@ -14,5 +14,8 @@ description: 设计前端请求边界、视图模型、状态所有权、缓存
|
||||
3. 设计加载、成功、空、错误、取消、重试、竞态、缓存失效和乐观更新行为。
|
||||
4. 按 [官方来源](references/sources.md) 核实浏览器请求和框架状态语义。
|
||||
5. 输出数据流、所有权、转换边界、并发策略、错误策略和测试点,不预设字段或请求封装。
|
||||
6. 用户要求保存设计文档时读取 `.craftkit/project.json` 的 `documents` 配置,过程设计使用 `workRoot`,共享设计使用 `designRoot`。
|
||||
|
||||
落盘前检索同主题的需求、设计、规范或知识,优先更新已有权威文档。共享长期文档新建或实质修改后按 `.craftkit/standards/document-maintenance.md` 更新审核状态;排版和错字修正不改变状态。`r`n`r`n写入后在 `workRoot/<task>/task.json` 登记本次创建、更新或引用的文档及 `relationship`;已有记录时保守合并。关联旧文档不转移所有权,也不产生删除权限;不修改项目级默认配置。
|
||||
|
||||
具体 API 字段映射交由 `prepare-api`,页面组合交由 `design-frontend`。
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "前端数据设计"
|
||||
display_name: "前端数据设计(dev:design-frontend-data)"
|
||||
short_description: "设计请求、状态、缓存和视图模型边界"
|
||||
default_prompt: "使用 $design-frontend-data 设计当前页面的数据流和状态边界。"
|
||||
|
||||
@@ -14,7 +14,9 @@ description: 基于需求、现有前端代码和项目规范设计页面清单
|
||||
3. 按 [数据设计](references/data.md) 设计视图模型、状态所有权、加载与提交转换、错误和权限呈现。
|
||||
4. 组件、样式和表单结构分别复用 `component`、`style`、`form` 的证据与结论;本 Skill 负责页面级组合。
|
||||
5. API 契约需要映射时交由 `prepare-api`,并在设计中记录所需接口、字段和未决项。
|
||||
6. 按 [设计输出](references/output.md) 展示方案和风险;用户要求落盘时,先确认项目约定路径。
|
||||
6. 按 [设计输出](references/output.md) 展示方案和风险;用户要求落盘时读取 `.craftkit/project.json` 的 `documents` 配置,过程设计使用 `workRoot`,共享设计使用 `designRoot`。
|
||||
|
||||
落盘前检索同主题的需求、设计、规范或知识,优先更新已有权威文档。共享长期文档新建或实质修改后按 `.craftkit/standards/document-maintenance.md` 更新审核状态;排版和错字修正不改变状态。`r`n`r`n写入后在 `workRoot/<task>/task.json` 登记本次创建、更新或引用的文档及 `relationship`;已有记录时保守合并。关联旧文档不转移所有权,也不产生删除权限;不修改项目级默认配置。
|
||||
|
||||
## 边界
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "前端设计"
|
||||
display_name: "前端设计(dev:design-frontend)"
|
||||
short_description: "设计页面、交互、状态和组件组合"
|
||||
default_prompt: "使用 $design-frontend 为当前需求制定前端页面设计。"
|
||||
|
||||
@@ -14,3 +14,6 @@ description: 基于项目现有流程引擎契约、业务状态和用户输入
|
||||
3. 设计业务事务与流程事务边界、幂等键、审计、通知和失败恢复。
|
||||
4. 需要过程建模时可参考 [官方来源](references/sources.md),但必须映射回项目真实引擎能力。
|
||||
5. 输出状态转换表、时序、异常路径、接口需求、数据需求和验收场景;未确认规则列为待确认。
|
||||
6. 用户要求保存设计文档时,读取 `.craftkit/project.json` 的 `documents` 配置选择过程或共享目录;先检索并更新已有权威流程设计,实质修改共享文档后按项目文档维护规范更新审核状态。
|
||||
|
||||
写入后在 `workRoot/<task>/task.json` 登记创建、更新或引用关系。已有文档属于其他任务时只登记关联,不取得删除权限;业务流程配置和脚本沿用项目源码约定。
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "工作流设计"
|
||||
display_name: "工作流设计(dev:design-workflow)"
|
||||
short_description: "设计状态、任务、权限和异常流程"
|
||||
default_prompt: "使用 $design-workflow 为当前业务设计可验证的工作流。"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "工作量评估"
|
||||
display_name: "工作量评估(dev:estimate)"
|
||||
short_description: "输出带假设和风险的软件工作量区间"
|
||||
default_prompt: "使用 $estimate 评估当前需求的工作量区间和风险。"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "表单设计"
|
||||
display_name: "表单设计(dev:form)"
|
||||
short_description: "设计和检查前端表单结构与响应布局"
|
||||
default_prompt: "使用 $form 为当前需求设计表单结构,并列出证据与待确认项。"
|
||||
|
||||
@@ -10,10 +10,12 @@ description: 按当前项目真实语言、框架版本、规范和现有实现
|
||||
## 工作流
|
||||
|
||||
1. 检查 Git 状态,保留用户已有改动;确认目标、范围和不可修改项。
|
||||
2. 读取 `AGENTS.md`、`.craftkit/project.json`,使用 `guidance` 获取项目规范,并从构建文件确认真实版本。
|
||||
3. 追踪入口、调用链、数据流、测试和相邻稳定实现;设计不足时先补最小决策,不套用固定模板。
|
||||
4. 实施最小完整变更,保持项目目录、依赖、异常、事务、日志和测试风格。
|
||||
5. 执行项目已有的编译、静态检查和相关测试,分别报告未执行的真实环境验证。
|
||||
2. 读取 `AGENTS.md`、`.craftkit/project.json`,从构建文件确认真实版本。已安装 `guidance` 时用它检索规范;未安装时按“目标目录适用的 `AGENTS.md` → `.craftkit/agents/index.md` → `.craftkit/standards/index.md` → 命中正文”的顺序手工读取,不因缺少另一插件中断实现。
|
||||
3. 按目标模块请求 `backend-implementation` 和 `command-resolution`;当前会话未发现语言提供方时继续使用通用实现流程并报告缺口,不扫描插件缓存。
|
||||
4. 追踪入口、调用链、数据流、测试和相邻稳定实现;检索相关需求、设计、规范和知识,设计不足时先补最小决策,不套用固定模板。
|
||||
5. 实施最小完整变更,保持项目目录、依赖、异常、事务、日志和测试风格。
|
||||
6. 检查本次接口、数据模型、业务行为和验证结论是否使长期文档过期;更新受影响的权威文档并登记到当前 `task.json`,不能完成时标为 `outdated` 并列入待办。
|
||||
7. 执行项目已有的编译、静态检查和相关测试,分别报告未执行的真实环境验证。
|
||||
|
||||
## 安全边界
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "后端实现"
|
||||
short_description: "按项目版本与规范实现后端代码变更"
|
||||
default_prompt: "使用 $implement-backend 实现并验证当前后端需求。"
|
||||
display_name: "后端实现(dev:implement-backend)"
|
||||
short_description: "实现后端变更并同步受影响的长期文档"
|
||||
default_prompt: "使用 $implement-backend 实现并验证当前后端需求,同时检查并更新受影响的长期文档。"
|
||||
|
||||
@@ -10,10 +10,11 @@ description: 按当前项目框架版本、组件契约、设计令牌和请求
|
||||
## 工作流
|
||||
|
||||
1. 检查 Git 状态并确认目标文件;从项目元数据、依赖和锁文件识别框架、构建工具及精确版本。
|
||||
2. 使用 `guidance` 获取规范,检查相邻页面和公共封装;组件、样式、表单分别消费 `component`、`style`、`form` 的证据。
|
||||
3. 有设计与接口映射时消费 `design-frontend` 和 `prepare-api`;没有时只补当前实现必需的最小决策。
|
||||
2. 已安装 `guidance` 时用它检索规范;未安装时按“目标目录适用的 `AGENTS.md` → `.craftkit/agents/index.md` → `.craftkit/standards/index.md` → 命中正文”的顺序手工读取。随后检查相邻页面和公共封装;组件、样式、表单分别消费 `component`、`style`、`form` 的证据。
|
||||
3. 检索相关需求、设计、规范和知识;有设计与接口映射时消费 `design-frontend` 和 `prepare-api`,没有时只补当前实现必需的最小决策。
|
||||
4. 修改页面、路由、状态和 API 层,保持项目现有契约,不虚构组件、props、事件、接口或业务校验。
|
||||
5. 执行已有格式化、类型检查、测试和构建;未进行真实渲染或浏览器验证时明确说明。
|
||||
5. 检查本次页面行为、接口字段、路由、状态和验证结论是否使长期文档过期;更新受影响的权威文档并登记到当前 `task.json`,不能完成时标为 `outdated` 并列入待办。
|
||||
6. 执行已有格式化、类型检查、测试和构建;未进行真实渲染或浏览器验证时明确说明。
|
||||
|
||||
## 安全边界
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "前端实现"
|
||||
short_description: "按项目框架与组件契约实现前端变更"
|
||||
default_prompt: "使用 $implement-frontend 实现并验证当前前端需求。"
|
||||
display_name: "前端实现(dev:implement-frontend)"
|
||||
short_description: "实现前端变更并同步受影响的长期文档"
|
||||
default_prompt: "使用 $implement-frontend 实现并验证当前前端需求,同时检查并更新受影响的长期文档。"
|
||||
|
||||
@@ -14,11 +14,13 @@ description: 分析软件需求或问题的现状、影响范围、依赖顺序
|
||||
3. 确认当前行为、目标行为、范围外事项、依赖、兼容要求和验收标准。
|
||||
4. 根据任务类型读取 [新功能](references/feature.md)、[现有变更](references/change.md) 或 [缺陷与重构](references/fix.md)。
|
||||
5. 输出按依赖排序的步骤,每步包含目标、证据、修改范围、输入、产物、验证和停止条件。
|
||||
6. 默认在对话中展示;用户要求保存时,先确认项目约定的路径再写入。
|
||||
6. 默认在对话中展示;用户要求保存时读取 `.craftkit/project.json` 的 `documents` 配置,过程计划使用 `workRoot`,共享计划使用 `designRoot`,后续设计沿用同一任务目录。
|
||||
|
||||
落盘前检索同主题的需求、设计、规范或知识,优先更新已有权威文档。共享长期文档新建或实质修改后按 `.craftkit/standards/document-maintenance.md` 更新审核状态;排版和错字修正不改变状态。`r`n`r`n写入后在 `workRoot/<task>/task.json` 登记本次创建、更新或引用的文档及 `relationship`;已有记录时保守合并。关联旧文档不转移所有权,也不产生删除权限;不修改项目级默认配置。
|
||||
|
||||
## 边界
|
||||
|
||||
- 不使用固定模块编码、固定文档目录或不存在的下游 Skill 名称。
|
||||
- 不使用固定模块编码或不存在的下游 Skill 名称;文档默认落点允许由用户路径和项目配置覆盖。
|
||||
- 无法从源码确认的运行行为标为待验证,不把推断写成事实。
|
||||
- 计划应保护现有工作区,并把外部环境、数据迁移和发布验证与本地代码验证分开。
|
||||
- 用户要求直接实施且任务简单明确时,不额外制造计划文档。
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "变更计划"
|
||||
display_name: "变更计划(dev:plan-change)"
|
||||
short_description: "基于项目证据制定可执行的软件变更计划"
|
||||
default_prompt: "使用 $plan-change 分析当前需求并制定可验证的实施计划。"
|
||||
|
||||
@@ -14,7 +14,9 @@ description: 对照前端需求或设计与现有 API 契约,整理接口清
|
||||
3. 按 [映射规则](references/mapping.md) 建立接口、请求、响应和双向类型转换映射。
|
||||
4. 分别列出已匹配、未匹配、冲突、缺失接口和需要后端或产品确认的事项。
|
||||
5. 按 [评审清单](references/review.md) 检查错误、分页、精度、时间、空值、权限和兼容风险。
|
||||
6. 默认在对话中输出;用户要求保存时,先确认项目约定路径再写入。
|
||||
6. 默认在对话中输出;用户要求保存时读取 `.craftkit/project.json` 的 `documents` 配置,过程映射使用 `workRoot`,共享映射使用 `designRoot`。
|
||||
|
||||
落盘前检索同主题的需求、设计、规范或知识,优先更新已有权威文档。共享长期文档新建或实质修改后按 `.craftkit/standards/document-maintenance.md` 更新审核状态;排版和错字修正不改变状态。`r`n`r`n写入后在 `workRoot/<task>/task.json` 登记本次创建、更新或引用的文档及 `relationship`;已有记录时保守合并。关联旧文档不转移所有权,也不产生删除权限;不修改项目级默认配置。
|
||||
|
||||
## 边界
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "接口准备"
|
||||
display_name: "接口准备(dev:prepare-api)"
|
||||
short_description: "整理前后端接口映射和契约差异"
|
||||
default_prompt: "使用 $prepare-api 分析前端需求与现有 API 契约的映射。"
|
||||
|
||||
@@ -5,7 +5,7 @@ description: 审查工作区、提交或分支中的代码变更,基于项目
|
||||
|
||||
# 代码审查
|
||||
|
||||
默认只读。先确认基线和范围,再读取差异、调用方、测试与适用规范;不得只凭补丁片段猜测运行行为。
|
||||
默认只读。先确认基线和范围,再读取差异、调用方、测试、适用规范及本次关联的需求和设计;不得只凭补丁片段猜测运行行为。
|
||||
|
||||
## 模式
|
||||
|
||||
@@ -13,4 +13,6 @@ description: 审查工作区、提交或分支中的代码变更,基于项目
|
||||
- 提交:审查指定提交及其父提交差异。
|
||||
- 分支:使用明确基线审查提交范围和最终差异。
|
||||
|
||||
按严重度输出可操作问题,每项包含文件、位置、触发条件、影响和最小修复方向。没有问题时说明检查范围和未验证边界。审查不自动修复、暂存、提交或推送;静态审查不等同于测试和真实环境验收。
|
||||
按严重度输出可操作问题,每项包含文件、位置、触发条件、影响和最小修复方向。审核实现与当前有效文档是否一致,并检查本次变更影响的长期文档是否已更新;`pending`、`outdated`、缺少状态和历史归档分别如实报告,不能把历史材料当作当前依据。
|
||||
|
||||
没有问题时说明检查范围和未验证边界。审查不自动修改文档、代码、审核状态、暂存、提交或推送;静态审查不等同于测试、文档批准和真实环境验收。
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "代码审查"
|
||||
short_description: "审查工作区、提交或分支的代码变更"
|
||||
default_prompt: "使用 $review-code 审查当前代码变更并按严重度报告问题。"
|
||||
display_name: "代码审查(dev:review-code)"
|
||||
short_description: "审查代码质量及实现与有效文档的一致性"
|
||||
default_prompt: "使用 $review-code 审查当前代码变更、相关文档同步情况,并按严重度报告问题。"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "前端审查"
|
||||
display_name: "前端审查(dev:review-frontend)"
|
||||
short_description: "按项目框架版本专项审查前端代码"
|
||||
default_prompt: "使用 $review-frontend 按当前框架版本审查前端代码。"
|
||||
|
||||
@@ -10,7 +10,8 @@ description: 按项目 Java 版本、框架、规范和真实调用上下文评
|
||||
## 工作流
|
||||
|
||||
1. 确认审查范围、版本、框架、编译选项和相关测试。
|
||||
2. 检查类型与空值、异常边界、资源关闭、集合、并发、序列化和公开契约。
|
||||
3. 语言结论按 [官方来源](references/sources.md) 路由到当前版本;预览特性不得视为默认可用。
|
||||
4. 只报告可复现、有代码证据且影响明确的问题,按严重度给出最小修复建议。
|
||||
5. 未运行编译或测试时明确说明,不自动修改代码。
|
||||
2. 当前会话发现 `java:profile` 时请求 `language-review`,由提供方读取自身资料;未发现时继续使用本 Skill 的最小基线并报告缺口。
|
||||
3. 检查类型与空值、异常边界、资源关闭、集合、并发、序列化和公开契约。
|
||||
4. 语言结论按 [官方来源](references/sources.md) 路由到当前版本;预览特性不得视为默认可用。
|
||||
5. 只报告可复现、有代码证据且影响明确的问题,按严重度给出最小修复建议。
|
||||
6. 未运行编译或测试时明确说明,不自动修改代码。
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "Java 审查"
|
||||
display_name: "Java 审查(dev:review-java)"
|
||||
short_description: "按项目版本专项审查 Java 代码"
|
||||
default_prompt: "使用 $review-java 按当前项目版本审查这段 Java 代码。"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "MyBatis 审查"
|
||||
display_name: "MyBatis 审查(dev:review-mybatis)"
|
||||
short_description: "专项审查映射、动态 SQL 和查询边界"
|
||||
default_prompt: "使用 $review-mybatis 审查当前 MyBatis Mapper 与 SQL。"
|
||||
|
||||
@@ -13,7 +13,7 @@ description: 基于当前项目的设计令牌、主题、页面和用户参考
|
||||
2. 按 [来源优先级](references/sources.md) 确定现有设计权威与用户参考的关系。
|
||||
3. 识别需要继承、补充或覆盖的颜色、排版、间距、圆角、阴影、断点和交互状态。
|
||||
4. 按 [输出约定](references/output.md) 给出规范或样式修改,并说明未验证风险。
|
||||
5. 需要写入 `.craftkit/standards/frontend/design.md` 时,先展示拟写内容和合并策略,经用户确认后再修改。
|
||||
5. 需要写入 `.craftkit/standards/frontend/design.md` 时,先读取原文并展示拟写内容和合并策略,经用户确认后更新;实质修改按项目文档维护规范重新审核。
|
||||
|
||||
如果项目没有视觉基线,先询问用户是否有设计稿、截图或参考项目;输入仍不足时只给出待确认项,不擅自确定品牌风格。
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "样式设计"
|
||||
display_name: "样式设计(dev:style)"
|
||||
short_description: "延续项目视觉语言并设计前端样式"
|
||||
default_prompt: "使用 $style 基于当前项目视觉基线设计或调整样式。"
|
||||
|
||||
@@ -5,6 +5,8 @@ description: 按当前项目测试框架为后端代码设计、生成、修改
|
||||
|
||||
# 后端测试
|
||||
|
||||
从构建文件和现有测试确认框架、版本、目录和运行方式。优先选择不启动完整应用即可验证业务规则的最小测试层级;只有集成边界确实需要时才加载框架上下文。
|
||||
从构建文件和现有测试确认框架、版本、目录和运行方式。按目标模块请求 `backend-testing` 和 `command-resolution`;当前会话未发现语言提供方时使用通用测试原则并报告缺口,不扫描插件缓存。优先选择不启动完整应用即可验证业务规则的最小测试层级;只有集成边界确实需要时才加载框架上下文。
|
||||
|
||||
测试应覆盖可观察行为,不绑定私有实现;外部依赖使用项目已有隔离方式,不连接真实生产资源。运行聚焦测试后分别报告通过、失败、未执行和环境阻塞。新增依赖、修改业务代码、删除既有测试或运行需要真实服务的测试必须先说明并取得相应授权。
|
||||
|
||||
Profile 返回的命令只是候选。只有项目脚本、构建文件、CI 配置或用户确认支持时才执行;不得因公共 Profile 自动新增测试依赖。
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "后端测试"
|
||||
display_name: "后端测试(dev:test-backend)"
|
||||
short_description: "生成并运行聚焦的后端自动化测试"
|
||||
default_prompt: "使用 $test-backend 为当前后端变更补充并运行聚焦测试。"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "UI 测试"
|
||||
display_name: "UI 测试(dev:test-ui)"
|
||||
short_description: "设计并执行用户行为导向的页面测试"
|
||||
default_prompt: "使用 $test-ui 为当前页面制定测试计划并在条件允许时执行。"
|
||||
|
||||
@@ -7,4 +7,4 @@ description: 规划并实施前端、后端或依赖的大版本升级,基于
|
||||
|
||||
升级前必须确认当前版本、目标版本、支持矩阵、运行环境、锁文件和回滚要求。只读取对应产品的官方迁移指南、发行说明和弃用清单,并记录访问日期;不得使用来源插件的内部升级矩阵。
|
||||
|
||||
先输出依赖差异、破坏性变化、代码与配置影响、数据或构建迁移、验证矩阵和回滚点。用户确认实施后分小步修改,每步运行项目已有检查。新增依赖下载或访问网络按环境授权执行。环境配置、生产数据、部署、提交、标签和推送均不在默认授权内。
|
||||
先输出依赖差异、破坏性变化、代码与配置影响、数据或构建迁移、验证矩阵和回滚点,并检索会被版本变化影响的长期设计、规范和知识。用户确认实施后分小步修改,每步运行项目已有检查,同步更新受影响的权威文档并按项目文档维护规范重新审核;不能完成时标为 `outdated`。新增依赖下载或访问网络按环境授权执行。环境配置、生产数据、部署、提交、标签和推送均不在默认授权内。
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "版本升级"
|
||||
display_name: "版本升级(dev:upgrade)"
|
||||
short_description: "基于官方迁移资料执行可回滚升级"
|
||||
default_prompt: "使用 $upgrade 评估并实施当前项目的版本升级。"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "doc",
|
||||
"version": "0.3.0",
|
||||
"version": "0.4.0",
|
||||
"description": "通用文档转换、表格提取、规则化归档与写作工具。",
|
||||
"author": {
|
||||
"name": "CraftKit"
|
||||
|
||||
@@ -27,6 +27,7 @@ python scripts/archive.py --root <project> --config <rules.json> --apply [--repo
|
||||
- 专有文档拆分逻辑改为通用 Markdown 标题章节抽取。
|
||||
- 内部数据库或服务校验改为显式 `requiredText` 内容校验;需要外部事实时由用户先提供结果,不隐式连接系统。
|
||||
- 来源专属元数据清理改为可选 `stripFrontmatter`,不会默认删除内容。
|
||||
- 历史归档保留当时快照并标明归档用途;它不作为当前有效依据。发现错误时增加勘误或当前版本链接,不静默改写历史内容。
|
||||
|
||||
## 安全边界
|
||||
|
||||
@@ -37,3 +38,5 @@ python scripts/archive.py --root <project> --config <rules.json> --apply [--repo
|
||||
- 规则不执行 Shell、SQL、模板代码或网络请求。
|
||||
|
||||
完整配置见 `references/config.md`。
|
||||
|
||||
当归档由任务关闭流程触发时,只复制 `task.json` 中标记为 `archive` 的文件。归档成功后将来源交回关闭流程重新分类;本 Skill 仍不删除来源,也不直接把来源标记为删除,实际删除只能由 `knowledge:document-output close` 按已确认清单执行。
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "Archive Documents"
|
||||
short_description: "按项目规则安全预演并归档文档"
|
||||
display_name: "Archive Documents(doc:archive)"
|
||||
short_description: "归档历史快照并关联当前有效版本"
|
||||
default_prompt: "使用 $archive 根据项目规则预演文档归档,确认后再执行写入。"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "DOCX to Markdown"
|
||||
display_name: "DOCX to Markdown(doc:docx-to-md)"
|
||||
short_description: "将 Word 文档转换为 Markdown 并提取图片"
|
||||
default_prompt: "使用 $docx-to-md 将这份 Word 文档转换为 Markdown,并报告转换警告。"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "Format Markdown"
|
||||
display_name: "Format Markdown(doc:format-md)"
|
||||
short_description: "整理 Markdown 排版并严格保持原文语义不变"
|
||||
default_prompt: "使用 $format-md 整理这份 Markdown 文件的排版,不改写内容。"
|
||||
|
||||
@@ -12,7 +12,8 @@ description: 将 Markdown 文档转换为 Word .docx,保留常见标题、段
|
||||
- 只接受存在的 `.md` 或 `.markdown` 文件。
|
||||
- 默认在输入文件旁生成同名 `.docx`;文件已存在时停止,只有用户明确同意覆盖后才传入 `--force`。
|
||||
- 用户提供 `.docx` 模板时可传入 `--template`,转换器沿用模板样式并在文档末尾追加内容,不替换模板中的占位符。
|
||||
- 不自动下载图片、字体或依赖;远程图片保留为文字提示,本地缺失图片产生警告。
|
||||
- 转换依赖 Python 包 `python-docx`。优先使用 Codex 工作区依赖运行时;环境缺失时停止并给出提示,不自动安装依赖。
|
||||
- 不自动下载图片或字体;远程图片保留为文字提示,本地缺失图片产生警告。
|
||||
- 不伪造修订记录、批注或目录。需要人工审阅留痕时应使用独立的文档修订流程。
|
||||
|
||||
## 转换流程
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "Markdown to DOCX"
|
||||
display_name: "Markdown to DOCX(doc:md-to-docx)"
|
||||
short_description: "将 Markdown 转换为结构清晰的 Word 文档"
|
||||
default_prompt: "使用 $md-to-docx 将这份 Markdown 转换为 Word,并报告降级内容。"
|
||||
|
||||
@@ -9,10 +9,6 @@ import sys
|
||||
from dataclasses import dataclass, field
|
||||
from pathlib import Path
|
||||
|
||||
from docx import Document
|
||||
from docx.shared import Inches, Pt
|
||||
|
||||
|
||||
@dataclass
|
||||
class Result:
|
||||
"""记录生成物与转换统计。"""
|
||||
@@ -43,6 +39,10 @@ class Converter:
|
||||
"""使用可预测的小型解析器转换常见 Markdown。"""
|
||||
|
||||
def __init__(self, source: Path, output: Path, template: Path | None) -> None:
|
||||
# 第三方库在真正转换时才加载,使 --help、参数错误和能力探测不依赖本机预装包。
|
||||
from docx import Document
|
||||
|
||||
self.document_type = Document
|
||||
self.source = source
|
||||
self.doc = Document(template) if template else Document()
|
||||
self.result = Result(output)
|
||||
@@ -61,12 +61,14 @@ class Converter:
|
||||
self.add_line(lines[index])
|
||||
index += 1
|
||||
self.doc.save(self.result.output)
|
||||
Document(self.result.output)
|
||||
self.document_type(self.result.output)
|
||||
return self.result
|
||||
|
||||
def add_code(self, lines: list[str], start: int) -> int:
|
||||
"""读取围栏代码块;未闭合时输出其余内容并记录警告。"""
|
||||
|
||||
from docx.shared import Pt
|
||||
|
||||
index = start + 1
|
||||
content: list[str] = []
|
||||
while index < len(lines) and not lines[index].lstrip().startswith("```"):
|
||||
@@ -101,6 +103,8 @@ class Converter:
|
||||
def add_line(self, line: str) -> None:
|
||||
"""识别标题、列表、引用、分隔线和普通段落。"""
|
||||
|
||||
from docx.shared import Inches
|
||||
|
||||
value = line.strip()
|
||||
if not value:
|
||||
return
|
||||
@@ -158,6 +162,8 @@ class Converter:
|
||||
def add_image(self, paragraph, alt: str, target: str) -> None:
|
||||
"""只处理本地图片,防止转换过程产生隐式网络访问。"""
|
||||
|
||||
from docx.shared import Inches
|
||||
|
||||
if re.match(r"^[a-z][a-z0-9+.-]*://", target, re.I):
|
||||
paragraph.add_run(f"[远程图片:{alt or target}]")
|
||||
self.result.warnings.append(f"未下载远程图片:{target}")
|
||||
@@ -193,9 +199,22 @@ def main(argv: list[str] | None = None) -> int:
|
||||
print("错误:输出必须是可写的 .docx;覆盖需使用 --force", file=sys.stderr); return 1
|
||||
if template and (not template.is_file() or template.suffix.lower() != ".docx"):
|
||||
print("错误:模板必须是存在的 .docx 文件", file=sys.stderr); return 2
|
||||
try:
|
||||
converter = Converter(source, output, template)
|
||||
except ModuleNotFoundError as error:
|
||||
if error.name == "docx":
|
||||
print(
|
||||
"错误:缺少 python-docx。请使用 Codex 工作区依赖运行时,"
|
||||
"或在已获授权的本地 Python 环境中安装 python-docx 后重试。",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return 3
|
||||
raise
|
||||
except (OSError, ValueError) as error:
|
||||
print(f"错误:{error}", file=sys.stderr); return 1
|
||||
output.parent.mkdir(parents=True, exist_ok=True)
|
||||
try:
|
||||
result = Converter(source, output, template).convert()
|
||||
result = converter.convert()
|
||||
except (OSError, ValueError) as error:
|
||||
print(f"错误:{error}", file=sys.stderr); return 1
|
||||
print(f"DOCX:{result.output}")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "项目消息"
|
||||
display_name: "项目消息(doc:message)"
|
||||
short_description: "起草清晰可执行的项目通知与提醒"
|
||||
default_prompt: "使用 $message 把这些事实整理成一条项目通知。"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "工作汇报"
|
||||
display_name: "工作汇报(doc:report)"
|
||||
short_description: "基于事实撰写面向不同受众的汇报"
|
||||
default_prompt: "使用 $report 根据这些事实整理一份简洁工作汇报。"
|
||||
|
||||
@@ -7,4 +7,6 @@ description: 将技术说明、问题描述、会议材料或现有实现整理
|
||||
|
||||
保留输入事实与来源,区分当前行为、期望行为、建议和待确认项。先识别角色、场景、触发条件、主流程、异常流程、数据、权限、兼容和范围外事项,再生成可测试的验收标准。
|
||||
|
||||
技术实现细节只有在构成真实约束时才保留;不能从代码结构反推业务意图。冲突、模糊词、缺失规则和不可测试表述进入疑问清单。默认在对话中展示,用户确认后才写入项目文档。
|
||||
技术实现细节只有在构成真实约束时才保留;不能从代码结构反推业务意图。冲突、模糊词、缺失规则和不可测试表述进入疑问清单。默认在对话中展示;用户要求保存时先展示待确认内容,再读取 `.craftkit/project.json` 的 `documents` 配置,过程需求使用 `workRoot`,共享需求使用 `designRoot`。
|
||||
|
||||
落盘前检索同主题的需求、设计、规范或知识,优先更新已有权威文档。共享长期文档新建或实质修改后按 `.craftkit/standards/document-maintenance.md` 更新审核状态;排版和错字修正不改变状态。`r`n`r`n写入后在 `workRoot/<task>/task.json` 登记本次创建、更新或引用的文档及 `relationship`;已有记录时保守合并。关联旧文档不转移所有权,也不产生删除权限;不修改项目级默认配置。
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "需求整理"
|
||||
short_description: "将技术输入整理为可确认的需求说明"
|
||||
default_prompt: "使用 $requirements 将这些材料整理成需求和疑问清单。"
|
||||
display_name: "需求整理(doc:requirements)"
|
||||
short_description: "创建或更新可审核的需求说明"
|
||||
default_prompt: "使用 $requirements 查找并更新已有需求,或将这些材料整理成新的需求和疑问清单。"
|
||||
|
||||
@@ -13,7 +13,8 @@ description: 将 Excel .xlsx 工作簿转换为 Markdown,按工作表提取表
|
||||
- 默认保留公式文本;只有用户希望读取工作簿内已有缓存值时才使用 `--values`。转换器不会计算公式。
|
||||
- 合并单元格默认将锚点值填充到合并区域,可用 `--merged anchor` 仅保留左上角值。
|
||||
- 默认在输入文件旁生成同名 `.md`,已存在时停止;覆盖必须获得用户确认并传入 `--force`。
|
||||
- 不提取宏、图表、批注、数据验证、条件格式或图片,也不自动安装依赖。
|
||||
- 转换依赖 Python 包 `openpyxl`。优先使用 Codex 工作区依赖运行时;环境缺失时停止并给出提示,不自动安装依赖。
|
||||
- 不提取宏、图表、批注、数据验证、条件格式或图片。
|
||||
|
||||
## 工作流
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "XLSX to Markdown"
|
||||
display_name: "XLSX to Markdown(doc:xlsx-to-md)"
|
||||
short_description: "将 Excel 工作簿按工作表转换为 Markdown"
|
||||
default_prompt: "使用 $xlsx-to-md 将这个 Excel 工作簿转换为 Markdown,并说明公式和合并单元格策略。"
|
||||
|
||||
@@ -5,12 +5,10 @@ from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import datetime as dt
|
||||
import importlib.util
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
from openpyxl import load_workbook
|
||||
|
||||
|
||||
def display(value: object) -> str:
|
||||
"""将单元格值转换为稳定、可读且适合表格的文本。"""
|
||||
|
||||
@@ -59,6 +57,9 @@ def render_sheet(title: str, rows: list[list[str]]) -> str:
|
||||
def convert(source: Path, output: Path, values_only: bool, merged_mode: str) -> tuple[int, int, int, list[str]]:
|
||||
"""打开工作簿、转换全部工作表并写入 UTF-8 Markdown。"""
|
||||
|
||||
# 第三方库在真正读取工作簿时才加载,使 --help 和参数校验可在干净环境中执行。
|
||||
from openpyxl import load_workbook
|
||||
|
||||
workbook = load_workbook(source, read_only=False, data_only=values_only)
|
||||
sections = [f"# {source.stem}"]
|
||||
row_count = merged_count = 0
|
||||
@@ -94,9 +95,26 @@ def main(argv: list[str] | None = None) -> int:
|
||||
print("错误:输出文件必须是 Markdown", file=sys.stderr); return 2
|
||||
if output.exists() and not args.force:
|
||||
print(f"错误:输出文件已存在:{output}", file=sys.stderr); return 1
|
||||
# 在创建输出目录前完成依赖预检,保证缺少运行库时不会留下空目录或半成品。
|
||||
if importlib.util.find_spec("openpyxl") is None:
|
||||
print(
|
||||
"错误:缺少 openpyxl。请使用 Codex 工作区依赖运行时,"
|
||||
"或在已获授权的本地 Python 环境中安装 openpyxl 后重试。",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return 3
|
||||
output.parent.mkdir(parents=True, exist_ok=True)
|
||||
try:
|
||||
sheets, rows, merged, warnings = convert(source, output, args.values, args.merged)
|
||||
except ModuleNotFoundError as error:
|
||||
if error.name == "openpyxl":
|
||||
print(
|
||||
"错误:缺少 openpyxl。请使用 Codex 工作区依赖运行时,"
|
||||
"或在已获授权的本地 Python 环境中安装 openpyxl 后重试。",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return 3
|
||||
raise
|
||||
except (OSError, ValueError) as error:
|
||||
print(f"错误:{error}", file=sys.stderr); return 1
|
||||
print(f"Markdown:{output}")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "git",
|
||||
"version": "0.4.0",
|
||||
"version": "0.5.2",
|
||||
"description": "安全、可复核的通用 Git 工作流。",
|
||||
"author": {
|
||||
"name": "CraftKit"
|
||||
|
||||
@@ -1,18 +1,25 @@
|
||||
---
|
||||
name: branch
|
||||
description: 根据当前仓库约定生成名称,并在用户确认准确命令后创建和切换本地 Git 分支。适用于明确要求新建分支的场景;仅查看、重命名、删除、合并、推送或发布分支不应触发本 Skill。
|
||||
description: 根据当前仓库约定,在用户确认后于当前工作区或独立 worktree 创建本地 Git 分支,并在分支任务结束后安全关闭额外 worktree。适用于新增需求、缺陷、维护分支及解除 worktree 分支占用;仅查看、重命名、删除、合并、推送或发布分支不应触发本 Skill。
|
||||
---
|
||||
|
||||
# 创建 Git 分支
|
||||
|
||||
安全地创建并切换本地分支。所有检查默认只读;`fetch` 和分支创建分别需要明确授权,不得把它们合并为一次隐含操作。
|
||||
安全地创建本地分支并管理其独立 worktree 生命周期。所有检查默认只读;`fetch`、分支创建和 worktree 移除分别需要明确授权,不得把它们合并为一次隐含操作。
|
||||
|
||||
## 选择模式
|
||||
|
||||
- `create`:规划名称,并在当前工作区或独立 worktree 创建分支。
|
||||
- `close`:分支任务结束后安全移除额外 worktree,释放分支占用。
|
||||
|
||||
涉及独立 worktree 时读取 [Worktree 分支规则](references/worktree-branch.md)。用户只说“创建分支”时进入 `create`;用户要求结束、关闭、清理额外 worktree,或出现分支已被 worktree 占用错误时进入 `close`。
|
||||
|
||||
## 创建前检查
|
||||
|
||||
1. 运行 `git status --short --branch`、`git branch --show-current`、`git branch --list`、`git branch --remotes` 和 `git worktree list --porcelain`。
|
||||
2. 读取当前仓库适用的 `AGENTS.md`、贡献指南或其他明确的分支约定;没有约定时再参考现有分支命名。
|
||||
3. 收集分支用途、简短描述和基准引用。不要默认 `main`、`master`、远程名称、版本分支或合并目标。
|
||||
4. 若工作区不干净,说明现有修改会随切换保留;在用户明确选择继续前不得创建分支,也不得自动暂存、提交、还原或清理。
|
||||
4. 若工作区不干净,列出现有修改并说明直接切换会携带这些修改;不得自动暂存、提交、还原或清理,优先建议使用独立 worktree。
|
||||
5. `.craftkit/local/**` 和 `.craftkit/cache/**` 不视为业务改动;若它们出现在普通状态中,提示检查 `.craftkit/.gitignore`。`.craftkit/agents/**`、`standards/**`、`knowledge/**`、`handoff/**` 和 `project.json` 属于普通项目改动,应与其他未提交内容一起展示。
|
||||
|
||||
## 生成和验证名称
|
||||
@@ -34,9 +41,11 @@ description: 根据当前仓库约定生成名称,并在用户确认准确命
|
||||
- 当前分支和工作区状态;
|
||||
- 目标分支名称;
|
||||
- 基准引用及其提交短哈希;
|
||||
- 是否会携带未提交修改;
|
||||
- 在当前工作区还是独立 worktree 创建,以及是否影响未提交修改;
|
||||
- 将执行的唯一创建命令。
|
||||
|
||||
工作区干净、当前 checkout 可以切换且用户没有隔离要求时,可以在当前工作区创建。工作区不干净、当前分支被 IDE/服务/测试占用,或用户要求不影响当前 checkout 时,使用独立 worktree;创建前确认目标绝对路径不存在、分支不存在且基准哈希已锁定。
|
||||
|
||||
本地基准使用:
|
||||
|
||||
```text
|
||||
@@ -49,10 +58,16 @@ git switch -c "<branch>" "<base>"
|
||||
git switch --no-track -c "<branch>" "<remote>/<base>"
|
||||
```
|
||||
|
||||
独立 worktree 使用:
|
||||
|
||||
```text
|
||||
git worktree add -b "<branch>" "<absolute-worktree-path>" "<base>"
|
||||
```
|
||||
|
||||
只有用户在看到上述最终信息后明确确认,才执行该命令。用户调整名称或基准后必须重新展示并确认。
|
||||
|
||||
## 创建后验证
|
||||
|
||||
运行 `git branch --show-current`、`git rev-parse --short HEAD` 和 `git status --short --branch`,确认当前分支、起点和工作区状态。远程基准创建时再用 `git rev-parse --abbrev-ref --symbolic-full-name @{upstream}` 检查没有错误 upstream;命令返回“无 upstream”属于预期结果。
|
||||
在实际创建位置运行 `git branch --show-current`、`git rev-parse --short HEAD` 和 `git status --short --branch`,确认当前分支、起点和工作区状态。独立 worktree 创建后还要复核主工作区分支、HEAD 和未提交内容未变化,并明确报告分支占用路径、后续操作目录以及生命周期结束后的清理义务。远程基准创建时再用 `git rev-parse --abbrev-ref --symbolic-full-name @{upstream}` 检查没有错误 upstream;命令返回“无 upstream”属于预期结果。
|
||||
|
||||
本 Skill 到此结束,不执行 push、不设置远程 upstream,也不创建合并请求。失败时报告原始错误和当前仓库状态,不自动重试破坏性替代命令。
|
||||
`create` 到此不执行 push、不设置远程 upstream,也不创建合并请求。独立 worktree 在分支任务完成前保持 `active`,完成后必须调用 `close` 进入清理门禁。失败时报告原始错误和当前仓库状态,不自动重试破坏性替代命令。
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "Create Branch"
|
||||
short_description: "确认名称和基准后安全创建本地 Git 分支"
|
||||
default_prompt: "使用 $branch 为当前仓库规划并创建一个本地分支,执行前先向我确认。"
|
||||
display_name: "Create Branch(git:branch)"
|
||||
short_description: "创建分支并管理独立 Worktree 的安全关闭"
|
||||
default_prompt: "使用 $branch 规划并创建本地分支;工作区不干净时使用独立 worktree,分支任务结束后安全关闭它,所有写操作前先向我确认。"
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
# Worktree 分支规则
|
||||
|
||||
## 创建条件
|
||||
|
||||
满足任一条件时,优先在独立 worktree 创建新需求、缺陷或维护分支,不切换当前主工作区:
|
||||
|
||||
- 主工作区存在未提交文件、本地配置、环境配置或缓存;
|
||||
- 用户要求不影响当前 checkout;
|
||||
- 当前分支正被 IDE、服务或测试占用;
|
||||
- 当前工作需要与主工作区并行进行。
|
||||
|
||||
Worktree 共享仓库对象和本地分支引用。同一个本地分支不能同时被两个 worktree 签出。
|
||||
|
||||
## 创建前检查
|
||||
|
||||
确认主仓库绝对路径、目标 worktree 绝对路径、分支名、基准引用和完整哈希。检查目标路径不存在、同名本地及远程引用的处理已经确认、目标分支未被其他 worktree 占用。分支名可能包含中文时始终加引号。
|
||||
|
||||
取得分支创建授权后执行唯一命令:
|
||||
|
||||
```text
|
||||
git worktree add -b "<branch>" "<absolute-worktree-path>" "<base>"
|
||||
```
|
||||
|
||||
创建后验证新 worktree 的分支、HEAD 和状态,并重新检查主工作区分支、HEAD 和未提交内容未变化。报告该分支的占用路径,提示主工作区不能同时签出,并记录任务完成后的清理义务。
|
||||
|
||||
## 关闭条件
|
||||
|
||||
创建分支的当次操作完成不等于 worktree 生命周期结束。只有分支开发任务、验证和用户要求的交付已经完成,并且用户不再要求保留现场时,才进入 `close`。
|
||||
|
||||
关闭前必须满足:
|
||||
|
||||
- worktree 没有未提交或未跟踪文件;
|
||||
- 没有进行中的 merge、rebase、cherry-pick 或 revert;
|
||||
- 当前 HEAD 已被预期本地分支引用;
|
||||
- 主仓库、worktree 路径、分支和 HEAD 均已准确确认。
|
||||
|
||||
还要读取 `.craftkit/project.json` 的 `documents.workRoot`,检查该 Worktree 中与本分支任务对应的 `task.json` 和 ignored 文件。任务状态未到 `closed`、存在未登记的忽略文件或关闭清单尚未处理时,先执行 `knowledge:document-output close` 预览;用户要求保留现场时不得移除 Worktree。
|
||||
|
||||
展示检查结果、移除后保留的分支和唯一清理命令,取得用户确认后执行:
|
||||
|
||||
```text
|
||||
git -C "<main-repository>" worktree remove "<absolute-worktree-path>"
|
||||
```
|
||||
|
||||
不得直接删除目录,不得默认使用 `--force`,不得删除或重置分支,也不得批量清理其他 worktree。
|
||||
|
||||
## 关闭后验证
|
||||
|
||||
```text
|
||||
Test-Path -LiteralPath "<absolute-worktree-path>"
|
||||
git -C "<main-repository>" rev-parse --verify "<branch>"
|
||||
git -C "<main-repository>" worktree list --porcelain
|
||||
git -C "<main-repository>" status --short --branch
|
||||
```
|
||||
|
||||
目录不存在、占用记录已释放、分支和提交仍存在、主工作区原有状态未变化时,关闭才算完成。
|
||||
|
||||
## 分支占用错误
|
||||
|
||||
```text
|
||||
fatal: '<branch>' is already used by worktree at '<path>'
|
||||
```
|
||||
|
||||
该错误表示分支仍由指定 worktree 签出。若任务仍在进行,继续在该 worktree 中操作;若任务已经结束,执行 `close`。不得强制 checkout、直接删除目录或删除分支绕过占用保护。
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "Commit Message"
|
||||
display_name: "Commit Message(git:commit-msg)"
|
||||
short_description: "只读分析 Git 变更并生成可复核的提交信息"
|
||||
default_prompt: "使用 $commit-msg 分析当前 Git 变更并建议提交信息,不要暂存或提交。"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "Export Git Changes"
|
||||
display_name: "Export Git Changes(git:export)"
|
||||
short_description: "预览并安全导出 Git 变更文件和分类清单"
|
||||
default_prompt: "使用 $export 预览这批 Git 变更,排除环境配置后再导出交付快照。"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
interface:
|
||||
display_name: "Git Identity"
|
||||
display_name: "Git Identity(git:identity)"
|
||||
short_description: "查看并安全设置 Git 提交用户名和邮箱"
|
||||
default_prompt: "使用 $identity 检查当前 Git 提交身份,并在我确认后设置正确作用域。"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user