@entelligentsia/forgecli 1.0.21 → 1.0.36

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 (218) hide show
  1. package/CHANGELOG.md +346 -0
  2. package/README.md +2 -0
  3. package/dist/CHANGELOG-forge-plugin.md +281 -0
  4. package/dist/bin/argv.d.ts +2 -2
  5. package/dist/bin/argv.js +25 -0
  6. package/dist/bin/argv.js.map +1 -1
  7. package/dist/bin/forge.js +12 -0
  8. package/dist/bin/forge.js.map +1 -1
  9. package/dist/bin/init.d.ts +23 -0
  10. package/dist/bin/init.js +123 -0
  11. package/dist/bin/init.js.map +1 -0
  12. package/dist/bin/uninstall.d.ts +20 -0
  13. package/dist/bin/uninstall.js +141 -0
  14. package/dist/bin/uninstall.js.map +1 -0
  15. package/dist/extensions/forgecli/claude-bootstrap/bootstrap.d.ts +40 -0
  16. package/dist/extensions/forgecli/claude-bootstrap/bootstrap.js +593 -0
  17. package/dist/extensions/forgecli/claude-bootstrap/bootstrap.js.map +1 -0
  18. package/dist/extensions/forgecli/claude-bootstrap/settings-merge.d.ts +46 -0
  19. package/dist/extensions/forgecli/claude-bootstrap/settings-merge.js +245 -0
  20. package/dist/extensions/forgecli/claude-bootstrap/settings-merge.js.map +1 -0
  21. package/dist/extensions/forgecli/claude-bootstrap/uninstall.d.ts +23 -0
  22. package/dist/extensions/forgecli/claude-bootstrap/uninstall.js +215 -0
  23. package/dist/extensions/forgecli/claude-bootstrap/uninstall.js.map +1 -0
  24. package/dist/extensions/forgecli/dashboard/component.js +10 -7
  25. package/dist/extensions/forgecli/dashboard/component.js.map +1 -1
  26. package/dist/extensions/forgecli/forge-tools.d.ts +1 -0
  27. package/dist/extensions/forgecli/forge-tools.js +73 -0
  28. package/dist/extensions/forgecli/forge-tools.js.map +1 -1
  29. package/dist/extensions/forgecli/lib/forge-root.d.ts +5 -0
  30. package/dist/extensions/forgecli/lib/forge-root.js +14 -1
  31. package/dist/extensions/forgecli/lib/forge-root.js.map +1 -1
  32. package/dist/extensions/forgecli/orchestrators/bug/bug-body.d.ts +1 -0
  33. package/dist/extensions/forgecli/orchestrators/bug/bug-body.js +65 -0
  34. package/dist/extensions/forgecli/orchestrators/bug/bug-body.js.map +1 -0
  35. package/dist/extensions/forgecli/orchestrators/bug/bug-id.d.ts +23 -0
  36. package/dist/extensions/forgecli/orchestrators/bug/bug-id.js +140 -0
  37. package/dist/extensions/forgecli/orchestrators/bug/bug-id.js.map +1 -0
  38. package/dist/extensions/forgecli/orchestrators/bug/bug-phase-dispatch.d.ts +54 -0
  39. package/dist/extensions/forgecli/orchestrators/bug/bug-phase-dispatch.js +349 -0
  40. package/dist/extensions/forgecli/orchestrators/bug/bug-phase-dispatch.js.map +1 -0
  41. package/dist/extensions/forgecli/orchestrators/bug/bug-phases.d.ts +8 -0
  42. package/dist/extensions/forgecli/orchestrators/bug/bug-phases.js +60 -0
  43. package/dist/extensions/forgecli/orchestrators/bug/bug-phases.js.map +1 -0
  44. package/dist/extensions/forgecli/orchestrators/bug/bug-state.d.ts +14 -0
  45. package/dist/extensions/forgecli/orchestrators/bug/bug-state.js +100 -0
  46. package/dist/extensions/forgecli/orchestrators/bug/bug-state.js.map +1 -0
  47. package/dist/extensions/forgecli/orchestrators/bug/bug-triage-routing.d.ts +72 -0
  48. package/dist/extensions/forgecli/orchestrators/bug/bug-triage-routing.js +204 -0
  49. package/dist/extensions/forgecli/orchestrators/bug/bug-triage-routing.js.map +1 -0
  50. package/dist/extensions/forgecli/orchestrators/bug/bug-verdict-loop.d.ts +38 -0
  51. package/dist/extensions/forgecli/orchestrators/bug/bug-verdict-loop.js +166 -0
  52. package/dist/extensions/forgecli/orchestrators/bug/bug-verdict-loop.js.map +1 -0
  53. package/dist/extensions/forgecli/orchestrators/bug/bug-verdict.d.ts +3 -0
  54. package/dist/extensions/forgecli/orchestrators/bug/bug-verdict.js +55 -0
  55. package/dist/extensions/forgecli/orchestrators/bug/bug-verdict.js.map +1 -0
  56. package/dist/extensions/forgecli/orchestrators/bug/run-bug-command.d.ts +7 -0
  57. package/dist/extensions/forgecli/orchestrators/bug/run-bug-command.js +293 -0
  58. package/dist/extensions/forgecli/orchestrators/bug/run-bug-command.js.map +1 -0
  59. package/dist/extensions/forgecli/orchestrators/bug/run-bug-pipeline.d.ts +2 -0
  60. package/dist/extensions/forgecli/orchestrators/bug/run-bug-pipeline.js +501 -0
  61. package/dist/extensions/forgecli/orchestrators/bug/run-bug-pipeline.js.map +1 -0
  62. package/dist/extensions/forgecli/orchestrators/bug/run-bug-types.d.ts +41 -0
  63. package/dist/extensions/forgecli/orchestrators/bug/run-bug-types.js +5 -0
  64. package/dist/extensions/forgecli/orchestrators/bug/run-bug-types.js.map +1 -0
  65. package/dist/extensions/forgecli/orchestrators/common/orchestrator-entry.d.ts +43 -0
  66. package/dist/extensions/forgecli/orchestrators/common/orchestrator-entry.js +85 -0
  67. package/dist/extensions/forgecli/orchestrators/common/orchestrator-entry.js.map +1 -0
  68. package/dist/extensions/forgecli/orchestrators/common/orchestrator-misc.d.ts +8 -0
  69. package/dist/extensions/forgecli/orchestrators/common/orchestrator-misc.js +37 -0
  70. package/dist/extensions/forgecli/orchestrators/common/orchestrator-misc.js.map +1 -0
  71. package/dist/extensions/forgecli/orchestrators/common/orchestrator-notify.d.ts +28 -0
  72. package/dist/extensions/forgecli/orchestrators/common/orchestrator-notify.js +45 -0
  73. package/dist/extensions/forgecli/orchestrators/common/orchestrator-notify.js.map +1 -0
  74. package/dist/extensions/forgecli/orchestrators/common/orchestrator-transcript-session.d.ts +26 -0
  75. package/dist/extensions/forgecli/orchestrators/common/orchestrator-transcript-session.js +75 -0
  76. package/dist/extensions/forgecli/orchestrators/common/orchestrator-transcript-session.js.map +1 -0
  77. package/dist/extensions/forgecli/orchestrators/common/summary-recovery.d.ts +24 -0
  78. package/dist/extensions/forgecli/orchestrators/common/summary-recovery.js +37 -0
  79. package/dist/extensions/forgecli/orchestrators/common/summary-recovery.js.map +1 -0
  80. package/dist/extensions/forgecli/orchestrators/fix-bug.d.ts +9 -92
  81. package/dist/extensions/forgecli/orchestrators/fix-bug.js +23 -1695
  82. package/dist/extensions/forgecli/orchestrators/fix-bug.js.map +1 -1
  83. package/dist/extensions/forgecli/orchestrators/run-sprint.d.ts +3 -12
  84. package/dist/extensions/forgecli/orchestrators/run-sprint.js +97 -270
  85. package/dist/extensions/forgecli/orchestrators/run-sprint.js.map +1 -1
  86. package/dist/extensions/forgecli/orchestrators/run-task.d.ts +10 -214
  87. package/dist/extensions/forgecli/orchestrators/run-task.js +31 -1481
  88. package/dist/extensions/forgecli/orchestrators/run-task.js.map +1 -1
  89. package/dist/extensions/forgecli/orchestrators/sprint/sprint-ceremony.d.ts +33 -0
  90. package/dist/extensions/forgecli/orchestrators/sprint/sprint-ceremony.js +135 -0
  91. package/dist/extensions/forgecli/orchestrators/sprint/sprint-ceremony.js.map +1 -0
  92. package/dist/extensions/forgecli/orchestrators/sprint/sprint-state.d.ts +18 -0
  93. package/dist/extensions/forgecli/orchestrators/sprint/sprint-state.js +55 -0
  94. package/dist/extensions/forgecli/orchestrators/sprint/sprint-state.js.map +1 -0
  95. package/dist/extensions/forgecli/orchestrators/task/run-task-command.d.ts +9 -0
  96. package/dist/extensions/forgecli/orchestrators/task/run-task-command.js +174 -0
  97. package/dist/extensions/forgecli/orchestrators/task/run-task-command.js.map +1 -0
  98. package/dist/extensions/forgecli/orchestrators/task/run-task-pipeline.d.ts +2 -0
  99. package/dist/extensions/forgecli/orchestrators/task/run-task-pipeline.js +494 -0
  100. package/dist/extensions/forgecli/orchestrators/task/run-task-pipeline.js.map +1 -0
  101. package/dist/extensions/forgecli/orchestrators/task/run-task-types.d.ts +62 -0
  102. package/dist/extensions/forgecli/orchestrators/task/run-task-types.js +5 -0
  103. package/dist/extensions/forgecli/orchestrators/task/run-task-types.js.map +1 -0
  104. package/dist/extensions/forgecli/orchestrators/task/task-body.d.ts +4 -0
  105. package/dist/extensions/forgecli/orchestrators/task/task-body.js +48 -0
  106. package/dist/extensions/forgecli/orchestrators/task/task-body.js.map +1 -0
  107. package/dist/extensions/forgecli/orchestrators/task/task-events.d.ts +63 -0
  108. package/dist/extensions/forgecli/orchestrators/task/task-events.js +185 -0
  109. package/dist/extensions/forgecli/orchestrators/task/task-events.js.map +1 -0
  110. package/dist/extensions/forgecli/orchestrators/task/task-gates.d.ts +34 -0
  111. package/dist/extensions/forgecli/orchestrators/task/task-gates.js +78 -0
  112. package/dist/extensions/forgecli/orchestrators/task/task-gates.js.map +1 -0
  113. package/dist/extensions/forgecli/orchestrators/task/task-phase-dispatch.d.ts +42 -0
  114. package/dist/extensions/forgecli/orchestrators/task/task-phase-dispatch.js +370 -0
  115. package/dist/extensions/forgecli/orchestrators/task/task-phase-dispatch.js.map +1 -0
  116. package/dist/extensions/forgecli/orchestrators/task/task-phases.d.ts +14 -0
  117. package/dist/extensions/forgecli/orchestrators/task/task-phases.js +26 -0
  118. package/dist/extensions/forgecli/orchestrators/task/task-phases.js.map +1 -0
  119. package/dist/extensions/forgecli/orchestrators/task/task-record.d.ts +9 -0
  120. package/dist/extensions/forgecli/orchestrators/task/task-record.js +58 -0
  121. package/dist/extensions/forgecli/orchestrators/task/task-record.js.map +1 -0
  122. package/dist/extensions/forgecli/orchestrators/task/task-state.d.ts +14 -0
  123. package/dist/extensions/forgecli/orchestrators/task/task-state.js +35 -0
  124. package/dist/extensions/forgecli/orchestrators/task/task-state.js.map +1 -0
  125. package/dist/extensions/forgecli/orchestrators/task/task-verdict-loop.d.ts +36 -0
  126. package/dist/extensions/forgecli/orchestrators/task/task-verdict-loop.js +152 -0
  127. package/dist/extensions/forgecli/orchestrators/task/task-verdict-loop.js.map +1 -0
  128. package/dist/extensions/forgecli/update/forge-update-command.js +10 -7
  129. package/dist/extensions/forgecli/update/forge-update-command.js.map +1 -1
  130. package/dist/forge-payload/.base-pack/commands/approve.md +2 -2
  131. package/dist/forge-payload/.base-pack/commands/check-agent.md +2 -2
  132. package/dist/forge-payload/.base-pack/commands/collate.md +2 -2
  133. package/dist/forge-payload/.base-pack/commands/commit.md +2 -2
  134. package/dist/forge-payload/.base-pack/commands/enhance.md +2 -2
  135. package/dist/forge-payload/.base-pack/commands/fix-bug.md +2 -2
  136. package/dist/forge-payload/.base-pack/commands/implement.md +2 -2
  137. package/dist/forge-payload/.base-pack/commands/init.md +278 -0
  138. package/dist/forge-payload/.base-pack/commands/new-sprint.md +2 -2
  139. package/dist/forge-payload/.base-pack/commands/plan-sprint.md +2 -2
  140. package/dist/forge-payload/.base-pack/commands/plan.md +2 -2
  141. package/dist/forge-payload/.base-pack/commands/retro.md +2 -2
  142. package/dist/forge-payload/.base-pack/commands/review-code.md +2 -2
  143. package/dist/forge-payload/.base-pack/commands/review-plan.md +2 -2
  144. package/dist/forge-payload/.base-pack/commands/run-sprint.md +2 -2
  145. package/dist/forge-payload/.base-pack/commands/run-task.md +2 -2
  146. package/dist/forge-payload/.base-pack/commands/validate.md +2 -2
  147. package/dist/forge-payload/.base-pack/workflows/_fragments/event-emission-schema.md +4 -0
  148. package/dist/forge-payload/.base-pack/workflows/_fragments/event-vocabulary.md +88 -0
  149. package/dist/forge-payload/.base-pack/workflows/collator_agent.md +5 -6
  150. package/dist/forge-payload/.base-pack/workflows/commit_task.md +41 -38
  151. package/dist/forge-payload/.base-pack/workflows/implement_plan.md +3 -3
  152. package/dist/forge-payload/.base-pack/workflows/migrate_structural.md +1 -1
  153. package/dist/forge-payload/.base-pack/workflows-js/wfl-fix-bug.js +42 -6
  154. package/dist/forge-payload/.base-pack/workflows-js/wfl-init.js +449 -0
  155. package/dist/forge-payload/.base-pack/workflows-js/wfl-run-task.js +32 -1
  156. package/dist/forge-payload/.claude-plugin/plugin.json +1 -1
  157. package/dist/forge-payload/.schemas/enum-catalog.json +2 -2
  158. package/dist/forge-payload/.schemas/event.schema.json +8 -3
  159. package/dist/forge-payload/.schemas/migrations.json +141 -0
  160. package/dist/forge-payload/commands/add-pipeline.md +1 -1
  161. package/dist/forge-payload/commands/add-task.md +3 -3
  162. package/dist/forge-payload/commands/ask.md +1 -1
  163. package/dist/forge-payload/commands/check-agent.md +1 -1
  164. package/dist/forge-payload/commands/config.md +1 -1
  165. package/dist/forge-payload/commands/health.md +1 -1
  166. package/dist/forge-payload/commands/init.md +62 -7
  167. package/dist/forge-payload/commands/rebuild.md +3 -3
  168. package/dist/forge-payload/commands/remove.md +1 -1
  169. package/dist/forge-payload/commands/repair.md +1 -1
  170. package/dist/forge-payload/commands/report-bug.md +1 -1
  171. package/dist/forge-payload/commands/status.md +1 -1
  172. package/dist/forge-payload/commands/update.md +3 -3
  173. package/dist/forge-payload/hooks/lib/common.cjs +228 -0
  174. package/dist/forge-payload/hooks/lib/plugin-detection.cjs +106 -0
  175. package/dist/forge-payload/hooks/lib/update-msg.cjs +23 -0
  176. package/dist/forge-payload/hooks/lib/update-url.cjs +46 -0
  177. package/dist/forge-payload/hooks/lib/write-registry.js +53 -0
  178. package/dist/forge-payload/init/discovery/discover-database.md +32 -0
  179. package/dist/forge-payload/init/discovery/discover-processes.md +31 -0
  180. package/dist/forge-payload/init/discovery/discover-routing.md +31 -0
  181. package/dist/forge-payload/init/discovery/discover-stack.md +33 -0
  182. package/dist/forge-payload/init/discovery/discover-testing.md +34 -0
  183. package/dist/forge-payload/init/generation/generate-commands.md +171 -0
  184. package/dist/forge-payload/init/generation/generate-kb-doc.md +60 -0
  185. package/dist/forge-payload/init/generation/generate-knowledge-base.md +56 -0
  186. package/dist/forge-payload/init/generation/generate-persona.md +73 -0
  187. package/dist/forge-payload/init/generation/generate-personas.md +54 -0
  188. package/dist/forge-payload/init/generation/generate-skill.md +66 -0
  189. package/dist/forge-payload/init/generation/generate-skills.md +36 -0
  190. package/dist/forge-payload/init/generation/generate-template.md +60 -0
  191. package/dist/forge-payload/init/generation/generate-templates.md +39 -0
  192. package/dist/forge-payload/init/generation/generate-tools.md +133 -0
  193. package/dist/forge-payload/init/generation/generate-workflows.md +78 -0
  194. package/dist/forge-payload/init/phases/phase-1-collect.md +10 -2
  195. package/dist/forge-payload/init/phases/phase-3-materialize.md +1 -1
  196. package/dist/forge-payload/init/phases/phase-4-register.md +8 -0
  197. package/dist/forge-payload/init/workflow-gen-plan.json +17 -0
  198. package/dist/forge-payload/integrity.json +16 -16
  199. package/dist/forge-payload/meta/store-schema/event.schema.md +7 -0
  200. package/dist/forge-payload/meta/workflows/_fragments/event-emission-schema.md +4 -0
  201. package/dist/forge-payload/meta/workflows/_fragments/event-vocabulary.md +88 -0
  202. package/dist/forge-payload/meta/workflows/meta-collate.md +5 -6
  203. package/dist/forge-payload/meta/workflows/meta-commit.md +46 -43
  204. package/dist/forge-payload/meta/workflows/meta-fix-bug.md +7 -2
  205. package/dist/forge-payload/meta/workflows/meta-implement.md +3 -3
  206. package/dist/forge-payload/meta/workflows/meta-migrate.md +1 -1
  207. package/dist/forge-payload/meta/workflows/meta-orchestrate.md +4 -1
  208. package/dist/forge-payload/schemas/enum-catalog.json +2 -2
  209. package/dist/forge-payload/schemas/event.schema.json +8 -3
  210. package/dist/forge-payload/schemas/structure-manifest.json +5 -12
  211. package/dist/forge-payload/tools/commit-task.cjs +218 -0
  212. package/dist/forge-payload/tools/forge-preflight.cjs +268 -0
  213. package/dist/forge-payload/tools/lib/paths.cjs +12 -11
  214. package/dist/forge-payload/tools/lib/pricing.cjs +31 -11
  215. package/dist/forge-payload/tools/query-logger.cjs +34 -0
  216. package/dist/forge-payload/tools/store-cli.cjs +6 -1
  217. package/dist/forge-payload/tools/substitute-placeholders.cjs +5 -6
  218. package/package.json +2 -2
@@ -0,0 +1,85 @@
1
+ // orchestrator-entry.ts — shared "common concerns" for orchestrator entry.
2
+ //
3
+ // Three helpers used by all three orchestrator handlers:
4
+ // - gatherModelValidationInputs: the byte-identical persona/pipeline/model
5
+ // catalogue snippet (run-task, fix-bug, run-sprint).
6
+ // - resolveOrchestratorEntry: discover the Forge config, fail-and-clear-status
7
+ // when absent, sweep orphaned transcripts, return resolved tool paths.
8
+ // - runPipelinePreflight: layered-config schema check + full model-config
9
+ // validation (used by run-task and fix-bug; run-sprint keeps its own inline
10
+ // sprint-entry validation per the N-H-D boundary).
11
+ import * as path from "node:path";
12
+ import { fileURLToPath } from "node:url";
13
+ import { loadLayeredConfig } from "../../config/config-layer.js";
14
+ import { readPersonaDir, readPipelineNames } from "../../lib/catalog-helpers.js";
15
+ import { discoverForgeConfigCached } from "../../lib/forge-config.js";
16
+ import { sweepProjectTranscripts } from "../../transcript-archive.js";
17
+ import { runOrchestratorPreflight } from "../orchestrator-preflight.js";
18
+ /** Gather the model-validation inputs shared by every orchestrator entry: the
19
+ * bundled persona catalogue, the project pipeline names, and the session model
20
+ * registry. The persona dir is resolved relative to this module's dist
21
+ * location (orchestrators/common → four levels up to dist/forge-payload). */
22
+ export function gatherModelValidationInputs(cwd, ctx) {
23
+ const personasDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "..", "..", "..", "forge-payload", ".base-pack", "personas");
24
+ const personaCatalogue = readPersonaDir(personasDir);
25
+ const forgeCfgPath = path.join(cwd, ".forge", "config.json");
26
+ const pipelineCatalogue = readPipelineNames(forgeCfgPath);
27
+ const availableModels = (ctx.modelRegistry?.getAvailable?.() ?? []).map((m) => ({ provider: m.provider, id: m.id }));
28
+ return { personaCatalogue, pipelineCatalogue, availableModels };
29
+ }
30
+ /** Discover the Forge config at cwd. On success, sweep orphaned project
31
+ * transcripts and return the resolved tool paths. On failure, notify and clear
32
+ * the status line, then return null (caller returns immediately). */
33
+ export function resolveOrchestratorEntry(opts) {
34
+ const { cwd, notify } = opts;
35
+ const forgeConfig = discoverForgeConfigCached(cwd);
36
+ if (!forgeConfig) {
37
+ notify.error("no Forge project found at cwd. Run /forge:init first.");
38
+ notify.clearStatus();
39
+ return null;
40
+ }
41
+ const forgeRoot = forgeConfig.forgeRoot;
42
+ // Best-effort transcript-archive sweep: adopt any project-local runs not yet
43
+ // in the central index (crash recovery + pre-existing history). Runs BEFORE
44
+ // any pipeline creates its own transcript writer, so in-flight runs are
45
+ // never swept half-written.
46
+ sweepProjectTranscripts(cwd);
47
+ return {
48
+ forgeRoot,
49
+ storeCli: path.join(forgeRoot, "tools", "store-cli.cjs"),
50
+ preflightGate: path.join(forgeRoot, "tools", "preflight-gate.cjs"),
51
+ };
52
+ }
53
+ /** Layered-config schema check followed by full model-config validation.
54
+ * Surfaces schema/validation errors via the notifier (matching the legacy
55
+ * inline strings) and returns the merged routing config on success. */
56
+ export function runPipelinePreflight(opts) {
57
+ const { cwd, ctx, notify } = opts;
58
+ // N-B-E: surface schema errors to caller (Decision 9 — orchestrators
59
+ // fail-fast). See doc/decisions/layered-config-error-policy.md.
60
+ const { merged: modelRoutingConfig, errors: layeredConfigErrors } = loadLayeredConfig(cwd);
61
+ if (layeredConfigErrors.length > 0) {
62
+ for (const e of layeredConfigErrors) {
63
+ notify.error(`forge-cli config schema error: ${e}`);
64
+ }
65
+ return { proceed: false, lastError: `forge-cli config schema errors: ${layeredConfigErrors.join("; ")}` };
66
+ }
67
+ const inputs = gatherModelValidationInputs(cwd, ctx);
68
+ const preflightResult = runOrchestratorPreflight({
69
+ mode: "task",
70
+ ctx,
71
+ notifyPrefix: notify.label,
72
+ personaCatalogue: inputs.personaCatalogue,
73
+ pipelineCatalogue: inputs.pipelineCatalogue,
74
+ modelRoutingConfig,
75
+ availableModels: inputs.availableModels,
76
+ });
77
+ if (!preflightResult.proceed) {
78
+ return {
79
+ proceed: false,
80
+ lastError: preflightResult.result.lastError ?? "model config validation failed",
81
+ };
82
+ }
83
+ return { proceed: true, modelRoutingConfig };
84
+ }
85
+ //# sourceMappingURL=orchestrator-entry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator-entry.js","sourceRoot":"","sources":["../../../../../src/extensions/forgecli/orchestrators/common/orchestrator-entry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export declare function isNonInteractive(): boolean;
2
+ /** Validate that an ID contains no path-traversal characters. */
3
+ export declare function validateId(id: string): boolean;
4
+ /**
5
+ * Format an ISO timestamp for human display in the user's local timezone.
6
+ * Falls back to the raw ISO string if parsing fails.
7
+ */
8
+ export declare function formatLocalTime(iso: string): string;
@@ -0,0 +1,37 @@
1
+ // orchestrator-misc.ts — generic orchestrator helpers shared across the
2
+ // task / sprint / bug pipelines. Extracted from run-task.ts (no logic changes)
3
+ // so the per-file architectural line cap is satisfied; run-task.ts re-exports
4
+ // these for backwards compatibility (fix-bug.ts and run-sprint.ts import them
5
+ // from run-task today).
6
+ // ── Non-interactive helpers ───────────────────────────────────────────────
7
+ export function isNonInteractive() {
8
+ return process.env.FORGE_YES === "1" || process.env.FORGE_NON_INTERACTIVE === "1";
9
+ }
10
+ /** Validate that an ID contains no path-traversal characters. */
11
+ export function validateId(id) {
12
+ return /^[A-Za-z0-9_-]+$/.test(id) && !id.includes("..");
13
+ }
14
+ /**
15
+ * Format an ISO timestamp for human display in the user's local timezone.
16
+ * Falls back to the raw ISO string if parsing fails.
17
+ */
18
+ export function formatLocalTime(iso) {
19
+ const d = new Date(iso);
20
+ if (Number.isNaN(d.getTime()))
21
+ return iso;
22
+ const date = d.toLocaleString(undefined, {
23
+ year: "numeric",
24
+ month: "short",
25
+ day: "2-digit",
26
+ hour: "2-digit",
27
+ minute: "2-digit",
28
+ second: "2-digit",
29
+ hour12: false,
30
+ });
31
+ // Append short timezone abbreviation for unambiguous reading.
32
+ const tz = new Intl.DateTimeFormat(undefined, { timeZoneName: "short" })
33
+ .formatToParts(d)
34
+ .find((p) => p.type === "timeZoneName")?.value ?? "";
35
+ return tz ? `${date} ${tz}` : date;
36
+ }
37
+ //# sourceMappingURL=orchestrator-misc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator-misc.js","sourceRoot":"","sources":["../../../../../src/extensions/forgecli/orchestrators/common/orchestrator-misc.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,+EAA+E;AAC/E,8EAA8E;AAC9E,8EAA8E;AAC9E,wBAAwB;AAExB,6EAA6E;AAE7E,MAAM,UAAU,gBAAgB;IAC/B,OAAO,OAAO,CAAC,GAAG,CAAC,SAAS,KAAK,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC,qBAAqB,KAAK,GAAG,CAAC;AACnF,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,UAAU,CAAC,EAAU;IACpC,OAAO,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAC1D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,GAAW;IAC1C,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC;IACxB,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;QAAE,OAAO,GAAG,CAAC;IAC1C,MAAM,IAAI,GAAG,CAAC,CAAC,cAAc,CAAC,SAAS,EAAE;QACxC,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,OAAO;QACd,GAAG,EAAE,SAAS;QACd,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,SAAS;QACjB,MAAM,EAAE,KAAK;KACb,CAAC,CAAC;IACH,8DAA8D;IAC9D,MAAM,EAAE,GACP,IAAI,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC;SAC3D,aAAa,CAAC,CAAC,CAAC;SAChB,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,cAAc,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC;IACvD,OAAO,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACpC,CAAC"}
@@ -0,0 +1,28 @@
1
+ import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
2
+ type NotifyLevel = Parameters<ExtensionCommandContext["ui"]["notify"]>[1];
3
+ export interface OrchestratorNotifierOptions {
4
+ /** Command label, e.g. "forge:run-task" / "forge:fix-bug" / "forge:run-sprint". */
5
+ label: string;
6
+ /** ctx.ui status key for this command. */
7
+ statusKey: string;
8
+ /** Optional detail-message status key (absent for run-sprint). */
9
+ messageKey?: string;
10
+ }
11
+ export interface OrchestratorNotifier {
12
+ readonly label: string;
13
+ readonly statusKey: string;
14
+ /** Raw passthrough to the live ctx.ui.notify. */
15
+ notify(message: string, level?: NotifyLevel): void;
16
+ /** `× <label> — <msg>` at error level. */
17
+ error(msg: string): void;
18
+ /** `⚠ <label> — <msg>` at warning level. */
19
+ warn(msg: string): void;
20
+ /** `<label> — <msg>` at info level. */
21
+ info(msg: string): void;
22
+ /** Set the command status line. */
23
+ setStatus(text: string): void;
24
+ /** Clear the status key (and message key, if configured). */
25
+ clearStatus(): void;
26
+ }
27
+ export declare function createOrchestratorNotifier(ctx: ExtensionCommandContext, opts: OrchestratorNotifierOptions): OrchestratorNotifier;
28
+ export {};
@@ -0,0 +1,45 @@
1
+ // orchestrator-notify.ts — shared UI-notification facade for the orchestrator
2
+ // pipelines (run-task, fix-bug, run-sprint).
3
+ //
4
+ // Owns the per-command label, the status/message keys, and the two highest-
5
+ // frequency mechanical notification shapes:
6
+ //
7
+ // error(msg) → `× <label> — <msg>` (level "error")
8
+ // warn(msg) → `⚠ <label> — <msg>` (level "warning")
9
+ // info(msg) → `<label> — <msg>` (level "info")
10
+ //
11
+ // The semantic-symbol lines (⊘ cancel, ⟳ loopback, 〇 complete, ✓ phase-done,
12
+ // → phase-start, ▶ dispatch) stay inline at their call sites but are emitted
13
+ // through `notify(...)` so they still hit the transcript recorder.
14
+ //
15
+ // IMPORTANT: every method reads `ctx.ui.notify` LIVE on each call (never a
16
+ // captured/bound reference) so the transcript-recorder swap installed by
17
+ // withOrchestratorTranscript is honored.
18
+ export function createOrchestratorNotifier(ctx, opts) {
19
+ const { label, statusKey, messageKey } = opts;
20
+ return {
21
+ label,
22
+ statusKey,
23
+ notify(message, level) {
24
+ ctx.ui.notify(message, level);
25
+ },
26
+ error(msg) {
27
+ ctx.ui.notify(`× ${label} — ${msg}`, "error");
28
+ },
29
+ warn(msg) {
30
+ ctx.ui.notify(`⚠ ${label} — ${msg}`, "warning");
31
+ },
32
+ info(msg) {
33
+ ctx.ui.notify(`${label} — ${msg}`, "info");
34
+ },
35
+ setStatus(text) {
36
+ ctx.ui.setStatus?.(statusKey, text);
37
+ },
38
+ clearStatus() {
39
+ ctx.ui.setStatus?.(statusKey, undefined);
40
+ if (messageKey)
41
+ ctx.ui.setStatus?.(messageKey, undefined);
42
+ },
43
+ };
44
+ }
45
+ //# sourceMappingURL=orchestrator-notify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator-notify.js","sourceRoot":"","sources":["../../../../../src/extensions/forgecli/orchestrators/common/orchestrator-notify.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,6CAA6C;AAC7C,EAAE;AACF,4EAA4E;AAC5E,4CAA4C;AAC5C,EAAE;AACF,wDAAwD;AACxD,0DAA0D;AAC1D,uDAAuD;AACvD,EAAE;AACF,6EAA6E;AAC7E,6EAA6E;AAC7E,mEAAmE;AACnE,EAAE;AACF,2EAA2E;AAC3E,yEAAyE;AACzE,yCAAyC;AAgCzC,MAAM,UAAU,0BAA0B,CACzC,GAA4B,EAC5B,IAAiC;IAEjC,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC;IAC9C,OAAO;QACN,KAAK;QACL,SAAS;QACT,MAAM,CAAC,OAAe,EAAE,KAAmB;YAC1C,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QAC/B,CAAC;QACD,KAAK,CAAC,GAAW;YAChB,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,KAAK,MAAM,GAAG,EAAE,EAAE,OAAO,CAAC,CAAC;QAC/C,CAAC;QACD,IAAI,CAAC,GAAW;YACf,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,KAAK,MAAM,GAAG,EAAE,EAAE,SAAS,CAAC,CAAC;QACjD,CAAC;QACD,IAAI,CAAC,GAAW;YACf,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,KAAK,MAAM,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC;QAC5C,CAAC;QACD,SAAS,CAAC,IAAY;YACrB,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;QACrC,CAAC;QACD,WAAW;YACV,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;YACzC,IAAI,UAAU;gBAAE,GAAG,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QAC3D,CAAC;KACD,CAAC;AACH,CAAC"}
@@ -0,0 +1,26 @@
1
+ import type { ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
2
+ import type { OrchestratorResult, OrchestratorStatus } from "../../lib/orchestrator-types.js";
3
+ import { OrchestratorTranscriptWriter } from "../../subagent/orchestrator-transcript.js";
4
+ /** Map a pipeline status to the orchestrator-transcript outcome vocabulary.
5
+ * Shared by run-task and fix-bug (same status union). */
6
+ export declare function transcriptOutcomeFor(status: OrchestratorStatus): "complete" | "halted" | "cancelled" | "error";
7
+ /** Handle passed to the inner pipeline loop — exposes the live transcript
8
+ * writer for structured phase-boundary records. */
9
+ export interface OrchestratorTranscriptSession {
10
+ readonly writer: OrchestratorTranscriptWriter;
11
+ }
12
+ export interface WithOrchestratorTranscriptOpts {
13
+ cwd: string;
14
+ entityKind: "bug" | "task" | "sprint";
15
+ entityId: string;
16
+ ctx: ExtensionCommandContext;
17
+ }
18
+ /**
19
+ * Create the orchestrator transcript writer, intercept ctx.ui.notify so every
20
+ * notification is recorded, run `inner(session)`, then close the writer with
21
+ * the result's mapped outcome and surface its path on the result. Restores the
22
+ * original ctx.ui.notify in a finally.
23
+ */
24
+ export declare function withOrchestratorTranscript<T extends OrchestratorResult & {
25
+ orchestratorTranscriptPath?: string;
26
+ }>(opts: WithOrchestratorTranscriptOpts, inner: (session: OrchestratorTranscriptSession) => Promise<T>): Promise<T>;
@@ -0,0 +1,75 @@
1
+ // orchestrator-transcript-session.ts — shared transcript-writing concern for
2
+ // the orchestrator pipelines (run-task, fix-bug).
3
+ //
4
+ // Collapses three byte-identical duplications that previously lived in both
5
+ // run-task.ts and fix-bug.ts:
6
+ // 1. the ctx.ui.notify interception that records every notify line into the
7
+ // orchestrator transcript,
8
+ // 2. the pipeline-wrapper dance (create writer → run inner → close with the
9
+ // mapped outcome → surface the file path), and
10
+ // 3. the status→outcome mapping (transcriptOutcomeFor).
11
+ //
12
+ // Behavior contract preserved exactly:
13
+ // - The writer is created INSIDE this helper, so callers must run their
14
+ // config/preflight early-returns BEFORE calling withOrchestratorTranscript
15
+ // (a failed preflight must not create a transcript file).
16
+ // - On a clean run the inner loop records its own "complete" pipeline-end;
17
+ // OrchestratorTranscriptWriter.record() marks the log closed, so the
18
+ // trailing close() here is an idempotent no-op. On cancel/halt/fail the
19
+ // inner returns without a pipeline-end and this close() is the guarantee
20
+ // that the run is archived with its true outcome.
21
+ // - ctx.ui.notify is restored in a finally, even if inner throws.
22
+ import { getOrchestratorTree } from "../../orchestrator-tree.js";
23
+ import { OrchestratorTranscriptWriter } from "../../subagent/orchestrator-transcript.js";
24
+ /** Map a pipeline status to the orchestrator-transcript outcome vocabulary.
25
+ * Shared by run-task and fix-bug (same status union). */
26
+ export function transcriptOutcomeFor(status) {
27
+ switch (status) {
28
+ case "completed":
29
+ return "complete";
30
+ case "cancelled":
31
+ return "cancelled";
32
+ case "halted":
33
+ case "escalated":
34
+ return "halted";
35
+ case "failed":
36
+ return "error";
37
+ }
38
+ }
39
+ /**
40
+ * Create the orchestrator transcript writer, intercept ctx.ui.notify so every
41
+ * notification is recorded, run `inner(session)`, then close the writer with
42
+ * the result's mapped outcome and surface its path on the result. Restores the
43
+ * original ctx.ui.notify in a finally.
44
+ */
45
+ export async function withOrchestratorTranscript(opts, inner) {
46
+ const { cwd, entityKind, entityId, ctx } = opts;
47
+ const writer = new OrchestratorTranscriptWriter({ cwd, entityKind, entityId });
48
+ const tree = getOrchestratorTree();
49
+ const origNotify = ctx.ui.notify.bind(ctx.ui);
50
+ ctx.ui.notify = ((msg, level) => {
51
+ origNotify(msg, level);
52
+ const text = typeof msg === "string" ? msg : String(msg);
53
+ writer.record({
54
+ kind: "notify",
55
+ ts: new Date().toISOString(),
56
+ level: (level ?? "info"),
57
+ message: text,
58
+ });
59
+ // Mirror the orchestrator's decision log onto its root node so the
60
+ // dashboard surfaces it. Leaf phase nodes carry subagent tool-call
61
+ // activity (via the viewport observer); this root node (entityId) carries
62
+ // the orchestrator's own narrative — gates, verdicts, escalations, halts.
63
+ tree.appendTail(entityId, text, level === "error" || level === "warning" ? { warning: true } : undefined);
64
+ });
65
+ try {
66
+ const result = await inner({ writer });
67
+ writer.close(transcriptOutcomeFor(result.status), result.lastError);
68
+ result.orchestratorTranscriptPath = writer.filePath;
69
+ return result;
70
+ }
71
+ finally {
72
+ ctx.ui.notify = origNotify;
73
+ }
74
+ }
75
+ //# sourceMappingURL=orchestrator-transcript-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator-transcript-session.js","sourceRoot":"","sources":["../../../../../src/extensions/forgecli/orchestrators/common/orchestrator-transcript-session.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,kDAAkD;AAClD,EAAE;AACF,4EAA4E;AAC5E,8BAA8B;AAC9B,8EAA8E;AAC9E,gCAAgC;AAChC,8EAA8E;AAC9E,oDAAoD;AACpD,0DAA0D;AAC1D,EAAE;AACF,uCAAuC;AACvC,0EAA0E;AAC1E,+EAA+E;AAC/E,8DAA8D;AAC9D,6EAA6E;AAC7E,yEAAyE;AACzE,4EAA4E;AAC5E,6EAA6E;AAC7E,sDAAsD;AACtD,oEAAoE;AAKpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,4BAA4B,EAAE,MAAM,2CAA2C,CAAC;AAEzF;0DAC0D;AAC1D,MAAM,UAAU,oBAAoB,CAAC,MAA0B;IAC9D,QAAQ,MAAM,EAAE,CAAC;QAChB,KAAK,WAAW;YACf,OAAO,UAAU,CAAC;QACnB,KAAK,WAAW;YACf,OAAO,WAAW,CAAC;QACpB,KAAK,QAAQ,CAAC;QACd,KAAK,WAAW;YACf,OAAO,QAAQ,CAAC;QACjB,KAAK,QAAQ;YACZ,OAAO,OAAO,CAAC;IACjB,CAAC;AACF,CAAC;AAeD;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAE9C,IAAoC,EAAE,KAA6D;IACpG,MAAM,EAAE,GAAG,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAChD,MAAM,MAAM,GAAG,IAAI,4BAA4B,CAAC,EAAE,GAAG,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC/E,MAAM,IAAI,GAAG,mBAAmB,EAAE,CAAC;IACnC,MAAM,UAAU,GAAyB,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACpE,GAAG,CAAC,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,GAAW,EAAE,KAAwC,EAAE,EAAE;QAC1E,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACvB,MAAM,IAAI,GAAG,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACzD,MAAM,CAAC,MAAM,CAAC;YACb,IAAI,EAAE,QAAQ;YACd,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YAC5B,KAAK,EAAE,CAAC,KAAK,IAAI,MAAM,CAA0C;YACjE,OAAO,EAAE,IAAI;SACb,CAAC,CAAC;QACH,mEAAmE;QACnE,mEAAmE;QACnE,0EAA0E;QAC1E,0EAA0E;QAC1E,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,IAAI,EAAE,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAC3G,CAAC,CAAyB,CAAC;IAE3B,IAAI,CAAC;QACJ,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QACvC,MAAM,CAAC,KAAK,CAAC,oBAAoB,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;QACpE,MAAM,CAAC,0BAA0B,GAAG,MAAM,CAAC,QAAQ,CAAC;QACpD,OAAO,MAAM,CAAC;IACf,CAAC;YAAS,CAAC;QACV,GAAG,CAAC,EAAE,CAAC,MAAM,GAAG,UAAU,CAAC;IAC5B,CAAC;AACF,CAAC"}
@@ -0,0 +1,24 @@
1
+ export interface SummaryRecoveryResult {
2
+ /** Always true — the recovery was attempted (caller decides when to call). */
3
+ attempted: boolean;
4
+ /** True only when set-summary exited 0 (sidecar present + schema-valid). */
5
+ ok: boolean;
6
+ /** Captured stderr for debug logging. */
7
+ stderr: string;
8
+ }
9
+ export interface RecoverPhaseSummaryParams {
10
+ /** Absolute path to the project's store-cli.cjs. */
11
+ storeCli: string;
12
+ /** Task or bug record id whose summary is being registered. */
13
+ entityId: string;
14
+ /** Canonical `summaries.*` store key (e.g. "plan", "code_review"). */
15
+ summaryKey: string;
16
+ cwd: string;
17
+ /** "set-summary" (task, default) or "set-bug-summary" (bug). */
18
+ summaryVerb?: "set-summary" | "set-bug-summary";
19
+ }
20
+ /**
21
+ * Attempt to register a phase's already-written {PHASE}-SUMMARY.json sidecar
22
+ * into the store via store-cli. Returns ok=true only when the verb exits 0.
23
+ */
24
+ export declare function recoverPhaseSummary(p: RecoverPhaseSummaryParams): SummaryRecoveryResult;
@@ -0,0 +1,37 @@
1
+ // summary-recovery.ts — deterministic phase-completion recovery for the
2
+ // orchestrator pipelines (forge-engineering#41).
3
+ //
4
+ // Failure mode: a phase's subagent finalizes in two steps —
5
+ // 1. `forge_artifact write <phase>-summary` → writes the {PHASE}-SUMMARY.json
6
+ // sidecar to the record's path on disk, and
7
+ // 2. `forge_store set-summary <id> <phaseKey>` → ingests that sidecar into
8
+ // `record.summaries.<phaseKey>`.
9
+ // Under turn-budget pressure (or with a weaker model) the subagent stops after
10
+ // step 1 with stopReason=stop, silently eliding step 2. The orchestrator then
11
+ // reads the store, finds no verdict, and hard-fails the phase — forcing the
12
+ // operator to rerun the whole task even though the work artifact is on disk.
13
+ //
14
+ // Recovery: the orchestrator registers the subagent's already-authored sidecar
15
+ // itself by running step 2 (store-cli set-summary / set-bug-summary — the
16
+ // sidecar is auto-resolved from record.path when the file arg is omitted), then
17
+ // re-checks its gate. This does NOT fabricate a verdict (IL10): the verdict
18
+ // content is the subagent's own sidecar; the orchestrator only registers it,
19
+ // exactly as it already emits phase events on the subagent's behalf. When the
20
+ // sidecar is genuinely absent, set-summary exits non-zero and the caller falls
21
+ // through to the existing hard-fail + halt advisor.
22
+ //
23
+ // IL6 — external invocation via spawnSync argv array, no shell interpolation.
24
+ import { spawnSync } from "node:child_process";
25
+ /**
26
+ * Attempt to register a phase's already-written {PHASE}-SUMMARY.json sidecar
27
+ * into the store via store-cli. Returns ok=true only when the verb exits 0.
28
+ */
29
+ export function recoverPhaseSummary(p) {
30
+ const verb = p.summaryVerb ?? "set-summary";
31
+ const r = spawnSync("node", [p.storeCli, verb, p.entityId, p.summaryKey], {
32
+ cwd: p.cwd,
33
+ encoding: "utf8",
34
+ });
35
+ return { attempted: true, ok: r.status === 0, stderr: (r.stderr ?? "").toString() };
36
+ }
37
+ //# sourceMappingURL=summary-recovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summary-recovery.js","sourceRoot":"","sources":["../../../../../src/extensions/forgecli/orchestrators/common/summary-recovery.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,iDAAiD;AACjD,EAAE;AACF,4DAA4D;AAC5D,gFAAgF;AAChF,iDAAiD;AACjD,6EAA6E;AAC7E,sCAAsC;AACtC,+EAA+E;AAC/E,8EAA8E;AAC9E,4EAA4E;AAC5E,6EAA6E;AAC7E,EAAE;AACF,+EAA+E;AAC/E,0EAA0E;AAC1E,gFAAgF;AAChF,4EAA4E;AAC5E,6EAA6E;AAC7E,8EAA8E;AAC9E,+EAA+E;AAC/E,oDAAoD;AACpD,EAAE;AACF,8EAA8E;AAE9E,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAuB/C;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,CAA4B;IAC/D,MAAM,IAAI,GAAG,CAAC,CAAC,WAAW,IAAI,aAAa,CAAC;IAC5C,MAAM,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,UAAU,CAAC,EAAE;QACzE,GAAG,EAAE,CAAC,CAAC,GAAG;QACV,QAAQ,EAAE,MAAM;KAChB,CAAC,CAAC;IACH,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC;AACrF,CAAC"}
@@ -1,93 +1,10 @@
1
- import type { ExtensionAPI, ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
2
- import { type ForgeToolDefs } from "../forge-tools.js";
3
- import { getSessionRegistry } from "../session-registry.js";
4
- import { type PhaseDescriptor } from "./run-task.js";
5
- export declare const BUG_PHASES: PhaseDescriptor[];
1
+ export { BUG_PHASES, BUG_TYPE_TOKENS, postTriageTransitions } from "./bug/bug-phases.js";
2
+ export { type RouteAfterTriageOutcome, type RouteAfterTriageParams, routeAfterTriage, } from "./bug/bug-triage-routing.js";
6
3
  export { BUG_SUMMARY_KEY_BY_ROLE } from "../subagent/phase-summary-map.js";
7
- export declare const BUG_TYPE_TOKENS: Record<string, {
8
- pass: string;
9
- fail: string;
10
- }>;
11
- export interface RunBugState {
12
- bugId: string;
13
- phaseIndex: number;
14
- iterationCounts: Record<string, number>;
15
- halted: boolean;
16
- /** Set on cancellation so the resume prompt says "cancelled" vs "halted". */
17
- status?: "cancelled" | "halted" | "running";
18
- lastError?: string;
19
- savedAt: string;
20
- }
21
- export declare function readBugState(cwd: string, bugId: string, sessionId?: string): RunBugState | null;
22
- export declare function writeBugState(cwd: string, state: RunBugState): void;
23
- export declare function deleteBugState(cwd: string, bugId: string): void;
24
- export declare function isBugStateStale(state: RunBugState): boolean;
25
- export interface BugRecord {
26
- bugId?: string;
27
- status?: string;
28
- summaries?: Record<string, unknown>;
29
- [key: string]: unknown;
30
- }
31
- export declare function readBugRecord(bugId: string, storeCli: string, cwd: string): BugRecord | null;
32
- export declare function computeNextBugId(bugIds: string[], prefix: string): string;
33
- export declare function assignNextBugId(storeCli: string, cwd: string, prefix?: string): string;
34
- export declare function extractBugIdFromReportText(text: string, prefix: string): string | null;
35
- export declare function preCreateBug(bugId: string, title: string, storeCli: string, cwd: string): boolean;
36
- type BugVerdict = "approved" | "revision" | "n/a" | "missing";
37
- export declare function readBugVerdict(bugRecord: BugRecord | null, phaseRole: string, summaryKeyByRole: Record<string, string | null>): BugVerdict;
38
- export declare function composeBugBody(subWorkflowMd: string, bugId: string, phaseRole: string, bugStatusBeforePhase?: string, summariesBlock?: string): string;
39
- /**
40
- * Scan tool_execution_end events to extract the bugId written by a triage
41
- * subagent. Returns the LAST matching tool call's bugId, or null if none found.
42
- *
43
- * In pi runtime, the forge_store tool is registered as "forge_store" (not
44
- * "store-cli"). In Claude Code runtime, subagents may shell out via Bash.
45
- * This function covers all three paths.
46
- */
47
- export declare function extractBugIdFromEvents(events: Array<{
48
- toolName?: string;
49
- result?: unknown;
50
- }>, prefix?: string): string | null;
51
- export type RunBugPipelineStatus = "completed" | "halted" | "escalated" | "failed" | "cancelled";
52
- export interface RunBugPipelineResult {
53
- status: RunBugPipelineStatus;
54
- lastPhaseIndex: number;
55
- iterationCounts: Record<string, number>;
56
- lastError?: string;
57
- model?: string;
58
- provider?: string;
59
- /**
60
- * Project-local orchestrator JSONL path for this run. Callers hand it to
61
- * archiveRun() to mirror the run into the central transcript archive.
62
- * Unset only when the pipeline returned before the writer was created.
63
- */
64
- orchestratorTranscriptPath?: string;
65
- }
66
- export interface RunBugPipelineOptions {
67
- bugId: string;
68
- /** Original free-form text argument when creating a new bug (not a FORGE-BUG-NNN ID).
69
- * Passed to triage-phase subagent so it can create the bug with a meaningful description. */
70
- originalArg?: string;
71
- /** Whether this is a new bug (free-form text) vs. an existing FORGE-BUG-NNN ID. */
72
- isNewBug?: boolean;
73
- cwd: string;
74
- ctx: ExtensionCommandContext;
75
- forgeRoot: string;
76
- storeCli: string;
77
- preflightGate: string;
78
- registry: ReturnType<typeof getSessionRegistry>;
79
- resumeFromState?: RunBugState;
80
- /**
81
- * Optional AbortSignal from SessionRegistry. When provided, the pipeline
82
- * checks signal.aborted between phases and passes the signal to
83
- * runForgeSubagent so in-flight subagents can be aborted.
84
- */
85
- signal?: AbortSignal;
86
- forgeToolDefs?: ForgeToolDefs;
87
- }
88
- export declare function runBugPipeline(opts: RunBugPipelineOptions): Promise<RunBugPipelineResult>;
89
- export interface RegisterFixBugOptions {
90
- cwd?: string;
91
- forgeToolDefs?: ForgeToolDefs;
92
- }
93
- export declare function registerFixBug(pi: ExtensionAPI, options?: RegisterFixBugOptions): void;
4
+ export { deleteBugState, isBugStateStale, readBugState, type RunBugState, writeBugState, } from "./bug/bug-state.js";
5
+ export { assignNextBugId, type BugRecord, computeNextBugId, extractBugIdFromEvents, extractBugIdFromReportText, preCreateBug, readBugRecord, } from "./bug/bug-id.js";
6
+ export { readBugVerdict } from "./bug/bug-verdict.js";
7
+ export { composeBugBody } from "./bug/bug-body.js";
8
+ export { type RunBugPipelineOptions, type RunBugPipelineResult, type RunBugPipelineStatus, } from "./bug/run-bug-types.js";
9
+ export { runBugPipeline } from "./bug/run-bug-pipeline.js";
10
+ export { type RegisterFixBugOptions, registerFixBug } from "./bug/run-bug-command.js";