@exaudeus/workrail 3.67.0 → 3.68.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 (144) hide show
  1. package/dist/application/services/compiler/template-registry.js +10 -1
  2. package/dist/cli/commands/worktrain-init.js +1 -1
  3. package/dist/console-ui/assets/{index-tOl8Vowf.js → index-DPdRJHMX.js} +1 -1
  4. package/dist/console-ui/index.html +1 -1
  5. package/dist/coordinators/modes/full-pipeline.js +4 -4
  6. package/dist/coordinators/modes/implement-shared.js +5 -5
  7. package/dist/coordinators/modes/implement.js +4 -4
  8. package/dist/coordinators/pr-review.js +4 -4
  9. package/dist/daemon/workflow-runner.d.ts +1 -0
  10. package/dist/daemon/workflow-runner.js +1 -0
  11. package/dist/manifest.json +31 -31
  12. package/dist/mcp/handlers/v2-context-budget.js +18 -0
  13. package/dist/mcp/handlers/v2-workflow.js +1 -1
  14. package/dist/mcp/workflow-protocol-contracts.js +2 -2
  15. package/dist/v2/durable-core/constants.d.ts +2 -0
  16. package/dist/v2/durable-core/constants.js +2 -1
  17. package/dist/v2/projections/session-metrics.js +1 -1
  18. package/docs/authoring-v2.md +4 -4
  19. package/docs/changelog-recent.md +3 -3
  20. package/docs/configuration.md +1 -1
  21. package/docs/design/adaptive-coordinator-context-candidates.md +1 -1
  22. package/docs/design/adaptive-coordinator-context.md +1 -1
  23. package/docs/design/adaptive-coordinator-routing-candidates.md +18 -18
  24. package/docs/design/adaptive-coordinator-routing-review.md +1 -1
  25. package/docs/design/adaptive-coordinator-routing.md +34 -34
  26. package/docs/design/agent-cascade-protocol.md +2 -2
  27. package/docs/design/console-daemon-separation-discovery.md +323 -0
  28. package/docs/design/context-assembly-design-candidates.md +1 -1
  29. package/docs/design/context-assembly-implementation-plan.md +1 -1
  30. package/docs/design/context-assembly-layer.md +2 -2
  31. package/docs/design/context-assembly-review-findings.md +1 -1
  32. package/docs/design/coordinator-access-audit.md +293 -0
  33. package/docs/design/coordinator-architecture-audit.md +62 -0
  34. package/docs/design/coordinator-error-handling-audit.md +240 -0
  35. package/docs/design/coordinator-testability-audit.md +426 -0
  36. package/docs/design/daemon-architecture-discovery.md +1 -1
  37. package/docs/design/daemon-console-separation-discovery.md +242 -0
  38. package/docs/design/daemon-memory-audit.md +203 -0
  39. package/docs/design/design-candidates-console-daemon-separation.md +256 -0
  40. package/docs/design/design-candidates-discovery-loop-fix.md +141 -0
  41. package/docs/design/design-review-findings-console-daemon-separation.md +106 -0
  42. package/docs/design/design-review-findings-discovery-loop-fix.md +81 -0
  43. package/docs/design/discovery-loop-fix-candidates.md +161 -0
  44. package/docs/design/discovery-loop-fix-design-review.md +106 -0
  45. package/docs/design/discovery-loop-fix-validation.md +258 -0
  46. package/docs/design/discovery-loop-investigation-A.md +188 -0
  47. package/docs/design/discovery-loop-investigation-B.md +287 -0
  48. package/docs/design/exploration-workflow-candidates.md +205 -0
  49. package/docs/design/exploration-workflow-design-review.md +166 -0
  50. package/docs/design/exploration-workflow-discovery.md +443 -0
  51. package/docs/design/ide-context-files-candidates.md +231 -0
  52. package/docs/design/ide-context-files-design-review.md +85 -0
  53. package/docs/design/ide-context-files.md +615 -0
  54. package/docs/design/implementation-plan-discovery-loop-fix.md +199 -0
  55. package/docs/design/implementation-plan-queue-poll-rotation.md +102 -0
  56. package/docs/design/in-process-http-audit.md +190 -0
  57. package/docs/design/layer3b-ghost-nodes-design-candidates.md +2 -2
  58. package/docs/design/loadSessionNotes-candidates.md +108 -0
  59. package/docs/design/loadSessionNotes-test-coverage-discovery.md +297 -0
  60. package/docs/design/loadSessionNotes-test-coverage-session4.md +209 -0
  61. package/docs/design/loadSessionNotes-test-coverage-v3.md +321 -0
  62. package/docs/design/probe-session-design-candidates.md +261 -0
  63. package/docs/design/probe-session-phase0.md +490 -0
  64. package/docs/design/routines-guide.md +7 -7
  65. package/docs/design/session-metrics-attribution-candidates.md +250 -0
  66. package/docs/design/session-metrics-attribution-design-review.md +115 -0
  67. package/docs/design/session-metrics-attribution-discovery.md +319 -0
  68. package/docs/design/session-metrics-candidates.md +227 -0
  69. package/docs/design/session-metrics-design-review.md +104 -0
  70. package/docs/design/session-metrics-discovery.md +454 -0
  71. package/docs/design/spawn-session-debug.md +202 -0
  72. package/docs/design/trigger-validator-candidates.md +214 -0
  73. package/docs/design/trigger-validator-review.md +109 -0
  74. package/docs/design/trigger-validator-shaping-phase0.md +239 -0
  75. package/docs/design/trigger-validator.md +454 -0
  76. package/docs/design/v2-core-design-locks.md +2 -2
  77. package/docs/design/workflow-extension-points.md +15 -15
  78. package/docs/design/workflow-id-validation-at-startup.md +1 -1
  79. package/docs/design/workflow-id-validation-implementation-plan.md +2 -2
  80. package/docs/design/workflow-trigger-lifecycle-audit.md +175 -0
  81. package/docs/design/worktrain-task-queue-candidates.md +5 -5
  82. package/docs/design/worktrain-task-queue.md +4 -4
  83. package/docs/discovery/coordinator-script-design.md +1 -1
  84. package/docs/discovery/coordinator-ux-discovery.md +3 -3
  85. package/docs/discovery/simulation-report.md +1 -1
  86. package/docs/discovery/workflow-modernization-discovery.md +326 -0
  87. package/docs/discovery/workflow-selection-for-discovery-tasks.md +33 -33
  88. package/docs/discovery/worktrain-status-briefing.md +1 -1
  89. package/docs/discovery/wr-discovery-goal-reframing.md +1 -1
  90. package/docs/docker.md +1 -1
  91. package/docs/ideas/backlog.md +227 -0
  92. package/docs/ideas/third-party-workflow-setup-design-thinking.md +1 -1
  93. package/docs/integrations/claude-code.md +5 -5
  94. package/docs/integrations/firebender.md +1 -1
  95. package/docs/plans/agentic-orchestration-roadmap.md +2 -2
  96. package/docs/plans/mr-review-workflow-redesign.md +9 -9
  97. package/docs/plans/ui-ux-workflow-design-candidates.md +4 -4
  98. package/docs/plans/ui-ux-workflow-discovery.md +2 -2
  99. package/docs/plans/workflow-categories-candidates.md +8 -8
  100. package/docs/plans/workflow-categories-discovery.md +4 -4
  101. package/docs/plans/workflow-modernization-design.md +430 -0
  102. package/docs/plans/workflow-staleness-detection-candidates.md +11 -11
  103. package/docs/plans/workflow-staleness-detection-review.md +4 -4
  104. package/docs/plans/workflow-staleness-detection.md +9 -9
  105. package/docs/plans/workrail-platform-vision.md +3 -3
  106. package/docs/reference/agent-context-cleaner-snippet.md +1 -1
  107. package/docs/reference/agent-context-guidance.md +4 -4
  108. package/docs/reference/context-optimization.md +2 -2
  109. package/docs/roadmap/now-next-later.md +2 -2
  110. package/docs/roadmap/open-work-inventory.md +16 -16
  111. package/docs/workflows.md +31 -31
  112. package/package.json +1 -1
  113. package/spec/workflow-tags.json +47 -47
  114. package/workflows/adaptive-ticket-creation.json +16 -16
  115. package/workflows/architecture-scalability-audit.json +22 -22
  116. package/workflows/bug-investigation.agentic.v2.json +3 -3
  117. package/workflows/classify-task-workflow.json +1 -1
  118. package/workflows/coding-task-workflow-agentic.json +6 -6
  119. package/workflows/cross-platform-code-conversion.v2.json +8 -8
  120. package/workflows/document-creation-workflow.json +8 -8
  121. package/workflows/documentation-update-workflow.json +8 -8
  122. package/workflows/intelligent-test-case-generation.json +2 -2
  123. package/workflows/learner-centered-course-workflow.json +2 -2
  124. package/workflows/mr-review-workflow.agentic.v2.json +4 -4
  125. package/workflows/personal-learning-materials-creation-branched.json +8 -8
  126. package/workflows/presentation-creation.json +5 -5
  127. package/workflows/production-readiness-audit.json +1 -1
  128. package/workflows/relocation-workflow-us.json +31 -31
  129. package/workflows/routines/context-gathering.json +1 -1
  130. package/workflows/routines/design-review.json +1 -1
  131. package/workflows/routines/execution-simulation.json +1 -1
  132. package/workflows/routines/feature-implementation.json +3 -3
  133. package/workflows/routines/final-verification.json +1 -1
  134. package/workflows/routines/hypothesis-challenge.json +1 -1
  135. package/workflows/routines/ideation.json +1 -1
  136. package/workflows/routines/parallel-work-partitioning.json +3 -3
  137. package/workflows/routines/philosophy-alignment.json +2 -2
  138. package/workflows/routines/plan-analysis.json +1 -1
  139. package/workflows/routines/plan-generation.json +1 -1
  140. package/workflows/routines/tension-driven-design.json +6 -6
  141. package/workflows/scoped-documentation-workflow.json +26 -26
  142. package/workflows/ui-ux-design-workflow.json +14 -14
  143. package/workflows/workflow-diagnose-environment.json +1 -1
  144. package/workflows/workflow-for-workflows.json +1 -1
@@ -15,7 +15,7 @@ async function runReviewAndVerdictCycle(deps, opts, prUrl, coordinatorStartMs, i
15
15
  ? `Review PR for merge: ${prUrl}`
16
16
  : `Re-review PR after fixes (iteration ${iteration}): ${prUrl}`;
17
17
  deps.stderr(`[review-cycle] Spawning review session (iteration=${iteration}): ${reviewGoal.slice(0, 80)}`);
18
- const reviewSpawnResult = await deps.spawnSession('mr-review-workflow-agentic', reviewGoal, opts.workspace, { prUrl });
18
+ const reviewSpawnResult = await deps.spawnSession('wr.mr-review', reviewGoal, opts.workspace, { prUrl });
19
19
  if (reviewSpawnResult.kind === 'err') {
20
20
  return {
21
21
  kind: 'escalated',
@@ -86,7 +86,7 @@ async function runReviewAndVerdictCycle(deps, opts, prUrl, coordinatorStartMs, i
86
86
  if (fixCutoff)
87
87
  return fixCutoff;
88
88
  const fixGoal = `Fix review findings: ${findings.findingSummaries.slice(0, 3).join('; ')}`;
89
- const fixSpawnResult = await deps.spawnSession('coding-task-workflow-agentic', fixGoal, opts.workspace, { prUrl, findings: findings.findingSummaries });
89
+ const fixSpawnResult = await deps.spawnSession('wr.coding-task', fixGoal, opts.workspace, { prUrl, findings: findings.findingSummaries });
90
90
  if (fixSpawnResult.kind === 'err') {
91
91
  return {
92
92
  kind: 'escalated',
@@ -124,8 +124,8 @@ async function runAuditChain(deps, opts, prUrl, coordinatorStartMs, severity, fi
124
124
  if (auditCutoff)
125
125
  return auditCutoff;
126
126
  const auditWorkflow = findings?.some((f) => f.findingCategory === 'architecture')
127
- ? 'architecture-scalability-audit'
128
- : 'production-readiness-audit';
127
+ ? 'wr.architecture-scalability-audit'
128
+ : 'wr.production-readiness-audit';
129
129
  const auditSpawnResult = await deps.spawnSession(auditWorkflow, `Audit PR before merge: ${prUrl}`, opts.workspace, { prUrl, severity });
130
130
  if (auditSpawnResult.kind === 'err') {
131
131
  try {
@@ -171,7 +171,7 @@ async function runAuditChain(deps, opts, prUrl, coordinatorStartMs, severity, fi
171
171
  const reReviewCutoff = (0, adaptive_pipeline_js_1.checkSpawnCutoff)(coordinatorStartMs, deps.now(), 're-review-after-audit');
172
172
  if (reReviewCutoff)
173
173
  return reReviewCutoff;
174
- const reReviewSpawnResult = await deps.spawnSession('mr-review-workflow-agentic', `Re-review after audit: ${prUrl}`, opts.workspace, { prUrl, auditComplete: true });
174
+ const reReviewSpawnResult = await deps.spawnSession('wr.mr-review', `Re-review after audit: ${prUrl}`, opts.workspace, { prUrl, auditComplete: true });
175
175
  if (reReviewSpawnResult.kind === 'err') {
176
176
  try {
177
177
  await deps.postToOutbox(`Adaptive pipeline escalated: re-review after audit failed to spawn`, { prUrl, phase: 're-review-after-audit', reason: reReviewSpawnResult.error });
@@ -35,11 +35,11 @@ async function runImplementPipeline(deps, opts, pitchPath, coordinatorStartMs) {
35
35
  }
36
36
  async function runImplementCore(deps, opts, pitchPath, coordinatorStartMs) {
37
37
  if (touchesUI(opts.goal)) {
38
- deps.stderr(`[implement] UX signals detected in goal, dispatching ui-ux-design-workflow`);
38
+ deps.stderr(`[implement] UX signals detected in goal, dispatching wr.ui-ux-design`);
39
39
  const cutoffCheck = (0, adaptive_pipeline_js_1.checkSpawnCutoff)(coordinatorStartMs, deps.now(), 'ux-gate');
40
40
  if (cutoffCheck)
41
41
  return cutoffCheck;
42
- const uxSpawnResult = await deps.spawnSession('ui-ux-design-workflow', opts.goal, opts.workspace, {
42
+ const uxSpawnResult = await deps.spawnSession('wr.ui-ux-design', opts.goal, opts.workspace, {
43
43
  pitchPath,
44
44
  });
45
45
  if (uxSpawnResult.kind === 'err') {
@@ -70,8 +70,8 @@ async function runImplementCore(deps, opts, pitchPath, coordinatorStartMs) {
70
70
  const cutoffCheck = (0, adaptive_pipeline_js_1.checkSpawnCutoff)(coordinatorStartMs, deps.now(), 'coding');
71
71
  if (cutoffCheck)
72
72
  return cutoffCheck;
73
- deps.stderr(`[implement] Spawning coding-task-workflow-agentic`);
74
- const codingSpawnResult = await deps.spawnSession('coding-task-workflow-agentic', opts.goal, opts.workspace, {
73
+ deps.stderr(`[implement] Spawning wr.coding-task`);
74
+ const codingSpawnResult = await deps.spawnSession('wr.coding-task', opts.goal, opts.workspace, {
75
75
  pitchPath,
76
76
  });
77
77
  if (codingSpawnResult.kind === 'err') {
@@ -383,7 +383,7 @@ async function runPrReviewCoordinator(deps, opts) {
383
383
  for (const pr of prs) {
384
384
  const goal = `Review PR #${pr.number} "${pr.title}" before merge`;
385
385
  if (opts.dryRun) {
386
- log(` PR #${pr.number} [dry-run] would spawn mr-review-workflow-agentic`);
386
+ log(` PR #${pr.number} [dry-run] would spawn wr.mr-review`);
387
387
  continue;
388
388
  }
389
389
  let spawnContext;
@@ -405,7 +405,7 @@ async function runPrReviewCoordinator(deps, opts) {
405
405
  deps.stderr(`[WARN coord:context prNumber=${pr.number}] priorSessionNotes failed: ${bundle.priorSessionNotes.error}`);
406
406
  }
407
407
  }
408
- const spawnResult = await deps.spawnSession('mr-review-workflow-agentic', goal, opts.workspace, spawnContext);
408
+ const spawnResult = await deps.spawnSession('wr.mr-review', goal, opts.workspace, spawnContext);
409
409
  if (spawnResult.kind === 'err') {
410
410
  spawnErrors.set(pr.number, spawnResult.error);
411
411
  log(` PR #${pr.number} spawn failed: ${spawnResult.error}`);
@@ -589,7 +589,7 @@ async function runFixAgentLoop(deps, opts, pr, initialFindings, initialOutcome,
589
589
  };
590
590
  }
591
591
  log(` PR #${pr.number} -> spawning fix agent (pass ${passCount})...`);
592
- const fixSpawnResult = await deps.spawnSession('coding-task-workflow-agentic', fixGoal, opts.workspace);
592
+ const fixSpawnResult = await deps.spawnSession('wr.coding-task', fixGoal, opts.workspace);
593
593
  if (fixSpawnResult.kind === 'err') {
594
594
  log(` PR #${pr.number} -> fix agent spawn failed: ${fixSpawnResult.error}`);
595
595
  return {
@@ -636,7 +636,7 @@ async function runFixAgentLoop(deps, opts, pr, initialFindings, initialOutcome,
636
636
  };
637
637
  }
638
638
  const reReviewGoal = `Re-review PR #${pr.number} after fixes (pass ${passCount})`;
639
- const reReviewSpawnResult = await deps.spawnSession('mr-review-workflow-agentic', reReviewGoal, opts.workspace, reviewSpawnContext);
639
+ const reReviewSpawnResult = await deps.spawnSession('wr.mr-review', reReviewGoal, opts.workspace, reviewSpawnContext);
640
640
  if (reReviewSpawnResult.kind === 'err') {
641
641
  log(` PR #${pr.number} -> re-review spawn failed: ${reReviewSpawnResult.error}`);
642
642
  return {
@@ -107,6 +107,7 @@ export declare function countOrphanStepAdvances(continueToken: string, ctx: V2To
107
107
  export declare function clearQueueIssueSidecars(sessionsDir: string): Promise<void>;
108
108
  export declare function stripFrontmatter(content: string): string;
109
109
  export declare function loadWorkspaceContext(workspacePath: string): Promise<string | null>;
110
+ export declare function loadSessionNotes(continueToken: string, ctx: V2ToolContext): Promise<readonly string[]>;
110
111
  export declare function makeContinueWorkflowTool(sessionId: string, ctx: V2ToolContext, onAdvance: (nextStepText: string, continueToken: string) => void, onComplete: (notes: string | undefined, artifacts?: readonly unknown[]) => void, schemas: Record<string, any>, _executeContinueWorkflowFn?: typeof executeContinueWorkflow, emitter?: DaemonEventEmitter, workrailSessionId?: string | null): AgentTool;
111
112
  export declare function makeCompleteStepTool(sessionId: string, ctx: V2ToolContext, getCurrentToken: () => string, onAdvance: (nextStepText: string, continueToken: string) => void, onComplete: (notes: string | undefined, artifacts?: readonly unknown[]) => void, onTokenUpdate: (t: string) => void, schemas: Record<string, any>, _executeContinueWorkflowFn?: typeof executeContinueWorkflow, emitter?: DaemonEventEmitter, workrailSessionId?: string | null): AgentTool;
112
113
  export declare function makeBashTool(workspacePath: string, schemas: Record<string, any>, sessionId?: string, emitter?: DaemonEventEmitter, workrailSessionId?: string | null): AgentTool;
@@ -44,6 +44,7 @@ exports.countOrphanStepAdvances = countOrphanStepAdvances;
44
44
  exports.clearQueueIssueSidecars = clearQueueIssueSidecars;
45
45
  exports.stripFrontmatter = stripFrontmatter;
46
46
  exports.loadWorkspaceContext = loadWorkspaceContext;
47
+ exports.loadSessionNotes = loadSessionNotes;
47
48
  exports.makeContinueWorkflowTool = makeContinueWorkflowTool;
48
49
  exports.makeCompleteStepTool = makeCompleteStepTool;
49
50
  exports.makeBashTool = makeBashTool;
@@ -86,8 +86,8 @@
86
86
  "bytes": 1168
87
87
  },
88
88
  "application/services/compiler/template-registry.js": {
89
- "sha256": "92f824723e8d137533f8c752f2f753bb2a88e5812631de0a6428e3c6ff44543a",
90
- "bytes": 5283
89
+ "sha256": "6df7c3b29f7eb62459e86bbafc7d279e19e95d363e820ca46ddb3e4daba6951b",
90
+ "bytes": 5453
91
91
  },
92
92
  "application/services/enhanced-error-service.d.ts": {
93
93
  "sha256": "b6fe8fad92717f0962f87aa9c0f88277bf28fe2b5e3cfd7875612ee57eb8c684",
@@ -358,8 +358,8 @@
358
358
  "bytes": 1041
359
359
  },
360
360
  "cli/commands/worktrain-init.js": {
361
- "sha256": "179afa86b7bb235ede92693ce45249cd30f0056841bdede6583f86a2124eb0dd",
362
- "bytes": 12528
361
+ "sha256": "726d5b3a6252bf25d99fa53445ec543ea7e8c3d020a845c0b13c08182876fdb9",
362
+ "bytes": 12514
363
363
  },
364
364
  "cli/commands/worktrain-overview.d.ts": {
365
365
  "sha256": "d9cb907b57aaa19ee5654c1726a33cdc6b7a54e3bd24dd8f2900d18491dd94a3",
@@ -477,12 +477,12 @@
477
477
  "sha256": "40290b50e21ee7e82433efe13b1aa31c1ea608bd057a5c4e324982f284bc928b",
478
478
  "bytes": 60673
479
479
  },
480
- "console-ui/assets/index-tOl8Vowf.js": {
481
- "sha256": "f598d8869c96cf01f1adc245ac289f9614d7616ce1d8f0a86a0bb9665a26fe5d",
480
+ "console-ui/assets/index-DPdRJHMX.js": {
481
+ "sha256": "5d77b82c529f8adaf1ce398dbab3a2c9a74d4f3e0cb59318f13967d2b659aa5f",
482
482
  "bytes": 767983
483
483
  },
484
484
  "console-ui/index.html": {
485
- "sha256": "908a96c5cb785772a69156cc4c8abaa821f37104d8b7ed0ce0f8db077d7d62e3",
485
+ "sha256": "e9b7fc1c2488485be8d965ba96d0ce2e29c1b59b7fdd09d194625341120ec404",
486
486
  "bytes": 417
487
487
  },
488
488
  "console/standalone-console.d.ts": {
@@ -538,24 +538,24 @@
538
538
  "bytes": 462
539
539
  },
540
540
  "coordinators/modes/full-pipeline.js": {
541
- "sha256": "945d726d728235f8f31f03f33fbde8f6614472b38921a44fba42da959875f37d",
542
- "bytes": 13201
541
+ "sha256": "040b412e33ecb46dcc27c9968c9c0cc5d416880a03dab6f93ed09b8f447c21aa",
542
+ "bytes": 13161
543
543
  },
544
544
  "coordinators/modes/implement-shared.d.ts": {
545
545
  "sha256": "fbad9d91d84d2112b273175618686489a7f106385e0e62d6cab80804d6d0f2d7",
546
546
  "bytes": 708
547
547
  },
548
548
  "coordinators/modes/implement-shared.js": {
549
- "sha256": "117eec98c38826e62150e4ca1ece6ac1cad91b2d0d7128dc34acb609151e4619",
550
- "bytes": 13672
549
+ "sha256": "96f95d9fca1c511eb1b12247148d0e0de3dd3add5aacd72e2a8bba4b36f5995b",
550
+ "bytes": 13636
551
551
  },
552
552
  "coordinators/modes/implement.d.ts": {
553
553
  "sha256": "23919c24d62a0bf15296a52fbc594cca8b1b34e6f8d98dcf7dede8d97ad4cabb",
554
554
  "bytes": 347
555
555
  },
556
556
  "coordinators/modes/implement.js": {
557
- "sha256": "e05ad7330c00db7b2ad8baf27e224616eae1b5cce460a0394a80633fca8827bf",
558
- "bytes": 5522
557
+ "sha256": "59b0dddf00587db1d565c1e460cdad1f75b4ca32687e3649452b0f4de90a3061",
558
+ "bytes": 5482
559
559
  },
560
560
  "coordinators/modes/quick-review.d.ts": {
561
561
  "sha256": "03a4f29a07047b0bf788d84f8e0ebab63d64c8eb98aa57087943a8fb84563998",
@@ -578,8 +578,8 @@
578
578
  "bytes": 3947
579
579
  },
580
580
  "coordinators/pr-review.js": {
581
- "sha256": "870d8baaaec89ebd1bf789a8c03e217c9866b5d89b828ef6efe3bdf3814155f4",
582
- "bytes": 32475
581
+ "sha256": "385baa9e6252dbd84060bb423ce219884d519752f4a6e9f8f04e5f503fa38b67",
582
+ "bytes": 32419
583
583
  },
584
584
  "coordinators/routing/route-task.d.ts": {
585
585
  "sha256": "6661d21e5cfbc9dffbfd8c2f9aaaf0e30a3251997a2c69c6a1b09929343e30e3",
@@ -654,12 +654,12 @@
654
654
  "bytes": 5921
655
655
  },
656
656
  "daemon/workflow-runner.d.ts": {
657
- "sha256": "784dea8d1b86c162bd025706273e07e622cef8bfeeee5c465e09b92f1552dfbd",
658
- "bytes": 8114
657
+ "sha256": "eba5089ec9210f27a06dc1c3fc89804de4d77208fad7678df2ad824c4511636f",
658
+ "bytes": 8227
659
659
  },
660
660
  "daemon/workflow-runner.js": {
661
- "sha256": "2718b3dcf42846c3aec5ae6533c377bf58c0dc1c9f450d0cc016649296ae39af",
662
- "bytes": 101417
661
+ "sha256": "b11fb90d06e7d2f45b76e05640475615295de4eadb89c0c3d1c18ed48d6d0cb4",
662
+ "bytes": 101462
663
663
  },
664
664
  "di/container.d.ts": {
665
665
  "sha256": "003bb7fb7478d627524b9b1e76bd0a963a243794a687ff233b96dc0e33a06d9f",
@@ -1106,8 +1106,8 @@
1106
1106
  "bytes": 674
1107
1107
  },
1108
1108
  "mcp/handlers/v2-context-budget.js": {
1109
- "sha256": "5450c08d25900fd639090ba0090fc4c866e02295ee11aa52c187447424fdc4c2",
1110
- "bytes": 7199
1109
+ "sha256": "e27121c84449f8bdcbcd37a242db54c1afda4a14bc6bc50e148aaf96fecd45b3",
1110
+ "bytes": 8181
1111
1111
  },
1112
1112
  "mcp/handlers/v2-error-mapping.d.ts": {
1113
1113
  "sha256": "4522217a754afc6a2ee3834368decb7fb22ebf9d4c72fc0de9890903d652d76c",
@@ -1234,8 +1234,8 @@
1234
1234
  "bytes": 4343
1235
1235
  },
1236
1236
  "mcp/handlers/v2-workflow.js": {
1237
- "sha256": "ed2594e771344c5c3fed99e92b196f72dcfdf1d34ef8dc911bf6e9a12669ef0d",
1238
- "bytes": 28075
1237
+ "sha256": "4b12fcb52c80bf2b141c99921d2ddae92da2f543ae65abc5035c0b794bd777b6",
1238
+ "bytes": 28078
1239
1239
  },
1240
1240
  "mcp/handlers/v2-workspace-resolution.d.ts": {
1241
1241
  "sha256": "dd4de57b4918ebe749cf8c1df70c02bf1effc50932634bae60db53c9a157e872",
@@ -1514,8 +1514,8 @@
1514
1514
  "bytes": 1863
1515
1515
  },
1516
1516
  "mcp/workflow-protocol-contracts.js": {
1517
- "sha256": "d57a075134f5e7ff7d6ce78f64572ef0322c16943f67a6c974795c5dad241277",
1518
- "bytes": 14372
1517
+ "sha256": "bcd0a058385ab23d2ff550267bfc88ac06b5d89ed2d773086a3cf83431a86c4f",
1518
+ "bytes": 14344
1519
1519
  },
1520
1520
  "mcp/workflow-tool-edition-selector.d.ts": {
1521
1521
  "sha256": "75194908a89aaf7dc48fb661aea099827e7032ec76daf8f2de91bd59d46764ef",
@@ -1894,12 +1894,12 @@
1894
1894
  "bytes": 447
1895
1895
  },
1896
1896
  "v2/durable-core/constants.d.ts": {
1897
- "sha256": "763799ad89e664118c556e6d496809f12f3f946a3083641aa5b5c5c15a7692ba",
1898
- "bytes": 3991
1897
+ "sha256": "14b721867f0866a9a2955b19f16868c39394e80dce2bd94021e6e7f6b4f62429",
1898
+ "bytes": 4159
1899
1899
  },
1900
1900
  "v2/durable-core/constants.js": {
1901
- "sha256": "9bfd85c65d303953aefd4bad643a8bc51f8cbca741bfcc0a87c6f464f5cf73dc",
1902
- "bytes": 3877
1901
+ "sha256": "21a7a514d3a365c7e7690c1c57dd402a25686bfd2dea38082fcc02ee6c266a5c",
1902
+ "bytes": 3987
1903
1903
  },
1904
1904
  "v2/durable-core/domain/ack-advance-append-plan.d.ts": {
1905
1905
  "sha256": "2b4a8ad0e1d9e9066f100f958e572f19af590ab70946c2396d2d5568875bdf00",
@@ -3066,8 +3066,8 @@
3066
3066
  "bytes": 730
3067
3067
  },
3068
3068
  "v2/projections/session-metrics.js": {
3069
- "sha256": "89a1ee5aae79a19c7fc60840e62741a7dd93028562e72cd26a15e4988953c6c4",
3070
- "bytes": 3421
3069
+ "sha256": "89dd4c149087234e3f4f18382340a9f855942fd96595783b7d7ad5c76449536a",
3070
+ "bytes": 3370
3071
3071
  },
3072
3072
  "v2/read-only/v1-to-v2-shim.d.ts": {
3073
3073
  "sha256": "b122df1d4eb4119b65465baa00f157ca4466575d3bc6ac20054a361eaff48e02",
@@ -149,6 +149,24 @@ function checkContextBudget(args) {
149
149
  }),
150
150
  };
151
151
  }
152
+ const rawMetricsOutcome = contextObj['metrics_outcome'];
153
+ if (rawMetricsOutcome !== undefined && rawMetricsOutcome !== null) {
154
+ if (!constants_js_1.VALID_METRICS_OUTCOME.includes(rawMetricsOutcome)) {
155
+ const details = {
156
+ kind: 'context_invalid_metrics_outcome',
157
+ tool: args.tool,
158
+ invalidValue: String(rawMetricsOutcome),
159
+ validValues: [...constants_js_1.VALID_METRICS_OUTCOME],
160
+ };
161
+ return {
162
+ ok: false,
163
+ error: (0, types_js_1.errNotRetryable)('VALIDATION_ERROR', `context.metrics_outcome has invalid value "${String(rawMetricsOutcome)}" for ${args.tool}. Valid values: ${constants_js_1.VALID_METRICS_OUTCOME.map(v => `"${v}"`).join(', ')}.`, {
164
+ suggestion: 'Set metrics_outcome to one of the valid enum values listed in validValues.',
165
+ details: details,
166
+ }),
167
+ };
168
+ }
169
+ }
152
170
  return { ok: true };
153
171
  }
154
172
  function collectArtifactsForEvaluation(args) {
@@ -136,7 +136,7 @@ function computeWorkflowStaleness(stamp, currentVersion) {
136
136
  if (stamp === undefined) {
137
137
  return {
138
138
  level: 'possible',
139
- reason: 'This workflow has not been validated against the authoring spec via workflow-for-workflows.',
139
+ reason: 'This workflow has not been validated against the authoring spec via wr.workflow-for-workflows.',
140
140
  };
141
141
  }
142
142
  if (stamp === currentVersion) {
@@ -61,7 +61,7 @@ exports.START_WORKFLOW_PROTOCOL = {
61
61
  'Only pass context on later continue_workflow calls if facts changed.',
62
62
  ],
63
63
  examplePayload: {
64
- workflowId: 'coding-task-workflow-agentic',
64
+ workflowId: 'wr.coding-task',
65
65
  workspacePath: '/Users/you/git/my-project',
66
66
  goal: 'implement OAuth refresh token rotation',
67
67
  },
@@ -77,7 +77,7 @@ exports.START_WORKFLOW_PROTOCOL = {
77
77
  'Pass goal on every call. A short sentence describing what you are trying to accomplish.',
78
78
  ],
79
79
  examplePayload: {
80
- workflowId: 'coding-task-workflow-agentic',
80
+ workflowId: 'wr.coding-task',
81
81
  workspacePath: '/Users/you/git/my-project',
82
82
  goal: 'implement OAuth refresh token rotation',
83
83
  },
@@ -86,3 +86,5 @@ export declare const AUTONOMY_MODE: {
86
86
  readonly FULL_AUTO_STOP_ON_USER_DEPS: "full_auto_stop_on_user_deps";
87
87
  };
88
88
  export type AutonomyModeV1 = typeof AUTONOMY_MODE[keyof typeof AUTONOMY_MODE];
89
+ export declare const VALID_METRICS_OUTCOME: readonly ["success", "partial", "abandoned", "error"];
90
+ export type MetricsOutcome = (typeof VALID_METRICS_OUTCOME)[number];
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AUTONOMY_MODE = exports.ADVANCE_INTENT = exports.MANIFEST_KIND = exports.EDGE_CAUSE = exports.ADVANCE_OUTCOME = exports.ENGINE_STATE = exports.EDGE_KIND = exports.PAYLOAD_KIND = exports.OUTPUT_CHANNEL = exports.EVENT_KIND = exports.DELIMITER_SAFE_ID_PATTERN = exports.SHA256_DIGEST_PATTERN = exports.MAX_RESUME_PREVIEW_BYTES = exports.RECOVERY_BUDGET_BYTES = exports.TRUNCATION_MARKER = exports.DEFAULT_RETRY_AFTER_MS = exports.SESSION_LOCK_RETRY_AFTER_MS = exports.MAX_OBSERVATION_PATH_LENGTH = exports.MAX_OBSERVATION_SHORT_STRING_LENGTH = exports.MAX_CONTEXT_DEPTH = exports.MAX_CONTEXT_BYTES = exports.MAX_VALIDATION_SUGGESTIONS_BYTES = exports.MAX_VALIDATION_ISSUES_BYTES = exports.MAX_VALIDATION_SUGGESTION_ITEM_BYTES = exports.MAX_VALIDATION_ISSUE_ITEM_BYTES = exports.MAX_OUTPUT_NOTES_MARKDOWN_BYTES = exports.MAX_DECISION_TRACE_TOTAL_BYTES = exports.MAX_DECISION_TRACE_ENTRY_SUMMARY_BYTES = exports.MAX_DECISION_TRACE_ENTRIES = exports.MAX_BLOCKER_SUGGESTED_FIX_BYTES = exports.MAX_BLOCKER_MESSAGE_BYTES = exports.MAX_BLOCKERS = void 0;
3
+ exports.VALID_METRICS_OUTCOME = exports.AUTONOMY_MODE = exports.ADVANCE_INTENT = exports.MANIFEST_KIND = exports.EDGE_CAUSE = exports.ADVANCE_OUTCOME = exports.ENGINE_STATE = exports.EDGE_KIND = exports.PAYLOAD_KIND = exports.OUTPUT_CHANNEL = exports.EVENT_KIND = exports.DELIMITER_SAFE_ID_PATTERN = exports.SHA256_DIGEST_PATTERN = exports.MAX_RESUME_PREVIEW_BYTES = exports.RECOVERY_BUDGET_BYTES = exports.TRUNCATION_MARKER = exports.DEFAULT_RETRY_AFTER_MS = exports.SESSION_LOCK_RETRY_AFTER_MS = exports.MAX_OBSERVATION_PATH_LENGTH = exports.MAX_OBSERVATION_SHORT_STRING_LENGTH = exports.MAX_CONTEXT_DEPTH = exports.MAX_CONTEXT_BYTES = exports.MAX_VALIDATION_SUGGESTIONS_BYTES = exports.MAX_VALIDATION_ISSUES_BYTES = exports.MAX_VALIDATION_SUGGESTION_ITEM_BYTES = exports.MAX_VALIDATION_ISSUE_ITEM_BYTES = exports.MAX_OUTPUT_NOTES_MARKDOWN_BYTES = exports.MAX_DECISION_TRACE_TOTAL_BYTES = exports.MAX_DECISION_TRACE_ENTRY_SUMMARY_BYTES = exports.MAX_DECISION_TRACE_ENTRIES = exports.MAX_BLOCKER_SUGGESTED_FIX_BYTES = exports.MAX_BLOCKER_MESSAGE_BYTES = exports.MAX_BLOCKERS = void 0;
4
4
  exports.MAX_BLOCKERS = 10;
5
5
  exports.MAX_BLOCKER_MESSAGE_BYTES = 512;
6
6
  exports.MAX_BLOCKER_SUGGESTED_FIX_BYTES = 1024;
@@ -82,3 +82,4 @@ exports.AUTONOMY_MODE = {
82
82
  FULL_AUTO_NEVER_STOP: 'full_auto_never_stop',
83
83
  FULL_AUTO_STOP_ON_USER_DEPS: 'full_auto_stop_on_user_deps',
84
84
  };
85
+ exports.VALID_METRICS_OUTCOME = ['success', 'partial', 'abandoned', 'error'];
@@ -40,7 +40,7 @@ function projectSessionMetricsV2(events) {
40
40
  const durationMs = typeof d.durationMs === 'number' && Number.isFinite(d.durationMs) ? d.durationMs : undefined;
41
41
  const captureConfidence = d.captureConfidence === 'high' ? 'high' : 'none';
42
42
  const outcomeRaw = metricsContext['metrics_outcome'];
43
- const outcome = outcomeRaw === 'success' || outcomeRaw === 'partial' || outcomeRaw === 'abandoned' || outcomeRaw === 'error'
43
+ const outcome = constants_js_1.VALID_METRICS_OUTCOME.includes(outcomeRaw)
44
44
  ? outcomeRaw
45
45
  : null;
46
46
  const prNumbers = [];
@@ -240,7 +240,7 @@ Profile selection guide:
240
240
  | `"research"` | Workflow produces a finding or recommendation but no commits | Outcome-only reminder on final step only |
241
241
  | `"none"` or absent | Meta-workflows, utilities, authoring tools | No injection -- existing behavior unchanged |
242
242
 
243
- The engine does NOT derive the profile from tags automatically. Authors must set this field explicitly. When using `workflow-for-workflows` to author or modernize a workflow, the `phase-7b` step will prompt you for this decision.
243
+ The engine does NOT derive the profile from tags automatically. Authors must set this field explicitly. When using `wr.workflow-for-workflows` to author or modernize a workflow, the `phase-7b` step will prompt you for this decision.
244
244
 
245
245
  **Final step detection**: The engine injects the final-step footer on the last top-level step, or on the exit step of a loop that is the last top-level step. A loop in a non-terminal position does not trigger the final-step footer on its exit step.
246
246
 
@@ -551,11 +551,11 @@ To keep authoring simple:
551
551
 
552
552
  Workflows can drift out of sync with the authoring spec they were written against. WorkRail surfaces this as a `staleness` signal in `list_workflows` and `inspect_workflow` output.
553
553
 
554
- **How it works:** Workflows carry an optional `validatedAgainstSpecVersion` field stamped by `workflow-for-workflows` after the quality gate passes. The engine compares this against the current `spec/authoring-spec.json` version at list/inspect time and returns:
554
+ **How it works:** Workflows carry an optional `validatedAgainstSpecVersion` field stamped by `wr.workflow-for-workflows` after the quality gate passes. The engine compares this against the current `spec/authoring-spec.json` version at list/inspect time and returns:
555
555
 
556
556
  - `none` — workflow was validated against the current spec version
557
557
  - `likely` — spec was updated since the workflow was last reviewed
558
- - `possible` — workflow has never been run through `workflow-for-workflows`
558
+ - `possible` — workflow has never been run through `wr.workflow-for-workflows`
559
559
 
560
560
  **Stamping a workflow:**
561
561
 
@@ -564,7 +564,7 @@ npm run stamp-workflow -- workflows/my-workflow.json
564
564
  git add workflows/my-workflow.json && git commit -m "chore: stamp workflow"
565
565
  ```
566
566
 
567
- The stamp must be committed to take effect. The `workflow-for-workflows` Phase 7 step includes a reminder to do this.
567
+ The stamp must be committed to take effect. The `wr.workflow-for-workflows` Phase 7 step includes a reminder to do this.
568
568
 
569
569
  **Visibility:** By default, the staleness signal is only shown for user-owned/imported workflows (`personal`, `rooted_sharing`, `external`). Built-in and legacy_project workflows are excluded. Set `WORKRAIL_DEV=1` to see staleness for all categories (useful for catalog maintenance).
570
570
 
@@ -117,7 +117,7 @@ Structured migration workflow for moving code between platforms (Android to iOS,
117
117
 
118
118
  Since you've created workflows yourself, these changes are directly relevant.
119
119
 
120
- ### `workflow-for-workflows.v2.json` was rebuilt
120
+ ### `wr.workflow-for-workflows.v2.json` was rebuilt
121
121
 
122
122
  The workflow used to create or modernize other workflows was significantly redesigned. The full phase structure now includes:
123
123
 
@@ -179,12 +179,12 @@ A visual catalog of every available workflow. Eight category filter pills. Click
179
179
  WorkRail can now detect when a workflow hasn't been reviewed against the current authoring spec. Three signal levels:
180
180
 
181
181
  - `none` -- validated against the current spec (has a version stamp and it's current)
182
- - `possible` -- no version stamp (was never run through `workflow-for-workflows`)
182
+ - `possible` -- no version stamp (was never run through `wr.workflow-for-workflows`)
183
183
  - `likely` -- has a stamp, but the spec has been updated since the workflow was last reviewed
184
184
 
185
185
  This shows up in `list_workflows` output (agents see it) and in the CI registry validation check. It's shown only for non-built-in workflows -- built-in workflows ship with their own quality process and don't show staleness signals.
186
186
 
187
- **What this means for your team:** Your team's existing workflows will show as `possible` (no stamp) until they're run through `workflow-for-workflows.v2.json`. That's expected -- it's not an error, just a signal that they haven't been through the new quality gate. Over time, as you modernize them, they'll show `none`.
187
+ **What this means for your team:** Your team's existing workflows will show as `possible` (no stamp) until they're run through `wr.workflow-for-workflows.v2.json`. That's expected -- it's not an error, just a signal that they haven't been through the new quality gate. Over time, as you modernize them, they'll show `none`.
188
188
 
189
189
  ---
190
190
 
@@ -407,7 +407,7 @@ When `isComplete: true` is returned, summarize all work done across the workflow
407
407
  After creating this file, the agent becomes available via the Agent tool:
408
408
 
409
409
  ```
410
- Agent(subagent_type="workrail-executor", prompt="Start the bug-investigation-agentic workflow...")
410
+ Agent(subagent_type="workrail-executor", prompt="Start the wr.bug-investigation workflow...")
411
411
  ```
412
412
 
413
413
  ### Cursor
@@ -59,7 +59,7 @@ Must stay consistent with:
59
59
  - `src/v2/durable-core/schemas/artifacts/` (typed artifact schemas)
60
60
  - `workflows/wr.discovery.json` (Phase 7 -- if emitting artifact)
61
61
  - `workflows/wr.shaping.json` (Step 1 -- if adding file search)
62
- - `workflows/coding-task-workflow-agentic.json` (Phase 0.5 -- no changes expected)
62
+ - `workflows/wr.coding-task.json` (Phase 0.5 -- no changes expected)
63
63
 
64
64
  ---
65
65
 
@@ -73,7 +73,7 @@ WorkTrain sessions are fully isolated. Each spawned session starts from the work
73
73
 
74
74
  **1. File-based handoff (wr.shaping -> coding):**
75
75
  - `wr.shaping` Step 9 writes `.workrail/current-pitch.md` at the workspace path
76
- - `coding-task-workflow-agentic` Phase 0.5 actively searches for upstream docs via repo search, WebFetch, MCP integrations
76
+ - `wr.coding-task` Phase 0.5 actively searches for upstream docs via repo search, WebFetch, MCP integrations
77
77
  - Phase 0.5 would find `.workrail/current-pitch.md` automatically
78
78
  - **Status: effectively already works** -- no coordinator intervention needed for Shaping->Coding
79
79
 
@@ -16,9 +16,9 @@
16
16
 
17
17
  3. **Monolithic coordinator vs per-mode decomposition**: `pr-review.ts` is 1462 lines for one pipeline mode. Five modes in one file would be unmanageable. The right architecture decomposes into mode files with a thin dispatcher -- but this requires deciding the seam deliberately.
18
18
 
19
- 4. **`recommendedPipeline` verbatim vs advisory**: If classify-task-workflow's pipeline output is authoritative, the coordinator cannot apply static overrides. If advisory, the coordinator re-implements routing and classify-task's rules become redundant for common cases.
19
+ 4. **`recommendedPipeline` verbatim vs advisory**: If wr.classify-task's pipeline output is authoritative, the coordinator cannot apply static overrides. If advisory, the coordinator re-implements routing and classify-task's rules become redundant for common cases.
20
20
 
21
- 5. **Phase 0.5 vs coordinator routing for upstream context**: `coding-task-workflow-agentic` Phase 0.5 auto-detects `pitch.md`. The coordinator's "should I skip shaping?" routing decision partially overlaps with this detection. They must agree.
21
+ 5. **Phase 0.5 vs coordinator routing for upstream context**: `wr.coding-task` Phase 0.5 auto-detects `pitch.md`. The coordinator's "should I skip shaping?" routing decision partially overlaps with this detection. They must agree.
22
22
 
23
23
  ### What the codebase already solves (and how)
24
24
 
@@ -29,12 +29,12 @@
29
29
  - Escalation-first: every failure produces `escalated: true` + `escalationReason`, never silent substitution
30
30
  - TRACE log before acting on routing decision
31
31
 
32
- **`classify-task-workflow.json`:**
32
+ **`wr.classify-task.json`:**
33
33
  - Exists as of v3.40.0. Single LLM step, no tools, outputs `recommendedPipeline` as ordered workflow ID array
34
34
  - Output format: structured text block with `recommendedPipeline: ["...", "..."]` line
35
35
  - Note: `spawn_agent` does NOT return artifacts (v3.40.0 limitation #5) -- output must be read via `spawnSession` + `awaitSessions` + `getAgentResult` + note parsing
36
36
 
37
- **Phase 0.5 (`coding-task-workflow-agentic`):**
37
+ **Phase 0.5 (`wr.coding-task`):**
38
38
  - Already detects `pitch.md` and sets `solutionFixed=true`, skipping design phases
39
39
  - The coordinator's "IMPLEMENT mode" (skip discovery/shaping) and Phase 0.5 are complementary, not conflicting
40
40
 
@@ -78,7 +78,7 @@ From CLAUDE.md (stated) and pr-review.ts (practiced):
78
78
  - `src/cli-worktrain.ts` -- needs `worktrain run pipeline` subcommand wiring
79
79
  - `src/coordinators/pr-review.ts` -- must remain unchanged; new coordinator is additive
80
80
  - `src/trigger/types.ts` -- if Candidate D's `pipelineMode` field is added; otherwise unchanged
81
- - `workflows/classify-task-workflow.json` -- coordinator depends on its note output format; format changes break parsing
81
+ - `workflows/wr.classify-task.json` -- coordinator depends on its note output format; format changes break parsing
82
82
  - `src/coordinators/routing/route-task.ts` (new) -- pure routing function; all mode selection logic lives here
83
83
  - `src/coordinators/modes/*.ts` (new files) -- each mode's pipeline execution logic
84
84
  - Test suite: each mode coordinator needs its own unit tests with `CoordinatorDeps` fakes
@@ -110,8 +110,8 @@ type PipelineMode =
110
110
  **Per-mode pipelines:**
111
111
  - REVIEW_ONLY: `mr-review-workflow.agentic.v2` -> route by verdict
112
112
  - QUICK_REVIEW: same + light model config, no arch audit override
113
- - IMPLEMENT: `coding-task-workflow-agentic` (Phase 0.5 picks up pitch) -> PR -> review -> merge
114
- - FULL: `wr.discovery` -> `wr.shaping` -> `coding-task-workflow-agentic` -> PR -> review -> merge
113
+ - IMPLEMENT: `wr.coding-task` (Phase 0.5 picks up pitch) -> PR -> review -> merge
114
+ - FULL: `wr.discovery` -> `wr.shaping` -> `wr.coding-task` -> PR -> review -> merge
115
115
 
116
116
  **Tensions resolved:** determinism, YAGNI, no LLM latency.
117
117
  **Tensions accepted:** all ambiguous tasks fall to FULL (wasteful for Medium complexity tasks that don't need full discovery).
@@ -125,14 +125,14 @@ type PipelineMode =
125
125
 
126
126
  ---
127
127
 
128
- ### Candidate B: classify-task-workflow as authoritative source
128
+ ### Candidate B: wr.classify-task as authoritative source
129
129
 
130
- **Summary:** Always spawn `classify-task-workflow` first, parse `recommendedPipeline` output, execute the returned workflow sequence. Pipeline modes are not named at the coordinator level.
130
+ **Summary:** Always spawn `wr.classify-task` first, parse `recommendedPipeline` output, execute the returned workflow sequence. Pipeline modes are not named at the coordinator level.
131
131
 
132
132
  **Architecture:**
133
133
  ```typescript
134
134
  async function routeTask(goal, workspace, deps): Promise<Result<readonly string[], string>> {
135
- const handle = await deps.spawnSession('classify-task-workflow', `Classify: ${goal}`, workspace);
135
+ const handle = await deps.spawnSession('wr.classify-task', `Classify: ${goal}`, workspace);
136
136
  await deps.awaitSessions([handle], CLASSIFY_TIMEOUT_MS); // 3 minutes max
137
137
  const agentResult = await deps.getAgentResult(handle);
138
138
  return parseRecommendedPipeline(agentResult.recapMarkdown);
@@ -141,12 +141,12 @@ async function routeTask(goal, workspace, deps): Promise<Result<readonly string[
141
141
 
142
142
  `parseRecommendedPipeline` is a pure function parsing the text block (two-tier: JSON array first, regex fallback).
143
143
 
144
- **Fallback:** if parsing fails, default to `['wr.discovery', 'coding-task-workflow-agentic', 'mr-review-workflow.agentic.v2']`.
144
+ **Fallback:** if parsing fails, default to `['wr.discovery', 'wr.coding-task', 'mr-review-workflow.agentic.v2']`.
145
145
 
146
146
  **Tensions resolved:** intelligent routing for all tasks including ambiguous ones; single source of truth for pipeline selection rules.
147
147
  **Tensions accepted:** non-deterministic; 5-15 second LLM latency per dispatch; no typed `PipelineMode` discriminated union (pipeline is a string[] at coordinator level).
148
- **Boundary:** classify-task-workflow is the routing authority; coordinator is a runner.
149
- **Failure mode:** classify-task-workflow misclassifies a PR-only task and returns discovery+coding phases, wasting 30+ minutes. Recovery: add a pre-check for PR number before spawning classify-task (hybrid).
148
+ **Boundary:** wr.classify-task is the routing authority; coordinator is a runner.
149
+ **Failure mode:** wr.classify-task misclassifies a PR-only task and returns discovery+coding phases, wasting 30+ minutes. Recovery: add a pre-check for PR number before spawning classify-task (hybrid).
150
150
  **Repo pattern:** departs from determinism-over-cleverness principle. No named discriminated union.
151
151
  **Gain:** routing rules live in a workflow file -- updatable without code deployment.
152
152
  **Give up:** determinism, transparency, typed modes, dispatch speed for obvious cases.
@@ -157,7 +157,7 @@ async function routeTask(goal, workspace, deps): Promise<Result<readonly string[
157
157
 
158
158
  ### Candidate C: Static-first with LLM fallback (hybrid, recommended for routing)
159
159
 
160
- **Summary:** Two-tier `routeTask()`: Tier 1 applies static rules (pure, covers 80% of cases); Tier 2 falls back to classify-task-workflow for ambiguous tasks and returns a `CLASSIFY_AND_RUN` mode.
160
+ **Summary:** Two-tier `routeTask()`: Tier 1 applies static rules (pure, covers 80% of cases); Tier 2 falls back to wr.classify-task for ambiguous tasks and returns a `CLASSIFY_AND_RUN` mode.
161
161
 
162
162
  **PipelineMode type (6 variants):**
163
163
  ```typescript
@@ -180,7 +180,7 @@ async function routeTask(
180
180
  // Tier 1: static (pure, no I/O except filesystem check for pitch.md)
181
181
  const staticMode = applyStaticRules(goal, workspace);
182
182
  if (staticMode !== null) return ok(staticMode);
183
- // Tier 2: classify-task-workflow
183
+ // Tier 2: wr.classify-task
184
184
  const classified = await runClassification(goal, workspace, deps);
185
185
  if (classified.kind === 'err') return err(`classification failed: ${classified.error}`);
186
186
  return ok({ kind: 'CLASSIFY_AND_RUN', classifiedPipeline: classified.value, goal });
@@ -293,7 +293,7 @@ export async function runAdaptivePipeline(
293
293
 
294
294
  ### Recommendation: Candidate C (routing mechanism) + Candidate E (architecture)
295
295
 
296
- **Routing (C):** Two-tier static-first with LLM fallback. Static rules cover the 4 well-defined cases at zero cost and latency. `CLASSIFY_AND_RUN` handles genuinely ambiguous tasks via classify-task-workflow. This precisely mirrors the `parseFindingsFromNotes` two-tier strategy already established in `pr-review.ts`.
296
+ **Routing (C):** Two-tier static-first with LLM fallback. Static rules cover the 4 well-defined cases at zero cost and latency. `CLASSIFY_AND_RUN` handles genuinely ambiguous tasks via wr.classify-task. This precisely mirrors the `parseFindingsFromNotes` two-tier strategy already established in `pr-review.ts`.
297
297
 
298
298
  **Architecture (E):** Per-mode coordinator files with thin dispatcher. Each mode file follows `pr-review.ts` independently. The dispatcher's `switch(mode.kind)` is exhaustive with `assertNever`. Adding a new mode is additive.
299
299
 
@@ -301,7 +301,7 @@ export async function runAdaptivePipeline(
301
301
 
302
302
  ### Why not A (pure static)?
303
303
 
304
- Candidate A is simpler but all tasks without static signals fall to FULL (wr.discovery + wr.shaping + coding). A genuinely vague idea needs FULL. But a Medium complexity coding task with no pitch.md and no PR number -- e.g., `"refactor auth.ts to use Result types"` -- also falls to FULL, running unnecessary discovery phases. Candidate C covers this case with classify-task-workflow returning `['coding-task-workflow-agentic', 'mr-review-workflow.agentic.v2']`.
304
+ Candidate A is simpler but all tasks without static signals fall to FULL (wr.discovery + wr.shaping + coding). A genuinely vague idea needs FULL. But a Medium complexity coding task with no pitch.md and no PR number -- e.g., `"refactor auth.ts to use Result types"` -- also falls to FULL, running unnecessary discovery phases. Candidate C covers this case with wr.classify-task returning `['wr.coding-task', 'mr-review-workflow.agentic.v2']`.
305
305
 
306
306
  ### Why not B (pure LLM)?
307
307
 
@@ -319,7 +319,7 @@ Non-deterministic routing is unacceptable for the coordinator. A PR review task
319
319
 
320
320
  ### Pivot conditions
321
321
 
322
- 1. If classify-task-workflow format drifts and `parseRecommendedPipeline` fails more than 10% of the time -> pivot to pure static (Candidate A) and accept FULL as default for ambiguous tasks
322
+ 1. If wr.classify-task format drifts and `parseRecommendedPipeline` fails more than 10% of the time -> pivot to pure static (Candidate A) and accept FULL as default for ambiguous tasks
323
323
  2. If trigger operators need deterministic routing for automated workflows -> add `pipelineMode` to TriggerDefinition (Candidate D addition)
324
324
  3. If context-passing agent's design requires structured handoff data from routing to mode executors -> add a `contextBundle` field to mode types (implementation change, not routing design change)
325
325
 
@@ -151,6 +151,6 @@ Even though not called at MVP, having the pure function ready preserves the upgr
151
151
 
152
152
  1. **wr.discovery output standardization**: the routing design assumes wr.discovery notes are injected by the coordinator as `assembledContextSummary` for wr.shaping. But wr.discovery's `designDocPath` output location is not standardized (finding from context-passing agent's doc). The FULL mode executor must parse `lastStepNotes` from the discovery session to build the shaping context -- this is per the context-passing agent's Candidate D (coordinator-injected text). This concern is correctly owned by the context-passing design, not the routing design.
153
153
 
154
- 2. **classify-task-workflow format stability**: if `parseRecommendedPipeline()` is written as a pure function now, it has no tests against real classify-task output. The function should include an integration test stub that documents the expected format.
154
+ 2. **wr.classify-task format stability**: if `parseRecommendedPipeline()` is written as a pure function now, it has no tests against real classify-task output. The function should include an integration test stub that documents the expected format.
155
155
 
156
156
  3. **REVIEW_ONLY vs pr-review coordinator**: the existing `worktrain run pr-review` command already provides REVIEW_ONLY+QUICK_REVIEW behavior. The new `worktrain run pipeline --mode review_only` should either (a) delegate to pr-review coordinator, or (b) reimplement the same logic in `modes/review-only.ts`. Recommendation: (a) delegate -- avoid duplicating the fix-agent loop logic. Document this delegation explicitly.