@snipcodeit/mgw 0.4.0 → 0.6.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 +1 -0
- package/commands/run/execute.md +456 -24
- package/commands/run/pr-create.md +46 -0
- package/commands/run/triage.md +199 -2
- package/commands/workflows/gsd.md +71 -0
- package/commands/workflows/state.md +340 -1
- package/dist/bin/mgw.cjs +2 -2
- package/dist/{index-B-_JvYpz.cjs → index-CHrVAIMY.cjs} +197 -1
- package/dist/lib/index.cjs +524 -2
- package/package.json +9 -4
|
@@ -141,6 +141,10 @@ function requireState () {
|
|
|
141
141
|
issueState.dead_letter = false;
|
|
142
142
|
issueChanged = true;
|
|
143
143
|
}
|
|
144
|
+
if (!issueState.hasOwnProperty("checkpoint")) {
|
|
145
|
+
issueState.checkpoint = null;
|
|
146
|
+
issueChanged = true;
|
|
147
|
+
}
|
|
144
148
|
if (issueChanged) {
|
|
145
149
|
try {
|
|
146
150
|
fs.writeFileSync(filePath, JSON.stringify(issueState, null, 2), "utf-8");
|
|
@@ -165,6 +169,148 @@ function requireState () {
|
|
|
165
169
|
}
|
|
166
170
|
return -1;
|
|
167
171
|
}
|
|
172
|
+
const CHECKPOINT_SCHEMA_VERSION = 1;
|
|
173
|
+
const CHECKPOINT_STEP_ORDER = ["triage", "plan", "execute", "verify", "pr"];
|
|
174
|
+
function initCheckpoint(pipelineStep) {
|
|
175
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
176
|
+
return {
|
|
177
|
+
schema_version: CHECKPOINT_SCHEMA_VERSION,
|
|
178
|
+
pipeline_step: pipelineStep || "triage",
|
|
179
|
+
step_progress: {},
|
|
180
|
+
last_agent_output: null,
|
|
181
|
+
artifacts: [],
|
|
182
|
+
resume: {
|
|
183
|
+
action: null,
|
|
184
|
+
context: {}
|
|
185
|
+
},
|
|
186
|
+
started_at: now,
|
|
187
|
+
updated_at: now,
|
|
188
|
+
step_history: []
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
function detectCheckpoint(issueNumber) {
|
|
192
|
+
const issueState = loadActiveIssue(issueNumber);
|
|
193
|
+
if (!issueState) return null;
|
|
194
|
+
const cp = issueState.checkpoint;
|
|
195
|
+
if (!cp || typeof cp !== "object") return null;
|
|
196
|
+
const step = cp.pipeline_step || "triage";
|
|
197
|
+
const stepIndex = CHECKPOINT_STEP_ORDER.indexOf(step);
|
|
198
|
+
if (stepIndex <= 0) return null;
|
|
199
|
+
return {
|
|
200
|
+
pipeline_step: cp.pipeline_step,
|
|
201
|
+
step_progress: cp.step_progress || {},
|
|
202
|
+
artifacts: cp.artifacts || [],
|
|
203
|
+
resume: cp.resume || { action: null, context: {} },
|
|
204
|
+
started_at: cp.started_at || null,
|
|
205
|
+
updated_at: cp.updated_at || null,
|
|
206
|
+
step_history: cp.step_history || []
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
function resumeFromCheckpoint(issueNumber) {
|
|
210
|
+
const cp = detectCheckpoint(issueNumber);
|
|
211
|
+
if (!cp) return null;
|
|
212
|
+
const action = cp.resume && cp.resume.action || null;
|
|
213
|
+
const actionToStage = {
|
|
214
|
+
"run-plan-checker": "planning",
|
|
215
|
+
"spawn-executor": "executing",
|
|
216
|
+
"continue-execution": "executing",
|
|
217
|
+
"spawn-verifier": "verifying",
|
|
218
|
+
"create-pr": "pr-pending",
|
|
219
|
+
"begin-execution": "planning"
|
|
220
|
+
};
|
|
221
|
+
const resumeStage = actionToStage[action] || "planning";
|
|
222
|
+
const completedSteps = (cp.step_history || []).map((entry) => entry.step).filter(Boolean);
|
|
223
|
+
return {
|
|
224
|
+
checkpoint: cp,
|
|
225
|
+
resumeStage,
|
|
226
|
+
resumeAction: action || "unknown",
|
|
227
|
+
completedSteps
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
function atomicWriteJson(filePath, data) {
|
|
231
|
+
const tmpPath = filePath + ".tmp";
|
|
232
|
+
const content = JSON.stringify(data, null, 2);
|
|
233
|
+
fs.writeFileSync(tmpPath, content, "utf-8");
|
|
234
|
+
fs.renameSync(tmpPath, filePath);
|
|
235
|
+
}
|
|
236
|
+
function clearCheckpoint(issueNumber) {
|
|
237
|
+
const activeDir = getActiveDir();
|
|
238
|
+
if (!fs.existsSync(activeDir)) {
|
|
239
|
+
throw new Error(`No active directory found. Cannot clear checkpoint for #${issueNumber}.`);
|
|
240
|
+
}
|
|
241
|
+
const prefix = String(issueNumber) + "-";
|
|
242
|
+
let entries;
|
|
243
|
+
try {
|
|
244
|
+
entries = fs.readdirSync(activeDir);
|
|
245
|
+
} catch (err) {
|
|
246
|
+
throw new Error(`Cannot read active directory: ${err.message}`, { cause: err });
|
|
247
|
+
}
|
|
248
|
+
const match = entries.find((f) => f.startsWith(prefix) && f.endsWith(".json"));
|
|
249
|
+
if (!match) {
|
|
250
|
+
throw new Error(`No state file found for issue #${issueNumber}.`);
|
|
251
|
+
}
|
|
252
|
+
const filePath = path.join(activeDir, match);
|
|
253
|
+
let issueState;
|
|
254
|
+
try {
|
|
255
|
+
issueState = JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
256
|
+
} catch (err) {
|
|
257
|
+
throw new Error(`Cannot parse state file for #${issueNumber}: ${err.message}`, { cause: err });
|
|
258
|
+
}
|
|
259
|
+
const hadCheckpoint = issueState.checkpoint != null;
|
|
260
|
+
issueState.checkpoint = null;
|
|
261
|
+
atomicWriteJson(filePath, issueState);
|
|
262
|
+
return { cleared: hadCheckpoint };
|
|
263
|
+
}
|
|
264
|
+
function updateCheckpoint(issueNumber, data) {
|
|
265
|
+
const activeDir = getActiveDir();
|
|
266
|
+
if (!fs.existsSync(activeDir)) {
|
|
267
|
+
throw new Error(`No active directory found. Cannot update checkpoint for #${issueNumber}.`);
|
|
268
|
+
}
|
|
269
|
+
const prefix = String(issueNumber) + "-";
|
|
270
|
+
let entries;
|
|
271
|
+
try {
|
|
272
|
+
entries = fs.readdirSync(activeDir);
|
|
273
|
+
} catch (err) {
|
|
274
|
+
throw new Error(`Cannot read active directory: ${err.message}`, { cause: err });
|
|
275
|
+
}
|
|
276
|
+
const match = entries.find((f) => f.startsWith(prefix) && f.endsWith(".json"));
|
|
277
|
+
if (!match) {
|
|
278
|
+
throw new Error(`No state file found for issue #${issueNumber}.`);
|
|
279
|
+
}
|
|
280
|
+
const filePath = path.join(activeDir, match);
|
|
281
|
+
let issueState;
|
|
282
|
+
try {
|
|
283
|
+
issueState = JSON.parse(fs.readFileSync(filePath, "utf-8"));
|
|
284
|
+
} catch (err) {
|
|
285
|
+
throw new Error(`Cannot parse state file for #${issueNumber}: ${err.message}`, { cause: err });
|
|
286
|
+
}
|
|
287
|
+
if (!issueState.checkpoint || typeof issueState.checkpoint !== "object") {
|
|
288
|
+
issueState.checkpoint = initCheckpoint();
|
|
289
|
+
}
|
|
290
|
+
const cp = issueState.checkpoint;
|
|
291
|
+
if (data.pipeline_step !== void 0) {
|
|
292
|
+
cp.pipeline_step = data.pipeline_step;
|
|
293
|
+
}
|
|
294
|
+
if (data.last_agent_output !== void 0) {
|
|
295
|
+
cp.last_agent_output = data.last_agent_output;
|
|
296
|
+
}
|
|
297
|
+
if (data.step_progress && typeof data.step_progress === "object") {
|
|
298
|
+
cp.step_progress = Object.assign({}, cp.step_progress, data.step_progress);
|
|
299
|
+
}
|
|
300
|
+
if (data.resume && typeof data.resume === "object") {
|
|
301
|
+
cp.resume = data.resume;
|
|
302
|
+
}
|
|
303
|
+
if (Array.isArray(data.artifacts) && data.artifacts.length > 0) {
|
|
304
|
+
cp.artifacts = (cp.artifacts || []).concat(data.artifacts);
|
|
305
|
+
}
|
|
306
|
+
if (Array.isArray(data.step_history) && data.step_history.length > 0) {
|
|
307
|
+
cp.step_history = (cp.step_history || []).concat(data.step_history);
|
|
308
|
+
}
|
|
309
|
+
cp.updated_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
310
|
+
issueState.checkpoint = cp;
|
|
311
|
+
atomicWriteJson(filePath, issueState);
|
|
312
|
+
return { updated: true, checkpoint: cp };
|
|
313
|
+
}
|
|
168
314
|
const VALID_LINK_TYPES = /* @__PURE__ */ new Set(["related", "implements", "tracks", "maps-to", "blocked-by"]);
|
|
169
315
|
function loadCrossRefs() {
|
|
170
316
|
const filePath = path.join(getMgwDir(), "cross-refs.json");
|
|
@@ -318,6 +464,47 @@ function requireState () {
|
|
|
318
464
|
}
|
|
319
465
|
return sorted;
|
|
320
466
|
}
|
|
467
|
+
function detectProjectState(options = {}) {
|
|
468
|
+
const repoRoot = options.repoRoot || process.cwd();
|
|
469
|
+
const G = typeof options.githubMilestoneCount === "number" ? options.githubMilestoneCount : 0;
|
|
470
|
+
const P = fs.existsSync(path.join(repoRoot, ".planning", "PROJECT.md"));
|
|
471
|
+
const R = fs.existsSync(path.join(repoRoot, ".planning", "ROADMAP.md"));
|
|
472
|
+
const S = fs.existsSync(path.join(repoRoot, ".planning", "STATE.md"));
|
|
473
|
+
const M = fs.existsSync(path.join(repoRoot, ".mgw", "project.json"));
|
|
474
|
+
const signals = { P, R, S, M, G };
|
|
475
|
+
if (M && G > 0) {
|
|
476
|
+
let projectData;
|
|
477
|
+
try {
|
|
478
|
+
const raw = fs.readFileSync(path.join(repoRoot, ".mgw", "project.json"), "utf-8");
|
|
479
|
+
projectData = JSON.parse(raw);
|
|
480
|
+
} catch (_e) {
|
|
481
|
+
return { stateClass: "Diverged", signals };
|
|
482
|
+
}
|
|
483
|
+
const milestones = Array.isArray(projectData.milestones) ? projectData.milestones : [];
|
|
484
|
+
const currentMilestone = typeof projectData.current_milestone === "number" ? projectData.current_milestone : 1;
|
|
485
|
+
const allComplete = milestones.length > 0 && currentMilestone > milestones.length;
|
|
486
|
+
if (allComplete) {
|
|
487
|
+
return { stateClass: "Extend", signals };
|
|
488
|
+
}
|
|
489
|
+
const localCount = milestones.length;
|
|
490
|
+
const countDiff = Math.abs(localCount - G);
|
|
491
|
+
if (countDiff <= 1) {
|
|
492
|
+
return { stateClass: "Aligned", signals };
|
|
493
|
+
} else {
|
|
494
|
+
return { stateClass: "Diverged", signals };
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
if (!M && G === 0) {
|
|
498
|
+
if (P && (R || S)) {
|
|
499
|
+
return { stateClass: "GSD-Mid-Exec", signals };
|
|
500
|
+
}
|
|
501
|
+
if (P) {
|
|
502
|
+
return { stateClass: "GSD-Only", signals };
|
|
503
|
+
}
|
|
504
|
+
return { stateClass: "Fresh", signals };
|
|
505
|
+
}
|
|
506
|
+
return { stateClass: "Fresh", signals };
|
|
507
|
+
}
|
|
321
508
|
state = {
|
|
322
509
|
getMgwDir,
|
|
323
510
|
getActiveDir,
|
|
@@ -328,11 +515,20 @@ function requireState () {
|
|
|
328
515
|
mergeProjectState,
|
|
329
516
|
migrateProjectState,
|
|
330
517
|
resolveActiveMilestoneIndex,
|
|
518
|
+
CHECKPOINT_SCHEMA_VERSION,
|
|
519
|
+
CHECKPOINT_STEP_ORDER,
|
|
520
|
+
initCheckpoint,
|
|
521
|
+
atomicWriteJson,
|
|
522
|
+
detectCheckpoint,
|
|
523
|
+
resumeFromCheckpoint,
|
|
524
|
+
clearCheckpoint,
|
|
525
|
+
updateCheckpoint,
|
|
331
526
|
loadCrossRefs,
|
|
332
527
|
VALID_LINK_TYPES,
|
|
333
528
|
parseDependencies,
|
|
334
529
|
storeDependencies,
|
|
335
|
-
topologicalSort
|
|
530
|
+
topologicalSort,
|
|
531
|
+
detectProjectState
|
|
336
532
|
};
|
|
337
533
|
return state;
|
|
338
534
|
}
|