@devcxl/opencode-cabbage 1.1.0 → 1.3.0

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.
Files changed (142) hide show
  1. package/.codex-plugin/plugin.json +36 -0
  2. package/README.md +53 -25
  3. package/README.zh.md +23 -23
  4. package/assets/agents/dev-lifecycle.md +208 -68
  5. package/assets/agents/team/architect.md +22 -7
  6. package/assets/agents/team/developer.md +13 -6
  7. package/assets/agents/team/goal-verify.md +4 -1
  8. package/assets/agents/team/researcher.md +59 -0
  9. package/assets/agents/team/reviewer.md +34 -18
  10. package/assets/commands/setup.md +1 -1
  11. package/assets/prompts/bootstrap.md +10 -9
  12. package/assets/prompts/stage-contract.md +25 -25
  13. package/assets/skills/flow-code/SKILL.md +23 -25
  14. package/assets/skills/flow-design/SKILL.md +94 -26
  15. package/assets/skills/flow-release/SKILL.md +41 -17
  16. package/assets/skills/flow-requirements/SKILL.md +19 -13
  17. package/assets/skills/flow-research/SKILL.md +77 -0
  18. package/assets/skills/flow-review/SKILL.md +55 -25
  19. package/assets/skills/flow-setup/SKILL.md +27 -24
  20. package/assets/skills/flow-tasks/SKILL.md +178 -35
  21. package/assets/skills/flow-tdd/SKILL.md +68 -40
  22. package/codex-skills/agent-architect/SKILL.md +79 -0
  23. package/codex-skills/agent-dev-lifecycle/SKILL.md +309 -0
  24. package/codex-skills/agent-developer/SKILL.md +51 -0
  25. package/codex-skills/agent-goal-verify/SKILL.md +45 -0
  26. package/codex-skills/agent-researcher/SKILL.md +32 -0
  27. package/codex-skills/agent-reviewer/SKILL.md +109 -0
  28. package/codex-skills/flow-code/SKILL.md +71 -0
  29. package/codex-skills/flow-design/SKILL.md +146 -0
  30. package/codex-skills/flow-release/SKILL.md +90 -0
  31. package/codex-skills/flow-requirements/SKILL.md +90 -0
  32. package/codex-skills/flow-research/SKILL.md +77 -0
  33. package/codex-skills/flow-review/SKILL.md +110 -0
  34. package/codex-skills/flow-setup/SKILL.md +75 -0
  35. package/codex-skills/flow-tasks/SKILL.md +220 -0
  36. package/codex-skills/flow-tdd/SKILL.md +235 -0
  37. package/dist/hooks/session-start.d.ts +1 -0
  38. package/dist/hooks/session-start.js +72 -0
  39. package/dist/hooks/session-start.js.map +1 -0
  40. package/dist/kernel/session-index.d.ts +8 -25
  41. package/dist/kernel/session-index.js +5 -55
  42. package/dist/kernel/session-index.js.map +1 -1
  43. package/dist/plugin/bootstrap.d.ts +0 -1
  44. package/dist/plugin/bootstrap.js +0 -3
  45. package/dist/plugin/bootstrap.js.map +1 -1
  46. package/dist/plugin/goal-store.d.ts +71 -0
  47. package/dist/plugin/goal-store.js +54 -0
  48. package/dist/plugin/goal-store.js.map +1 -0
  49. package/dist/plugin/goal.d.ts +47 -13
  50. package/dist/plugin/goal.js +228 -128
  51. package/dist/plugin/goal.js.map +1 -1
  52. package/dist/plugin/prompt-lint.js +3 -11
  53. package/dist/plugin/prompt-lint.js.map +1 -1
  54. package/dist/plugin/prompts.d.ts +0 -1
  55. package/dist/plugin/prompts.js +0 -4
  56. package/dist/plugin/prompts.js.map +1 -1
  57. package/dist/plugin/server.d.ts +3 -5
  58. package/dist/plugin/server.js +247 -155
  59. package/dist/plugin/server.js.map +1 -1
  60. package/dist/plugin/skills.d.ts +7 -1
  61. package/dist/plugin/skills.js +75 -12
  62. package/dist/plugin/skills.js.map +1 -1
  63. package/dist/plugin.d.ts +0 -1
  64. package/dist/plugin.js +1 -4
  65. package/dist/plugin.js.map +1 -1
  66. package/dist/util/gh.d.ts +0 -11
  67. package/dist/util/gh.js +0 -14
  68. package/dist/util/gh.js.map +1 -1
  69. package/dist/util/paths.d.ts +0 -14
  70. package/dist/util/paths.js +0 -69
  71. package/dist/util/paths.js.map +1 -1
  72. package/hooks/hooks.json +17 -0
  73. package/package.json +12 -4
  74. package/assets/prompts/ADR-FORMAT.md +0 -45
  75. package/assets/prompts/PRD-FORMAT.md +0 -17
  76. package/assets/templates/gitignore +0 -5
  77. package/dist/kernel/caller.d.ts +0 -48
  78. package/dist/kernel/caller.js +0 -88
  79. package/dist/kernel/caller.js.map +0 -1
  80. package/dist/kernel/flow.d.ts +0 -175
  81. package/dist/kernel/flow.js +0 -467
  82. package/dist/kernel/flow.js.map +0 -1
  83. package/dist/kernel/legacy.d.ts +0 -19
  84. package/dist/kernel/legacy.js +0 -34
  85. package/dist/kernel/legacy.js.map +0 -1
  86. package/dist/kernel/records.d.ts +0 -103
  87. package/dist/kernel/records.js +0 -240
  88. package/dist/kernel/records.js.map +0 -1
  89. package/dist/kernel/release.d.ts +0 -106
  90. package/dist/kernel/release.js +0 -241
  91. package/dist/kernel/release.js.map +0 -1
  92. package/dist/kernel/review.d.ts +0 -34
  93. package/dist/kernel/review.js +0 -82
  94. package/dist/kernel/review.js.map +0 -1
  95. package/dist/kernel/setup.d.ts +0 -95
  96. package/dist/kernel/setup.js +0 -401
  97. package/dist/kernel/setup.js.map +0 -1
  98. package/dist/kernel/slug.d.ts +0 -23
  99. package/dist/kernel/slug.js +0 -67
  100. package/dist/kernel/slug.js.map +0 -1
  101. package/dist/kernel/task.d.ts +0 -213
  102. package/dist/kernel/task.js +0 -873
  103. package/dist/kernel/task.js.map +0 -1
  104. package/dist/kernel/tdd/adapter.d.ts +0 -49
  105. package/dist/kernel/tdd/adapter.js +0 -294
  106. package/dist/kernel/tdd/adapter.js.map +0 -1
  107. package/dist/kernel/tdd/digest.d.ts +0 -18
  108. package/dist/kernel/tdd/digest.js +0 -303
  109. package/dist/kernel/tdd/digest.js.map +0 -1
  110. package/dist/kernel/tdd/evaluator.d.ts +0 -38
  111. package/dist/kernel/tdd/evaluator.js +0 -185
  112. package/dist/kernel/tdd/evaluator.js.map +0 -1
  113. package/dist/kernel/tdd/evidence.d.ts +0 -42
  114. package/dist/kernel/tdd/evidence.js +0 -48
  115. package/dist/kernel/tdd/evidence.js.map +0 -1
  116. package/dist/kernel/tdd/state.d.ts +0 -79
  117. package/dist/kernel/tdd/state.js +0 -363
  118. package/dist/kernel/tdd/state.js.map +0 -1
  119. package/dist/kernel/types.d.ts +0 -180
  120. package/dist/kernel/types.js +0 -2
  121. package/dist/kernel/types.js.map +0 -1
  122. package/dist/kernel/worktree.d.ts +0 -45
  123. package/dist/kernel/worktree.js +0 -156
  124. package/dist/kernel/worktree.js.map +0 -1
  125. package/dist/plugin/flow-control.d.ts +0 -91
  126. package/dist/plugin/flow-control.js +0 -287
  127. package/dist/plugin/flow-control.js.map +0 -1
  128. package/dist/plugin/release-control.d.ts +0 -39
  129. package/dist/plugin/release-control.js +0 -343
  130. package/dist/plugin/release-control.js.map +0 -1
  131. package/dist/plugin/setup-control.d.ts +0 -59
  132. package/dist/plugin/setup-control.js +0 -111
  133. package/dist/plugin/setup-control.js.map +0 -1
  134. package/dist/plugin/task-control.d.ts +0 -90
  135. package/dist/plugin/task-control.js +0 -208
  136. package/dist/plugin/task-control.js.map +0 -1
  137. package/dist/plugin/tdd-checkpoint.d.ts +0 -128
  138. package/dist/plugin/tdd-checkpoint.js +0 -664
  139. package/dist/plugin/tdd-checkpoint.js.map +0 -1
  140. package/dist/util/shell.d.ts +0 -1
  141. package/dist/util/shell.js +0 -4
  142. package/dist/util/shell.js.map +0 -1
@@ -1,303 +0,0 @@
1
- import { createHash } from "node:crypto";
2
- import { readFile, lstat, readdir, realpath } from "node:fs/promises";
3
- import { join, resolve, sep, isAbsolute } from "node:path";
4
- import { execFileSync } from "node:child_process";
5
- // ─── 常量 ───
6
- /** 始终忽略的目录 */
7
- const ALWAYS_IGNORED = new Set([
8
- ".git",
9
- "node_modules",
10
- "coverage",
11
- "dist",
12
- ".nyc_output",
13
- ]);
14
- /** 始终忽略的前缀(目录 + 分隔符) */
15
- function isAlwaysIgnored(relPath) {
16
- const parts = relPath.split(sep);
17
- if (parts.length === 0)
18
- return false;
19
- const top = parts[0];
20
- if (!top)
21
- return false;
22
- return ALWAYS_IGNORED.has(top);
23
- }
24
- /** 危险字符正则:拒绝可能逃逸路径的字符 */
25
- const DANGEROUS_PATH = /[\x00-\x1f\x7f]/;
26
- // ─── Git 辅助 ───
27
- function runGit(args, cwd) {
28
- try {
29
- const output = execFileSync("git", args, {
30
- cwd,
31
- encoding: "utf-8",
32
- env: { ...process.env, GIT_CONFIG_NOSYSTEM: "1" },
33
- maxBuffer: 10 * 1024 * 1024,
34
- });
35
- return output.trim().split("\n").filter(Boolean);
36
- }
37
- catch {
38
- return [];
39
- }
40
- }
41
- /** 获取 Git 已跟踪的文件列表(repo-relative paths) */
42
- function getTrackedFiles(cwd) {
43
- const lines = runGit(["ls-files", "--cached", "-z"], cwd);
44
- if (lines.length === 0)
45
- return new Set();
46
- // -z 输出的行以 null 分隔,但 execFileSync 返回时 null 被转为换行
47
- // 实际用 -z 时输出用 \0 分隔,这里按 \0 分割
48
- const raw = execFileSync("git", ["ls-files", "--cached", "-z"], {
49
- cwd, encoding: "utf-8",
50
- env: { ...process.env, GIT_CONFIG_NOSYSTEM: "1" },
51
- maxBuffer: 10 * 1024 * 1024,
52
- });
53
- return new Set(raw.split("\0").filter(Boolean));
54
- }
55
- /** 获取已跟踪但已删除的文件列表 */
56
- function getDeletedFiles(cwd) {
57
- try {
58
- const raw = execFileSync("git", ["ls-files", "--deleted", "-z"], {
59
- cwd, encoding: "utf-8",
60
- env: { ...process.env, GIT_CONFIG_NOSYSTEM: "1" },
61
- maxBuffer: 10 * 1024 * 1024,
62
- });
63
- return new Set(raw.split("\0").filter(Boolean));
64
- }
65
- catch {
66
- return new Set();
67
- }
68
- }
69
- // ─── 模式匹配 ───
70
- /**
71
- * 简单的 glob 匹配(支持 **、*)
72
- * 不做完整 micromatch,仅覆盖常见 pattern
73
- */
74
- function matchPattern(filePath, pattern) {
75
- // 将路径分隔符统一为 /
76
- const normalized = filePath.split(sep).join("/");
77
- // 构建正则
78
- let regexStr = "";
79
- let i = 0;
80
- while (i < pattern.length) {
81
- if (pattern[i] === "*" && pattern[i + 1] === "*") {
82
- // **:零或多个路径段
83
- i += 2;
84
- // 跳过可选的 /(**/ 匹配零或多个目录)
85
- if (i < pattern.length && pattern[i] === "/") {
86
- regexStr += "(.*/)?";
87
- i++;
88
- }
89
- else {
90
- // 独立的 **(末尾):匹配所有
91
- regexStr += ".*";
92
- }
93
- }
94
- else if (pattern[i] === "*") {
95
- // *:匹配单段内的任意字符(除 /)
96
- regexStr += "[^/]*";
97
- i++;
98
- }
99
- else if (pattern[i] === ".") {
100
- regexStr += "\\.";
101
- i++;
102
- }
103
- else if (pattern[i] === "?") {
104
- regexStr += "[^/]";
105
- i++;
106
- }
107
- else {
108
- // 转义正则特殊字符
109
- if ("+^$(){}[]|\\".includes(pattern[i])) {
110
- regexStr += "\\" + pattern[i];
111
- }
112
- else {
113
- regexStr += pattern[i];
114
- }
115
- i++;
116
- }
117
- }
118
- const regex = new RegExp(`^${regexStr}$`);
119
- return regex.test(normalized);
120
- }
121
- export function matchesAnyPattern(filePath, patterns) {
122
- return patterns.some(p => matchPattern(filePath, p));
123
- }
124
- // ─── 路径校验 ───
125
- function validateRelPath(relPath) {
126
- // 拒绝包含危险字符的路径
127
- if (DANGEROUS_PATH.test(relPath)) {
128
- throw new Error(`Dangerous characters in path: ${relPath}`);
129
- }
130
- // 拒绝以 .. 开头的路径
131
- const normalized = relPath.split(sep).join("/");
132
- if (normalized.startsWith("..") || normalized.includes("/../")) {
133
- throw new Error(`Path escapes worktree: ${relPath}`);
134
- }
135
- if (isAbsolute(relPath)) {
136
- throw new Error(`Path must be relative: ${relPath}`);
137
- }
138
- }
139
- // ─── 文件扫描 ───
140
- /**
141
- * 递归列出目录下所有文件(repo-relative paths)
142
- * 忽略 always-ignored 目录
143
- */
144
- async function scanDir(root, subDir = "", results = []) {
145
- const fullPath = subDir ? join(root, subDir) : root;
146
- let dirents;
147
- try {
148
- dirents = await readdir(fullPath, { withFileTypes: true });
149
- }
150
- catch {
151
- return results;
152
- }
153
- for (const entry of dirents) {
154
- const relPath = subDir ? `${subDir}${sep}${entry.name}` : entry.name;
155
- const relPathSlash = relPath.split(sep).join("/");
156
- // 跳过 always-ignored 顶层目录
157
- if (isAlwaysIgnored(relPath))
158
- continue;
159
- if (entry.isDirectory()) {
160
- await scanDir(root, relPath, results);
161
- }
162
- else if (entry.isFile() || entry.isSymbolicLink()) {
163
- results.push(relPathSlash);
164
- }
165
- }
166
- return results;
167
- }
168
- async function collectFileEntries(root, tracked, deleted, untrackedPaths, generatedPatterns) {
169
- const entries = [];
170
- // 处理已跟踪文件
171
- for (const relPath of tracked) {
172
- validateRelPath(relPath);
173
- // 跳过生成的 artifacts
174
- if (matchesAnyPattern(relPath, generatedPatterns))
175
- continue;
176
- // 跳过 always-ignored 目录
177
- if (isAlwaysIgnored(relPath))
178
- continue;
179
- // 已删除文件:使用删除标记
180
- if (deleted.has(relPath)) {
181
- entries.push({ path: relPath, mode: 0, content: null });
182
- continue;
183
- }
184
- const absPath = join(root, relPath);
185
- try {
186
- const fileLstat = await lstat(absPath);
187
- // 检查 symlink 是否逃逸
188
- if (fileLstat.isSymbolicLink()) {
189
- const resolved = await realpath(absPath);
190
- const resolvedNorm = resolve(resolved);
191
- const rootNorm = resolve(root);
192
- if (!resolvedNorm.startsWith(rootNorm + sep) && resolvedNorm !== rootNorm) {
193
- throw new Error(`Symlink escapes worktree: ${relPath} → ${resolved}`);
194
- }
195
- }
196
- if (fileLstat.isFile() || fileLstat.isSymbolicLink()) {
197
- const content = await readFile(absPath);
198
- // mode: 只保留权限位(低 9 位),用于区分可执行位
199
- const mode = fileLstat.mode & 0o777;
200
- entries.push({ path: relPath, mode, content });
201
- }
202
- // 目录、设备文件等跳过
203
- }
204
- catch (err) {
205
- if (err instanceof Error && err.message.startsWith("Symlink escapes")) {
206
- throw err;
207
- }
208
- // 文件不存在(可能被外部删除),添加删除标记
209
- entries.push({ path: relPath, mode: 0, content: null });
210
- }
211
- }
212
- // 处理 policy 范围内的 untracked 文件
213
- for (const relPath of untrackedPaths) {
214
- validateRelPath(relPath);
215
- // 跳过已跟踪文件的重复
216
- if (tracked.has(relPath))
217
- continue;
218
- // 跳过 always-ignored
219
- if (isAlwaysIgnored(relPath))
220
- continue;
221
- // 跳过生成的 artifacts
222
- if (matchesAnyPattern(relPath, generatedPatterns))
223
- continue;
224
- const absPath = join(root, relPath);
225
- try {
226
- const fileLstat = await lstat(absPath);
227
- if (fileLstat.isSymbolicLink()) {
228
- const resolved = await realpath(absPath);
229
- const resolvedNorm = resolve(resolved);
230
- const rootNorm = resolve(root);
231
- if (!resolvedNorm.startsWith(rootNorm + sep) && resolvedNorm !== rootNorm) {
232
- throw new Error(`Symlink escapes worktree: ${relPath} → ${resolved}`);
233
- }
234
- }
235
- if (fileLstat.isFile() || fileLstat.isSymbolicLink()) {
236
- const content = await readFile(absPath);
237
- const mode = fileLstat.mode & 0o777;
238
- entries.push({ path: relPath, mode, content });
239
- }
240
- }
241
- catch (err) {
242
- if (err instanceof Error && err.message.startsWith("Symlink escapes")) {
243
- throw err;
244
- }
245
- // 无法读取的文件跳过
246
- }
247
- }
248
- return entries;
249
- }
250
- // ─── 主函数 ───
251
- /**
252
- * 计算 worktree 的 Canonical Content Digest。
253
- *
254
- * 规则:
255
- * 1. repo-relative paths,按 UTF-8 字节序排序
256
- * 2. 纳入文件类型(含可执行位)、原始字节、删除标记
257
- * 3. 拒绝逃逸 worktree 的 symlink
258
- * 4. 忽略 .git/、node_modules/、coverage/、dist/、policy 声明的 generated artifacts
259
- * 5. tracked + policy 范围内 untracked 文件均纳入
260
- */
261
- export async function computeWorkspaceDigest(root, options) {
262
- const rootNorm = resolve(root);
263
- // 1. 获取 Git 跟踪状态
264
- const tracked = getTrackedFiles(rootNorm);
265
- const deleted = getDeletedFiles(rootNorm);
266
- // 2. 扫描文件系统;tracked 与 untracked 均只纳入匹配 pattern 的文件,
267
- // 保证实现 digest 与测试输入 digest 互不污染(GREEN 门禁依赖此隔离)
268
- const allFiles = await scanDir(rootNorm);
269
- const includedPatterns = [...options.testFilePatterns, ...options.implementationFilePatterns];
270
- const includedTracked = new Set([...tracked].filter(f => matchesAnyPattern(f, includedPatterns)));
271
- const untrackedPaths = new Set(allFiles.filter(f => !tracked.has(f) && matchesAnyPattern(f, includedPatterns)));
272
- // 3. 收集文件条目
273
- const entries = await collectFileEntries(rootNorm, includedTracked, deleted, untrackedPaths, options.generatedArtifactPatterns);
274
- // 4. 按 UTF-8 字节序排序
275
- entries.sort((a, b) => {
276
- const bufA = Buffer.from(a.path, "utf-8");
277
- const bufB = Buffer.from(b.path, "utf-8");
278
- return Buffer.compare(bufA, bufB);
279
- });
280
- // 5. 构建 canonical 内容
281
- const hash = createHash("sha256");
282
- for (const entry of entries) {
283
- // path
284
- hash.update(entry.path);
285
- hash.update("\0");
286
- // mode (8 进制字符串)
287
- hash.update(entry.mode.toString(8));
288
- hash.update("\0");
289
- // content 或删除标记
290
- if (entry.content === null) {
291
- hash.update("\0DELETED\0");
292
- }
293
- else {
294
- hash.update(entry.content);
295
- }
296
- hash.update("\0");
297
- }
298
- return {
299
- algorithm: "sha256-content-v1",
300
- value: hash.digest("hex"),
301
- };
302
- }
303
- //# sourceMappingURL=digest.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"digest.js","sourceRoot":"","sources":["../../../src/kernel/tdd/digest.ts"],"names":[],"mappings":"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"}
@@ -1,38 +0,0 @@
1
- import type { TddPolicy, TddEvidence, AcceptanceCriterion } from "../types.js";
2
- /**
3
- * evaluateTddCompliance 的结果类型。
4
- *
5
- * - status = pass → 合规(advisory 下缺口记 warning)
6
- * - status = fail → 不合规,阻断
7
- * - status = waived → 豁免(bypass 模式下替代验证全部通过)
8
- */
9
- export interface EvaluationResult {
10
- status: "pass" | "fail" | "waived";
11
- warnings: string[];
12
- }
13
- /**
14
- * 判定 TDD 模式是否合规的纯函数。
15
- *
16
- * 规则(参见 Spec Section 4.3):
17
- *
18
- * **strict**:
19
- * - 必须至少有一个 verification=tDD 的 criterion
20
- * - 每个 TDD criterion 都必须有 status=pass 的 cycle 覆盖
21
- * - verification=regression 的 criterion 由 final regression 覆盖
22
- * - verification=manual 不允许在 strict 模式下使用
23
- * - final regression 和 final verification 必须 pass
24
- *
25
- * **relaxed**:
26
- * - 仅要求 final regression 为 pass,不检查 cycle
27
- * - final verification 必须 pass
28
- *
29
- * **bypass**:
30
- * - 必须有 exception 且其 alternativeValidation 全部完成(evidence 中对应 status=pass)
31
- * - final verification 仍必须 pass
32
- * - 不要求 runner / cycle / regression
33
- *
34
- * **enforcement**:
35
- * - advisory:缺失 evidence 仅产生 warning,不阻断(仍返回 pass/waived)
36
- * - runtime:缺失 evidence 直接阻断(返回 fail)
37
- */
38
- export declare function evaluateTddCompliance(policy: TddPolicy, evidence: TddEvidence, criteria: AcceptanceCriterion[]): EvaluationResult;
@@ -1,185 +0,0 @@
1
- /**
2
- * 判定 TDD 模式是否合规的纯函数。
3
- *
4
- * 规则(参见 Spec Section 4.3):
5
- *
6
- * **strict**:
7
- * - 必须至少有一个 verification=tDD 的 criterion
8
- * - 每个 TDD criterion 都必须有 status=pass 的 cycle 覆盖
9
- * - verification=regression 的 criterion 由 final regression 覆盖
10
- * - verification=manual 不允许在 strict 模式下使用
11
- * - final regression 和 final verification 必须 pass
12
- *
13
- * **relaxed**:
14
- * - 仅要求 final regression 为 pass,不检查 cycle
15
- * - final verification 必须 pass
16
- *
17
- * **bypass**:
18
- * - 必须有 exception 且其 alternativeValidation 全部完成(evidence 中对应 status=pass)
19
- * - final verification 仍必须 pass
20
- * - 不要求 runner / cycle / regression
21
- *
22
- * **enforcement**:
23
- * - advisory:缺失 evidence 仅产生 warning,不阻断(仍返回 pass/waived)
24
- * - runtime:缺失 evidence 直接阻断(返回 fail)
25
- */
26
- export function evaluateTddCompliance(policy, evidence, criteria) {
27
- const warnings = [];
28
- const isAdvisory = policy.enforcement === "advisory";
29
- // ── 通用检查:final verification ──
30
- const verificationOk = evidence.verification.status === "pass";
31
- if (!verificationOk) {
32
- if (isAdvisory) {
33
- warnings.push("final verification 未通过(advisory 模式:仅记录 warning)");
34
- }
35
- else {
36
- warnings.push("final verification 未通过");
37
- return { status: "fail", warnings };
38
- }
39
- }
40
- // ── bypass 模式 ──
41
- if (policy.mode === "bypass") {
42
- return evaluateBypass(policy, evidence, isAdvisory, warnings, verificationOk);
43
- }
44
- // ── strict 模式 ──
45
- if (policy.mode === "strict") {
46
- return evaluateStrict(policy, evidence, criteria, isAdvisory, warnings, verificationOk);
47
- }
48
- // ── relaxed 模式 ──
49
- return evaluateRelaxed(evidence, isAdvisory, warnings, verificationOk);
50
- }
51
- // ── 私有辅助函数 ──
52
- function evaluateBypass(policy, evidence, isAdvisory, warnings, verificationOk) {
53
- // bypass 必须有 exception
54
- if (!policy.exception) {
55
- if (isAdvisory) {
56
- warnings.push("bypass 模式缺少 exception(advisory 模式:仅记录 warning)");
57
- return { status: "waived", warnings };
58
- }
59
- warnings.push("bypass 模式缺少 exception");
60
- return { status: "fail", warnings };
61
- }
62
- // verification 失败时已在主函数中返回 fail,此处 verificationOk 保证为 true(或 advisory 已记 warning)
63
- if (!verificationOk) {
64
- // advisory 下 verification 失败已记 warning,继续检查替代验证
65
- // 统一返回 waived(advisory 不阻断)
66
- if (isAdvisory) {
67
- checkAltValidations(policy, evidence, isAdvisory, warnings);
68
- return { status: "waived", warnings };
69
- }
70
- return { status: "fail", warnings };
71
- }
72
- // 检查替代验证
73
- const altOk = checkAltValidations(policy, evidence, isAdvisory, warnings);
74
- if (isAdvisory) {
75
- return { status: "waived", warnings };
76
- }
77
- if (!altOk) {
78
- return { status: "fail", warnings };
79
- }
80
- return { status: "waived", warnings: warnings.filter(w => w.length > 0) };
81
- }
82
- function evaluateStrict(_policy, evidence, criteria, isAdvisory, warnings, verificationOk) {
83
- // verification 已前置检查,runtime 下失败则已在主函数返回 fail
84
- if (!verificationOk && !isAdvisory) {
85
- return { status: "fail", warnings };
86
- }
87
- const tddCriteria = criteria.filter(c => c.verification === "tdd");
88
- const regressionCriteria = criteria.filter(c => c.verification === "regression");
89
- const manualCriteria = criteria.filter(c => c.verification === "manual");
90
- let hasFailure = false;
91
- // strict 必须至少有一个 TDD criterion
92
- if (tddCriteria.length === 0) {
93
- if (isAdvisory) {
94
- warnings.push("strict 模式要求至少一个 verification=tdd 的 criterion(advisory 模式:仅记录 warning)");
95
- }
96
- else {
97
- warnings.push("strict 模式要求至少一个 verification=tdd 的 criterion");
98
- hasFailure = true;
99
- }
100
- }
101
- // manual criterion 不允许在 strict 模式
102
- if (manualCriteria.length > 0) {
103
- if (isAdvisory) {
104
- warnings.push(`strict 模式不允许 verification=manual 的 criterion: ${manualCriteria.map(c => c.id).join(", ")}(advisory 模式:仅记录 warning)`);
105
- }
106
- else {
107
- warnings.push(`strict 模式不允许 verification=manual 的 criterion: ${manualCriteria.map(c => c.id).join(", ")}`);
108
- hasFailure = true;
109
- }
110
- }
111
- // 每个 TDD criterion 都需要有 pass cycle 覆盖
112
- for (const c of tddCriteria) {
113
- const matchingCycles = evidence.cycles.filter(cycle => cycle.criterionId === c.id);
114
- const hasPassCycle = matchingCycles.some(cycle => cycle.status === "pass");
115
- if (!hasPassCycle) {
116
- if (isAdvisory) {
117
- warnings.push(`TDD criterion "${c.id}" 缺少有效 cycle(advisory 模式:仅记录 warning)`);
118
- }
119
- else {
120
- warnings.push(`TDD criterion "${c.id}" 缺少有效 cycle`);
121
- hasFailure = true;
122
- }
123
- }
124
- }
125
- // regression criterion 由 final regression 覆盖
126
- if (regressionCriteria.length > 0) {
127
- const regressionOk = evidence.regression.status === "pass";
128
- if (!regressionOk) {
129
- if (isAdvisory) {
130
- warnings.push("final regression 未通过,无法覆盖 regression criterion(advisory 模式:仅记录 warning)");
131
- }
132
- else {
133
- warnings.push("final regression 未通过,无法覆盖 regression criterion");
134
- hasFailure = true;
135
- }
136
- }
137
- }
138
- if (isAdvisory) {
139
- return { status: "pass", warnings };
140
- }
141
- if (hasFailure) {
142
- return { status: "fail", warnings };
143
- }
144
- return { status: "pass", warnings };
145
- }
146
- function evaluateRelaxed(evidence, isAdvisory, warnings, verificationOk) {
147
- if (!verificationOk && !isAdvisory) {
148
- return { status: "fail", warnings };
149
- }
150
- const regressionOk = evidence.regression.status === "pass";
151
- if (!regressionOk) {
152
- if (isAdvisory) {
153
- warnings.push("relaxed 模式要求 final regression 通过(advisory 模式:仅记录 warning)");
154
- return { status: "pass", warnings };
155
- }
156
- warnings.push("relaxed 模式要求 final regression 通过");
157
- return { status: "fail", warnings };
158
- }
159
- return { status: "pass", warnings };
160
- }
161
- /**
162
- * 检查 bypass 模式下所有 alternative validation 是否完成。
163
- * 返回 true 表示全部通过,false 表示有缺失或失败。
164
- */
165
- function checkAltValidations(policy, evidence, isAdvisory, warnings) {
166
- if (!policy.exception) {
167
- return false;
168
- }
169
- let allOk = true;
170
- for (const av of policy.exception.alternativeValidation) {
171
- const matchingEvidence = evidence.alternativeValidation.filter(ev => ev.validationId === av.validationId);
172
- const hasPass = matchingEvidence.some(ev => ev.status === "pass");
173
- if (!hasPass) {
174
- if (isAdvisory) {
175
- warnings.push(`替代验证 "${av.validationId}" 未完成(advisory 模式:仅记录 warning)`);
176
- }
177
- else {
178
- warnings.push(`替代验证 "${av.validationId}" 未完成`);
179
- allOk = false;
180
- }
181
- }
182
- }
183
- return allOk;
184
- }
185
- //# sourceMappingURL=evaluator.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"evaluator.js","sourceRoot":"","sources":["../../../src/kernel/tdd/evaluator.ts"],"names":[],"mappings":"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"}
@@ -1,42 +0,0 @@
1
- import { type DigestOptions } from "./digest.js";
2
- import type { TddFailureKind, VersionedDigest } from "../types.js";
3
- /** worktree-start 时记录的干净基线快照 */
4
- export interface WorkspaceBaseline {
5
- digest: VersionedDigest;
6
- capturedAt: string;
7
- testFilePatterns: string[];
8
- implementationFilePatterns: string[];
9
- }
10
- /**
11
- * 计算 worktree 的干净基线 digest 快照。
12
- * 供 task_control start-task 在 worktree-start 时调用,作为 RED 阶段
13
- * "实现文件相对基线未变" 与 GREEN "输入未偷换" 校验的基准。
14
- */
15
- export declare function captureWorkspaceBaseline(worktreeDir: string, options: DigestOptions): Promise<WorkspaceBaseline>;
16
- /** 组装 evidence block 的输入(criterion/cycle/命令/exit code/failure kind/digest/状态) */
17
- export interface EvidenceBlockInput {
18
- stage: string;
19
- criterionId?: string;
20
- cycleId?: string;
21
- command: string;
22
- testSelector: string | null;
23
- exitCode: number | null;
24
- failureKind: TddFailureKind | null;
25
- status: string;
26
- workspaceDigest: VersionedDigest | null;
27
- summary: string;
28
- }
29
- /**
30
- * 将结构化证据组装为可追加到 Task Record 受控 comment 的 markdown block。
31
- * 纯函数:内容含 criterion、cycle、命令、exit code、failure kind、digest、状态、summary。
32
- */
33
- export declare function buildEvidenceBlock(input: EvidenceBlockInput): string;
34
- /**
35
- * 组装 evidence block 并追加到 Task Record 的单个受控 comment。
36
- * 委托 records.appendTddEvidence 完成写入(含 mutex 串行与 revision 管理)。
37
- */
38
- export declare function recordTddEvidence(issueNumber: number, input: EvidenceBlockInput): Promise<{
39
- ok: boolean;
40
- revision: number;
41
- error?: string;
42
- }>;
@@ -1,48 +0,0 @@
1
- import { appendTddEvidence } from "../records.js";
2
- import { computeWorkspaceDigest } from "./digest.js";
3
- /**
4
- * 计算 worktree 的干净基线 digest 快照。
5
- * 供 task_control start-task 在 worktree-start 时调用,作为 RED 阶段
6
- * "实现文件相对基线未变" 与 GREEN "输入未偷换" 校验的基准。
7
- */
8
- export async function captureWorkspaceBaseline(worktreeDir, options) {
9
- const digest = await computeWorkspaceDigest(worktreeDir, options);
10
- return {
11
- digest,
12
- capturedAt: new Date().toISOString(),
13
- testFilePatterns: options.testFilePatterns,
14
- implementationFilePatterns: options.implementationFilePatterns,
15
- };
16
- }
17
- /**
18
- * 将结构化证据组装为可追加到 Task Record 受控 comment 的 markdown block。
19
- * 纯函数:内容含 criterion、cycle、命令、exit code、failure kind、digest、状态、summary。
20
- */
21
- export function buildEvidenceBlock(input) {
22
- const lines = [`### stage: ${input.stage}`];
23
- if (input.criterionId)
24
- lines.push(`- criterion: ${input.criterionId}`);
25
- if (input.cycleId)
26
- lines.push(`- cycle: ${input.cycleId}`);
27
- lines.push(`- command: \`${input.command}\``);
28
- if (input.testSelector)
29
- lines.push(`- selector: \`${input.testSelector}\``);
30
- lines.push(`- exitCode: ${input.exitCode ?? "null"}`);
31
- lines.push(`- failureKind: ${input.failureKind ?? "null"}`);
32
- lines.push(`- status: ${input.status}`);
33
- if (input.workspaceDigest) {
34
- lines.push(`- workspaceDigest: ${input.workspaceDigest.algorithm}:${input.workspaceDigest.value}`);
35
- }
36
- lines.push(`- summary: ${input.summary}`);
37
- return lines.join("\n");
38
- }
39
- // ─── evidence 追加(复用 records.appendTddEvidence) ───
40
- /**
41
- * 组装 evidence block 并追加到 Task Record 的单个受控 comment。
42
- * 委托 records.appendTddEvidence 完成写入(含 mutex 串行与 revision 管理)。
43
- */
44
- export async function recordTddEvidence(issueNumber, input) {
45
- const block = buildEvidenceBlock(input);
46
- return appendTddEvidence(issueNumber, block);
47
- }
48
- //# sourceMappingURL=evidence.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"evidence.js","sourceRoot":"","sources":["../../../src/kernel/tdd/evidence.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,EAAE,sBAAsB,EAAsB,MAAM,aAAa,CAAA;AAaxE;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,WAAmB,EACnB,OAAsB;IAEtB,MAAM,MAAM,GAAG,MAAM,sBAAsB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;IACjE,OAAO;QACL,MAAM;QACN,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACpC,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;QAC1C,0BAA0B,EAAE,OAAO,CAAC,0BAA0B;KAC/D,CAAA;AACH,CAAC;AAkBD;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAyB;IAC1D,MAAM,KAAK,GAAG,CAAC,cAAc,KAAK,CAAC,KAAK,EAAE,CAAC,CAAA;IAC3C,IAAI,KAAK,CAAC,WAAW;QAAE,KAAK,CAAC,IAAI,CAAC,gBAAgB,KAAK,CAAC,WAAW,EAAE,CAAC,CAAA;IACtE,IAAI,KAAK,CAAC,OAAO;QAAE,KAAK,CAAC,IAAI,CAAC,YAAY,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;IAC1D,KAAK,CAAC,IAAI,CAAC,gBAAgB,KAAK,CAAC,OAAO,IAAI,CAAC,CAAA;IAC7C,IAAI,KAAK,CAAC,YAAY;QAAE,KAAK,CAAC,IAAI,CAAC,iBAAiB,KAAK,CAAC,YAAY,IAAI,CAAC,CAAA;IAC3E,KAAK,CAAC,IAAI,CAAC,eAAe,KAAK,CAAC,QAAQ,IAAI,MAAM,EAAE,CAAC,CAAA;IACrD,KAAK,CAAC,IAAI,CAAC,kBAAkB,KAAK,CAAC,WAAW,IAAI,MAAM,EAAE,CAAC,CAAA;IAC3D,KAAK,CAAC,IAAI,CAAC,aAAa,KAAK,CAAC,MAAM,EAAE,CAAC,CAAA;IACvC,IAAI,KAAK,CAAC,eAAe,EAAE,CAAC;QAC1B,KAAK,CAAC,IAAI,CAAC,sBAAsB,KAAK,CAAC,eAAe,CAAC,SAAS,IAAI,KAAK,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC,CAAA;IACpG,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,cAAc,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;IACzC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC;AAED,oDAAoD;AAEpD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,WAAmB,EACnB,KAAyB;IAEzB,MAAM,KAAK,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAA;IACvC,OAAO,iBAAiB,CAAC,WAAW,EAAE,KAAK,CAAC,CAAA;AAC9C,CAAC"}