add-coder 0.1.5 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +700 -0
- package/README.md +117 -11
- package/dist/index.js +38 -30
- package/package.json +18 -13
- package/templates/adapters/qoder/hooks/doc-format-guard.sh +0 -0
- package/templates/adapters/qoder/hooks/lib/context-inject.sh +0 -0
- package/templates/adapters/qoder/hooks/lib/state-detect.sh +0 -0
- package/templates/adapters/qoder/hooks/lib/vocabulary.sh +0 -0
- package/templates/adapters/qoder/hooks/notification.sh +0 -0
- package/templates/adapters/qoder/hooks/permission-gate.sh +0 -0
- package/templates/adapters/qoder/hooks/post-tool-failure.sh +0 -0
- package/templates/adapters/qoder/hooks/post-tool-use.sh +0 -0
- package/templates/adapters/qoder/hooks/pre-compact.sh +0 -0
- package/templates/adapters/qoder/hooks/pre-tool-use.sh +0 -0
- package/templates/adapters/qoder/hooks/prompt-submit.sh +0 -0
- package/templates/adapters/qoder/hooks/review-checklist.sh +0 -0
- package/templates/adapters/qoder/hooks/session-start.sh +0 -0
- package/templates/adapters/qoder/hooks/stop-check.sh +0 -0
- package/templates/adapters/qoder/hooks/subagent-guard.sh +0 -0
- package/templates/core/plans/2026-07/08/farm-agent-add-coder-npm-package-add-route-v1.md +10 -2
- package/templates/core/plans/2026-07/08/farm-agent-add-coder-npm-package-handoff-v1.md +8 -0
- package/templates/core/plans/2026-07/08/farm-agent-add-coder-npm-package-plan-v1.md +111 -1
- package/templates/core/scripts/mcp-server.ts +59 -17
- package/templates/core/specs/farm-agent-add-coder-npm-package/spec.md +19 -3
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
- ADD Route: `.qoder/plans/2026-07/08/farm-agent-add-coder-npm-package-add-route-v1.md` ✅
|
|
12
12
|
- Handoff: `.qoder/plans/2026-07/08/farm-agent-add-coder-npm-package-handoff-v1.md` ✅
|
|
13
13
|
- Review: `.qoder/reviews/farm-agent-add-coder-npm-package-review-v1.md` ✅
|
|
14
|
+
- Review v2: `.qoder/reviews/farm-agent-add-coder-npm-package-review-v2.md` ✅ — 代码实现评审,2 条 P0(spawnSync catch 失能、ask 重复定义)
|
|
14
15
|
- **ADD-7 审计策略**:
|
|
15
16
|
|
|
16
17
|
| 文件 | targetType | action | beforeState | afterState | 状态 |
|
|
@@ -242,10 +243,11 @@ packages/add-coder/
|
|
|
242
243
|
│ │ ├── skills/ # add-paradigm/SKILL.md, session-init/SKILL.md
|
|
243
244
|
│ │ ├── docs/ # 15 个 .md 模板(plan/spec/tasks/checklist/handoff/review/add-route 等)
|
|
244
245
|
│ │ ├── docs-schema/ # 15 个 .schema.json
|
|
246
|
+
│ │ ├── plans/ # 示例 plans(含 add-coder 6轮范例)
|
|
247
|
+
│ │ ├── specs/ # 示例 specs(含 add-coder spec/tasks/checklist)
|
|
245
248
|
│ │ ├── rules/ # project_rules.md, theory-practice-map.toml
|
|
246
249
|
│ │ ├── vocabulary/ # add-governance-vocabulary.md
|
|
247
250
|
│ │ ├── scripts/ # mcp-server.ts, add-coder-mcp-server.ts
|
|
248
|
-
│ │ ├── prisma/ # add.prisma(ADD 治理模型,init 时复制到用户项目)
|
|
249
251
|
│ │ ├── reports/ # 7 个 report 模板
|
|
250
252
|
│ │ └── tools/ # README.md
|
|
251
253
|
│ │
|
|
@@ -273,6 +275,90 @@ packages/add-coder/
|
|
|
273
275
|
└── README.md
|
|
274
276
|
```
|
|
275
277
|
|
|
278
|
+
|
|
279
|
+
# ──── npx add-coder init 后的用户项目结构 ────
|
|
280
|
+
|
|
281
|
+
```
|
|
282
|
+
用户项目/
|
|
283
|
+
├── .add/ # ★ ADD 蓝图(推荐路径)
|
|
284
|
+
│ ├── agents/ # ← templates/core/agents/
|
|
285
|
+
│ ├── skills/ # ← templates/core/skills/
|
|
286
|
+
│ ├── templates/ # ← templates/core/docs/(.md 模板 + .schema.json,扁平)
|
|
287
|
+
│ ├── rules/ # ← templates/core/rules/
|
|
288
|
+
│ ├── vocabulary/ # ← templates/core/vocabulary/
|
|
289
|
+
│ ├── scripts/ # ← templates/core/scripts/
|
|
290
|
+
│ ├── hooks/ # ← templates/adapters/{target}/hooks/
|
|
291
|
+
│ ├── plans/ # ← templates/core/plans/
|
|
292
|
+
│ ├── specs/ # ← templates/core/specs/
|
|
293
|
+
│ ├── reports/ # ← templates/core/reports/
|
|
294
|
+
│ ├── tools/ # ← templates/core/tools/
|
|
295
|
+
│ ├── debug-dump/ # ← templates/shared/debug-dump/(空目录占位)
|
|
296
|
+
│ ├── repowiki/ # ← templates/shared/repowiki/(空目录占位)
|
|
297
|
+
│ ├── reviews/ # ← 用户自建(init 后空目录)
|
|
298
|
+
│ ├── mcp.json # ← templates/adapters/{target}/mcp.json
|
|
299
|
+
│ ├── settings.json # ← templates/adapters/{target}/settings.json
|
|
300
|
+
│ └── sync-policy.json # ← templates/adapters/qoder/sync-policy.json
|
|
301
|
+
│
|
|
302
|
+
├── .qoder/ # ★ Qoder IDE 配置
|
|
303
|
+
│ ├── agents/ # ← 同 .add/agents/
|
|
304
|
+
│ ├── skills/ # ← 同 .add/skills/
|
|
305
|
+
│ ├── templates/ # ← 同 .add/templates/
|
|
306
|
+
│ ├── rules/ # ← 同 .add/rules/
|
|
307
|
+
│ ├── vocabulary/ # ← 同 .add/vocabulary/
|
|
308
|
+
│ ├── scripts/ # ← 同 .add/scripts/
|
|
309
|
+
│ ├── hooks/ # ← adapter/qoder/hooks/(Qoder 专属 matcher)
|
|
310
|
+
│ ├── plans/ # ← 同 .add/plans/
|
|
311
|
+
│ ├── specs/ # ← 同 .add/specs/
|
|
312
|
+
│ ├── reports/ # ← 同 .add/reports/
|
|
313
|
+
│ ├── tools/ # ← 同 .add/tools/
|
|
314
|
+
│ ├── debug-dump/ # ← 同 .add/debug-dump/
|
|
315
|
+
│ ├── repowiki/ # ← 同 .add/repowiki/
|
|
316
|
+
│ ├── reviews/ # ← 同 .add/reviews/
|
|
317
|
+
│ ├── mcp.json # ← adapter/qoder/mcp.json
|
|
318
|
+
│ ├── settings.json # ← adapter/qoder/settings.json
|
|
319
|
+
│ └── sync-policy.json # ← adapter/qoder/sync-policy.json
|
|
320
|
+
│
|
|
321
|
+
├── .claude/ # ★ Claude Code 配置
|
|
322
|
+
│ ├── agents/ # ← 同 .add/agents/
|
|
323
|
+
│ ├── skills/ # ← 同 .add/skills/
|
|
324
|
+
│ ├── templates/ # ← 同 .add/templates/
|
|
325
|
+
│ ├── rules/ # ← 同 .add/rules/
|
|
326
|
+
│ ├── vocabulary/ # ← 同 .add/vocabulary/
|
|
327
|
+
│ ├── scripts/ # ← 同 .add/scripts/
|
|
328
|
+
│ ├── hooks/ # ← adapter/claude/hooks/(Claude 标准工具名)
|
|
329
|
+
│ ├── plans/ # ← 同 .add/plans/
|
|
330
|
+
│ ├── specs/ # ← 同 .add/specs/
|
|
331
|
+
│ ├── reports/ # ← 同 .add/reports/
|
|
332
|
+
│ ├── tools/ # ← 同 .add/tools/
|
|
333
|
+
│ ├── debug-dump/ # ← 同 .add/debug-dump/
|
|
334
|
+
│ ├── repowiki/ # ← 同 .add/repowiki/
|
|
335
|
+
│ ├── reviews/ # ← 同 .add/reviews/
|
|
336
|
+
│ ├── mcp.json # ← adapter/claude/mcp.json
|
|
337
|
+
│ └── settings.json # ← adapter/claude/settings.json
|
|
338
|
+
│
|
|
339
|
+
├── .vscode/ # ★ VS Code 配置
|
|
340
|
+
│ ├── settings.json # ← templates/adapters/vscode/settings.json
|
|
341
|
+
│ ├── launch.json # ← templates/adapters/vscode/launch.json
|
|
342
|
+
│ ├── tasks.json # ← templates/adapters/vscode/tasks.json
|
|
343
|
+
│ └── extensions.json # ← templates/adapters/vscode/extensions.json
|
|
344
|
+
│
|
|
345
|
+
├── prisma/
|
|
346
|
+
│ ├── schema.prisma # 用户已有或 prisma init 创建
|
|
347
|
+
│ └── add.prisma # injectPrisma 注入(来自 npm 包内置)
|
|
348
|
+
│
|
|
349
|
+
└── .env.development # prisma init 创建,用户配置 DATABASE_URL
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
> **部署策略**:`templates/core/` 内容复制到 `.add/`、`.qoder/`、`.claude/` 三个目录。
|
|
353
|
+
> IDE 只认自身的 magic path(`.qoder/` / `.claude/`),必须各自包含完整内容。
|
|
354
|
+
> `.add/` 保留作为 add-coder 推荐蓝图,供未来工具链引用。
|
|
355
|
+
|
|
356
|
+
> **⚠️ 改造待执行**:当前 `renderCore()` 仅输出到 `.add/`,需改造为三目录并行输出:
|
|
357
|
+
> 1. `src/core/renderer.ts`:`renderCore()` 返回值改为 `Map<string, string>[]`(三份)
|
|
358
|
+
> 2. `src/cli/commands/init.ts`:core 文件写入 `.add/` `.qoder/` `.claude/` 三个目标
|
|
359
|
+
> 3. adapter renderers:不再单独部署 core 内容,只处理 adapter 专属文件(hooks/mcp/settings)
|
|
360
|
+
> 4. 写入去重:三目录同名文件只写一次,后两次 skip(内容相同)
|
|
361
|
+
|
|
276
362
|
**关键命名决策**:旧的 `templates/templates/` 嵌套命名 → 改为 `templates/core/docs/`,避免 `templates/templates/` 这种令人困惑的路径。
|
|
277
363
|
|
|
278
364
|
**渲染器路径约定**:
|
|
@@ -366,6 +452,25 @@ const adapterDir = path.join(TEMPLATES_ROOT, 'adapters', target)
|
|
|
366
452
|
> **add-coder 作为通用转录引擎**:类似 Prisma 的 `prisma generate`——读 caijue.toml,生成策略代码。
|
|
367
453
|
> 引擎本身不关心 caijue.toml 的内容来源,只负责"TOML → TS"的编译时转录。
|
|
368
454
|
|
|
455
|
+
#### 3.5.1 实际实现架构(偏离原 Plan §3.5.2,以 handoff §7 为准)
|
|
456
|
+
|
|
457
|
+
```
|
|
458
|
+
caijue.toml(索引) *-rules.toml(规则参数) strategies/*.ts
|
|
459
|
+
───────────────── ──────────────────── ┌──────────────────┐
|
|
460
|
+
[[caijue]] detect-rules.toml → │ GENERATED (转录) │
|
|
461
|
+
rules = "detect-rules" prisma-rules.toml → │ DETECT_RULES=[] │
|
|
462
|
+
impl = "strategies/..." adapter-rules.toml → │ PRISMA_CONFIG={} │
|
|
463
|
+
writer-rules.toml → ├──────────────────┤
|
|
464
|
+
│ USER CODE (手写) │
|
|
465
|
+
转录流程: │ detectIDE() │
|
|
466
|
+
npm run generate → transcribe.ts → GENERATED 区块 │ injectPrisma() │
|
|
467
|
+
└──────────────────┘
|
|
468
|
+
|
|
469
|
+
- caijue.toml 只做索引,不耦合规则逻辑
|
|
470
|
+
- *-rules.toml 定义规则参数,transcribe.ts 产出 GENERATED 区块
|
|
471
|
+
- USER CODE 手写业务逻辑,npm run generate 不覆盖
|
|
472
|
+
```
|
|
473
|
+
|
|
369
474
|
#### 3.5.1 裁决点清单
|
|
370
475
|
|
|
371
476
|
| 裁决点 | 当前位置 | 决策内容 | 归入 caijue |
|
|
@@ -525,6 +630,8 @@ packages/add-coder/
|
|
|
525
630
|
|
|
526
631
|
**验收**:在空白 Prisma 项目中执行 `prisma migrate dev --schema=prisma/` 成功创建 DevOperation 和 AuditLog 表
|
|
527
632
|
|
|
633
|
+
> **Review v2 回流(P0-1)**:`prisma-injector.ts` 中 `spawnSync` 返回状态须检查 `r.status`,不可依赖 try/catch。迁移失败时 `add.prisma` 回滚删除。
|
|
634
|
+
|
|
528
635
|
#### Task 1: 清理硬编码 + 参数化 core 模板
|
|
529
636
|
|
|
530
637
|
**范围**:`packages/add-coder/templates/` 下所有文件(共 ~70 个文件)
|
|
@@ -741,6 +848,9 @@ packages/add-coder/
|
|
|
741
848
|
|
|
742
849
|
**回流机制**:
|
|
743
850
|
- Review 发现的 P0/P1 问题回写至 Plan 对应章节
|
|
851
|
+
- Review v2 P0-1(spawnSync catch 失能):已在 Task 0 补充验收项
|
|
852
|
+
- Review v2 P0-2(ask 重复定义):已记录至 Task 1(CaijueHub 重构时一并提取到 utils)
|
|
853
|
+
- Review v2 P1-1/2/3(unlinkSync 缺口、gitignore):已记录至 CI 基建清单
|
|
744
854
|
- 回流完成后方可进入 Step 1 实施
|
|
745
855
|
- P2 问题在 Step 3 实施前解决或记录为 Known Issue
|
|
746
856
|
|
|
@@ -23,9 +23,9 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"
|
|
|
23
23
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
|
|
24
24
|
import { z } from "zod"
|
|
25
25
|
import { readFile, readdir, stat, mkdir, writeFile } from "fs/promises"
|
|
26
|
-
import { join, relative
|
|
26
|
+
import { join, relative } from "path"
|
|
27
27
|
import { existsSync } from "fs"
|
|
28
|
-
import {
|
|
28
|
+
import { spawnSync } from "child_process"
|
|
29
29
|
import { PrismaClient, Prisma } from "@prisma/client"
|
|
30
30
|
|
|
31
31
|
const prisma = new PrismaClient({
|
|
@@ -51,6 +51,31 @@ async function readFileSafe(filePath: string): Promise<string | null> {
|
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
// ── ADD 文档模板校验(共享函数,供 create_plan / check_add_compliance / check_spec_sync 等复用)──
|
|
55
|
+
|
|
56
|
+
interface GuardResult { ok: boolean; issues: string }
|
|
57
|
+
|
|
58
|
+
async function validateDocWithGuard(filePath: string): Promise<GuardResult> {
|
|
59
|
+
const guardScript = join(PROJECT_ROOT, MAGIC_DIR, "hooks", "doc-format-guard.sh")
|
|
60
|
+
if (!existsSync(guardScript)) return { ok: true, issues: "" }
|
|
61
|
+
const content = await readFileSafe(filePath)
|
|
62
|
+
if (!content) return { ok: false, issues: "文件无法读取" }
|
|
63
|
+
const guardInput = JSON.stringify({
|
|
64
|
+
tool_input: { file_path: filePath, file_content: content },
|
|
65
|
+
})
|
|
66
|
+
const guard = spawnSync("/bin/bash", [guardScript], {
|
|
67
|
+
input: guardInput,
|
|
68
|
+
encoding: "utf-8",
|
|
69
|
+
timeout: 15000,
|
|
70
|
+
cwd: PROJECT_ROOT,
|
|
71
|
+
env: { ...process.env, MAGIC_DIR },
|
|
72
|
+
})
|
|
73
|
+
if (guard.status === 2 || guard.stderr?.includes("校验不通过")) {
|
|
74
|
+
return { ok: false, issues: guard.stderr || guard.stdout || "校验失败" }
|
|
75
|
+
}
|
|
76
|
+
return { ok: true, issues: "" }
|
|
77
|
+
}
|
|
78
|
+
|
|
54
79
|
/** 递归读取目录下所有文件(扁平化返回),支持 ${MAGIC_DIR}/plans/2026-06/05/ 等分层结构 */
|
|
55
80
|
async function readdirRecursive(dir: string): Promise<string[]> {
|
|
56
81
|
const results: string[] = []
|
|
@@ -2080,7 +2105,9 @@ server.registerTool(
|
|
|
2080
2105
|
return errorResponse(`未找到匹配的 Plan 文件(关键词: ${args.planKeyword})`)
|
|
2081
2106
|
}
|
|
2082
2107
|
const planPath = join(plansDir, planMatch)
|
|
2108
|
+
const planGuard = await validateDocWithGuard(planPath)
|
|
2083
2109
|
lines.push(`Plan: ${planMatch}`)
|
|
2110
|
+
if (!planGuard.ok) lines.push(` ⚠️ 模板校验: ${planGuard.issues.split("\n")[0]}`)
|
|
2084
2111
|
|
|
2085
2112
|
// 2. 从 Plan 中提取关联的 spec 目录名
|
|
2086
2113
|
const planContent = await readFileSafe(planPath)
|
|
@@ -2387,9 +2414,10 @@ server.registerTool(
|
|
|
2387
2414
|
// 5. Git diff 统计
|
|
2388
2415
|
let changedFiles: string[] = []
|
|
2389
2416
|
if (isEnabled("gitDiff")) {
|
|
2390
|
-
const {
|
|
2417
|
+
const { spawnSync } = await import("child_process")
|
|
2391
2418
|
try {
|
|
2392
|
-
const
|
|
2419
|
+
const diff = spawnSync("git", ["diff", "--name-only"], { cwd: PROJECT_ROOT, encoding: "utf-8", timeout: 5000 })
|
|
2420
|
+
const diffStat = diff.stdout || ""
|
|
2393
2421
|
changedFiles = diffStat.trim().split("\n").filter(Boolean)
|
|
2394
2422
|
} catch {
|
|
2395
2423
|
lines.push("Git diff: 无法获取(可能无 git 仓库或无暂存变更)")
|
|
@@ -2576,6 +2604,9 @@ server.registerTool(
|
|
|
2576
2604
|
return errorResponse(`add-route 完整性扫描失败:无法读取文件 ${matchedFile}`)
|
|
2577
2605
|
}
|
|
2578
2606
|
|
|
2607
|
+
// 模板格式校验
|
|
2608
|
+
const routeGuard = await validateDocWithGuard(filePath)
|
|
2609
|
+
|
|
2579
2610
|
const lines = content.split("\n")
|
|
2580
2611
|
|
|
2581
2612
|
// === 3. 解析 Step 结构和勾选状态 ===
|
|
@@ -2681,6 +2712,7 @@ server.registerTool(
|
|
|
2681
2712
|
"",
|
|
2682
2713
|
`整体完成度: ${globalChecked}/${globalTotal} (${completionRate}%)`,
|
|
2683
2714
|
`状态: ${isComplete ? "✅ complete — add-route 完整闭环" : "⚠️ incomplete — 存在未勾选 Step"}`,
|
|
2715
|
+
`模板校验: ${routeGuard.ok ? "✅ 通过" : `⚠️ ${routeGuard.issues.split("\n")[0]}`}`,
|
|
2684
2716
|
"",
|
|
2685
2717
|
]
|
|
2686
2718
|
|
|
@@ -3198,8 +3230,9 @@ server.registerTool(
|
|
|
3198
3230
|
let scopeScore = 100
|
|
3199
3231
|
let changedFiles: string[] = []
|
|
3200
3232
|
try {
|
|
3201
|
-
const {
|
|
3202
|
-
const
|
|
3233
|
+
const { spawnSync } = await import("child_process")
|
|
3234
|
+
const diff = spawnSync("git", ["diff", "--name-only"], { cwd: PROJECT_ROOT, encoding: "utf-8", timeout: 5000 })
|
|
3235
|
+
const diffStat = diff.stdout || ""
|
|
3203
3236
|
changedFiles = diffStat.trim().split("\n").filter(Boolean)
|
|
3204
3237
|
} catch { /* ignore */ }
|
|
3205
3238
|
|
|
@@ -3240,12 +3273,13 @@ server.registerTool(
|
|
|
3240
3273
|
// ====== 维度二:类型安全(权重 20%) ======
|
|
3241
3274
|
let typeScore = 100
|
|
3242
3275
|
try {
|
|
3243
|
-
const {
|
|
3244
|
-
const
|
|
3276
|
+
const { spawnSync } = await import("child_process")
|
|
3277
|
+
const tsc = spawnSync("npx", ["tsc", "--noEmit"], {
|
|
3245
3278
|
cwd: PROJECT_ROOT,
|
|
3246
3279
|
encoding: "utf-8",
|
|
3247
3280
|
timeout: 30000,
|
|
3248
3281
|
})
|
|
3282
|
+
const tscOut = (tsc.stdout || "") + (tsc.stderr || "")
|
|
3249
3283
|
// 统计 error TS 行数
|
|
3250
3284
|
const errorLines = tscOut.split("\n").filter(l => l.includes("error TS")).length
|
|
3251
3285
|
typeScore = Math.max(0, 100 - errorLines * 10)
|
|
@@ -3431,20 +3465,28 @@ server.registerTool(
|
|
|
3431
3465
|
|
|
3432
3466
|
// 写入 Plan 文件
|
|
3433
3467
|
await writeFile(filePath, content, "utf-8")
|
|
3468
|
+
|
|
3469
|
+
// 写后校验
|
|
3470
|
+
const guard = await validateDocWithGuard(filePath)
|
|
3471
|
+
if (!guard.ok) {
|
|
3472
|
+
try { await import("fs/promises").then(m => m.unlink(filePath)) } catch { }
|
|
3473
|
+
return errorResponse(`Plan 模板校验不通过,拒绝写入:\n${guard.issues}`)
|
|
3474
|
+
}
|
|
3475
|
+
|
|
3434
3476
|
parts.push(`✅ Plan 文件已创建: ${relativePath}`)
|
|
3435
3477
|
|
|
3436
3478
|
// 更新 index.md
|
|
3437
3479
|
const indexScript = join(PROJECT_ROOT, "scripts", "gen-plan-index.sh")
|
|
3438
3480
|
if (existsSync(indexScript)) {
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
parts.push(`📋 index.md 已更新: ${result.trim()}`)
|
|
3446
|
-
}
|
|
3447
|
-
parts.push(`⚠️ index.md
|
|
3481
|
+
const result = spawnSync("/bin/bash", [indexScript], {
|
|
3482
|
+
cwd: PROJECT_ROOT,
|
|
3483
|
+
encoding: "utf-8",
|
|
3484
|
+
timeout: 10000,
|
|
3485
|
+
})
|
|
3486
|
+
if (result.status === 0) {
|
|
3487
|
+
parts.push(`📋 index.md 已更新: ${result.stdout?.trim() || "ok"}`)
|
|
3488
|
+
} else {
|
|
3489
|
+
parts.push(`⚠️ index.md 更新失败: ${result.stderr?.trim() || result.error?.message || "unknown"}`)
|
|
3448
3490
|
}
|
|
3449
3491
|
} else {
|
|
3450
3492
|
parts.push(`⚠️ gen-plan-index.sh 不存在,index.md 将在 crontab 自动更新`)
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
| 轮次 | 变更概要 | 涉及文件 |
|
|
19
19
|
|:--:|------|------|
|
|
20
|
-
| 1 | Prisma 模型准备 + 清理硬编码 | `
|
|
20
|
+
| 1 | Prisma 模型准备 + 清理硬编码 | `src/cli/prisma-injector.ts`(add.prisma 内置在 npm 包)、`templates/` 下约 70 个文件 |
|
|
21
21
|
| 2 | 模板目录重组 + 适配器架构搭建 | `templates/core/`、`src/adapters/`、`src/core/`、旧 `templates/` 迁移 |
|
|
22
22
|
| 3 | 三端适配器实现(Claude → Qoder → VS Code 串行) | 见下方 Hook 清单 |
|
|
23
23
|
| 4 | 配置系统(Zod schema)+ CLI 重写 | `src/config/`、`src/cli/`、`bin/add-coder.js`、`tsup.config.ts` |
|
|
@@ -171,6 +171,17 @@
|
|
|
171
171
|
- **WHEN** 重复执行 `add-coder init`
|
|
172
172
|
- **THEN** `prisma migrate dev` 不报错(已应用的迁移自动跳过)
|
|
173
173
|
|
|
174
|
+
#### Scenario: 三目录部署(core 内容同步到 IDE magic path)
|
|
175
|
+
|
|
176
|
+
- **WHEN** 执行 `init` 渲染 core 模板后
|
|
177
|
+
- **THEN** `templates/core/` 的所有文件 SHALL 同时写入 `.add/`、`.qoder/`、`.claude/` 三个目标目录
|
|
178
|
+
- **AND** adapter renderers SHALL 只处理 adapter 专属文件(hooks/mcp.json/settings.json/sync-policy.json),不再单独渲染 core 内容
|
|
179
|
+
|
|
180
|
+
**改造步骤**:
|
|
181
|
+
1. `src/core/renderer.ts`:`renderCore()` 返回值改为输出三份文件的映射(`.add/` + `.qoder/` + `.claude/`)
|
|
182
|
+
2. `src/cli/commands/init.ts`:写入阶段对三目录同名文件去重(内容相同则 skip)
|
|
183
|
+
3. `src/adapters/{claude,qoder,vscode}/renderer.ts`:删除 core 渲染逻辑,只保留 hooks + mcp + settings 等 adapter 专属文件
|
|
184
|
+
|
|
174
185
|
---
|
|
175
186
|
|
|
176
187
|
### Requirement: 适配器三层架构
|
|
@@ -317,10 +328,15 @@
|
|
|
317
328
|
|
|
318
329
|
系统 SHALL 在空白项目中通过完整的 init 流程验证。
|
|
319
330
|
|
|
320
|
-
#### Scenario:
|
|
331
|
+
#### Scenario: 空项目 init
|
|
321
332
|
|
|
322
333
|
- **WHEN** 在空白项目中执行 `npx add-coder init`
|
|
323
|
-
- **THEN**
|
|
334
|
+
- **THEN** `.add/` `.qoder/` `.claude/` 三目录均含完整 ADD 内容(agents/skills/templates/rules/vocabulary/scripts/hooks/plans/specs/reports/tools),`.vscode/` 含 IDE 配置
|
|
335
|
+
|
|
336
|
+
#### Scenario: plans/specs 示例
|
|
337
|
+
|
|
338
|
+
- **WHEN** 用户首次 init
|
|
339
|
+
- **THEN** `.qoder/plans/` 含 add-coder 6轮范例,`.qoder/specs/` 含 spec/tasks/checklist 范例
|
|
324
340
|
|
|
325
341
|
#### Scenario: 三端兼容
|
|
326
342
|
|