@entelligentsia/forgecli 0.6.6 → 0.7.6

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 (183) hide show
  1. package/CHANGELOG.md +88 -0
  2. package/README.md +28 -1
  3. package/dist/bin/forge.js +20 -0
  4. package/dist/bin/forge.js.map +1 -1
  5. package/dist/extensions/forgecli/approve.d.ts +24 -0
  6. package/dist/extensions/forgecli/approve.js +202 -0
  7. package/dist/extensions/forgecli/approve.js.map +1 -0
  8. package/dist/extensions/forgecli/audience-gate.d.ts +4 -0
  9. package/dist/extensions/forgecli/audience-gate.js +8 -5
  10. package/dist/extensions/forgecli/audience-gate.js.map +1 -1
  11. package/dist/extensions/forgecli/collate.d.ts +24 -0
  12. package/dist/extensions/forgecli/collate.js +199 -0
  13. package/dist/extensions/forgecli/collate.js.map +1 -0
  14. package/dist/extensions/forgecli/commit.d.ts +24 -0
  15. package/dist/extensions/forgecli/commit.js +202 -0
  16. package/dist/extensions/forgecli/commit.js.map +1 -0
  17. package/dist/extensions/forgecli/fix-bug.d.ts +75 -0
  18. package/dist/extensions/forgecli/fix-bug.js +1133 -0
  19. package/dist/extensions/forgecli/fix-bug.js.map +1 -0
  20. package/dist/extensions/forgecli/forge-commands.js +7 -0
  21. package/dist/extensions/forgecli/forge-commands.js.map +1 -1
  22. package/dist/extensions/forgecli/forge-init.js +16 -8
  23. package/dist/extensions/forgecli/forge-init.js.map +1 -1
  24. package/dist/extensions/forgecli/forge-subagent.d.ts +29 -0
  25. package/dist/extensions/forgecli/forge-subagent.js +14 -1
  26. package/dist/extensions/forgecli/forge-subagent.js.map +1 -1
  27. package/dist/extensions/forgecli/hook-dispatcher.d.ts +53 -1
  28. package/dist/extensions/forgecli/hook-dispatcher.js +47 -1
  29. package/dist/extensions/forgecli/hook-dispatcher.js.map +1 -1
  30. package/dist/extensions/forgecli/hooks/post-init-hook.d.ts +15 -0
  31. package/dist/extensions/forgecli/hooks/post-init-hook.js +127 -0
  32. package/dist/extensions/forgecli/hooks/post-init-hook.js.map +1 -0
  33. package/dist/extensions/forgecli/hooks/post-sprint-hook.d.ts +37 -0
  34. package/dist/extensions/forgecli/hooks/post-sprint-hook.js +166 -0
  35. package/dist/extensions/forgecli/hooks/post-sprint-hook.js.map +1 -0
  36. package/dist/extensions/forgecli/index.js +47 -0
  37. package/dist/extensions/forgecli/index.js.map +1 -1
  38. package/dist/extensions/forgecli/review-code.d.ts +24 -0
  39. package/dist/extensions/forgecli/review-code.js +202 -0
  40. package/dist/extensions/forgecli/review-code.js.map +1 -0
  41. package/dist/extensions/forgecli/review-plan.d.ts +24 -0
  42. package/dist/extensions/forgecli/review-plan.js +203 -0
  43. package/dist/extensions/forgecli/review-plan.js.map +1 -0
  44. package/dist/extensions/forgecli/run-sprint.d.ts +18 -0
  45. package/dist/extensions/forgecli/run-sprint.js +33 -1
  46. package/dist/extensions/forgecli/run-sprint.js.map +1 -1
  47. package/dist/extensions/forgecli/run-task.d.ts +21 -2
  48. package/dist/extensions/forgecli/run-task.js +33 -9
  49. package/dist/extensions/forgecli/run-task.js.map +1 -1
  50. package/dist/extensions/forgecli/session-registry.d.ts +10 -0
  51. package/dist/extensions/forgecli/session-registry.js +9 -0
  52. package/dist/extensions/forgecli/session-registry.js.map +1 -1
  53. package/dist/extensions/forgecli/validate.d.ts +24 -0
  54. package/dist/extensions/forgecli/validate.js +202 -0
  55. package/dist/extensions/forgecli/validate.js.map +1 -0
  56. package/dist/extensions/forgecli/wf-engine/engine.d.ts +23 -0
  57. package/dist/extensions/forgecli/wf-engine/engine.js +384 -0
  58. package/dist/extensions/forgecli/wf-engine/engine.js.map +1 -0
  59. package/dist/extensions/forgecli/wf-engine/event-parser.d.ts +6 -0
  60. package/dist/extensions/forgecli/wf-engine/event-parser.js +29 -0
  61. package/dist/extensions/forgecli/wf-engine/event-parser.js.map +1 -0
  62. package/dist/extensions/forgecli/wf-engine/id-gen.d.ts +6 -0
  63. package/dist/extensions/forgecli/wf-engine/id-gen.js +17 -0
  64. package/dist/extensions/forgecli/wf-engine/id-gen.js.map +1 -0
  65. package/dist/extensions/forgecli/wf-engine/loader.d.ts +2 -0
  66. package/dist/extensions/forgecli/wf-engine/loader.js +100 -0
  67. package/dist/extensions/forgecli/wf-engine/loader.js.map +1 -0
  68. package/dist/extensions/forgecli/wf-engine/predicate.d.ts +7 -0
  69. package/dist/extensions/forgecli/wf-engine/predicate.js +36 -0
  70. package/dist/extensions/forgecli/wf-engine/predicate.js.map +1 -0
  71. package/dist/extensions/forgecli/wf-engine/prompt-compiler.d.ts +15 -0
  72. package/dist/extensions/forgecli/wf-engine/prompt-compiler.js +23 -0
  73. package/dist/extensions/forgecli/wf-engine/prompt-compiler.js.map +1 -0
  74. package/dist/extensions/forgecli/wf-engine/register.d.ts +9 -0
  75. package/dist/extensions/forgecli/wf-engine/register.js +59 -0
  76. package/dist/extensions/forgecli/wf-engine/register.js.map +1 -0
  77. package/dist/extensions/forgecli/wf-engine/remit-check.d.ts +6 -0
  78. package/dist/extensions/forgecli/wf-engine/remit-check.js +42 -0
  79. package/dist/extensions/forgecli/wf-engine/remit-check.js.map +1 -0
  80. package/dist/extensions/forgecli/wf-engine/state-store.d.ts +13 -0
  81. package/dist/extensions/forgecli/wf-engine/state-store.js +43 -0
  82. package/dist/extensions/forgecli/wf-engine/state-store.js.map +1 -0
  83. package/dist/extensions/forgecli/wf-engine/types.d.ts +66 -0
  84. package/dist/extensions/forgecli/wf-engine/types.js +2 -0
  85. package/dist/extensions/forgecli/wf-engine/types.js.map +1 -0
  86. package/dist/extensions/forgecli/wf-engine/worker.d.ts +11 -0
  87. package/dist/extensions/forgecli/wf-engine/worker.js +50 -0
  88. package/dist/extensions/forgecli/wf-engine/worker.js.map +1 -0
  89. package/dist/forge-payload/.base-pack/workflows/_fragments/context-injection.md +10 -4
  90. package/dist/forge-payload/.base-pack/workflows/fix_bug.md +12 -0
  91. package/dist/forge-payload/.schemas/bug.schema.json +4 -2
  92. package/dist/forge-payload/.schemas/event.schema.json +22 -3
  93. package/dist/forge-payload/commands/add-pipeline.md +342 -0
  94. package/dist/forge-payload/commands/add-task.md +269 -0
  95. package/dist/forge-payload/commands/ask.md +43 -0
  96. package/dist/forge-payload/commands/calibrate.md +356 -0
  97. package/dist/forge-payload/commands/config.md +202 -0
  98. package/dist/forge-payload/commands/enhance.md +38 -0
  99. package/dist/forge-payload/commands/health.md +225 -0
  100. package/dist/forge-payload/commands/init.md +165 -0
  101. package/dist/forge-payload/commands/materialize.md +119 -0
  102. package/dist/forge-payload/commands/migrate.md +160 -0
  103. package/dist/forge-payload/commands/quiz-agent.md +38 -0
  104. package/dist/forge-payload/commands/regenerate.md +673 -0
  105. package/dist/forge-payload/commands/remove.md +174 -0
  106. package/dist/forge-payload/commands/report-bug.md +191 -0
  107. package/dist/forge-payload/commands/store-query.md +73 -0
  108. package/dist/forge-payload/commands/store-repair.md +187 -0
  109. package/dist/forge-payload/commands/update-tools.md +56 -0
  110. package/dist/forge-payload/commands/update.md +1376 -0
  111. package/dist/forge-payload/tools/preflight-gate.cjs +2 -1
  112. package/dist/forge-payload/tools/read-verdict.cjs +41 -8
  113. package/dist/forge-payload/tools/store-cli.cjs +4 -3
  114. package/node_modules/argparse/CHANGELOG.md +216 -0
  115. package/node_modules/argparse/LICENSE +254 -0
  116. package/node_modules/argparse/README.md +84 -0
  117. package/node_modules/argparse/argparse.js +3707 -0
  118. package/node_modules/argparse/lib/sub.js +67 -0
  119. package/node_modules/argparse/lib/textwrap.js +440 -0
  120. package/node_modules/argparse/package.json +31 -0
  121. package/node_modules/cliui/CHANGELOG.md +121 -0
  122. package/node_modules/color-convert/CHANGELOG.md +54 -0
  123. package/node_modules/esprima/ChangeLog +235 -0
  124. package/node_modules/js-yaml/LICENSE +21 -0
  125. package/node_modules/js-yaml/README.md +247 -0
  126. package/node_modules/js-yaml/bin/js-yaml.js +126 -0
  127. package/node_modules/js-yaml/dist/js-yaml.js +3880 -0
  128. package/node_modules/js-yaml/dist/js-yaml.min.js +2 -0
  129. package/node_modules/js-yaml/dist/js-yaml.mjs +3856 -0
  130. package/node_modules/js-yaml/index.js +47 -0
  131. package/node_modules/js-yaml/lib/common.js +59 -0
  132. package/node_modules/js-yaml/lib/dumper.js +965 -0
  133. package/node_modules/js-yaml/lib/exception.js +55 -0
  134. package/node_modules/js-yaml/lib/loader.js +1733 -0
  135. package/node_modules/js-yaml/lib/schema/core.js +11 -0
  136. package/node_modules/js-yaml/lib/schema/default.js +22 -0
  137. package/node_modules/js-yaml/lib/schema/failsafe.js +17 -0
  138. package/node_modules/js-yaml/lib/schema/json.js +19 -0
  139. package/node_modules/js-yaml/lib/schema.js +121 -0
  140. package/node_modules/js-yaml/lib/snippet.js +101 -0
  141. package/node_modules/js-yaml/lib/type/binary.js +125 -0
  142. package/node_modules/js-yaml/lib/type/bool.js +35 -0
  143. package/node_modules/js-yaml/lib/type/float.js +97 -0
  144. package/node_modules/js-yaml/lib/type/int.js +156 -0
  145. package/node_modules/js-yaml/lib/type/map.js +8 -0
  146. package/node_modules/js-yaml/lib/type/merge.js +12 -0
  147. package/node_modules/js-yaml/lib/type/null.js +35 -0
  148. package/node_modules/js-yaml/lib/type/omap.js +44 -0
  149. package/node_modules/js-yaml/lib/type/pairs.js +53 -0
  150. package/node_modules/js-yaml/lib/type/seq.js +8 -0
  151. package/node_modules/js-yaml/lib/type/set.js +29 -0
  152. package/node_modules/js-yaml/lib/type/str.js +8 -0
  153. package/node_modules/js-yaml/lib/type/timestamp.js +88 -0
  154. package/node_modules/js-yaml/lib/type.js +66 -0
  155. package/node_modules/js-yaml/package.json +66 -0
  156. package/node_modules/mz/HISTORY.md +66 -0
  157. package/node_modules/proper-lockfile/CHANGELOG.md +108 -0
  158. package/node_modules/source-map/CHANGELOG.md +301 -0
  159. package/node_modules/thenify/History.md +11 -0
  160. package/node_modules/thenify-all/History.md +11 -0
  161. package/node_modules/y18n/CHANGELOG.md +100 -0
  162. package/node_modules/yargs/CHANGELOG.md +88 -0
  163. package/node_modules/yargs-parser/CHANGELOG.md +263 -0
  164. package/package.json +6 -2
  165. package/workflows/lead-qualifier/prompts/digest.md +44 -0
  166. package/workflows/lead-qualifier/prompts/draft-outreach.md +44 -0
  167. package/workflows/lead-qualifier/prompts/enrich.md +52 -0
  168. package/workflows/lead-qualifier/prompts/intake.md +48 -0
  169. package/workflows/lead-qualifier/prompts/mark-cold.md +38 -0
  170. package/workflows/lead-qualifier/prompts/score.md +45 -0
  171. package/workflows/lead-qualifier/workflow.yaml +95 -0
  172. package/workflows/research-brief/prompts/brief-synthesize.md +43 -0
  173. package/workflows/research-brief/prompts/intake.md +51 -0
  174. package/workflows/research-brief/prompts/source-critique.md +38 -0
  175. package/workflows/research-brief/prompts/source-score.md +38 -0
  176. package/workflows/research-brief/prompts/source-summarize.md +54 -0
  177. package/workflows/research-brief/workflow.yaml +66 -0
  178. package/dist/extensions/forgecli/session-monitor-widget.d.ts +0 -37
  179. package/dist/extensions/forgecli/session-monitor-widget.js +0 -320
  180. package/dist/extensions/forgecli/session-monitor-widget.js.map +0 -1
  181. package/dist/extensions/forgecli/session-monitor.d.ts +0 -2
  182. package/dist/extensions/forgecli/session-monitor.js +0 -135
  183. package/dist/extensions/forgecli/session-monitor.js.map +0 -1
@@ -0,0 +1,6 @@
1
+ import type { Event } from "./types.js";
2
+ export interface ParsedEvents {
3
+ events: Event[];
4
+ rawBlock?: string;
5
+ }
6
+ export declare function parseEventsBlock(response: string): ParsedEvents;
@@ -0,0 +1,29 @@
1
+ // Match any ```json events ... ``` block; g flag so we can take the last one.
2
+ // LLMs often emit the block mid-response followed by explanatory prose, so we
3
+ // cannot anchor to $ — we take the last occurrence instead.
4
+ const FENCE_RE = /```json\s+events\s*\n([\s\S]*?)\n```/g;
5
+ export function parseEventsBlock(response) {
6
+ // Scan all matches; keep the last one (the actual output, not prompt examples).
7
+ let last = null;
8
+ let m;
9
+ const re = new RegExp(FENCE_RE.source, "g");
10
+ while ((m = re.exec(response)) !== null) {
11
+ last = m;
12
+ }
13
+ if (!last) {
14
+ return { events: [] };
15
+ }
16
+ const block = last[1];
17
+ let arr;
18
+ try {
19
+ arr = JSON.parse(block);
20
+ }
21
+ catch (err) {
22
+ throw new Error(`events block is not valid JSON: ${err.message}`);
23
+ }
24
+ if (!Array.isArray(arr)) {
25
+ throw new Error(`events block must be a JSON array, got ${typeof arr}`);
26
+ }
27
+ return { events: arr, rawBlock: block };
28
+ }
29
+ //# sourceMappingURL=event-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-parser.js","sourceRoot":"","sources":["../../../../src/extensions/forgecli/wf-engine/event-parser.ts"],"names":[],"mappings":"AAEA,8EAA8E;AAC9E,8EAA8E;AAC9E,4DAA4D;AAC5D,MAAM,QAAQ,GAAG,uCAAuC,CAAC;AAOzD,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,gFAAgF;IAChF,IAAI,IAAI,GAA2B,IAAI,CAAC;IACxC,IAAI,CAAyB,CAAC;IAC9B,MAAM,EAAE,GAAG,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5C,OAAO,CAAC,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACxC,IAAI,GAAG,CAAC,CAAC;IACX,CAAC;IACD,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACxB,CAAC;IACD,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACtB,IAAI,GAAY,CAAC;IACjB,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,mCAAoC,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;IAC/E,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,0CAA0C,OAAO,GAAG,EAAE,CAAC,CAAC;IAC1E,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,GAAc,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;AACrD,CAAC"}
@@ -0,0 +1,6 @@
1
+ export declare function makeInstanceId(workflowId: string, rand?: () => string): string;
2
+ export declare function makeNodeExecId(instanceId: string, nodeId: string, loop?: {
3
+ iter: number;
4
+ itemId: string;
5
+ }): string;
6
+ export declare function makeEventId(nodeExecId: string, seq: number, type: string): string;
@@ -0,0 +1,17 @@
1
+ import * as crypto from "node:crypto";
2
+ export function makeInstanceId(workflowId, rand) {
3
+ const iso = new Date().toISOString().replace(/[-:]/g, "").replace(/\.\d{3}Z$/, "Z");
4
+ const r = rand ? rand() : crypto.randomBytes(2).toString("hex");
5
+ return `wf_${workflowId}_${iso}_${r}`;
6
+ }
7
+ export function makeNodeExecId(instanceId, nodeId, loop) {
8
+ if (!loop)
9
+ return `${instanceId}__${nodeId}`;
10
+ const iterPad = String(loop.iter).padStart(2, "0");
11
+ return `${instanceId}__${nodeId}__iter${iterPad}__${loop.itemId}`;
12
+ }
13
+ export function makeEventId(nodeExecId, seq, type) {
14
+ const seqPad = String(seq).padStart(3, "0");
15
+ return `${nodeExecId}__${seqPad}__${type}`;
16
+ }
17
+ //# sourceMappingURL=id-gen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"id-gen.js","sourceRoot":"","sources":["../../../../src/extensions/forgecli/wf-engine/id-gen.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AAEtC,MAAM,UAAU,cAAc,CAAC,UAAkB,EAAE,IAAmB;IACpE,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;IACpF,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAChE,OAAO,MAAM,UAAU,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,UAAkB,EAClB,MAAc,EACd,IAAuC;IAEvC,IAAI,CAAC,IAAI;QAAE,OAAO,GAAG,UAAU,KAAK,MAAM,EAAE,CAAC;IAC7C,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACnD,OAAO,GAAG,UAAU,KAAK,MAAM,SAAS,OAAO,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;AACpE,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,UAAkB,EAAE,GAAW,EAAE,IAAY;IACvE,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC5C,OAAO,GAAG,UAAU,KAAK,MAAM,KAAK,IAAI,EAAE,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { WorkflowDef } from "./types.js";
2
+ export declare function loadWorkflow(workflowDir: string): WorkflowDef;
@@ -0,0 +1,100 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import * as yaml from "js-yaml";
4
+ export function loadWorkflow(workflowDir) {
5
+ const yamlPath = path.join(workflowDir, "workflow.yaml");
6
+ if (!fs.existsSync(yamlPath)) {
7
+ throw new Error(`workflow.yaml not found at ${yamlPath}`);
8
+ }
9
+ const raw = fs.readFileSync(yamlPath, "utf8");
10
+ const parsed = yaml.load(raw);
11
+ validateWorkflow(parsed, workflowDir);
12
+ return parsed;
13
+ }
14
+ function validateWorkflow(wf, workflowDir) {
15
+ if (!wf.id || typeof wf.id !== "string")
16
+ throw new Error("workflow.id required (string)");
17
+ if (!Array.isArray(wf.nodes) || wf.nodes.length === 0)
18
+ throw new Error("workflow.nodes required (non-empty array)");
19
+ if (!Array.isArray(wf.edges) || wf.edges.length === 0)
20
+ throw new Error("workflow.edges required (non-empty array)");
21
+ const nodeIds = new Set(wf.nodes.map(n => n.id));
22
+ for (const n of wf.nodes) {
23
+ if (!n.id)
24
+ throw new Error(`node missing id`);
25
+ if (!n.prompt)
26
+ throw new Error(`node ${n.id} missing prompt`);
27
+ const promptPath = path.join(workflowDir, n.prompt);
28
+ if (!fs.existsSync(promptPath))
29
+ throw new Error(`node ${n.id} prompt file not found: ${promptPath}`);
30
+ if (!n.expects?.success)
31
+ throw new Error(`node ${n.id} missing expects.success`);
32
+ if (!n.expects?.failure)
33
+ throw new Error(`node ${n.id} missing expects.failure`);
34
+ }
35
+ for (const e of wf.edges) {
36
+ if (!nodeIds.has(e.from))
37
+ throw new Error(`edge.from references unknown node: ${e.from}`);
38
+ if (e.to && !nodeIds.has(e.to))
39
+ throw new Error(`edge.to references unknown node: ${e.to}`);
40
+ if (e.next && !nodeIds.has(e.next))
41
+ throw new Error(`edge.next references unknown node: ${e.next}`);
42
+ if (!e.on || (e.on !== "success" && e.on !== "failure" && e.on !== "exhausted")) {
43
+ throw new Error(`edge.on must be 'success' | 'failure' | 'exhausted' (from ${e.from})`);
44
+ }
45
+ const hasOne = [e.to, e.halt, e.terminal, e.advance].filter(Boolean).length;
46
+ if (hasOne === 0)
47
+ throw new Error(`edge from ${e.from} has no continuation (to/halt/terminal/advance)`);
48
+ if (e.when && typeof e.when !== "string") {
49
+ throw new Error(`edge.when must be a string predicate (from ${e.from})`);
50
+ }
51
+ if (e.when && e.on !== "success") {
52
+ throw new Error(`edge.when only valid on success edges (from ${e.from})`);
53
+ }
54
+ }
55
+ // Group validation: collect groups, enforce single head, consistent loop.over
56
+ const groupMembers = new Map();
57
+ for (const n of wf.nodes) {
58
+ if (n.loop?.group) {
59
+ const arr = groupMembers.get(n.loop.group) ?? [];
60
+ arr.push(n.id);
61
+ groupMembers.set(n.loop.group, arr);
62
+ }
63
+ }
64
+ for (const [group, members] of groupMembers) {
65
+ const heads = members.filter(id => wf.nodes.find(n => n.id === id).loop?.head === true);
66
+ if (heads.length !== 1) {
67
+ throw new Error(`loop group '${group}' must have exactly one head node, found ${heads.length}`);
68
+ }
69
+ const overs = new Set(members.map(id => wf.nodes.find(n => n.id === id).loop.over));
70
+ if (overs.size !== 1) {
71
+ throw new Error(`loop group '${group}' members must share the same loop.over (found: ${[...overs].join(", ")})`);
72
+ }
73
+ }
74
+ // Exhausted edges only valid from loop head (or non-grouped loop node)
75
+ for (const e of wf.edges) {
76
+ if (e.on === "exhausted") {
77
+ const fromNode = wf.nodes.find(n => n.id === e.from);
78
+ if (!fromNode.loop)
79
+ throw new Error(`edge.on='exhausted' requires from node to have a loop (from ${e.from})`);
80
+ if (fromNode.loop.group && fromNode.loop.head !== true) {
81
+ throw new Error(`edge.on='exhausted' must originate from group head (from ${e.from})`);
82
+ }
83
+ }
84
+ }
85
+ // Every node must have a success and failure edge; loop heads in groups must also have an exhausted edge
86
+ for (const n of wf.nodes) {
87
+ const hasSuccess = wf.edges.some(e => e.from === n.id && e.on === "success");
88
+ const hasFailure = wf.edges.some(e => e.from === n.id && e.on === "failure");
89
+ if (!hasSuccess)
90
+ throw new Error(`node ${n.id} missing success edge`);
91
+ if (!hasFailure)
92
+ throw new Error(`node ${n.id} missing failure edge`);
93
+ if (n.loop?.group && n.loop?.head) {
94
+ const hasExhausted = wf.edges.some(e => e.from === n.id && e.on === "exhausted");
95
+ if (!hasExhausted)
96
+ throw new Error(`group-head node ${n.id} missing exhausted edge`);
97
+ }
98
+ }
99
+ }
100
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../../src/extensions/forgecli/wf-engine/loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export interface PredicateContext {
2
+ state: unknown;
3
+ loop?: {
4
+ item: unknown;
5
+ };
6
+ }
7
+ export declare function evalPredicate(expr: string, ctx: PredicateContext): boolean;
@@ -0,0 +1,36 @@
1
+ const OP_RE = /^(\S+)\s+(==|!=|<=|>=|<|>)\s+(.+)$/;
2
+ export function evalPredicate(expr, ctx) {
3
+ const trimmed = expr.trim();
4
+ const m = trimmed.match(OP_RE);
5
+ if (!m)
6
+ throw new Error(`predicate: cannot parse '${expr}' — expected '<path> <op> <literal>'`);
7
+ const [, lhsPath, op, rhsLit] = m;
8
+ const lhs = resolvePath({ state: ctx.state, loop: ctx.loop }, lhsPath);
9
+ let rhs;
10
+ try {
11
+ rhs = JSON.parse(rhsLit);
12
+ }
13
+ catch {
14
+ throw new Error(`predicate: rhs '${rhsLit}' is not a valid JSON literal`);
15
+ }
16
+ switch (op) {
17
+ case "==": return lhs === rhs;
18
+ case "!=": return lhs !== rhs;
19
+ case "<": return lhs < rhs;
20
+ case "<=": return lhs <= rhs;
21
+ case ">": return lhs > rhs;
22
+ case ">=": return lhs >= rhs;
23
+ default: throw new Error(`predicate: unsupported op '${op}'`);
24
+ }
25
+ }
26
+ function resolvePath(obj, dotted) {
27
+ const parts = dotted.split(".");
28
+ let cur = obj;
29
+ for (const p of parts) {
30
+ if (cur === null || typeof cur !== "object")
31
+ return undefined;
32
+ cur = cur[p];
33
+ }
34
+ return cur;
35
+ }
36
+ //# sourceMappingURL=predicate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"predicate.js","sourceRoot":"","sources":["../../../../src/extensions/forgecli/wf-engine/predicate.ts"],"names":[],"mappings":"AAKA,MAAM,KAAK,GAAG,oCAAoC,CAAC;AAEnD,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,GAAqB;IAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC/B,IAAI,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,IAAI,sCAAsC,CAAC,CAAC;IAChG,MAAM,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;IAElC,MAAM,GAAG,GAAG,WAAW,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC;IACvE,IAAI,GAAY,CAAC;IACjB,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,mBAAmB,MAAM,+BAA+B,CAAC,CAAC;IAC5E,CAAC;IAED,QAAQ,EAAE,EAAE,CAAC;QACX,KAAK,IAAI,CAAC,CAAC,OAAO,GAAG,KAAK,GAAG,CAAC;QAC9B,KAAK,IAAI,CAAC,CAAC,OAAO,GAAG,KAAK,GAAG,CAAC;QAC9B,KAAK,GAAG,CAAC,CAAE,OAAQ,GAAc,GAAK,GAAc,CAAC;QACrD,KAAK,IAAI,CAAC,CAAC,OAAQ,GAAc,IAAK,GAAc,CAAC;QACrD,KAAK,GAAG,CAAC,CAAE,OAAQ,GAAc,GAAK,GAAc,CAAC;QACrD,KAAK,IAAI,CAAC,CAAC,OAAQ,GAAc,IAAK,GAAc,CAAC;QACrD,OAAO,CAAC,CAAG,MAAM,IAAI,KAAK,CAAC,8BAA8B,EAAE,GAAG,CAAC,CAAC;IAClE,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,GAAY,EAAE,MAAc;IAC/C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAChC,IAAI,GAAG,GAAY,GAAG,CAAC;IACvB,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,IAAI,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK,QAAQ;YAAE,OAAO,SAAS,CAAC;QAC9D,GAAG,GAAI,GAA+B,CAAC,CAAC,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,15 @@
1
+ export interface PromptContext {
2
+ wf: {
3
+ instanceId: string;
4
+ workingDir: string;
5
+ };
6
+ node: {
7
+ execId: string;
8
+ id: string;
9
+ };
10
+ state: unknown;
11
+ loop?: {
12
+ item: unknown;
13
+ };
14
+ }
15
+ export declare function compilePrompt(promptFile: string, ctx: PromptContext): string;
@@ -0,0 +1,23 @@
1
+ import * as fs from "node:fs";
2
+ export function compilePrompt(promptFile, ctx) {
3
+ let body = fs.readFileSync(promptFile, "utf8");
4
+ body = substitute(body, "{{wf.instanceId}}", ctx.wf.instanceId);
5
+ body = substitute(body, "{{wf.workingDir}}", ctx.wf.workingDir);
6
+ body = substitute(body, "{{node.execId}}", ctx.node.execId);
7
+ body = substitute(body, "{{node.id}}", ctx.node.id);
8
+ body = substitute(body, "{{state}}", JSON.stringify(ctx.state, null, 2));
9
+ if (ctx.loop) {
10
+ body = substitute(body, "{{loop.item}}", JSON.stringify(ctx.loop.item, null, 2));
11
+ // Also support {{loop.item.<key>}} for shallow object access
12
+ if (typeof ctx.loop.item === "object" && ctx.loop.item !== null) {
13
+ for (const [k, v] of Object.entries(ctx.loop.item)) {
14
+ body = substitute(body, `{{loop.item.${k}}}`, String(v));
15
+ }
16
+ }
17
+ }
18
+ return body;
19
+ }
20
+ function substitute(s, token, value) {
21
+ return s.split(token).join(value);
22
+ }
23
+ //# sourceMappingURL=prompt-compiler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt-compiler.js","sourceRoot":"","sources":["../../../../src/extensions/forgecli/wf-engine/prompt-compiler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAS9B,MAAM,UAAU,aAAa,CAAC,UAAkB,EAAE,GAAkB;IAClE,IAAI,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAC/C,IAAI,GAAG,UAAU,CAAC,IAAI,EAAE,mBAAmB,EAAI,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC;IAClE,IAAI,GAAG,UAAU,CAAC,IAAI,EAAE,mBAAmB,EAAI,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC;IAClE,IAAI,GAAG,UAAU,CAAC,IAAI,EAAE,iBAAiB,EAAM,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAChE,IAAI,GAAG,UAAU,CAAC,IAAI,EAAE,aAAa,EAAU,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC5D,IAAI,GAAG,UAAU,CAAC,IAAI,EAAE,WAAW,EAAY,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACnF,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC;QACb,IAAI,GAAG,UAAU,CAAC,IAAI,EAAE,eAAe,EAAM,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACrF,6DAA6D;QAC7D,IAAI,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;YAChE,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnD,IAAI,GAAG,UAAU,CAAC,IAAI,EAAE,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3D,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,UAAU,CAAC,CAAS,EAAE,KAAa,EAAE,KAAa;IACzD,OAAO,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACpC,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { ExtensionAPI } from "@entelligentsia/pi-coding-agent";
2
+ export interface RegisterRunWorkflowOptions {
3
+ cwd?: string;
4
+ /** Explicit single search dir. If set, overrides the CWD-first/bundled-fallback resolution. */
5
+ workflowsDir?: string;
6
+ /** Bundled workflows shipped with the package — used as fallback when CWD/workflows/<id> doesn't exist. */
7
+ bundledWorkflowsDir?: string;
8
+ }
9
+ export declare function registerRunWorkflow(pi: ExtensionAPI, options?: RegisterRunWorkflowOptions): void;
@@ -0,0 +1,59 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ import { runWorkflow } from "./engine.js";
4
+ import { getSessionRegistry } from "../session-registry.js";
5
+ export function registerRunWorkflow(pi, options = {}) {
6
+ pi.registerCommand("forge:run-workflow", {
7
+ description: "Run a generic workflow defined in workflows/<workflowId>/workflow.yaml. " +
8
+ "Resolution: CWD/workflows/<id> first, then bundled examples. " +
9
+ "Usage: /forge:run-workflow <workflowId> [entryPrompt...]",
10
+ async handler(args, ctx) {
11
+ const cwd = options.cwd ?? process.cwd();
12
+ const trimmed = args.trim();
13
+ if (!trimmed) {
14
+ ctx.ui.notify("× /forge:run-workflow — workflowId required. Usage: /forge:run-workflow <workflowId> [prompt]", "error");
15
+ return;
16
+ }
17
+ const [workflowId, ...rest] = trimmed.split(/\s+/);
18
+ const entryPrompt = rest.join(" ");
19
+ // Resolve workflowsDir: explicit override > CWD/workflows (if it has the id) > bundled fallback
20
+ let workflowsDir;
21
+ if (options.workflowsDir) {
22
+ workflowsDir = options.workflowsDir;
23
+ }
24
+ else {
25
+ const cwdCandidate = path.join(cwd, "workflows");
26
+ if (fs.existsSync(path.join(cwdCandidate, workflowId, "workflow.yaml"))) {
27
+ workflowsDir = cwdCandidate;
28
+ }
29
+ else if (options.bundledWorkflowsDir) {
30
+ workflowsDir = options.bundledWorkflowsDir;
31
+ }
32
+ else {
33
+ workflowsDir = cwdCandidate; // last resort — will surface a clear not-found error
34
+ }
35
+ }
36
+ try {
37
+ const result = await runWorkflow({
38
+ workflowsDir,
39
+ workflowId,
40
+ cwd,
41
+ entryPrompt,
42
+ notify: (line) => ctx.ui.notify(line, "info"),
43
+ registry: getSessionRegistry(),
44
+ });
45
+ if (result.status === "completed") {
46
+ ctx.ui.notify(`✓ workflow complete: ${result.workingDir}`, "info");
47
+ }
48
+ else {
49
+ ctx.ui.notify(`× workflow halted (${result.haltReason}): ${result.workingDir}`, "error");
50
+ }
51
+ }
52
+ catch (err) {
53
+ const e = err;
54
+ ctx.ui.notify(`× /forge:run-workflow threw: ${e.message ?? "unknown"}`, "error");
55
+ }
56
+ },
57
+ });
58
+ }
59
+ //# sourceMappingURL=register.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register.js","sourceRoot":"","sources":["../../../../src/extensions/forgecli/wf-engine/register.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAU5D,MAAM,UAAU,mBAAmB,CAAC,EAAgB,EAAE,UAAsC,EAAE;IAC5F,EAAE,CAAC,eAAe,CAAC,oBAAoB,EAAE;QACvC,WAAW,EACT,0EAA0E;YAC1E,+DAA+D;YAC/D,0DAA0D;QAC5D,KAAK,CAAC,OAAO,CAAC,IAAY,EAAE,GAA4B;YACtD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;YAEzC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAC5B,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,+FAA+F,EAAE,OAAO,CAAC,CAAC;gBACxH,OAAO;YACT,CAAC;YACD,MAAM,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACnD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAEnC,gGAAgG;YAChG,IAAI,YAAgC,CAAC;YACrC,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;gBACzB,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;YACtC,CAAC;iBAAM,CAAC;gBACN,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;gBACjD,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,UAAU,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC;oBACxE,YAAY,GAAG,YAAY,CAAC;gBAC9B,CAAC;qBAAM,IAAI,OAAO,CAAC,mBAAmB,EAAE,CAAC;oBACvC,YAAY,GAAG,OAAO,CAAC,mBAAmB,CAAC;gBAC7C,CAAC;qBAAM,CAAC;oBACN,YAAY,GAAG,YAAY,CAAC,CAAG,qDAAqD;gBACtF,CAAC;YACH,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC;oBAC/B,YAAY;oBACZ,UAAU;oBACV,GAAG;oBACH,WAAW;oBACX,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC;oBAC7C,QAAQ,EAAE,kBAAkB,EAAE;iBAC/B,CAAC,CAAC;gBACH,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;oBAClC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,wBAAwB,MAAM,CAAC,UAAU,EAAE,EAAE,MAAM,CAAC,CAAC;gBACrE,CAAC;qBAAM,CAAC;oBACN,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,sBAAsB,MAAM,CAAC,UAAU,MAAM,MAAM,CAAC,UAAU,EAAE,EAAE,OAAO,CAAC,CAAC;gBAC3F,CAAC;YACH,CAAC;YAAC,OAAO,GAAY,EAAE,CAAC;gBACtB,MAAM,CAAC,GAAG,GAA2B,CAAC;gBACtC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,gCAAgC,CAAC,CAAC,OAAO,IAAI,SAAS,EAAE,EAAE,OAAO,CAAC,CAAC;YACnF,CAAC;QACH,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { Event, NodeDef } from "./types.js";
2
+ export interface RemitCheckResult {
3
+ ok: boolean;
4
+ violations: string[];
5
+ }
6
+ export declare function checkRemit(emitted: Event[], node: NodeDef, loopItemId?: string): RemitCheckResult;
@@ -0,0 +1,42 @@
1
+ export function checkRemit(emitted, node, loopItemId) {
2
+ const violations = [];
3
+ // Must have started + exactly one terminal
4
+ const startedCount = emitted.filter(e => e.type === "started").length;
5
+ if (startedCount !== 1)
6
+ violations.push(`expected exactly 1 'started' event, got ${startedCount}`);
7
+ const terminals = emitted.filter(e => e.type === "success" || e.type === "failure");
8
+ if (terminals.length !== 1)
9
+ violations.push(`expected exactly 1 terminal event (success/failure), got ${terminals.length}`);
10
+ if (terminals.length === 1) {
11
+ const term = terminals[0];
12
+ if (term.type === "success" && term.writes?.artifact) {
13
+ const pattern = node.expects.success.writes?.artifact?.pattern;
14
+ if (!pattern) {
15
+ violations.push(`node emitted artifact but expects.success.writes.artifact not declared`);
16
+ }
17
+ else {
18
+ const resolved = pattern.replace(/\{loop\.item\.id\}/g, loopItemId ?? "");
19
+ if (term.writes.artifact.path !== resolved) {
20
+ violations.push(`artifact path '${term.writes.artifact.path}' does not match declared pattern '${resolved}'`);
21
+ }
22
+ }
23
+ }
24
+ if (term.type === "success" && term.writes?.state) {
25
+ const allowed = node.expects.success.writes?.state ?? [];
26
+ for (const key of Object.keys(term.writes.state)) {
27
+ const matched = allowed.some(a => {
28
+ const resolved = a.replace(/\{loop\.item\.id\}/g, loopItemId ?? "");
29
+ return resolved === key;
30
+ });
31
+ if (!matched) {
32
+ violations.push(`state write '${key}' not in declared expects.success.writes.state`);
33
+ }
34
+ }
35
+ }
36
+ if (term.type === "failure" && (!term.reason || typeof term.reason !== "string")) {
37
+ violations.push(`failure event missing 'reason' string`);
38
+ }
39
+ }
40
+ return { ok: violations.length === 0, violations };
41
+ }
42
+ //# sourceMappingURL=remit-check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remit-check.js","sourceRoot":"","sources":["../../../../src/extensions/forgecli/wf-engine/remit-check.ts"],"names":[],"mappings":"AAOA,MAAM,UAAU,UAAU,CACxB,OAAgB,EAChB,IAAa,EACb,UAAmB;IAEnB,MAAM,UAAU,GAAa,EAAE,CAAC;IAEhC,2CAA2C;IAC3C,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,MAAM,CAAC;IACtE,IAAI,YAAY,KAAK,CAAC;QAAE,UAAU,CAAC,IAAI,CAAC,2CAA2C,YAAY,EAAE,CAAC,CAAC;IAEnG,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;IACpF,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;QAAE,UAAU,CAAC,IAAI,CAAC,4DAA4D,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;IAE5H,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QAC1B,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC;YACrD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC;YAC/D,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,UAAU,CAAC,IAAI,CAAC,wEAAwE,CAAC,CAAC;YAC5F,CAAC;iBAAM,CAAC;gBACN,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,qBAAqB,EAAE,UAAU,IAAI,EAAE,CAAC,CAAC;gBAC1E,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;oBAC3C,UAAU,CAAC,IAAI,CAAC,kBAAkB,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,sCAAsC,QAAQ,GAAG,CAAC,CAAC;gBAChH,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC;YAClD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,KAAK,IAAI,EAAE,CAAC;YACzD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;gBACjD,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;oBAC/B,MAAM,QAAQ,GAAG,CAAC,CAAC,OAAO,CAAC,qBAAqB,EAAE,UAAU,IAAI,EAAE,CAAC,CAAC;oBACpE,OAAO,QAAQ,KAAK,GAAG,CAAC;gBAC1B,CAAC,CAAC,CAAC;gBACH,IAAI,CAAC,OAAO,EAAE,CAAC;oBACb,UAAU,CAAC,IAAI,CAAC,gBAAgB,GAAG,gDAAgD,CAAC,CAAC;gBACvF,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,EAAE,CAAC;YACjF,UAAU,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;AACrD,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { Event, RuntimeState } from "./types.js";
2
+ export declare class StateStore {
3
+ private readonly workingDir;
4
+ constructor(workingDir: string);
5
+ initialState(initial: RuntimeState): void;
6
+ readState(): RuntimeState;
7
+ writeState(s: RuntimeState): void;
8
+ appendEvents(events: Event[]): void;
9
+ writeArtifact(relPath: string, content: string): void;
10
+ writeNodeArchive(nodeExecId: string, files: Record<string, string>): void;
11
+ private statePath;
12
+ private eventLogPath;
13
+ }
@@ -0,0 +1,43 @@
1
+ import * as fs from "node:fs";
2
+ import * as path from "node:path";
3
+ export class StateStore {
4
+ workingDir;
5
+ constructor(workingDir) {
6
+ this.workingDir = workingDir;
7
+ }
8
+ initialState(initial) {
9
+ fs.mkdirSync(this.workingDir, { recursive: true });
10
+ fs.mkdirSync(path.join(this.workingDir, "nodes"), { recursive: true });
11
+ fs.mkdirSync(path.join(this.workingDir, "artifacts"), { recursive: true });
12
+ fs.writeFileSync(this.statePath(), JSON.stringify(initial, null, 2));
13
+ fs.writeFileSync(this.eventLogPath(), ""); // create empty file
14
+ }
15
+ readState() {
16
+ return JSON.parse(fs.readFileSync(this.statePath(), "utf8"));
17
+ }
18
+ writeState(s) {
19
+ // Atomic write: tmp + rename
20
+ const tmp = `${this.statePath()}.tmp`;
21
+ fs.writeFileSync(tmp, JSON.stringify(s, null, 2));
22
+ fs.renameSync(tmp, this.statePath());
23
+ }
24
+ appendEvents(events) {
25
+ const lines = events.map(e => JSON.stringify(e)).join("\n") + "\n";
26
+ fs.appendFileSync(this.eventLogPath(), lines);
27
+ }
28
+ writeArtifact(relPath, content) {
29
+ const abs = path.join(this.workingDir, relPath);
30
+ fs.mkdirSync(path.dirname(abs), { recursive: true });
31
+ fs.writeFileSync(abs, content);
32
+ }
33
+ writeNodeArchive(nodeExecId, files) {
34
+ const dir = path.join(this.workingDir, "nodes", nodeExecId);
35
+ fs.mkdirSync(dir, { recursive: true });
36
+ for (const [name, content] of Object.entries(files)) {
37
+ fs.writeFileSync(path.join(dir, name), content);
38
+ }
39
+ }
40
+ statePath() { return path.join(this.workingDir, "state.json"); }
41
+ eventLogPath() { return path.join(this.workingDir, "events.log.jsonl"); }
42
+ }
43
+ //# sourceMappingURL=state-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-store.js","sourceRoot":"","sources":["../../../../src/extensions/forgecli/wf-engine/state-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAGlC,MAAM,OAAO,UAAU;IACQ;IAA7B,YAA6B,UAAkB;QAAlB,eAAU,GAAV,UAAU,CAAQ;IAAG,CAAC;IAEnD,YAAY,CAAC,OAAqB;QAChC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACvE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3E,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACrE,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,EAAE,CAAC,CAAC,CAAG,oBAAoB;IACnE,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,MAAM,CAAC,CAAiB,CAAC;IAC/E,CAAC;IAED,UAAU,CAAC,CAAe;QACxB,6BAA6B;QAC7B,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC;QACtC,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAClD,EAAE,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;IACvC,CAAC;IAED,YAAY,CAAC,MAAe;QAC1B,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;QACnE,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,KAAK,CAAC,CAAC;IAChD,CAAC;IAED,aAAa,CAAC,OAAe,EAAE,OAAe;QAC5C,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAChD,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACjC,CAAC;IAED,gBAAgB,CAAC,UAAkB,EAAE,KAA6B;QAChE,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;QAC5D,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACvC,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACpD,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IAEO,SAAS,KAAgB,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;IAC3E,YAAY,KAAa,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAC;CAC1F"}
@@ -0,0 +1,66 @@
1
+ export interface WorkflowDef {
2
+ id: string;
3
+ version: number;
4
+ description?: string;
5
+ nodes: NodeDef[];
6
+ edges: EdgeDef[];
7
+ }
8
+ export interface NodeDef {
9
+ id: string;
10
+ prompt: string;
11
+ loop?: LoopSpec;
12
+ expects: ExpectsSpec;
13
+ }
14
+ export interface LoopSpec {
15
+ over: string;
16
+ alias: string;
17
+ alsoEmitsItemId?: boolean;
18
+ group?: string;
19
+ head?: boolean;
20
+ }
21
+ export interface ExpectsSpec {
22
+ success: {
23
+ writes?: {
24
+ state?: string[];
25
+ artifact?: {
26
+ pattern: string;
27
+ };
28
+ };
29
+ };
30
+ failure: {};
31
+ }
32
+ export interface EdgeDef {
33
+ from: string;
34
+ on: "success" | "failure" | "exhausted";
35
+ to?: string;
36
+ halt?: string;
37
+ terminal?: "complete";
38
+ advance?: "loop-or-next";
39
+ next?: string;
40
+ when?: string;
41
+ }
42
+ export interface RuntimeState {
43
+ cursor: string;
44
+ loopCursor: Record<string, number>;
45
+ entryPrompt?: string;
46
+ [key: string]: unknown;
47
+ }
48
+ export interface Event {
49
+ eventId: string;
50
+ nodeExecId: string;
51
+ type: "started" | "progress" | "success" | "failure" | "workflow.started" | "workflow.completed" | "workflow.halted" | "node.dispatched" | "node.committed" | "node.remit-violation";
52
+ ts: string;
53
+ writes?: {
54
+ state?: Record<string, unknown>;
55
+ artifact?: {
56
+ path: string;
57
+ content: string;
58
+ };
59
+ };
60
+ summary?: string;
61
+ reason?: string;
62
+ details?: string;
63
+ workflowId?: string;
64
+ instanceId?: string;
65
+ violatedRule?: string;
66
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/extensions/forgecli/wf-engine/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,11 @@
1
+ import { type AgentSessionEvent } from "@entelligentsia/pi-coding-agent";
2
+ export interface WorkerResult {
3
+ responseText: string;
4
+ exitCode: 0 | 1;
5
+ errorMessage?: string;
6
+ }
7
+ export declare function dispatchLlmWorker(opts: {
8
+ compiledPrompt: string;
9
+ cwd: string;
10
+ onEvent?: (event: AgentSessionEvent) => void;
11
+ }): Promise<WorkerResult>;
@@ -0,0 +1,50 @@
1
+ import { AuthStorage, createAgentSession, DefaultResourceLoader, getAgentDir, ModelRegistry, SessionManager, } from "@entelligentsia/pi-coding-agent";
2
+ export async function dispatchLlmWorker(opts) {
3
+ const loader = new DefaultResourceLoader({
4
+ cwd: opts.cwd,
5
+ agentDir: getAgentDir(),
6
+ systemPromptOverride: () => "You are a workflow node worker. Read the user message carefully. "
7
+ + "At the end of your reply, emit a ```json events block per the protocol. "
8
+ + "Outside that block, you may write reasoning prose if helpful — but the engine ignores it.",
9
+ noExtensions: true,
10
+ noSkills: true,
11
+ noPromptTemplates: true,
12
+ noContextFiles: true,
13
+ });
14
+ await loader.reload();
15
+ const authStorage = AuthStorage.create();
16
+ const modelRegistry = ModelRegistry.create(authStorage);
17
+ const { session } = await createAgentSession({
18
+ sessionManager: SessionManager.inMemory(),
19
+ authStorage,
20
+ modelRegistry,
21
+ resourceLoader: loader,
22
+ });
23
+ let responseText = "";
24
+ const unsub = session.subscribe((event) => {
25
+ if (opts.onEvent)
26
+ opts.onEvent(event);
27
+ if (event.type === "turn_end" && event.message) {
28
+ const msg = event.message;
29
+ if (msg.role === "assistant") {
30
+ for (const part of msg.content) {
31
+ if (part.type === "text")
32
+ responseText += part.text;
33
+ }
34
+ }
35
+ }
36
+ });
37
+ try {
38
+ await session.prompt(opts.compiledPrompt);
39
+ unsub();
40
+ session.dispose();
41
+ return { responseText, exitCode: 0 };
42
+ }
43
+ catch (err) {
44
+ unsub();
45
+ session.dispose();
46
+ const e = err;
47
+ return { responseText, exitCode: 1, errorMessage: e.message ?? "worker threw" };
48
+ }
49
+ }
50
+ //# sourceMappingURL=worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker.js","sourceRoot":"","sources":["../../../../src/extensions/forgecli/wf-engine/worker.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,kBAAkB,EAClB,qBAAqB,EACrB,WAAW,EACX,aAAa,EACb,cAAc,GAEf,MAAM,iCAAiC,CAAC;AASzC,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAIvC;IACC,MAAM,MAAM,GAAG,IAAI,qBAAqB,CAAC;QACvC,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,QAAQ,EAAE,WAAW,EAAE;QACvB,oBAAoB,EAAE,GAAG,EAAE,CACzB,mEAAmE;cACjE,0EAA0E;cAC1E,2FAA2F;QAC/F,YAAY,EAAE,IAAI;QAClB,QAAQ,EAAE,IAAI;QACd,iBAAiB,EAAE,IAAI;QACvB,cAAc,EAAE,IAAI;KACrB,CAAC,CAAC;IACH,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC;IAEtB,MAAM,WAAW,GAAK,WAAW,CAAC,MAAM,EAAE,CAAC;IAC3C,MAAM,aAAa,GAAG,aAAa,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IAExD,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,kBAAkB,CAAC;QAC3C,cAAc,EAAE,cAAc,CAAC,QAAQ,EAAE;QACzC,WAAW;QACX,aAAa;QACb,cAAc,EAAE,MAAM;KACvB,CAAC,CAAC;IAEH,IAAI,YAAY,GAAG,EAAE,CAAC;IAEtB,MAAM,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,KAAwB,EAAE,EAAE;QAC3D,IAAI,IAAI,CAAC,OAAO;YAAE,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACtC,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YAC/C,MAAM,GAAG,GAAG,KAAK,CAAC,OAAkB,CAAC;YACrC,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;gBAC7B,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;oBAC/B,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;wBAAE,YAAY,IAAI,IAAI,CAAC,IAAI,CAAC;gBACtD,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC1C,KAAK,EAAE,CAAC;QACR,OAAO,CAAC,OAAO,EAAE,CAAC;QAClB,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;IACvC,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,KAAK,EAAE,CAAC;QACR,OAAO,CAAC,OAAO,EAAE,CAAC;QAClB,MAAM,CAAC,GAAG,GAA2B,CAAC;QACtC,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC,OAAO,IAAI,cAAc,EAAE,CAAC;IAClF,CAAC;AACH,CAAC"}