@devcxl/opencode-cabbage 0.2.0 → 0.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 (84) hide show
  1. package/README.md +57 -54
  2. package/README.zh.md +91 -0
  3. package/assets/agents/dev-lifecycle.md +28 -22
  4. package/assets/agents/team/architect.md +14 -0
  5. package/assets/agents/team/backend.md +14 -0
  6. package/assets/agents/team/frontend.md +14 -0
  7. package/assets/agents/team/goal-verify.md +54 -0
  8. package/assets/agents/team/reviewer.md +10 -0
  9. package/assets/skills/flow-code/SKILL.md +13 -0
  10. package/assets/skills/flow-review/SKILL.md +7 -0
  11. package/assets/skills/flow-tasks/SKILL.md +42 -0
  12. package/assets/skills/flow-tdd/SKILL.md +208 -0
  13. package/dist/flowrun/adapter.d.ts +49 -0
  14. package/dist/flowrun/adapter.js +293 -0
  15. package/dist/flowrun/adapter.js.map +1 -0
  16. package/dist/flowrun/ci.d.ts +64 -0
  17. package/dist/flowrun/ci.js +184 -0
  18. package/dist/flowrun/ci.js.map +1 -0
  19. package/dist/flowrun/coverage.d.ts +70 -0
  20. package/dist/flowrun/coverage.js +207 -0
  21. package/dist/flowrun/coverage.js.map +1 -0
  22. package/dist/flowrun/digest.d.ts +17 -0
  23. package/dist/flowrun/digest.js +301 -0
  24. package/dist/flowrun/digest.js.map +1 -0
  25. package/dist/flowrun/evaluator.d.ts +38 -0
  26. package/dist/flowrun/evaluator.js +185 -0
  27. package/dist/flowrun/evaluator.js.map +1 -0
  28. package/dist/flowrun/gate.d.ts +20 -0
  29. package/dist/flowrun/gate.js +40 -3
  30. package/dist/flowrun/gate.js.map +1 -1
  31. package/dist/flowrun/github.d.ts +13 -9
  32. package/dist/flowrun/github.js +46 -26
  33. package/dist/flowrun/github.js.map +1 -1
  34. package/dist/flowrun/index.d.ts +12 -4
  35. package/dist/flowrun/index.js +11 -3
  36. package/dist/flowrun/index.js.map +1 -1
  37. package/dist/flowrun/merge.d.ts +35 -2
  38. package/dist/flowrun/merge.js +72 -8
  39. package/dist/flowrun/merge.js.map +1 -1
  40. package/dist/flowrun/migration.d.ts +11 -0
  41. package/dist/flowrun/migration.js +276 -0
  42. package/dist/flowrun/migration.js.map +1 -0
  43. package/dist/flowrun/pr.d.ts +132 -0
  44. package/dist/flowrun/pr.js +343 -0
  45. package/dist/flowrun/pr.js.map +1 -0
  46. package/dist/flowrun/state.d.ts +79 -0
  47. package/dist/flowrun/state.js +363 -0
  48. package/dist/flowrun/state.js.map +1 -0
  49. package/dist/flowrun/transitions.d.ts +66 -0
  50. package/dist/flowrun/transitions.js +168 -0
  51. package/dist/flowrun/transitions.js.map +1 -0
  52. package/dist/flowrun/types.d.ts +279 -4
  53. package/dist/flowrun/types.js +2 -1
  54. package/dist/flowrun/types.js.map +1 -1
  55. package/dist/flowrun/validator.d.ts +15 -5
  56. package/dist/flowrun/validator.js +117 -5
  57. package/dist/flowrun/validator.js.map +1 -1
  58. package/dist/plugin/agents.d.ts +4 -0
  59. package/dist/plugin/agents.js +19 -0
  60. package/dist/plugin/agents.js.map +1 -1
  61. package/dist/plugin/broker.d.ts +73 -0
  62. package/dist/plugin/broker.js +140 -0
  63. package/dist/plugin/broker.js.map +1 -0
  64. package/dist/plugin/flow-pr-tool.d.ts +37 -0
  65. package/dist/plugin/flow-pr-tool.js +176 -0
  66. package/dist/plugin/flow-pr-tool.js.map +1 -0
  67. package/dist/plugin/goal.d.ts +39 -1
  68. package/dist/plugin/goal.js +80 -1
  69. package/dist/plugin/goal.js.map +1 -1
  70. package/dist/plugin/prompt-lint.js +129 -0
  71. package/dist/plugin/prompt-lint.js.map +1 -1
  72. package/dist/plugin/server.d.ts +8 -0
  73. package/dist/plugin/server.js +306 -11
  74. package/dist/plugin/server.js.map +1 -1
  75. package/dist/plugin/shell.d.ts +37 -0
  76. package/dist/plugin/shell.js +144 -0
  77. package/dist/plugin/shell.js.map +1 -0
  78. package/dist/plugin/tdd-tool.d.ts +62 -0
  79. package/dist/plugin/tdd-tool.js +336 -0
  80. package/dist/plugin/tdd-tool.js.map +1 -0
  81. package/dist/util/gh.d.ts +8 -1
  82. package/dist/util/gh.js +10 -2
  83. package/dist/util/gh.js.map +1 -1
  84. package/package.json +2 -1
@@ -0,0 +1,363 @@
1
+ // ─── 辅助函数 ───
2
+ function findCycle(evidence, cycleId) {
3
+ return evidence.cycles.find(c => c.cycleId === cycleId);
4
+ }
5
+ function replaceCycle(evidence, updated) {
6
+ return evidence.cycles.map(c => c.cycleId === updated.cycleId ? updated : c);
7
+ }
8
+ function bumpRevision(evidence) {
9
+ return { ...evidence, revision: evidence.revision + 1, updatedAt: new Date().toISOString() };
10
+ }
11
+ /**
12
+ * 简单 glob 匹配(支持 *、**)
13
+ */
14
+ function matchSimpleGlob(filePath, pattern) {
15
+ const normalized = filePath.split("/").join("/");
16
+ let regexStr = "";
17
+ let i = 0;
18
+ while (i < pattern.length) {
19
+ if (pattern[i] === "*" && pattern[i + 1] === "*") {
20
+ i += 2;
21
+ if (i < pattern.length && pattern[i] === "/") {
22
+ regexStr += "(.*/)?";
23
+ i++;
24
+ }
25
+ else {
26
+ regexStr += ".*";
27
+ }
28
+ }
29
+ else if (pattern[i] === "*") {
30
+ regexStr += "[^/]*";
31
+ i++;
32
+ }
33
+ else if (pattern[i] === ".") {
34
+ regexStr += "\\.";
35
+ i++;
36
+ }
37
+ else if (pattern[i] === "?") {
38
+ regexStr += "[^/]";
39
+ i++;
40
+ }
41
+ else {
42
+ if ("+^$(){}[]|\\".includes(pattern[i])) {
43
+ regexStr += "\\" + pattern[i];
44
+ }
45
+ else {
46
+ regexStr += pattern[i];
47
+ }
48
+ i++;
49
+ }
50
+ }
51
+ return new RegExp(`^${regexStr}$`).test(normalized);
52
+ }
53
+ function matchesAnyPattern(path, patterns) {
54
+ if (patterns.length === 0)
55
+ return false;
56
+ return patterns.some(p => matchSimpleGlob(path, p));
57
+ }
58
+ function digestEqual(a, b) {
59
+ if (a === null || b === null)
60
+ return a === b;
61
+ return a.algorithm === b.algorithm && a.value === b.value;
62
+ }
63
+ /**
64
+ * 判断 RED failure 是否有效:
65
+ * 只有 assertion 和 missing-behavior 才是有效的 RED failure。
66
+ */
67
+ function isValidRedFailure(failureKind) {
68
+ return failureKind === "assertion" || failureKind === "missing-behavior";
69
+ }
70
+ // ─── 公开函数 ───
71
+ /**
72
+ * 创建初始 TddEvidence(status=not-recorded, revision=0)。
73
+ */
74
+ export function createTaskEvidence() {
75
+ return {
76
+ revision: 0,
77
+ reworkRevision: 0,
78
+ status: "not-recorded",
79
+ taskStart: { status: "pending", headSha: null, treeSha: null, startedAt: null },
80
+ cycles: [],
81
+ regression: { status: "pending", headSha: null, treeSha: null, reworkRevision: 0, runs: [] },
82
+ verification: { status: "pending", headSha: null, treeSha: null, runs: [] },
83
+ alternativeValidation: [],
84
+ reworks: [],
85
+ warnings: [],
86
+ updatedAt: null,
87
+ };
88
+ }
89
+ /**
90
+ * 启动一个新的 TDD cycle。
91
+ *
92
+ * 验证:
93
+ * - criterion 存在且 verification=tdd
94
+ * - testPaths 匹配 testFilePatterns
95
+ * - 同 cycleId + 同 workspace digest → 幂等返回原 evidence
96
+ * - 同 cycleId + 不同 workspace digest → CYCLE_CONFLICT
97
+ */
98
+ export function startCycle(evidence, cycleId, criterionId, testPaths, testSelector, workspaceDigest, acceptanceCriteria, testFilePatterns) {
99
+ // ── 验证 criterion 存在且为 tdd ──
100
+ const criterion = acceptanceCriteria.find(c => c.id === criterionId);
101
+ if (!criterion || criterion.verification !== "tdd") {
102
+ return {
103
+ ok: false,
104
+ error: { code: "CRITERION_NOT_FOUND", message: `Criterion "${criterionId}" not found or not verification=tdd` },
105
+ };
106
+ }
107
+ // ── 验证 testPaths 匹配 testFilePatterns ──
108
+ for (const tp of testPaths) {
109
+ if (!matchesAnyPattern(tp, testFilePatterns)) {
110
+ return {
111
+ ok: false,
112
+ error: { code: "POLICY_INVALID", message: `Test path "${tp}" does not match testFilePatterns` },
113
+ };
114
+ }
115
+ }
116
+ // ── 检查已有 cycle ──
117
+ const existing = findCycle(evidence, cycleId);
118
+ if (existing) {
119
+ // 幂等:相同 workspace digest
120
+ if (digestEqual(existing.startWorkspaceDigest, workspaceDigest)) {
121
+ return { ok: true, value: { evidence, cycle: existing } };
122
+ }
123
+ // 冲突
124
+ return {
125
+ ok: false,
126
+ error: { code: "CYCLE_CONFLICT", message: `Cycle "${cycleId}" already exists with different workspace digest` },
127
+ };
128
+ }
129
+ // ── 创建新 cycle ──
130
+ const cycle = {
131
+ cycleId,
132
+ criterionId,
133
+ reworkRevision: evidence.reworkRevision,
134
+ status: "started",
135
+ startWorkspaceDigest: workspaceDigest,
136
+ testFiles: testPaths,
137
+ redTestDigest: null,
138
+ redAttempts: [],
139
+ greenAttempts: [],
140
+ };
141
+ const newEvidence = bumpRevision({
142
+ ...evidence,
143
+ status: evidence.status === "not-recorded" ? "in-progress" : evidence.status,
144
+ cycles: [...evidence.cycles, cycle],
145
+ });
146
+ return { ok: true, value: { evidence: newEvidence, cycle } };
147
+ }
148
+ /**
149
+ * 记录 RED 尝试。
150
+ *
151
+ * 验证:
152
+ * - cycle 存在且 status ∈ {started, red}
153
+ * - failureKind 为 assertion 或 missing-behavior(有效 RED)
154
+ * - 幂等:相同 outputDigest → 返回原结果
155
+ */
156
+ export function recordRed(evidence, cycleId, redEvidence) {
157
+ const existing = findCycle(evidence, cycleId);
158
+ if (!existing) {
159
+ return {
160
+ ok: false,
161
+ error: { code: "CYCLE_CONFLICT", message: `Cycle "${cycleId}" not found` },
162
+ };
163
+ }
164
+ // cycle 必须处于 started 或 red 状态
165
+ if (existing.status !== "started" && existing.status !== "red") {
166
+ return {
167
+ ok: false,
168
+ error: { code: "INVALID_TRANSITION", message: `Cycle "${cycleId}" is in "${existing.status}" state, cannot record RED` },
169
+ };
170
+ }
171
+ // ── 失败分类校验 ──
172
+ const exitCode = redEvidence.exitCode;
173
+ // 测试通过(exitCode === 0)→ RED_EXPECTED_FAILURE
174
+ if (exitCode === 0) {
175
+ return {
176
+ ok: false,
177
+ error: { code: "RED_EXPECTED_FAILURE", message: "RED requires test failure (exitCode !== 0)" },
178
+ };
179
+ }
180
+ // timeout
181
+ if (redEvidence.failureKind === "timeout") {
182
+ return {
183
+ ok: false,
184
+ error: { code: "COMMAND_TIMEOUT", message: "Test execution timed out" },
185
+ };
186
+ }
187
+ // infrastructure 或 unknown → 不算 RED
188
+ if (!isValidRedFailure(redEvidence.failureKind)) {
189
+ return {
190
+ ok: false,
191
+ error: { code: "RED_INFRASTRUCTURE_FAILURE", message: `Failure kind "${redEvidence.failureKind}" is not a valid RED failure (expected assertion or missing-behavior)` },
192
+ };
193
+ }
194
+ // ── 幂等检查:相同 outputDigest ──
195
+ const dup = existing.redAttempts.find(a => digestEqual(a.outputDigest, redEvidence.outputDigest));
196
+ if (dup) {
197
+ // 已经记录过相同的 RED,返回原 evidence(不修改)
198
+ return { ok: true, value: { evidence, cycle: existing } };
199
+ }
200
+ // ── 记录 RED ──
201
+ const updatedCycle = {
202
+ ...existing,
203
+ status: "red",
204
+ redTestDigest: redEvidence.executionInputDigest,
205
+ redAttempts: [...existing.redAttempts, redEvidence],
206
+ };
207
+ const newEvidence = bumpRevision({
208
+ ...evidence,
209
+ cycles: replaceCycle(evidence, updatedCycle),
210
+ });
211
+ return { ok: true, value: { evidence: newEvidence, cycle: updatedCycle } };
212
+ }
213
+ /**
214
+ * 记录 GREEN 尝试。
215
+ *
216
+ * 验证:
217
+ * - cycle 存在且已有有效 RED(redTestDigest !== null)
218
+ * - GREEN exitCode === 0
219
+ * - implementation files 有变化
220
+ * - 幂等:相同 outputDigest → 返回原结果
221
+ */
222
+ export function recordGreen(evidence, cycleId, greenEvidence, implementationFilesChanged) {
223
+ const existing = findCycle(evidence, cycleId);
224
+ if (!existing) {
225
+ return {
226
+ ok: false,
227
+ error: { code: "CYCLE_CONFLICT", message: `Cycle "${cycleId}" not found` },
228
+ };
229
+ }
230
+ // 必须有 RED
231
+ if (existing.redTestDigest === null || existing.redAttempts.length === 0) {
232
+ return {
233
+ ok: false,
234
+ error: { code: "INVALID_TRANSITION", message: `Cycle "${cycleId}" has no RED recorded` },
235
+ };
236
+ }
237
+ // GREEN 测试必须通过
238
+ if (greenEvidence.exitCode !== 0) {
239
+ return {
240
+ ok: false,
241
+ error: { code: "GREEN_EXPECTED_PASS", message: "GREEN requires all tests to pass (exitCode === 0)" },
242
+ };
243
+ }
244
+ // 必须有实现变化
245
+ if (!implementationFilesChanged) {
246
+ return {
247
+ ok: false,
248
+ error: { code: "IMPLEMENTATION_CHANGE_REQUIRED", message: "GREEN requires implementation file changes" },
249
+ };
250
+ }
251
+ // ── 幂等检查:相同 outputDigest ──
252
+ const dup = existing.greenAttempts.find(a => digestEqual(a.outputDigest, greenEvidence.outputDigest));
253
+ if (dup) {
254
+ return { ok: true, value: { evidence, cycle: existing } };
255
+ }
256
+ // ── 记录 GREEN ──
257
+ const updatedCycle = {
258
+ ...existing,
259
+ status: "pass",
260
+ greenAttempts: [...existing.greenAttempts, greenEvidence],
261
+ };
262
+ const newEvidence = bumpRevision({
263
+ ...evidence,
264
+ cycles: replaceCycle(evidence, updatedCycle),
265
+ });
266
+ return { ok: true, value: { evidence: newEvidence, cycle: updatedCycle } };
267
+ }
268
+ /**
269
+ * 记录最终 regression 结果。
270
+ *
271
+ * 验证:
272
+ * - runs 非空
273
+ * - 所有 run exitCode === 0 且无 timeout 则 pass,否则 fail
274
+ */
275
+ export function recordFinalRegression(evidence, headSha, treeSha, runs) {
276
+ if (runs.length === 0) {
277
+ return {
278
+ ok: false,
279
+ error: { code: "REGRESSION_FAILED", message: "Regression requires at least one run" },
280
+ };
281
+ }
282
+ const allPass = runs.every(r => r.exitCode === 0 && r.failureKind !== "timeout");
283
+ const status = allPass ? "pass" : "fail";
284
+ const newEvidence = bumpRevision({
285
+ ...evidence,
286
+ regression: {
287
+ status,
288
+ headSha,
289
+ treeSha,
290
+ reworkRevision: evidence.reworkRevision,
291
+ runs,
292
+ },
293
+ });
294
+ return { ok: true, value: newEvidence };
295
+ }
296
+ /**
297
+ * 记录最终 verification 结果。
298
+ *
299
+ * 规则:
300
+ * - runs 为空 → pass(未配置 verifyCommands)
301
+ * - 所有 run exitCode === 0 则 pass,否则 fail
302
+ */
303
+ export function recordFinalVerification(evidence, headSha, treeSha, runs) {
304
+ if (runs.length === 0) {
305
+ // 未配置 verifyCommands,视为 pass
306
+ const newEvidence = bumpRevision({
307
+ ...evidence,
308
+ verification: {
309
+ status: "pass",
310
+ headSha,
311
+ treeSha,
312
+ runs: [],
313
+ },
314
+ });
315
+ return { ok: true, value: newEvidence };
316
+ }
317
+ const allPass = runs.every(r => r.exitCode === 0);
318
+ const status = allPass ? "pass" : "fail";
319
+ const newEvidence = bumpRevision({
320
+ ...evidence,
321
+ verification: {
322
+ status,
323
+ headSha,
324
+ treeSha,
325
+ runs,
326
+ },
327
+ });
328
+ return { ok: true, value: newEvidence };
329
+ }
330
+ /**
331
+ * 放弃一个 cycle。
332
+ *
333
+ * 规则:
334
+ * - cycle 必须存在
335
+ * - cycle 状态不能是 "pass"(已通过的 cycle 不能放弃)
336
+ * - 保留审计记录,reason 写入 warnings
337
+ */
338
+ export function abandonCycle(evidence, cycleId, reason) {
339
+ const existing = findCycle(evidence, cycleId);
340
+ if (!existing) {
341
+ return {
342
+ ok: false,
343
+ error: { code: "CYCLE_CONFLICT", message: `Cycle "${cycleId}" not found` },
344
+ };
345
+ }
346
+ if (existing.status === "pass") {
347
+ return {
348
+ ok: false,
349
+ error: { code: "INVALID_TRANSITION", message: `Cannot abandon cycle "${cycleId}" that has already passed` },
350
+ };
351
+ }
352
+ const updatedCycle = {
353
+ ...existing,
354
+ status: "abandoned",
355
+ };
356
+ const newEvidence = bumpRevision({
357
+ ...evidence,
358
+ cycles: replaceCycle(evidence, updatedCycle),
359
+ warnings: [...evidence.warnings, reason],
360
+ });
361
+ return { ok: true, value: newEvidence };
362
+ }
363
+ //# sourceMappingURL=state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/flowrun/state.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ import type { FlowRun, FlowStage, TaskState, TaskExecutionBinding, TddPolicy } from "./types.js";
2
+ export interface TransitionError {
3
+ code: string;
4
+ message: string;
5
+ }
6
+ export type TransitionResult<T> = {
7
+ ok: true;
8
+ value: T;
9
+ } | {
10
+ ok: false;
11
+ error: TransitionError;
12
+ };
13
+ /**
14
+ * 启动 FlowRun:planned → running
15
+ *
16
+ * 幂等:已经是 running 则直接返回(不报错)。
17
+ */
18
+ export declare function flowRunStart(flowRun: FlowRun): TransitionResult<FlowRun>;
19
+ /**
20
+ * 启动 Stage:pending → running
21
+ *
22
+ * 约束:
23
+ * - 仅允许 requirements/design/tasks/code
24
+ * - 验证前置 stage 已 pass
25
+ *
26
+ * 幂等:已经是 running 则直接返回。
27
+ */
28
+ export declare function flowStageStart(flowRun: FlowRun, stage: FlowStage): TransitionResult<FlowRun>;
29
+ /**
30
+ * 完成 Stage:running → pass
31
+ *
32
+ * 约束:
33
+ * - 仅允许 requirements/design/tasks
34
+ * - code/test/review/merge 由 finalize 完成
35
+ * - 验证 pending checks 均已 pass
36
+ *
37
+ * 幂等:已经是 pass 则直接返回。
38
+ */
39
+ export declare function flowStageComplete(flowRun: FlowRun, stage: FlowStage): TransitionResult<FlowRun>;
40
+ /**
41
+ * 启动 Task:pending/ready → running
42
+ *
43
+ * 步骤:
44
+ * 1. gate check:canStartTask(依赖已 merged、code stage 活跃等)
45
+ * 2. policy 冻结:如果传入 tddPolicy,则覆盖 TaskState.tddPolicy
46
+ * 3. 写入 executionBinding
47
+ * 4. status → running
48
+ *
49
+ * 幂等:已经是 running 则直接返回(相同 taskId)。
50
+ */
51
+ export declare function flowTaskStart(flowRun: FlowRun, taskId: string, executionBinding: TaskExecutionBinding, tddPolicy?: TddPolicy): TransitionResult<{
52
+ flowRun: FlowRun;
53
+ task: TaskState;
54
+ }>;
55
+ /**
56
+ * FlowRun 终态绑定:所有 Task merged 后,顺序标记 code→test→review→merge 为 pass,
57
+ * 并将 FlowRun 状态设为 completed。
58
+ *
59
+ * 规则:
60
+ * - canMerge() 必须通过(所有 Task merged + FlowRun status 为 running/merging)
61
+ * - 对 code/test/review/merge 四个 stage:若未 pass 则逐个标记 pass
62
+ * - FlowRun status → completed,设置 completedAt
63
+ *
64
+ * 幂等:已经是 completed 则直接返回(不修改任何字段)。
65
+ */
66
+ export declare function flowRunFinalize(flowRun: FlowRun): TransitionResult<FlowRun>;
@@ -0,0 +1,168 @@
1
+ import { canStartStage, canCompleteStage, canStartTask, canMerge, } from "./gate.js";
2
+ // ─── 受控 stage 集合 ───
3
+ /** flow_control 可启动的 stage */
4
+ const STARTABLE_STAGES = ["requirements", "design", "tasks", "code"];
5
+ /** flow_control 可完成的 stage(code/test/review/merge 由 finalize 完成) */
6
+ const COMPLETABLE_STAGES = ["requirements", "design", "tasks"];
7
+ function gateToError(gate) {
8
+ return {
9
+ code: "GATE_BLOCKED",
10
+ message: gate.reason ?? "Gate check failed",
11
+ };
12
+ }
13
+ // ─── FlowRun 状态迁移 ───
14
+ /**
15
+ * 启动 FlowRun:planned → running
16
+ *
17
+ * 幂等:已经是 running 则直接返回(不报错)。
18
+ */
19
+ export function flowRunStart(flowRun) {
20
+ if (flowRun.status === "running") {
21
+ return { ok: true, value: flowRun };
22
+ }
23
+ if (flowRun.status !== "planned") {
24
+ return {
25
+ ok: false,
26
+ error: { code: "INVALID_TRANSITION", message: `FlowRun is ${flowRun.status}, not planned` },
27
+ };
28
+ }
29
+ flowRun.status = "running";
30
+ flowRun.startedAt = new Date().toISOString();
31
+ return { ok: true, value: flowRun };
32
+ }
33
+ // ─── Stage 状态迁移 ───
34
+ /**
35
+ * 启动 Stage:pending → running
36
+ *
37
+ * 约束:
38
+ * - 仅允许 requirements/design/tasks/code
39
+ * - 验证前置 stage 已 pass
40
+ *
41
+ * 幂等:已经是 running 则直接返回。
42
+ */
43
+ export function flowStageStart(flowRun, stage) {
44
+ if (!STARTABLE_STAGES.includes(stage)) {
45
+ return {
46
+ ok: false,
47
+ error: { code: "STAGE_NOT_CONTROLLABLE", message: `Stage "${stage}" cannot be started via flow_control` },
48
+ };
49
+ }
50
+ if (flowRun.stages[stage].status === "running") {
51
+ return { ok: true, value: flowRun };
52
+ }
53
+ const gate = canStartStage(flowRun, stage);
54
+ if (!gate.allowed) {
55
+ return { ok: false, error: gateToError(gate) };
56
+ }
57
+ flowRun.stages[stage].status = "running";
58
+ return { ok: true, value: flowRun };
59
+ }
60
+ /**
61
+ * 完成 Stage:running → pass
62
+ *
63
+ * 约束:
64
+ * - 仅允许 requirements/design/tasks
65
+ * - code/test/review/merge 由 finalize 完成
66
+ * - 验证 pending checks 均已 pass
67
+ *
68
+ * 幂等:已经是 pass 则直接返回。
69
+ */
70
+ export function flowStageComplete(flowRun, stage) {
71
+ if (!COMPLETABLE_STAGES.includes(stage)) {
72
+ return {
73
+ ok: false,
74
+ error: { code: "STAGE_NOT_CONTROLLABLE", message: `Stage "${stage}" completion is only via finalize` },
75
+ };
76
+ }
77
+ if (flowRun.stages[stage].status === "pass") {
78
+ return { ok: true, value: flowRun };
79
+ }
80
+ const gate = canCompleteStage(flowRun, stage);
81
+ if (!gate.allowed) {
82
+ return { ok: false, error: gateToError(gate) };
83
+ }
84
+ flowRun.stages[stage].status = "pass";
85
+ flowRun.stages[stage].completedAt = new Date().toISOString();
86
+ return { ok: true, value: flowRun };
87
+ }
88
+ // ─── Task 状态迁移 ───
89
+ /**
90
+ * 启动 Task:pending/ready → running
91
+ *
92
+ * 步骤:
93
+ * 1. gate check:canStartTask(依赖已 merged、code stage 活跃等)
94
+ * 2. policy 冻结:如果传入 tddPolicy,则覆盖 TaskState.tddPolicy
95
+ * 3. 写入 executionBinding
96
+ * 4. status → running
97
+ *
98
+ * 幂等:已经是 running 则直接返回(相同 taskId)。
99
+ */
100
+ export function flowTaskStart(flowRun, taskId, executionBinding, tddPolicy) {
101
+ const task = flowRun.tasks[taskId];
102
+ if (!task) {
103
+ return {
104
+ ok: false,
105
+ error: { code: "TASK_NOT_FOUND", message: `Task "${taskId}" not found in FlowRun` },
106
+ };
107
+ }
108
+ // 幂等:已经是 running
109
+ if (task.status === "running") {
110
+ // 更新 executionBinding(可能重连)
111
+ task.executionBinding = executionBinding;
112
+ return { ok: true, value: { flowRun, task } };
113
+ }
114
+ const gate = canStartTask(flowRun, taskId);
115
+ if (!gate.allowed) {
116
+ return { ok: false, error: gateToError(gate) };
117
+ }
118
+ // 冻结 policy
119
+ if (tddPolicy) {
120
+ task.tddPolicy = tddPolicy;
121
+ }
122
+ // 写入 execution binding
123
+ task.executionBinding = executionBinding;
124
+ task.status = "running";
125
+ task.startedAt = new Date().toISOString();
126
+ return { ok: true, value: { flowRun, task } };
127
+ }
128
+ // ─── FlowRun Finalize ───
129
+ /**
130
+ * FlowRun 终态绑定:所有 Task merged 后,顺序标记 code→test→review→merge 为 pass,
131
+ * 并将 FlowRun 状态设为 completed。
132
+ *
133
+ * 规则:
134
+ * - canMerge() 必须通过(所有 Task merged + FlowRun status 为 running/merging)
135
+ * - 对 code/test/review/merge 四个 stage:若未 pass 则逐个标记 pass
136
+ * - FlowRun status → completed,设置 completedAt
137
+ *
138
+ * 幂等:已经是 completed 则直接返回(不修改任何字段)。
139
+ */
140
+ export function flowRunFinalize(flowRun) {
141
+ // 幂等:已 completed
142
+ if (flowRun.status === "completed") {
143
+ return { ok: true, value: flowRun };
144
+ }
145
+ // 前置检查:canMerge(所有 Task merged + FlowRun 状态正确)
146
+ const mergeGate = canMerge(flowRun);
147
+ if (!mergeGate.allowed) {
148
+ return { ok: false, error: gateToError(mergeGate) };
149
+ }
150
+ // 顺序标记 finalize stages
151
+ const finalizeStages = ["code", "test", "review", "merge"];
152
+ for (const stage of finalizeStages) {
153
+ const stageState = flowRun.stages[stage];
154
+ if (!stageState)
155
+ continue;
156
+ // 已经是 pass → 跳过
157
+ if (stageState.status === "pass")
158
+ continue;
159
+ // 标记 pass
160
+ stageState.status = "pass";
161
+ stageState.completedAt = new Date().toISOString();
162
+ }
163
+ // FlowRun → completed
164
+ flowRun.status = "completed";
165
+ flowRun.completedAt = new Date().toISOString();
166
+ return { ok: true, value: flowRun };
167
+ }
168
+ //# sourceMappingURL=transitions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transitions.js","sourceRoot":"","sources":["../../src/flowrun/transitions.ts"],"names":[],"mappings":"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"}