@devcxl/opencode-cabbage 0.3.2 → 1.1.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/README.md +34 -19
- package/README.zh.md +34 -19
- package/assets/agents/dev-lifecycle.md +60 -49
- package/assets/agents/team/architect.md +8 -1
- package/assets/agents/team/developer.md +89 -0
- package/assets/agents/team/goal-verify.md +5 -1
- package/assets/agents/team/reviewer.md +6 -0
- package/assets/commands/code.md +3 -2
- package/assets/commands/design.md +3 -2
- package/assets/commands/release.md +3 -2
- package/assets/commands/requirements.md +3 -2
- package/assets/commands/review.md +3 -2
- package/assets/commands/setup.md +3 -2
- package/assets/commands/tasks.md +2 -1
- package/assets/prompts/bootstrap.md +9 -8
- package/assets/prompts/stage-contract.md +55 -0
- package/assets/skills/flow-code/SKILL.md +38 -140
- package/assets/skills/flow-design/SKILL.md +28 -79
- package/assets/skills/flow-release/SKILL.md +31 -51
- package/assets/skills/flow-requirements/SKILL.md +31 -196
- package/assets/skills/flow-review/SKILL.md +26 -123
- package/assets/skills/flow-setup/SKILL.md +40 -43
- package/assets/skills/flow-tasks/SKILL.md +23 -153
- package/assets/skills/flow-tdd/SKILL.md +30 -31
- package/dist/kernel/caller.d.ts +48 -0
- package/dist/kernel/caller.js +88 -0
- package/dist/kernel/caller.js.map +1 -0
- package/dist/kernel/context.d.ts +27 -0
- package/dist/kernel/context.js +84 -0
- package/dist/kernel/context.js.map +1 -0
- package/dist/kernel/flow.d.ts +175 -0
- package/dist/kernel/flow.js +467 -0
- package/dist/kernel/flow.js.map +1 -0
- package/dist/kernel/legacy.d.ts +19 -0
- package/dist/kernel/legacy.js +34 -0
- package/dist/kernel/legacy.js.map +1 -0
- package/dist/kernel/mutex.d.ts +8 -0
- package/dist/kernel/mutex.js +23 -0
- package/dist/kernel/mutex.js.map +1 -0
- package/dist/kernel/permission.d.ts +21 -0
- package/dist/kernel/permission.js +45 -0
- package/dist/kernel/permission.js.map +1 -0
- package/dist/kernel/profile.d.ts +35 -0
- package/dist/kernel/profile.js +147 -0
- package/dist/kernel/profile.js.map +1 -0
- package/dist/kernel/records.d.ts +103 -0
- package/dist/kernel/records.js +240 -0
- package/dist/kernel/records.js.map +1 -0
- package/dist/kernel/release.d.ts +106 -0
- package/dist/kernel/release.js +241 -0
- package/dist/kernel/release.js.map +1 -0
- package/dist/kernel/review.d.ts +34 -0
- package/dist/kernel/review.js +82 -0
- package/dist/kernel/review.js.map +1 -0
- package/dist/kernel/session-index.d.ts +45 -0
- package/dist/kernel/session-index.js +136 -0
- package/dist/kernel/session-index.js.map +1 -0
- package/dist/kernel/setup.d.ts +95 -0
- package/dist/kernel/setup.js +401 -0
- package/dist/kernel/setup.js.map +1 -0
- package/dist/kernel/slug.d.ts +23 -0
- package/dist/kernel/slug.js +67 -0
- package/dist/kernel/slug.js.map +1 -0
- package/dist/kernel/task.d.ts +213 -0
- package/dist/kernel/task.js +873 -0
- package/dist/kernel/task.js.map +1 -0
- package/dist/{flowrun → kernel/tdd}/adapter.d.ts +1 -1
- package/dist/{flowrun → kernel/tdd}/adapter.js +27 -26
- package/dist/kernel/tdd/adapter.js.map +1 -0
- package/dist/{flowrun → kernel/tdd}/digest.d.ts +2 -1
- package/dist/{flowrun → kernel/tdd}/digest.js +6 -4
- package/dist/kernel/tdd/digest.js.map +1 -0
- package/dist/{flowrun → kernel/tdd}/evaluator.d.ts +1 -1
- package/dist/{flowrun → kernel/tdd}/evaluator.js +1 -1
- package/dist/kernel/tdd/evaluator.js.map +1 -0
- package/dist/kernel/tdd/evidence.d.ts +42 -0
- package/dist/kernel/tdd/evidence.js +48 -0
- package/dist/kernel/tdd/evidence.js.map +1 -0
- package/dist/{flowrun → kernel/tdd}/state.d.ts +2 -2
- package/dist/{flowrun → kernel/tdd}/state.js +1 -1
- package/dist/kernel/tdd/state.js.map +1 -0
- package/dist/kernel/types.d.ts +180 -0
- package/dist/kernel/types.js +2 -0
- package/dist/kernel/types.js.map +1 -0
- package/dist/kernel/worktree.d.ts +45 -0
- package/dist/kernel/worktree.js +156 -0
- package/dist/kernel/worktree.js.map +1 -0
- package/dist/plugin/agents.d.ts +5 -17
- package/dist/plugin/agents.js +0 -23
- package/dist/plugin/agents.js.map +1 -1
- package/dist/plugin/flow-control.d.ts +91 -0
- package/dist/plugin/flow-control.js +287 -0
- package/dist/plugin/flow-control.js.map +1 -0
- package/dist/plugin/goal.d.ts +17 -46
- package/dist/plugin/goal.js +47 -117
- package/dist/plugin/goal.js.map +1 -1
- package/dist/plugin/prompt-lint.js +78 -6
- package/dist/plugin/prompt-lint.js.map +1 -1
- package/dist/plugin/release-control.d.ts +39 -0
- package/dist/plugin/release-control.js +343 -0
- package/dist/plugin/release-control.js.map +1 -0
- package/dist/plugin/server.d.ts +19 -0
- package/dist/plugin/server.js +198 -320
- package/dist/plugin/server.js.map +1 -1
- package/dist/plugin/setup-control.d.ts +59 -0
- package/dist/plugin/setup-control.js +111 -0
- package/dist/plugin/setup-control.js.map +1 -0
- package/dist/plugin/shell.d.ts +7 -34
- package/dist/plugin/shell.js +12 -137
- package/dist/plugin/shell.js.map +1 -1
- package/dist/plugin/skills.d.ts +1 -1
- package/dist/plugin/skills.js +1 -7
- package/dist/plugin/skills.js.map +1 -1
- package/dist/plugin/task-control.d.ts +90 -0
- package/dist/plugin/task-control.js +208 -0
- package/dist/plugin/task-control.js.map +1 -0
- package/dist/plugin/tdd-checkpoint.d.ts +128 -0
- package/dist/plugin/tdd-checkpoint.js +664 -0
- package/dist/plugin/tdd-checkpoint.js.map +1 -0
- package/dist/util/gh.d.ts +5 -0
- package/dist/util/gh.js +12 -0
- package/dist/util/gh.js.map +1 -1
- package/dist/util/paths.d.ts +6 -2
- package/dist/util/paths.js +15 -7
- package/dist/util/paths.js.map +1 -1
- package/package.json +4 -4
- package/assets/agents/team/backend.md +0 -100
- package/assets/agents/team/frontend.md +0 -98
- package/assets/commands/handoff.md +0 -4
- package/assets/commands/test.md +0 -4
- package/assets/context/CONTEXT.md +0 -41
- package/assets/skills/flow-handoff/SKILL.md +0 -76
- package/assets/skills/flow-test/SKILL.md +0 -75
- package/dist/flowrun/adapter.js.map +0 -1
- package/dist/flowrun/audit.d.ts +0 -5
- package/dist/flowrun/audit.js +0 -67
- package/dist/flowrun/audit.js.map +0 -1
- package/dist/flowrun/ci.d.ts +0 -64
- package/dist/flowrun/ci.js +0 -184
- package/dist/flowrun/ci.js.map +0 -1
- package/dist/flowrun/coverage.d.ts +0 -70
- package/dist/flowrun/coverage.js +0 -207
- package/dist/flowrun/coverage.js.map +0 -1
- package/dist/flowrun/digest.js.map +0 -1
- package/dist/flowrun/evaluator.js.map +0 -1
- package/dist/flowrun/gate.d.ts +0 -28
- package/dist/flowrun/gate.js +0 -139
- package/dist/flowrun/gate.js.map +0 -1
- package/dist/flowrun/github.d.ts +0 -24
- package/dist/flowrun/github.js +0 -154
- package/dist/flowrun/github.js.map +0 -1
- package/dist/flowrun/index.d.ts +0 -14
- package/dist/flowrun/index.js +0 -15
- package/dist/flowrun/index.js.map +0 -1
- package/dist/flowrun/merge.d.ts +0 -57
- package/dist/flowrun/merge.js +0 -180
- package/dist/flowrun/merge.js.map +0 -1
- package/dist/flowrun/migration.d.ts +0 -11
- package/dist/flowrun/migration.js +0 -276
- package/dist/flowrun/migration.js.map +0 -1
- package/dist/flowrun/resilience.d.ts +0 -18
- package/dist/flowrun/resilience.js +0 -80
- package/dist/flowrun/resilience.js.map +0 -1
- package/dist/flowrun/state.js.map +0 -1
- package/dist/flowrun/transitions.d.ts +0 -66
- package/dist/flowrun/transitions.js +0 -168
- package/dist/flowrun/transitions.js.map +0 -1
- package/dist/flowrun/types.d.ts +0 -356
- package/dist/flowrun/types.js +0 -21
- package/dist/flowrun/types.js.map +0 -1
- package/dist/flowrun/validator.d.ts +0 -19
- package/dist/flowrun/validator.js +0 -209
- package/dist/flowrun/validator.js.map +0 -1
- package/dist/plugin/broker.d.ts +0 -73
- package/dist/plugin/broker.js +0 -140
- package/dist/plugin/broker.js.map +0 -1
- package/dist/plugin/tdd-tool.d.ts +0 -62
- package/dist/plugin/tdd-tool.js +0 -336
- package/dist/plugin/tdd-tool.js.map +0 -1
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
import { FLOW_RUN_STAGES, FLOW_RUN_STATUSES, TASK_STATUSES, STAGE_STATUSES, CHECKPOINT_STATUSES, } from "./types.js";
|
|
2
|
-
export function validateFlowRun(raw) {
|
|
3
|
-
const errors = [];
|
|
4
|
-
if (!raw || typeof raw !== "object") {
|
|
5
|
-
errors.push({ path: "", message: "FlowRun must be a non-null object" });
|
|
6
|
-
return { data: null, errors };
|
|
7
|
-
}
|
|
8
|
-
const obj = raw;
|
|
9
|
-
if (typeof obj.flowRunId !== "string" || !obj.flowRunId) {
|
|
10
|
-
errors.push({ path: "flowRunId", message: "Required string" });
|
|
11
|
-
}
|
|
12
|
-
if (typeof obj.repo !== "string" || !obj.repo) {
|
|
13
|
-
errors.push({ path: "repo", message: "Required string" });
|
|
14
|
-
}
|
|
15
|
-
if (typeof obj.parentIssueNumber !== "number" || obj.parentIssueNumber <= 0) {
|
|
16
|
-
errors.push({ path: "parentIssueNumber", message: "Required positive number" });
|
|
17
|
-
}
|
|
18
|
-
if (!FLOW_RUN_STATUSES.includes(obj.status)) {
|
|
19
|
-
errors.push({ path: "status", message: `Must be one of: ${FLOW_RUN_STATUSES.join(", ")}` });
|
|
20
|
-
}
|
|
21
|
-
if (typeof obj.schemaVersion !== "number") {
|
|
22
|
-
errors.push({ path: "schemaVersion", message: "Required number" });
|
|
23
|
-
}
|
|
24
|
-
if (typeof obj.revision !== "number" || obj.revision < 0) {
|
|
25
|
-
errors.push({ path: "revision", message: "Required non-negative number" });
|
|
26
|
-
}
|
|
27
|
-
// v2: FlowRun 级 repositoryQualityPolicy
|
|
28
|
-
if (!obj.repositoryQualityPolicy || typeof obj.repositoryQualityPolicy !== "object") {
|
|
29
|
-
errors.push({ path: "repositoryQualityPolicy", message: "Required object" });
|
|
30
|
-
}
|
|
31
|
-
else {
|
|
32
|
-
const rqp = obj.repositoryQualityPolicy;
|
|
33
|
-
if (typeof rqp.mode !== "string" || !["off", "required"].includes(rqp.mode)) {
|
|
34
|
-
errors.push({ path: "repositoryQualityPolicy.mode", message: 'Must be "off" or "required"' });
|
|
35
|
-
}
|
|
36
|
-
if (!Array.isArray(rqp.requiredChecks)) {
|
|
37
|
-
errors.push({ path: "repositoryQualityPolicy.requiredChecks", message: "Required array" });
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
validateStages(obj.stages, errors);
|
|
41
|
-
validateTasks(obj.tasks, errors);
|
|
42
|
-
const data = errors.length === 0 ? raw : null;
|
|
43
|
-
return { data, errors };
|
|
44
|
-
}
|
|
45
|
-
function validateStages(stages, errors) {
|
|
46
|
-
if (!stages || typeof stages !== "object") {
|
|
47
|
-
errors.push({ path: "stages", message: "Required object with stage keys" });
|
|
48
|
-
return false;
|
|
49
|
-
}
|
|
50
|
-
const stageObj = stages;
|
|
51
|
-
for (const key of FLOW_RUN_STAGES) {
|
|
52
|
-
const s = stageObj[key];
|
|
53
|
-
if (!s || typeof s !== "object") {
|
|
54
|
-
errors.push({ path: `stages.${key}`, message: "Missing or invalid stage object" });
|
|
55
|
-
continue;
|
|
56
|
-
}
|
|
57
|
-
validateStage(key, s, errors);
|
|
58
|
-
}
|
|
59
|
-
return true;
|
|
60
|
-
}
|
|
61
|
-
function validateStage(stageKey, stage, errors) {
|
|
62
|
-
if (!STAGE_STATUSES.includes(stage.status)) {
|
|
63
|
-
errors.push({ path: `stages.${stageKey}.status`, message: "Invalid stage status" });
|
|
64
|
-
}
|
|
65
|
-
if (!Array.isArray(stage.requiredArtifacts)) {
|
|
66
|
-
errors.push({ path: `stages.${stageKey}.requiredArtifacts`, message: "Required array" });
|
|
67
|
-
}
|
|
68
|
-
if (typeof stage.completedAt !== "string" && stage.completedAt !== null) {
|
|
69
|
-
errors.push({ path: `stages.${stageKey}.completedAt`, message: "Must be string or null" });
|
|
70
|
-
}
|
|
71
|
-
if (!Array.isArray(stage.checks)) {
|
|
72
|
-
errors.push({ path: `stages.${stageKey}.checks`, message: "Required array" });
|
|
73
|
-
}
|
|
74
|
-
if (!Array.isArray(stage.evidence)) {
|
|
75
|
-
errors.push({ path: `stages.${stageKey}.evidence`, message: "Required array" });
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
function validateTasks(tasks, errors) {
|
|
79
|
-
if (!tasks || typeof tasks !== "object") {
|
|
80
|
-
errors.push({ path: "tasks", message: "Required object with task keys" });
|
|
81
|
-
return false;
|
|
82
|
-
}
|
|
83
|
-
const taskObj = tasks;
|
|
84
|
-
for (const [key, value] of Object.entries(taskObj)) {
|
|
85
|
-
if (!value || typeof value !== "object") {
|
|
86
|
-
errors.push({ path: `tasks.${key}`, message: "Invalid task object" });
|
|
87
|
-
continue;
|
|
88
|
-
}
|
|
89
|
-
validateTask(key, value, errors);
|
|
90
|
-
}
|
|
91
|
-
return true;
|
|
92
|
-
}
|
|
93
|
-
function validateTask(taskKey, task, errors) {
|
|
94
|
-
if (!task.id || typeof task.id !== "string") {
|
|
95
|
-
errors.push({ path: `tasks.${taskKey}.id`, message: "Required string" });
|
|
96
|
-
}
|
|
97
|
-
if (!TASK_STATUSES.includes(task.status)) {
|
|
98
|
-
errors.push({ path: `tasks.${taskKey}.status`, message: "Invalid task status" });
|
|
99
|
-
}
|
|
100
|
-
if (!Array.isArray(task.dependsOn)) {
|
|
101
|
-
errors.push({ path: `tasks.${taskKey}.dependsOn`, message: "Required array" });
|
|
102
|
-
}
|
|
103
|
-
if (!Array.isArray(task.expectedFiles)) {
|
|
104
|
-
errors.push({ path: `tasks.${taskKey}.expectedFiles`, message: "Required array" });
|
|
105
|
-
}
|
|
106
|
-
if (!Array.isArray(task.testCommands)) {
|
|
107
|
-
errors.push({ path: `tasks.${taskKey}.testCommands`, message: "Required array" });
|
|
108
|
-
}
|
|
109
|
-
// v2: acceptanceCriteria
|
|
110
|
-
if (!Array.isArray(task.acceptanceCriteria)) {
|
|
111
|
-
errors.push({ path: `tasks.${taskKey}.acceptanceCriteria`, message: "Required array" });
|
|
112
|
-
}
|
|
113
|
-
// v2: verifyCommands
|
|
114
|
-
if (!Array.isArray(task.verifyCommands)) {
|
|
115
|
-
errors.push({ path: `tasks.${taskKey}.verifyCommands`, message: "Required array" });
|
|
116
|
-
}
|
|
117
|
-
// v2: tddPolicy
|
|
118
|
-
if (!task.tddPolicy || typeof task.tddPolicy !== "object") {
|
|
119
|
-
errors.push({ path: `tasks.${taskKey}.tddPolicy`, message: "Required object" });
|
|
120
|
-
}
|
|
121
|
-
// v2: tddEvidence
|
|
122
|
-
if (!task.tddEvidence || typeof task.tddEvidence !== "object") {
|
|
123
|
-
errors.push({ path: `tasks.${taskKey}.tddEvidence`, message: "Required object" });
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* 验证 Task DAG:
|
|
128
|
-
* - Task ID 唯一
|
|
129
|
-
* - record key 与 Task.id 一致
|
|
130
|
-
* - 所有依赖存在
|
|
131
|
-
* - 禁止自依赖
|
|
132
|
-
* - 检测环路
|
|
133
|
-
*/
|
|
134
|
-
export function validateFlowRunDag(tasks) {
|
|
135
|
-
const errors = [];
|
|
136
|
-
// Task ID 唯一(Record key 天然唯一,检查 key 与 id 是否一致)
|
|
137
|
-
const seenIds = new Set();
|
|
138
|
-
for (const [key, task] of Object.entries(tasks)) {
|
|
139
|
-
if (key !== task.id) {
|
|
140
|
-
errors.push({ path: `tasks.${key}`, message: `Record key "${key}" does not match task.id "${task.id}"` });
|
|
141
|
-
}
|
|
142
|
-
if (seenIds.has(task.id)) {
|
|
143
|
-
errors.push({ path: `tasks.${key}`, message: `Duplicate task id "${task.id}"` });
|
|
144
|
-
}
|
|
145
|
-
seenIds.add(task.id);
|
|
146
|
-
}
|
|
147
|
-
// 禁止自依赖 + 依赖存在
|
|
148
|
-
for (const [key, task] of Object.entries(tasks)) {
|
|
149
|
-
for (const dep of task.dependsOn) {
|
|
150
|
-
if (dep === task.id) {
|
|
151
|
-
errors.push({ path: `tasks.${key}.dependsOn`, message: `Task "${task.id}" depends on itself` });
|
|
152
|
-
}
|
|
153
|
-
if (!seenIds.has(dep)) {
|
|
154
|
-
errors.push({ path: `tasks.${key}.dependsOn`, message: `Dependency "${dep}" not found in tasks` });
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
// 环路检测(拓扑排序)
|
|
159
|
-
if (errors.length === 0) {
|
|
160
|
-
const cycleError = detectCycle(tasks, seenIds);
|
|
161
|
-
if (cycleError) {
|
|
162
|
-
errors.push(cycleError);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
return errors;
|
|
166
|
-
}
|
|
167
|
-
/**
|
|
168
|
-
* 拓扑排序检测环路,返回发现环路时的错误
|
|
169
|
-
*/
|
|
170
|
-
function detectCycle(tasks, allIds) {
|
|
171
|
-
const inDegree = new Map();
|
|
172
|
-
const adjacency = new Map();
|
|
173
|
-
for (const id of allIds) {
|
|
174
|
-
inDegree.set(id, 0);
|
|
175
|
-
adjacency.set(id, []);
|
|
176
|
-
}
|
|
177
|
-
for (const task of Object.values(tasks)) {
|
|
178
|
-
for (const dep of task.dependsOn) {
|
|
179
|
-
adjacency.get(dep).push(task.id);
|
|
180
|
-
inDegree.set(task.id, (inDegree.get(task.id) ?? 0) + 1);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
const queue = [];
|
|
184
|
-
for (const [id, degree] of inDegree) {
|
|
185
|
-
if (degree === 0)
|
|
186
|
-
queue.push(id);
|
|
187
|
-
}
|
|
188
|
-
let visitedCount = 0;
|
|
189
|
-
while (queue.length > 0) {
|
|
190
|
-
const current = queue.shift();
|
|
191
|
-
visitedCount++;
|
|
192
|
-
for (const neighbor of adjacency.get(current) ?? []) {
|
|
193
|
-
const newDegree = (inDegree.get(neighbor) ?? 1) - 1;
|
|
194
|
-
inDegree.set(neighbor, newDegree);
|
|
195
|
-
if (newDegree === 0)
|
|
196
|
-
queue.push(neighbor);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
if (visitedCount !== allIds.size) {
|
|
200
|
-
// 找出环路中的节点
|
|
201
|
-
const cycleNodes = [...allIds].filter(id => (inDegree.get(id) ?? 0) > 0);
|
|
202
|
-
return {
|
|
203
|
-
path: "tasks",
|
|
204
|
-
message: `Circular dependency detected involving: ${cycleNodes.join(", ")}`,
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
return null;
|
|
208
|
-
}
|
|
209
|
-
//# sourceMappingURL=validator.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/flowrun/validator.ts"],"names":[],"mappings":"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"}
|
package/dist/plugin/broker.d.ts
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import type { FlowRun } from "../flowrun/types.js";
|
|
2
|
-
export interface BrokerCredentials {
|
|
3
|
-
/** 独立 GitHub API token(不传入 Agent shell) */
|
|
4
|
-
token: string;
|
|
5
|
-
}
|
|
6
|
-
export interface MutateResult<R> {
|
|
7
|
-
flowRun: FlowRun;
|
|
8
|
-
result: R;
|
|
9
|
-
shouldPersist: boolean;
|
|
10
|
-
}
|
|
11
|
-
export type WriteResult<R> = {
|
|
12
|
-
ok: true;
|
|
13
|
-
flowRun: FlowRun;
|
|
14
|
-
result: R;
|
|
15
|
-
persisted: boolean;
|
|
16
|
-
} | {
|
|
17
|
-
ok: false;
|
|
18
|
-
code: "PERSIST_CONFLICT" | "READ_FAILED";
|
|
19
|
-
message: string;
|
|
20
|
-
};
|
|
21
|
-
/**
|
|
22
|
-
* 单进程 broker,负责:
|
|
23
|
-
* 1. 按 parentIssueNumber 的 keyed mutex 串行所有 FlowRun 写入
|
|
24
|
-
* 2. read-modify-write 循环(乐观锁)
|
|
25
|
-
* 3. 检测外部 body 变化 → PERSIST_CONFLICT
|
|
26
|
-
* 4. 持有独立 GitHub API 凭证,Agent shell 不可访问
|
|
27
|
-
*
|
|
28
|
-
* 所有 FlowRun/Task/Evidence 写入必须经过 broker,不直接暴露 GitHub API。
|
|
29
|
-
*
|
|
30
|
-
* 凭证安全:credentials 存储在闭包变量中,不挂载在 this 上,
|
|
31
|
-
* JSON.stringify / Object.keys 无法访问。
|
|
32
|
-
*/
|
|
33
|
-
export declare class FlowBroker {
|
|
34
|
-
#private;
|
|
35
|
-
private mutex;
|
|
36
|
-
/**
|
|
37
|
-
* @param credentials 可选。独立 GitHub API 凭证。
|
|
38
|
-
* 传入时:所有 gh 操作使用该 token,而非 ambient 环境。
|
|
39
|
-
* 不传时:降级使用 ambient 环境变量(GH_TOKEN etc.)。
|
|
40
|
-
*/
|
|
41
|
-
constructor(credentials?: BrokerCredentials);
|
|
42
|
-
/**
|
|
43
|
-
* 获取凭证对应的环境变量覆盖(仅内部使用)。
|
|
44
|
-
* 返回 undefined 表示无独立凭证,应使用 ambient 环境。
|
|
45
|
-
*/
|
|
46
|
-
private get ghEnv();
|
|
47
|
-
/**
|
|
48
|
-
* 验证 broker 持有的 GitHub 凭证是否有效。
|
|
49
|
-
*
|
|
50
|
-
* 调用 `gh auth status` 检查 token 可用性。
|
|
51
|
-
* 无凭证时返回 ok: false。
|
|
52
|
-
*/
|
|
53
|
-
verifyCredentials(): Promise<{
|
|
54
|
-
ok: boolean;
|
|
55
|
-
message: string;
|
|
56
|
-
}>;
|
|
57
|
-
/**
|
|
58
|
-
* 将操作加入 keyed mutex 队列。
|
|
59
|
-
*
|
|
60
|
-
* 用于需要串行化但对 FlowRun 无影响的通用操作。
|
|
61
|
-
*/
|
|
62
|
-
enqueue<T>(parentIssueNumber: number, op: () => Promise<T>): Promise<T>;
|
|
63
|
-
/**
|
|
64
|
-
* read-modify-write 循环:读取 FlowRun → 应用 handler 变更 → 乐观锁写回。
|
|
65
|
-
*
|
|
66
|
-
* - handler 返回 { flowRun, result, shouldPersist }
|
|
67
|
-
* - shouldPersist=false 时跳过写入(如校验失败)
|
|
68
|
-
* - 自动增加 revision 和时间戳
|
|
69
|
-
* - body 不匹配时返回 PERSIST_CONFLICT
|
|
70
|
-
* - 使用 broker 独立凭证执行 gh 操作
|
|
71
|
-
*/
|
|
72
|
-
writeFlowRunWithLock<R>(issueNumber: number, handler: (flowRun: FlowRun) => MutateResult<R>): Promise<WriteResult<R>>;
|
|
73
|
-
}
|
package/dist/plugin/broker.js
DELETED
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
import { readFlowRunWithLock, writeFlowRunWithLock as ghWriteFlowRunWithLock } from "../flowrun/github.js";
|
|
2
|
-
// ─── Keyed Mutex ───
|
|
3
|
-
/**
|
|
4
|
-
* 按 key 隔离的互斥锁,用于单进程内串行化并发操作。
|
|
5
|
-
*
|
|
6
|
-
* 每个 key(parentIssueNumber)维护独立的 promise 链,
|
|
7
|
-
* 相同 key 的操作依次执行,不同 key 的操作可以并行。
|
|
8
|
-
*/
|
|
9
|
-
class KeyedMutex {
|
|
10
|
-
locks = new Map();
|
|
11
|
-
async runExclusive(key, fn) {
|
|
12
|
-
const prev = this.locks.get(key) ?? Promise.resolve();
|
|
13
|
-
let release;
|
|
14
|
-
const next = new Promise(r => {
|
|
15
|
-
release = r;
|
|
16
|
-
});
|
|
17
|
-
this.locks.set(key, next);
|
|
18
|
-
await prev;
|
|
19
|
-
try {
|
|
20
|
-
return await fn();
|
|
21
|
-
}
|
|
22
|
-
finally {
|
|
23
|
-
release();
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
// ─── FlowBroker ───
|
|
28
|
-
/**
|
|
29
|
-
* 单进程 broker,负责:
|
|
30
|
-
* 1. 按 parentIssueNumber 的 keyed mutex 串行所有 FlowRun 写入
|
|
31
|
-
* 2. read-modify-write 循环(乐观锁)
|
|
32
|
-
* 3. 检测外部 body 变化 → PERSIST_CONFLICT
|
|
33
|
-
* 4. 持有独立 GitHub API 凭证,Agent shell 不可访问
|
|
34
|
-
*
|
|
35
|
-
* 所有 FlowRun/Task/Evidence 写入必须经过 broker,不直接暴露 GitHub API。
|
|
36
|
-
*
|
|
37
|
-
* 凭证安全:credentials 存储在闭包变量中,不挂载在 this 上,
|
|
38
|
-
* JSON.stringify / Object.keys 无法访问。
|
|
39
|
-
*/
|
|
40
|
-
export class FlowBroker {
|
|
41
|
-
mutex = new KeyedMutex();
|
|
42
|
-
#credentials;
|
|
43
|
-
/**
|
|
44
|
-
* @param credentials 可选。独立 GitHub API 凭证。
|
|
45
|
-
* 传入时:所有 gh 操作使用该 token,而非 ambient 环境。
|
|
46
|
-
* 不传时:降级使用 ambient 环境变量(GH_TOKEN etc.)。
|
|
47
|
-
*/
|
|
48
|
-
constructor(credentials) {
|
|
49
|
-
this.#credentials = credentials ?? null;
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* 获取凭证对应的环境变量覆盖(仅内部使用)。
|
|
53
|
-
* 返回 undefined 表示无独立凭证,应使用 ambient 环境。
|
|
54
|
-
*/
|
|
55
|
-
get ghEnv() {
|
|
56
|
-
if (!this.#credentials)
|
|
57
|
-
return undefined;
|
|
58
|
-
return {
|
|
59
|
-
GH_TOKEN: this.#credentials.token,
|
|
60
|
-
GITHUB_TOKEN: this.#credentials.token,
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* 验证 broker 持有的 GitHub 凭证是否有效。
|
|
65
|
-
*
|
|
66
|
-
* 调用 `gh auth status` 检查 token 可用性。
|
|
67
|
-
* 无凭证时返回 ok: false。
|
|
68
|
-
*/
|
|
69
|
-
async verifyCredentials() {
|
|
70
|
-
if (!this.#credentials) {
|
|
71
|
-
return { ok: false, message: "No broker credentials configured" };
|
|
72
|
-
}
|
|
73
|
-
try {
|
|
74
|
-
const { gh } = await import("../util/gh.js");
|
|
75
|
-
await gh("auth status", 15_000, this.ghEnv);
|
|
76
|
-
return { ok: true, message: "Broker credentials are valid" };
|
|
77
|
-
}
|
|
78
|
-
catch (err) {
|
|
79
|
-
return { ok: false, message: `Broker credentials verification failed: ${String(err)}` };
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* 将操作加入 keyed mutex 队列。
|
|
84
|
-
*
|
|
85
|
-
* 用于需要串行化但对 FlowRun 无影响的通用操作。
|
|
86
|
-
*/
|
|
87
|
-
async enqueue(parentIssueNumber, op) {
|
|
88
|
-
return this.mutex.runExclusive(parentIssueNumber, op);
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* read-modify-write 循环:读取 FlowRun → 应用 handler 变更 → 乐观锁写回。
|
|
92
|
-
*
|
|
93
|
-
* - handler 返回 { flowRun, result, shouldPersist }
|
|
94
|
-
* - shouldPersist=false 时跳过写入(如校验失败)
|
|
95
|
-
* - 自动增加 revision 和时间戳
|
|
96
|
-
* - body 不匹配时返回 PERSIST_CONFLICT
|
|
97
|
-
* - 使用 broker 独立凭证执行 gh 操作
|
|
98
|
-
*/
|
|
99
|
-
async writeFlowRunWithLock(issueNumber, handler) {
|
|
100
|
-
return this.mutex.runExclusive(issueNumber, async () => {
|
|
101
|
-
// ── 读取(broker 凭证) ──
|
|
102
|
-
const { flowRunResult, currentBody } = await readFlowRunWithLock(issueNumber, this.ghEnv);
|
|
103
|
-
if (!flowRunResult.ok || currentBody === null) {
|
|
104
|
-
return {
|
|
105
|
-
ok: false,
|
|
106
|
-
code: "READ_FAILED",
|
|
107
|
-
message: `Failed to read FlowRun from issue #${issueNumber}: ${flowRunResult.ok ? "missing body" : flowRunResult.code}`,
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
// ── 修改 ──
|
|
111
|
-
const { flowRun: updated, result, shouldPersist } = handler(flowRunResult.data);
|
|
112
|
-
if (!shouldPersist) {
|
|
113
|
-
return {
|
|
114
|
-
ok: true,
|
|
115
|
-
flowRun: flowRunResult.data,
|
|
116
|
-
result,
|
|
117
|
-
persisted: false,
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
// ── 写入(乐观锁,broker 凭证) ──
|
|
121
|
-
updated.revision += 1;
|
|
122
|
-
updated.lastTickAt = new Date().toISOString();
|
|
123
|
-
const writeResult = await ghWriteFlowRunWithLock(issueNumber, updated, currentBody, this.ghEnv);
|
|
124
|
-
if (!writeResult.success) {
|
|
125
|
-
return {
|
|
126
|
-
ok: false,
|
|
127
|
-
code: "PERSIST_CONFLICT",
|
|
128
|
-
message: writeResult.error ?? "Issue body changed since last read — external modification detected",
|
|
129
|
-
};
|
|
130
|
-
}
|
|
131
|
-
return {
|
|
132
|
-
ok: true,
|
|
133
|
-
flowRun: updated,
|
|
134
|
-
result,
|
|
135
|
-
persisted: true,
|
|
136
|
-
};
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
//# sourceMappingURL=broker.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"broker.js","sourceRoot":"","sources":["../../src/plugin/broker.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import type { TaskState, TddEvidence, TddCycleEvidence, TddCommandEvidence } from "../flowrun/types.js";
|
|
2
|
-
import { createTaskEvidence as createBaseEvidence } from "../flowrun/state.js";
|
|
3
|
-
import type { FlowBroker } from "./broker.js";
|
|
4
|
-
export type TddCheckpointOp = "cycle-start" | "red" | "green" | "final-regression" | "final-verification" | "status" | "alternative-command" | "abandon-cycle";
|
|
5
|
-
export interface TddCheckpointRequest {
|
|
6
|
-
op: TddCheckpointOp;
|
|
7
|
-
parentIssueNumber: number;
|
|
8
|
-
taskId: string;
|
|
9
|
-
cycleId?: string;
|
|
10
|
-
criterionId?: string;
|
|
11
|
-
testPaths?: string[];
|
|
12
|
-
testSelector?: string;
|
|
13
|
-
redEvidence?: TddCommandEvidence;
|
|
14
|
-
greenEvidence?: TddCommandEvidence;
|
|
15
|
-
reason?: string;
|
|
16
|
-
validationId?: string;
|
|
17
|
-
regressionRuns?: TddCommandEvidence[];
|
|
18
|
-
verificationRuns?: TddCommandEvidence[];
|
|
19
|
-
}
|
|
20
|
-
export interface TddCheckpointResponse {
|
|
21
|
-
ok: boolean;
|
|
22
|
-
evidence?: TddEvidence;
|
|
23
|
-
cycle?: TddCycleEvidence;
|
|
24
|
-
evidenceRevision?: number;
|
|
25
|
-
error?: {
|
|
26
|
-
code: string;
|
|
27
|
-
message: string;
|
|
28
|
-
};
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Broker-aware 响应:包含冲突暂停标志。
|
|
32
|
-
* PERSIST_CONFLICT 时 conflictPause=true,调用方应暂停 FlowRun。
|
|
33
|
-
*/
|
|
34
|
-
export interface TddCheckpointBrokerResponse extends TddCheckpointResponse {
|
|
35
|
-
conflictPause: boolean;
|
|
36
|
-
persisted: boolean;
|
|
37
|
-
}
|
|
38
|
-
export { createBaseEvidence as createTaskEvidence };
|
|
39
|
-
/**
|
|
40
|
-
* 处理 tdd_checkpoint 工具请求。
|
|
41
|
-
*
|
|
42
|
-
* 职责:
|
|
43
|
-
* - 验证 Task 状态(running + executionBinding)
|
|
44
|
-
* - 根据 op 分发到 state.ts 各纯函数
|
|
45
|
-
* - 返回结构化 response(evidence revision + cycle/evidence)
|
|
46
|
-
*
|
|
47
|
-
* 注意:C2 只实现内存状态机。持久化由 C3 broker 负责。
|
|
48
|
-
*/
|
|
49
|
-
export declare function handleTddCheckpoint(req: TddCheckpointRequest, task: TaskState): TddCheckpointResponse;
|
|
50
|
-
/**
|
|
51
|
-
* 通过 FlowBroker 执行 tdd_checkpoint 操作。
|
|
52
|
-
*
|
|
53
|
-
* 流程:
|
|
54
|
-
* 1. 通过 broker.writeFlowRunWithLock 读取 FlowRun
|
|
55
|
-
* 2. 提取目标 TaskState
|
|
56
|
-
* 3. 调用 handleTddCheckpoint 执行状态机转换
|
|
57
|
-
* 4. 成功时持久化回 Issue(broker 自动处理 revision + 乐观锁)
|
|
58
|
-
* 5. PERSIST_CONFLICT 时设置 conflictPause=true
|
|
59
|
-
*
|
|
60
|
-
* @returns TddCheckpointBrokerResponse — 包含 conflictPause 标志
|
|
61
|
-
*/
|
|
62
|
-
export declare function handleTddCheckpointWithBroker(broker: FlowBroker, req: TddCheckpointRequest): Promise<TddCheckpointBrokerResponse>;
|