@devcxl/opencode-cabbage 0.2.1 → 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.
- package/assets/agents/dev-lifecycle.md +25 -19
- package/assets/agents/team/architect.md +14 -0
- package/assets/agents/team/backend.md +14 -0
- package/assets/agents/team/frontend.md +14 -0
- package/assets/agents/team/goal-verify.md +54 -0
- package/assets/agents/team/reviewer.md +10 -0
- package/assets/skills/flow-code/SKILL.md +13 -0
- package/assets/skills/flow-review/SKILL.md +7 -0
- package/assets/skills/flow-tasks/SKILL.md +42 -0
- package/assets/skills/flow-tdd/SKILL.md +208 -0
- package/dist/flowrun/adapter.d.ts +49 -0
- package/dist/flowrun/adapter.js +293 -0
- package/dist/flowrun/adapter.js.map +1 -0
- package/dist/flowrun/ci.d.ts +64 -0
- package/dist/flowrun/ci.js +184 -0
- package/dist/flowrun/ci.js.map +1 -0
- package/dist/flowrun/coverage.d.ts +70 -0
- package/dist/flowrun/coverage.js +207 -0
- package/dist/flowrun/coverage.js.map +1 -0
- package/dist/flowrun/digest.d.ts +17 -0
- package/dist/flowrun/digest.js +301 -0
- package/dist/flowrun/digest.js.map +1 -0
- package/dist/flowrun/evaluator.d.ts +38 -0
- package/dist/flowrun/evaluator.js +185 -0
- package/dist/flowrun/evaluator.js.map +1 -0
- package/dist/flowrun/gate.d.ts +20 -0
- package/dist/flowrun/gate.js +40 -3
- package/dist/flowrun/gate.js.map +1 -1
- package/dist/flowrun/github.d.ts +13 -9
- package/dist/flowrun/github.js +46 -26
- package/dist/flowrun/github.js.map +1 -1
- package/dist/flowrun/index.d.ts +12 -4
- package/dist/flowrun/index.js +11 -3
- package/dist/flowrun/index.js.map +1 -1
- package/dist/flowrun/merge.d.ts +35 -2
- package/dist/flowrun/merge.js +72 -8
- package/dist/flowrun/merge.js.map +1 -1
- package/dist/flowrun/migration.d.ts +11 -0
- package/dist/flowrun/migration.js +276 -0
- package/dist/flowrun/migration.js.map +1 -0
- package/dist/flowrun/pr.d.ts +132 -0
- package/dist/flowrun/pr.js +343 -0
- package/dist/flowrun/pr.js.map +1 -0
- package/dist/flowrun/state.d.ts +79 -0
- package/dist/flowrun/state.js +363 -0
- package/dist/flowrun/state.js.map +1 -0
- package/dist/flowrun/transitions.d.ts +66 -0
- package/dist/flowrun/transitions.js +168 -0
- package/dist/flowrun/transitions.js.map +1 -0
- package/dist/flowrun/types.d.ts +279 -4
- package/dist/flowrun/types.js +2 -1
- package/dist/flowrun/types.js.map +1 -1
- package/dist/flowrun/validator.d.ts +15 -5
- package/dist/flowrun/validator.js +117 -5
- package/dist/flowrun/validator.js.map +1 -1
- package/dist/plugin/agents.d.ts +4 -0
- package/dist/plugin/agents.js +19 -0
- package/dist/plugin/agents.js.map +1 -1
- package/dist/plugin/broker.d.ts +73 -0
- package/dist/plugin/broker.js +140 -0
- package/dist/plugin/broker.js.map +1 -0
- package/dist/plugin/flow-pr-tool.d.ts +37 -0
- package/dist/plugin/flow-pr-tool.js +176 -0
- package/dist/plugin/flow-pr-tool.js.map +1 -0
- package/dist/plugin/goal.d.ts +39 -1
- package/dist/plugin/goal.js +80 -1
- package/dist/plugin/goal.js.map +1 -1
- package/dist/plugin/prompt-lint.js +129 -0
- package/dist/plugin/prompt-lint.js.map +1 -1
- package/dist/plugin/server.js +295 -11
- package/dist/plugin/server.js.map +1 -1
- package/dist/plugin/shell.d.ts +37 -0
- package/dist/plugin/shell.js +144 -0
- package/dist/plugin/shell.js.map +1 -0
- package/dist/plugin/tdd-tool.d.ts +62 -0
- package/dist/plugin/tdd-tool.js +336 -0
- package/dist/plugin/tdd-tool.js.map +1 -0
- package/dist/util/gh.d.ts +8 -1
- package/dist/util/gh.js +10 -2
- package/dist/util/gh.js.map +1 -1
- package/package.json +2 -1
package/dist/flowrun/merge.js
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
let mergeGhExecutor = null;
|
|
2
|
+
export function setMergeGhExecutor(fn) {
|
|
3
|
+
mergeGhExecutor = fn;
|
|
4
|
+
}
|
|
5
|
+
async function gh(args) {
|
|
6
|
+
if (mergeGhExecutor) {
|
|
7
|
+
return mergeGhExecutor(args);
|
|
8
|
+
}
|
|
9
|
+
const mod = await import("../util/gh.js");
|
|
10
|
+
return mod.gh(args);
|
|
11
|
+
}
|
|
12
|
+
// ─── Branch Protection ───
|
|
3
13
|
export async function checkBranchProtection(owner, repo) {
|
|
4
14
|
try {
|
|
5
15
|
const { stdout } = await gh(`api repos/${owner}/${repo}/branches/main/protection`);
|
|
@@ -26,6 +36,7 @@ export async function checkBranchProtection(owner, repo) {
|
|
|
26
36
|
};
|
|
27
37
|
}
|
|
28
38
|
}
|
|
39
|
+
// ─── Checkpoint 验证 ───
|
|
29
40
|
export function validateCheckpoint(cp) {
|
|
30
41
|
if (cp.status === "pass")
|
|
31
42
|
return "pass";
|
|
@@ -63,24 +74,51 @@ export function validatePRCheckpoints(checkpoints) {
|
|
|
63
74
|
}
|
|
64
75
|
return { allowed: true, checkpointResults: results };
|
|
65
76
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
77
|
+
// ─── Task-local Merge Gate ───
|
|
78
|
+
/**
|
|
79
|
+
* Task-local merge gate(不依赖全局 canMerge)。
|
|
80
|
+
*
|
|
81
|
+
* 检查条件(按顺序):
|
|
82
|
+
* 1. Task 状态为 "reviewing"
|
|
83
|
+
* 2. 存在 PR Checkpoints
|
|
84
|
+
* 3. 所有 checkpoint 状态为 pass
|
|
85
|
+
* 4. TDD compliance 为 pass / waived / null(无 TDD 要求)
|
|
86
|
+
* 5. Branch Protection 已启用
|
|
87
|
+
*
|
|
88
|
+
* 不要求全局 review Stage 为 pass。
|
|
89
|
+
*/
|
|
90
|
+
export function canMergeTaskPR(task, hasBranchProtection) {
|
|
91
|
+
// 1. Task 状态检查
|
|
71
92
|
if (task.status === "merged") {
|
|
72
93
|
return { allowed: false, reason: "Task already merged", checkpointResults: {} };
|
|
73
94
|
}
|
|
74
95
|
if (task.status !== "reviewing") {
|
|
75
96
|
return { allowed: false, reason: `Task status is ${task.status}, expected reviewing`, checkpointResults: {} };
|
|
76
97
|
}
|
|
98
|
+
// 2. PR Checkpoints 存在性
|
|
77
99
|
if (!task.prCheckpoints) {
|
|
78
100
|
return { allowed: false, reason: "No PR checkpoints recorded", checkpointResults: {} };
|
|
79
101
|
}
|
|
102
|
+
// 3. 标准 checkpoint 验证
|
|
80
103
|
const prResult = validatePRCheckpoints(task.prCheckpoints);
|
|
81
104
|
if (!prResult.allowed)
|
|
82
105
|
return prResult;
|
|
83
|
-
|
|
106
|
+
// 4. TDD compliance 验证
|
|
107
|
+
const tdd = task.prCheckpoints.tddCompliance;
|
|
108
|
+
if (tdd !== null && tdd.status === "fail") {
|
|
109
|
+
prResult.checkpointResults["tddCompliance"] = "fail";
|
|
110
|
+
return {
|
|
111
|
+
allowed: false,
|
|
112
|
+
reason: `TDD compliance failed: ${tdd.summary}`,
|
|
113
|
+
checkpointResults: prResult.checkpointResults,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
// tdd === null → 无 TDD 要求,视为通过
|
|
117
|
+
// tdd.status === "pass" / "waived" → 通过
|
|
118
|
+
prResult.checkpointResults["tddCompliance"] =
|
|
119
|
+
tdd === null ? "skipped" : tdd.status;
|
|
120
|
+
// 5. Branch Protection
|
|
121
|
+
if (!hasBranchProtection) {
|
|
84
122
|
prResult.checkpointResults.branchProtection = "fail";
|
|
85
123
|
return {
|
|
86
124
|
allowed: false,
|
|
@@ -91,6 +129,10 @@ export function canAutoMergeTask(flowRun, task, protection) {
|
|
|
91
129
|
prResult.checkpointResults.branchProtection = "pass";
|
|
92
130
|
return prResult;
|
|
93
131
|
}
|
|
132
|
+
// ─── PR 合并操作 ───
|
|
133
|
+
/**
|
|
134
|
+
* 标准化合并 PR(无安全检查,向后兼容)。
|
|
135
|
+
*/
|
|
94
136
|
export async function mergePR(prNumber) {
|
|
95
137
|
try {
|
|
96
138
|
await gh(`pr merge ${prNumber} --squash --delete-branch`);
|
|
@@ -100,6 +142,28 @@ export async function mergePR(prNumber) {
|
|
|
100
142
|
return { success: false, error: String(err) };
|
|
101
143
|
}
|
|
102
144
|
}
|
|
145
|
+
/**
|
|
146
|
+
* Task-local PR 合并(带 --match-head-commit 安全检查)。
|
|
147
|
+
*
|
|
148
|
+
* 步骤:
|
|
149
|
+
* 1. 验证 verifiedSha 非空
|
|
150
|
+
* 2. 使用 gh pr merge --squash --delete-branch --match-head-commit <verifiedSha>
|
|
151
|
+
* 3. 失败时返回错误
|
|
152
|
+
*/
|
|
153
|
+
export async function mergeTaskPR(prNumber, verifiedSha) {
|
|
154
|
+
if (!verifiedSha) {
|
|
155
|
+
return { success: false, error: "verifiedSha is required for merge --match-head-commit" };
|
|
156
|
+
}
|
|
157
|
+
try {
|
|
158
|
+
// --match-head-commit 确保只有 verified 的 commit 才会被合并
|
|
159
|
+
await gh(`pr merge ${prNumber} --squash --delete-branch --match-head-commit ${verifiedSha}`);
|
|
160
|
+
return { success: true };
|
|
161
|
+
}
|
|
162
|
+
catch (err) {
|
|
163
|
+
return { success: false, error: String(err) };
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
// ─── Revert ───
|
|
103
167
|
export async function createRevertPR(prNumber, reason) {
|
|
104
168
|
try {
|
|
105
169
|
const { stdout } = await gh(`pr view ${prNumber} --json headRefName,headRepository,body,title`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merge.js","sourceRoot":"","sources":["../../src/flowrun/merge.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"merge.js","sourceRoot":"","sources":["../../src/flowrun/merge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { FlowRunReadResult } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* v1→v2 幂等迁移器
|
|
4
|
+
*
|
|
5
|
+
* 纯函数:输入 v1 FlowRun (unknown),输出 FlowRunReadResult。
|
|
6
|
+
* - 如果输入已经是 v2 格式 → 直接返回(幂等)
|
|
7
|
+
* - 如果 schemaVersion > 2 → 返回 UNSUPPORTED_SCHEMA
|
|
8
|
+
* - 如果 schemaVersion 缺失/非整数/< 1 → 返回 VALIDATION_FAILED
|
|
9
|
+
* - 如果 schemaVersion === 1 → 执行迁移
|
|
10
|
+
*/
|
|
11
|
+
export declare function migrateV1ToV2(flowRun: unknown): FlowRunReadResult;
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import { CURRENT_SCHEMA_VERSION } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* v1→v2 幂等迁移器
|
|
4
|
+
*
|
|
5
|
+
* 纯函数:输入 v1 FlowRun (unknown),输出 FlowRunReadResult。
|
|
6
|
+
* - 如果输入已经是 v2 格式 → 直接返回(幂等)
|
|
7
|
+
* - 如果 schemaVersion > 2 → 返回 UNSUPPORTED_SCHEMA
|
|
8
|
+
* - 如果 schemaVersion 缺失/非整数/< 1 → 返回 VALIDATION_FAILED
|
|
9
|
+
* - 如果 schemaVersion === 1 → 执行迁移
|
|
10
|
+
*/
|
|
11
|
+
export function migrateV1ToV2(flowRun) {
|
|
12
|
+
if (!flowRun || typeof flowRun !== "object") {
|
|
13
|
+
return { ok: false, code: "INVALID_JSON", errors: [{ path: "", message: "FlowRun must be a non-null object" }] };
|
|
14
|
+
}
|
|
15
|
+
const obj = flowRun;
|
|
16
|
+
const version = obj.schemaVersion;
|
|
17
|
+
if (typeof version !== "number" || !Number.isInteger(version) || version < 1) {
|
|
18
|
+
return {
|
|
19
|
+
ok: false,
|
|
20
|
+
code: "VALIDATION_FAILED",
|
|
21
|
+
errors: [{ path: "schemaVersion", message: `Must be a positive integer, got: ${version}` }],
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
if (version > CURRENT_SCHEMA_VERSION) {
|
|
25
|
+
return {
|
|
26
|
+
ok: false,
|
|
27
|
+
code: "UNSUPPORTED_SCHEMA",
|
|
28
|
+
errors: [{ path: "schemaVersion", message: `Schema version ${version} is not supported (current: ${CURRENT_SCHEMA_VERSION})` }],
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
// 已经是 v2,直接返回
|
|
32
|
+
if (version === CURRENT_SCHEMA_VERSION) {
|
|
33
|
+
return { ok: true, data: obj, migrated: false };
|
|
34
|
+
}
|
|
35
|
+
// v1 → v2 迁移
|
|
36
|
+
try {
|
|
37
|
+
const migrated = doMigrateV1ToV2(obj);
|
|
38
|
+
return { ok: true, data: migrated, migrated: true };
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
return {
|
|
42
|
+
ok: false,
|
|
43
|
+
code: "MIGRATION_FAILED",
|
|
44
|
+
errors: [{ path: "", message: `Migration failed: ${String(err)}` }],
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function doMigrateV1ToV2(v1) {
|
|
49
|
+
const tasks = {};
|
|
50
|
+
if (v1.tasks && typeof v1.tasks === "object") {
|
|
51
|
+
const v1Tasks = v1.tasks;
|
|
52
|
+
for (const [key, v1Task] of Object.entries(v1Tasks)) {
|
|
53
|
+
tasks[key] = migrateTaskV1ToV2(v1Task, key);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// v1 PR checkpoints 有旧的 PR 字段,需要补充 v2 的新字段
|
|
57
|
+
// 这些在 migrateTaskV1ToV2 中处理
|
|
58
|
+
return {
|
|
59
|
+
flowRunId: String(v1.flowRunId ?? ""),
|
|
60
|
+
repo: String(v1.repo ?? ""),
|
|
61
|
+
parentIssueNumber: Number(v1.parentIssueNumber ?? 0),
|
|
62
|
+
status: String(v1.status ?? "planned"),
|
|
63
|
+
schemaVersion: CURRENT_SCHEMA_VERSION,
|
|
64
|
+
revision: Number(v1.revision ?? 0),
|
|
65
|
+
stages: migrateStages(v1.stages),
|
|
66
|
+
tasks,
|
|
67
|
+
startedAt: typeof v1.startedAt === "string" ? v1.startedAt : null,
|
|
68
|
+
lastTickAt: typeof v1.lastTickAt === "string" ? v1.lastTickAt : null,
|
|
69
|
+
nextTickAfter: typeof v1.nextTickAfter === "string" ? v1.nextTickAfter : null,
|
|
70
|
+
maxRuntime: Number(v1.maxRuntime ?? 86_400_000),
|
|
71
|
+
completedAt: typeof v1.completedAt === "string" ? v1.completedAt : null,
|
|
72
|
+
repositoryQualityPolicy: { mode: "off", requiredChecks: [] },
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
function migrateStages(stages) {
|
|
76
|
+
function defaultStage() {
|
|
77
|
+
return {
|
|
78
|
+
status: "pending",
|
|
79
|
+
requiredArtifacts: [],
|
|
80
|
+
checks: [],
|
|
81
|
+
completedAt: null,
|
|
82
|
+
evidence: [],
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
if (!stages || typeof stages !== "object") {
|
|
86
|
+
return {
|
|
87
|
+
requirements: defaultStage(),
|
|
88
|
+
design: defaultStage(),
|
|
89
|
+
tasks: defaultStage(),
|
|
90
|
+
code: defaultStage(),
|
|
91
|
+
test: defaultStage(),
|
|
92
|
+
review: defaultStage(),
|
|
93
|
+
merge: defaultStage(),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
const s = stages;
|
|
97
|
+
const stageKeys = ["requirements", "design", "tasks", "code", "test", "review", "merge"];
|
|
98
|
+
const result = {};
|
|
99
|
+
for (const key of stageKeys) {
|
|
100
|
+
const val = s[key];
|
|
101
|
+
if (val && typeof val === "object") {
|
|
102
|
+
const v = val;
|
|
103
|
+
result[key] = {
|
|
104
|
+
status: (typeof v.status === "string" && ["pending", "running", "pass", "failed", "blocked"].includes(v.status))
|
|
105
|
+
? v.status
|
|
106
|
+
: "pending",
|
|
107
|
+
requiredArtifacts: Array.isArray(v.requiredArtifacts) ? v.requiredArtifacts : [],
|
|
108
|
+
checks: Array.isArray(v.checks) ? v.checks : [],
|
|
109
|
+
completedAt: typeof v.completedAt === "string" ? v.completedAt : null,
|
|
110
|
+
evidence: Array.isArray(v.evidence) ? v.evidence : [],
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
result[key] = defaultStage();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* 将单个 v1 Task 迁移为 v2 TaskState
|
|
121
|
+
*/
|
|
122
|
+
function migrateTaskV1ToV2(v1Task, recordKey) {
|
|
123
|
+
const hasTestCommands = Array.isArray(v1Task.testCommands) && v1Task.testCommands.length > 0;
|
|
124
|
+
// 迁移 testCommands: string[] → TaskCommand[]
|
|
125
|
+
const testCommands = hasTestCommands
|
|
126
|
+
? v1Task.testCommands.map(cmd => ({
|
|
127
|
+
command: cmd,
|
|
128
|
+
cwd: ".",
|
|
129
|
+
timeoutMs: 120_000,
|
|
130
|
+
env: {},
|
|
131
|
+
}))
|
|
132
|
+
: [];
|
|
133
|
+
// 迁移 acceptance → acceptanceCriteria
|
|
134
|
+
const v1Acceptance = typeof v1Task.acceptance === "string" ? v1Task.acceptance : "";
|
|
135
|
+
const acceptanceCriteria = [
|
|
136
|
+
{
|
|
137
|
+
id: "legacy-1",
|
|
138
|
+
description: v1Acceptance || "历史任务验收条件(v1 迁移)",
|
|
139
|
+
verification: hasTestCommands ? "regression" : "manual",
|
|
140
|
+
},
|
|
141
|
+
];
|
|
142
|
+
// 构造 TDD policy(按 spec 10.2)
|
|
143
|
+
const tddPolicy = {
|
|
144
|
+
mode: hasTestCommands ? "relaxed" : "bypass",
|
|
145
|
+
enforcement: "advisory",
|
|
146
|
+
runner: null,
|
|
147
|
+
testFilePatterns: [],
|
|
148
|
+
implementationFilePatterns: [],
|
|
149
|
+
generatedArtifactPatterns: [],
|
|
150
|
+
exception: {
|
|
151
|
+
reason: "legacy schema v1 migration",
|
|
152
|
+
alternativeValidation: hasTestCommands
|
|
153
|
+
? testCommands.map((cmd, i) => ({
|
|
154
|
+
validationId: `legacy-alt-${i + 1}`,
|
|
155
|
+
kind: "command",
|
|
156
|
+
command: cmd,
|
|
157
|
+
}))
|
|
158
|
+
: [{
|
|
159
|
+
validationId: "legacy-alt-1",
|
|
160
|
+
kind: "manual",
|
|
161
|
+
description: "历史任务未记录自动验证",
|
|
162
|
+
}],
|
|
163
|
+
approval: {
|
|
164
|
+
kind: "legacy-migration",
|
|
165
|
+
fromSchemaVersion: 1,
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
source: {
|
|
169
|
+
manifestPath: "legacy:v1",
|
|
170
|
+
revisionSha: "migration:v1",
|
|
171
|
+
},
|
|
172
|
+
};
|
|
173
|
+
// 构造 TDD evidence(完整默认对象)
|
|
174
|
+
const tddEvidence = {
|
|
175
|
+
revision: 0,
|
|
176
|
+
reworkRevision: 0,
|
|
177
|
+
status: "not-recorded",
|
|
178
|
+
taskStart: makeDefaultTaskStart(),
|
|
179
|
+
cycles: [],
|
|
180
|
+
regression: makeDefaultRegression(),
|
|
181
|
+
verification: makeDefaultVerification(),
|
|
182
|
+
alternativeValidation: [],
|
|
183
|
+
reworks: [],
|
|
184
|
+
warnings: ["legacy schema v1 migration: evidence not recorded"],
|
|
185
|
+
updatedAt: null,
|
|
186
|
+
};
|
|
187
|
+
// 迁移 PR checkpoints(保留旧字段 + 新增 null)
|
|
188
|
+
const v1PR = v1Task.prCheckpoints;
|
|
189
|
+
const prCheckpoints = v1PR && typeof v1PR === "object"
|
|
190
|
+
? migratePRCheckpoints(v1PR)
|
|
191
|
+
: null;
|
|
192
|
+
return {
|
|
193
|
+
id: String(v1Task.id ?? recordKey),
|
|
194
|
+
name: String(v1Task.name ?? recordKey),
|
|
195
|
+
status: (typeof v1Task.status === "string" ? v1Task.status : "pending"),
|
|
196
|
+
dependsOn: Array.isArray(v1Task.dependsOn) ? v1Task.dependsOn : [],
|
|
197
|
+
area: String(v1Task.area ?? ""),
|
|
198
|
+
expectedFiles: Array.isArray(v1Task.expectedFiles) ? v1Task.expectedFiles : [],
|
|
199
|
+
parallelSafe: Boolean(v1Task.parallelSafe ?? false),
|
|
200
|
+
prNumber: typeof v1Task.prNumber === "number" ? v1Task.prNumber : null,
|
|
201
|
+
prCheckpoints,
|
|
202
|
+
blockedReason: typeof v1Task.blockedReason === "string" ? v1Task.blockedReason : null,
|
|
203
|
+
startedAt: typeof v1Task.startedAt === "string" ? v1Task.startedAt : null,
|
|
204
|
+
// v2 新字段
|
|
205
|
+
acceptanceCriteria,
|
|
206
|
+
testCommands,
|
|
207
|
+
verifyCommands: [],
|
|
208
|
+
executionBinding: null,
|
|
209
|
+
tddPolicy,
|
|
210
|
+
tddEvidence,
|
|
211
|
+
coveragePolicy: null,
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
function migratePRCheckpoints(v1PR) {
|
|
215
|
+
function makeCheckpoint(name) {
|
|
216
|
+
return {
|
|
217
|
+
name,
|
|
218
|
+
status: "pending",
|
|
219
|
+
evidence: [],
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
const getCheckpoint = (key) => {
|
|
223
|
+
const cp = v1PR[key];
|
|
224
|
+
if (cp && typeof cp === "object") {
|
|
225
|
+
const c = cp;
|
|
226
|
+
return {
|
|
227
|
+
name: String(c.name ?? key),
|
|
228
|
+
status: (typeof c.status === "string" && ["pending", "pass", "fail"].includes(c.status))
|
|
229
|
+
? c.status
|
|
230
|
+
: "pending",
|
|
231
|
+
evidence: Array.isArray(c.evidence) ? c.evidence : [],
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
return makeCheckpoint(key);
|
|
235
|
+
};
|
|
236
|
+
return {
|
|
237
|
+
prNumber: Number(v1PR.prNumber ?? 0),
|
|
238
|
+
localChecks: getCheckpoint("localChecks"),
|
|
239
|
+
ciChecks: getCheckpoint("ciChecks"),
|
|
240
|
+
reviewerApproval: getCheckpoint("reviewerApproval"),
|
|
241
|
+
goalVerification: getCheckpoint("goalVerification"),
|
|
242
|
+
branchProtection: getCheckpoint("branchProtection"),
|
|
243
|
+
mergeResult: getCheckpoint("mergeResult"),
|
|
244
|
+
// v2 新增
|
|
245
|
+
tddCompliance: null,
|
|
246
|
+
verification: null,
|
|
247
|
+
coverage: null,
|
|
248
|
+
qualityContractDigest: null,
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
function makeDefaultTaskStart() {
|
|
252
|
+
return {
|
|
253
|
+
status: "pending",
|
|
254
|
+
headSha: null,
|
|
255
|
+
treeSha: null,
|
|
256
|
+
startedAt: null,
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
function makeDefaultRegression() {
|
|
260
|
+
return {
|
|
261
|
+
status: "pending",
|
|
262
|
+
headSha: null,
|
|
263
|
+
treeSha: null,
|
|
264
|
+
reworkRevision: 0,
|
|
265
|
+
runs: [],
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
function makeDefaultVerification() {
|
|
269
|
+
return {
|
|
270
|
+
status: "pending",
|
|
271
|
+
headSha: null,
|
|
272
|
+
treeSha: null,
|
|
273
|
+
runs: [],
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
//# sourceMappingURL=migration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migration.js","sourceRoot":"","sources":["../../src/flowrun/migration.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import type { TaskState } from "./types.js";
|
|
2
|
+
export interface CreatePRParams {
|
|
3
|
+
repo: string;
|
|
4
|
+
headBranch: string;
|
|
5
|
+
baseBranch: string;
|
|
6
|
+
title: string;
|
|
7
|
+
body: string;
|
|
8
|
+
}
|
|
9
|
+
export interface CreatePRResult {
|
|
10
|
+
prNumber: number;
|
|
11
|
+
prUrl: string;
|
|
12
|
+
created: boolean;
|
|
13
|
+
}
|
|
14
|
+
export type PreflightResult = {
|
|
15
|
+
ok: true;
|
|
16
|
+
} | {
|
|
17
|
+
ok: false;
|
|
18
|
+
code: string;
|
|
19
|
+
message: string;
|
|
20
|
+
};
|
|
21
|
+
export interface ReworkInput {
|
|
22
|
+
kind: "behavior" | "refactor";
|
|
23
|
+
affectedCriterionIds: string[];
|
|
24
|
+
startHeadSha: string;
|
|
25
|
+
}
|
|
26
|
+
export type ReworkResult = {
|
|
27
|
+
ok: true;
|
|
28
|
+
task: TaskState;
|
|
29
|
+
} | {
|
|
30
|
+
ok: false;
|
|
31
|
+
code: string;
|
|
32
|
+
message: string;
|
|
33
|
+
};
|
|
34
|
+
export interface CompleteReworkInput {
|
|
35
|
+
committedHeadSha: string;
|
|
36
|
+
}
|
|
37
|
+
export type CompleteReworkResult = {
|
|
38
|
+
ok: true;
|
|
39
|
+
task: TaskState;
|
|
40
|
+
} | {
|
|
41
|
+
ok: false;
|
|
42
|
+
code: string;
|
|
43
|
+
message: string;
|
|
44
|
+
};
|
|
45
|
+
export interface RemotePRHead {
|
|
46
|
+
headSha: string;
|
|
47
|
+
treeSha: string;
|
|
48
|
+
}
|
|
49
|
+
export type FetchRemoteHeadResult = {
|
|
50
|
+
ok: true;
|
|
51
|
+
head: RemotePRHead;
|
|
52
|
+
} | {
|
|
53
|
+
ok: false;
|
|
54
|
+
code: string;
|
|
55
|
+
message: string;
|
|
56
|
+
};
|
|
57
|
+
export type RevalidateResult = {
|
|
58
|
+
ok: true;
|
|
59
|
+
action: "revalidate";
|
|
60
|
+
summary: string;
|
|
61
|
+
} | {
|
|
62
|
+
ok: false;
|
|
63
|
+
action: "rework-needed";
|
|
64
|
+
summary: string;
|
|
65
|
+
};
|
|
66
|
+
type GhFn = (args: string) => Promise<{
|
|
67
|
+
stdout: string;
|
|
68
|
+
stderr: string;
|
|
69
|
+
}>;
|
|
70
|
+
export declare function setGhExecutor(fn: GhFn): void;
|
|
71
|
+
/**
|
|
72
|
+
* 执行 PR 创建前的前置条件检查(无副作用)。
|
|
73
|
+
*
|
|
74
|
+
* 规则:
|
|
75
|
+
* 1. Task 状态为 running
|
|
76
|
+
* 2. committed-head regression.status === "pass"
|
|
77
|
+
* 3. committed-head verification.status === "pass"
|
|
78
|
+
* 4. evidence headSha 与当前 head 一致
|
|
79
|
+
*/
|
|
80
|
+
export declare function preflightPRCreate(task: TaskState, currentHeadSha: string): PreflightResult;
|
|
81
|
+
/**
|
|
82
|
+
* 创建或复用 PR。
|
|
83
|
+
*
|
|
84
|
+
* 流程:
|
|
85
|
+
* 1. 查询已有 open PR(按 head branch)
|
|
86
|
+
* 2. 已有 → 复用(created: false)
|
|
87
|
+
* 3. 无 → 创建新 PR(created: true)
|
|
88
|
+
*
|
|
89
|
+
* @throws 如果 gh CLI 执行失败
|
|
90
|
+
*/
|
|
91
|
+
export declare function createOrReusePR(params: CreatePRParams): Promise<CreatePRResult>;
|
|
92
|
+
/**
|
|
93
|
+
* 发起 rework。
|
|
94
|
+
*
|
|
95
|
+
* behavior rework:
|
|
96
|
+
* - 声明 affected criterionIds,增加 reworkRevision
|
|
97
|
+
* - 重置 regression 和 verification 为 pending
|
|
98
|
+
* - 旧 cycle 保持不变(不重新绑定)
|
|
99
|
+
*
|
|
100
|
+
* refactor rework:
|
|
101
|
+
* - 不要求 RED,但必须重跑 regression + 审批
|
|
102
|
+
* - 同样增加 reworkRevision,重置 evidence
|
|
103
|
+
*
|
|
104
|
+
* 要求:Task 状态为 reviewing 且已有 PR。
|
|
105
|
+
*/
|
|
106
|
+
export declare function initiateRework(task: TaskState, input: ReworkInput): ReworkResult;
|
|
107
|
+
/**
|
|
108
|
+
* 完成 rework,验证后恢复 Task 为 reviewing。
|
|
109
|
+
*
|
|
110
|
+
* 检查:
|
|
111
|
+
* 1. 当前有激活的 rework(evidence.status === "in-progress")
|
|
112
|
+
* 2. regression 和 verification 均已 pass
|
|
113
|
+
* 3. evidence head SHA 与 committed head 一致
|
|
114
|
+
*/
|
|
115
|
+
export declare function completeRework(task: TaskState, input: CompleteReworkInput): CompleteReworkResult;
|
|
116
|
+
/**
|
|
117
|
+
* 查询 remote PR 的 head commit SHA 和 tree SHA。
|
|
118
|
+
*
|
|
119
|
+
* 步骤:
|
|
120
|
+
* 1. `gh pr view --json headRefOid` 获取完整 JSON,自行解析提取 headRefOid
|
|
121
|
+
* 2. `gh api repos/{owner}/{repo}/git/commits/{sha} --jq '.tree.sha'` 获取 tree SHA
|
|
122
|
+
*/
|
|
123
|
+
export declare function fetchRemotePRHead(repo: string, prNumber: number): Promise<FetchRemoteHeadResult>;
|
|
124
|
+
/**
|
|
125
|
+
* 重新验证 remote head。
|
|
126
|
+
*
|
|
127
|
+
* 比较 task.tddEvidence.verification.treeSha 与 remote tree SHA:
|
|
128
|
+
* - 相同 tree SHA:可以重新绑定 new head(重跑 regression/verification)
|
|
129
|
+
* - 不同 tree SHA:需要先执行 rework
|
|
130
|
+
*/
|
|
131
|
+
export declare function revalidateRemoteHead(task: TaskState, remoteHead: RemotePRHead): RevalidateResult;
|
|
132
|
+
export {};
|