@agwab/pi-workflow 0.2.1 → 0.4.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.
Files changed (119) hide show
  1. package/README.md +3 -1
  2. package/dist/artifact-graph-runtime.d.ts +1 -1
  3. package/dist/artifact-graph-runtime.js +10 -5
  4. package/dist/artifact-graph-schema.js +127 -5
  5. package/dist/compiler.js +52 -19
  6. package/dist/dynamic-generated-task-runtime.js +3 -1
  7. package/dist/dynamic-profiles.d.ts +1 -1
  8. package/dist/engine-run-graph.d.ts +3 -0
  9. package/dist/engine-run-graph.js +194 -4
  10. package/dist/engine.d.ts +5 -0
  11. package/dist/engine.js +389 -41
  12. package/dist/extension.d.ts +2 -1
  13. package/dist/extension.js +30 -8
  14. package/dist/index.d.ts +11 -3
  15. package/dist/index.js +6 -1
  16. package/dist/prompt-json.d.ts +7 -0
  17. package/dist/prompt-json.js +13 -0
  18. package/dist/roles.d.ts +1 -1
  19. package/dist/roles.js +5 -8
  20. package/dist/store.d.ts +20 -1
  21. package/dist/store.js +139 -35
  22. package/dist/strings.d.ts +11 -0
  23. package/dist/strings.js +24 -0
  24. package/dist/subagent-backend.js +710 -40
  25. package/dist/types.d.ts +107 -1
  26. package/dist/verification-ontology.d.ts +31 -0
  27. package/dist/verification-ontology.js +66 -0
  28. package/dist/workflow-artifact-tool.js +5 -6
  29. package/dist/workflow-artifacts.d.ts +7 -0
  30. package/dist/workflow-artifacts.js +55 -4
  31. package/dist/workflow-fetch-cache-extension.d.ts +1 -0
  32. package/dist/workflow-fetch-cache-extension.js +57 -9
  33. package/dist/workflow-metrics.d.ts +113 -0
  34. package/dist/workflow-metrics.js +272 -0
  35. package/dist/workflow-output-artifacts.js +5 -3
  36. package/dist/workflow-partial-output.d.ts +45 -0
  37. package/dist/workflow-partial-output.js +205 -0
  38. package/dist/workflow-progress-health.js +42 -10
  39. package/dist/workflow-runtime.js +10 -1
  40. package/dist/workflow-view.js +3 -1
  41. package/dist/workflow-web-source-extension.js +194 -52
  42. package/dist/workflow-web-source.d.ts +2 -1
  43. package/dist/workflow-web-source.js +109 -30
  44. package/docs/usage.md +76 -29
  45. package/node_modules/@agwab/pi-subagent/README.md +3 -3
  46. package/node_modules/@agwab/pi-subagent/api.mjs +1 -0
  47. package/node_modules/@agwab/pi-subagent/docs/usage.md +63 -12
  48. package/node_modules/@agwab/pi-subagent/package.json +2 -2
  49. package/node_modules/@agwab/pi-subagent/src/api.ts +54 -1
  50. package/node_modules/@agwab/pi-subagent/src/artifacts/registry.ts +9 -4
  51. package/node_modules/@agwab/pi-subagent/src/artifacts/result.ts +8 -0
  52. package/node_modules/@agwab/pi-subagent/src/core/constants.ts +9 -0
  53. package/node_modules/@agwab/pi-subagent/src/core/validation.ts +21 -0
  54. package/node_modules/@agwab/pi-subagent/src/index.ts +1046 -576
  55. package/node_modules/@agwab/pi-subagent/src/orchestrate/async.ts +279 -156
  56. package/node_modules/@agwab/pi-subagent/src/orchestrate/interrupt.ts +165 -89
  57. package/node_modules/@agwab/pi-subagent/src/orchestrate/reconcile.ts +111 -65
  58. package/node_modules/@agwab/pi-subagent/src/orchestrate/run-ref.ts +219 -0
  59. package/node_modules/@agwab/pi-subagent/src/orchestrate/run.ts +88 -8
  60. package/node_modules/@agwab/pi-subagent/src/orchestrate/status.ts +614 -298
  61. package/node_modules/@agwab/pi-subagent/src/panel.ts +1356 -560
  62. package/node_modules/@agwab/pi-subagent/src/runners/headless-model.ts +53 -5
  63. package/node_modules/@agwab/pi-subagent/src/runners/tmux.ts +13 -6
  64. package/package.json +2 -2
  65. package/skills/workflow-guide/SKILL.md +1 -0
  66. package/src/artifact-graph-runtime.ts +19 -13
  67. package/src/artifact-graph-schema.ts +143 -3
  68. package/src/cli.mjs +52 -0
  69. package/src/compiler.ts +63 -18
  70. package/src/dynamic-generated-task-runtime.ts +3 -1
  71. package/src/dynamic-profiles.ts +1 -1
  72. package/src/engine-run-graph.ts +246 -4
  73. package/src/engine.ts +545 -38
  74. package/src/extension.ts +36 -6
  75. package/src/index.ts +52 -1
  76. package/src/prompt-json.ts +13 -0
  77. package/src/roles.ts +6 -9
  78. package/src/store.ts +194 -42
  79. package/src/strings.ts +38 -0
  80. package/src/subagent-backend.ts +921 -62
  81. package/src/types.ts +116 -2
  82. package/src/verification-ontology.ts +88 -0
  83. package/src/workflow-artifact-tool.ts +5 -7
  84. package/src/workflow-artifacts.ts +83 -3
  85. package/src/workflow-fetch-cache-extension.ts +78 -13
  86. package/src/workflow-metrics.ts +478 -0
  87. package/src/workflow-output-artifacts.ts +5 -3
  88. package/src/workflow-partial-output.ts +299 -0
  89. package/src/workflow-progress-health.ts +47 -15
  90. package/src/workflow-runtime.ts +18 -2
  91. package/src/workflow-view.ts +2 -1
  92. package/src/workflow-web-source-extension.ts +654 -232
  93. package/src/workflow-web-source.ts +153 -39
  94. package/workflows/README.md +7 -25
  95. package/workflows/deep-research/batched-verification.spec.json +253 -0
  96. package/workflows/deep-research/helpers/batch-verification-candidates.mjs +136 -0
  97. package/workflows/deep-research/helpers/claim-evidence-gate.mjs +229 -36
  98. package/workflows/deep-research/helpers/final-audit-packet.mjs +1 -4
  99. package/workflows/deep-research/helpers/normalize-input-packet.mjs +81 -2
  100. package/workflows/deep-research/helpers/render-executive.mjs +40 -26
  101. package/workflows/deep-research/helpers/sanitize-verification-candidates.mjs +89 -15
  102. package/workflows/deep-research/helpers/shadow-select-verification.mjs +229 -0
  103. package/workflows/deep-research/helpers/verification-ontology.mjs +77 -0
  104. package/workflows/deep-research/schemas/deep-research-executive-render-control.schema.json +3 -3
  105. package/workflows/deep-research/schemas/deep-research-research-questions-control.schema.json +38 -0
  106. package/workflows/deep-research/schemas/deep-research-sanitize-claims-control.schema.json +63 -0
  107. package/workflows/deep-research/schemas/deep-research-verify-claims-batch-control.schema.json +47 -0
  108. package/workflows/deep-research/schemas/deep-research-verify-claims-control.schema.json +13 -3
  109. package/workflows/deep-research/spec.json +32 -12
  110. package/workflows/impact-review/spec.json +3 -3
  111. package/workflows/spec-review/helpers/spec-review-pipeline.mjs +1 -8
  112. package/dist/dynamic-loader.d.ts +0 -25
  113. package/dist/dynamic-loader.js +0 -13
  114. package/skills/workflow-guide/scaffolds/dag-required-reads/spec.json.validate.stderr +0 -0
  115. package/skills/workflow-guide/scaffolds/dag-required-reads/spec.json.validate.stdout +0 -13
  116. package/src/dynamic-loader.ts +0 -49
  117. package/workflows/impact-review/schemas/docs-release-impact-control.schema.json +0 -42
  118. package/workflows/impact-review/schemas/security-performance-impact-control.schema.json +0 -42
  119. package/workflows/impact-review/schemas/state-data-impact-control.schema.json +0 -42
@@ -92,6 +92,118 @@ export function reconcileDynamicGeneratedRunRecords(cwd, run, compiledFlow) {
92
92
  }
93
93
  return changed;
94
94
  }
95
+ export function reconcileForeachGeneratedRunRecords(cwd, run, compiledFlow) {
96
+ let changed = false;
97
+ const compiledSpecIds = new Set(compiledFlow.tasks.map((task) => compiledTaskSpecId(task)));
98
+ const compiledTaskBySpecId = new Map(compiledFlow.tasks.map((task) => [compiledTaskSpecId(task), task]));
99
+ const placeholderToGeneratedSpecIds = new Map();
100
+ const streamingPlaceholderSpecIds = new Set();
101
+ for (const compiledTask of compiledFlow.tasks) {
102
+ const specId = compiledTaskSpecId(compiledTask);
103
+ if (compiledTask.foreach && foreachStreamingEnabled(compiledTask)) {
104
+ streamingPlaceholderSpecIds.add(specId);
105
+ }
106
+ const placeholderSpecId = foreachGeneratedPlaceholderSpecId(compiledTask, compiledFlow, specId);
107
+ if (!placeholderSpecId)
108
+ continue;
109
+ if (compiledTask.foreachGenerated?.placeholderSpecId !== placeholderSpecId) {
110
+ compiledTask.foreachGenerated = { placeholderSpecId };
111
+ changed = true;
112
+ }
113
+ const generated = placeholderToGeneratedSpecIds.get(placeholderSpecId) ?? [];
114
+ generated.push(specId);
115
+ placeholderToGeneratedSpecIds.set(placeholderSpecId, generated);
116
+ }
117
+ if (placeholderToGeneratedSpecIds.size === 0)
118
+ return changed;
119
+ const filteredRunTasks = [];
120
+ const seenGeneratedSpecIds = new Set();
121
+ for (const task of run.tasks) {
122
+ const generatedSpecIds = placeholderToGeneratedSpecIds.get(task.specId);
123
+ let placeholderSpecId = foreachGeneratedPlaceholderSpecId(task, compiledFlow, task.specId);
124
+ if (generatedSpecIds && !placeholderSpecId) {
125
+ const compiledTask = compiledTaskBySpecId.get(task.specId);
126
+ if (compiledTask?.foreach &&
127
+ streamingPlaceholderSpecIds.has(task.specId)) {
128
+ filteredRunTasks.push(task);
129
+ continue;
130
+ }
131
+ if (generatedSpecIds.includes(task.specId)) {
132
+ placeholderSpecId = task.specId;
133
+ task.foreachGenerated = { placeholderSpecId };
134
+ changed = true;
135
+ }
136
+ else {
137
+ changed = true;
138
+ continue;
139
+ }
140
+ }
141
+ if (placeholderSpecId && !compiledSpecIds.has(task.specId)) {
142
+ changed = true;
143
+ continue;
144
+ }
145
+ if (placeholderSpecId && seenGeneratedSpecIds.has(task.specId)) {
146
+ changed = true;
147
+ continue;
148
+ }
149
+ if (placeholderSpecId) {
150
+ seenGeneratedSpecIds.add(task.specId);
151
+ if (task.foreachGenerated?.placeholderSpecId !== placeholderSpecId) {
152
+ task.foreachGenerated = { placeholderSpecId };
153
+ changed = true;
154
+ }
155
+ }
156
+ filteredRunTasks.push(task);
157
+ }
158
+ const runTaskBySpecId = new Map();
159
+ for (const task of filteredRunTasks) {
160
+ if (!runTaskBySpecId.has(task.specId))
161
+ runTaskBySpecId.set(task.specId, task);
162
+ }
163
+ const reordered = [];
164
+ const usedSpecIds = new Set();
165
+ let nextIndex = nextTaskRecordIndex({ ...run, tasks: filteredRunTasks });
166
+ for (const compiledTask of compiledFlow.tasks) {
167
+ const specId = compiledTaskSpecId(compiledTask);
168
+ const existing = runTaskBySpecId.get(specId);
169
+ if (existing) {
170
+ const placeholderSpecId = compiledTask.foreachGenerated?.placeholderSpecId;
171
+ if (placeholderSpecId &&
172
+ existing.foreachGenerated?.placeholderSpecId !== placeholderSpecId) {
173
+ existing.foreachGenerated = { placeholderSpecId };
174
+ changed = true;
175
+ }
176
+ reordered.push(existing);
177
+ usedSpecIds.add(specId);
178
+ continue;
179
+ }
180
+ if (!compiledTask.foreachGenerated)
181
+ continue;
182
+ const created = createTaskRunRecord(cwd, run.runId, compiledTask, nextIndex);
183
+ nextIndex += 1;
184
+ reordered.push(created);
185
+ usedSpecIds.add(specId);
186
+ changed = true;
187
+ }
188
+ for (const task of filteredRunTasks) {
189
+ if (!usedSpecIds.has(task.specId))
190
+ reordered.push(task);
191
+ }
192
+ if (!sameTaskRecordOrder(run.tasks, reordered))
193
+ changed = true;
194
+ for (const task of reordered) {
195
+ if (!task.dependsOn)
196
+ continue;
197
+ const replaced = replaceForeachGeneratedDependencies(task.dependsOn, placeholderToGeneratedSpecIds, streamingPlaceholderSpecIds);
198
+ if (!sameStringList(task.dependsOn, replaced)) {
199
+ task.dependsOn = replaced;
200
+ changed = true;
201
+ }
202
+ }
203
+ if (changed)
204
+ run.tasks = reordered;
205
+ return changed;
206
+ }
95
207
  export function assertRunTaskPositionalAlignment(run, compiledFlow) {
96
208
  const maxLength = Math.max(run.tasks.length, compiledFlow.tasks.length);
97
209
  for (let index = 0; index < maxLength; index += 1) {
@@ -141,6 +253,43 @@ export function compiledTaskSpecId(task) {
141
253
  const specId = task.specId;
142
254
  return typeof specId === "string" && specId.trim() !== "" ? specId : task.id;
143
255
  }
256
+ function foreachGeneratedPlaceholderSpecId(task, compiledFlow, specId) {
257
+ const explicit = task.foreachGenerated?.placeholderSpecId;
258
+ if (typeof explicit === "string" && explicit.trim() !== "")
259
+ return explicit;
260
+ if (task.foreach)
261
+ return undefined;
262
+ if (task.kind !== "foreach" || !task.stageId)
263
+ return undefined;
264
+ const placeholderSpecId = foreachPlaceholderSpecId(compiledFlow, task.stageId);
265
+ if (!placeholderSpecId || specId === placeholderSpecId)
266
+ return undefined;
267
+ return placeholderSpecId;
268
+ }
269
+ function foreachPlaceholderSpecId(compiledFlow, stageId) {
270
+ const stage = (compiledFlow.stages ?? []).find((candidate) => candidate?.id === stageId);
271
+ if (stage?.type !== "foreach")
272
+ return undefined;
273
+ return `${stageId}.item`;
274
+ }
275
+ function replaceForeachGeneratedDependencies(dependsOn, placeholderToGeneratedSpecIds, keepPlaceholderSpecIds = new Set()) {
276
+ const replaced = [];
277
+ for (const dep of dependsOn) {
278
+ const generatedSpecIds = placeholderToGeneratedSpecIds.get(dep);
279
+ if (generatedSpecIds) {
280
+ if (keepPlaceholderSpecIds.has(dep))
281
+ replaced.push(dep);
282
+ replaced.push(...generatedSpecIds);
283
+ }
284
+ else
285
+ replaced.push(dep);
286
+ }
287
+ return [...new Set(replaced)];
288
+ }
289
+ function sameStringList(left, right) {
290
+ return (left.length === right.length &&
291
+ left.every((value, index) => value === right[index]));
292
+ }
144
293
  function isLoopGeneratedCompiledTask(task, loopIds) {
145
294
  return Boolean((task.loopChild?.loopId && loopIds.has(task.loopChild.loopId)) ||
146
295
  (task.loopExhausted?.loopId && loopIds.has(task.loopExhausted.loopId)));
@@ -206,6 +355,29 @@ export function dependenciesReady(compiledTask, bySpecId, compiledFlow) {
206
355
  if (deps.length === 0)
207
356
  return true;
208
357
  const partial = stageSourcePolicy(compiledFlow, compiledTask.stageId ?? "") === "partial";
358
+ if (foreachStreamingEnabled(compiledTask)) {
359
+ let completedDependencyReady = false;
360
+ let runningDependencyMayHavePartialItems = false;
361
+ let allKnownDependenciesTerminal = true;
362
+ for (const dep of deps) {
363
+ const status = bySpecId.get(dep)?.status;
364
+ if (status === "completed") {
365
+ completedDependencyReady = true;
366
+ continue;
367
+ }
368
+ if (status && isTerminalTaskStatus(status)) {
369
+ if (!partial)
370
+ return false;
371
+ continue;
372
+ }
373
+ if (status === "running")
374
+ runningDependencyMayHavePartialItems = true;
375
+ allKnownDependenciesTerminal = false;
376
+ }
377
+ return (completedDependencyReady ||
378
+ runningDependencyMayHavePartialItems ||
379
+ allKnownDependenciesTerminal);
380
+ }
209
381
  return deps.every((dep) => {
210
382
  const status = bySpecId.get(dep)?.status;
211
383
  if (status === "completed")
@@ -215,6 +387,18 @@ export function dependenciesReady(compiledTask, bySpecId, compiledFlow) {
215
387
  return false;
216
388
  });
217
389
  }
390
+ export function foreachStreamingEnabled(compiledTask) {
391
+ const streaming = compiledTask.foreach?.from?.streaming;
392
+ return Boolean(streaming &&
393
+ typeof streaming === "object" &&
394
+ streaming.enabled === true);
395
+ }
396
+ export function foreachStreamingMinChunk(compiledTask) {
397
+ const value = compiledTask.foreach?.from?.streaming?.minChunk;
398
+ return typeof value === "number" && Number.isFinite(value) && value > 0
399
+ ? Math.floor(value)
400
+ : 1;
401
+ }
218
402
  export function buildForeachGeneratedTasks(template, runtimeTask, items) {
219
403
  const seen = new Set();
220
404
  const tasks = [];
@@ -228,14 +412,15 @@ export function buildForeachGeneratedTasks(template, runtimeTask, items) {
228
412
  seen.add(taskId);
229
413
  const specId = `${template.stageId}.${taskId}`;
230
414
  const itemText = formatForeachItem(item);
231
- const instructions = template.foreach.prompt.replace(/\$\{item\}/g, itemText);
415
+ const instructions = template.foreach.prompt.replace(/\$\{item\}/g, escapeReplacementText(itemText));
232
416
  const compiledPrompt = [
233
417
  template.foreach.injectRuntimeTask && runtimeTask
234
418
  ? `# Task\n\n${runtimeTask}`
235
419
  : undefined,
236
- `# Workflow Stage\n\nstage=${template.stageId}\ntype=foreach\nitem=${taskId}`,
237
- `# Instructions\n\n${instructions}`,
420
+ `# Workflow Stage\n\nstage=${template.stageId}\ntype=foreach`,
238
421
  template.foreach.roleText || undefined,
422
+ `# Workflow Item\n\nitem=${taskId}`,
423
+ `# Instructions\n\n${instructions}`,
239
424
  ]
240
425
  .filter(Boolean)
241
426
  .join("\n\n");
@@ -249,6 +434,7 @@ export function buildForeachGeneratedTasks(template, runtimeTask, items) {
249
434
  compiledPrompt,
250
435
  dependsOn: [...(template.dependsOn ?? [])],
251
436
  foreach: undefined,
437
+ foreachGenerated: { placeholderSpecId: template.id },
252
438
  });
253
439
  }
254
440
  return { tasks };
@@ -274,6 +460,9 @@ export function sanitizeTaskId(value) {
274
460
  function formatForeachItem(item) {
275
461
  return typeof item === "string" ? item : JSON.stringify(item);
276
462
  }
463
+ function escapeReplacementText(value) {
464
+ return value.replace(/\$/g, "$$$$");
465
+ }
277
466
  export function sourceStageIdsForFrom(from) {
278
467
  if (Array.isArray(from))
279
468
  return from.filter((item) => typeof item === "string");
@@ -321,7 +510,8 @@ export function markDagDependentsSkipped(run, compiledFlow) {
321
510
  const status = bySpecId.get(dep)?.status;
322
511
  return (status === "failed" ||
323
512
  status === "interrupted" ||
324
- status === "skipped");
513
+ status === "skipped" ||
514
+ status === "blocked");
325
515
  });
326
516
  if (!failedDep)
327
517
  continue;
package/dist/engine.d.ts CHANGED
@@ -25,6 +25,11 @@ export interface ResumeRunSummary {
25
25
  run: WorkflowRunRecord;
26
26
  resetTaskIds: string[];
27
27
  }
28
+ export interface StopRunSummary {
29
+ run: WorkflowRunRecord;
30
+ interruptedTaskIds: string[];
31
+ }
32
+ export declare function stopRun(cwd: string, runIdOrPrefix: string): Promise<StopRunSummary>;
28
33
  export declare function resumeRun(cwd: string, runIdOrPrefix: string, options?: WorkflowScheduleOptions): Promise<ResumeRunSummary>;
29
34
  export declare function resumeSupervisors(cwd: string, options?: WorkflowScheduleOptions): Promise<void>;
30
35
  export declare function watchRun(cwd: string, runId: string, options?: WorkflowScheduleOptions): void;