@osolmaz/pi-workflows 0.11.2 → 0.12.1

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.
Files changed (177) hide show
  1. package/README.md +15 -10
  2. package/dist/builtins/autoimplement-command-batches.d.ts +52 -0
  3. package/dist/builtins/autoimplement-command-batches.js +258 -0
  4. package/dist/builtins/autoimplement-command-batches.js.map +1 -0
  5. package/dist/builtins/autoimplement.workflow.d.ts +509 -124
  6. package/dist/builtins/autoimplement.workflow.js +884 -327
  7. package/dist/builtins/autoimplement.workflow.js.map +1 -1
  8. package/dist/builtins/catalog.js +5 -3
  9. package/dist/builtins/catalog.js.map +1 -1
  10. package/dist/builtins/index.d.ts +4 -1
  11. package/dist/builtins/index.js +3 -1
  12. package/dist/builtins/index.js.map +1 -1
  13. package/dist/builtins/monitor.workflow.d.ts +2 -4
  14. package/dist/builtins/monitor.workflow.js +26 -128
  15. package/dist/builtins/monitor.workflow.js.map +1 -1
  16. package/dist/builtins/pi-agent-group.d.ts +72 -0
  17. package/dist/builtins/pi-agent-group.js +1087 -0
  18. package/dist/builtins/pi-agent-group.js.map +1 -0
  19. package/dist/builtins/plan-approval.workflow.d.ts +39 -5
  20. package/dist/builtins/plan-approval.workflow.js +92 -14
  21. package/dist/builtins/plan-approval.workflow.js.map +1 -1
  22. package/dist/builtins/plan-change.workflow.d.ts +301 -0
  23. package/dist/builtins/plan-change.workflow.js +256 -0
  24. package/dist/builtins/plan-change.workflow.js.map +1 -0
  25. package/dist/builtins/plan-presentation.js +2 -2
  26. package/dist/builtins/plan-presentation.js.map +1 -1
  27. package/dist/builtins/sanity-check.workflow.d.ts +85 -0
  28. package/dist/builtins/sanity-check.workflow.js +482 -0
  29. package/dist/builtins/sanity-check.workflow.js.map +1 -0
  30. package/dist/controllers/sqlite.d.ts +90 -2
  31. package/dist/controllers/sqlite.js +380 -5
  32. package/dist/controllers/sqlite.js.map +1 -1
  33. package/dist/extension/decision-channels.d.ts +2 -2
  34. package/dist/extension/decision-channels.js +29 -35
  35. package/dist/extension/decision-channels.js.map +1 -1
  36. package/dist/extension/deferred-turn-coordinator.d.ts +32 -0
  37. package/dist/extension/deferred-turn-coordinator.js +143 -0
  38. package/dist/extension/deferred-turn-coordinator.js.map +1 -0
  39. package/dist/extension/deferred-turn.d.ts +44 -0
  40. package/dist/extension/deferred-turn.js +110 -0
  41. package/dist/extension/deferred-turn.js.map +1 -0
  42. package/dist/extension/index.js +348 -80
  43. package/dist/extension/index.js.map +1 -1
  44. package/dist/extension/session-events.d.ts +2 -2
  45. package/dist/extension/step-message.d.ts +1 -0
  46. package/dist/extension/step-message.js.map +1 -1
  47. package/dist/extension/widget.js +23 -3
  48. package/dist/extension/widget.js.map +1 -1
  49. package/dist/herdr/setup.js +4 -4
  50. package/dist/render/graph-render.js +1 -2
  51. package/dist/render/graph-render.js.map +1 -1
  52. package/dist/viewer/render.js +7 -6
  53. package/dist/viewer/render.js.map +1 -1
  54. package/dist/workflows/catalog.js +7 -2
  55. package/dist/workflows/catalog.js.map +1 -1
  56. package/dist/workflows/command-batch.d.ts +38 -0
  57. package/dist/workflows/command-batch.js +176 -0
  58. package/dist/workflows/command-batch.js.map +1 -0
  59. package/dist/workflows/composition.js +8 -0
  60. package/dist/workflows/composition.js.map +1 -1
  61. package/dist/workflows/decision-presentation.d.ts +1 -1
  62. package/dist/workflows/decision-presentation.js +51 -38
  63. package/dist/workflows/decision-presentation.js.map +1 -1
  64. package/dist/workflows/engine.d.ts +2 -2
  65. package/dist/workflows/engine.js +22 -17
  66. package/dist/workflows/engine.js.map +1 -1
  67. package/dist/workflows/errors.d.ts +13 -0
  68. package/dist/workflows/errors.js +15 -0
  69. package/dist/workflows/errors.js.map +1 -1
  70. package/dist/workflows/human-decision.d.ts +16 -4
  71. package/dist/workflows/human-decision.js +175 -72
  72. package/dist/workflows/human-decision.js.map +1 -1
  73. package/dist/workflows/index.d.ts +3 -2
  74. package/dist/workflows/index.js +2 -1
  75. package/dist/workflows/index.js.map +1 -1
  76. package/dist/workflows/progress.d.ts +1 -0
  77. package/dist/workflows/progress.js +15 -3
  78. package/dist/workflows/progress.js.map +1 -1
  79. package/dist/workflows/schema.js +12 -1
  80. package/dist/workflows/schema.js.map +1 -1
  81. package/dist/workflows/shell.d.ts +4 -0
  82. package/dist/workflows/shell.js +6 -0
  83. package/dist/workflows/shell.js.map +1 -1
  84. package/dist/workflows/store.js +8 -1
  85. package/dist/workflows/store.js.map +1 -1
  86. package/dist/workflows/types.d.ts +37 -48
  87. package/docs/2026-08-18-herdr-piw-plan.md +1 -1
  88. package/docs/2026-08-20-durable-workflow-launch-plan.md +19 -23
  89. package/docs/CONTROLLERS.md +2 -2
  90. package/docs/DEFERRED_TURNS.md +298 -0
  91. package/docs/DESIGN_PHILOSOPHY.md +1 -1
  92. package/docs/HUMAN_DECISIONS.md +30 -40
  93. package/docs/HUMAN_DECISION_PRESENTATIONS.md +17 -27
  94. package/docs/MONITOR.md +7 -13
  95. package/docs/WORKFLOW_COMPOSITION.md +10 -9
  96. package/docs/WORKFLOW_STEP_MESSAGES.md +5 -5
  97. package/docs/WORKFLOW_UPDATES.md +28 -5
  98. package/docs/plans/2026-08-04-controller-runtime-plan.md +1 -1
  99. package/docs/plans/2026-08-05-always-on-workflows-plan.md +1 -1
  100. package/docs/plans/2026-08-10-agent-managed-monitor-workflows-plan.md +9 -9
  101. package/docs/plans/2026-08-13-built-in-workflow-catalog-plan.md +1 -1
  102. package/docs/plans/2026-08-13-session-addressed-workflow-notifications-plan.md +1 -1
  103. package/docs/plans/2026-08-16-workflow-updates-plan.md +3 -3
  104. package/docs/plans/2026-08-17-bundled-skills-plan.md +6 -6
  105. package/docs/plans/2026-08-19-human-decision-gates-plan.md +5 -5
  106. package/docs/plans/2026-08-19-human-decision-presentations-plan.md +1 -1
  107. package/docs/plans/2026-08-19-provider-compatible-workflow-tool-schema-plan.md +1 -1
  108. package/docs/plans/2026-08-19-workflow-composition-plan.md +6 -6
  109. package/docs/plans/2026-08-20-autoimplement-blocker-challenge-plan.md +3 -3
  110. package/docs/plans/2026-08-20-bounded-command-batches-plan.md +206 -0
  111. package/docs/plans/2026-08-20-herdr-plugin-sync-plan.md +9 -9
  112. package/docs/plans/2026-08-21-autoimplement-timeout-fallback-plan.md +242 -0
  113. package/docs/plans/2026-08-21-deferred-turn-intents-plan.md +324 -0
  114. package/docs/plans/2026-08-21-plan-change-approval-policy-plan.md +322 -0
  115. package/docs/plans/2026-08-21-sanity-check-plan.md +283 -0
  116. package/docs/run-bundles.md +8 -6
  117. package/docs/workflows.md +85 -22
  118. package/examples/workflows/approved-plan.workflow.ts +19 -46
  119. package/examples/workflows/command-batch.workflow.ts +50 -0
  120. package/examples/workflows/sanity-check.workflow.ts +1 -0
  121. package/herdr-plugin.toml +3 -3
  122. package/package.json +7 -7
  123. package/schemas/decision-presentation-v1.schema.json +1 -1
  124. package/schemas/human-decision-accepted-v1.schema.json +16 -4
  125. package/schemas/human-decision-answer-attempt-v1.schema.json +1 -1
  126. package/schemas/human-decision-cancellation-v1.schema.json +1 -1
  127. package/schemas/human-decision-continuation-v1.schema.json +11 -2
  128. package/schemas/human-decision-delivery-v1.schema.json +9 -1
  129. package/schemas/human-decision-receipt-v1.schema.json +9 -1
  130. package/schemas/human-decision-request-v1.schema.json +25 -5
  131. package/schemas/human-decision-resolution-v1.schema.json +1 -1
  132. package/schemas/human-decision-settlement-v1.schema.json +1 -1
  133. package/skills/autodoc/SKILL.md +33 -2
  134. package/skills/autoimplement/SKILL.md +93 -12
  135. package/skills/autoplan/SKILL.md +26 -2
  136. package/skills/monitor/SKILL.md +66 -24
  137. package/skills/pi-workflows/SKILL.md +21 -6
  138. package/skills/sanity-check/SKILL.md +44 -0
  139. package/src/builtins/autoimplement-command-batches.ts +364 -0
  140. package/src/builtins/autoimplement.workflow.ts +1075 -370
  141. package/src/builtins/catalog.ts +5 -3
  142. package/src/builtins/index.ts +24 -0
  143. package/src/builtins/monitor.workflow.ts +27 -150
  144. package/src/builtins/pi-agent-group.ts +1407 -0
  145. package/src/builtins/plan-approval.workflow.ts +157 -24
  146. package/src/builtins/plan-change.workflow.ts +321 -0
  147. package/src/builtins/plan-presentation.ts +2 -2
  148. package/src/builtins/sanity-check.workflow.ts +769 -0
  149. package/src/controllers/sqlite.ts +580 -7
  150. package/src/extension/decision-channels.ts +36 -66
  151. package/src/extension/deferred-turn-coordinator.ts +171 -0
  152. package/src/extension/deferred-turn.ts +166 -0
  153. package/src/extension/index.ts +438 -90
  154. package/src/extension/session-events.ts +2 -2
  155. package/src/extension/step-message.ts +1 -0
  156. package/src/extension/widget.ts +24 -5
  157. package/src/herdr/setup.ts +4 -4
  158. package/src/render/graph-render.ts +1 -2
  159. package/src/viewer/render.ts +7 -6
  160. package/src/workflows/catalog.ts +7 -2
  161. package/src/workflows/command-batch.ts +254 -0
  162. package/src/workflows/composition.ts +9 -0
  163. package/src/workflows/decision-presentation.ts +56 -43
  164. package/src/workflows/engine.ts +25 -20
  165. package/src/workflows/errors.ts +24 -0
  166. package/src/workflows/human-decision.ts +218 -101
  167. package/src/workflows/index.ts +20 -11
  168. package/src/workflows/progress.ts +18 -3
  169. package/src/workflows/schema.ts +19 -1
  170. package/src/workflows/shell.ts +10 -0
  171. package/src/workflows/store.ts +8 -1
  172. package/src/workflows/types.ts +43 -59
  173. package/schemas/human-decision-accepted-v2.schema.json +0 -50
  174. package/schemas/human-decision-delivery-v2.schema.json +0 -36
  175. package/schemas/human-decision-receipt-v2.schema.json +0 -39
  176. package/schemas/human-decision-request-v2.schema.json +0 -69
  177. package/schemas/human-decision-resolution-v2.schema.json +0 -27
@@ -4,15 +4,17 @@ import autoimplementWorkflow from "./autoimplement.workflow.js";
4
4
  import autoplanWorkflow from "./autoplan.workflow.js";
5
5
  import monitorWorkflow from "./monitor.workflow.js";
6
6
  import planApprovalWorkflow from "./plan-approval.workflow.js";
7
+ import sanityCheckWorkflow from "./sanity-check.workflow.js";
7
8
 
8
9
  export const builtinWorkflowCatalog = new BuiltinWorkflowCatalog([
9
10
  { id: "autoplan", revision: "1", definition: autoplanWorkflow },
10
11
  { id: "autodoc", revision: "1", definition: autodocWorkflow },
11
- { id: "autoimplement", revision: "4", definition: autoimplementWorkflow },
12
- { id: "plan-approval", revision: "2", definition: planApprovalWorkflow },
12
+ { id: "autoimplement", revision: "8", definition: autoimplementWorkflow },
13
+ { id: "plan-approval", revision: "4", definition: planApprovalWorkflow },
14
+ { id: "sanity-check", revision: "3", definition: sanityCheckWorkflow },
13
15
  {
14
16
  id: "monitor",
15
- revision: "7",
17
+ revision: "9",
16
18
  definition: monitorWorkflow,
17
19
  legacySources: [
18
20
  {
@@ -17,16 +17,40 @@ export {
17
17
  type AutoimplementInput,
18
18
  type ExistingPlanDiscovery,
19
19
  } from "./autoimplement.workflow.js";
20
+ export type { AutoimplementConcurrency } from "./autoimplement-command-batches.js";
20
21
  export {
21
22
  default as monitorWorkflow,
22
23
  type MonitorInput,
23
24
  type MonitorRepairPolicy,
24
25
  } from "./monitor.workflow.js";
26
+ export {
27
+ planChangeWorkflow,
28
+ type PlanChangeBlocked,
29
+ type PlanChangeInput,
30
+ type PlanChangeReady,
31
+ } from "./plan-change.workflow.js";
25
32
  export { presentPlan } from "./plan-presentation.js";
33
+ export {
34
+ sanityCheckWorkflow,
35
+ type ContributionEvidence,
36
+ type SanityCheckArea,
37
+ type SanityCheckAreaResult,
38
+ type SanityCheckEvidence,
39
+ type SanityCheckInput,
40
+ type SanityCheckMode,
41
+ type SanityCheckResult,
42
+ type SanityCheckReview,
43
+ type SanityCheckVerdict,
44
+ } from "./sanity-check.workflow.js";
26
45
  export {
27
46
  planApprovalWorkflow,
47
+ parsePlanApprovalPolicy,
28
48
  type PlanApprovalContinue,
29
49
  type PlanApprovalInput,
50
+ type PlanApprovalMode,
51
+ type PlanApprovalPolicy,
30
52
  type PlanApprovalReplan,
53
+ type PlanApprovalResolution,
31
54
  type PlanApprovalStop,
55
+ type ResolvedPlanApprovalPolicy,
32
56
  } from "./plan-approval.workflow.js";
@@ -20,10 +20,9 @@ import type {
20
20
  WorkflowProgressData,
21
21
  } from "../workflows/types.js";
22
22
  import { validateProgressData } from "../workflows/updates.js";
23
- import autodocWorkflow, { type AutodocInput } from "./autodoc.workflow.js";
24
23
  import autoimplementWorkflow, { type AutoimplementInput } from "./autoimplement.workflow.js";
25
- import autoplanWorkflow from "./autoplan.workflow.js";
26
- import planApprovalWorkflow, { type PlanApprovalInput } from "./plan-approval.workflow.js";
24
+ import { parsePlanApprovalPolicy, type PlanApprovalPolicy } from "./plan-approval.workflow.js";
25
+ import planChangeWorkflow, { type NormalizedPlanChangeInput } from "./plan-change.workflow.js";
27
26
 
28
27
  const MIN_INTERVAL_MINUTES = 1;
29
28
  const MAX_INTERVAL_MINUTES = 24 * 60;
@@ -47,10 +46,7 @@ export type MonitorRepairPolicy = {
47
46
  repository?: string;
48
47
  baseBranch?: string;
49
48
  merge?: boolean;
50
- approval?: {
51
- audience: string;
52
- maxReplans: number;
53
- };
49
+ approval?: PlanApprovalPolicy;
54
50
  };
55
51
 
56
52
  export type MonitorInput = {
@@ -169,22 +165,7 @@ export function prepareMonitorInput(input: unknown): MonitorConfig {
169
165
  if (raw.merge !== undefined && typeof raw.merge !== "boolean") {
170
166
  throw new Error("repair merge must be a boolean");
171
167
  }
172
- let approval: MonitorRepairPolicy["approval"];
173
- if (raw.approval !== undefined) {
174
- const value = requireRecord(raw.approval, "repair approval");
175
- const maxReplans = value.maxReplans ?? 3;
176
- if (
177
- !Number.isInteger(maxReplans) ||
178
- (maxReplans as number) < 1 ||
179
- (maxReplans as number) > 20
180
- ) {
181
- throw new Error("repair approval maxReplans must be from 1 through 20");
182
- }
183
- approval = {
184
- audience: requireBoundedString(value.audience, "repair approval audience", 200),
185
- maxReplans: maxReplans as number,
186
- };
187
- }
168
+ const approval = parsePlanApprovalPolicy(raw.approval);
188
169
  repair = {
189
170
  authorized: true,
190
171
  ...(raw.scope !== undefined
@@ -198,7 +179,7 @@ export function prepareMonitorInput(input: unknown): MonitorConfig {
198
179
  ? { baseBranch: requireBoundedString(raw.baseBranch, "repair base branch", 256) }
199
180
  : {}),
200
181
  ...(raw.merge !== undefined ? { merge: raw.merge !== false } : {}),
201
- ...(approval !== undefined ? { approval } : {}),
182
+ approval,
202
183
  };
203
184
  }
204
185
  return {
@@ -325,61 +306,27 @@ function currentRepairPlan(outputs: Record<string, unknown>): {
325
306
  planDigest: string;
326
307
  documents: string[];
327
308
  } {
328
- const documentation = outputs.documentation as
329
- | {
330
- exit?: string;
331
- output?: {
332
- plan?: unknown;
333
- planDigest?: string;
334
- documentation?: { files?: string[] };
335
- };
336
- }
337
- | undefined;
338
- if (
339
- documentation?.exit === "ready" &&
340
- documentation.output?.plan !== undefined &&
341
- typeof documentation.output.planDigest === "string"
342
- ) {
343
- return {
344
- plan: documentation.output.plan,
345
- planDigest: documentation.output.planDigest,
346
- documents: documentation.output.documentation?.files ?? [],
347
- };
348
- }
349
- const design = includedResult(autoplanWorkflow, outputs.initialDesign);
350
- if (design.exit !== "ready") throw new Error("monitor design did not return a ready plan");
351
- return { plan: design.output.plan, planDigest: design.output.planDigest, documents: [] };
352
- }
353
-
354
- function latestReplanInstructions(outputs: Record<string, unknown>): string | undefined {
355
- const approval = outputs.approval as
356
- | { exit?: string; output?: { instructions?: unknown } }
357
- | undefined;
358
- return approval?.exit === "replan" && typeof approval.output?.instructions === "string"
359
- ? approval.output.instructions
360
- : undefined;
309
+ const result = includedResult(planChangeWorkflow, outputs.planChange);
310
+ if (result.exit !== "ready") throw new Error("monitor plan change did not return a ready plan");
311
+ return {
312
+ plan: result.output.plan,
313
+ planDigest: result.output.planDigest,
314
+ documents: result.output.documents,
315
+ };
361
316
  }
362
317
 
363
318
  function repairBlockedReason(outputs: Record<string, unknown>): string {
364
319
  const guard = outputs.repairGuard as { reason?: string; route?: string } | undefined;
365
320
  if (guard?.route === "blocked" && guard.reason !== undefined) return guard.reason;
366
- const replan = outputs.replanGuard as { reason?: string; route?: string } | undefined;
367
- if (replan?.route === "blocked" && replan.reason !== undefined) return replan.reason;
368
- const approval = outputs.approval as { exit?: string; output?: { status?: string } } | undefined;
369
- if (approval?.exit === "stop") return "The operator stopped the proposed repair.";
370
- const documentation = outputs.documentation as
321
+ const planChange = outputs.planChange as
371
322
  | { exit?: string; output?: { reason?: string } }
372
323
  | undefined;
373
324
  const implementation = outputs.implementation as
374
325
  | { exit?: string; output?: { reason?: string } }
375
326
  | undefined;
376
- const design = outputs.initialDesign as
377
- | { exit?: string; output?: { reason?: string } }
378
- | undefined;
379
327
  return (
380
328
  implementation?.output?.reason ??
381
- documentation?.output?.reason ??
382
- design?.output?.reason ??
329
+ planChange?.output?.reason ??
383
330
  "The repair did not produce new verified progress."
384
331
  );
385
332
  }
@@ -427,67 +374,28 @@ const monitorWorkflow: WorkflowDefinition = defineWorkflow({
427
374
  startAt: "prepare",
428
375
  maxSteps: 200_000,
429
376
  includes: {
430
- initialDesign: includeWorkflow({
431
- workflow: "autoplan",
432
- contract: autoplanWorkflow,
433
- input: ({ outputs }) => {
377
+ planChange: includeWorkflow(planChangeWorkflow, {
378
+ input: ({ outputs }): NormalizedPlanChangeInput => {
434
379
  const config = configFrom(outputs);
435
380
  const repair = (outputs.check as MonitorCheck).repair;
436
381
  if (repair === undefined) throw new Error("monitor repair details are missing");
437
- const prior = outputs.initialDesign as
382
+ const prior = outputs.planChange as
438
383
  | { exit?: string; output?: { plan?: unknown } }
439
384
  | undefined;
440
- const instructions = latestReplanInstructions(outputs);
441
385
  return {
442
- problem: repair.problem,
386
+ task: repair.problem,
443
387
  ...(config.repair?.scope !== undefined ? { scope: config.repair.scope } : {}),
444
388
  ...(config.repair?.constraints !== undefined
445
389
  ? { constraints: config.repair.constraints }
446
390
  : {}),
447
- ...(prior?.exit === "ready" && prior.output?.plan !== undefined
448
- ? { previousPlan: prior.output.plan }
449
- : {}),
450
- newEvidence:
451
- instructions === undefined
452
- ? repair.evidence
453
- : { observedEvidence: repair.evidence, operatorInstructions: instructions },
454
- };
455
- },
456
- }),
457
- documentation: includeWorkflow(autodocWorkflow, {
458
- input: ({ outputs }): AutodocInput => {
459
- const config = configFrom(outputs);
460
- const repair = (outputs.check as MonitorCheck).repair;
461
- const design = includedResult(autoplanWorkflow, outputs.initialDesign);
462
- if (design.exit !== "ready") throw new Error("monitor design did not return a ready plan");
463
- if (repair === undefined) throw new Error("monitor repair details are missing");
464
- return {
465
- task: repair.problem,
466
- plan: design.output.plan,
467
391
  ...(config.repair?.repository !== undefined
468
392
  ? { repository: config.repair.repository }
469
393
  : {}),
470
- evidence: latestReplanInstructions(outputs) ?? repair.evidence,
471
- };
472
- },
473
- }),
474
- approval: includeWorkflow(planApprovalWorkflow, {
475
- input: ({ outputs, state }): PlanApprovalInput => {
476
- const config = configFrom(outputs);
477
- const repair = (outputs.check as MonitorCheck).repair;
478
- const approval = config.repair?.approval;
479
- if (repair === undefined || approval === undefined) {
480
- throw new Error("monitor approval was entered without an approval policy");
481
- }
482
- const current = currentRepairPlan(outputs);
483
- const revision =
484
- state.steps.filter((step) => step.nodeId === "approval/approve").length + 1;
485
- return {
486
- task: repair.problem,
487
- plan: current.plan,
488
- planDigest: current.planDigest,
489
- audience: approval.audience,
490
- revision,
394
+ ...(prior?.exit === "ready" && prior.output?.plan !== undefined
395
+ ? { previousPlan: prior.output.plan }
396
+ : {}),
397
+ newEvidence: repair.evidence,
398
+ approval: parsePlanApprovalPolicy(config.repair?.approval),
491
399
  };
492
400
  },
493
401
  }),
@@ -517,6 +425,7 @@ const monitorWorkflow: WorkflowDefinition = defineWorkflow({
517
425
  ...(config.repair?.baseBranch !== undefined
518
426
  ? { baseBranch: config.repair.baseBranch }
519
427
  : {}),
428
+ approval: parsePlanApprovalPolicy(config.repair?.approval),
520
429
  merge: config.repair?.merge === true,
521
430
  };
522
431
  return request;
@@ -603,25 +512,6 @@ const monitorWorkflow: WorkflowDefinition = defineWorkflow({
603
512
  }
604
513
  : { route: "repair", reason: "The issue is new or has changed evidence." },
605
514
  }),
606
- approvalRoute: compute({
607
- run: ({ outputs }) => ({
608
- route: configFrom(outputs).repair?.approval === undefined ? "implement" : "approve",
609
- }),
610
- }),
611
- replanGuard: compute({
612
- run: (context) => {
613
- const limit = configFrom(context.outputs).repair?.approval?.maxReplans ?? 3;
614
- const replans = context.state.steps.filter(
615
- (step) => step.nodeId === "approval/replan",
616
- ).length;
617
- return replans > limit
618
- ? {
619
- route: "blocked",
620
- reason: `Monitor repair reached the ${limit}-replan safety limit.`,
621
- }
622
- : { route: "design", replans, limit };
623
- },
624
- }),
625
515
  repairBlocked: compute({
626
516
  run: (context) => ({
627
517
  reason: repairBlockedReason(context.outputs),
@@ -707,23 +597,10 @@ const monitorWorkflow: WorkflowDefinition = defineWorkflow({
707
597
  },
708
598
  {
709
599
  from: "repairGuard",
710
- switch: { on: "$.route", cases: { repair: "initialDesign", blocked: "repairBlocked" } },
711
- },
712
- { from: "initialDesign.ready", to: "documentation" },
713
- { from: "initialDesign.blocked", to: "repairBlocked" },
714
- { from: "documentation.ready", to: "approvalRoute" },
715
- { from: "documentation.blocked", to: "repairBlocked" },
716
- {
717
- from: "approvalRoute",
718
- switch: { on: "$.route", cases: { approve: "approval", implement: "implementation" } },
719
- },
720
- { from: "approval.continue", to: "implementation" },
721
- { from: "approval.stop", to: "repairBlocked" },
722
- { from: "approval.replan", to: "replanGuard" },
723
- {
724
- from: "replanGuard",
725
- switch: { on: "$.route", cases: { design: "initialDesign", blocked: "repairBlocked" } },
600
+ switch: { on: "$.route", cases: { repair: "planChange", blocked: "repairBlocked" } },
726
601
  },
602
+ { from: "planChange.ready", to: "implementation" },
603
+ { from: "planChange.blocked", to: "repairBlocked" },
727
604
  { from: "implementation.completed", to: "check" },
728
605
  { from: "implementation.blocked", to: "repairBlocked" },
729
606
  { from: "repairBlocked", to: "repairReport" },