@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,343 @@
1
+ let ghExecutor = null;
2
+ export function setGhExecutor(fn) {
3
+ ghExecutor = fn;
4
+ }
5
+ async function gh(args) {
6
+ if (ghExecutor) {
7
+ return ghExecutor(args);
8
+ }
9
+ const mod = await import("../util/gh.js");
10
+ return mod.gh(args);
11
+ }
12
+ // ─── PR 号解析 ───
13
+ function parsePrNumber(stdout) {
14
+ const trimmed = stdout.trim();
15
+ // 纯数字
16
+ if (/^\d+$/.test(trimmed))
17
+ return parseInt(trimmed, 10);
18
+ // URL 格式:https://github.com/owner/repo/pull/123
19
+ const urlMatch = trimmed.match(/\/pull\/(\d+)$/);
20
+ if (urlMatch)
21
+ return parseInt(urlMatch[1], 10);
22
+ // 其他格式尝试提取尾部数字
23
+ const numMatch = trimmed.match(/(\d+)$/);
24
+ if (numMatch)
25
+ return parseInt(numMatch[1], 10);
26
+ return null;
27
+ }
28
+ // ─── Preflight 检查 ───
29
+ /**
30
+ * 执行 PR 创建前的前置条件检查(无副作用)。
31
+ *
32
+ * 规则:
33
+ * 1. Task 状态为 running
34
+ * 2. committed-head regression.status === "pass"
35
+ * 3. committed-head verification.status === "pass"
36
+ * 4. evidence headSha 与当前 head 一致
37
+ */
38
+ export function preflightPRCreate(task, currentHeadSha) {
39
+ // 1. Task 状态检查
40
+ if (task.status !== "running") {
41
+ return {
42
+ ok: false,
43
+ code: "TASK_NOT_RUNNING",
44
+ message: `Task "${task.id}" is not running (status: ${task.status})`,
45
+ };
46
+ }
47
+ const { regression, verification } = task.tddEvidence;
48
+ // 2. Regression 状态检查
49
+ if (regression.status !== "pass") {
50
+ return {
51
+ ok: false,
52
+ code: "REGRESSION_NOT_COMPLETE",
53
+ message: `Committed-head regression is not pass (status: ${regression.status})`,
54
+ };
55
+ }
56
+ // 3. Verification 状态检查
57
+ if (verification.status !== "pass") {
58
+ return {
59
+ ok: false,
60
+ code: "VERIFICATION_NOT_COMPLETE",
61
+ message: `Final verification is not pass (status: ${verification.status})`,
62
+ };
63
+ }
64
+ // 4. Head SHA 一致性检查
65
+ if (!regression.headSha) {
66
+ return {
67
+ ok: false,
68
+ code: "HEAD_MISMATCH",
69
+ message: "Regression evidence is missing head SHA",
70
+ };
71
+ }
72
+ if (regression.headSha !== currentHeadSha) {
73
+ return {
74
+ ok: false,
75
+ code: "HEAD_MISMATCH",
76
+ message: `Evidence head SHA "${regression.headSha}" does not match current head "${currentHeadSha}"`,
77
+ };
78
+ }
79
+ return { ok: true };
80
+ }
81
+ // ─── PR 查找 ───
82
+ /**
83
+ * 按 repo + head branch 查询已存在的 open PR。
84
+ */
85
+ async function findExistingPR(repo, headBranch) {
86
+ try {
87
+ const { stdout } = await gh(`pr list --head "${headBranch}" --repo "${repo}" --state open --json number,url --jq '.[0]'`);
88
+ if (!stdout.trim())
89
+ return null;
90
+ const pr = JSON.parse(stdout);
91
+ if (!pr || typeof pr.number !== "number")
92
+ return null;
93
+ return { number: pr.number, url: pr.url };
94
+ }
95
+ catch {
96
+ return null;
97
+ }
98
+ }
99
+ // ─── PR 创建 ───
100
+ /**
101
+ * 创建或复用 PR。
102
+ *
103
+ * 流程:
104
+ * 1. 查询已有 open PR(按 head branch)
105
+ * 2. 已有 → 复用(created: false)
106
+ * 3. 无 → 创建新 PR(created: true)
107
+ *
108
+ * @throws 如果 gh CLI 执行失败
109
+ */
110
+ export async function createOrReusePR(params) {
111
+ // 1. 查询已有 PR
112
+ const existing = await findExistingPR(params.repo, params.headBranch);
113
+ if (existing) {
114
+ return {
115
+ prNumber: existing.number,
116
+ prUrl: existing.url,
117
+ created: false,
118
+ };
119
+ }
120
+ // 2. 创建新 PR
121
+ const escapedTitle = params.title.replace(/'/g, "'\\''");
122
+ const escapedBody = params.body.replace(/'/g, "'\\''");
123
+ const { stdout } = await gh(`pr create --head "${params.headBranch}" --base "${params.baseBranch}" --title '${escapedTitle}' --body '${escapedBody}'`);
124
+ const prNumber = parsePrNumber(stdout);
125
+ if (prNumber === null) {
126
+ throw new Error(`Failed to parse PR number from gh output: ${stdout}`);
127
+ }
128
+ return {
129
+ prNumber,
130
+ prUrl: stdout.trim(),
131
+ created: true,
132
+ };
133
+ }
134
+ // ─── Rework 流程 ───
135
+ /**
136
+ * 发起 rework。
137
+ *
138
+ * behavior rework:
139
+ * - 声明 affected criterionIds,增加 reworkRevision
140
+ * - 重置 regression 和 verification 为 pending
141
+ * - 旧 cycle 保持不变(不重新绑定)
142
+ *
143
+ * refactor rework:
144
+ * - 不要求 RED,但必须重跑 regression + 审批
145
+ * - 同样增加 reworkRevision,重置 evidence
146
+ *
147
+ * 要求:Task 状态为 reviewing 且已有 PR。
148
+ */
149
+ export function initiateRework(task, input) {
150
+ if (task.status !== "reviewing") {
151
+ return {
152
+ ok: false,
153
+ code: "TASK_NOT_REVIEWING",
154
+ message: `Task "${task.id}" is not in reviewing status (current: ${task.status})`,
155
+ };
156
+ }
157
+ if (task.prNumber === null) {
158
+ return {
159
+ ok: false,
160
+ code: "NO_PR_EXISTS",
161
+ message: `Task "${task.id}" has no associated PR`,
162
+ };
163
+ }
164
+ const evidence = task.tddEvidence;
165
+ const newRevision = evidence.reworkRevision + 1;
166
+ const rework = {
167
+ reworkRevision: newRevision,
168
+ kind: input.kind,
169
+ affectedCriterionIds: input.affectedCriterionIds,
170
+ status: "started",
171
+ startHeadSha: input.startHeadSha,
172
+ approval: null,
173
+ };
174
+ const updatedTask = {
175
+ ...task,
176
+ tddEvidence: {
177
+ ...evidence,
178
+ reworkRevision: newRevision,
179
+ status: "in-progress",
180
+ regression: {
181
+ status: "pending",
182
+ headSha: null,
183
+ treeSha: null,
184
+ reworkRevision: newRevision,
185
+ runs: [],
186
+ },
187
+ verification: {
188
+ status: "pending",
189
+ headSha: null,
190
+ treeSha: null,
191
+ runs: [],
192
+ },
193
+ reworks: [...evidence.reworks, rework],
194
+ updatedAt: new Date().toISOString(),
195
+ },
196
+ };
197
+ return { ok: true, task: updatedTask };
198
+ }
199
+ /**
200
+ * 完成 rework,验证后恢复 Task 为 reviewing。
201
+ *
202
+ * 检查:
203
+ * 1. 当前有激活的 rework(evidence.status === "in-progress")
204
+ * 2. regression 和 verification 均已 pass
205
+ * 3. evidence head SHA 与 committed head 一致
206
+ */
207
+ export function completeRework(task, input) {
208
+ const evidence = task.tddEvidence;
209
+ // 1. 检查是否有激活的 rework
210
+ if (evidence.status !== "in-progress") {
211
+ return {
212
+ ok: false,
213
+ code: "NO_ACTIVE_REWORK",
214
+ message: `Task "${task.id}" has no active rework (current TDD status: ${evidence.status})`,
215
+ };
216
+ }
217
+ // 2. 检查 regression
218
+ if (evidence.regression.status !== "pass") {
219
+ return {
220
+ ok: false,
221
+ code: "REGRESSION_NOT_PASS",
222
+ message: `Committed-head regression is not pass (status: ${evidence.regression.status})`,
223
+ };
224
+ }
225
+ // 3. 检查 verification
226
+ if (evidence.verification.status !== "pass") {
227
+ return {
228
+ ok: false,
229
+ code: "VERIFICATION_NOT_PASS",
230
+ message: `Final verification is not pass (status: ${evidence.verification.status})`,
231
+ };
232
+ }
233
+ // 4. 检查 head SHA 一致性(regression 和 verification 都需检查)
234
+ const regHead = evidence.regression.headSha;
235
+ const verHead = evidence.verification.headSha;
236
+ if (regHead !== input.committedHeadSha) {
237
+ return {
238
+ ok: false,
239
+ code: "HEAD_MISMATCH",
240
+ message: `Regression head SHA "${regHead}" does not match committed head "${input.committedHeadSha}"`,
241
+ };
242
+ }
243
+ if (verHead !== input.committedHeadSha) {
244
+ return {
245
+ ok: false,
246
+ code: "HEAD_MISMATCH",
247
+ message: `Verification head SHA "${verHead}" does not match committed head "${input.committedHeadSha}"`,
248
+ };
249
+ }
250
+ // 更新最后一个 rework 状态为 pass
251
+ const reworks = [...evidence.reworks];
252
+ if (reworks.length > 0) {
253
+ const last = { ...reworks[reworks.length - 1] };
254
+ last.status = "pass";
255
+ reworks[reworks.length - 1] = last;
256
+ }
257
+ const updatedTask = {
258
+ ...task,
259
+ status: "reviewing",
260
+ tddEvidence: {
261
+ ...evidence,
262
+ status: "pass",
263
+ reworks,
264
+ updatedAt: new Date().toISOString(),
265
+ },
266
+ };
267
+ return { ok: true, task: updatedTask };
268
+ }
269
+ // ─── Remote head revalidation ───
270
+ /**
271
+ * 查询 remote PR 的 head commit SHA 和 tree SHA。
272
+ *
273
+ * 步骤:
274
+ * 1. `gh pr view --json headRefOid` 获取完整 JSON,自行解析提取 headRefOid
275
+ * 2. `gh api repos/{owner}/{repo}/git/commits/{sha} --jq '.tree.sha'` 获取 tree SHA
276
+ */
277
+ export async function fetchRemotePRHead(repo, prNumber) {
278
+ // 步骤 1: 查询 PR head SHA
279
+ let prJson;
280
+ try {
281
+ const { stdout } = await gh(`pr view ${prNumber} --repo "${repo}" --json headRefOid`);
282
+ try {
283
+ prJson = JSON.parse(stdout);
284
+ }
285
+ catch {
286
+ return { ok: false, code: "PARSE_ERROR", message: "Failed to parse gh pr view JSON output" };
287
+ }
288
+ }
289
+ catch (err) {
290
+ return { ok: false, code: "GH_ERROR", message: `Failed to fetch PR head: ${String(err)}` };
291
+ }
292
+ if (!prJson || typeof prJson !== "object") {
293
+ return { ok: false, code: "PARSE_ERROR", message: "gh pr view returned unexpected output" };
294
+ }
295
+ const prData = prJson;
296
+ if (!prData.headRefOid || typeof prData.headRefOid !== "string") {
297
+ return { ok: false, code: "MISSING_HEAD_SHA", message: "Remote PR headRefOid is missing or not a string" };
298
+ }
299
+ const headSha = prData.headRefOid;
300
+ // 步骤 2: 获取 tree SHA
301
+ let treeSha;
302
+ try {
303
+ const { stdout } = await gh(`api repos/${repo}/git/commits/${headSha} --jq '.tree.sha'`);
304
+ treeSha = stdout.trim();
305
+ if (!treeSha) {
306
+ return { ok: false, code: "MISSING_HEAD_SHA", message: "Remote commit tree SHA is empty" };
307
+ }
308
+ }
309
+ catch (err) {
310
+ return { ok: false, code: "GH_ERROR", message: `Failed to fetch commit tree SHA: ${String(err)}` };
311
+ }
312
+ return { ok: true, head: { headSha, treeSha } };
313
+ }
314
+ /**
315
+ * 重新验证 remote head。
316
+ *
317
+ * 比较 task.tddEvidence.verification.treeSha 与 remote tree SHA:
318
+ * - 相同 tree SHA:可以重新绑定 new head(重跑 regression/verification)
319
+ * - 不同 tree SHA:需要先执行 rework
320
+ */
321
+ export function revalidateRemoteHead(task, remoteHead) {
322
+ const evidenceTreeSha = task.tddEvidence.verification.treeSha;
323
+ if (!evidenceTreeSha) {
324
+ return {
325
+ ok: false,
326
+ action: "rework-needed",
327
+ summary: `No tree SHA in evidence; remote head ${remoteHead.headSha.slice(0, 7)} (tree: ${remoteHead.treeSha.slice(0, 7)}) requires rework`,
328
+ };
329
+ }
330
+ if (evidenceTreeSha === remoteHead.treeSha) {
331
+ return {
332
+ ok: true,
333
+ action: "revalidate",
334
+ summary: `Remote head ${remoteHead.headSha.slice(0, 7)} tree matches evidence tree ${evidenceTreeSha.slice(0, 7)} — re-run regression and rebind head`,
335
+ };
336
+ }
337
+ return {
338
+ ok: false,
339
+ action: "rework-needed",
340
+ summary: `Remote head ${remoteHead.headSha.slice(0, 7)} tree changed (was: ${evidenceTreeSha.slice(0, 7)}, now: ${remoteHead.treeSha.slice(0, 7)}) — rework required`,
341
+ };
342
+ }
343
+ //# sourceMappingURL=pr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pr.js","sourceRoot":"","sources":["../../src/flowrun/pr.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ import type { TddEvidence, TddCycleEvidence, TddCommandEvidence, AcceptanceCriterion, VersionedDigest } from "./types.js";
2
+ export interface StateError {
3
+ code: string;
4
+ message: string;
5
+ }
6
+ export type StateResult<T> = {
7
+ ok: true;
8
+ value: T;
9
+ } | {
10
+ ok: false;
11
+ error: StateError;
12
+ };
13
+ /**
14
+ * 创建初始 TddEvidence(status=not-recorded, revision=0)。
15
+ */
16
+ export declare function createTaskEvidence(): TddEvidence;
17
+ /**
18
+ * 启动一个新的 TDD cycle。
19
+ *
20
+ * 验证:
21
+ * - criterion 存在且 verification=tdd
22
+ * - testPaths 匹配 testFilePatterns
23
+ * - 同 cycleId + 同 workspace digest → 幂等返回原 evidence
24
+ * - 同 cycleId + 不同 workspace digest → CYCLE_CONFLICT
25
+ */
26
+ export declare function startCycle(evidence: TddEvidence, cycleId: string, criterionId: string, testPaths: string[], testSelector: string, workspaceDigest: VersionedDigest, acceptanceCriteria: AcceptanceCriterion[], testFilePatterns: string[]): StateResult<{
27
+ evidence: TddEvidence;
28
+ cycle: TddCycleEvidence;
29
+ }>;
30
+ /**
31
+ * 记录 RED 尝试。
32
+ *
33
+ * 验证:
34
+ * - cycle 存在且 status ∈ {started, red}
35
+ * - failureKind 为 assertion 或 missing-behavior(有效 RED)
36
+ * - 幂等:相同 outputDigest → 返回原结果
37
+ */
38
+ export declare function recordRed(evidence: TddEvidence, cycleId: string, redEvidence: TddCommandEvidence): StateResult<{
39
+ evidence: TddEvidence;
40
+ cycle: TddCycleEvidence;
41
+ }>;
42
+ /**
43
+ * 记录 GREEN 尝试。
44
+ *
45
+ * 验证:
46
+ * - cycle 存在且已有有效 RED(redTestDigest !== null)
47
+ * - GREEN exitCode === 0
48
+ * - implementation files 有变化
49
+ * - 幂等:相同 outputDigest → 返回原结果
50
+ */
51
+ export declare function recordGreen(evidence: TddEvidence, cycleId: string, greenEvidence: TddCommandEvidence, implementationFilesChanged: boolean): StateResult<{
52
+ evidence: TddEvidence;
53
+ cycle: TddCycleEvidence;
54
+ }>;
55
+ /**
56
+ * 记录最终 regression 结果。
57
+ *
58
+ * 验证:
59
+ * - runs 非空
60
+ * - 所有 run exitCode === 0 且无 timeout 则 pass,否则 fail
61
+ */
62
+ export declare function recordFinalRegression(evidence: TddEvidence, headSha: string, treeSha: string, runs: TddCommandEvidence[]): StateResult<TddEvidence>;
63
+ /**
64
+ * 记录最终 verification 结果。
65
+ *
66
+ * 规则:
67
+ * - runs 为空 → pass(未配置 verifyCommands)
68
+ * - 所有 run exitCode === 0 则 pass,否则 fail
69
+ */
70
+ export declare function recordFinalVerification(evidence: TddEvidence, headSha: string, treeSha: string, runs: TddCommandEvidence[]): StateResult<TddEvidence>;
71
+ /**
72
+ * 放弃一个 cycle。
73
+ *
74
+ * 规则:
75
+ * - cycle 必须存在
76
+ * - cycle 状态不能是 "pass"(已通过的 cycle 不能放弃)
77
+ * - 保留审计记录,reason 写入 warnings
78
+ */
79
+ export declare function abandonCycle(evidence: TddEvidence, cycleId: string, reason: string): StateResult<TddEvidence>;