feat(skill): REQ-20260406-0004 技能三层分离重构(7主线+16插件)
批次1: req-prd 瘦身 + req-design 重定位 + dev-coding 聚焦 批次2: dev-review 新建 + review-checklist 插件 批次3: dev-integration 新建 + req-compare 拆出 批次4: 插件完善 (req-research/db-migration/dev-scaffold/deploy-rollback) 批次5: 平台拆分 (dev-ios/dev-android/dev-mcp/dev-pda) + dev 分组更新 批次6: marketplace.json 32→44 plugins Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "db-migration-plugin",
|
||||
"description": "数据库变更方案插件。Migration 脚本生成、数据迁移策略、回滚方案。挂载在 design 阶段,涉及数据库变更时激活。",
|
||||
"version": "1.0.0",
|
||||
"author": { "name": "qiudl" }
|
||||
}
|
||||
105
skills-dev/db-migration-plugin/skills/SKILL.md
Normal file
105
skills-dev/db-migration-plugin/skills/SKILL.md
Normal file
@@ -0,0 +1,105 @@
|
||||
---
|
||||
name: db-migration
|
||||
description: 数据库变更方案插件。Migration 脚本生成、数据迁移策略、回滚方案。挂载在 design 阶段,涉及数据库变更时由 req-design 推荐激活。
|
||||
---
|
||||
|
||||
# 数据库变更方案插件 (db-migration)
|
||||
|
||||
## 概述
|
||||
|
||||
当需求涉及数据库结构变更时使用,确保变更安全、可回滚。
|
||||
|
||||
**触发条件**:
|
||||
- 新增/修改/删除表或字段
|
||||
- 数据迁移(旧数据转换)
|
||||
- 索引优化
|
||||
|
||||
## Migration 规范
|
||||
|
||||
### 文件命名
|
||||
|
||||
```
|
||||
backend/migrations/YYYYMMDDHHMMSS_description.up.sql # 正向迁移
|
||||
backend/migrations/YYYYMMDDHHMMSS_description.down.sql # 回滚迁移
|
||||
```
|
||||
|
||||
### 安全规则
|
||||
|
||||
| 操作 | 风险等级 | 注意事项 |
|
||||
|------|---------|---------|
|
||||
| ADD COLUMN (nullable) | 低 | 安全,无锁表 |
|
||||
| ADD COLUMN (NOT NULL + DEFAULT) | 中 | PG 12+ 不锁表,旧版本锁表 |
|
||||
| DROP COLUMN | 高 | 确认无代码引用,先标记废弃 |
|
||||
| ALTER COLUMN TYPE | 高 | 可能锁表,大表慎用 |
|
||||
| ADD INDEX | 中 | 使用 CONCURRENTLY 避免锁表 |
|
||||
| DROP TABLE | 极高 | 必须确认无依赖 |
|
||||
|
||||
### Migration 模板
|
||||
|
||||
**新增表**:
|
||||
```sql
|
||||
-- up.sql
|
||||
CREATE TABLE IF NOT EXISTS xxx (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
tenant_id BIGINT NOT NULL,
|
||||
-- 业务字段
|
||||
name VARCHAR(255) NOT NULL,
|
||||
status VARCHAR(50) NOT NULL DEFAULT 'active',
|
||||
-- 审计字段
|
||||
created_by BIGINT,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
deleted_at TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE INDEX idx_xxx_tenant_id ON xxx(tenant_id);
|
||||
CREATE INDEX idx_xxx_deleted_at ON xxx(deleted_at);
|
||||
|
||||
-- down.sql
|
||||
DROP TABLE IF EXISTS xxx;
|
||||
```
|
||||
|
||||
**新增字段**:
|
||||
```sql
|
||||
-- up.sql
|
||||
ALTER TABLE xxx ADD COLUMN yyy VARCHAR(255);
|
||||
-- 如果需要索引
|
||||
CREATE INDEX CONCURRENTLY idx_xxx_yyy ON xxx(yyy);
|
||||
|
||||
-- down.sql
|
||||
DROP INDEX IF EXISTS idx_xxx_yyy;
|
||||
ALTER TABLE xxx DROP COLUMN IF EXISTS yyy;
|
||||
```
|
||||
|
||||
**数据迁移**:
|
||||
```sql
|
||||
-- up.sql
|
||||
-- 1. 先添加新字段
|
||||
ALTER TABLE xxx ADD COLUMN new_field VARCHAR(255);
|
||||
|
||||
-- 2. 迁移数据
|
||||
UPDATE xxx SET new_field = old_field WHERE new_field IS NULL;
|
||||
|
||||
-- 3. 添加约束(数据迁移完成后)
|
||||
ALTER TABLE xxx ALTER COLUMN new_field SET NOT NULL;
|
||||
|
||||
-- down.sql
|
||||
ALTER TABLE xxx ALTER COLUMN new_field DROP NOT NULL;
|
||||
ALTER TABLE xxx DROP COLUMN IF EXISTS new_field;
|
||||
```
|
||||
|
||||
## 大表变更策略
|
||||
|
||||
当表数据量 > 100 万行时:
|
||||
|
||||
1. **添加索引**:必须使用 `CREATE INDEX CONCURRENTLY`
|
||||
2. **修改字段类型**:分步执行(新增列→迁移数据→切换引用→删除旧列)
|
||||
3. **添加 NOT NULL**:先添加 DEFAULT,再 SET NOT NULL
|
||||
4. **数据迁移**:分批处理,每批 1000-10000 行
|
||||
|
||||
## 回滚检查
|
||||
|
||||
每个 Migration 必须有可执行的 down.sql:
|
||||
- [ ] down.sql 存在且语法正确
|
||||
- [ ] down.sql 可以完全撤销 up.sql 的变更
|
||||
- [ ] down.sql 不会丢失业务数据(除非是 DROP TABLE)
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "deploy-rollback-plugin",
|
||||
"description": "回滚方案插件。部署后发现问题时的回滚策略、数据修复、灰度回退。挂载在 deploy 阶段。",
|
||||
"version": "1.0.0",
|
||||
"author": { "name": "qiudl" }
|
||||
}
|
||||
102
skills-dev/deploy-rollback-plugin/skills/SKILL.md
Normal file
102
skills-dev/deploy-rollback-plugin/skills/SKILL.md
Normal file
@@ -0,0 +1,102 @@
|
||||
---
|
||||
name: deploy-rollback
|
||||
description: 回滚方案插件。部署后发现问题时的回滚策略和执行步骤。挂载在 deploy 阶段,部署出问题时激活。
|
||||
---
|
||||
|
||||
# 回滚方案插件 (deploy-rollback)
|
||||
|
||||
## 概述
|
||||
|
||||
当生产部署后发现问题时,提供结构化的回滚决策和执行步骤。
|
||||
|
||||
**触发条件**:
|
||||
- 部署后健康检查失败
|
||||
- 部署后用户报告问题
|
||||
- 部署后监控告警
|
||||
|
||||
## 回滚决策树
|
||||
|
||||
```
|
||||
问题发现
|
||||
├── 服务完全不可用?
|
||||
│ └── YES → 立即回滚(紧急)
|
||||
├── 核心功能异常?
|
||||
│ └── YES → 评估影响范围 → 回滚或热修复
|
||||
├── 非核心功能异常?
|
||||
│ └── 评估修复时间
|
||||
│ ├── < 30 分钟 → 热修复
|
||||
│ └── > 30 分钟 → 回滚
|
||||
└── 性能下降?
|
||||
├── 严重(>5x) → 回滚
|
||||
└── 轻微(<2x) → 监控 + 排期修复
|
||||
```
|
||||
|
||||
## 回滚类型
|
||||
|
||||
### 1. Docker 镜像回滚(最常用)
|
||||
|
||||
```bash
|
||||
# 查看历史镜像
|
||||
docker images | grep ai-proj
|
||||
|
||||
# 回滚到上一版本
|
||||
cd deploy
|
||||
# 修改 docker-compose.prod.yml 中的镜像 tag
|
||||
docker compose -f docker-compose.prod.yml up -d
|
||||
|
||||
# 验证
|
||||
curl -s http://localhost:8080/health | jq .
|
||||
```
|
||||
|
||||
### 2. 数据库回滚
|
||||
|
||||
```bash
|
||||
# 执行 down migration
|
||||
cd backend
|
||||
migrate -path migrations -database "$DB_URL" down 1
|
||||
|
||||
# 验证表结构
|
||||
psql -U user -d db -c "\d affected_table"
|
||||
```
|
||||
|
||||
**注意**:数据库回滚可能导致数据丢失,必须先评估影响。
|
||||
|
||||
### 3. 配置回滚
|
||||
|
||||
```bash
|
||||
# 恢复旧配置
|
||||
git checkout HEAD~1 -- deploy/config/
|
||||
docker compose -f docker-compose.prod.yml restart
|
||||
```
|
||||
|
||||
## 回滚检查清单
|
||||
|
||||
- [ ] 确认问题现象和影响范围
|
||||
- [ ] 通知相关人员(用户需知道在维护中)
|
||||
- [ ] 执行回滚操作
|
||||
- [ ] 验证服务恢复正常
|
||||
- [ ] 验证数据完整性
|
||||
- [ ] 记录回滚原因和过程
|
||||
- [ ] 创建修复任务
|
||||
|
||||
## 回滚记录模板
|
||||
|
||||
```markdown
|
||||
## 回滚记录
|
||||
|
||||
**时间**: YYYY-MM-DD HH:mm
|
||||
**触发原因**: [问题描述]
|
||||
**影响范围**: [受影响的功能/用户]
|
||||
**回滚类型**: Docker 镜像 / 数据库 / 配置
|
||||
**回滚操作**: [具体步骤]
|
||||
**恢复确认**: [验证结果]
|
||||
**根因分析**: [问题根因]
|
||||
**修复计划**: [后续修复方案]
|
||||
```
|
||||
|
||||
## 预防措施
|
||||
|
||||
- 部署前确保 Migration 有 down.sql
|
||||
- 部署前确保 Docker 保留上一版本镜像
|
||||
- 大变更使用灰度发布
|
||||
- 监控关键指标(错误率、延迟、CPU/内存)
|
||||
1
skills-dev/dev-android-plugin/.claude-plugin/plugin.json
Normal file
1
skills-dev/dev-android-plugin/.claude-plugin/plugin.json
Normal file
@@ -0,0 +1 @@
|
||||
{"name":"dev-android-plugin","description":"Android 开发插件。Kotlin + Jetpack Compose + Hilt 依赖注入。按需加载。","version":"1.0.0","author":{"name":"qiudl"}}
|
||||
54
skills-dev/dev-android-plugin/skills/SKILL.md
Normal file
54
skills-dev/dev-android-plugin/skills/SKILL.md
Normal file
@@ -0,0 +1,54 @@
|
||||
---
|
||||
name: dev-android
|
||||
description: Android 开发插件。Kotlin + Jetpack Compose + Hilt 依赖注入。当涉及 Android 开发任务时按需加载。
|
||||
---
|
||||
|
||||
# Android 开发插件 (dev-android)
|
||||
|
||||
## 架构:MVVM + Hilt
|
||||
|
||||
```
|
||||
android-app/app/src/main/
|
||||
├── java/com/project/
|
||||
│ ├── ui/ # Compose 屏幕 + 组件
|
||||
│ ├── data/ # API + Repository + 本地存储
|
||||
│ ├── domain/ # 业务逻辑
|
||||
│ └── di/ # Hilt 依赖注入
|
||||
└── res/ # 资源文件
|
||||
```
|
||||
|
||||
## 代码规范
|
||||
|
||||
```kotlin
|
||||
@HiltViewModel
|
||||
class TaskViewModel @Inject constructor(
|
||||
private val taskRepository: TaskRepository
|
||||
) : ViewModel() {
|
||||
|
||||
private val _tasks = MutableStateFlow<List<Task>>(emptyList())
|
||||
val tasks: StateFlow<List<Task>> = _tasks.asStateFlow()
|
||||
|
||||
fun fetchTasks() {
|
||||
viewModelScope.launch {
|
||||
taskRepository.getTasks()
|
||||
.collect { _tasks.value = it }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TaskListScreen(viewModel: TaskViewModel = hiltViewModel()) {
|
||||
val tasks by viewModel.tasks.collectAsState()
|
||||
LazyColumn {
|
||||
items(tasks) { task -> TaskItem(task = task) }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 构建
|
||||
|
||||
```bash
|
||||
./gradlew assembleDebug # Debug 构建
|
||||
./gradlew assembleRelease # Release 构建
|
||||
./gradlew test # 测试
|
||||
```
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "dev-coding-plugin",
|
||||
"description": "Plugin for dev-coding",
|
||||
"version": "1.0.0",
|
||||
"description": "软件编码开发技能。Go 后端 + Vue/React 前端编码实现,集成 ai-proj 任务管理。",
|
||||
"version": "2.0.0",
|
||||
"author": {
|
||||
"name": "qiudl"
|
||||
}
|
||||
|
||||
@@ -1,43 +1,24 @@
|
||||
---
|
||||
name: dev-coding
|
||||
description: 软件编码开发技能。用于代码编写、功能实现、代码审查、重构优化。集成 ai-proj CLI 进行任务管理和进度跟踪。支持 Go、Vue、React、iOS、Android、小程序等全栈开发。
|
||||
description: 软件编码开发技能。用于代码编写、功能实现、重构优化。集成 ai-proj CLI 进行任务管理和进度跟踪。核心支持 Go 后端 + Vue/React 前端开发。
|
||||
---
|
||||
|
||||
# 软件编码开发 Skill (dev-coding)
|
||||
|
||||
## ⚠️ REQ 任务自动工作流
|
||||
|
||||
**当收到 REQ 任务(包含 REQ-YYYYMMDD-XXXX)需要开发时,必须严格按以下顺序执行:**
|
||||
|
||||
1. **读取 ticket** — 从 ai-proj 获取需求详情和关联文档
|
||||
```
|
||||
mcp__ai-proj-dev__get_detailed_task_info (通过 REQ 号查找)
|
||||
mcp__ai-proj-dev__get_task_document (如果有 PRD 文档)
|
||||
```
|
||||
|
||||
2. **进入 Plan Mode** — 调用 `EnterPlanMode` 工具
|
||||
- 分析需求,探索代码库,设计实现方案
|
||||
- 输出实现计划(涉及的文件、改动范围、测试策略)
|
||||
- 等待用户审批后再开始编码
|
||||
|
||||
3. **执行计划** — 用户批准后按计划编码 + 写测试
|
||||
|
||||
**禁止跳过 plan mode 直接编码。**
|
||||
|
||||
---
|
||||
|
||||
## 概述
|
||||
|
||||
本技能用于软件编码开发工作,支持多种项目类型:
|
||||
本技能用于软件编码实现,核心覆盖:
|
||||
- Go 后端 (Gin + GORM)
|
||||
- Vue 3 / React 前端
|
||||
- iOS (Swift/SwiftUI)
|
||||
- Android (Kotlin/Jetpack Compose)
|
||||
- PDA 应用
|
||||
- MCP 桥接服务
|
||||
- 微服务架构
|
||||
|
||||
核心集成 **ai-proj CLI** 进行任务管理。
|
||||
集成 **ai-proj CLI** 进行任务管理。
|
||||
|
||||
**不包含**(由其他技能/插件负责):
|
||||
- 开发设计(API 契约、任务拆分)→ `req-design`
|
||||
- 代码评审 → `dev-review`(批次2)
|
||||
- iOS 开发 → `dev-ios`(插件)
|
||||
- Android 开发 → `dev-android`(插件)
|
||||
- MCP 开发 → `dev-mcp`(插件)
|
||||
|
||||
---
|
||||
|
||||
@@ -84,11 +65,11 @@ ai-proj task append-doc --id <taskId> --content "实现说明"
|
||||
|
||||
### 当前项目生态
|
||||
|
||||
| 项目 | 类型 | 后端 | 前端 | 移动端 |
|
||||
|------|------|------|------|--------|
|
||||
| TWMS | 仓储物流 | Go+Gin+MySQL | Vue 3 | - |
|
||||
| AI-Proj | 项目管理 | Go+Gin+PostgreSQL | React 18 | iOS+Android |
|
||||
| DICIAI | 进销存SaaS | Go+Gin+MySQL | Vue 3 | Android PDA |
|
||||
| 项目 | 类型 | 后端 | 前端 |
|
||||
|------|------|------|------|
|
||||
| TWMS | 仓储物流 | Go+Gin+MySQL | Vue 3 |
|
||||
| AI-Proj | 项目管理 | Go+Gin+PostgreSQL | React 18 |
|
||||
| DICIAI | 进销存SaaS | Go+Gin+MySQL | Vue 3 |
|
||||
|
||||
---
|
||||
|
||||
@@ -349,309 +330,6 @@ npm run test:e2e
|
||||
|
||||
---
|
||||
|
||||
## iOS 开发 (Swift/SwiftUI)
|
||||
|
||||
### 项目结构
|
||||
|
||||
```
|
||||
AI-Proj-iOS/
|
||||
├── Core/ # 核心服务
|
||||
│ ├── Network/ # 网络层
|
||||
│ ├── Storage/ # 本地存储
|
||||
│ └── Auth/ # 认证
|
||||
├── Features/ # 功能模块
|
||||
│ ├── Dashboard/
|
||||
│ ├── Tasks/
|
||||
│ └── Settings/
|
||||
├── Models/ # 数据模型
|
||||
└── UI/ # UI 组件
|
||||
```
|
||||
|
||||
### 代码规范
|
||||
|
||||
```swift
|
||||
// MVVM 架构
|
||||
class TaskViewModel: ObservableObject {
|
||||
@Published var tasks: [Task] = []
|
||||
@Published var isLoading = false
|
||||
|
||||
private let taskService: TaskServiceProtocol
|
||||
|
||||
init(taskService: TaskServiceProtocol = TaskService()) {
|
||||
self.taskService = taskService
|
||||
}
|
||||
|
||||
func fetchTasks() async {
|
||||
isLoading = true
|
||||
defer { isLoading = false }
|
||||
|
||||
do {
|
||||
tasks = try await taskService.getTasks()
|
||||
} catch {
|
||||
// 错误处理
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SwiftUI 视图
|
||||
struct TaskListView: View {
|
||||
@StateObject private var viewModel = TaskViewModel()
|
||||
|
||||
var body: some View {
|
||||
List(viewModel.tasks) { task in
|
||||
TaskRow(task: task)
|
||||
}
|
||||
.task {
|
||||
await viewModel.fetchTasks()
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 构建命令
|
||||
|
||||
```bash
|
||||
# Xcode 构建
|
||||
xcodebuild -scheme AI-Proj-iOS -configuration Debug
|
||||
|
||||
# 测试
|
||||
xcodebuild test -scheme AI-Proj-iOS
|
||||
```
|
||||
|
||||
### 常见问题排查
|
||||
|
||||
#### SwiftLint 沙盒错误
|
||||
|
||||
**问题描述**:
|
||||
构建时出现错误:
|
||||
```
|
||||
Sandbox: swiftlint(xxxx) deny(1) file-read-data /path/to/.swiftlint.yml
|
||||
```
|
||||
|
||||
**原因**:
|
||||
Xcode 15+ 默认启用 User Script Sandboxing,限制脚本访问文件系统。
|
||||
|
||||
**解决方案**:
|
||||
|
||||
方案 1 - 修改项目配置(推荐):
|
||||
1. 打开 Xcode → 选择项目 → Build Settings
|
||||
2. 搜索 "User Script Sandboxing"
|
||||
3. 将 `ENABLE_USER_SCRIPT_SANDBOXING` 设置为 `NO`
|
||||
|
||||
方案 2 - 命令行构建时禁用:
|
||||
```bash
|
||||
xcodebuild -scheme AI-Proj-iOS -configuration Debug \
|
||||
ENABLE_USER_SCRIPT_SANDBOXING=NO
|
||||
```
|
||||
|
||||
方案 3 - 直接修改 project.pbxproj:
|
||||
```bash
|
||||
sed -i '' 's/ENABLE_USER_SCRIPT_SANDBOXING = YES/ENABLE_USER_SCRIPT_SANDBOXING = NO/g' \
|
||||
AI-Proj-iOS.xcodeproj/project.pbxproj
|
||||
```
|
||||
|
||||
#### Personal Development Team 功能限制
|
||||
|
||||
**问题描述**:
|
||||
使用免费 Personal Team 签名时报错:
|
||||
```
|
||||
Cannot create iOS App Development provisioning profile...
|
||||
Personal development teams do not support the Associated Domains,
|
||||
Push Notifications and App Groups capabilities.
|
||||
```
|
||||
|
||||
**原因**:
|
||||
Personal Team(免费账户)不支持以下 Entitlements:
|
||||
- Associated Domains (`com.apple.developer.associated-domains`)
|
||||
- Push Notifications (`aps-environment`)
|
||||
- App Groups (`com.apple.security.application-groups`)
|
||||
|
||||
**解决方案**:
|
||||
|
||||
1. 从 Entitlements 文件中移除不支持的功能:
|
||||
|
||||
```xml
|
||||
<!-- AI-Proj-iOS.entitlements -->
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<!-- 仅保留 Personal Team 支持的功能 -->
|
||||
<key>keychain-access-groups</key>
|
||||
<array>
|
||||
<string>$(AppIdentifierPrefix)com.yourcompany.app</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
2. Personal Team 支持的功能:
|
||||
- Keychain Access Groups ✓
|
||||
- In-App Purchase ✓
|
||||
- Game Center ✓
|
||||
|
||||
3. 需要付费 Apple Developer Program 的功能:
|
||||
- Push Notifications ✗
|
||||
- Associated Domains ✗
|
||||
- App Groups ✗
|
||||
- CloudKit ✗
|
||||
- Sign in with Apple ✗
|
||||
|
||||
---
|
||||
|
||||
## Android 开发 (Kotlin)
|
||||
|
||||
### 项目结构
|
||||
|
||||
```
|
||||
android-app/app/src/main/
|
||||
├── java/com/project/
|
||||
│ ├── ui/ # UI 层
|
||||
│ │ ├── screens/ # Compose 屏幕
|
||||
│ │ └── components/ # 可复用组件
|
||||
│ ├── data/ # 数据层
|
||||
│ │ ├── api/ # 网络接口
|
||||
│ │ ├── repository/ # 仓库模式
|
||||
│ │ └── local/ # 本地存储
|
||||
│ ├── domain/ # 业务逻辑
|
||||
│ └── di/ # 依赖注入
|
||||
└── res/ # 资源文件
|
||||
```
|
||||
|
||||
### 代码规范
|
||||
|
||||
```kotlin
|
||||
// Hilt 依赖注入
|
||||
@HiltViewModel
|
||||
class TaskViewModel @Inject constructor(
|
||||
private val taskRepository: TaskRepository
|
||||
) : ViewModel() {
|
||||
|
||||
private val _tasks = MutableStateFlow<List<Task>>(emptyList())
|
||||
val tasks: StateFlow<List<Task>> = _tasks.asStateFlow()
|
||||
|
||||
fun fetchTasks() {
|
||||
viewModelScope.launch {
|
||||
taskRepository.getTasks()
|
||||
.collect { _tasks.value = it }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Jetpack Compose
|
||||
@Composable
|
||||
fun TaskListScreen(
|
||||
viewModel: TaskViewModel = hiltViewModel()
|
||||
) {
|
||||
val tasks by viewModel.tasks.collectAsState()
|
||||
|
||||
LazyColumn {
|
||||
items(tasks) { task ->
|
||||
TaskItem(task = task)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 构建命令
|
||||
|
||||
```bash
|
||||
# 构建 Debug
|
||||
./gradlew assembleDebug
|
||||
|
||||
# 构建 Release
|
||||
./gradlew assembleRelease
|
||||
|
||||
# 测试
|
||||
./gradlew test
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## PDA 应用开发
|
||||
|
||||
### 特点
|
||||
|
||||
- Android 原生开发
|
||||
- 扫码枪集成
|
||||
- 离线优先
|
||||
- 简洁 UI
|
||||
|
||||
### 常见功能
|
||||
|
||||
```kotlin
|
||||
// 扫码处理
|
||||
class ScanReceiver : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
val barcode = intent.getStringExtra("SCAN_BARCODE")
|
||||
// 处理扫码结果
|
||||
}
|
||||
}
|
||||
|
||||
// 离线存储
|
||||
@Entity(tableName = "inventory")
|
||||
data class Inventory(
|
||||
@PrimaryKey val id: Long,
|
||||
val barcode: String,
|
||||
val quantity: Int,
|
||||
@ColumnInfo(name = "sync_status")
|
||||
val syncStatus: SyncStatus = SyncStatus.PENDING
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## MCP 桥接开发
|
||||
|
||||
### 项目结构
|
||||
|
||||
```
|
||||
mcp-task-bridge/
|
||||
├── index.ts # 入口
|
||||
├── task-service.ts # 任务服务
|
||||
├── document-service.ts # 文档服务
|
||||
├── base-client.ts # HTTP 基类
|
||||
├── types.ts # 类型定义
|
||||
└── token-storage.ts # Token 管理
|
||||
```
|
||||
|
||||
### 代码规范
|
||||
|
||||
```typescript
|
||||
// 服务类模式
|
||||
export class TaskService extends BaseClient {
|
||||
async createTask(
|
||||
title: string,
|
||||
projectId: number = 1,
|
||||
options: CreateTaskOptions = {}
|
||||
): Promise<ApiResponse<Task>> {
|
||||
try {
|
||||
const response = await this.makeRequest<Task>(
|
||||
'POST',
|
||||
`/projects/${projectId}/tasks`,
|
||||
{ title, project_id: projectId, ...options }
|
||||
);
|
||||
|
||||
if (response.success) {
|
||||
return {
|
||||
success: true,
|
||||
data: response.data,
|
||||
message: `✅ 任务 "${title}" 创建成功`
|
||||
};
|
||||
}
|
||||
return response;
|
||||
} catch (error: any) {
|
||||
return {
|
||||
success: false,
|
||||
error: `创建任务失败: ${error.message}`
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 通用开发规范
|
||||
|
||||
### API 响应格式
|
||||
@@ -695,13 +373,6 @@ try {
|
||||
} catch (error) {
|
||||
message.error(error.message);
|
||||
}
|
||||
|
||||
// Swift
|
||||
do {
|
||||
let result = try await service.fetch()
|
||||
} catch {
|
||||
// 处理错误
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
@@ -811,6 +482,11 @@ fi
|
||||
|
||||
## 相关技能
|
||||
|
||||
| 技能 | 用途 | 关系 |
|
||||
|------|------|------|
|
||||
| `req-test-gate` | 测试与质量门禁 + Harness Engineering | 建立项目质量门禁和约定自动检测,dev-coding 遵守其建立的 CLAUDE.md 约定 |
|
||||
| 技能 | 用途 |
|
||||
|------|------|
|
||||
| `req-design` | 开发设计(API 契约、任务拆分)— dev-coding 的输入 |
|
||||
| `dev-test` | 测试与质量门禁 |
|
||||
| `dev-review` | 代码评审(五视角扫描)|
|
||||
| `dev-ios` | iOS 开发(插件,按需加载)|
|
||||
| `dev-android` | Android 开发(插件,按需加载)|
|
||||
| `dev-mcp` | MCP bridge 开发(插件,按需加载)|
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "dev-integration-plugin",
|
||||
"description": "前后端联调技能。API 契约验证、联调报告、纯后端需求自动跳过。对应 req 流程 integration 阶段。",
|
||||
"version": "1.0.0",
|
||||
"author": {
|
||||
"name": "qiudl"
|
||||
}
|
||||
}
|
||||
154
skills-dev/dev-integration-plugin/skills/SKILL.md
Normal file
154
skills-dev/dev-integration-plugin/skills/SKILL.md
Normal file
@@ -0,0 +1,154 @@
|
||||
---
|
||||
name: dev-integration
|
||||
description: 前后端联调技能。API 契约验证、接口对接、联调报告生成。对应 req 流程 integration 阶段。纯后端需求自动跳过。
|
||||
---
|
||||
|
||||
# 前后端联调 Skill (dev-integration)
|
||||
|
||||
## 概述
|
||||
|
||||
本技能用于前后端联调阶段,确保实际实现与 API 契约一致。
|
||||
|
||||
**核心价值**:发现契约偏差(字段名不一致、类型不匹配、缺少错误码处理)比测试阶段更早、修复成本更低。
|
||||
|
||||
---
|
||||
|
||||
## 技能间契约
|
||||
|
||||
| 上游 | 本技能输入 | 本技能输出 | 下游 |
|
||||
|------|-----------|-----------|------|
|
||||
| dev-coding | 已实现的前后端代码 + API 契约(来自 req-design) | 联调报告(通过/不通过 + 问题列表) | dev-test |
|
||||
|
||||
---
|
||||
|
||||
## 自动跳过条件
|
||||
|
||||
以下情况 integration 阶段**自动通过**,无需执行联调:
|
||||
|
||||
| 条件 | 原因 |
|
||||
|------|------|
|
||||
| 需求只有后端 implementation 任务(无前端任务) | 没有前端对接,无需联调 |
|
||||
| 需求只有前端 implementation 任务(无后端任务) | 使用已有 API,无需联调 |
|
||||
| 需求无 implementation 任务(纯 skill/ops/doc) | 非代码需求 |
|
||||
|
||||
**检测方法**:
|
||||
```
|
||||
get_requirement_tasks → 检查 linkRole=implementation 的任务标题
|
||||
含【开发-后端】和【开发-前端】→ 需要联调
|
||||
仅含一端 → 自动跳过
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 工作流程
|
||||
|
||||
```
|
||||
1. 检查是否需要联调
|
||||
├── 获取 implementation 任务列表
|
||||
├── 判断是否有前后端双端任务
|
||||
└── 仅单端 → 自动跳过,生成跳过说明
|
||||
|
||||
2. 获取 API 契约
|
||||
├── 从 req-design 文档中提取 API 契约
|
||||
└── 无契约 → 从代码反推接口定义
|
||||
|
||||
3. 契约验证
|
||||
├── 后端实际接口 vs 契约定义
|
||||
│ ├── URL 路径是否一致
|
||||
│ ├── 请求/响应字段名是否一致
|
||||
│ ├── 字段类型是否匹配
|
||||
│ └── 错误码是否完整
|
||||
├── 前端调用 vs 契约定义
|
||||
│ ├── API service 调用路径是否正确
|
||||
│ ├── 请求参数是否完整
|
||||
│ └── 响应处理是否覆盖所有错误码
|
||||
└── 前端 ↔ 后端一致性
|
||||
├── 字段命名一致(camelCase vs snake_case 转换)
|
||||
└── 分页参数格式一致
|
||||
|
||||
4. 功能对接验证
|
||||
├── 前端表单字段 vs 后端 binding 规则
|
||||
├── 前端列表列 vs 后端响应字段
|
||||
└── 前端状态流转 vs 后端状态机
|
||||
|
||||
5. 生成联调报告
|
||||
├── 契约一致性结果
|
||||
├── 发现的偏差列表
|
||||
└── 结论:通过/不通过
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 联调报告模板
|
||||
|
||||
```markdown
|
||||
## 联调报告 — {需求标题}
|
||||
|
||||
**日期**: YYYY-MM-DD
|
||||
**API 契约来源**: {req-design 文档 / 代码反推}
|
||||
|
||||
### 契约验证结果
|
||||
|
||||
| # | 接口 | 契约 | 后端实际 | 前端调用 | 结果 |
|
||||
|---|------|------|---------|---------|------|
|
||||
| 1 | POST /api/v1/xxx | ✅ 已定义 | ✅ 一致 | ✅ 一致 | PASS |
|
||||
| 2 | GET /api/v1/xxx | ✅ 已定义 | ⚠️ 字段名不一致 | ✅ 一致 | FAIL |
|
||||
|
||||
### 发现的偏差
|
||||
|
||||
| # | 类型 | 接口 | 描述 | 影响 | 建议 |
|
||||
|---|------|------|------|------|------|
|
||||
| 1 | 字段名不一致 | GET /api/v1/xxx | 契约定义 `created_at`,后端返回 `createTime` | 前端解析失败 | 统一为 `created_at` |
|
||||
|
||||
### 结论
|
||||
|
||||
**{通过 / 不通过}**
|
||||
|
||||
{如不通过,列出必须修复的偏差编号}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 插件支持
|
||||
|
||||
| 插件 | 触发条件 | 说明 |
|
||||
|------|---------|------|
|
||||
| `api-contract-verify` | 有 API 变更 | 自动化契约验证(未来) |
|
||||
|
||||
---
|
||||
|
||||
## 与 ai-proj 集成
|
||||
|
||||
### req 流程内
|
||||
|
||||
```typescript
|
||||
// 创建联调任务(如需要)
|
||||
mcp__ai-proj__create_task({ title: "【联调】前后端对接: {需求标题}" })
|
||||
mcp__ai-proj__link_tasks_to_requirement({
|
||||
requirementId, taskIds: [taskId], linkRole: "implementation"
|
||||
})
|
||||
|
||||
// 附加联调报告
|
||||
mcp__ai-proj__create-and-attach({
|
||||
taskId, title: "联调报告", content: "<报告内容>"
|
||||
})
|
||||
```
|
||||
|
||||
### 自动跳过时
|
||||
|
||||
```typescript
|
||||
// 记录跳过原因
|
||||
mcp__ai-proj__create-and-attach({
|
||||
taskId: <设计任务ID>,
|
||||
content: "## 联调阶段\n\n自动跳过:仅后端变更,无前端对接。"
|
||||
})
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 最佳实践
|
||||
|
||||
1. **契约先行** — API 契约是联调的基准,没有契约就先补
|
||||
2. **字段级验证** — 不只检查接口是否通,要检查每个字段名、类型、格式
|
||||
3. **错误码覆盖** — 前端必须处理契约中定义的所有错误码
|
||||
4. **snake_case 转换** — Go 后端用 snake_case,前端用 camelCase,确认自动转换正确
|
||||
1
skills-dev/dev-ios-plugin/.claude-plugin/plugin.json
Normal file
1
skills-dev/dev-ios-plugin/.claude-plugin/plugin.json
Normal file
@@ -0,0 +1 @@
|
||||
{"name":"dev-ios-plugin","description":"iOS 开发插件。Swift/SwiftUI + MVVM 架构、TestFlight 部署、Xcode 构建。按需加载。","version":"1.0.0","author":{"name":"qiudl"}}
|
||||
90
skills-dev/dev-ios-plugin/skills/SKILL.md
Normal file
90
skills-dev/dev-ios-plugin/skills/SKILL.md
Normal file
@@ -0,0 +1,90 @@
|
||||
---
|
||||
name: dev-ios
|
||||
description: iOS 开发插件。Swift/SwiftUI + MVVM 架构,TestFlight 部署。当涉及 iOS 开发任务时按需加载。
|
||||
---
|
||||
|
||||
# iOS 开发插件 (dev-ios)
|
||||
|
||||
## 架构:SwiftUI + MVVM
|
||||
|
||||
```
|
||||
AI-Proj-iOS/
|
||||
├── Core/ # 核心层
|
||||
│ ├── Architecture/ # AppCoordinator, AppState
|
||||
│ ├── Components/ # 通用 UI 组件
|
||||
│ ├── Config.swift # 配置
|
||||
│ ├── Services/ # APIEndpoints, AuthService, NetworkService, DIContainer
|
||||
│ ├── Theme/ # 主题配置
|
||||
│ └── Utilities/ # 设备适配
|
||||
├── Features/ # 功能模块(MVVM)
|
||||
│ └── Requirements/ # 示例:List/Detail View + ViewModel
|
||||
├── Models/ # 数据模型 + DTOs
|
||||
└── Resources/ # Assets
|
||||
```
|
||||
|
||||
**开发顺序**:Model → DTO → APIEndpoints → ServiceProtocols → ViewModel → View
|
||||
|
||||
## 代码规范
|
||||
|
||||
```swift
|
||||
@MainActor
|
||||
class TaskViewModel: ObservableObject {
|
||||
@Published private(set) var tasks: [Task] = []
|
||||
@Published private(set) var isLoading = false
|
||||
@Published var error: String?
|
||||
|
||||
private let taskService: TaskServiceProtocol
|
||||
|
||||
init(taskService: TaskServiceProtocol) {
|
||||
self.taskService = taskService
|
||||
}
|
||||
|
||||
func loadTasks() async {
|
||||
guard !isLoading else { return }
|
||||
isLoading = true
|
||||
defer { isLoading = false }
|
||||
|
||||
do {
|
||||
tasks = try await taskService.fetchTasks()
|
||||
} catch {
|
||||
self.error = error.localizedDescription
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**规则**:
|
||||
- ViewModel 使用 `@MainActor`
|
||||
- Published 属性用 `private(set)`
|
||||
- 使用协议依赖注入
|
||||
- `async/await` 而非 completion handler
|
||||
- `guard` 提前返回,`defer` 确保状态重置
|
||||
|
||||
## 命名规范
|
||||
|
||||
| 类型 | 规范 | 示例 |
|
||||
|------|------|------|
|
||||
| 文件/类 | 大驼峰 | `ManualListView.swift` |
|
||||
| 协议 | 大驼峰 + Protocol | `ManualServiceProtocol` |
|
||||
| 函数/变量 | 小驼峰 | `loadManuals()`, `isLoading` |
|
||||
| 枚举 case | 小驼峰 | `case draft` |
|
||||
|
||||
## 构建与部署
|
||||
|
||||
```bash
|
||||
# 构建
|
||||
xcodebuild -scheme AI-Proj-iOS -configuration Debug
|
||||
|
||||
# 测试
|
||||
xcodebuild test -scheme AI-Proj-iOS
|
||||
|
||||
# TestFlight 部署详见 memory: testflight-deploy.md
|
||||
```
|
||||
|
||||
## 常见问题
|
||||
|
||||
### SwiftLint 沙盒错误
|
||||
Xcode 15+ 默认启用 User Script Sandboxing → Build Settings → `ENABLE_USER_SCRIPT_SANDBOXING = NO`
|
||||
|
||||
### Personal Team 功能限制
|
||||
免费账户不支持 Push Notifications / Associated Domains / App Groups → 从 Entitlements 中移除
|
||||
1
skills-dev/dev-mcp-plugin/.claude-plugin/plugin.json
Normal file
1
skills-dev/dev-mcp-plugin/.claude-plugin/plugin.json
Normal file
@@ -0,0 +1 @@
|
||||
{"name":"dev-mcp-plugin","description":"MCP Bridge 开发插件。TypeScript MCP 服务开发、Token 管理、HTTP 客户端模式。按需加载。","version":"1.0.0","author":{"name":"qiudl"}}
|
||||
59
skills-dev/dev-mcp-plugin/skills/SKILL.md
Normal file
59
skills-dev/dev-mcp-plugin/skills/SKILL.md
Normal file
@@ -0,0 +1,59 @@
|
||||
---
|
||||
name: dev-mcp
|
||||
description: MCP Bridge 开发插件。TypeScript MCP 服务开发,Token 管理,HTTP 客户端模式。当涉及 mcp-task-bridge 开发时按需加载。
|
||||
---
|
||||
|
||||
# MCP Bridge 开发插件 (dev-mcp)
|
||||
|
||||
## 项目结构
|
||||
|
||||
```
|
||||
mcp-task-bridge/
|
||||
├── index.ts # 入口,MCP server 注册
|
||||
├── task-service.ts # 任务服务
|
||||
├── document-service.ts # 文档服务
|
||||
├── requirement-service.ts # 需求服务
|
||||
├── base-client.ts # HTTP 基类(认证、重试)
|
||||
├── types.ts # 类型定义
|
||||
└── token-storage.ts # Token 持久化
|
||||
```
|
||||
|
||||
## 代码规范
|
||||
|
||||
```typescript
|
||||
export class TaskService extends BaseClient {
|
||||
async createTask(
|
||||
title: string,
|
||||
projectId: number = 1,
|
||||
options: CreateTaskOptions = {}
|
||||
): Promise<ApiResponse<Task>> {
|
||||
try {
|
||||
const response = await this.makeRequest<Task>(
|
||||
'POST',
|
||||
`/projects/${projectId}/tasks`,
|
||||
{ title, project_id: projectId, ...options }
|
||||
);
|
||||
return response.success
|
||||
? { success: true, data: response.data, message: `✅ 任务创建成功` }
|
||||
: response;
|
||||
} catch (error: any) {
|
||||
return { success: false, error: `创建任务失败: ${error.message}` };
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 关键规则
|
||||
|
||||
1. **MCP endpoint 前缀**:所有 MCP 专用后端接口必须包含 `/mcp/` 前缀
|
||||
2. **修改后重新构建**:`npm run build` → `pkill -f "mcp-task-bridge/dist/index.js"`
|
||||
3. **环境一致性**:不要跨环境混用数据(dev/staging/prod)
|
||||
|
||||
## 常用命令
|
||||
|
||||
```bash
|
||||
npm run dev # 开发(hot reload)
|
||||
npm run build # 编译 TypeScript
|
||||
npm test # 快速测试
|
||||
npm run test:integration # 集成测试
|
||||
```
|
||||
1
skills-dev/dev-pda-plugin/.claude-plugin/plugin.json
Normal file
1
skills-dev/dev-pda-plugin/.claude-plugin/plugin.json
Normal file
@@ -0,0 +1 @@
|
||||
{"name":"dev-pda-plugin","description":"PDA 应用开发插件。Android 原生 + 扫码枪集成 + 离线优先模式。按需加载。","version":"1.0.0","author":{"name":"qiudl"}}
|
||||
49
skills-dev/dev-pda-plugin/skills/SKILL.md
Normal file
49
skills-dev/dev-pda-plugin/skills/SKILL.md
Normal file
@@ -0,0 +1,49 @@
|
||||
---
|
||||
name: dev-pda
|
||||
description: PDA 应用开发插件。Android 原生 + 扫码枪集成 + 离线优先。当涉及 PDA/手持终端开发时按需加载。
|
||||
---
|
||||
|
||||
# PDA 应用开发插件 (dev-pda)
|
||||
|
||||
## 特点
|
||||
|
||||
- Android 原生开发(Kotlin)
|
||||
- 扫码枪硬件集成
|
||||
- 离线优先(本地 Room DB + 同步队列)
|
||||
- 简洁 UI(大按钮、大字体、适配小屏幕)
|
||||
|
||||
## 扫码集成
|
||||
|
||||
```kotlin
|
||||
class ScanReceiver : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
val barcode = intent.getStringExtra("SCAN_BARCODE")
|
||||
// 处理扫码结果
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 离线存储
|
||||
|
||||
```kotlin
|
||||
@Entity(tableName = "inventory")
|
||||
data class Inventory(
|
||||
@PrimaryKey val id: Long,
|
||||
val barcode: String,
|
||||
val quantity: Int,
|
||||
@ColumnInfo(name = "sync_status")
|
||||
val syncStatus: SyncStatus = SyncStatus.PENDING
|
||||
)
|
||||
|
||||
enum class SyncStatus { PENDING, SYNCED, FAILED }
|
||||
```
|
||||
|
||||
## 离线同步策略
|
||||
|
||||
```
|
||||
操作 → 写入本地 DB (PENDING)
|
||||
↓
|
||||
网络可用 → 批量上传 → 成功 → 标记 SYNCED
|
||||
↓ 失败
|
||||
标记 FAILED → 下次重试
|
||||
```
|
||||
8
skills-dev/dev-review-plugin/.claude-plugin/plugin.json
Normal file
8
skills-dev/dev-review-plugin/.claude-plugin/plugin.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "dev-review-plugin",
|
||||
"description": "代码评审技能。五视角对抗性扫描法(攻击者/泄露者/并发者/边界者/依赖者),CR 报告生成,独立于 req 工作流可单独使用。",
|
||||
"version": "1.0.0",
|
||||
"author": {
|
||||
"name": "qiudl"
|
||||
}
|
||||
}
|
||||
280
skills-dev/dev-review-plugin/skills/SKILL.md
Normal file
280
skills-dev/dev-review-plugin/skills/SKILL.md
Normal file
@@ -0,0 +1,280 @@
|
||||
---
|
||||
name: dev-review
|
||||
description: 代码评审技能。五视角对抗性扫描法,用于 PR 代码审查、安全评审、质量检查。当执行 /req cr 或独立 PR review 时自动激活。
|
||||
---
|
||||
|
||||
# 代码评审 Skill (dev-review)
|
||||
|
||||
## 概述
|
||||
|
||||
独立的代码评审技能,核心方法论是**五视角对抗性扫描法**。
|
||||
|
||||
**适用场景**:
|
||||
- `/req cr [REQ-ID]` — 需求流程中的代码评审阶段
|
||||
- 独立 PR review — 不绑定需求的代码审查
|
||||
- 安全评审 — 专项安全扫描
|
||||
|
||||
**核心原则**:实现阶段关注"怎么让它跑通",评审阶段关注**"怎么让它出错"**。AI 必须切换到对抗性思维。
|
||||
|
||||
---
|
||||
|
||||
## 技能间契约
|
||||
|
||||
| 上游 | 本技能输入 | 本技能输出 | 下游 |
|
||||
|------|-----------|-----------|------|
|
||||
| dev-coding | PR diff + 开发设计文档 | CR 报告(五视角扫描 + 发现汇总 + 结论) | dev-test |
|
||||
|
||||
---
|
||||
|
||||
## 工作流程
|
||||
|
||||
```
|
||||
1. 确定评审范围
|
||||
├── git diff 获取变更文件列表
|
||||
├── 统计文件数、行数
|
||||
└── 排除 test 文件(单独审查)
|
||||
|
||||
2. 读取变更代码
|
||||
├── 逐个读取变更<E58F98><E69BB4><EFBFBD>件源码
|
||||
├── 理解业务上下文
|
||||
└── 参考开发设计文档(如有)
|
||||
|
||||
3. 五视角扫描(核心)
|
||||
├── 攻击<E694BB><E587BB><EFBFBD>视角
|
||||
├── 泄露者视角
|
||||
├── 并发者视角
|
||||
├── 边界者视角
|
||||
└── 依赖者视角
|
||||
|
||||
4. 加载项目检查清单(如有)
|
||||
└── review-checklist 插件
|
||||
|
||||
5. 生成 CR 报告
|
||||
├── 变更概要
|
||||
├── 五视角扫描结果
|
||||
├── 发现汇总表
|
||||
└── 结论(通过/有条件通过/需修改)
|
||||
|
||||
6. 创建评审任务(req 流程内)
|
||||
├── ai-proj task create【代码评审】
|
||||
├── 关联需求(linkRole=code_review)
|
||||
└── 附加 CR 报告文档
|
||||
|
||||
7. 处理发现
|
||||
├── Critical/High → 创建修复任务
|
||||
└── Medium/Low → 记录建议
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五视角对抗性扫描法
|
||||
|
||||
### 总览
|
||||
|
||||
| 视角 | 思维模式 | 核心问题 |
|
||||
|------|---------|---------|
|
||||
| **1. 攻击者** | "我怎么绕过/<2F><><EFBFBD>用它?" | 跨租户泄露、越权访问、参数注入、重放攻击 |
|
||||
| **2. 泄露者** | "它暴露了什么不该暴露的?" | 错误信息泄露、日志敏感数据、响应内部细节 |
|
||||
| **3. 并发者** | "两个请求同时来会怎样?" | 竞态条件、双重扣款、幂等性缺失、锁粒度 |
|
||||
| **4. 边界者** | "极端输入会怎样?" | 空值/零值/负值/超长字符串、类型溢出、分页越界 |
|
||||
| **5. 依赖者** | "外部服务挂了会怎样?" | 超时处理、重试策略、降级方案、连接泄露 |
|
||||
|
||||
### 视角1:攻击者(多租户安全)
|
||||
|
||||
**思维模式**:我是恶意用户,如何绕过权限获取他人数据。
|
||||
|
||||
扫描清单:
|
||||
- [ ] 所有 Store/Repository 层查询是否带 `tenant_id` 过滤?
|
||||
- [ ] 通过 ID 直接查询的方法是否校验归属?
|
||||
- [ ] 用户只能操作自己的数据?(consumer_id 校验)
|
||||
- [ ] URL/请求参数是否有注入风险?(SQL、URL、命令注入)
|
||||
- [ ] 外部输入是否直接拼接到查询/URL?(应使用参数化查询或编码)
|
||||
- [ ] 批量操作是否逐条校验权限?(不能只校验第一条)
|
||||
- [ ] 文件上传是否有类型/大小限制?
|
||||
|
||||
**典型发现示例**:
|
||||
```
|
||||
file:line — Store.GetByID(id) 缺少 tenant_id 过滤,
|
||||
攻击者可通过遍<EFBFBD><EFBFBD> ID 获取其他租户数据。
|
||||
建议:添加 WHERE tenant_id = ? 条件。
|
||||
```
|
||||
|
||||
### 视角2:泄露者(信息安全)
|
||||
|
||||
**思维模式**:我是安全审计员,检查每个出口是否泄露了不该泄露的信息。
|
||||
|
||||
扫描清单:
|
||||
- [ ] 错误消息是否泄露业务状态?(如"手机号未注册"暴露用户存在性)
|
||||
- [ ] 日志是否打印了密码、token、密钥、身份证号?
|
||||
- [ ] 响应是否包含不必要的内部字段?(如内部 ID、数据库字段名、堆栈跟踪)
|
||||
- [ ] panic recover 后是否返回了内部错误详情?
|
||||
- [ ] 导出/下载功能是否过滤了敏感字段?
|
||||
|
||||
### 视角3:并发者(数据一致性)
|
||||
|
||||
**思维模式**:两个用户同时操作同一条数据,会发生什么。
|
||||
|
||||
扫描清单:
|
||||
- [ ] 涉及金额/库存变更是否使用事务 + 悲观锁/乐观锁?
|
||||
- [ ] 关键操作是否有幂等保护?(bizNo 唯一索引、幂等键)
|
||||
- [ ] 全局状态(如进程内计数器、缓存)重启后是否安全?
|
||||
- [ ] 是否有 TOCTOU(检查-使用)竞态?(先查状态再操作,中间被修改)
|
||||
- [ ] 并发创建是否会产生重复数据?(唯一约束)
|
||||
|
||||
### 视角4:边界者(健壮性)
|
||||
|
||||
**思维模<E7BBB4><E6A8A1>**:用最极端的输入来测试系统的承受能力。
|
||||
|
||||
扫描清单:
|
||||
- [ ] 必填参数是否有 `binding:"required"` 校验?
|
||||
- [ ] 数值参数是否有范围校验?(min/max,防止负数、溢出)
|
||||
- [ ] 字符串是否有长度限制?(防止超长输入消耗内存)
|
||||
- [ ] 分页参数是否有默认值和上限?(page_size 不能为 0 或 999999)
|
||||
- [ ] 数组参数是否有长度限制?(批量操作不能传 10 万条)
|
||||
- [ ] 空数组/空字符串是否正确处理?(不应触发不必要的数据库操作)
|
||||
- [ ] 除零错误?百分比计算分母为 0?
|
||||
|
||||
### 视角5:依赖者(可靠性)
|
||||
|
||||
**思维模式**:外部服务全部挂掉,系统还能正常运行吗。
|
||||
|
||||
扫描清单:
|
||||
- [ ] HTTP 客户端是否设置超时?(connect/read/write timeout)
|
||||
- [ ] 外部 API 调用失败是否有合理的错误处理?(不能直接 panic)
|
||||
- [ ] 是否有重试策略?重试是否有退避?是否幂等安全?
|
||||
- [ ] 数据库连接池配置是否合理?(max idle/max open/lifetime)
|
||||
- [ ] Redis 不可用时是否有降级方案?(缓存穿透到数据库)
|
||||
- [ ] token 过期/刷新逻辑是否正确?(access vs refresh 不同策略)
|
||||
|
||||
---
|
||||
|
||||
## CR 报告模板
|
||||
|
||||
```markdown
|
||||
## 代<><E4BBA3>评审报告 — {需求标题/PR 标题}
|
||||
|
||||
**日期**: YYYY-MM-DD
|
||||
**评审范围**: {N} 个文件, {M} 行变更
|
||||
**评审人**: AI (dev-review)
|
||||
|
||||
### 变更概要
|
||||
{1-3 句描述本次变更的目的和范围}
|
||||
|
||||
### 五视角扫描结果
|
||||
|
||||
#### 1. 攻击者视角
|
||||
{扫描发现,或 "未发现问题"}
|
||||
|
||||
#### 2. 泄露者视角
|
||||
{扫描发现,或 "未发现问题"}
|
||||
|
||||
#### 3. 并发者视角
|
||||
{扫描发现,或 "未发现问题"}
|
||||
|
||||
#### 4. 边界者视角
|
||||
{扫描发现,或 "未发现问题"}
|
||||
|
||||
#### 5. 依赖者视角
|
||||
{扫描发现,或 "未发现问题"}
|
||||
|
||||
### 审查发现汇总
|
||||
|
||||
| # | 严重度 | 文件:行号 | <20><><EFBFBD>角 | 描述 | 建议 |
|
||||
|---|--------|----------|------|------|------|
|
||||
| 1 | {Critical/High/Medium/Low} | {file:line} | {视角} | {问题} | {建议} |
|
||||
|
||||
### 统计
|
||||
|
||||
| 严重度 | 数量 |
|
||||
|--------|------|
|
||||
| Critical | 0 |
|
||||
| High | 0 |
|
||||
| Medium | 0 |
|
||||
| Low | 0 |
|
||||
|
||||
### 结论
|
||||
|
||||
**{通过 / 有条件通过 / 需修改}**
|
||||
|
||||
{结论说明:如果有 Critical/High 必须修复后重新评审}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 严重度定义
|
||||
|
||||
| 严重度 | 含义 | 处理方式 |
|
||||
|--------|------|---------|
|
||||
| **Critical** | 安全漏洞、数据泄露、资金风险 | 必须修复,阻断合并 |
|
||||
| **High** | 数据一致性风险、业务逻辑错误 | 必须修复,阻断合并 |
|
||||
| **Medium** | 边界未处理、缺少校验、性能隐患 | 建议修复,不阻断 |
|
||||
| **Low** | 代码风格、命名优化、文档补充 | 可选修复 |
|
||||
|
||||
---
|
||||
|
||||
## CR 报告质量门禁
|
||||
|
||||
`/req next` 从 review 阶段推进时,检查 CR 报告质量:
|
||||
|
||||
| 检查项 | 标准 |
|
||||
|--------|------|
|
||||
| 文档存在 | CR 任务有附加文档 |
|
||||
| 字数 | ≥ 500 字 |
|
||||
| 代码引用 | 含 `file:line` 格式的引用 |
|
||||
| 五视角扫描 | 含全部 5 个视角章节 |
|
||||
| 结论章节 | 含明确的通过/不通过结论 |
|
||||
|
||||
---
|
||||
|
||||
## 插件支持
|
||||
|
||||
| 插件 | 触发条件 | 说明 |
|
||||
|------|---------|------|
|
||||
| `review-checklist` | 每次 CR | 加载项目特定检查清单 |
|
||||
| `figma-design-qa` | 有设计稿 | 设计还原度对比 |
|
||||
|
||||
---
|
||||
|
||||
## 与 ai-proj 集成
|
||||
|
||||
### req 流程内(/req cr)
|
||||
|
||||
```typescript
|
||||
// 1. 确认 implementation 任务已完成
|
||||
mcp__ai-proj__get_requirement_tasks({ requirementId })
|
||||
// 检查所有 linkRole=implementation 的任务状态
|
||||
|
||||
// 2. 创建 CR 任务
|
||||
mcp__ai-proj__create_task({ title: "【代码评审】CR: {需求标题}" })
|
||||
mcp__ai-proj__link_tasks_to_requirement({
|
||||
requirementId, taskIds: [crTaskId], linkRole: "code_review"
|
||||
})
|
||||
|
||||
// 3. 附加 CR 报告
|
||||
mcp__ai-proj__create-and-attach({
|
||||
taskId: crTaskId,
|
||||
title: "代码评审报告",
|
||||
content: "<CR <20><><EFBFBD>告 Markdown>"
|
||||
})
|
||||
|
||||
// 4. High/Critical 发现 → 创建修复任务
|
||||
mcp__ai-proj__create_task({ title: "【修复】{问题描述}" })
|
||||
mcp__ai-proj__link_tasks_to_requirement({
|
||||
requirementId, taskIds: [fixTaskId], linkRole: "implementation"
|
||||
})
|
||||
```
|
||||
|
||||
### 独立 PR review
|
||||
|
||||
不需要 ai-proj 集成,直接输出 CR 报告到对话。
|
||||
|
||||
---
|
||||
|
||||
## 最佳实践
|
||||
|
||||
1. **先理解再审查** — 读完所有变更<E58F98><E69BB4><EFBFBD>件后再开始扫描,避免断章取义
|
||||
2. **对抗性思维** — 切换到"怎么让它出错"的心态,不是"怎么让它跑通"
|
||||
3. **证据驱动** — 每个发现必须引用具体的 `file:line`
|
||||
4. **严重度准确** — 不要所有问题都标 High,按实际影响分级
|
||||
5. **建议可操作** — 每个发现必须附带具体修复建议
|
||||
6. **关注变更** — 评审范围是 diff,不要对未变更的代码提意见(除非变更引入了对旧代码的新风险)
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "dev-scaffold-plugin",
|
||||
"description": "模块脚手架插件。新建模块时自动生成分层代码骨架(Model/Repository/Service/Handler/Route)。挂载在 dev 阶段。",
|
||||
"version": "1.0.0",
|
||||
"author": { "name": "qiudl" }
|
||||
}
|
||||
78
skills-dev/dev-scaffold-plugin/skills/SKILL.md
Normal file
78
skills-dev/dev-scaffold-plugin/skills/SKILL.md
Normal file
@@ -0,0 +1,78 @@
|
||||
---
|
||||
name: dev-scaffold
|
||||
description: 模块脚手架插件。新建模块时自动生成分层代码骨架。挂载在 dev 阶段,新建模块时激活。
|
||||
---
|
||||
|
||||
# 模块脚手架插件 (dev-scaffold)
|
||||
|
||||
## 概述
|
||||
|
||||
当需要新建一个完整模块时,自动生成分层代码骨架,避免手动创建大量样板文件。
|
||||
|
||||
**触发条件**:
|
||||
- 需求需要新建数据库表 + 完整 CRUD
|
||||
- 开发设计文档中有"新增"类型的文件
|
||||
|
||||
## Go 后端脚手架
|
||||
|
||||
输入模块名(如 `manual`),生成以下文件:
|
||||
|
||||
```
|
||||
backend/
|
||||
├── models/manual.go # GORM 模型
|
||||
├── database/manual_repository.go # Repository
|
||||
├── services/manual_service.go # Service
|
||||
├── handlers/manual_handler.go # Handler
|
||||
├── routes/manual_routes.go # Route
|
||||
└── migrations/YYYYMMDDHHMMSS_create_manual.up.sql # Migration
|
||||
```
|
||||
|
||||
### 生成规则
|
||||
|
||||
**Model** (`models/{name}.go`):
|
||||
- struct 定义 + GORM tags
|
||||
- TableName() 方法
|
||||
- 标准字段:ID, TenantID, CreatedBy, CreatedAt, UpdatedAt, DeletedAt
|
||||
|
||||
**Repository** (`database/{name}_repository.go`):
|
||||
- interface 定义
|
||||
- Create, GetByID, List(分页), Update, Delete 方法
|
||||
- 所有查询带 tenant_id 过滤
|
||||
|
||||
**Service** (`services/{name}_service.go`):
|
||||
- interface 定义
|
||||
- 注入 Repository
|
||||
- 基础 CRUD + 业务校验
|
||||
|
||||
**Handler** (`handlers/{name}_handler.go`):
|
||||
- Create, Get, List, Update, Delete 方法
|
||||
- 请求参数绑定 + 验证
|
||||
- 统一错误处理
|
||||
|
||||
**Route** (`routes/{name}_routes.go`):
|
||||
- RESTful 路由注册
|
||||
- Auth 中间件
|
||||
|
||||
**Migration** (`migrations/YYYYMMDDHHMMSS_create_{name}.up.sql`):
|
||||
- CREATE TABLE + 标准字段 + 索引
|
||||
|
||||
## React 前端脚手架
|
||||
|
||||
输入模块名(如 `Manual`),生成:
|
||||
|
||||
```
|
||||
frontend/src/
|
||||
├── types/manual.ts # TypeScript 类型
|
||||
├── services/manualService.ts # API Service
|
||||
├── pages/ManualListPage.tsx # 列表页
|
||||
└── pages/ManualDetailPage.tsx # 详情页(可选)
|
||||
```
|
||||
|
||||
## 使用方式
|
||||
|
||||
```
|
||||
用户: "新建 manual 模块的脚手架"
|
||||
AI: 根据 req-design 的变更文件清单,生成所有骨架文件
|
||||
```
|
||||
|
||||
**注意**:脚手架只生成骨架,具体业务逻辑需在骨架基础上补充。
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "review-checklist-plugin",
|
||||
"description": "项目级代码评审检查清单。按项目积累的特定检查项,挂载在 dev-review 下自动加载。",
|
||||
"version": "1.0.0",
|
||||
"author": {
|
||||
"name": "qiudl"
|
||||
}
|
||||
}
|
||||
42
skills-dev/review-checklist-plugin/checklists/ai-proj.md
Normal file
42
skills-dev/review-checklist-plugin/checklists/ai-proj.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# AI-Proj 代码评审检查清单
|
||||
|
||||
## 后端(Go + Gin + GORM)
|
||||
|
||||
### 分层架构
|
||||
- [ ] Handler 是否直接 import `database/` 包?— 禁止,必须通过 Service 层。教训:架构退化导致循环依赖
|
||||
- [ ] 新 Handler 是否在 routes/ 中注册?— 遗漏会导致 404
|
||||
- [ ] MCP 专用 endpoint 是否包含 `/mcp/` 前缀?— 教训:缺少前缀导致 MCP bridge 404
|
||||
|
||||
### 数据库
|
||||
- [ ] 新增 Migration 文件名是否符合 `YYYYMMDDHHMMSS_xxx.up.sql` 格式?
|
||||
- [ ] Migration 是否有对应的 `.down.sql`?
|
||||
- [ ] GORM 查询是否带 `tenant_id` 过滤?(多租户安全)
|
||||
- [ ] 软删除查询是否正确使用 `Unscoped()`?— 误用导致查不到已删除数据或查出已删除数据
|
||||
|
||||
### 认证与权限
|
||||
- [ ] 新 API 是否配置了 Auth 中间件?— 遗漏导致未授权访问
|
||||
- [ ] JWT token 类型是否区分 access/refresh?— 教训:token 混用导致安全漏洞
|
||||
- [ ] bcrypt cost 是否使用 12?— 教训:默认 cost 10 导致登录失败
|
||||
|
||||
### Redis
|
||||
- [ ] Redis key 是否有 TTL?— 缺少 TTL 导致内存泄露
|
||||
- [ ] Redis 不可用时是否降级到数据库?
|
||||
|
||||
## 前端(React 18 + Ant Design)
|
||||
|
||||
### Modal 安全
|
||||
- [ ] `Modal.success/info/warning/error` 之后是否有立即执行的 UI 操作?— 必须放在 `onOk` 回调中。教训:两个 Modal 同时弹出互相遮挡
|
||||
|
||||
### 状态管理
|
||||
- [ ] React Query 的 queryKey 是否正确包含所有依赖参数?— 缺少导致缓存错误
|
||||
- [ ] 列表页分页是否正确重置 page?— 教训:筛选条件变更后 page 未重置导致空页
|
||||
|
||||
### 类型安全
|
||||
- [ ] 是否有 `any` 类型?— 应使用具体类型
|
||||
- [ ] API 响应是否有 TypeScript 接口定义?
|
||||
|
||||
## 通用
|
||||
|
||||
- [ ] `.env` <20><>凭据文件是否被意外加入 git?
|
||||
- [ ] 是否有硬编码的 URL/IP/端口?— 应使用配置
|
||||
- [ ] 错误日志是否包含足够的上下文信息?(user_id, tenant_id, request_id)
|
||||
@@ -0,0 +1,20 @@
|
||||
# Coolbuy PaaS(酷采3.0)代码评审检查清单
|
||||
|
||||
## 后端(Go + Gin + MySQL)
|
||||
|
||||
### 多租户
|
||||
- [ ] 所有查询是否带 `tenant_id` 和 `enterprise_id` 过滤?
|
||||
- [ ] 跨租户数据操作是否被阻止?
|
||||
|
||||
### 数据迁移
|
||||
- [ ] 从酷采2.0迁移的字段映射是否正确?(varchar ID → bigint ID)
|
||||
- [ ] 迁移脚本是否处理了酷采2.0<EFBFBD><EFBFBD><EFBFBD>软删除标记(is_delete → deleted_at)?
|
||||
|
||||
## 前端(Vue 3 + Ant Design Vue)
|
||||
|
||||
### i18n
|
||||
- [ ] 新增文案是否使用 `$t()` 国际化?— 不允许硬编码中文
|
||||
- [ ] i18n key 是否在 zh-CN 和 en-US 都有定义?
|
||||
|
||||
### 权限
|
||||
- [ ] 按钮/菜单是否有权限控制(v-permission 指令)?
|
||||
23
skills-dev/review-checklist-plugin/checklists/general.md
Normal file
23
skills-dev/review-checklist-plugin/checklists/general.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# 通用代码评审检查清单
|
||||
|
||||
适用于所有项目,补充五视角扫描法。
|
||||
|
||||
## API 设计
|
||||
- [ ] RESTful 命名是否规范?(复数名词、无动词)
|
||||
- [ ] 分页参数是否有默认值和上限?
|
||||
- [ ] 响应格式是否统一?(code/message/data)
|
||||
|
||||
## 错误处理
|
||||
- [ ] 错误是否被正确传播?(不要吞掉错误)
|
||||
- [ ] 用户可见的错误消息是否友好?(不暴露技术细节)
|
||||
- [ ] 是否有 panic recover 兜底?
|
||||
|
||||
## 性能
|
||||
- [ ] 列表查询是否有分页?(不允许无限制查询)
|
||||
- [ ] N+1 查询问题?(循环内查数据库)
|
||||
- [ ] 是否有不必要的全表扫描?(缺少索引)
|
||||
|
||||
## 可维护性
|
||||
- [ ] 魔法数字是否提取为常量?
|
||||
- [ ] 复杂业务逻辑是否有注释说明?
|
||||
- [ ] 函数是否过长?(超过 100 行考虑拆分)
|
||||
49
skills-dev/review-checklist-plugin/skills/SKILL.md
Normal file
49
skills-dev/review-checklist-plugin/skills/SKILL.md
Normal file
@@ -0,0 +1,49 @@
|
||||
---
|
||||
name: review-checklist
|
||||
description: 项目级代码评审检查清单。按项目积累特定检查项,挂载在 dev-review 下自动加载。每次 CR 时触发。
|
||||
---
|
||||
|
||||
# 代码评审检查清单插件 (review-checklist)
|
||||
|
||||
## 概述
|
||||
|
||||
本插件为 `dev-review` 提供**项目特定的检查清单**,补充五视角扫描法之外的项目级经验。
|
||||
|
||||
检查清单按项目独立维护,每个项目文件记录该项目踩过的坑和必查项。
|
||||
|
||||
## 使用方式
|
||||
|
||||
1. `dev-review` 执行五视角扫描时,自动加载当前项目的检查清单
|
||||
2. 扫描完成后,逐条检查清单项
|
||||
3. 检查结果附加到 CR 报告的「项目检查清单」章节
|
||||
|
||||
## 检查清单文件
|
||||
|
||||
```
|
||||
review-checklist-plugin/
|
||||
├── skills/SKILL.md # 本文件
|
||||
└── checklists/
|
||||
├── ai-proj.md # AI-Proj 项目清单
|
||||
├── coolbuy-paas.md # 酷采3.0 项目清单
|
||||
└── general.md # 通用清单(所有项目适用)
|
||||
```
|
||||
|
||||
## 如何添加检查项
|
||||
|
||||
当 CR 中发现了一个**项目特有**的问题模式,且未来可能复发时:
|
||||
|
||||
1. 打开对应项目的检查清单文件
|
||||
2. 添加条目,格式:`- [ ] {检查项} — 教训:{来源}`
|
||||
3. 标注严重度和适用范围
|
||||
|
||||
**不要添加**五视角扫描已覆盖的通用安全/并发/边界问题。
|
||||
|
||||
## CR 报告附加章节
|
||||
|
||||
```markdown
|
||||
### 项目检查清单({项目名})
|
||||
|
||||
| # | 检查项 | 结果 | 说明 |
|
||||
|---|--------|------|------|
|
||||
| 1 | {检查项} | ✅/❌/N/A | {说明} |
|
||||
```
|
||||
Reference in New Issue
Block a user