@entelligentsia/forgecli 1.0.3 → 1.0.14

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 (497) hide show
  1. package/CHANGELOG.md +93 -0
  2. package/README.md +2 -1
  3. package/dist/CHANGELOG-forge-plugin.md +250 -0
  4. package/dist/CHANGELOG-pi.md +94 -0
  5. package/dist/bin/forge.js +0 -0
  6. package/dist/extensions/forgecli/config-layer.d.ts +16 -0
  7. package/dist/extensions/forgecli/config-layer.js +5 -0
  8. package/dist/extensions/forgecli/config-layer.js.map +1 -1
  9. package/dist/extensions/forgecli/dashboard/component.d.ts +102 -0
  10. package/dist/extensions/forgecli/dashboard/component.js +882 -0
  11. package/dist/extensions/forgecli/dashboard/component.js.map +1 -0
  12. package/dist/extensions/forgecli/dashboard/register.d.ts +2 -0
  13. package/dist/extensions/forgecli/dashboard/register.js +45 -0
  14. package/dist/extensions/forgecli/dashboard/register.js.map +1 -0
  15. package/dist/extensions/forgecli/dashboard/view-model.d.ts +35 -0
  16. package/dist/extensions/forgecli/dashboard/view-model.js +54 -0
  17. package/dist/extensions/forgecli/dashboard/view-model.js.map +1 -0
  18. package/dist/extensions/forgecli/fix-bug.js +72 -7
  19. package/dist/extensions/forgecli/fix-bug.js.map +1 -1
  20. package/dist/extensions/forgecli/forge-artifact-tool.js +27 -4
  21. package/dist/extensions/forgecli/forge-artifact-tool.js.map +1 -1
  22. package/dist/extensions/forgecli/forge-cli-schema.json +4 -0
  23. package/dist/extensions/forgecli/forge-commands.js +1 -0
  24. package/dist/extensions/forgecli/forge-commands.js.map +1 -1
  25. package/dist/extensions/forgecli/forge-init/phase4-register.js +53 -0
  26. package/dist/extensions/forgecli/forge-init/phase4-register.js.map +1 -1
  27. package/dist/extensions/forgecli/forge-subagent.js +6 -4
  28. package/dist/extensions/forgecli/forge-subagent.js.map +1 -1
  29. package/dist/extensions/forgecli/forge-tools.js +2 -2
  30. package/dist/extensions/forgecli/forge-tools.js.map +1 -1
  31. package/dist/extensions/forgecli/index.js +5 -0
  32. package/dist/extensions/forgecli/index.js.map +1 -1
  33. package/dist/extensions/forgecli/lib/halt-advisor.d.ts +54 -0
  34. package/dist/extensions/forgecli/lib/halt-advisor.js +90 -0
  35. package/dist/extensions/forgecli/lib/halt-advisor.js.map +1 -0
  36. package/dist/extensions/forgecli/migration-engine.js +25 -12
  37. package/dist/extensions/forgecli/migration-engine.js.map +1 -1
  38. package/dist/extensions/forgecli/orchestrator-status-bar.d.ts +25 -0
  39. package/dist/extensions/forgecli/orchestrator-status-bar.js +183 -0
  40. package/dist/extensions/forgecli/orchestrator-status-bar.js.map +1 -0
  41. package/dist/extensions/forgecli/orchestrator-tree.d.ts +96 -0
  42. package/dist/extensions/forgecli/orchestrator-tree.js +390 -0
  43. package/dist/extensions/forgecli/orchestrator-tree.js.map +1 -0
  44. package/dist/extensions/forgecli/project-orientation.js +12 -8
  45. package/dist/extensions/forgecli/project-orientation.js.map +1 -1
  46. package/dist/extensions/forgecli/regenerate.d.ts +16 -0
  47. package/dist/extensions/forgecli/regenerate.js +110 -0
  48. package/dist/extensions/forgecli/regenerate.js.map +1 -1
  49. package/dist/extensions/forgecli/run-sprint.js +33 -3
  50. package/dist/extensions/forgecli/run-sprint.js.map +1 -1
  51. package/dist/extensions/forgecli/run-task.d.ts +32 -0
  52. package/dist/extensions/forgecli/run-task.js +185 -12
  53. package/dist/extensions/forgecli/run-task.js.map +1 -1
  54. package/dist/extensions/forgecli/subagent/phase-guard.js +15 -5
  55. package/dist/extensions/forgecli/subagent/phase-guard.js.map +1 -1
  56. package/dist/extensions/forgecli/subagent/phase-summary-map.d.ts +1 -0
  57. package/dist/extensions/forgecli/subagent/phase-summary-map.js +17 -0
  58. package/dist/extensions/forgecli/subagent/phase-summary-map.js.map +1 -1
  59. package/dist/extensions/forgecli/thread-switcher.js +105 -764
  60. package/dist/extensions/forgecli/thread-switcher.js.map +1 -1
  61. package/dist/extensions/forgecli/viewport-events.js +32 -0
  62. package/dist/extensions/forgecli/viewport-events.js.map +1 -1
  63. package/dist/forge-payload/.base-pack/commands/fix-bug.md +1 -1
  64. package/dist/forge-payload/.base-pack/commands/run-sprint.md +1 -1
  65. package/dist/forge-payload/.base-pack/commands/run-task.md +1 -1
  66. package/dist/forge-payload/.base-pack/personas/architect.md +1 -1
  67. package/dist/forge-payload/.base-pack/personas/bug-fixer.md +1 -1
  68. package/dist/forge-payload/.base-pack/personas/collator.md +3 -3
  69. package/dist/forge-payload/.base-pack/personas/engineer.md +1 -1
  70. package/dist/forge-payload/.base-pack/personas/librarian.md +1 -1
  71. package/dist/forge-payload/.base-pack/personas/orchestrator.md +1 -1
  72. package/dist/forge-payload/.base-pack/personas/product-manager.md +1 -1
  73. package/dist/forge-payload/.base-pack/personas/qa-engineer.md +1 -1
  74. package/dist/forge-payload/.base-pack/personas/supervisor.md +1 -1
  75. package/dist/forge-payload/.base-pack/workflows/_fragments/event-emission-schema.md +1 -1
  76. package/dist/forge-payload/.base-pack/workflows/_fragments/friction-emit.md +1 -1
  77. package/dist/forge-payload/.base-pack/workflows/_fragments/iron-laws.md +1 -1
  78. package/dist/forge-payload/.base-pack/workflows/_fragments/progress-reporting.md +2 -2
  79. package/dist/forge-payload/.base-pack/workflows/_fragments/store-cli-verbs.md +29 -5
  80. package/dist/forge-payload/.base-pack/workflows/architect_approve.md +8 -10
  81. package/dist/forge-payload/.base-pack/workflows/architect_review_sprint_completion.md +2 -2
  82. package/dist/forge-payload/.base-pack/workflows/architect_sprint_intake.md +2 -2
  83. package/dist/forge-payload/.base-pack/workflows/architect_sprint_plan.md +5 -5
  84. package/dist/forge-payload/.base-pack/workflows/collator_agent.md +5 -7
  85. package/dist/forge-payload/.base-pack/workflows/commit_task.md +7 -9
  86. package/dist/forge-payload/.base-pack/workflows/enhance.md +5 -5
  87. package/dist/forge-payload/.base-pack/workflows/implement_plan.md +9 -9
  88. package/dist/forge-payload/.base-pack/workflows/migrate_structural.md +12 -13
  89. package/dist/forge-payload/.base-pack/workflows/plan_task.md +5 -6
  90. package/dist/forge-payload/.base-pack/workflows/review_code.md +8 -8
  91. package/dist/forge-payload/.base-pack/workflows/review_plan.md +8 -8
  92. package/dist/forge-payload/.base-pack/workflows/sprint_retrospective.md +3 -3
  93. package/dist/forge-payload/.base-pack/workflows/triage.md +13 -10
  94. package/dist/forge-payload/.base-pack/workflows/update_implementation.md +2 -2
  95. package/dist/forge-payload/.base-pack/workflows/update_plan.md +2 -2
  96. package/dist/forge-payload/.base-pack/workflows/validate_task.md +6 -8
  97. package/dist/forge-payload/.base-pack/workflows-js/wfl-fix-bug.js +490 -0
  98. package/dist/forge-payload/.base-pack/workflows-js/wfl-run-sprint.js +416 -0
  99. package/dist/forge-payload/.base-pack/workflows-js/wfl-run-task.js +608 -0
  100. package/dist/forge-payload/.claude-plugin/plugin.json +1 -1
  101. package/dist/forge-payload/.schemas/_defs/locator.schema.json +13 -0
  102. package/dist/forge-payload/.schemas/bug.schema.json +1 -0
  103. package/dist/forge-payload/.schemas/config.schema.json +2 -3
  104. package/dist/forge-payload/.schemas/enum-catalog.json +2 -2
  105. package/dist/forge-payload/.schemas/event.schema.json +16 -0
  106. package/dist/forge-payload/.schemas/migrations.json +299 -0
  107. package/dist/forge-payload/.schemas/sprint.schema.json +1 -0
  108. package/dist/forge-payload/.schemas/task.schema.json +1 -0
  109. package/dist/forge-payload/commands/health.md +29 -0
  110. package/dist/forge-payload/commands/rebuild.md +143 -15
  111. package/dist/forge-payload/commands/update.md +28 -27
  112. package/dist/forge-payload/hooks/preflight-session.cjs +99 -0
  113. package/dist/forge-payload/init/phases/phase-3-materialize.md +18 -5
  114. package/dist/forge-payload/integrity.json +7 -6
  115. package/dist/forge-payload/meta/fragments/tool-discipline.md +1 -1
  116. package/dist/forge-payload/meta/personas/meta-architect.md +1 -1
  117. package/dist/forge-payload/meta/personas/meta-bug-fixer.md +1 -1
  118. package/dist/forge-payload/meta/personas/meta-collator.md +7 -7
  119. package/dist/forge-payload/meta/personas/meta-engineer.md +1 -1
  120. package/dist/forge-payload/meta/personas/meta-orchestrator.md +1 -1
  121. package/dist/forge-payload/meta/personas/meta-supervisor.md +1 -1
  122. package/dist/forge-payload/meta/tool-specs/store-cli.spec.md +1 -1
  123. package/dist/forge-payload/meta/workflows/_fragments/event-emission-schema.md +1 -1
  124. package/dist/forge-payload/meta/workflows/_fragments/friction-emit.md +1 -1
  125. package/dist/forge-payload/meta/workflows/_fragments/iron-laws.md +1 -1
  126. package/dist/forge-payload/meta/workflows/_fragments/progress-reporting.md +2 -2
  127. package/dist/forge-payload/meta/workflows/_fragments/store-cli-verbs.md +29 -5
  128. package/dist/forge-payload/meta/workflows/meta-approve.md +8 -10
  129. package/dist/forge-payload/meta/workflows/meta-bug-triage.md +13 -10
  130. package/dist/forge-payload/meta/workflows/meta-collate.md +6 -8
  131. package/dist/forge-payload/meta/workflows/meta-commit.md +7 -9
  132. package/dist/forge-payload/meta/workflows/meta-enhance.md +5 -5
  133. package/dist/forge-payload/meta/workflows/meta-fix-bug.md +35 -11
  134. package/dist/forge-payload/meta/workflows/meta-implement.md +18 -9
  135. package/dist/forge-payload/meta/workflows/meta-migrate.md +13 -14
  136. package/dist/forge-payload/meta/workflows/meta-new-sprint.md +3 -3
  137. package/dist/forge-payload/meta/workflows/meta-orchestrate.md +175 -82
  138. package/dist/forge-payload/meta/workflows/meta-plan-sprint.md +6 -6
  139. package/dist/forge-payload/meta/workflows/meta-plan-task.md +12 -6
  140. package/dist/forge-payload/meta/workflows/meta-retro.md +4 -4
  141. package/dist/forge-payload/meta/workflows/meta-retrospective.md +4 -4
  142. package/dist/forge-payload/meta/workflows/meta-review-implementation.md +8 -8
  143. package/dist/forge-payload/meta/workflows/meta-review-plan.md +8 -8
  144. package/dist/forge-payload/meta/workflows/meta-review-sprint-completion.md +3 -3
  145. package/dist/forge-payload/meta/workflows/meta-sprint-intake.md +3 -3
  146. package/dist/forge-payload/meta/workflows/meta-sprint-plan.md +6 -6
  147. package/dist/forge-payload/meta/workflows/meta-update-implementation.md +2 -2
  148. package/dist/forge-payload/meta/workflows/meta-update-plan.md +2 -2
  149. package/dist/forge-payload/meta/workflows/meta-validate.md +6 -8
  150. package/dist/forge-payload/schemas/_defs/locator.schema.json +13 -0
  151. package/dist/forge-payload/schemas/bug.schema.json +1 -0
  152. package/dist/forge-payload/schemas/config.schema.json +2 -3
  153. package/dist/forge-payload/schemas/enum-catalog.json +2 -2
  154. package/dist/forge-payload/schemas/event.schema.json +16 -0
  155. package/dist/forge-payload/schemas/sprint.schema.json +1 -0
  156. package/dist/forge-payload/schemas/structure-manifest.json +76 -73
  157. package/dist/forge-payload/schemas/task.schema.json +1 -0
  158. package/dist/forge-payload/skills/refresh-kb-links/SKILL.md +14 -7
  159. package/dist/forge-payload/tools/artifact-store.cjs +242 -0
  160. package/dist/forge-payload/tools/artifact.cjs +60 -120
  161. package/dist/forge-payload/tools/banners.cjs +29 -10
  162. package/dist/forge-payload/tools/check-structure.cjs +88 -7
  163. package/dist/forge-payload/tools/collate.cjs +16 -2
  164. package/dist/forge-payload/tools/lib/artifact-kinds.cjs +95 -0
  165. package/dist/forge-payload/tools/lib/store-nlp.cjs +6 -0
  166. package/dist/forge-payload/tools/lib/store-query-exec.cjs +39 -5
  167. package/dist/forge-payload/tools/lib/suggest.cjs +2 -1
  168. package/dist/forge-payload/tools/manage-config.cjs +5 -7
  169. package/dist/forge-payload/tools/parse-gates.cjs +73 -1
  170. package/dist/forge-payload/tools/postflight-gate.cjs +252 -0
  171. package/dist/forge-payload/tools/preflight-gate.cjs +102 -5
  172. package/dist/forge-payload/tools/store-cli.cjs +50 -15
  173. package/dist/forge-payload/tools/substitute-placeholders.cjs +5 -4
  174. package/dist/forge-payload/tools/verify-phase.cjs +17 -0
  175. package/node_modules/@earendil-works/pi-agent-core/dist/harness/agent-harness.d.ts +5 -2
  176. package/node_modules/@earendil-works/pi-agent-core/dist/harness/agent-harness.d.ts.map +1 -1
  177. package/node_modules/@earendil-works/pi-agent-core/dist/harness/agent-harness.js +81 -18
  178. package/node_modules/@earendil-works/pi-agent-core/dist/harness/agent-harness.js.map +1 -1
  179. package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/branch-summarization.d.ts.map +1 -1
  180. package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/branch-summarization.js +1 -0
  181. package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/branch-summarization.js.map +1 -1
  182. package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.d.ts.map +1 -1
  183. package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.js +19 -24
  184. package/node_modules/@earendil-works/pi-agent-core/dist/harness/compaction/compaction.js.map +1 -1
  185. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/session.d.ts +1 -0
  186. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/session.d.ts.map +1 -1
  187. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/session.js +14 -1
  188. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/session.js.map +1 -1
  189. package/node_modules/@earendil-works/pi-agent-core/dist/harness/types.d.ts +22 -8
  190. package/node_modules/@earendil-works/pi-agent-core/dist/harness/types.d.ts.map +1 -1
  191. package/node_modules/@earendil-works/pi-agent-core/dist/harness/types.js.map +1 -1
  192. package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
  193. package/node_modules/@earendil-works/pi-ai/README.md +1 -1
  194. package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts +374 -122
  195. package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts.map +1 -1
  196. package/node_modules/@earendil-works/pi-ai/dist/models.generated.js +424 -232
  197. package/node_modules/@earendil-works/pi-ai/dist/models.generated.js.map +1 -1
  198. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.d.ts +1 -1
  199. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.d.ts.map +1 -1
  200. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.js +38 -2
  201. package/node_modules/@earendil-works/pi-ai/dist/providers/amazon-bedrock.js.map +1 -1
  202. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
  203. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.js +21 -12
  204. package/node_modules/@earendil-works/pi-ai/dist/providers/anthropic.js.map +1 -1
  205. package/node_modules/@earendil-works/pi-ai/dist/providers/azure-openai-responses.d.ts.map +1 -1
  206. package/node_modules/@earendil-works/pi-ai/dist/providers/azure-openai-responses.js +6 -10
  207. package/node_modules/@earendil-works/pi-ai/dist/providers/azure-openai-responses.js.map +1 -1
  208. package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.d.ts.map +1 -1
  209. package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.js +1 -1
  210. package/node_modules/@earendil-works/pi-ai/dist/providers/google-vertex.js.map +1 -1
  211. package/node_modules/@earendil-works/pi-ai/dist/providers/google.d.ts.map +1 -1
  212. package/node_modules/@earendil-works/pi-ai/dist/providers/google.js +5 -3
  213. package/node_modules/@earendil-works/pi-ai/dist/providers/google.js.map +1 -1
  214. package/node_modules/@earendil-works/pi-ai/dist/providers/images/openrouter.d.ts.map +1 -1
  215. package/node_modules/@earendil-works/pi-ai/dist/providers/images/openrouter.js +3 -4
  216. package/node_modules/@earendil-works/pi-ai/dist/providers/images/openrouter.js.map +1 -1
  217. package/node_modules/@earendil-works/pi-ai/dist/providers/mistral.d.ts.map +1 -1
  218. package/node_modules/@earendil-works/pi-ai/dist/providers/mistral.js +2 -3
  219. package/node_modules/@earendil-works/pi-ai/dist/providers/mistral.js.map +1 -1
  220. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex-responses.d.ts.map +1 -1
  221. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex-responses.js +159 -78
  222. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-codex-responses.js.map +1 -1
  223. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
  224. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-completions.js +16 -11
  225. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-completions.js.map +1 -1
  226. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses-shared.d.ts.map +1 -1
  227. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses-shared.js +4 -1
  228. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses-shared.js.map +1 -1
  229. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses.d.ts.map +1 -1
  230. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses.js +6 -10
  231. package/node_modules/@earendil-works/pi-ai/dist/providers/openai-responses.js.map +1 -1
  232. package/node_modules/@earendil-works/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
  233. package/node_modules/@earendil-works/pi-ai/dist/providers/simple-options.js +1 -0
  234. package/node_modules/@earendil-works/pi-ai/dist/providers/simple-options.js.map +1 -1
  235. package/node_modules/@earendil-works/pi-ai/dist/stream.d.ts.map +1 -1
  236. package/node_modules/@earendil-works/pi-ai/dist/stream.js +14 -2
  237. package/node_modules/@earendil-works/pi-ai/dist/stream.js.map +1 -1
  238. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +14 -4
  239. package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
  240. package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
  241. package/node_modules/@earendil-works/pi-ai/dist/utils/abort-signals.d.ts +6 -0
  242. package/node_modules/@earendil-works/pi-ai/dist/utils/abort-signals.d.ts.map +1 -0
  243. package/node_modules/@earendil-works/pi-ai/dist/utils/abort-signals.js +34 -0
  244. package/node_modules/@earendil-works/pi-ai/dist/utils/abort-signals.js.map +1 -0
  245. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/device-code.d.ts +9 -7
  246. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/device-code.d.ts.map +1 -1
  247. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/device-code.js +8 -7
  248. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/device-code.js.map +1 -1
  249. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
  250. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/github-copilot.js +1 -1
  251. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
  252. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/index.d.ts +1 -1
  253. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/index.d.ts.map +1 -1
  254. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/index.js +1 -1
  255. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/index.js.map +1 -1
  256. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/openai-codex.d.ts +10 -1
  257. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/openai-codex.d.ts.map +1 -1
  258. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/openai-codex.js +179 -79
  259. package/node_modules/@earendil-works/pi-ai/dist/utils/oauth/openai-codex.js.map +1 -1
  260. package/node_modules/@earendil-works/pi-ai/package.json +2 -2
  261. package/node_modules/@earendil-works/pi-coding-agent/CHANGELOG.md +94 -0
  262. package/node_modules/@earendil-works/pi-coding-agent/README.md +9 -0
  263. package/node_modules/@earendil-works/pi-coding-agent/dist/cli/args.d.ts +3 -0
  264. package/node_modules/@earendil-works/pi-coding-agent/dist/cli/args.d.ts.map +1 -1
  265. package/node_modules/@earendil-works/pi-coding-agent/dist/cli/args.js +27 -0
  266. package/node_modules/@earendil-works/pi-coding-agent/dist/cli/args.js.map +1 -1
  267. package/node_modules/@earendil-works/pi-coding-agent/dist/config.d.ts.map +1 -1
  268. package/node_modules/@earendil-works/pi-coding-agent/dist/config.js +15 -2
  269. package/node_modules/@earendil-works/pi-coding-agent/dist/config.js.map +1 -1
  270. package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session-services.d.ts +1 -0
  271. package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session-services.d.ts.map +1 -1
  272. package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session-services.js +1 -0
  273. package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session-services.js.map +1 -1
  274. package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.d.ts +5 -1
  275. package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
  276. package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js +28 -4
  277. package/node_modules/@earendil-works/pi-coding-agent/dist/core/agent-session.js.map +1 -1
  278. package/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
  279. package/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/compaction.js +18 -24
  280. package/node_modules/@earendil-works/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
  281. package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/runner.d.ts +1 -1
  282. package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
  283. package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/runner.js +8 -2
  284. package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
  285. package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/types.d.ts +7 -5
  286. package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
  287. package/node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
  288. package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
  289. package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-registry.js +65 -13
  290. package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-registry.js.map +1 -1
  291. package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
  292. package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-resolver.js +1 -1
  293. package/node_modules/@earendil-works/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
  294. package/node_modules/@earendil-works/pi-coding-agent/dist/core/resolve-config-value.d.ts +9 -1
  295. package/node_modules/@earendil-works/pi-coding-agent/dist/core/resolve-config-value.d.ts.map +1 -1
  296. package/node_modules/@earendil-works/pi-coding-agent/dist/core/resolve-config-value.js +134 -11
  297. package/node_modules/@earendil-works/pi-coding-agent/dist/core/resolve-config-value.js.map +1 -1
  298. package/node_modules/@earendil-works/pi-coding-agent/dist/core/sdk.d.ts +2 -0
  299. package/node_modules/@earendil-works/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
  300. package/node_modules/@earendil-works/pi-coding-agent/dist/core/sdk.js +10 -6
  301. package/node_modules/@earendil-works/pi-coding-agent/dist/core/sdk.js.map +1 -1
  302. package/node_modules/@earendil-works/pi-coding-agent/dist/core/session-manager.d.ts +6 -7
  303. package/node_modules/@earendil-works/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
  304. package/node_modules/@earendil-works/pi-coding-agent/dist/core/session-manager.js +75 -28
  305. package/node_modules/@earendil-works/pi-coding-agent/dist/core/session-manager.js.map +1 -1
  306. package/node_modules/@earendil-works/pi-coding-agent/dist/core/settings-manager.d.ts +2 -0
  307. package/node_modules/@earendil-works/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  308. package/node_modules/@earendil-works/pi-coding-agent/dist/core/settings-manager.js +14 -9
  309. package/node_modules/@earendil-works/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  310. package/node_modules/@earendil-works/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  311. package/node_modules/@earendil-works/pi-coding-agent/dist/core/system-prompt.js +0 -3
  312. package/node_modules/@earendil-works/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  313. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
  314. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/edit.js +7 -10
  315. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
  316. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/find.d.ts.map +1 -1
  317. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/find.js.map +1 -1
  318. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/grep.d.ts.map +1 -1
  319. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/grep.js.map +1 -1
  320. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/ls.d.ts.map +1 -1
  321. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/ls.js +5 -7
  322. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/ls.js.map +1 -1
  323. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
  324. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/read.js +6 -7
  325. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/read.js.map +1 -1
  326. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/render-utils.d.ts +5 -2
  327. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/render-utils.d.ts.map +1 -1
  328. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/render-utils.js +17 -1
  329. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/render-utils.js.map +1 -1
  330. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
  331. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/write.js +5 -6
  332. package/node_modules/@earendil-works/pi-coding-agent/dist/core/tools/write.js.map +1 -1
  333. package/node_modules/@earendil-works/pi-coding-agent/dist/index.d.ts +2 -0
  334. package/node_modules/@earendil-works/pi-coding-agent/dist/index.d.ts.map +1 -1
  335. package/node_modules/@earendil-works/pi-coding-agent/dist/index.js +2 -0
  336. package/node_modules/@earendil-works/pi-coding-agent/dist/index.js.map +1 -1
  337. package/node_modules/@earendil-works/pi-coding-agent/dist/main.d.ts.map +1 -1
  338. package/node_modules/@earendil-works/pi-coding-agent/dist/main.js +69 -16
  339. package/node_modules/@earendil-works/pi-coding-agent/dist/main.js.map +1 -1
  340. package/node_modules/@earendil-works/pi-coding-agent/dist/migrations.d.ts.map +1 -1
  341. package/node_modules/@earendil-works/pi-coding-agent/dist/migrations.js +118 -1
  342. package/node_modules/@earendil-works/pi-coding-agent/dist/migrations.js.map +1 -1
  343. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts +1 -3
  344. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  345. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/login-dialog.js +2 -4
  346. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/login-dialog.js.map +1 -1
  347. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  348. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/user-message.js +1 -1
  349. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/components/user-message.js.map +1 -1
  350. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +3 -0
  351. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  352. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.js +59 -6
  353. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  354. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  355. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/theme/theme.js +10 -0
  356. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/interactive/theme/theme.js.map +1 -1
  357. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  358. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-mode.js +3 -1
  359. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-mode.js.map +1 -1
  360. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts +1 -0
  361. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  362. package/node_modules/@earendil-works/pi-coding-agent/dist/modes/rpc/rpc-types.js.map +1 -1
  363. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/deprecation.d.ts +4 -0
  364. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/deprecation.d.ts.map +1 -0
  365. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/deprecation.js +13 -0
  366. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/deprecation.js.map +1 -0
  367. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/json.d.ts +3 -0
  368. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/json.d.ts.map +1 -0
  369. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/json.js +7 -0
  370. package/node_modules/@earendil-works/pi-coding-agent/dist/utils/json.js.map +1 -0
  371. package/node_modules/@earendil-works/pi-coding-agent/docs/custom-provider.md +13 -10
  372. package/node_modules/@earendil-works/pi-coding-agent/docs/development.md +1 -1
  373. package/node_modules/@earendil-works/pi-coding-agent/docs/extensions.md +12 -6
  374. package/node_modules/@earendil-works/pi-coding-agent/docs/models.md +25 -12
  375. package/node_modules/@earendil-works/pi-coding-agent/docs/providers.md +13 -5
  376. package/node_modules/@earendil-works/pi-coding-agent/docs/quickstart.md +1 -0
  377. package/node_modules/@earendil-works/pi-coding-agent/docs/rpc.md +2 -1
  378. package/node_modules/@earendil-works/pi-coding-agent/docs/sdk.md +6 -0
  379. package/node_modules/@earendil-works/pi-coding-agent/docs/session-format.md +1 -1
  380. package/node_modules/@earendil-works/pi-coding-agent/docs/sessions.md +8 -0
  381. package/node_modules/@earendil-works/pi-coding-agent/docs/settings.md +7 -3
  382. package/node_modules/@earendil-works/pi-coding-agent/docs/terminal-setup.md +2 -0
  383. package/node_modules/@earendil-works/pi-coding-agent/docs/tui.md +2 -2
  384. package/node_modules/@earendil-works/pi-coding-agent/docs/usage.md +9 -0
  385. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/README.md +1 -0
  386. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/custom-provider-anthropic/index.ts +1 -1
  387. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/custom-provider-anthropic/package.json +1 -1
  388. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/custom-provider-gitlab-duo/index.ts +54 -3
  389. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  390. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/git-merge-and-resolve.ts +115 -0
  391. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/input-transform-streaming.ts +39 -0
  392. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/sandbox/package.json +1 -1
  393. package/node_modules/@earendil-works/pi-coding-agent/examples/extensions/with-deps/package.json +1 -1
  394. package/node_modules/@earendil-works/pi-coding-agent/npm-shrinkwrap.json +443 -61
  395. package/node_modules/@earendil-works/pi-coding-agent/package.json +6 -6
  396. package/node_modules/@earendil-works/pi-tui/README.md +2 -2
  397. package/node_modules/@earendil-works/pi-tui/dist/components/editor.d.ts.map +1 -1
  398. package/node_modules/@earendil-works/pi-tui/dist/components/editor.js +24 -83
  399. package/node_modules/@earendil-works/pi-tui/dist/components/editor.js.map +1 -1
  400. package/node_modules/@earendil-works/pi-tui/dist/components/input.d.ts.map +1 -1
  401. package/node_modules/@earendil-works/pi-tui/dist/components/input.js +7 -55
  402. package/node_modules/@earendil-works/pi-tui/dist/components/input.js.map +1 -1
  403. package/node_modules/@earendil-works/pi-tui/dist/components/markdown.d.ts +7 -1
  404. package/node_modules/@earendil-works/pi-tui/dist/components/markdown.d.ts.map +1 -1
  405. package/node_modules/@earendil-works/pi-tui/dist/components/markdown.js +12 -2
  406. package/node_modules/@earendil-works/pi-tui/dist/components/markdown.js.map +1 -1
  407. package/node_modules/@earendil-works/pi-tui/dist/index.d.ts +1 -1
  408. package/node_modules/@earendil-works/pi-tui/dist/index.d.ts.map +1 -1
  409. package/node_modules/@earendil-works/pi-tui/dist/index.js.map +1 -1
  410. package/node_modules/@earendil-works/pi-tui/dist/terminal-image.d.ts +1 -1
  411. package/node_modules/@earendil-works/pi-tui/dist/terminal-image.d.ts.map +1 -1
  412. package/node_modules/@earendil-works/pi-tui/dist/terminal-image.js +34 -7
  413. package/node_modules/@earendil-works/pi-tui/dist/terminal-image.js.map +1 -1
  414. package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts +33 -10
  415. package/node_modules/@earendil-works/pi-tui/dist/terminal.d.ts.map +1 -1
  416. package/node_modules/@earendil-works/pi-tui/dist/terminal.js +172 -37
  417. package/node_modules/@earendil-works/pi-tui/dist/terminal.js.map +1 -1
  418. package/node_modules/@earendil-works/pi-tui/dist/utils.d.ts +6 -1
  419. package/node_modules/@earendil-works/pi-tui/dist/utils.d.ts.map +1 -1
  420. package/node_modules/@earendil-works/pi-tui/dist/utils.js +27 -15
  421. package/node_modules/@earendil-works/pi-tui/dist/utils.js.map +1 -1
  422. package/node_modules/@earendil-works/pi-tui/dist/word-navigation.d.ts +25 -0
  423. package/node_modules/@earendil-works/pi-tui/dist/word-navigation.d.ts.map +1 -0
  424. package/node_modules/@earendil-works/pi-tui/dist/word-navigation.js +96 -0
  425. package/node_modules/@earendil-works/pi-tui/dist/word-navigation.js.map +1 -0
  426. package/node_modules/@earendil-works/pi-tui/package.json +2 -2
  427. package/node_modules/@entelligentsia/forge-compress/LICENSE +21 -0
  428. package/node_modules/@entelligentsia/forge-compress/README.md +85 -0
  429. package/node_modules/@mariozechner/clipboard/Cargo.toml +3 -3
  430. package/node_modules/@mariozechner/clipboard/index.d.ts +34 -20
  431. package/node_modules/@mariozechner/clipboard/index.js +546 -257
  432. package/node_modules/@mariozechner/clipboard/package.json +5 -6
  433. package/node_modules/@mariozechner/clipboard/package.json.prepack-backup +14 -14
  434. package/node_modules/@mariozechner/clipboard/src/lib.rs +4 -9
  435. package/node_modules/@mariozechner/clipboard-linux-x64-gnu/clipboard.linux-x64-gnu.node +0 -0
  436. package/node_modules/@mariozechner/clipboard-linux-x64-gnu/package.json +2 -2
  437. package/package.json +7 -7
  438. package/dist/bin/forgecli.d.ts +0 -2
  439. package/dist/bin/forgecli.js +0 -6
  440. package/dist/bin/forgecli.js.map +0 -1
  441. package/dist/extensions/forgecli/config-tui/index.d.ts +0 -5
  442. package/dist/extensions/forgecli/config-tui/index.js +0 -5
  443. package/dist/extensions/forgecli/config-tui/index.js.map +0 -1
  444. package/dist/extensions/forgecli/loaders/persona-skill-loader.d.ts +0 -45
  445. package/dist/extensions/forgecli/loaders/persona-skill-loader.js +0 -227
  446. package/dist/extensions/forgecli/loaders/persona-skill-loader.js.map +0 -1
  447. package/dist/extensions/forgecli/loaders/template-render.d.ts +0 -20
  448. package/dist/extensions/forgecli/loaders/template-render.js +0 -85
  449. package/dist/extensions/forgecli/loaders/template-render.js.map +0 -1
  450. package/dist/extensions/forgecli/loaders/workflow-loader.d.ts +0 -41
  451. package/dist/extensions/forgecli/loaders/workflow-loader.js +0 -164
  452. package/dist/extensions/forgecli/loaders/workflow-loader.js.map +0 -1
  453. package/dist/forge-payload/.base-pack/commands/quiz-agent.md +0 -6
  454. package/dist/forge-payload/.base-pack/commands/retrospective.md +0 -6
  455. package/dist/forge-payload/.base-pack/commands/sprint-intake.md +0 -6
  456. package/dist/forge-payload/.base-pack/commands/sprint-plan.md +0 -6
  457. package/dist/forge-payload/.base-pack/workflows/fix_bug.md +0 -446
  458. package/dist/forge-payload/.base-pack/workflows/orchestrate_task.md +0 -934
  459. package/dist/forge-payload/.base-pack/workflows/run_sprint.md +0 -225
  460. package/dist/forge-payload/commands/calibrate.md +0 -10
  461. package/dist/forge-payload/commands/materialize.md +0 -119
  462. package/dist/forge-payload/commands/migrate.md +0 -12
  463. package/dist/forge-payload/commands/quiz-agent.md +0 -6
  464. package/dist/forge-payload/commands/regenerate.md +0 -6
  465. package/dist/forge-payload/commands/store-query.md +0 -6
  466. package/dist/forge-payload/commands/store-repair.md +0 -6
  467. package/dist/forge-payload/commands/update-tools.md +0 -10
  468. package/dist/forge-payload/meta/templates/meta-retrospective.md +0 -28
  469. package/dist/forge-payload/tools/prompts/sprint-plan-prompt.md +0 -70
  470. package/dist/forge-payload/tools/schemas/task-list.schema.json +0 -53
  471. package/node_modules/@earendil-works/pi-agent-core/dist/harness/execution-env.d.ts +0 -4
  472. package/node_modules/@earendil-works/pi-agent-core/dist/harness/execution-env.d.ts.map +0 -1
  473. package/node_modules/@earendil-works/pi-agent-core/dist/harness/execution-env.js +0 -3
  474. package/node_modules/@earendil-works/pi-agent-core/dist/harness/execution-env.js.map +0 -1
  475. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/jsonl.d.ts +0 -20
  476. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/jsonl.d.ts.map +0 -1
  477. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/jsonl.js +0 -92
  478. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/jsonl.js.map +0 -1
  479. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/memory.d.ts +0 -18
  480. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/memory.d.ts.map +0 -1
  481. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/memory.js +0 -42
  482. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/memory.js.map +0 -1
  483. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/shared.d.ts +0 -10
  484. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/shared.d.ts.map +0 -1
  485. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/shared.js +0 -31
  486. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/repo/shared.js.map +0 -1
  487. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/storage/jsonl.d.ts +0 -30
  488. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/storage/jsonl.d.ts.map +0 -1
  489. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/storage/jsonl.js +0 -170
  490. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/storage/jsonl.js.map +0 -1
  491. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/storage/memory.d.ts +0 -26
  492. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/storage/memory.d.ts.map +0 -1
  493. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/storage/memory.js +0 -90
  494. package/node_modules/@earendil-works/pi-agent-core/dist/harness/session/storage/memory.js.map +0 -1
  495. package/node_modules/@mariozechner/clipboard-linux-x64-musl/README.md +0 -3
  496. package/node_modules/@mariozechner/clipboard-linux-x64-musl/clipboard.linux-x64-musl.node +0 -0
  497. package/node_modules/@mariozechner/clipboard-linux-x64-musl/package.json +0 -25
@@ -0,0 +1,252 @@
1
+ 'use strict';
2
+
3
+ // postflight-gate.cjs — evaluates a phase's declared outputs block against
4
+ // the filesystem / task state, post-subagent-return. Returns structured failure
5
+ // data so the orchestrator (run-task.ts) can halt before FSM advance when outputs
6
+ // are not satisfied.
7
+ //
8
+ // Pure function: only fs.existsSync / fs.statSync / fs.readFileSync. No writes,
9
+ // no network, no LLM, no process spawns.
10
+ //
11
+ // CLI shim: node postflight-gate.cjs --phase <name> --task <taskId>
12
+ // Exit codes: 0 (ok), 1 (guard failed), 2 (invalid args / parse error)
13
+ // Stdout on exit 1: single JSON line { phase, reasonCode, detail, remediation }
14
+ //
15
+ // New reasonCodes (FORGE-S26-T19):
16
+ // output-missing — artifact path does not exist
17
+ // output-stub — artifact exists but size < min= bytes
18
+ // require-failed — require predicate over state field failed
19
+ // tool-error — internal parse or store-read failure
20
+
21
+ const fs = require('node:fs');
22
+ const path = require('node:path');
23
+
24
+ /**
25
+ * postflight({ phase, outputs, state, substitutions })
26
+ *
27
+ * @param {string} phase - Phase name (e.g. 'implement')
28
+ * @param {object} outputs - Parsed outputs spec from parseOutputs() — { [phase]: { artifacts, require } }
29
+ * @param {object} [state] - Task/bug state for require predicates (e.g. { task: {...} })
30
+ * @param {object} [substitutions] - Template variable substitutions (e.g. { engineering, sprint, task })
31
+ * @returns {{ ok: boolean, missing: string[], reasonCode: string, detail: string, remediation: string }}
32
+ */
33
+ function postflight({ phase, outputs, state = {}, substitutions = {} }) {
34
+ const spec = outputs && outputs[phase];
35
+ if (!spec) {
36
+ // No outputs block for this phase — pass through (no-op)
37
+ return { ok: true, missing: [], reasonCode: null, detail: '', remediation: '' };
38
+ }
39
+
40
+ const missing = [];
41
+
42
+ for (const art of spec.artifacts || []) {
43
+ const resolved = applySubstitutions(art.path, substitutions);
44
+ let exists = false;
45
+ let size = 0;
46
+ try {
47
+ const st = fs.statSync(resolved);
48
+ exists = st.isFile();
49
+ size = st.size;
50
+ } catch (_) {
51
+ exists = false;
52
+ }
53
+ if (!exists) {
54
+ missing.push(`output-missing: artifact absent: ${resolved}`);
55
+ } else if (size < (art.minBytes || 0)) {
56
+ missing.push(
57
+ `output-stub: artifact too small: ${resolved} (${size} bytes, need >= ${art.minBytes})`,
58
+ );
59
+ }
60
+ }
61
+
62
+ for (const pred of spec.require || []) {
63
+ if (!evalPredicate(pred, state)) {
64
+ missing.push(
65
+ `require-failed: ${describePredicate(pred)} (got ${JSON.stringify(readField(pred.field, state))})`,
66
+ );
67
+ }
68
+ }
69
+
70
+ if (missing.length === 0) {
71
+ return { ok: true, missing: [], reasonCode: null, detail: '', remediation: '' };
72
+ }
73
+
74
+ const { reasonCode, detail, remediation } = buildStructuredFailure(phase, missing);
75
+ return { ok: false, missing, reasonCode, detail, remediation };
76
+ }
77
+
78
+ function applySubstitutions(template, subs) {
79
+ return template.replace(/\{(\w+)\}/g, (full, key) => {
80
+ if (Object.prototype.hasOwnProperty.call(subs, key)) return String(subs[key]);
81
+ return full;
82
+ });
83
+ }
84
+
85
+ function readField(dottedPath, state) {
86
+ const parts = dottedPath.split('.');
87
+ let cur = state;
88
+ for (const p of parts) {
89
+ if (cur === null || cur === undefined) return undefined;
90
+ cur = cur[p];
91
+ }
92
+ return cur;
93
+ }
94
+
95
+ function evalPredicate(pred, state) {
96
+ const actual = readField(pred.field, state);
97
+ switch (pred.op) {
98
+ case '==':
99
+ return String(actual) === String(pred.value);
100
+ case '!=':
101
+ return String(actual) !== String(pred.value);
102
+ case 'in':
103
+ return (pred.value || []).map(String).includes(String(actual));
104
+ default:
105
+ throw new Error(`postflight-gate: unknown predicate op "${pred.op}"`);
106
+ }
107
+ }
108
+
109
+ function describePredicate(pred) {
110
+ if (pred.op === 'in') return `${pred.field} in [${(pred.value || []).join(', ')}]`;
111
+ return `${pred.field} ${pred.op} ${pred.value}`;
112
+ }
113
+
114
+ function buildStructuredFailure(phase, missing) {
115
+ let reasonCode = 'tool-error';
116
+ const detailParts = [];
117
+
118
+ for (const m of missing) {
119
+ detailParts.push(m);
120
+ if (reasonCode === 'tool-error') {
121
+ if (/^output-missing/i.test(m)) {
122
+ reasonCode = 'output-missing';
123
+ } else if (/^output-stub/i.test(m)) {
124
+ reasonCode = 'output-stub';
125
+ } else if (/^require-failed/i.test(m)) {
126
+ reasonCode = 'require-failed';
127
+ }
128
+ }
129
+ }
130
+
131
+ const detail = detailParts.join('; ');
132
+
133
+ const remediationMap = {
134
+ 'output-missing': 'Re-run the phase that produces this artifact (e.g. /forge:implement), then retry.',
135
+ 'output-stub': 'The artifact was produced but appears incomplete (stub). Ensure the phase wrote a complete file.',
136
+ 'require-failed': 'Correct the task/bug state so it satisfies the postflight require predicate, then retry.',
137
+ 'tool-error': 'Check the outputs block configuration and store records; run node .forge/tools/postflight-gate.cjs manually for diagnostics.',
138
+ };
139
+
140
+ return {
141
+ reasonCode,
142
+ detail,
143
+ remediation: remediationMap[reasonCode],
144
+ };
145
+ }
146
+
147
+ module.exports = { postflight };
148
+
149
+ // CLI shim — only runs when invoked directly
150
+ if (require.main === module) {
151
+ const args = parseArgs(process.argv.slice(2));
152
+ if (!args.phase || !args.task) {
153
+ process.stderr.write('Usage: postflight-gate.cjs --phase <phaseName> --task <taskId>\n');
154
+ process.exit(2);
155
+ }
156
+
157
+ const { parseOutputs } = require('./parse-gates.cjs');
158
+
159
+ // Resolve config
160
+ let engineeringRoot = 'engineering';
161
+ try {
162
+ const cfg = JSON.parse(fs.readFileSync(path.resolve(process.cwd(), '.forge/config.json'), 'utf8'));
163
+ if (cfg.paths && cfg.paths.engineering) engineeringRoot = cfg.paths.engineering;
164
+ } catch (_) { /* fall back to default */ }
165
+
166
+ // Load task record
167
+ let taskRecord = null;
168
+ try {
169
+ const store = require('./store.cjs');
170
+ taskRecord = store.getTask(args.task);
171
+ } catch (_) {
172
+ // store.cjs not available or task not found — continue with substitutions from args
173
+ }
174
+
175
+ // Build substitutions
176
+ const sprintId = taskRecord ? taskRecord.sprintId : undefined;
177
+ const substitutions = {
178
+ engineering: engineeringRoot,
179
+ sprint: sprintId,
180
+ task: args.task,
181
+ };
182
+
183
+ // Load workflow markdown (scan .forge/workflows/ for phase)
184
+ const workflowMd = loadWorkflowMarkdown(args.phase);
185
+ if (!workflowMd) {
186
+ process.stderr.write(`postflight-gate: no outputs block defined for phase "${args.phase}" — skipping\n`);
187
+ process.exit(0);
188
+ }
189
+
190
+ let outputs;
191
+ try {
192
+ outputs = parseOutputs(workflowMd);
193
+ } catch (err) {
194
+ process.stderr.write(`postflight-gate: ${err.message}\n`);
195
+ process.exit(2);
196
+ }
197
+
198
+ if (!outputs[args.phase]) {
199
+ process.stderr.write(`postflight-gate: no outputs block for phase "${args.phase}" — skipping\n`);
200
+ process.exit(0);
201
+ }
202
+
203
+ // Build state from task record
204
+ const state = {};
205
+ if (taskRecord) state.task = taskRecord;
206
+
207
+ const result = postflight({ phase: args.phase, outputs, state, substitutions });
208
+
209
+ if (result.ok) process.exit(0);
210
+
211
+ process.stderr.write(`Postflight guard failed for phase "${args.phase}":\n`);
212
+ for (const m of result.missing) process.stderr.write(` - ${m}\n`);
213
+
214
+ // Emit structured JSON on stdout for orchestrators
215
+ process.stdout.write(JSON.stringify({
216
+ phase: args.phase,
217
+ reasonCode: result.reasonCode,
218
+ detail: result.detail,
219
+ remediation: result.remediation,
220
+ }) + '\n');
221
+ process.exit(1);
222
+ }
223
+
224
+ function parseArgs(argv) {
225
+ const out = {};
226
+ for (let i = 0; i < argv.length; i++) {
227
+ const a = argv[i];
228
+ if (a === '--phase') out.phase = argv[++i];
229
+ else if (a === '--task') out.task = argv[++i];
230
+ }
231
+ return out;
232
+ }
233
+
234
+ function loadWorkflowMarkdown(phaseName) {
235
+ const workflowsDir = path.resolve(process.cwd(), '.forge/workflows');
236
+ let entries;
237
+ try {
238
+ entries = fs.readdirSync(workflowsDir).filter((f) => f.endsWith('.md'));
239
+ } catch (_) {
240
+ return null;
241
+ }
242
+ const fencePattern = new RegExp('^```outputs\\s+phase=' + escapeRegex(phaseName) + '\\s*$', 'm');
243
+ for (const entry of entries) {
244
+ const md = fs.readFileSync(path.join(workflowsDir, entry), 'utf8');
245
+ if (fencePattern.test(md)) return md;
246
+ }
247
+ return null;
248
+ }
249
+
250
+ function escapeRegex(s) {
251
+ return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
252
+ }
@@ -113,7 +113,49 @@ function describePredicate(pred) {
113
113
  return `${pred.field} ${pred.op} ${pred.value}`;
114
114
  }
115
115
 
116
- module.exports = { preflight, resolveTaskArtifactDir, resolveSprintArtifactDir };
116
+ module.exports = { preflight, resolveTaskArtifactDir, resolveSprintArtifactDir, deriveSprintTaskFromArtifactPath };
117
+
118
+ // Derive {sprint} and {task} substitutions directly from a task's artifact path
119
+ // (task.path) when that path is a directory under `<engineeringRoot>/sprints/`.
120
+ //
121
+ // task.path is the authoritative artifact location — it is where the plan /
122
+ // implement phases actually write PLAN.md, REVIEW.md, etc. Splitting it tolerates
123
+ // ANY nesting depth and ANY on-disk naming, so a single rule covers both the
124
+ // modern 2-level layout (`sprints/<sprint>/<task>/`) and legacy 3-level layouts
125
+ // (`sprints/<sprint>/tasks/<task>/`) whose on-disk sprint dir name need not equal
126
+ // sprintId (e.g. sprintId "S19" → dir "sprint_19_platform_ux_improvements"). The
127
+ // directory-scan resolution (resolveSprintArtifactDir + resolveTaskArtifactDir)
128
+ // cannot express the `tasks/` nesting, which is what broke review-plan preflight
129
+ // for heterogeneous-layout projects (walkinto.in S19/S32/S33).
130
+ //
131
+ // {task} = the last path segment (the artifact directory name)
132
+ // {sprint} = everything between `sprints/` and that last segment, joined by "/"
133
+ //
134
+ // File-vs-dir guard: if task.path ends in a filename (has an extension), the
135
+ // artifact directory is its PARENT — strip the filename first. This prevents the
136
+ // bogus `.../TASK_PROMPT.md/PLAN.md` (ENOTDIR) seen when a project stores
137
+ // task.path as a file inside the artifact dir.
138
+ //
139
+ // Returns null when the path is absent, or not under `<engineeringRoot>/sprints/`
140
+ // (e.g. a forge/ source-file path — see regression S12-T06), or resolves to
141
+ // fewer than 2 directory segments. In every null case the caller falls back to
142
+ // the directory-scan resolution, preserving prior behaviour.
143
+ function deriveSprintTaskFromArtifactPath(taskPath, engineeringRoot) {
144
+ if (!taskPath) return null;
145
+ let norm = String(taskPath).replace(/\\/g, '/').replace(/\/+$/, '');
146
+ // File-vs-dir guard — drop a trailing filename so we split on the dir.
147
+ if (/\.[a-zA-Z0-9]+$/.test(norm)) {
148
+ norm = norm.replace(/\/[^/]*$/, '');
149
+ }
150
+ const er = String(engineeringRoot || 'engineering').replace(/\/+$/, '');
151
+ const prefix = er + '/sprints/';
152
+ if (!norm.startsWith(prefix)) return null;
153
+ const segs = norm.slice(prefix.length).split('/').filter(Boolean);
154
+ if (segs.length < 2) return null;
155
+ const task = segs[segs.length - 1];
156
+ const sprint = segs.slice(0, -1).join('/');
157
+ return { sprint, task };
158
+ }
117
159
 
118
160
  // CLI shim: `node preflight-gate.cjs --phase <name> --task <taskId> [--bug <bugId>] [--workflow <name>]`
119
161
  // exit codes: 0 ok, 1 gate(s) failed, 2 invalid args / missing definitions
@@ -246,10 +288,18 @@ if (require.main === module) {
246
288
  // name is used both as the {sprint} substitution and as the directory in
247
289
  // which resolveTaskArtifactDir scans for task subdirectories.
248
290
  const sprintId = taskRecord ? taskRecord.sprintId : undefined;
249
- const resolvedSprintDir = sprintId
250
- ? (resolveSprintArtifactDir(sprintId, engineeringRoot) || sprintId)
251
- : undefined;
252
- const taskArtifactDir = resolveTaskArtifactDir(taskRecord, engineeringRoot, undefined, resolvedSprintDir);
291
+ // Primary resolution: derive {sprint}/{task} straight from task.path (the
292
+ // authoritative artifact directory). This honours arbitrary layout nesting —
293
+ // including legacy 3-level `sprints/<sprint>/tasks/<task>/` trees the
294
+ // directory-scan resolution below cannot express. Falls back to the scan when
295
+ // task.path is not an artifact dir under sprints/ (e.g. a forge/ source file).
296
+ const derived = taskRecord ? deriveSprintTaskFromArtifactPath(taskRecord.path, engineeringRoot) : null;
297
+ const resolvedSprintDir = derived
298
+ ? derived.sprint
299
+ : (sprintId ? (resolveSprintArtifactDir(sprintId, engineeringRoot) || sprintId) : undefined);
300
+ const taskArtifactDir = derived
301
+ ? derived.task
302
+ : resolveTaskArtifactDir(taskRecord, engineeringRoot, undefined, resolvedSprintDir);
253
303
  // Fallback: if task.path points to a file (e.g., TASK_PROMPT.md) we want
254
304
  // the *directory* segment, not the filename. Without this, a project that
255
305
  // stores task.path as the prompt file would propagate "TASK_PROMPT.md" as
@@ -299,9 +349,56 @@ if (require.main === module) {
299
349
  if (result.ok) process.exit(0);
300
350
  process.stderr.write(`Gate failed for phase "${args.phase}":\n`);
301
351
  for (const m of result.missing) process.stderr.write(` - ${m}\n`);
352
+ // Emit structured JSON on stdout for orchestrators to parse and render.
353
+ // Shape: { phase, reasonCode, detail, remediation }
354
+ const structured = buildStructuredFailure(args.phase, result.missing);
355
+ process.stdout.write(JSON.stringify(structured) + '\n');
302
356
  process.exit(1);
303
357
  }
304
358
 
359
+ // Build a structured gate-failure object for orchestrators.
360
+ // Maps the human-readable `missing[]` strings to a typed { phase, reasonCode, detail, remediation }.
361
+ // reasonCode is derived from the dominant failure pattern:
362
+ // artifact-missing — artifact missing / too small
363
+ // predecessor-verdict-missing — after-clause verdict absent or wrong
364
+ // illegal-status — require/forbid predicate fired
365
+ // tool-error — internal error / unrecognised pattern
366
+ // When multiple failures exist, reasonCode reflects the first recognised pattern;
367
+ // detail combines all messages; only a single JSON object is ever emitted.
368
+ function buildStructuredFailure(phase, missing) {
369
+ let reasonCode = 'tool-error';
370
+ const detailParts = [];
371
+
372
+ for (const m of missing) {
373
+ detailParts.push(m);
374
+ if (reasonCode === 'tool-error') {
375
+ if (/^artifact (missing|too small)/i.test(m)) {
376
+ reasonCode = 'artifact-missing';
377
+ } else if (/^predecessor verdict (missing|unreadable)/i.test(m) || /verdict is "/i.test(m)) {
378
+ reasonCode = 'predecessor-verdict-missing';
379
+ } else if (/^(require failed|forbid triggered)/i.test(m)) {
380
+ reasonCode = 'illegal-status';
381
+ }
382
+ }
383
+ }
384
+
385
+ const detail = detailParts.join('; ');
386
+
387
+ const remediationMap = {
388
+ 'artifact-missing': `Re-run the phase that produces this artifact (e.g. /forge:plan or /forge:implement), then retry.`,
389
+ 'predecessor-verdict-missing': `Ensure the predecessor review phase completed and recorded a verdict via set-summary, then retry.`,
390
+ 'illegal-status': `Correct the task/bug status (use store-cli update-status) so it satisfies the gate predicate, then retry.`,
391
+ 'tool-error': `Check the gate configuration and store records for this task; run node .forge/tools/preflight-gate.cjs manually for diagnostics.`,
392
+ };
393
+
394
+ return {
395
+ phase,
396
+ reasonCode,
397
+ detail,
398
+ remediation: remediationMap[reasonCode],
399
+ };
400
+ }
401
+
305
402
  function parseArgs(argv) {
306
403
  const out = {};
307
404
  for (let i = 0; i < argv.length; i++) {
@@ -55,6 +55,7 @@ const { validateRecord, NULLABLE_FIELDS } = require('./lib/validate.js');
55
55
 
56
56
  // FORGE-S22-T03: suggestion engine for "Did you mean?" on validation/transition errors
57
57
  const { suggest, suggestEntityType, formatSuggestion } = require('./lib/suggest.cjs');
58
+ const { resolveSummaryFilename, PHASE_TO_KIND } = require('./lib/artifact-kinds.cjs');
58
59
 
59
60
  // Valid phase keys for summaries (dot-delimited → underscore in JSON key)
60
61
  const VALID_SUMMARY_PHASES = new Set(['plan', 'review_plan', 'implementation', 'code_review', 'validation', 'triage', 'approve']);
@@ -432,8 +433,8 @@ Commands:
432
433
  progress-clear <sprintOrBugId> Clear (truncate) the progress log
433
434
  write-collation-state '<json>' Write COLLATION_STATE.json
434
435
  validate <entity> '<json>' Validate against schema without writing
435
- set-summary <taskId> <phase> <jsonFile> Set a phase summary on a task record
436
- set-bug-summary <bugId> <phase> <jsonFile> Set a phase summary on a bug record
436
+ set-summary <taskId> <phase> [<jsonFile>] Set a phase summary on a task record (sidecar auto-resolved from record.path when jsonFile omitted)
437
+ set-bug-summary <bugId> <phase> [<jsonFile>] Set a phase summary on a bug record (sidecar auto-resolved from record.path when jsonFile omitted)
437
438
  describe <entity> Print the JSON Schema for an entity
438
439
  template <entity> Print a canonical sample record (required fields populated)
439
440
 
@@ -1289,9 +1290,50 @@ function _setSummaryOnEntity(entityKind, entityId, phase, summaryFilePath) {
1289
1290
  process.exit(1);
1290
1291
  }
1291
1292
 
1293
+ // Load entity first — its `path` is the authoritative artifact directory and
1294
+ // is needed both to self-resolve the sidecar (when no file arg is given) and
1295
+ // to merge the summary below.
1296
+ const record = entityKind === 'task' ? store.getTask(entityId) : store.getBug(entityId);
1297
+ if (!record) {
1298
+ console.error(`${entityKind} not found: ${entityId}`);
1299
+ process.exit(1);
1300
+ }
1301
+
1302
+ // ADR artifact-resolution Phase 1: when the caller omits the JSON file, derive
1303
+ // the sidecar from record.path + the canonical phase→filename map. The agent
1304
+ // never hand-builds the path (kills the Class-1 failures + the arity bug).
1305
+ let selfResolved = false;
1306
+ if (!summaryFilePath) {
1307
+ if (typeof record.path !== 'string' || record.path.length === 0) {
1308
+ console.error(`Cannot self-resolve summary sidecar: ${entityKind} ${entityId} has no "path". Pass an explicit <jsonFile>.`);
1309
+ process.exit(1);
1310
+ }
1311
+ // record.path is the entity directory; defensively strip a trailing filename.
1312
+ const dir = /\.(md|json)$/i.test(record.path) ? path.dirname(record.path) : record.path;
1313
+ summaryFilePath = path.join(dir, resolveSummaryFilename(entityKind, phase));
1314
+ selfResolved = true;
1315
+ }
1316
+
1292
1317
  // Read and validate summary JSON
1293
1318
  if (!fs.existsSync(summaryFilePath)) {
1294
- console.error(`Summary file not found: ${summaryFilePath}`);
1319
+ // v1.0.10: self-resolve looks for the CANONICAL filename. If an agent wrote a
1320
+ // non-canonical sidecar (e.g. VALIDATE-SUMMARY.json via the Write tool instead
1321
+ // of forge_artifact's VALIDATION-SUMMARY.json), surface the near-name file so
1322
+ // the error is fixable in one step rather than a silent dead-end.
1323
+ let hint = '';
1324
+ if (selfResolved) {
1325
+ try {
1326
+ const dir = path.dirname(summaryFilePath);
1327
+ const expected = path.basename(summaryFilePath);
1328
+ const nearby = fs.readdirSync(dir).filter((f) => f !== expected && f.endsWith('.json') && /summary/i.test(f));
1329
+ if (nearby.length > 0) {
1330
+ const kind = PHASE_TO_KIND[phase];
1331
+ hint = ` (expected ${expected}; found ${nearby.join(', ')} in the same dir — write the sidecar via ` +
1332
+ `forge_artifact artifact:"${kind}", or rename it to ${expected})`;
1333
+ }
1334
+ } catch (_) { /* dir unreadable — fall back to the plain message */ }
1335
+ }
1336
+ console.error(`Summary file not found: ${summaryFilePath}${hint}`);
1295
1337
  process.exit(1);
1296
1338
  }
1297
1339
 
@@ -1309,14 +1351,7 @@ function _setSummaryOnEntity(entityKind, entityId, phase, summaryFilePath) {
1309
1351
  process.exit(1);
1310
1352
  }
1311
1353
 
1312
- // Load entity
1313
- const record = entityKind === 'task' ? store.getTask(entityId) : store.getBug(entityId);
1314
- if (!record) {
1315
- console.error(`${entityKind} not found: ${entityId}`);
1316
- process.exit(1);
1317
- }
1318
-
1319
- // Merge summary
1354
+ // Merge summary (record was loaded above for path resolution)
1320
1355
  if (!record.summaries) record.summaries = {};
1321
1356
  record.summaries[phase] = summary;
1322
1357
 
@@ -1394,8 +1429,8 @@ function cmdSetSummary() {
1394
1429
  const phase = args[2];
1395
1430
  const summaryFile = args[3];
1396
1431
 
1397
- if (!taskId || !phase || !summaryFile) {
1398
- console.error('Usage: store-cli.cjs set-summary <taskId> <phase> <jsonFile>');
1432
+ if (!taskId || !phase) {
1433
+ console.error('Usage: store-cli.cjs set-summary <taskId> <phase> [<jsonFile>]');
1399
1434
  process.exit(1);
1400
1435
  }
1401
1436
 
@@ -1407,8 +1442,8 @@ function cmdSetBugSummary() {
1407
1442
  const phase = args[2];
1408
1443
  const summaryFile = args[3];
1409
1444
 
1410
- if (!bugId || !phase || !summaryFile) {
1411
- console.error('Usage: store-cli.cjs set-bug-summary <bugId> <phase> <jsonFile>');
1445
+ if (!bugId || !phase) {
1446
+ console.error('Usage: store-cli.cjs set-bug-summary <bugId> <phase> [<jsonFile>]');
1412
1447
  process.exit(1);
1413
1448
  }
1414
1449
 
@@ -120,10 +120,11 @@ const RUNTIME_PASSTHROUGH_KEYS = new Set([
120
120
  * project prefix via getCommandsSubdir() — see walkBasePack.
121
121
  */
122
122
  const SUBDIR_OUTPUT_MAP = {
123
- personas: path.join('.forge', 'personas'),
124
- skills: path.join('.forge', 'skills'),
125
- workflows: path.join('.forge', 'workflows'),
126
- templates: path.join('.forge', 'templates'),
123
+ personas: path.join('.forge', 'personas'),
124
+ skills: path.join('.forge', 'skills'),
125
+ workflows: path.join('.forge', 'workflows'),
126
+ templates: path.join('.forge', 'templates'),
127
+ 'workflows-js': path.join('.claude', 'workflows'),
127
128
  };
128
129
 
129
130
  /**
@@ -194,6 +194,14 @@ function verifyPhase2(cwd, kbPath) {
194
194
 
195
195
  const PHASE3_DIRS = ['workflows', 'personas', 'skills', 'templates'];
196
196
 
197
+ // JS workflow files that substitute-placeholders.cjs emits from
198
+ // base-pack/workflows-js/ into .claude/workflows/ (FORGE-S28-T01).
199
+ // These are checked in addition to the .forge/ directory checks.
200
+ const PHASE3_JS_FILES = [
201
+ path.join('.claude', 'workflows', 'wfl-run-task.js'),
202
+ path.join('.claude', 'workflows', 'wfl-run-sprint.js'),
203
+ ];
204
+
197
205
  function verifyPhase3(cwd) {
198
206
  const missing = [];
199
207
  const checked = [];
@@ -213,6 +221,15 @@ function verifyPhase3(cwd) {
213
221
  }
214
222
  }
215
223
 
224
+ // Assert generated JS workflow files are present (FORGE-S28-T01)
225
+ for (const relFile of PHASE3_JS_FILES) {
226
+ checked.push(relFile);
227
+ const absFile = path.join(cwd, relFile);
228
+ if (!fs.existsSync(absFile)) {
229
+ missing.push(relFile);
230
+ }
231
+ }
232
+
216
233
  return {
217
234
  phase: 3,
218
235
  ok: missing.length === 0,
@@ -36,6 +36,7 @@ export declare class AgentHarness<TSkill extends Skill = Skill, TPromptTemplate
36
36
  private createStreamFn;
37
37
  private drainQueuedMessages;
38
38
  private createLoopConfig;
39
+ private validateUniqueNames;
39
40
  private validateToolNames;
40
41
  private flushPendingSessionWrites;
41
42
  private handleAgentEvent;
@@ -69,9 +70,12 @@ export declare class AgentHarness<TSkill extends Skill = Skill, TPromptTemplate
69
70
  label?: string;
70
71
  }): Promise<NavigateTreeResult>;
71
72
  getModel(): Model<any>;
72
- getThinkingLevel(): ThinkingLevel;
73
73
  setModel(model: Model<any>): Promise<void>;
74
+ getThinkingLevel(): ThinkingLevel;
74
75
  setThinkingLevel(level: ThinkingLevel): Promise<void>;
76
+ getTools(): TTool[];
77
+ setTools(tools: TTool[], activeToolNames?: string[]): Promise<void>;
78
+ getActiveTools(): TTool[];
75
79
  setActiveTools(toolNames: string[]): Promise<void>;
76
80
  getSteeringMode(): QueueMode;
77
81
  setSteeringMode(mode: QueueMode): Promise<void>;
@@ -81,7 +85,6 @@ export declare class AgentHarness<TSkill extends Skill = Skill, TPromptTemplate
81
85
  setResources(resources: AgentHarnessResources<TSkill, TPromptTemplate>): Promise<void>;
82
86
  getStreamOptions(): AgentHarnessStreamOptions;
83
87
  setStreamOptions(streamOptions: AgentHarnessStreamOptions): Promise<void>;
84
- setTools(tools: TTool[], activeToolNames?: string[]): Promise<void>;
85
88
  abort(): Promise<AbortResult>;
86
89
  waitForIdle(): Promise<void>;
87
90
  subscribe(listener: (event: AgentHarnessEvent<TSkill, TPromptTemplate>, signal?: AbortSignal) => Promise<void> | void): () => void;