@wichayutdew/pi-workflows 0.2.2 → 0.2.3
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/LICENSE +21 -201
- package/README.md +191 -104
- package/agents/step.md +15 -1
- package/dist/index.js +1803 -463
- package/examples/mr-comments.workflow.yaml +4 -4
- package/examples/prompts/mr-comments/implement.md +10 -5
- package/examples/prompts/mr-comments/plan.md +10 -5
- package/examples/prompts/mr-comments/verify.md +5 -4
- package/examples/settings.yaml +3 -1
- package/package.json +10 -6
- package/schemas/settings.schema.json +8 -0
- package/schemas/workflow.schema.json +10 -2
- package/src/command-names.ts +0 -1
- package/src/commands.ts +0 -6
- package/src/config/ceiling.ts +8 -0
- package/src/config/load.ts +3 -9
- package/src/config/types.ts +15 -3
- package/src/config/validate.ts +147 -22
- package/src/engine/state.ts +7 -0
- package/src/engine/transitions.ts +52 -7
- package/src/harness.ts +701 -74
- package/src/index.ts +6 -2
- package/src/integrations/prompt-gate.ts +14 -13
- package/src/integrations/subagents/child-runtime.ts +187 -69
- package/src/integrations/subagents/client.ts +4 -3
- package/src/integrations/subagents/diagnostics.ts +799 -0
- package/src/integrations/subagents/protocol.ts +86 -15
- package/src/policy/approved-commands.ts +212 -5
- package/src/policy/bash.ts +0 -9
- package/src/prompt.ts +106 -7
- package/src/runtime/serial-task-queue.ts +5 -1
- package/src/workflow-status.ts +244 -35
|
@@ -51,11 +51,25 @@ export function pauseRun(
|
|
|
51
51
|
status: 'paused',
|
|
52
52
|
pausedFrom: run.status,
|
|
53
53
|
pauseReason: reason || `Paused during step "${run.currentStepId}"`,
|
|
54
|
+
failedStepId: undefined,
|
|
54
55
|
},
|
|
55
56
|
now,
|
|
56
57
|
);
|
|
57
58
|
}
|
|
58
59
|
|
|
60
|
+
export function failRun(
|
|
61
|
+
run: WorkflowRun,
|
|
62
|
+
reason: string,
|
|
63
|
+
now: number,
|
|
64
|
+
): WorkflowRun {
|
|
65
|
+
const paused = pauseRun(run, reason, now);
|
|
66
|
+
if (paused.status !== 'paused') return paused;
|
|
67
|
+
return {
|
|
68
|
+
...paused,
|
|
69
|
+
failedStepId: paused.currentStepId,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
59
73
|
export function resumeRun(run: WorkflowRun, now: number): WorkflowRun {
|
|
60
74
|
if (run.status !== 'paused') return run;
|
|
61
75
|
return withUpdate(
|
|
@@ -64,6 +78,7 @@ export function resumeRun(run: WorkflowRun, now: number): WorkflowRun {
|
|
|
64
78
|
status: run.pausedFrom ?? (run.pendingGate ? 'awaiting-gate' : 'running'),
|
|
65
79
|
pauseReason: undefined,
|
|
66
80
|
pausedFrom: undefined,
|
|
81
|
+
failedStepId: undefined,
|
|
67
82
|
},
|
|
68
83
|
now,
|
|
69
84
|
);
|
|
@@ -80,6 +95,7 @@ export function abortRun(
|
|
|
80
95
|
status: 'aborted',
|
|
81
96
|
pauseReason: reason || 'Aborted by user',
|
|
82
97
|
pausedFrom: undefined,
|
|
98
|
+
failedStepId: undefined,
|
|
83
99
|
pendingGate: undefined,
|
|
84
100
|
},
|
|
85
101
|
now,
|
|
@@ -166,6 +182,7 @@ export function advanceRun(
|
|
|
166
182
|
stepHandoff: summary,
|
|
167
183
|
lastSummary: summary,
|
|
168
184
|
gateFeedback: '',
|
|
185
|
+
...(nextStep.gate ? { reviewedArtifact: '' } : {}),
|
|
169
186
|
...(overVisitLimit
|
|
170
187
|
? {
|
|
171
188
|
pausedFrom: 'running' as const,
|
|
@@ -334,6 +351,31 @@ function retainedReviewedArtifact(
|
|
|
334
351
|
return sourceRetained ? reviewedArtifact : '';
|
|
335
352
|
}
|
|
336
353
|
|
|
354
|
+
function refreshApprovedGateHistory(
|
|
355
|
+
run: WorkflowRun,
|
|
356
|
+
workflow: LoadedWorkflow,
|
|
357
|
+
): WorkflowRun {
|
|
358
|
+
const reviewedArtifact = run.reviewedArtifact ?? '';
|
|
359
|
+
if (!reviewedArtifact) return run;
|
|
360
|
+
let changed = false;
|
|
361
|
+
const history = run.history.map((entry) => {
|
|
362
|
+
const gate = workflow.definition.steps[entry.stepId]?.gate;
|
|
363
|
+
const currentDigest = workflow.stepDigests[entry.stepId];
|
|
364
|
+
if (
|
|
365
|
+
gate &&
|
|
366
|
+
currentDigest &&
|
|
367
|
+
entry.outcome === gate.approvedOutcome &&
|
|
368
|
+
entry.summary === reviewedArtifact &&
|
|
369
|
+
entry.stepDigest !== currentDigest
|
|
370
|
+
) {
|
|
371
|
+
changed = true;
|
|
372
|
+
return { ...entry, stepDigest: currentDigest };
|
|
373
|
+
}
|
|
374
|
+
return entry;
|
|
375
|
+
});
|
|
376
|
+
return changed ? { ...run, history } : run;
|
|
377
|
+
}
|
|
378
|
+
|
|
337
379
|
export function reconcileRun(
|
|
338
380
|
run: WorkflowRun,
|
|
339
381
|
workflow: LoadedWorkflow,
|
|
@@ -354,12 +396,13 @@ export function reconcileRun(
|
|
|
354
396
|
error: `current step "${run.currentStepId}" was removed; abort or restore the configuration`,
|
|
355
397
|
};
|
|
356
398
|
}
|
|
399
|
+
const reconciledRun = refreshApprovedGateHistory(run, workflow);
|
|
357
400
|
|
|
358
|
-
const changedHistoryIndex =
|
|
401
|
+
const changedHistoryIndex = reconciledRun.history.findIndex(
|
|
359
402
|
(entry) => workflow.stepDigests[entry.stepId] !== entry.stepDigest,
|
|
360
403
|
);
|
|
361
404
|
if (changedHistoryIndex >= 0) {
|
|
362
|
-
const changedEntry =
|
|
405
|
+
const changedEntry = reconciledRun.history[changedHistoryIndex];
|
|
363
406
|
if (!changedEntry || !workflow.definition.steps[changedEntry.stepId]) {
|
|
364
407
|
return {
|
|
365
408
|
changed: true,
|
|
@@ -367,19 +410,19 @@ export function reconcileRun(
|
|
|
367
410
|
'a completed step was removed; abort or restore the configuration',
|
|
368
411
|
};
|
|
369
412
|
}
|
|
370
|
-
const retainedHistory =
|
|
413
|
+
const retainedHistory = reconciledRun.history.slice(0, changedHistoryIndex);
|
|
371
414
|
const restartedStep = changedEntry.stepId;
|
|
372
415
|
const stepHandoff = retainedHistory.at(-1)?.summary ?? '';
|
|
373
416
|
const reviewedArtifact = retainedReviewedArtifact(
|
|
374
417
|
workflow,
|
|
375
|
-
|
|
418
|
+
reconciledRun,
|
|
376
419
|
retainedHistory,
|
|
377
420
|
);
|
|
378
421
|
return {
|
|
379
422
|
changed: true,
|
|
380
423
|
restartedStep,
|
|
381
424
|
run: withUpdate(
|
|
382
|
-
|
|
425
|
+
reconciledRun,
|
|
383
426
|
{
|
|
384
427
|
workflowDigest: workflow.digest,
|
|
385
428
|
status: 'paused',
|
|
@@ -392,6 +435,7 @@ export function reconcileRun(
|
|
|
392
435
|
lastSummary: stepHandoff,
|
|
393
436
|
pendingGate: undefined,
|
|
394
437
|
pausedFrom: 'running',
|
|
438
|
+
failedStepId: undefined,
|
|
395
439
|
pauseReason: `Configuration changed; restarted step "${restartedStep}"`,
|
|
396
440
|
gateFeedback: '',
|
|
397
441
|
},
|
|
@@ -401,12 +445,12 @@ export function reconcileRun(
|
|
|
401
445
|
}
|
|
402
446
|
|
|
403
447
|
const currentDigest = workflow.stepDigests[run.currentStepId] ?? '';
|
|
404
|
-
const currentChanged = currentDigest !==
|
|
448
|
+
const currentChanged = currentDigest !== reconciledRun.currentStepDigest;
|
|
405
449
|
return {
|
|
406
450
|
changed: true,
|
|
407
451
|
...(currentChanged ? { restartedStep: run.currentStepId } : {}),
|
|
408
452
|
run: withUpdate(
|
|
409
|
-
|
|
453
|
+
reconciledRun,
|
|
410
454
|
{
|
|
411
455
|
workflowDigest: workflow.digest,
|
|
412
456
|
currentStepDigest: currentDigest,
|
|
@@ -415,6 +459,7 @@ export function reconcileRun(
|
|
|
415
459
|
status: 'paused' as const,
|
|
416
460
|
pendingGate: undefined,
|
|
417
461
|
pausedFrom: 'running' as const,
|
|
462
|
+
failedStepId: undefined,
|
|
418
463
|
pauseReason: `Configuration changed; restarted step "${run.currentStepId}"`,
|
|
419
464
|
gateFeedback: '',
|
|
420
465
|
}
|