@entelligentsia/forgecli 1.0.20 → 1.0.21

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 (324) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/README.md +7 -1
  3. package/dist/bin/config.js +4 -4
  4. package/dist/bin/config.js.map +1 -1
  5. package/dist/bin/update-cli.d.ts +1 -1
  6. package/dist/bin/update-cli.js +1 -1
  7. package/dist/bin/update-cli.js.map +1 -1
  8. package/dist/extensions/forgecli/ask-user-tool.js +1 -1
  9. package/dist/extensions/forgecli/ask-user-tool.js.map +1 -1
  10. package/dist/extensions/forgecli/commands/add-pipeline.d.ts +19 -0
  11. package/dist/extensions/forgecli/commands/add-pipeline.js +143 -0
  12. package/dist/extensions/forgecli/commands/add-pipeline.js.map +1 -0
  13. package/dist/extensions/forgecli/commands/add-task.d.ts +20 -0
  14. package/dist/extensions/forgecli/commands/add-task.js +154 -0
  15. package/dist/extensions/forgecli/commands/add-task.js.map +1 -0
  16. package/dist/extensions/forgecli/commands/approve.d.ts +22 -0
  17. package/dist/extensions/forgecli/commands/approve.js +152 -0
  18. package/dist/extensions/forgecli/commands/approve.js.map +1 -0
  19. package/dist/extensions/forgecli/commands/collate.d.ts +22 -0
  20. package/dist/extensions/forgecli/commands/collate.js +134 -0
  21. package/dist/extensions/forgecli/commands/collate.js.map +1 -0
  22. package/dist/extensions/forgecli/commands/commit.d.ts +22 -0
  23. package/dist/extensions/forgecli/commands/commit.js +152 -0
  24. package/dist/extensions/forgecli/commands/commit.js.map +1 -0
  25. package/dist/extensions/forgecli/commands/config-command.d.ts +8 -0
  26. package/dist/extensions/forgecli/commands/config-command.js +67 -0
  27. package/dist/extensions/forgecli/commands/config-command.js.map +1 -0
  28. package/dist/extensions/forgecli/commands/enhance.d.ts +45 -0
  29. package/dist/extensions/forgecli/commands/enhance.js +219 -0
  30. package/dist/extensions/forgecli/commands/enhance.js.map +1 -0
  31. package/dist/extensions/forgecli/commands/implement.d.ts +22 -0
  32. package/dist/extensions/forgecli/commands/implement.js +170 -0
  33. package/dist/extensions/forgecli/commands/implement.js.map +1 -0
  34. package/dist/extensions/forgecli/commands/plan.d.ts +22 -0
  35. package/dist/extensions/forgecli/commands/plan.js +167 -0
  36. package/dist/extensions/forgecli/commands/plan.js.map +1 -0
  37. package/dist/extensions/forgecli/commands/quiz-agent.d.ts +17 -0
  38. package/dist/extensions/forgecli/commands/quiz-agent.js +98 -0
  39. package/dist/extensions/forgecli/commands/quiz-agent.js.map +1 -0
  40. package/dist/extensions/forgecli/commands/read-command.d.ts +2 -0
  41. package/dist/extensions/forgecli/commands/read-command.js +100 -0
  42. package/dist/extensions/forgecli/commands/read-command.js.map +1 -0
  43. package/dist/extensions/forgecli/commands/regenerate.d.ts +40 -0
  44. package/dist/extensions/forgecli/commands/regenerate.js +426 -0
  45. package/dist/extensions/forgecli/commands/regenerate.js.map +1 -0
  46. package/dist/extensions/forgecli/commands/remove-command.d.ts +17 -0
  47. package/dist/extensions/forgecli/commands/remove-command.js +124 -0
  48. package/dist/extensions/forgecli/commands/remove-command.js.map +1 -0
  49. package/dist/extensions/forgecli/commands/report-bug.d.ts +25 -0
  50. package/dist/extensions/forgecli/commands/report-bug.js +159 -0
  51. package/dist/extensions/forgecli/commands/report-bug.js.map +1 -0
  52. package/dist/extensions/forgecli/commands/retrospective.d.ts +20 -0
  53. package/dist/extensions/forgecli/commands/retrospective.js +126 -0
  54. package/dist/extensions/forgecli/commands/retrospective.js.map +1 -0
  55. package/dist/extensions/forgecli/commands/review-code.d.ts +35 -0
  56. package/dist/extensions/forgecli/commands/review-code.js +196 -0
  57. package/dist/extensions/forgecli/commands/review-code.js.map +1 -0
  58. package/dist/extensions/forgecli/commands/review-plan.d.ts +35 -0
  59. package/dist/extensions/forgecli/commands/review-plan.js +200 -0
  60. package/dist/extensions/forgecli/commands/review-plan.js.map +1 -0
  61. package/dist/extensions/forgecli/commands/sprint-intake.d.ts +10 -0
  62. package/dist/extensions/forgecli/commands/sprint-intake.js +91 -0
  63. package/dist/extensions/forgecli/commands/sprint-intake.js.map +1 -0
  64. package/dist/extensions/forgecli/commands/sprint-plan.d.ts +14 -0
  65. package/dist/extensions/forgecli/commands/sprint-plan.js +122 -0
  66. package/dist/extensions/forgecli/commands/sprint-plan.js.map +1 -0
  67. package/dist/extensions/forgecli/commands/status-command.d.ts +19 -0
  68. package/dist/extensions/forgecli/commands/status-command.js +140 -0
  69. package/dist/extensions/forgecli/commands/status-command.js.map +1 -0
  70. package/dist/extensions/forgecli/commands/store-query.d.ts +22 -0
  71. package/dist/extensions/forgecli/commands/store-query.js +107 -0
  72. package/dist/extensions/forgecli/commands/store-query.js.map +1 -0
  73. package/dist/extensions/forgecli/commands/store-repair.d.ts +17 -0
  74. package/dist/extensions/forgecli/commands/store-repair.js +123 -0
  75. package/dist/extensions/forgecli/commands/store-repair.js.map +1 -0
  76. package/dist/extensions/forgecli/commands/test-orchestrate.d.ts +2 -0
  77. package/dist/extensions/forgecli/commands/test-orchestrate.js +182 -0
  78. package/dist/extensions/forgecli/commands/test-orchestrate.js.map +1 -0
  79. package/dist/extensions/forgecli/commands/transcripts-command.d.ts +87 -0
  80. package/dist/extensions/forgecli/commands/transcripts-command.js +418 -0
  81. package/dist/extensions/forgecli/commands/transcripts-command.js.map +1 -0
  82. package/dist/extensions/forgecli/commands/validate.d.ts +22 -0
  83. package/dist/extensions/forgecli/commands/validate.js +152 -0
  84. package/dist/extensions/forgecli/commands/validate.js.map +1 -0
  85. package/dist/extensions/forgecli/config/config-layer.d.ts +53 -0
  86. package/dist/extensions/forgecli/config/config-layer.js +72 -0
  87. package/dist/extensions/forgecli/config/config-layer.js.map +1 -0
  88. package/dist/extensions/forgecli/config/config-writer.d.ts +16 -0
  89. package/dist/extensions/forgecli/config/config-writer.js +69 -0
  90. package/dist/extensions/forgecli/config/config-writer.js.map +1 -0
  91. package/dist/extensions/forgecli/config/model-registry.d.ts +61 -0
  92. package/dist/extensions/forgecli/config/model-registry.js +127 -0
  93. package/dist/extensions/forgecli/config/model-registry.js.map +1 -0
  94. package/dist/extensions/forgecli/config/model-resolver.d.ts +32 -0
  95. package/dist/extensions/forgecli/config/model-resolver.js +65 -0
  96. package/dist/extensions/forgecli/config/model-resolver.js.map +1 -0
  97. package/dist/extensions/forgecli/config/model-validator.d.ts +29 -0
  98. package/dist/extensions/forgecli/config/model-validator.js +107 -0
  99. package/dist/extensions/forgecli/config/model-validator.js.map +1 -0
  100. package/dist/extensions/forgecli/config-tui/component.js +1 -1
  101. package/dist/extensions/forgecli/config-tui/component.js.map +1 -1
  102. package/dist/extensions/forgecli/config-tui/handler.js +1 -1
  103. package/dist/extensions/forgecli/config-tui/handler.js.map +1 -1
  104. package/dist/extensions/forgecli/config-tui/screens/override-editor.js +1 -1
  105. package/dist/extensions/forgecli/config-tui/screens/override-editor.js.map +1 -1
  106. package/dist/extensions/forgecli/config-tui/screens/overrides-list-phases.js +1 -1
  107. package/dist/extensions/forgecli/config-tui/screens/overrides-list-phases.js.map +1 -1
  108. package/dist/extensions/forgecli/config-tui/screens/show-resolved.js +1 -1
  109. package/dist/extensions/forgecli/config-tui/screens/show-resolved.js.map +1 -1
  110. package/dist/extensions/forgecli/config-tui/state/buffer.d.ts +2 -2
  111. package/dist/extensions/forgecli/config-tui/state/model.d.ts +1 -1
  112. package/dist/extensions/forgecli/config-tui/state/reducer.js.map +1 -1
  113. package/dist/extensions/forgecli/config-tui/state/selectors.d.ts +2 -2
  114. package/dist/extensions/forgecli/config-tui/state/selectors.js +1 -1
  115. package/dist/extensions/forgecli/config-tui/state/selectors.js.map +1 -1
  116. package/dist/extensions/forgecli/context-governor-compaction.d.ts +13 -2
  117. package/dist/extensions/forgecli/context-governor-compaction.js +66 -41
  118. package/dist/extensions/forgecli/context-governor-compaction.js.map +1 -1
  119. package/dist/extensions/forgecli/context-governor.d.ts +3 -7
  120. package/dist/extensions/forgecli/context-governor.js +43 -69
  121. package/dist/extensions/forgecli/context-governor.js.map +1 -1
  122. package/dist/extensions/forgecli/dashboard/component.d.ts +10 -1
  123. package/dist/extensions/forgecli/dashboard/component.js +84 -18
  124. package/dist/extensions/forgecli/dashboard/component.js.map +1 -1
  125. package/dist/extensions/forgecli/dashboard/register.js +1 -1
  126. package/dist/extensions/forgecli/dashboard/register.js.map +1 -1
  127. package/dist/extensions/forgecli/forge-artifact-tool.js +1 -1
  128. package/dist/extensions/forgecli/forge-commands.js +1 -1
  129. package/dist/extensions/forgecli/forge-commands.js.map +1 -1
  130. package/dist/extensions/forgecli/forge-init/forge-init.d.ts +26 -0
  131. package/dist/extensions/forgecli/forge-init/forge-init.js +514 -0
  132. package/dist/extensions/forgecli/forge-init/forge-init.js.map +1 -0
  133. package/dist/extensions/forgecli/forge-init/init-context.d.ts +99 -0
  134. package/dist/extensions/forgecli/forge-init/init-context.js +178 -0
  135. package/dist/extensions/forgecli/forge-init/init-context.js.map +1 -0
  136. package/dist/extensions/forgecli/forge-init/init-progress.d.ts +39 -0
  137. package/dist/extensions/forgecli/forge-init/init-progress.js +117 -0
  138. package/dist/extensions/forgecli/forge-init/init-progress.js.map +1 -0
  139. package/dist/extensions/forgecli/forge-init/phase4-register.js +1 -1
  140. package/dist/extensions/forgecli/forge-init/phase4-register.js.map +1 -1
  141. package/dist/extensions/forgecli/forge-init/run-phases.js +2 -2
  142. package/dist/extensions/forgecli/forge-init/run-phases.js.map +1 -1
  143. package/dist/extensions/forgecli/forge-subagent.d.ts +22 -0
  144. package/dist/extensions/forgecli/forge-subagent.js +42 -15
  145. package/dist/extensions/forgecli/forge-subagent.js.map +1 -1
  146. package/dist/extensions/forgecli/forge-tools.d.ts +0 -25
  147. package/dist/extensions/forgecli/forge-tools.js +6 -37
  148. package/dist/extensions/forgecli/forge-tools.js.map +1 -1
  149. package/dist/extensions/forgecli/governor-config.d.ts +19 -0
  150. package/dist/extensions/forgecli/governor-config.js +58 -0
  151. package/dist/extensions/forgecli/governor-config.js.map +1 -0
  152. package/dist/extensions/forgecli/health-check.js +1 -1
  153. package/dist/extensions/forgecli/health-check.js.map +1 -1
  154. package/dist/extensions/forgecli/hook-dispatcher.js +2 -2
  155. package/dist/extensions/forgecli/hook-dispatcher.js.map +1 -1
  156. package/dist/extensions/forgecli/hooks/post-init-hook.js +11 -6
  157. package/dist/extensions/forgecli/hooks/post-init-hook.js.map +1 -1
  158. package/dist/extensions/forgecli/hooks/post-sprint-hook.js +11 -6
  159. package/dist/extensions/forgecli/hooks/post-sprint-hook.js.map +1 -1
  160. package/dist/extensions/forgecli/hooks/write-guard.js +1 -1
  161. package/dist/extensions/forgecli/hooks/write-guard.js.map +1 -1
  162. package/dist/extensions/forgecli/index.js +37 -35
  163. package/dist/extensions/forgecli/index.js.map +1 -1
  164. package/dist/extensions/forgecli/kickoff.d.ts +9 -0
  165. package/dist/extensions/forgecli/kickoff.js +15 -0
  166. package/dist/extensions/forgecli/kickoff.js.map +1 -1
  167. package/dist/extensions/forgecli/lib/forge-config.d.ts +1 -1
  168. package/dist/extensions/forgecli/lib/forge-config.js +1 -1
  169. package/dist/extensions/forgecli/lib/forge-config.js.map +1 -1
  170. package/dist/extensions/forgecli/lib/forge-root.d.ts +10 -0
  171. package/dist/extensions/forgecli/lib/forge-root.js +62 -0
  172. package/dist/extensions/forgecli/lib/forge-root.js.map +1 -0
  173. package/dist/extensions/forgecli/lib/run-cjs.d.ts +26 -0
  174. package/dist/extensions/forgecli/lib/run-cjs.js +42 -0
  175. package/dist/extensions/forgecli/lib/run-cjs.js.map +1 -0
  176. package/dist/extensions/forgecli/orchestrator-tree.d.ts +4 -0
  177. package/dist/extensions/forgecli/orchestrator-tree.js +21 -3
  178. package/dist/extensions/forgecli/orchestrator-tree.js.map +1 -1
  179. package/dist/extensions/forgecli/orchestrators/calibrate.d.ts +64 -0
  180. package/dist/extensions/forgecli/orchestrators/calibrate.js +481 -0
  181. package/dist/extensions/forgecli/orchestrators/calibrate.js.map +1 -0
  182. package/dist/extensions/forgecli/orchestrators/fix-bug.d.ts +93 -0
  183. package/dist/extensions/forgecli/orchestrators/fix-bug.js +1705 -0
  184. package/dist/extensions/forgecli/orchestrators/fix-bug.js.map +1 -0
  185. package/dist/extensions/forgecli/orchestrators/halt-advisor.d.ts +59 -0
  186. package/dist/extensions/forgecli/orchestrators/halt-advisor.js +113 -0
  187. package/dist/extensions/forgecli/orchestrators/halt-advisor.js.map +1 -0
  188. package/dist/extensions/forgecli/orchestrators/materialize.d.ts +16 -0
  189. package/dist/extensions/forgecli/orchestrators/materialize.js +195 -0
  190. package/dist/extensions/forgecli/orchestrators/materialize.js.map +1 -0
  191. package/dist/extensions/forgecli/orchestrators/migrate.d.ts +22 -0
  192. package/dist/extensions/forgecli/orchestrators/migrate.js +260 -0
  193. package/dist/extensions/forgecli/orchestrators/migrate.js.map +1 -0
  194. package/dist/extensions/forgecli/orchestrators/orchestrator-preflight.d.ts +46 -0
  195. package/dist/extensions/forgecli/orchestrators/orchestrator-preflight.js +64 -0
  196. package/dist/extensions/forgecli/orchestrators/orchestrator-preflight.js.map +1 -0
  197. package/dist/extensions/forgecli/orchestrators/run-sprint.d.ts +27 -0
  198. package/dist/extensions/forgecli/orchestrators/run-sprint.js +734 -0
  199. package/dist/extensions/forgecli/orchestrators/run-sprint.js.map +1 -0
  200. package/dist/extensions/forgecli/orchestrators/run-task.d.ts +215 -0
  201. package/dist/extensions/forgecli/orchestrators/run-task.js +1491 -0
  202. package/dist/extensions/forgecli/orchestrators/run-task.js.map +1 -0
  203. package/dist/extensions/forgecli/paths/paths.d.ts +8 -0
  204. package/dist/extensions/forgecli/paths/paths.js +17 -0
  205. package/dist/extensions/forgecli/paths/paths.js.map +1 -1
  206. package/dist/extensions/forgecli/phase-vocab.d.ts +31 -0
  207. package/dist/extensions/forgecli/phase-vocab.js +82 -0
  208. package/dist/extensions/forgecli/phase-vocab.js.map +1 -0
  209. package/dist/extensions/forgecli/session-registry.d.ts +2 -2
  210. package/dist/extensions/forgecli/session-registry.js +6 -2
  211. package/dist/extensions/forgecli/session-registry.js.map +1 -1
  212. package/dist/extensions/forgecli/skill-curation/friction-emit.d.ts +99 -0
  213. package/dist/extensions/forgecli/skill-curation/friction-emit.js +245 -0
  214. package/dist/extensions/forgecli/skill-curation/friction-emit.js.map +1 -0
  215. package/dist/extensions/forgecli/skill-curation/skill-curation-flag.d.ts +21 -0
  216. package/dist/extensions/forgecli/skill-curation/skill-curation-flag.js +71 -0
  217. package/dist/extensions/forgecli/skill-curation/skill-curation-flag.js.map +1 -0
  218. package/dist/extensions/forgecli/skill-curation/skill-curator-subagent.d.ts +102 -0
  219. package/dist/extensions/forgecli/skill-curation/skill-curator-subagent.js +339 -0
  220. package/dist/extensions/forgecli/skill-curation/skill-curator-subagent.js.map +1 -0
  221. package/dist/extensions/forgecli/skill-curation/skill-retriever.d.ts +84 -0
  222. package/dist/extensions/forgecli/skill-curation/skill-retriever.js +246 -0
  223. package/dist/extensions/forgecli/skill-curation/skill-retriever.js.map +1 -0
  224. package/dist/extensions/forgecli/skill-curation/skill-usage-tracker.d.ts +91 -0
  225. package/dist/extensions/forgecli/skill-curation/skill-usage-tracker.js +224 -0
  226. package/dist/extensions/forgecli/skill-curation/skill-usage-tracker.js.map +1 -0
  227. package/dist/extensions/forgecli/store/store-error-remediation.d.ts +65 -0
  228. package/dist/extensions/forgecli/store/store-error-remediation.js +307 -0
  229. package/dist/extensions/forgecli/store/store-error-remediation.js.map +1 -0
  230. package/dist/extensions/forgecli/store/store-resolver.d.ts +56 -0
  231. package/dist/extensions/forgecli/store/store-resolver.js +263 -0
  232. package/dist/extensions/forgecli/store/store-resolver.js.map +1 -0
  233. package/dist/extensions/forgecli/store/store-validator.d.ts +16 -0
  234. package/dist/extensions/forgecli/store/store-validator.js +32 -0
  235. package/dist/extensions/forgecli/store/store-validator.js.map +1 -0
  236. package/dist/extensions/forgecli/store/transition-guard.d.ts +20 -0
  237. package/dist/extensions/forgecli/store/transition-guard.js +89 -0
  238. package/dist/extensions/forgecli/store/transition-guard.js.map +1 -0
  239. package/dist/extensions/forgecli/subagent/orchestrator-transcript.js +5 -0
  240. package/dist/extensions/forgecli/subagent/orchestrator-transcript.js.map +1 -1
  241. package/dist/extensions/forgecli/transcript-archive-types.d.ts +171 -0
  242. package/dist/extensions/forgecli/transcript-archive-types.js +130 -0
  243. package/dist/extensions/forgecli/transcript-archive-types.js.map +1 -0
  244. package/dist/extensions/forgecli/transcript-archive.d.ts +127 -0
  245. package/dist/extensions/forgecli/transcript-archive.js +656 -0
  246. package/dist/extensions/forgecli/transcript-archive.js.map +1 -0
  247. package/dist/extensions/forgecli/transcript-replay.d.ts +28 -0
  248. package/dist/extensions/forgecli/transcript-replay.js +153 -0
  249. package/dist/extensions/forgecli/transcript-replay.js.map +1 -0
  250. package/dist/extensions/forgecli/transcripts-tui/component.d.ts +36 -0
  251. package/dist/extensions/forgecli/transcripts-tui/component.js +112 -0
  252. package/dist/extensions/forgecli/transcripts-tui/component.js.map +1 -0
  253. package/dist/extensions/forgecli/transcripts-tui/index.d.ts +4 -0
  254. package/dist/extensions/forgecli/transcripts-tui/index.js +5 -0
  255. package/dist/extensions/forgecli/transcripts-tui/index.js.map +1 -0
  256. package/dist/extensions/forgecli/transcripts-tui/screens/browse.d.ts +21 -0
  257. package/dist/extensions/forgecli/transcripts-tui/screens/browse.js +172 -0
  258. package/dist/extensions/forgecli/transcripts-tui/screens/browse.js.map +1 -0
  259. package/dist/extensions/forgecli/transcripts-tui/screens/types.d.ts +22 -0
  260. package/dist/extensions/forgecli/transcripts-tui/screens/types.js +4 -0
  261. package/dist/extensions/forgecli/transcripts-tui/screens/types.js.map +1 -0
  262. package/dist/extensions/forgecli/transcripts-tui/state/index.d.ts +4 -0
  263. package/dist/extensions/forgecli/transcripts-tui/state/index.js +5 -0
  264. package/dist/extensions/forgecli/transcripts-tui/state/index.js.map +1 -0
  265. package/dist/extensions/forgecli/transcripts-tui/state/init.d.ts +8 -0
  266. package/dist/extensions/forgecli/transcripts-tui/state/init.js +18 -0
  267. package/dist/extensions/forgecli/transcripts-tui/state/init.js.map +1 -0
  268. package/dist/extensions/forgecli/transcripts-tui/state/model.d.ts +56 -0
  269. package/dist/extensions/forgecli/transcripts-tui/state/model.js +6 -0
  270. package/dist/extensions/forgecli/transcripts-tui/state/model.js.map +1 -0
  271. package/dist/extensions/forgecli/transcripts-tui/state/reducer.d.ts +2 -0
  272. package/dist/extensions/forgecli/transcripts-tui/state/reducer.js +51 -0
  273. package/dist/extensions/forgecli/transcripts-tui/state/reducer.js.map +1 -0
  274. package/dist/extensions/forgecli/transcripts-tui/state/selectors.d.ts +10 -0
  275. package/dist/extensions/forgecli/transcripts-tui/state/selectors.js +62 -0
  276. package/dist/extensions/forgecli/transcripts-tui/state/selectors.js.map +1 -0
  277. package/dist/extensions/forgecli/transcripts-tui/theme.d.ts +20 -0
  278. package/dist/extensions/forgecli/transcripts-tui/theme.js +47 -0
  279. package/dist/extensions/forgecli/transcripts-tui/theme.js.map +1 -0
  280. package/dist/extensions/forgecli/tui/banner.d.ts +10 -0
  281. package/dist/extensions/forgecli/tui/banner.js +36 -0
  282. package/dist/extensions/forgecli/tui/banner.js.map +1 -0
  283. package/dist/extensions/forgecli/tui/forge-header.d.ts +12 -0
  284. package/dist/extensions/forgecli/tui/forge-header.js +114 -0
  285. package/dist/extensions/forgecli/tui/forge-header.js.map +1 -0
  286. package/dist/extensions/forgecli/tui/input-router.d.ts +33 -0
  287. package/dist/extensions/forgecli/tui/input-router.js +136 -0
  288. package/dist/extensions/forgecli/tui/input-router.js.map +1 -0
  289. package/dist/extensions/forgecli/tui/orchestrator-status-bar.d.ts +26 -0
  290. package/dist/extensions/forgecli/tui/orchestrator-status-bar.js +213 -0
  291. package/dist/extensions/forgecli/tui/orchestrator-status-bar.js.map +1 -0
  292. package/dist/extensions/forgecli/tui/thread-switcher.d.ts +18 -0
  293. package/dist/extensions/forgecli/tui/thread-switcher.js +194 -0
  294. package/dist/extensions/forgecli/tui/thread-switcher.js.map +1 -0
  295. package/dist/extensions/forgecli/update/forge-update-command.d.ts +100 -0
  296. package/dist/extensions/forgecli/update/forge-update-command.js +435 -0
  297. package/dist/extensions/forgecli/update/forge-update-command.js.map +1 -0
  298. package/dist/extensions/forgecli/update/migration-engine.d.ts +117 -0
  299. package/dist/extensions/forgecli/update/migration-engine.js +563 -0
  300. package/dist/extensions/forgecli/update/migration-engine.js.map +1 -0
  301. package/dist/extensions/forgecli/update/update-check.d.ts +37 -0
  302. package/dist/extensions/forgecli/update/update-check.js +185 -0
  303. package/dist/extensions/forgecli/update/update-check.js.map +1 -0
  304. package/dist/extensions/forgecli/update/update-tools.d.ts +23 -0
  305. package/dist/extensions/forgecli/update/update-tools.js +135 -0
  306. package/dist/extensions/forgecli/update/update-tools.js.map +1 -0
  307. package/dist/extensions/forgecli/update/whats-new-widget.d.ts +26 -0
  308. package/dist/extensions/forgecli/update/whats-new-widget.js +376 -0
  309. package/dist/extensions/forgecli/update/whats-new-widget.js.map +1 -0
  310. package/dist/extensions/forgecli/update/whats-new.d.ts +120 -0
  311. package/dist/extensions/forgecli/update/whats-new.js +470 -0
  312. package/dist/extensions/forgecli/update/whats-new.js.map +1 -0
  313. package/dist/extensions/forgecli/viewport/events.d.ts +113 -0
  314. package/dist/extensions/forgecli/viewport/events.js +290 -0
  315. package/dist/extensions/forgecli/viewport/events.js.map +1 -0
  316. package/dist/extensions/forgecli/viewport/renderer.d.ts +102 -0
  317. package/dist/extensions/forgecli/viewport/renderer.js +277 -0
  318. package/dist/extensions/forgecli/viewport/renderer.js.map +1 -0
  319. package/dist/extensions/forgecli/viewport/theme.d.ts +11 -0
  320. package/dist/extensions/forgecli/viewport/theme.js +131 -0
  321. package/dist/extensions/forgecli/viewport/theme.js.map +1 -0
  322. package/dist/extensions/forgecli/wf-engine/engine.js +1 -1
  323. package/dist/extensions/forgecli/wf-engine/engine.js.map +1 -1
  324. package/package.json +4 -2
@@ -0,0 +1,136 @@
1
+ // Centralised onTerminalInput dispatch for forge-cli.
2
+ //
3
+ // Plan 16 Slice 4c. Pi-mono's `ctx.ui.onTerminalInput` lets any extension hook
4
+ // raw stdin, with the first consumer winning. Pi runs listeners BEFORE
5
+ // routing to the focused overlay (pi-mono/packages/tui/src/tui.ts:544-560).
6
+ // That made forge-cli's two existing arrow-activator listeners
7
+ // (thread-switcher, whats-new-widget) silently eat ↑/↓ when the config TUI was
8
+ // mounted as an overlay.
9
+ //
10
+ // This router gives forge-cli a single pi listener whose dispatch is
11
+ // overlay-aware: listeners flagged `skipWhenOverlayActive: true` are bypassed
12
+ // whenever an overlay has been registered via `pushOverlay()`. Other listeners
13
+ // (critical hotkeys, theme switchers, etc.) still run.
14
+ //
15
+ // Wiring:
16
+ // 1. index.ts session_start: `ctx.ui.onTerminalInput((d) => router.dispatch(d))`.
17
+ // 2. Each consumer: `router.register(listener, { name, skipWhenOverlayActive })`.
18
+ // 3. Each overlay mounter: `router.pushOverlay()` before ctx.ui.custom,
19
+ // `popOverlay()` in a finally.
20
+ //
21
+ // Debug logging (when FORGE_DEBUG_INPUT=1):
22
+ // Each dispatch + push/pop is logged with timestamp + listener name +
23
+ // overlay depth + raw byte sequence (hex-escaped). Default target:
24
+ // /tmp/forge-input-router.log. Override with FORGE_DEBUG_INPUT_LOG=<path>.
25
+ // Logging goes through fs.appendFileSync — synchronous so events are
26
+ // captured even when the process crashes mid-render.
27
+ import * as fs from "node:fs";
28
+ function debugEnabled() {
29
+ return process.env.FORGE_DEBUG_INPUT === "1";
30
+ }
31
+ function debugLogPath() {
32
+ return process.env.FORGE_DEBUG_INPUT_LOG ?? "/tmp/forge-input-router.log";
33
+ }
34
+ function hexEscape(s) {
35
+ // Render printable ASCII as-is, escape everything else as \xNN. Helps spot
36
+ // arrow sequences (\x1b[A etc.) and Kitty-protocol variants at a glance.
37
+ return [...s]
38
+ .map((c) => {
39
+ const cp = c.codePointAt(0);
40
+ if (cp >= 0x20 && cp <= 0x7e)
41
+ return c;
42
+ return `\\x${cp.toString(16).padStart(2, "0")}`;
43
+ })
44
+ .join("");
45
+ }
46
+ function logEvent(line) {
47
+ if (!debugEnabled())
48
+ return;
49
+ try {
50
+ const ts = new Date().toISOString();
51
+ fs.appendFileSync(debugLogPath(), `${ts} ${line}\n`);
52
+ }
53
+ catch {
54
+ // Logging must never crash the host; failure to write is silently ignored.
55
+ }
56
+ }
57
+ export class ForgeInputRouter {
58
+ listeners = [];
59
+ overlayDepth = 0;
60
+ register(listener, opts) {
61
+ const entry = { fn: listener, opts };
62
+ this.listeners.push(entry);
63
+ logEvent(`register name=${opts.name} skipWhenOverlayActive=${!!opts.skipWhenOverlayActive} total=${this.listeners.length}`);
64
+ return () => {
65
+ const i = this.listeners.indexOf(entry);
66
+ if (i >= 0) {
67
+ this.listeners.splice(i, 1);
68
+ logEvent(`unregister name=${opts.name} remaining=${this.listeners.length}`);
69
+ }
70
+ };
71
+ }
72
+ pushOverlay() {
73
+ this.overlayDepth++;
74
+ logEvent(`pushOverlay depth=${this.overlayDepth}`);
75
+ }
76
+ popOverlay() {
77
+ if (this.overlayDepth > 0)
78
+ this.overlayDepth--;
79
+ logEvent(`popOverlay depth=${this.overlayDepth}`);
80
+ }
81
+ isOverlayActive() {
82
+ return this.overlayDepth > 0;
83
+ }
84
+ /**
85
+ * Mirrors pi's listener-chain semantics (tui.ts:544-560):
86
+ * - Each listener may return { consume: true } to stop dispatch.
87
+ * - Each listener may return { data: rewritten } to alter the value the
88
+ * next listener (and ultimately the focused overlay) sees.
89
+ * - Listeners flagged skipWhenOverlayActive=true are silently bypassed
90
+ * whenever overlayDepth > 0.
91
+ */
92
+ dispatch(data) {
93
+ if (debugEnabled()) {
94
+ logEvent(`dispatch IN data="${hexEscape(data)}" overlayDepth=${this.overlayDepth} listeners=${this.listeners.length}`);
95
+ }
96
+ let current = data;
97
+ for (const entry of this.listeners) {
98
+ if (this.overlayDepth > 0 && entry.opts.skipWhenOverlayActive) {
99
+ logEvent(` skip name=${entry.opts.name} (overlay active)`);
100
+ continue;
101
+ }
102
+ const result = entry.fn(current);
103
+ if (debugEnabled()) {
104
+ const r = result === undefined
105
+ ? "passthrough"
106
+ : `${result.consume ? "consume" : ""}${result.data !== undefined ? ` data="${hexEscape(result.data)}"` : ""}`.trim() ||
107
+ "noop";
108
+ logEvent(` call name=${entry.opts.name} → ${r}`);
109
+ }
110
+ if (result?.consume) {
111
+ logEvent(`dispatch OUT consumed-by=${entry.opts.name}`);
112
+ return { consume: true };
113
+ }
114
+ if (result?.data !== undefined)
115
+ current = result.data;
116
+ }
117
+ if (current !== data) {
118
+ logEvent(`dispatch OUT rewritten data="${hexEscape(current)}"`);
119
+ return { data: current };
120
+ }
121
+ logEvent(`dispatch OUT passthrough (focused overlay should receive)`);
122
+ return undefined;
123
+ }
124
+ }
125
+ // ── Module-level singleton ───────────────────────────────────────────────────
126
+ let singleton = null;
127
+ export function getInputRouter() {
128
+ if (!singleton)
129
+ singleton = new ForgeInputRouter();
130
+ return singleton;
131
+ }
132
+ /** Test helper — replace the singleton with a fresh router. */
133
+ export function __resetInputRouterForTesting() {
134
+ singleton = null;
135
+ }
136
+ //# sourceMappingURL=input-router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input-router.js","sourceRoot":"","sources":["../../../../src/extensions/forgecli/tui/input-router.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { Theme } from "@earendil-works/pi-coding-agent";
2
+ import type { Component } from "@earendil-works/pi-tui";
3
+ import type { OrchestratorTree } from "../orchestrator-tree.js";
4
+ export declare class OrchestratorStatusBar implements Component {
5
+ private tree;
6
+ private theme;
7
+ private active;
8
+ private disposed;
9
+ private invalidationCb?;
10
+ private spinnerTimer?;
11
+ private spinnerIdx;
12
+ private onAction?;
13
+ private disposeFns;
14
+ constructor(tree: OrchestratorTree, theme: Theme);
15
+ setInvalidationCallback(cb: () => void): void;
16
+ setOnAction(cb: () => void): void;
17
+ setActive(active: boolean): void;
18
+ isActive(): boolean;
19
+ private ensureSpinnerTimer;
20
+ private stopSpinnerTimer;
21
+ render(width: number): string[];
22
+ invalidate(): void;
23
+ dispose(): void;
24
+ /** Walk depth-first to find the deepest running/cancelling leaf. */
25
+ private findDeepestRunningLeaf;
26
+ }
@@ -0,0 +1,213 @@
1
+ // orchestrator-status-bar.ts — One-line status bar for running orchestrations.
2
+ //
3
+ // Two render modes, distinguished by focus indicator:
4
+ //
5
+ // INACTIVE (outline ○ prefix — navigation hint):
6
+ // ○ [CART-S03-T01 · writeback:1 ⠋] "preview…" ↓ dashboard
7
+ //
8
+ // ○ signals "you can ↓ here". Colour carries status: green=completed,
9
+ // red=failed, accent=running, muted=other terminal.
10
+ //
11
+ // ACTIVE (filled ● prefix — focus confirmation):
12
+ // ● [CART-S03-T01 · writeback:1 ⠋] "preview…" ⏎ open · esc back
13
+ //
14
+ // ● signals "you're here". ↑/Esc returns focus to the prompt.
15
+ //
16
+ // Visual semantics (two dimensions on one circle):
17
+ // Shape: ○ = not focused, ● = focused
18
+ // Colour: accent=running, success=completed, error=failed, muted=terminal
19
+ // ⠋ spinner: shows activity (only for running/cancelling nodes)
20
+ //
21
+ // Focus lifecycle: ↓ activates → ↑/Esc deactivates → prompt gets focus.
22
+ // All activation/deactivation is handled by the ForgeInputRouter listener
23
+ // in thread-switcher.ts (not by this widget's handleInput, which is dead
24
+ // code for setWidget components since pi-tui routes input to the prompt
25
+ // editor before setWidget components).
26
+ //
27
+ // Iron Laws conformance:
28
+ // IL1 — All visible strings route through theme.fg()/bg()/bold(). No raw glyphs.
29
+ // IL7 — Spinner timer guarded by disposed flag to prevent stale callbacks.
30
+ import { truncateToWidth } from "@earendil-works/pi-tui";
31
+ import { fmtTokenMeter } from "../viewport/renderer.js";
32
+ // ── Braille spinner ────────────────────────────────────────────────────────
33
+ const SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
34
+ const SPINNER_INTERVAL_MS = 100;
35
+ // ── Focus indicator colour: derives the theme colour from the root's
36
+ // aggregate status. The shape (○/●) carries focus; the colour carries
37
+ // status. Both dimensions on the same circle glyph.
38
+ //
39
+ // ○ green = not focused, completed ● green = focused, completed
40
+ // ○ red = not focused, failed ● red = focused, failed
41
+ // ○ dim = not focused, terminal ● dim = focused, terminal
42
+ // ○ accent = not focused, running ● accent = focused, running
43
+ function focusIndicatorColour(roots, theme) {
44
+ // Derive the aggregate status from all visible roots.
45
+ // Running/cancelling wins over terminal; failed wins over completed.
46
+ const hasRunning = roots.some((r) => r.status === "running" || r.status === "cancelling");
47
+ if (hasRunning)
48
+ return "accent";
49
+ const hasFailed = roots.some((r) => r.status === "failed" || r.status === "escalated");
50
+ if (hasFailed)
51
+ return "error";
52
+ const hasCompleted = roots.some((r) => r.status === "completed");
53
+ if (hasCompleted)
54
+ return "success";
55
+ // Terminal but not failed/completed (cancelled, pending, etc.).
56
+ return "muted";
57
+ }
58
+ // ── OrchestratorStatusBar ──────────────────────────────────────────────────
59
+ export class OrchestratorStatusBar {
60
+ tree;
61
+ theme;
62
+ active = false;
63
+ disposed = false; // IL7: guards interval callbacks after dispose
64
+ invalidationCb;
65
+ spinnerTimer;
66
+ spinnerIdx = 0;
67
+ onAction; // callback to open dashboard
68
+ disposeFns = [];
69
+ constructor(tree, theme) {
70
+ this.tree = tree;
71
+ this.theme = theme;
72
+ const onChange = () => {
73
+ if (!this.disposed) {
74
+ this.ensureSpinnerTimer(); // restart spinner if roots became active
75
+ this.invalidationCb?.();
76
+ }
77
+ };
78
+ this.tree.on("change", onChange);
79
+ this.tree.on("tree", onChange);
80
+ this.tree.on("tail", onChange);
81
+ this.tree.on("preview", onChange);
82
+ this.disposeFns.push(() => { this.tree.off("change", onChange); this.tree.off("tree", onChange); this.tree.off("tail", onChange); this.tree.off("preview", onChange); });
83
+ }
84
+ setInvalidationCallback(cb) {
85
+ this.invalidationCb = cb;
86
+ this.ensureSpinnerTimer();
87
+ }
88
+ setOnAction(cb) {
89
+ this.onAction = cb;
90
+ }
91
+ setActive(active) {
92
+ this.active = active;
93
+ if (!this.disposed) {
94
+ this.ensureSpinnerTimer(); // restart spinner if needed
95
+ this.invalidationCb?.();
96
+ }
97
+ }
98
+ isActive() {
99
+ return this.active;
100
+ }
101
+ ensureSpinnerTimer() {
102
+ if (this.spinnerTimer)
103
+ return;
104
+ // Only start the timer when there are running/cancelling roots to animate.
105
+ const anyActive = this.tree.getActiveRoots().some((r) => r.status === "running" || r.status === "cancelling");
106
+ if (!anyActive)
107
+ return; // no spinner needed yet
108
+ this.spinnerTimer = setInterval(() => {
109
+ // IL7: guard against firing after dispose.
110
+ if (this.disposed) {
111
+ this.stopSpinnerTimer();
112
+ return;
113
+ }
114
+ const anyActive = this.tree.getActiveRoots().some((r) => r.status === "running" || r.status === "cancelling");
115
+ if (!anyActive) {
116
+ // One last render to settle spinner, then stop.
117
+ this.invalidationCb?.();
118
+ this.stopSpinnerTimer();
119
+ return;
120
+ }
121
+ this.spinnerIdx = (this.spinnerIdx + 1) % SPINNER_FRAMES.length;
122
+ this.invalidationCb?.();
123
+ }, SPINNER_INTERVAL_MS);
124
+ }
125
+ stopSpinnerTimer() {
126
+ if (this.spinnerTimer) {
127
+ clearInterval(this.spinnerTimer);
128
+ this.spinnerTimer = undefined;
129
+ }
130
+ }
131
+ render(width) {
132
+ const roots = this.tree.getActiveRoots();
133
+ if (roots.length === 0)
134
+ return []; // Hidden when nothing is running.
135
+ const dim = (s) => this.theme.fg("dim", s);
136
+ const bold = (s) => this.theme.bold(this.theme.fg("accent", s));
137
+ // Build a segment for each active root.
138
+ const segments = [];
139
+ for (const root of roots) {
140
+ // Find the deepest running leaf or the root itself.
141
+ const leaf = this.findDeepestRunningLeaf(root.id);
142
+ const displayNode = leaf ?? root;
143
+ // Label: root label, with current phase as suffix if different.
144
+ let label = root.label;
145
+ if (leaf && leaf.id !== root.id) {
146
+ const shortRole = leaf.id.includes(":") ? leaf.id.split(":").slice(1).join(":") : leaf.label;
147
+ label = `${root.label} · ${shortRole}`;
148
+ }
149
+ // Usage footer (right-aligned within segment).
150
+ const usage = this.tree.getSubtreeUsage(root.id);
151
+ const meter = fmtTokenMeter(usage);
152
+ const meterPart = meter ? dim(` ${meter}`) : "";
153
+ // IL1: spinner (worm) shows activity — only for running/cancelling.
154
+ // Not shown for terminal states (completed, failed, etc.).
155
+ const spin = (displayNode.status === "running" || displayNode.status === "cancelling")
156
+ ? ` ${this.theme.fg("accent", SPINNER_FRAMES[this.spinnerIdx])}`
157
+ : "";
158
+ // Turn preview (truncated).
159
+ const preview = displayNode.lastTurnPreview
160
+ ? dim(` "${truncateToWidth(displayNode.lastTurnPreview, 60)}"`)
161
+ : "";
162
+ const segment = `${bold(`[${label}]`)}${spin}${preview}${meterPart}`;
163
+ segments.push(segment);
164
+ }
165
+ // Right-side hint depends on active state.
166
+ const hint = this.active
167
+ ? dim(" ⏎ open · esc back")
168
+ : dim(" ↓ dashboard");
169
+ // Focus indicator: ○/● coloured by aggregate status.
170
+ // Shape: ○ when inactive ("↓ here"), ● when active ("you're here").
171
+ // Colour: accent=running, success=completed, error=failed, muted=terminal.
172
+ const indicatorColour = focusIndicatorColour(roots, this.theme);
173
+ const indicatorGlyph = this.active ? "●" : "○";
174
+ const prefix = this.theme.fg(indicatorColour, indicatorGlyph) + " ";
175
+ const joined = segments.join(dim(" │ "));
176
+ const line = `${prefix}${joined}${hint}`;
177
+ return [truncateToWidth(line, width)];
178
+ }
179
+ invalidate() {
180
+ // Re-render driven by external invalidationCb → tui.requestRender().
181
+ }
182
+ // Note: handleInput is dead code for setWidget("belowEditor") components —
183
+ // pi-tui routes input to the prompt editor, not to belowEditor widgets.
184
+ // All key handling (↓ focus, ↑/Esc unfocus, Enter open dashboard) is in
185
+ // the ForgeInputRouter listener in thread-switcher.ts.
186
+ // Keeping the method for Component interface conformance; it does nothing.
187
+ dispose() {
188
+ this.disposed = true; // IL7: set before clearing timer so callback sees it
189
+ this.stopSpinnerTimer();
190
+ for (const fn of this.disposeFns)
191
+ fn();
192
+ this.disposeFns = [];
193
+ }
194
+ /** Walk depth-first to find the deepest running/cancelling leaf. */
195
+ findDeepestRunningLeaf(id) {
196
+ const node = this.tree.getNode(id);
197
+ if (!node)
198
+ return undefined;
199
+ if (node.kind === "leaf" && (node.status === "running" || node.status === "cancelling")) {
200
+ return node;
201
+ }
202
+ for (const childId of node.children) {
203
+ const found = this.findDeepestRunningLeaf(childId);
204
+ if (found)
205
+ return found;
206
+ }
207
+ // If no running leaf, return the root if it's running.
208
+ if (node.status === "running" || node.status === "cancelling")
209
+ return node;
210
+ return undefined;
211
+ }
212
+ }
213
+ //# sourceMappingURL=orchestrator-status-bar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator-status-bar.js","sourceRoot":"","sources":["../../../../src/extensions/forgecli/tui/orchestrator-status-bar.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
2
+ import { type OrchestratorTree } from "../orchestrator-tree.js";
3
+ export interface OpenDashboardOptions {
4
+ /**
5
+ * Inject a detached tree (transcript replay). Defaults to the live
6
+ * singleton. Injected trees are NEVER memoized into the module-level
7
+ * treeRef — a replay must not pollute the live dashboard entry points.
8
+ */
9
+ tree?: OrchestratorTree;
10
+ /** Read-only mode: cancel (`x`) disabled; footer marks the replay. */
11
+ readOnly?: boolean;
12
+ }
13
+ /** Open the dashboard overlay. Shared by /forge:threads, /forge:dashboard,
14
+ * the status bar Enter action, and transcript replay (injected tree).
15
+ * Returns the overlay's lifetime promise so callers (replay re-entry loop)
16
+ * can await close; existing fire-and-forget call sites ignore it. */
17
+ export declare function openDashboardTui(ctx: ExtensionContext, opts?: OpenDashboardOptions): Promise<void>;
18
+ export declare function registerThreadSwitcher(pi: ExtensionAPI): void;
@@ -0,0 +1,194 @@
1
+ // thread-switcher.ts — orchestrator status bar + dashboard overlay for forge.
2
+ //
3
+ // Two elements:
4
+ // 1. OrchestratorStatusBar (belowEditor widget): a one-line summary of
5
+ // running orchestrations — label, current phase, status glyph, spinner,
6
+ // turn preview, token meter. Press ↓ to open the dashboard overlay.
7
+ // Hidden when no orchestration is running.
8
+ //
9
+ // 2. Dashboard overlay (/forge:dashboard command or ↓ from status bar):
10
+ // full-screen two-panel tree browser + detail view. See dashboard/.
11
+ //
12
+ // The chip strip and TailViewComponent have been retired — the dashboard
13
+ // replaces them for all orchestration visualization. The main viewport
14
+ // stays clean for user prompts and new tasks.
15
+ import { getInputRouter } from "./input-router.js";
16
+ import { matchesKey, Key } from "@earendil-works/pi-tui";
17
+ import { getOrchestratorTree } from "../orchestrator-tree.js";
18
+ import { DashboardComponent, DashboardController } from "../dashboard/component.js";
19
+ import { OrchestratorStatusBar } from "./orchestrator-status-bar.js";
20
+ import { getSessionRegistry, } from "../session-registry.js";
21
+ import { fmtModelLabel, fmtTokenFooter } from "../viewport/renderer.js";
22
+ import { paintFooterLine } from "../viewport/theme.js";
23
+ const STATUS_BAR_WIDGET_KEY = "forge:orchestrator-status-bar";
24
+ const FOOTER_WIDGET_KEY = "forge:viewport-footer";
25
+ // ── Aggregate token footer ──────────────────────────────────────────────────
26
+ // Mirrors the per-phase footer rendered inside TailView when a subagent chip
27
+ // was focused. Now shown at the bottom of the main viewport whenever an
28
+ // orchestration is active.
29
+ class ViewportFooterComponent {
30
+ registry;
31
+ theme;
32
+ getOrchestratorModel;
33
+ invalidationCb;
34
+ constructor(registry, theme, getOrchestratorModel) {
35
+ this.registry = registry;
36
+ this.theme = theme;
37
+ this.getOrchestratorModel = getOrchestratorModel;
38
+ const onChange = () => this.invalidationCb?.();
39
+ registry.on("change", onChange);
40
+ registry.on("tail", onChange);
41
+ registry.on("turn", onChange);
42
+ this.dispose = () => {
43
+ registry.off("change", onChange);
44
+ registry.off("tail", onChange);
45
+ registry.off("turn", onChange);
46
+ };
47
+ }
48
+ render(width) {
49
+ const sessions = this.registry.listSessions();
50
+ const hasActive = sessions.some((s) => s.status === "running" || s.status === "cancelling");
51
+ if (!hasActive)
52
+ return [];
53
+ const tokens = fmtTokenFooter(this.registry.getAggregateUsage(), this.registry.getAggregateCompression());
54
+ const orchModel = fmtModelLabel(this.getOrchestratorModel?.());
55
+ if (!tokens && !orchModel)
56
+ return [];
57
+ const left = orchModel ? `⌂ ${orchModel}` : "";
58
+ const right = tokens ? `Σ ${tokens}` : "";
59
+ const text = left && right ? `${left} ${right}` : left || right;
60
+ return [paintFooterLine(text, width, this.theme)];
61
+ }
62
+ invalidate() { }
63
+ setInvalidationCallback(cb) {
64
+ this.invalidationCb = cb;
65
+ }
66
+ dispose;
67
+ }
68
+ // ── Registration ─────────────────────────────────────────────────────────────
69
+ function isDownArrow(data) {
70
+ return data === "\x1b[B" || data === "\x1bOB";
71
+ }
72
+ let statusBarRef;
73
+ let statusBarTui;
74
+ // Module-level tree reference so openDashboardTui can access the singleton
75
+ // without being nested inside registerThreadSwitcher.
76
+ let treeRef;
77
+ /** Open the dashboard overlay. Shared by /forge:threads, /forge:dashboard,
78
+ * the status bar Enter action, and transcript replay (injected tree).
79
+ * Returns the overlay's lifetime promise so callers (replay re-entry loop)
80
+ * can await close; existing fire-and-forget call sites ignore it. */
81
+ export function openDashboardTui(ctx, opts = {}) {
82
+ const tree = opts.tree ?? treeRef ?? getOrchestratorTree();
83
+ if (!opts.tree && !treeRef)
84
+ treeRef = tree;
85
+ const controller = new DashboardController(tree, undefined, { readOnly: opts.readOnly ?? false });
86
+ const router = getInputRouter();
87
+ router.pushOverlay();
88
+ return ctx.ui
89
+ .custom((tui, theme, _kb, done) => {
90
+ const component = new DashboardComponent(controller, tui, theme, done);
91
+ return component;
92
+ }, {
93
+ overlay: true,
94
+ overlayOptions: {
95
+ width: "100%",
96
+ anchor: "center",
97
+ margin: 0,
98
+ },
99
+ })
100
+ .then(() => undefined)
101
+ .finally(() => {
102
+ router.popOverlay();
103
+ });
104
+ }
105
+ export function registerThreadSwitcher(pi) {
106
+ const registry = getSessionRegistry();
107
+ const tree = getOrchestratorTree();
108
+ treeRef = tree;
109
+ let mounted = false;
110
+ let currentCtx;
111
+ function mount(ctx) {
112
+ currentCtx = ctx;
113
+ if (mounted)
114
+ return;
115
+ // ── Orchestrator status bar (belowEditor) ────────────────────────
116
+ ctx.ui.setWidget(STATUS_BAR_WIDGET_KEY, (tui, theme) => {
117
+ statusBarTui = tui;
118
+ const bar = new OrchestratorStatusBar(tree, theme);
119
+ bar.setInvalidationCallback(() => tui.requestRender());
120
+ bar.setOnAction(() => {
121
+ // Enter on focused status bar → open dashboard.
122
+ const live = currentCtx;
123
+ if (live)
124
+ openDashboardTui(live);
125
+ });
126
+ statusBarRef = bar;
127
+ return bar;
128
+ }, { placement: "belowEditor" });
129
+ // ── Aggregate token footer (aboveEditor) ─────────────────────────
130
+ ctx.ui.setWidget(FOOTER_WIDGET_KEY, (tui, theme) => {
131
+ const getOrchestratorModel = () => {
132
+ try {
133
+ const m = ctx.model;
134
+ if (!m)
135
+ return undefined;
136
+ return { provider: m.provider, model: m.id };
137
+ }
138
+ catch {
139
+ return undefined;
140
+ }
141
+ };
142
+ const footer = new ViewportFooterComponent(registry, theme, getOrchestratorModel);
143
+ footer.setInvalidationCallback(() => tui.requestRender());
144
+ return footer;
145
+ }, { placement: "aboveEditor" });
146
+ // ── Input routing: ↓ focuses status bar; Enter opens dashboard ────────
147
+ getInputRouter().register((data) => {
148
+ if (!statusBarRef || !statusBarTui)
149
+ return undefined;
150
+ // Allow ↓ navigation whenever orchestration roots are visible —
151
+ // this includes completed/failed/escalated roots so the user
152
+ // can review results even after execution ends.
153
+ const activeRoots = tree.getActiveRoots();
154
+ if (activeRoots.length === 0)
155
+ return undefined;
156
+ // ↓ focuses the status bar (makes it active).
157
+ if (isDownArrow(data)) {
158
+ statusBarRef.setActive(true);
159
+ return { consume: true };
160
+ }
161
+ // When the status bar is focused, ↑ / Esc return focus to the prompt.
162
+ if (statusBarRef.isActive() && (matchesKey(data, Key.up) || matchesKey(data, Key.escape))) {
163
+ statusBarRef.setActive(false);
164
+ return { consume: true };
165
+ }
166
+ // When the status bar is focused, Enter opens the dashboard.
167
+ if (statusBarRef.isActive() && matchesKey(data, Key.enter)) {
168
+ statusBarRef.setActive(false);
169
+ const live = currentCtx;
170
+ if (live)
171
+ openDashboardTui(live);
172
+ return { consume: true };
173
+ }
174
+ return undefined;
175
+ }, { name: "orchestrator-status-bar", skipWhenOverlayActive: true });
176
+ mounted = true;
177
+ }
178
+ pi.registerCommand("forge:threads", {
179
+ description: "Open the Forge orchestrator dashboard. " +
180
+ "Shows a two-panel view of sprint/task/phase tree with status, " +
181
+ "metrics, and live activity. You can also press ↓ from the prompt " +
182
+ "when an orchestration is running.",
183
+ async handler(_args, ctx) {
184
+ mount(ctx);
185
+ openDashboardTui(ctx);
186
+ },
187
+ });
188
+ // Mount at session_start so the status bar + ↓ listener are live from
189
+ // the first keystroke. mount() is idempotent.
190
+ pi.on("session_start", async (_event, ctx) => {
191
+ mount(ctx);
192
+ });
193
+ }
194
+ //# sourceMappingURL=thread-switcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"thread-switcher.js","sourceRoot":"","sources":["../../../../src/extensions/forgecli/tui/thread-switcher.ts"],"names":[],"mappings":"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"}