@fredericboyer/dev-team 0.6.0 → 0.8.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 +12 -11
- package/dist/bin/dev-team.js +12 -12
- package/dist/bin/dev-team.js.map +1 -1
- package/dist/create-agent.js +6 -6
- package/dist/create-agent.js.map +1 -1
- package/dist/doctor.js +15 -16
- package/dist/doctor.js.map +1 -1
- package/dist/files.js +2 -0
- package/dist/files.js.map +1 -1
- package/dist/init.js +55 -44
- package/dist/init.js.map +1 -1
- package/dist/scan.js +9 -9
- package/dist/scan.js.map +1 -1
- package/dist/skill-recommendations.d.ts +57 -0
- package/dist/skill-recommendations.js +290 -0
- package/dist/skill-recommendations.js.map +1 -0
- package/dist/status.js +11 -11
- package/dist/status.js.map +1 -1
- package/dist/update.d.ts +1 -4
- package/dist/update.js +178 -59
- package/dist/update.js.map +1 -1
- package/package.json +3 -3
- package/templates/CLAUDE.md +9 -7
- package/templates/agents/dev-team-beck.md +14 -2
- package/templates/agents/dev-team-borges.md +4 -4
- package/templates/agents/dev-team-conway.md +15 -3
- package/templates/agents/dev-team-deming.md +20 -2
- package/templates/agents/dev-team-drucker.md +21 -7
- package/templates/agents/dev-team-hamilton.md +14 -2
- package/templates/agents/dev-team-mori.md +14 -2
- package/templates/agents/dev-team-tufte.md +14 -2
- package/templates/agents/dev-team-voss.md +14 -2
- package/templates/hooks/dev-team-post-change-review.js +1 -25
- package/templates/hooks/dev-team-pre-commit-gate.js +80 -47
- package/templates/hooks/dev-team-watch-list.js +3 -3
- package/templates/settings.json +6 -20
- package/templates/skill-recommendations.json +169 -0
- package/templates/skills/dev-team-assess/SKILL.md +167 -0
- package/templates/skills/dev-team-audit/SKILL.md +8 -3
- package/templates/skills/dev-team-merge/SKILL.md +95 -0
- package/templates/skills/dev-team-review/SKILL.md +11 -4
- package/templates/skills/dev-team-task/SKILL.md +34 -44
- package/dist/parallel.d.ts +0 -127
- package/dist/parallel.js +0 -323
- package/dist/parallel.js.map +0 -1
- package/templates/hooks/dev-team-parallel-loop.js +0 -188
- package/templates/hooks/dev-team-task-loop.js +0 -73
package/dist/parallel.d.ts
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* parallel.ts — Parallel state management for multi-issue orchestration (ADR-019).
|
|
3
|
-
*
|
|
4
|
-
* Manages the `.claude/dev-team-parallel.json` state file that tracks
|
|
5
|
-
* parallel implementation phases, sync barriers, and review waves.
|
|
6
|
-
*
|
|
7
|
-
* Zero runtime dependencies (project constraint from ADR-002).
|
|
8
|
-
*/
|
|
9
|
-
export type IssueStatus = "pending" | "implementing" | "implemented" | "reviewing" | "defects-found" | "fixing" | "approved";
|
|
10
|
-
export type Phase = "pre-assessment" | "implementation" | "sync-barrier" | "review-wave" | "defect-routing" | "borges-completion" | "done";
|
|
11
|
-
export interface IssueEntry {
|
|
12
|
-
issue: number;
|
|
13
|
-
branch: string;
|
|
14
|
-
agent: string;
|
|
15
|
-
status: IssueStatus;
|
|
16
|
-
defects?: string[];
|
|
17
|
-
reviewIteration?: number;
|
|
18
|
-
}
|
|
19
|
-
export interface ReviewWave {
|
|
20
|
-
wave: number;
|
|
21
|
-
startedAt: string;
|
|
22
|
-
completedAt?: string;
|
|
23
|
-
branches: string[];
|
|
24
|
-
findings: Record<string, BranchFindings>;
|
|
25
|
-
}
|
|
26
|
-
export interface BranchFindings {
|
|
27
|
-
defects: string[];
|
|
28
|
-
risks: string[];
|
|
29
|
-
suggestions: string[];
|
|
30
|
-
questions: string[];
|
|
31
|
-
}
|
|
32
|
-
export interface ParallelState {
|
|
33
|
-
mode: "parallel";
|
|
34
|
-
issues: IssueEntry[];
|
|
35
|
-
phase: Phase;
|
|
36
|
-
conflictGroups: number[][];
|
|
37
|
-
reviewWave: ReviewWave | null;
|
|
38
|
-
maxIterations: number;
|
|
39
|
-
createdAt: string;
|
|
40
|
-
updatedAt: string;
|
|
41
|
-
phaseLog: PhaseTransition[];
|
|
42
|
-
}
|
|
43
|
-
export interface PhaseTransition {
|
|
44
|
-
from: Phase;
|
|
45
|
-
to: Phase;
|
|
46
|
-
timestamp: string;
|
|
47
|
-
reason: string;
|
|
48
|
-
}
|
|
49
|
-
export declare const STATE_FILENAME = "dev-team-parallel.json";
|
|
50
|
-
export declare const DEFAULT_MAX_ITERATIONS = 10;
|
|
51
|
-
export declare function statePath(projectRoot: string): string;
|
|
52
|
-
export declare function readState(projectRoot: string): ParallelState | null;
|
|
53
|
-
export declare function writeState(projectRoot: string, state: ParallelState): void;
|
|
54
|
-
export declare function stateExists(projectRoot: string): boolean;
|
|
55
|
-
export declare function deleteState(projectRoot: string): boolean;
|
|
56
|
-
export interface CreateOptions {
|
|
57
|
-
issues: Array<{
|
|
58
|
-
issue: number;
|
|
59
|
-
branch: string;
|
|
60
|
-
agent: string;
|
|
61
|
-
}>;
|
|
62
|
-
conflictGroups?: number[][];
|
|
63
|
-
maxIterations?: number;
|
|
64
|
-
}
|
|
65
|
-
export declare function createState(projectRoot: string, options: CreateOptions): ParallelState;
|
|
66
|
-
export declare function transitionPhase(state: ParallelState, to: Phase, reason: string): ParallelState;
|
|
67
|
-
export declare function isValidTransition(from: Phase, to: Phase): boolean;
|
|
68
|
-
export declare function allowedTransitions(from: Phase): Phase[];
|
|
69
|
-
export declare function updateIssueStatus(state: ParallelState, issueNumber: number, status: IssueStatus): ParallelState;
|
|
70
|
-
/**
|
|
71
|
-
* Checks whether ALL implementation agents have completed.
|
|
72
|
-
* Returns true when every issue has status "implemented" or later.
|
|
73
|
-
*/
|
|
74
|
-
export declare function checkSyncBarrier(state: ParallelState): {
|
|
75
|
-
ready: boolean;
|
|
76
|
-
pending: number[];
|
|
77
|
-
completed: number[];
|
|
78
|
-
};
|
|
79
|
-
export declare function startReviewWave(state: ParallelState): ParallelState;
|
|
80
|
-
export declare function recordFindings(state: ParallelState, branch: string, findings: BranchFindings): ParallelState;
|
|
81
|
-
/**
|
|
82
|
-
* Checks if ALL branches in the current review wave have reported findings.
|
|
83
|
-
*/
|
|
84
|
-
export declare function isReviewWaveComplete(state: ParallelState): boolean;
|
|
85
|
-
export interface DefectRoute {
|
|
86
|
-
issue: number;
|
|
87
|
-
branch: string;
|
|
88
|
-
agent: string;
|
|
89
|
-
defects: string[];
|
|
90
|
-
iteration: number;
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Returns defect routes: which issues need fixes routed back to their implementing agent.
|
|
94
|
-
* Respects per-branch iteration limits.
|
|
95
|
-
*/
|
|
96
|
-
export declare function getDefectRoutes(state: ParallelState): {
|
|
97
|
-
routes: DefectRoute[];
|
|
98
|
-
exhausted: DefectRoute[];
|
|
99
|
-
};
|
|
100
|
-
export interface ConvergenceResult {
|
|
101
|
-
converged: boolean;
|
|
102
|
-
allApproved: boolean;
|
|
103
|
-
exhaustedBranches: number[];
|
|
104
|
-
pendingDefects: number[];
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Checks if the parallel execution has converged (all approved or exhausted).
|
|
108
|
-
*/
|
|
109
|
-
export declare function checkConvergence(state: ParallelState): ConvergenceResult;
|
|
110
|
-
/**
|
|
111
|
-
* Returns issues that can execute in parallel (not in any conflict group with
|
|
112
|
-
* currently-running issues).
|
|
113
|
-
*/
|
|
114
|
-
export declare function getIndependentIssues(state: ParallelState): number[];
|
|
115
|
-
/**
|
|
116
|
-
* Returns the conflict group that contains a given issue, or null.
|
|
117
|
-
*/
|
|
118
|
-
export declare function getConflictGroup(state: ParallelState, issueNumber: number): number[] | null;
|
|
119
|
-
export interface ParallelSummary {
|
|
120
|
-
phase: Phase;
|
|
121
|
-
totalIssues: number;
|
|
122
|
-
byStatus: Record<IssueStatus, number>;
|
|
123
|
-
currentWave: number | null;
|
|
124
|
-
phaseTransitions: number;
|
|
125
|
-
conflictGroupCount: number;
|
|
126
|
-
}
|
|
127
|
-
export declare function summarize(state: ParallelState): ParallelSummary;
|
package/dist/parallel.js
DELETED
|
@@ -1,323 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* parallel.ts — Parallel state management for multi-issue orchestration (ADR-019).
|
|
4
|
-
*
|
|
5
|
-
* Manages the `.claude/dev-team-parallel.json` state file that tracks
|
|
6
|
-
* parallel implementation phases, sync barriers, and review waves.
|
|
7
|
-
*
|
|
8
|
-
* Zero runtime dependencies (project constraint from ADR-002).
|
|
9
|
-
*/
|
|
10
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
11
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
12
|
-
};
|
|
13
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
-
exports.DEFAULT_MAX_ITERATIONS = exports.STATE_FILENAME = void 0;
|
|
15
|
-
exports.statePath = statePath;
|
|
16
|
-
exports.readState = readState;
|
|
17
|
-
exports.writeState = writeState;
|
|
18
|
-
exports.stateExists = stateExists;
|
|
19
|
-
exports.deleteState = deleteState;
|
|
20
|
-
exports.createState = createState;
|
|
21
|
-
exports.transitionPhase = transitionPhase;
|
|
22
|
-
exports.isValidTransition = isValidTransition;
|
|
23
|
-
exports.allowedTransitions = allowedTransitions;
|
|
24
|
-
exports.updateIssueStatus = updateIssueStatus;
|
|
25
|
-
exports.checkSyncBarrier = checkSyncBarrier;
|
|
26
|
-
exports.startReviewWave = startReviewWave;
|
|
27
|
-
exports.recordFindings = recordFindings;
|
|
28
|
-
exports.isReviewWaveComplete = isReviewWaveComplete;
|
|
29
|
-
exports.getDefectRoutes = getDefectRoutes;
|
|
30
|
-
exports.checkConvergence = checkConvergence;
|
|
31
|
-
exports.getIndependentIssues = getIndependentIssues;
|
|
32
|
-
exports.getConflictGroup = getConflictGroup;
|
|
33
|
-
exports.summarize = summarize;
|
|
34
|
-
const fs_1 = __importDefault(require("fs"));
|
|
35
|
-
const path_1 = __importDefault(require("path"));
|
|
36
|
-
const files_1 = require("./files");
|
|
37
|
-
// ─── Constants ───────────────────────────────────────────────────────────────
|
|
38
|
-
exports.STATE_FILENAME = "dev-team-parallel.json";
|
|
39
|
-
exports.DEFAULT_MAX_ITERATIONS = 10;
|
|
40
|
-
// ─── State file path ─────────────────────────────────────────────────────────
|
|
41
|
-
function statePath(projectRoot) {
|
|
42
|
-
return path_1.default.join(projectRoot, ".claude", exports.STATE_FILENAME);
|
|
43
|
-
}
|
|
44
|
-
// ─── Read / Write ────────────────────────────────────────────────────────────
|
|
45
|
-
function readState(projectRoot) {
|
|
46
|
-
const fp = statePath(projectRoot);
|
|
47
|
-
const content = (0, files_1.readFile)(fp);
|
|
48
|
-
if (content === null)
|
|
49
|
-
return null;
|
|
50
|
-
try {
|
|
51
|
-
return JSON.parse(content);
|
|
52
|
-
}
|
|
53
|
-
catch {
|
|
54
|
-
return null;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
function writeState(projectRoot, state) {
|
|
58
|
-
state.updatedAt = new Date().toISOString();
|
|
59
|
-
const fp = statePath(projectRoot);
|
|
60
|
-
(0, files_1.writeFile)(fp, JSON.stringify(state, null, 2) + "\n");
|
|
61
|
-
}
|
|
62
|
-
function stateExists(projectRoot) {
|
|
63
|
-
return (0, files_1.fileExists)(statePath(projectRoot));
|
|
64
|
-
}
|
|
65
|
-
function deleteState(projectRoot) {
|
|
66
|
-
const fp = statePath(projectRoot);
|
|
67
|
-
if (!(0, files_1.fileExists)(fp))
|
|
68
|
-
return false;
|
|
69
|
-
fs_1.default.unlinkSync(fp);
|
|
70
|
-
return true;
|
|
71
|
-
}
|
|
72
|
-
function createState(projectRoot, options) {
|
|
73
|
-
if (options.issues.length === 0) {
|
|
74
|
-
throw new Error("Cannot create parallel state with zero issues");
|
|
75
|
-
}
|
|
76
|
-
// Validate no duplicate issue numbers
|
|
77
|
-
const issueNumbers = options.issues.map((i) => i.issue);
|
|
78
|
-
const unique = new Set(issueNumbers);
|
|
79
|
-
if (unique.size !== issueNumbers.length) {
|
|
80
|
-
throw new Error("Duplicate issue numbers in parallel state");
|
|
81
|
-
}
|
|
82
|
-
// Validate conflict groups reference existing issues
|
|
83
|
-
for (const group of options.conflictGroups || []) {
|
|
84
|
-
for (const issueNum of group) {
|
|
85
|
-
if (!unique.has(issueNum)) {
|
|
86
|
-
throw new Error(`Conflict group references unknown issue #${issueNum}`);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
const now = new Date().toISOString();
|
|
91
|
-
const state = {
|
|
92
|
-
mode: "parallel",
|
|
93
|
-
issues: options.issues.map((i) => ({
|
|
94
|
-
issue: i.issue,
|
|
95
|
-
branch: i.branch,
|
|
96
|
-
agent: i.agent,
|
|
97
|
-
status: "pending",
|
|
98
|
-
reviewIteration: 0,
|
|
99
|
-
})),
|
|
100
|
-
phase: "pre-assessment",
|
|
101
|
-
conflictGroups: options.conflictGroups || [],
|
|
102
|
-
reviewWave: null,
|
|
103
|
-
maxIterations: options.maxIterations ?? exports.DEFAULT_MAX_ITERATIONS,
|
|
104
|
-
createdAt: now,
|
|
105
|
-
updatedAt: now,
|
|
106
|
-
phaseLog: [],
|
|
107
|
-
};
|
|
108
|
-
writeState(projectRoot, state);
|
|
109
|
-
return state;
|
|
110
|
-
}
|
|
111
|
-
// ─── Phase transitions ──────────────────────────────────────────────────────
|
|
112
|
-
function transitionPhase(state, to, reason) {
|
|
113
|
-
const from = state.phase;
|
|
114
|
-
// Validate transition is legal
|
|
115
|
-
if (!isValidTransition(from, to)) {
|
|
116
|
-
throw new Error(`Invalid phase transition: ${from} -> ${to}. Allowed from ${from}: ${allowedTransitions(from).join(", ")}`);
|
|
117
|
-
}
|
|
118
|
-
state.phaseLog.push({
|
|
119
|
-
from,
|
|
120
|
-
to,
|
|
121
|
-
timestamp: new Date().toISOString(),
|
|
122
|
-
reason,
|
|
123
|
-
});
|
|
124
|
-
state.phase = to;
|
|
125
|
-
return state;
|
|
126
|
-
}
|
|
127
|
-
const TRANSITION_MAP = {
|
|
128
|
-
"pre-assessment": ["implementation"],
|
|
129
|
-
implementation: ["sync-barrier"],
|
|
130
|
-
"sync-barrier": ["review-wave"],
|
|
131
|
-
"review-wave": ["defect-routing", "borges-completion"],
|
|
132
|
-
"defect-routing": ["review-wave", "borges-completion"],
|
|
133
|
-
"borges-completion": ["done"],
|
|
134
|
-
done: [],
|
|
135
|
-
};
|
|
136
|
-
function isValidTransition(from, to) {
|
|
137
|
-
return TRANSITION_MAP[from]?.includes(to) ?? false;
|
|
138
|
-
}
|
|
139
|
-
function allowedTransitions(from) {
|
|
140
|
-
return TRANSITION_MAP[from] || [];
|
|
141
|
-
}
|
|
142
|
-
// ─── Issue status updates ────────────────────────────────────────────────────
|
|
143
|
-
function updateIssueStatus(state, issueNumber, status) {
|
|
144
|
-
const entry = state.issues.find((i) => i.issue === issueNumber);
|
|
145
|
-
if (!entry) {
|
|
146
|
-
throw new Error(`Issue #${issueNumber} not found in parallel state`);
|
|
147
|
-
}
|
|
148
|
-
entry.status = status;
|
|
149
|
-
return state;
|
|
150
|
-
}
|
|
151
|
-
// ─── Sync barrier ────────────────────────────────────────────────────────────
|
|
152
|
-
/**
|
|
153
|
-
* Checks whether ALL implementation agents have completed.
|
|
154
|
-
* Returns true when every issue has status "implemented" or later.
|
|
155
|
-
*/
|
|
156
|
-
function checkSyncBarrier(state) {
|
|
157
|
-
const completedStatuses = [
|
|
158
|
-
"implemented",
|
|
159
|
-
"reviewing",
|
|
160
|
-
"defects-found",
|
|
161
|
-
"fixing",
|
|
162
|
-
"approved",
|
|
163
|
-
];
|
|
164
|
-
const completed = [];
|
|
165
|
-
const pending = [];
|
|
166
|
-
for (const issue of state.issues) {
|
|
167
|
-
if (completedStatuses.includes(issue.status)) {
|
|
168
|
-
completed.push(issue.issue);
|
|
169
|
-
}
|
|
170
|
-
else {
|
|
171
|
-
pending.push(issue.issue);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
return {
|
|
175
|
-
ready: pending.length === 0,
|
|
176
|
-
pending,
|
|
177
|
-
completed,
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
|
-
// ─── Review wave management ──────────────────────────────────────────────────
|
|
181
|
-
function startReviewWave(state) {
|
|
182
|
-
const barrier = checkSyncBarrier(state);
|
|
183
|
-
if (!barrier.ready) {
|
|
184
|
-
throw new Error(`Cannot start review wave: issues still pending: ${barrier.pending.join(", ")}`);
|
|
185
|
-
}
|
|
186
|
-
const waveNumber = state.reviewWave ? state.reviewWave.wave + 1 : 1;
|
|
187
|
-
const branches = state.issues.map((i) => i.branch);
|
|
188
|
-
state.reviewWave = {
|
|
189
|
-
wave: waveNumber,
|
|
190
|
-
startedAt: new Date().toISOString(),
|
|
191
|
-
branches,
|
|
192
|
-
findings: {},
|
|
193
|
-
};
|
|
194
|
-
// Update all issue statuses to reviewing
|
|
195
|
-
for (const issue of state.issues) {
|
|
196
|
-
if (issue.status !== "approved") {
|
|
197
|
-
issue.status = "reviewing";
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
return state;
|
|
201
|
-
}
|
|
202
|
-
function recordFindings(state, branch, findings) {
|
|
203
|
-
if (!state.reviewWave) {
|
|
204
|
-
throw new Error("No active review wave to record findings for");
|
|
205
|
-
}
|
|
206
|
-
const issue = state.issues.find((i) => i.branch === branch);
|
|
207
|
-
if (!issue) {
|
|
208
|
-
throw new Error(`Branch "${branch}" not found in parallel state`);
|
|
209
|
-
}
|
|
210
|
-
state.reviewWave.findings[branch] = findings;
|
|
211
|
-
// Update issue status based on findings
|
|
212
|
-
if (findings.defects.length > 0) {
|
|
213
|
-
issue.status = "defects-found";
|
|
214
|
-
issue.defects = findings.defects;
|
|
215
|
-
issue.reviewIteration = (issue.reviewIteration || 0) + 1;
|
|
216
|
-
}
|
|
217
|
-
else {
|
|
218
|
-
issue.status = "approved";
|
|
219
|
-
issue.defects = [];
|
|
220
|
-
}
|
|
221
|
-
return state;
|
|
222
|
-
}
|
|
223
|
-
/**
|
|
224
|
-
* Checks if ALL branches in the current review wave have reported findings.
|
|
225
|
-
*/
|
|
226
|
-
function isReviewWaveComplete(state) {
|
|
227
|
-
if (!state.reviewWave)
|
|
228
|
-
return false;
|
|
229
|
-
const reported = new Set(Object.keys(state.reviewWave.findings));
|
|
230
|
-
return state.reviewWave.branches.every((b) => reported.has(b));
|
|
231
|
-
}
|
|
232
|
-
/**
|
|
233
|
-
* Returns defect routes: which issues need fixes routed back to their implementing agent.
|
|
234
|
-
* Respects per-branch iteration limits.
|
|
235
|
-
*/
|
|
236
|
-
function getDefectRoutes(state) {
|
|
237
|
-
const routes = [];
|
|
238
|
-
const exhausted = [];
|
|
239
|
-
for (const issue of state.issues) {
|
|
240
|
-
if (issue.status !== "defects-found")
|
|
241
|
-
continue;
|
|
242
|
-
const route = {
|
|
243
|
-
issue: issue.issue,
|
|
244
|
-
branch: issue.branch,
|
|
245
|
-
agent: issue.agent,
|
|
246
|
-
defects: issue.defects || [],
|
|
247
|
-
iteration: issue.reviewIteration || 1,
|
|
248
|
-
};
|
|
249
|
-
if ((issue.reviewIteration || 0) >= state.maxIterations) {
|
|
250
|
-
exhausted.push(route);
|
|
251
|
-
}
|
|
252
|
-
else {
|
|
253
|
-
routes.push(route);
|
|
254
|
-
issue.status = "fixing";
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
return { routes, exhausted };
|
|
258
|
-
}
|
|
259
|
-
/**
|
|
260
|
-
* Checks if the parallel execution has converged (all approved or exhausted).
|
|
261
|
-
*/
|
|
262
|
-
function checkConvergence(state) {
|
|
263
|
-
const approved = [];
|
|
264
|
-
const exhausted = [];
|
|
265
|
-
const pendingDefects = [];
|
|
266
|
-
for (const issue of state.issues) {
|
|
267
|
-
if (issue.status === "approved") {
|
|
268
|
-
approved.push(issue.issue);
|
|
269
|
-
}
|
|
270
|
-
else if ((issue.reviewIteration || 0) >= state.maxIterations) {
|
|
271
|
-
exhausted.push(issue.issue);
|
|
272
|
-
}
|
|
273
|
-
else {
|
|
274
|
-
pendingDefects.push(issue.issue);
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
return {
|
|
278
|
-
converged: approved.length + exhausted.length === state.issues.length,
|
|
279
|
-
allApproved: approved.length === state.issues.length,
|
|
280
|
-
exhaustedBranches: exhausted,
|
|
281
|
-
pendingDefects,
|
|
282
|
-
};
|
|
283
|
-
}
|
|
284
|
-
// ─── Conflict group helpers ──────────────────────────────────────────────────
|
|
285
|
-
/**
|
|
286
|
-
* Returns issues that can execute in parallel (not in any conflict group with
|
|
287
|
-
* currently-running issues).
|
|
288
|
-
*/
|
|
289
|
-
function getIndependentIssues(state) {
|
|
290
|
-
const inConflict = new Set();
|
|
291
|
-
for (const group of state.conflictGroups) {
|
|
292
|
-
for (const num of group) {
|
|
293
|
-
inConflict.add(num);
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
return state.issues.filter((i) => !inConflict.has(i.issue)).map((i) => i.issue);
|
|
297
|
-
}
|
|
298
|
-
/**
|
|
299
|
-
* Returns the conflict group that contains a given issue, or null.
|
|
300
|
-
*/
|
|
301
|
-
function getConflictGroup(state, issueNumber) {
|
|
302
|
-
for (const group of state.conflictGroups) {
|
|
303
|
-
if (group.includes(issueNumber)) {
|
|
304
|
-
return group;
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
return null;
|
|
308
|
-
}
|
|
309
|
-
function summarize(state) {
|
|
310
|
-
const byStatus = {};
|
|
311
|
-
for (const issue of state.issues) {
|
|
312
|
-
byStatus[issue.status] = (byStatus[issue.status] || 0) + 1;
|
|
313
|
-
}
|
|
314
|
-
return {
|
|
315
|
-
phase: state.phase,
|
|
316
|
-
totalIssues: state.issues.length,
|
|
317
|
-
byStatus: byStatus,
|
|
318
|
-
currentWave: state.reviewWave?.wave ?? null,
|
|
319
|
-
phaseTransitions: state.phaseLog.length,
|
|
320
|
-
conflictGroupCount: state.conflictGroups.length,
|
|
321
|
-
};
|
|
322
|
-
}
|
|
323
|
-
//# sourceMappingURL=parallel.js.map
|
package/dist/parallel.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"parallel.js","sourceRoot":"","sources":["../src/parallel.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* dev-team-parallel-loop.js
|
|
5
|
-
* Stop hook — enforces the parallel review wave protocol (ADR-019).
|
|
6
|
-
*
|
|
7
|
-
* When a parallel state file (.claude/dev-team-parallel.json) exists:
|
|
8
|
-
* - Reads current phase and issue statuses
|
|
9
|
-
* - Enforces sync barrier: blocks review until all implementations complete
|
|
10
|
-
* - Enforces phase transitions: prevents skipping phases
|
|
11
|
-
* - Validates phase transitions and enforces sync barriers
|
|
12
|
-
*
|
|
13
|
-
* State file: .claude/dev-team-parallel.json (created by Drucker orchestrator)
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
"use strict";
|
|
17
|
-
|
|
18
|
-
const fs = require("fs");
|
|
19
|
-
const path = require("path");
|
|
20
|
-
|
|
21
|
-
const STATE_FILE = path.join(process.cwd(), ".claude", "dev-team-parallel.json");
|
|
22
|
-
|
|
23
|
-
// No state file means no active parallel loop — allow normal exit
|
|
24
|
-
if (!fs.existsSync(STATE_FILE)) {
|
|
25
|
-
process.exit(0);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
let state;
|
|
29
|
-
try {
|
|
30
|
-
state = JSON.parse(fs.readFileSync(STATE_FILE, "utf-8"));
|
|
31
|
-
} catch {
|
|
32
|
-
// Corrupted state file — warn and allow exit
|
|
33
|
-
console.error("[dev-team parallel-loop] Warning: corrupted dev-team-parallel.json. Removing.");
|
|
34
|
-
try {
|
|
35
|
-
fs.unlinkSync(STATE_FILE);
|
|
36
|
-
} catch {
|
|
37
|
-
/* ignore */
|
|
38
|
-
}
|
|
39
|
-
process.exit(0);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Validate required fields
|
|
43
|
-
if (!state.mode || state.mode !== "parallel" || !Array.isArray(state.issues) || !state.phase) {
|
|
44
|
-
console.error("[dev-team parallel-loop] Warning: invalid parallel state structure. Removing.");
|
|
45
|
-
try {
|
|
46
|
-
fs.unlinkSync(STATE_FILE);
|
|
47
|
-
} catch {
|
|
48
|
-
/* ignore */
|
|
49
|
-
}
|
|
50
|
-
process.exit(0);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const phase = state.phase;
|
|
54
|
-
const issues = state.issues;
|
|
55
|
-
|
|
56
|
-
// Validate per-issue required fields and status values
|
|
57
|
-
const VALID_STATUSES = [
|
|
58
|
-
"pending",
|
|
59
|
-
"implementing",
|
|
60
|
-
"implemented",
|
|
61
|
-
"reviewing",
|
|
62
|
-
"defects-found",
|
|
63
|
-
"fixing",
|
|
64
|
-
"approved",
|
|
65
|
-
];
|
|
66
|
-
for (let idx = 0; idx < issues.length; idx++) {
|
|
67
|
-
const entry = issues[idx];
|
|
68
|
-
if (!entry || typeof entry.issue !== "number" || typeof entry.status !== "string") {
|
|
69
|
-
const output = JSON.stringify({
|
|
70
|
-
decision: "block",
|
|
71
|
-
reason: `[dev-team parallel-loop] Issue at index ${idx} is missing required fields (issue, status). Cannot proceed with invalid parallel state.`,
|
|
72
|
-
});
|
|
73
|
-
console.log(output);
|
|
74
|
-
process.exit(0);
|
|
75
|
-
}
|
|
76
|
-
if (!VALID_STATUSES.includes(entry.status)) {
|
|
77
|
-
const output = JSON.stringify({
|
|
78
|
-
decision: "block",
|
|
79
|
-
reason: `[dev-team parallel-loop] Issue #${entry.issue} has unrecognized status "${entry.status}". Cannot proceed with invalid parallel state.`,
|
|
80
|
-
});
|
|
81
|
-
console.log(output);
|
|
82
|
-
process.exit(0);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Phase: done — clean up and exit
|
|
87
|
-
if (phase === "done") {
|
|
88
|
-
try {
|
|
89
|
-
fs.unlinkSync(STATE_FILE);
|
|
90
|
-
} catch {
|
|
91
|
-
/* ignore */
|
|
92
|
-
}
|
|
93
|
-
console.log("[dev-team parallel-loop] Parallel execution complete. State file cleaned up.");
|
|
94
|
-
process.exit(0);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// Phase: implementation — check sync barrier
|
|
98
|
-
if (phase === "implementation") {
|
|
99
|
-
const implementing = issues.filter((i) => i.status === "implementing" || i.status === "pending");
|
|
100
|
-
const implemented = issues.filter(
|
|
101
|
-
(i) => i.status === "implemented" || i.status === "reviewing" || i.status === "approved",
|
|
102
|
-
);
|
|
103
|
-
|
|
104
|
-
if (implementing.length > 0) {
|
|
105
|
-
const output = JSON.stringify({
|
|
106
|
-
decision: "block",
|
|
107
|
-
reason: `[dev-team parallel-loop] SYNC BARRIER: ${implementing.length} issue(s) still implementing (${implementing.map((i) => "#" + i.issue).join(", ")}). ${implemented.length}/${issues.length} complete. Wait for all implementations to finish before starting reviews.`,
|
|
108
|
-
});
|
|
109
|
-
console.log(output);
|
|
110
|
-
process.exit(0);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// All implementations done — allow transition to sync-barrier
|
|
114
|
-
console.log(
|
|
115
|
-
`[dev-team parallel-loop] All ${issues.length} implementations complete. Ready for review wave.`,
|
|
116
|
-
);
|
|
117
|
-
process.exit(0);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// Phase: sync-barrier — remind to start review wave
|
|
121
|
-
if (phase === "sync-barrier") {
|
|
122
|
-
const output = JSON.stringify({
|
|
123
|
-
decision: "block",
|
|
124
|
-
reason:
|
|
125
|
-
"[dev-team parallel-loop] All implementations complete. Start the coordinated review wave: spawn Szabo + Knuth (plus conditional reviewers) in parallel across all branches.",
|
|
126
|
-
});
|
|
127
|
-
console.log(output);
|
|
128
|
-
process.exit(0);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Phase: review-wave — check if all reviews reported
|
|
132
|
-
if (phase === "review-wave") {
|
|
133
|
-
const wave = state.reviewWave;
|
|
134
|
-
if (!wave || !Array.isArray(wave.branches) || wave.branches.length === 0) {
|
|
135
|
-
const output = JSON.stringify({
|
|
136
|
-
decision: "block",
|
|
137
|
-
reason:
|
|
138
|
-
"[dev-team parallel-loop] Invalid review-wave state: reviewWave is missing or has no branches. Cannot proceed without a valid review wave.",
|
|
139
|
-
});
|
|
140
|
-
console.log(output);
|
|
141
|
-
process.exit(0);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const reported = Object.keys(wave.findings || {});
|
|
145
|
-
const pending = wave.branches.filter((b) => !reported.includes(b));
|
|
146
|
-
|
|
147
|
-
if (pending.length > 0) {
|
|
148
|
-
const output = JSON.stringify({
|
|
149
|
-
decision: "block",
|
|
150
|
-
reason: `[dev-team parallel-loop] Review wave ${wave.wave}: ${pending.length} branch(es) awaiting review results (${pending.join(", ")}). Collect all findings before routing defects.`,
|
|
151
|
-
});
|
|
152
|
-
console.log(output);
|
|
153
|
-
process.exit(0);
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// All reviews complete
|
|
157
|
-
console.log("[dev-team parallel-loop] Review wave complete. Route defects or proceed to Borges.");
|
|
158
|
-
process.exit(0);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
// Phase: defect-routing — check if fixes are done
|
|
162
|
-
if (phase === "defect-routing") {
|
|
163
|
-
const fixing = issues.filter((i) => i.status === "fixing");
|
|
164
|
-
if (fixing.length > 0) {
|
|
165
|
-
const output = JSON.stringify({
|
|
166
|
-
decision: "block",
|
|
167
|
-
reason: `[dev-team parallel-loop] ${fixing.length} issue(s) being fixed (${fixing.map((i) => "#" + i.issue).join(", ")}). Wait for fixes, then start another review wave.`,
|
|
168
|
-
});
|
|
169
|
-
console.log(output);
|
|
170
|
-
process.exit(0);
|
|
171
|
-
}
|
|
172
|
-
process.exit(0);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// Phase: borges-completion — remind to run Borges
|
|
176
|
-
if (phase === "borges-completion") {
|
|
177
|
-
const output = JSON.stringify({
|
|
178
|
-
decision: "block",
|
|
179
|
-
reason:
|
|
180
|
-
"[dev-team parallel-loop] Run Borges across all branches for cross-branch coherence review. After Borges completes, transition to 'done'.",
|
|
181
|
-
});
|
|
182
|
-
console.log(output);
|
|
183
|
-
process.exit(0);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// Unknown phase — allow exit with warning
|
|
187
|
-
console.error(`[dev-team parallel-loop] Warning: unknown phase "${phase}". Allowing exit.`);
|
|
188
|
-
process.exit(0);
|