@promptwheel/cli 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (530) hide show
  1. package/README.md +215 -0
  2. package/dist/bin/promptwheel.d.ts +17 -0
  3. package/dist/bin/promptwheel.d.ts.map +1 -0
  4. package/dist/bin/promptwheel.js +90 -0
  5. package/dist/bin/promptwheel.js.map +1 -0
  6. package/dist/commands/auto-auth.d.ts +26 -0
  7. package/dist/commands/auto-auth.d.ts.map +1 -0
  8. package/dist/commands/auto-auth.js +216 -0
  9. package/dist/commands/auto-auth.js.map +1 -0
  10. package/dist/commands/auto-ci-mode.d.ts +9 -0
  11. package/dist/commands/auto-ci-mode.d.ts.map +1 -0
  12. package/dist/commands/auto-ci-mode.js +176 -0
  13. package/dist/commands/auto-ci-mode.js.map +1 -0
  14. package/dist/commands/solo-analytics.d.ts +6 -0
  15. package/dist/commands/solo-analytics.d.ts.map +1 -0
  16. package/dist/commands/solo-analytics.js +267 -0
  17. package/dist/commands/solo-analytics.js.map +1 -0
  18. package/dist/commands/solo-auto.d.ts +6 -0
  19. package/dist/commands/solo-auto.d.ts.map +1 -0
  20. package/dist/commands/solo-auto.js +135 -0
  21. package/dist/commands/solo-auto.js.map +1 -0
  22. package/dist/commands/solo-daemon.d.ts +12 -0
  23. package/dist/commands/solo-daemon.d.ts.map +1 -0
  24. package/dist/commands/solo-daemon.js +177 -0
  25. package/dist/commands/solo-daemon.js.map +1 -0
  26. package/dist/commands/solo-exec.d.ts +6 -0
  27. package/dist/commands/solo-exec.d.ts.map +1 -0
  28. package/dist/commands/solo-exec.js +656 -0
  29. package/dist/commands/solo-exec.js.map +1 -0
  30. package/dist/commands/solo-inspect.d.ts +6 -0
  31. package/dist/commands/solo-inspect.d.ts.map +1 -0
  32. package/dist/commands/solo-inspect.js +765 -0
  33. package/dist/commands/solo-inspect.js.map +1 -0
  34. package/dist/commands/solo-lifecycle.d.ts +6 -0
  35. package/dist/commands/solo-lifecycle.d.ts.map +1 -0
  36. package/dist/commands/solo-lifecycle.js +226 -0
  37. package/dist/commands/solo-lifecycle.js.map +1 -0
  38. package/dist/commands/solo-nudge.d.ts +6 -0
  39. package/dist/commands/solo-nudge.d.ts.map +1 -0
  40. package/dist/commands/solo-nudge.js +49 -0
  41. package/dist/commands/solo-nudge.js.map +1 -0
  42. package/dist/commands/solo-qa.d.ts +6 -0
  43. package/dist/commands/solo-qa.d.ts.map +1 -0
  44. package/dist/commands/solo-qa.js +253 -0
  45. package/dist/commands/solo-qa.js.map +1 -0
  46. package/dist/commands/solo-trajectory.d.ts +6 -0
  47. package/dist/commands/solo-trajectory.d.ts.map +1 -0
  48. package/dist/commands/solo-trajectory.js +268 -0
  49. package/dist/commands/solo-trajectory.js.map +1 -0
  50. package/dist/commands/solo.d.ts +11 -0
  51. package/dist/commands/solo.d.ts.map +1 -0
  52. package/dist/commands/solo.js +52 -0
  53. package/dist/commands/solo.js.map +1 -0
  54. package/dist/index.d.ts +18 -0
  55. package/dist/index.d.ts.map +1 -0
  56. package/dist/index.js +18 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/lib/artifacts.d.ts +136 -0
  59. package/dist/lib/artifacts.d.ts.map +1 -0
  60. package/dist/lib/artifacts.js +147 -0
  61. package/dist/lib/artifacts.js.map +1 -0
  62. package/dist/lib/codebase-index.d.ts +5 -0
  63. package/dist/lib/codebase-index.d.ts.map +1 -0
  64. package/dist/lib/codebase-index.js +5 -0
  65. package/dist/lib/codebase-index.js.map +1 -0
  66. package/dist/lib/cycle-context.d.ts +62 -0
  67. package/dist/lib/cycle-context.d.ts.map +1 -0
  68. package/dist/lib/cycle-context.js +141 -0
  69. package/dist/lib/cycle-context.js.map +1 -0
  70. package/dist/lib/daemon-fork.d.ts +39 -0
  71. package/dist/lib/daemon-fork.d.ts.map +1 -0
  72. package/dist/lib/daemon-fork.js +164 -0
  73. package/dist/lib/daemon-fork.js.map +1 -0
  74. package/dist/lib/daemon-notifier.d.ts +29 -0
  75. package/dist/lib/daemon-notifier.d.ts.map +1 -0
  76. package/dist/lib/daemon-notifier.js +147 -0
  77. package/dist/lib/daemon-notifier.js.map +1 -0
  78. package/dist/lib/daemon.d.ts +75 -0
  79. package/dist/lib/daemon.d.ts.map +1 -0
  80. package/dist/lib/daemon.js +265 -0
  81. package/dist/lib/daemon.js.map +1 -0
  82. package/dist/lib/dedup-memory.d.ts +46 -0
  83. package/dist/lib/dedup-memory.d.ts.map +1 -0
  84. package/dist/lib/dedup-memory.js +190 -0
  85. package/dist/lib/dedup-memory.js.map +1 -0
  86. package/dist/lib/dedup.d.ts +37 -0
  87. package/dist/lib/dedup.d.ts.map +1 -0
  88. package/dist/lib/dedup.js +85 -0
  89. package/dist/lib/dedup.js.map +1 -0
  90. package/dist/lib/display-adapter-log.d.ts +26 -0
  91. package/dist/lib/display-adapter-log.d.ts.map +1 -0
  92. package/dist/lib/display-adapter-log.js +63 -0
  93. package/dist/lib/display-adapter-log.js.map +1 -0
  94. package/dist/lib/display-adapter-spinner.d.ts +28 -0
  95. package/dist/lib/display-adapter-spinner.d.ts.map +1 -0
  96. package/dist/lib/display-adapter-spinner.js +93 -0
  97. package/dist/lib/display-adapter-spinner.js.map +1 -0
  98. package/dist/lib/display-adapter-tui.d.ts +32 -0
  99. package/dist/lib/display-adapter-tui.d.ts.map +1 -0
  100. package/dist/lib/display-adapter-tui.js +77 -0
  101. package/dist/lib/display-adapter-tui.js.map +1 -0
  102. package/dist/lib/display-adapter.d.ts +40 -0
  103. package/dist/lib/display-adapter.d.ts.map +1 -0
  104. package/dist/lib/display-adapter.js +9 -0
  105. package/dist/lib/display-adapter.js.map +1 -0
  106. package/dist/lib/doctor.d.ts +45 -0
  107. package/dist/lib/doctor.d.ts.map +1 -0
  108. package/dist/lib/doctor.js +382 -0
  109. package/dist/lib/doctor.js.map +1 -0
  110. package/dist/lib/exclusion-index.d.ts +50 -0
  111. package/dist/lib/exclusion-index.d.ts.map +1 -0
  112. package/dist/lib/exclusion-index.js +249 -0
  113. package/dist/lib/exclusion-index.js.map +1 -0
  114. package/dist/lib/exec.d.ts +24 -0
  115. package/dist/lib/exec.d.ts.map +1 -0
  116. package/dist/lib/exec.js +295 -0
  117. package/dist/lib/exec.js.map +1 -0
  118. package/dist/lib/execution-backends/claude.d.ts +27 -0
  119. package/dist/lib/execution-backends/claude.d.ts.map +1 -0
  120. package/dist/lib/execution-backends/claude.js +161 -0
  121. package/dist/lib/execution-backends/claude.js.map +1 -0
  122. package/dist/lib/execution-backends/codex.d.ts +28 -0
  123. package/dist/lib/execution-backends/codex.d.ts.map +1 -0
  124. package/dist/lib/execution-backends/codex.js +216 -0
  125. package/dist/lib/execution-backends/codex.js.map +1 -0
  126. package/dist/lib/execution-backends/index.d.ts +10 -0
  127. package/dist/lib/execution-backends/index.d.ts.map +1 -0
  128. package/dist/lib/execution-backends/index.js +9 -0
  129. package/dist/lib/execution-backends/index.js.map +1 -0
  130. package/dist/lib/execution-backends/kimi.d.ts +25 -0
  131. package/dist/lib/execution-backends/kimi.d.ts.map +1 -0
  132. package/dist/lib/execution-backends/kimi.js +76 -0
  133. package/dist/lib/execution-backends/kimi.js.map +1 -0
  134. package/dist/lib/execution-backends/types.d.ts +38 -0
  135. package/dist/lib/execution-backends/types.d.ts.map +1 -0
  136. package/dist/lib/execution-backends/types.js +5 -0
  137. package/dist/lib/execution-backends/types.js.map +1 -0
  138. package/dist/lib/failure-classifier.d.ts +11 -0
  139. package/dist/lib/failure-classifier.d.ts.map +1 -0
  140. package/dist/lib/failure-classifier.js +24 -0
  141. package/dist/lib/failure-classifier.js.map +1 -0
  142. package/dist/lib/file-cooldown.d.ts +9 -0
  143. package/dist/lib/file-cooldown.d.ts.map +1 -0
  144. package/dist/lib/file-cooldown.js +75 -0
  145. package/dist/lib/file-cooldown.js.map +1 -0
  146. package/dist/lib/formulas.d.ts +52 -0
  147. package/dist/lib/formulas.d.ts.map +1 -0
  148. package/dist/lib/formulas.js +123 -0
  149. package/dist/lib/formulas.js.map +1 -0
  150. package/dist/lib/git.d.ts +9 -0
  151. package/dist/lib/git.d.ts.map +1 -0
  152. package/dist/lib/git.js +60 -0
  153. package/dist/lib/git.js.map +1 -0
  154. package/dist/lib/goals.d.ts +59 -0
  155. package/dist/lib/goals.d.ts.map +1 -0
  156. package/dist/lib/goals.js +216 -0
  157. package/dist/lib/goals.js.map +1 -0
  158. package/dist/lib/guidelines.d.ts +32 -0
  159. package/dist/lib/guidelines.d.ts.map +1 -0
  160. package/dist/lib/guidelines.js +102 -0
  161. package/dist/lib/guidelines.js.map +1 -0
  162. package/dist/lib/learnings.d.ts +65 -0
  163. package/dist/lib/learnings.d.ts.map +1 -0
  164. package/dist/lib/learnings.js +193 -0
  165. package/dist/lib/learnings.js.map +1 -0
  166. package/dist/lib/logger.d.ts +17 -0
  167. package/dist/lib/logger.d.ts.map +1 -0
  168. package/dist/lib/logger.js +42 -0
  169. package/dist/lib/logger.js.map +1 -0
  170. package/dist/lib/meta-learnings.d.ts +27 -0
  171. package/dist/lib/meta-learnings.d.ts.map +1 -0
  172. package/dist/lib/meta-learnings.js +270 -0
  173. package/dist/lib/meta-learnings.js.map +1 -0
  174. package/dist/lib/metrics.d.ts +48 -0
  175. package/dist/lib/metrics.d.ts.map +1 -0
  176. package/dist/lib/metrics.js +107 -0
  177. package/dist/lib/metrics.js.map +1 -0
  178. package/dist/lib/openai-local-execution.d.ts +29 -0
  179. package/dist/lib/openai-local-execution.d.ts.map +1 -0
  180. package/dist/lib/openai-local-execution.js +282 -0
  181. package/dist/lib/openai-local-execution.js.map +1 -0
  182. package/dist/lib/project-metadata/csharp.d.ts +6 -0
  183. package/dist/lib/project-metadata/csharp.d.ts.map +1 -0
  184. package/dist/lib/project-metadata/csharp.js +19 -0
  185. package/dist/lib/project-metadata/csharp.js.map +1 -0
  186. package/dist/lib/project-metadata/elixir.d.ts +6 -0
  187. package/dist/lib/project-metadata/elixir.d.ts.map +1 -0
  188. package/dist/lib/project-metadata/elixir.js +23 -0
  189. package/dist/lib/project-metadata/elixir.js.map +1 -0
  190. package/dist/lib/project-metadata/go.d.ts +6 -0
  191. package/dist/lib/project-metadata/go.d.ts.map +1 -0
  192. package/dist/lib/project-metadata/go.js +30 -0
  193. package/dist/lib/project-metadata/go.js.map +1 -0
  194. package/dist/lib/project-metadata/index.d.ts +13 -0
  195. package/dist/lib/project-metadata/index.d.ts.map +1 -0
  196. package/dist/lib/project-metadata/index.js +111 -0
  197. package/dist/lib/project-metadata/index.js.map +1 -0
  198. package/dist/lib/project-metadata/java.d.ts +6 -0
  199. package/dist/lib/project-metadata/java.d.ts.map +1 -0
  200. package/dist/lib/project-metadata/java.js +37 -0
  201. package/dist/lib/project-metadata/java.js.map +1 -0
  202. package/dist/lib/project-metadata/node.d.ts +6 -0
  203. package/dist/lib/project-metadata/node.d.ts.map +1 -0
  204. package/dist/lib/project-metadata/node.js +135 -0
  205. package/dist/lib/project-metadata/node.js.map +1 -0
  206. package/dist/lib/project-metadata/php.d.ts +6 -0
  207. package/dist/lib/project-metadata/php.d.ts.map +1 -0
  208. package/dist/lib/project-metadata/php.js +29 -0
  209. package/dist/lib/project-metadata/php.js.map +1 -0
  210. package/dist/lib/project-metadata/python.d.ts +6 -0
  211. package/dist/lib/project-metadata/python.d.ts.map +1 -0
  212. package/dist/lib/project-metadata/python.js +79 -0
  213. package/dist/lib/project-metadata/python.js.map +1 -0
  214. package/dist/lib/project-metadata/ruby.d.ts +6 -0
  215. package/dist/lib/project-metadata/ruby.d.ts.map +1 -0
  216. package/dist/lib/project-metadata/ruby.js +38 -0
  217. package/dist/lib/project-metadata/ruby.js.map +1 -0
  218. package/dist/lib/project-metadata/rust.d.ts +6 -0
  219. package/dist/lib/project-metadata/rust.d.ts.map +1 -0
  220. package/dist/lib/project-metadata/rust.js +33 -0
  221. package/dist/lib/project-metadata/rust.js.map +1 -0
  222. package/dist/lib/project-metadata/swift.d.ts +6 -0
  223. package/dist/lib/project-metadata/swift.d.ts.map +1 -0
  224. package/dist/lib/project-metadata/swift.js +19 -0
  225. package/dist/lib/project-metadata/swift.js.map +1 -0
  226. package/dist/lib/project-metadata/types.d.ts +37 -0
  227. package/dist/lib/project-metadata/types.d.ts.map +1 -0
  228. package/dist/lib/project-metadata/types.js +5 -0
  229. package/dist/lib/project-metadata/types.js.map +1 -0
  230. package/dist/lib/proposal-review.d.ts +9 -0
  231. package/dist/lib/proposal-review.d.ts.map +1 -0
  232. package/dist/lib/proposal-review.js +9 -0
  233. package/dist/lib/proposal-review.js.map +1 -0
  234. package/dist/lib/providers/claude.d.ts +6 -0
  235. package/dist/lib/providers/claude.d.ts.map +1 -0
  236. package/dist/lib/providers/claude.js +21 -0
  237. package/dist/lib/providers/claude.js.map +1 -0
  238. package/dist/lib/providers/codex.d.ts +6 -0
  239. package/dist/lib/providers/codex.d.ts.map +1 -0
  240. package/dist/lib/providers/codex.js +26 -0
  241. package/dist/lib/providers/codex.js.map +1 -0
  242. package/dist/lib/providers/index.d.ts +22 -0
  243. package/dist/lib/providers/index.d.ts.map +1 -0
  244. package/dist/lib/providers/index.js +39 -0
  245. package/dist/lib/providers/index.js.map +1 -0
  246. package/dist/lib/providers/kimi.d.ts +6 -0
  247. package/dist/lib/providers/kimi.d.ts.map +1 -0
  248. package/dist/lib/providers/kimi.js +22 -0
  249. package/dist/lib/providers/kimi.js.map +1 -0
  250. package/dist/lib/providers/openai-local.d.ts +8 -0
  251. package/dist/lib/providers/openai-local.d.ts.map +1 -0
  252. package/dist/lib/providers/openai-local.js +30 -0
  253. package/dist/lib/providers/openai-local.js.map +1 -0
  254. package/dist/lib/providers/types.d.ts +37 -0
  255. package/dist/lib/providers/types.d.ts.map +1 -0
  256. package/dist/lib/providers/types.js +5 -0
  257. package/dist/lib/providers/types.js.map +1 -0
  258. package/dist/lib/qa-stats.d.ts +113 -0
  259. package/dist/lib/qa-stats.d.ts.map +1 -0
  260. package/dist/lib/qa-stats.js +311 -0
  261. package/dist/lib/qa-stats.js.map +1 -0
  262. package/dist/lib/retention.d.ts +125 -0
  263. package/dist/lib/retention.d.ts.map +1 -0
  264. package/dist/lib/retention.js +767 -0
  265. package/dist/lib/retention.js.map +1 -0
  266. package/dist/lib/run-history.d.ts +52 -0
  267. package/dist/lib/run-history.d.ts.map +1 -0
  268. package/dist/lib/run-history.js +116 -0
  269. package/dist/lib/run-history.js.map +1 -0
  270. package/dist/lib/run-state.d.ts +129 -0
  271. package/dist/lib/run-state.d.ts.map +1 -0
  272. package/dist/lib/run-state.js +312 -0
  273. package/dist/lib/run-state.js.map +1 -0
  274. package/dist/lib/scope.d.ts +8 -0
  275. package/dist/lib/scope.d.ts.map +1 -0
  276. package/dist/lib/scope.js +8 -0
  277. package/dist/lib/scope.js.map +1 -0
  278. package/dist/lib/scout-prompt-builder.d.ts +22 -0
  279. package/dist/lib/scout-prompt-builder.d.ts.map +1 -0
  280. package/dist/lib/scout-prompt-builder.js +97 -0
  281. package/dist/lib/scout-prompt-builder.js.map +1 -0
  282. package/dist/lib/sectors.d.ts +21 -0
  283. package/dist/lib/sectors.d.ts.map +1 -0
  284. package/dist/lib/sectors.js +96 -0
  285. package/dist/lib/sectors.js.map +1 -0
  286. package/dist/lib/selection.d.ts +35 -0
  287. package/dist/lib/selection.d.ts.map +1 -0
  288. package/dist/lib/selection.js +110 -0
  289. package/dist/lib/selection.js.map +1 -0
  290. package/dist/lib/session-report.d.ts +26 -0
  291. package/dist/lib/session-report.d.ts.map +1 -0
  292. package/dist/lib/session-report.js +143 -0
  293. package/dist/lib/session-report.js.map +1 -0
  294. package/dist/lib/solo-auto-between-cycles.d.ts +10 -0
  295. package/dist/lib/solo-auto-between-cycles.d.ts.map +1 -0
  296. package/dist/lib/solo-auto-between-cycles.js +577 -0
  297. package/dist/lib/solo-auto-between-cycles.js.map +1 -0
  298. package/dist/lib/solo-auto-execute.d.ts +22 -0
  299. package/dist/lib/solo-auto-execute.d.ts.map +1 -0
  300. package/dist/lib/solo-auto-execute.js +530 -0
  301. package/dist/lib/solo-auto-execute.js.map +1 -0
  302. package/dist/lib/solo-auto-filter.d.ts +14 -0
  303. package/dist/lib/solo-auto-filter.d.ts.map +1 -0
  304. package/dist/lib/solo-auto-filter.js +311 -0
  305. package/dist/lib/solo-auto-filter.js.map +1 -0
  306. package/dist/lib/solo-auto-finalize.d.ts +6 -0
  307. package/dist/lib/solo-auto-finalize.d.ts.map +1 -0
  308. package/dist/lib/solo-auto-finalize.js +242 -0
  309. package/dist/lib/solo-auto-finalize.js.map +1 -0
  310. package/dist/lib/solo-auto-init-qa.d.ts +23 -0
  311. package/dist/lib/solo-auto-init-qa.d.ts.map +1 -0
  312. package/dist/lib/solo-auto-init-qa.js +183 -0
  313. package/dist/lib/solo-auto-init-qa.js.map +1 -0
  314. package/dist/lib/solo-auto-planning.d.ts +40 -0
  315. package/dist/lib/solo-auto-planning.d.ts.map +1 -0
  316. package/dist/lib/solo-auto-planning.js +171 -0
  317. package/dist/lib/solo-auto-planning.js.map +1 -0
  318. package/dist/lib/solo-auto-scout.d.ts +18 -0
  319. package/dist/lib/solo-auto-scout.d.ts.map +1 -0
  320. package/dist/lib/solo-auto-scout.js +269 -0
  321. package/dist/lib/solo-auto-scout.js.map +1 -0
  322. package/dist/lib/solo-auto-state.d.ts +20 -0
  323. package/dist/lib/solo-auto-state.d.ts.map +1 -0
  324. package/dist/lib/solo-auto-state.js +859 -0
  325. package/dist/lib/solo-auto-state.js.map +1 -0
  326. package/dist/lib/solo-auto-types.d.ts +197 -0
  327. package/dist/lib/solo-auto-types.d.ts.map +1 -0
  328. package/dist/lib/solo-auto-types.js +11 -0
  329. package/dist/lib/solo-auto-types.js.map +1 -0
  330. package/dist/lib/solo-auto-utils.d.ts +23 -0
  331. package/dist/lib/solo-auto-utils.d.ts.map +1 -0
  332. package/dist/lib/solo-auto-utils.js +53 -0
  333. package/dist/lib/solo-auto-utils.js.map +1 -0
  334. package/dist/lib/solo-auto.d.ts +25 -0
  335. package/dist/lib/solo-auto.d.ts.map +1 -0
  336. package/dist/lib/solo-auto.js +345 -0
  337. package/dist/lib/solo-auto.js.map +1 -0
  338. package/dist/lib/solo-ci.d.ts +84 -0
  339. package/dist/lib/solo-ci.d.ts.map +1 -0
  340. package/dist/lib/solo-ci.js +306 -0
  341. package/dist/lib/solo-ci.js.map +1 -0
  342. package/dist/lib/solo-config.d.ts +242 -0
  343. package/dist/lib/solo-config.d.ts.map +1 -0
  344. package/dist/lib/solo-config.js +354 -0
  345. package/dist/lib/solo-config.js.map +1 -0
  346. package/dist/lib/solo-cycle-formula.d.ts +36 -0
  347. package/dist/lib/solo-cycle-formula.d.ts.map +1 -0
  348. package/dist/lib/solo-cycle-formula.js +90 -0
  349. package/dist/lib/solo-cycle-formula.js.map +1 -0
  350. package/dist/lib/solo-git.d.ts +87 -0
  351. package/dist/lib/solo-git.d.ts.map +1 -0
  352. package/dist/lib/solo-git.js +365 -0
  353. package/dist/lib/solo-git.js.map +1 -0
  354. package/dist/lib/solo-hints.d.ts +32 -0
  355. package/dist/lib/solo-hints.d.ts.map +1 -0
  356. package/dist/lib/solo-hints.js +98 -0
  357. package/dist/lib/solo-hints.js.map +1 -0
  358. package/dist/lib/solo-prompt-builder.d.ts +12 -0
  359. package/dist/lib/solo-prompt-builder.d.ts.map +1 -0
  360. package/dist/lib/solo-prompt-builder.js +53 -0
  361. package/dist/lib/solo-prompt-builder.js.map +1 -0
  362. package/dist/lib/solo-qa-retry.d.ts +43 -0
  363. package/dist/lib/solo-qa-retry.d.ts.map +1 -0
  364. package/dist/lib/solo-qa-retry.js +125 -0
  365. package/dist/lib/solo-qa-retry.js.map +1 -0
  366. package/dist/lib/solo-remote.d.ts +14 -0
  367. package/dist/lib/solo-remote.d.ts.map +1 -0
  368. package/dist/lib/solo-remote.js +48 -0
  369. package/dist/lib/solo-remote.js.map +1 -0
  370. package/dist/lib/solo-session-summary.d.ts +52 -0
  371. package/dist/lib/solo-session-summary.d.ts.map +1 -0
  372. package/dist/lib/solo-session-summary.js +188 -0
  373. package/dist/lib/solo-session-summary.js.map +1 -0
  374. package/dist/lib/solo-stdin.d.ts +33 -0
  375. package/dist/lib/solo-stdin.d.ts.map +1 -0
  376. package/dist/lib/solo-stdin.js +299 -0
  377. package/dist/lib/solo-stdin.js.map +1 -0
  378. package/dist/lib/solo-ticket-qa.d.ts +19 -0
  379. package/dist/lib/solo-ticket-qa.d.ts.map +1 -0
  380. package/dist/lib/solo-ticket-qa.js +68 -0
  381. package/dist/lib/solo-ticket-qa.js.map +1 -0
  382. package/dist/lib/solo-ticket-types.d.ts +146 -0
  383. package/dist/lib/solo-ticket-types.d.ts.map +1 -0
  384. package/dist/lib/solo-ticket-types.js +26 -0
  385. package/dist/lib/solo-ticket-types.js.map +1 -0
  386. package/dist/lib/solo-ticket.d.ts +12 -0
  387. package/dist/lib/solo-ticket.d.ts.map +1 -0
  388. package/dist/lib/solo-ticket.js +192 -0
  389. package/dist/lib/solo-ticket.js.map +1 -0
  390. package/dist/lib/solo-utils.d.ts +130 -0
  391. package/dist/lib/solo-utils.d.ts.map +1 -0
  392. package/dist/lib/solo-utils.js +277 -0
  393. package/dist/lib/solo-utils.js.map +1 -0
  394. package/dist/lib/spindle/failure-patterns.d.ts +15 -0
  395. package/dist/lib/spindle/failure-patterns.d.ts.map +1 -0
  396. package/dist/lib/spindle/failure-patterns.js +22 -0
  397. package/dist/lib/spindle/failure-patterns.js.map +1 -0
  398. package/dist/lib/spindle/format.d.ts +9 -0
  399. package/dist/lib/spindle/format.d.ts.map +1 -0
  400. package/dist/lib/spindle/format.js +37 -0
  401. package/dist/lib/spindle/format.js.map +1 -0
  402. package/dist/lib/spindle/index.d.ts +33 -0
  403. package/dist/lib/spindle/index.d.ts.map +1 -0
  404. package/dist/lib/spindle/index.js +231 -0
  405. package/dist/lib/spindle/index.js.map +1 -0
  406. package/dist/lib/spindle/oscillation.d.ts +17 -0
  407. package/dist/lib/spindle/oscillation.d.ts.map +1 -0
  408. package/dist/lib/spindle/oscillation.js +96 -0
  409. package/dist/lib/spindle/oscillation.js.map +1 -0
  410. package/dist/lib/spindle/repetition.d.ts +16 -0
  411. package/dist/lib/spindle/repetition.d.ts.map +1 -0
  412. package/dist/lib/spindle/repetition.js +52 -0
  413. package/dist/lib/spindle/repetition.js.map +1 -0
  414. package/dist/lib/spindle/similarity.d.ts +14 -0
  415. package/dist/lib/spindle/similarity.d.ts.map +1 -0
  416. package/dist/lib/spindle/similarity.js +58 -0
  417. package/dist/lib/spindle/similarity.js.map +1 -0
  418. package/dist/lib/spindle/types.d.ts +97 -0
  419. package/dist/lib/spindle/types.d.ts.map +1 -0
  420. package/dist/lib/spindle/types.js +46 -0
  421. package/dist/lib/spindle/types.js.map +1 -0
  422. package/dist/lib/spinner.d.ts +41 -0
  423. package/dist/lib/spinner.d.ts.map +1 -0
  424. package/dist/lib/spinner.js +186 -0
  425. package/dist/lib/spinner.js.map +1 -0
  426. package/dist/lib/taste-profile.d.ts +26 -0
  427. package/dist/lib/taste-profile.d.ts.map +1 -0
  428. package/dist/lib/taste-profile.js +121 -0
  429. package/dist/lib/taste-profile.js.map +1 -0
  430. package/dist/lib/ticket-steps/index.d.ts +14 -0
  431. package/dist/lib/ticket-steps/index.d.ts.map +1 -0
  432. package/dist/lib/ticket-steps/index.js +13 -0
  433. package/dist/lib/ticket-steps/index.js.map +1 -0
  434. package/dist/lib/ticket-steps/step-agent.d.ts +6 -0
  435. package/dist/lib/ticket-steps/step-agent.d.ts.map +1 -0
  436. package/dist/lib/ticket-steps/step-agent.js +122 -0
  437. package/dist/lib/ticket-steps/step-agent.js.map +1 -0
  438. package/dist/lib/ticket-steps/step-cleanup.d.ts +6 -0
  439. package/dist/lib/ticket-steps/step-cleanup.d.ts.map +1 -0
  440. package/dist/lib/ticket-steps/step-cleanup.js +11 -0
  441. package/dist/lib/ticket-steps/step-cleanup.js.map +1 -0
  442. package/dist/lib/ticket-steps/step-commit.d.ts +6 -0
  443. package/dist/lib/ticket-steps/step-commit.d.ts.map +1 -0
  444. package/dist/lib/ticket-steps/step-commit.js +31 -0
  445. package/dist/lib/ticket-steps/step-commit.js.map +1 -0
  446. package/dist/lib/ticket-steps/step-pr.d.ts +6 -0
  447. package/dist/lib/ticket-steps/step-pr.d.ts.map +1 -0
  448. package/dist/lib/ticket-steps/step-pr.js +38 -0
  449. package/dist/lib/ticket-steps/step-pr.js.map +1 -0
  450. package/dist/lib/ticket-steps/step-push.d.ts +6 -0
  451. package/dist/lib/ticket-steps/step-push.d.ts.map +1 -0
  452. package/dist/lib/ticket-steps/step-push.js +35 -0
  453. package/dist/lib/ticket-steps/step-push.js.map +1 -0
  454. package/dist/lib/ticket-steps/step-qa.d.ts +6 -0
  455. package/dist/lib/ticket-steps/step-qa.d.ts.map +1 -0
  456. package/dist/lib/ticket-steps/step-qa.js +300 -0
  457. package/dist/lib/ticket-steps/step-qa.js.map +1 -0
  458. package/dist/lib/ticket-steps/step-scope.d.ts +6 -0
  459. package/dist/lib/ticket-steps/step-scope.d.ts.map +1 -0
  460. package/dist/lib/ticket-steps/step-scope.js +121 -0
  461. package/dist/lib/ticket-steps/step-scope.js.map +1 -0
  462. package/dist/lib/ticket-steps/step-spindle.d.ts +9 -0
  463. package/dist/lib/ticket-steps/step-spindle.d.ts.map +1 -0
  464. package/dist/lib/ticket-steps/step-spindle.js +160 -0
  465. package/dist/lib/ticket-steps/step-spindle.js.map +1 -0
  466. package/dist/lib/ticket-steps/step-worktree.d.ts +6 -0
  467. package/dist/lib/ticket-steps/step-worktree.d.ts.map +1 -0
  468. package/dist/lib/ticket-steps/step-worktree.js +157 -0
  469. package/dist/lib/ticket-steps/step-worktree.js.map +1 -0
  470. package/dist/lib/ticket-steps/types.d.ts +70 -0
  471. package/dist/lib/ticket-steps/types.d.ts.map +1 -0
  472. package/dist/lib/ticket-steps/types.js +8 -0
  473. package/dist/lib/ticket-steps/types.js.map +1 -0
  474. package/dist/lib/tool-command-map.d.ts +11 -0
  475. package/dist/lib/tool-command-map.d.ts.map +1 -0
  476. package/dist/lib/tool-command-map.js +24 -0
  477. package/dist/lib/tool-command-map.js.map +1 -0
  478. package/dist/lib/trajectory-generate.d.ts +24 -0
  479. package/dist/lib/trajectory-generate.d.ts.map +1 -0
  480. package/dist/lib/trajectory-generate.js +163 -0
  481. package/dist/lib/trajectory-generate.js.map +1 -0
  482. package/dist/lib/trajectory.d.ts +20 -0
  483. package/dist/lib/trajectory.d.ts.map +1 -0
  484. package/dist/lib/trajectory.js +104 -0
  485. package/dist/lib/trajectory.js.map +1 -0
  486. package/dist/lib/trigger-config.d.ts +12 -0
  487. package/dist/lib/trigger-config.d.ts.map +1 -0
  488. package/dist/lib/trigger-config.js +37 -0
  489. package/dist/lib/trigger-config.js.map +1 -0
  490. package/dist/lib/update-check.d.ts +28 -0
  491. package/dist/lib/update-check.d.ts.map +1 -0
  492. package/dist/lib/update-check.js +178 -0
  493. package/dist/lib/update-check.js.map +1 -0
  494. package/dist/lib/wave-scheduling.d.ts +18 -0
  495. package/dist/lib/wave-scheduling.d.ts.map +1 -0
  496. package/dist/lib/wave-scheduling.js +29 -0
  497. package/dist/lib/wave-scheduling.js.map +1 -0
  498. package/dist/tui/app.d.ts +17 -0
  499. package/dist/tui/app.d.ts.map +1 -0
  500. package/dist/tui/app.js +139 -0
  501. package/dist/tui/app.js.map +1 -0
  502. package/dist/tui/index.d.ts +10 -0
  503. package/dist/tui/index.d.ts.map +1 -0
  504. package/dist/tui/index.js +9 -0
  505. package/dist/tui/index.js.map +1 -0
  506. package/dist/tui/poller.d.ts +42 -0
  507. package/dist/tui/poller.d.ts.map +1 -0
  508. package/dist/tui/poller.js +62 -0
  509. package/dist/tui/poller.js.map +1 -0
  510. package/dist/tui/screens/auto.d.ts +85 -0
  511. package/dist/tui/screens/auto.d.ts.map +1 -0
  512. package/dist/tui/screens/auto.js +440 -0
  513. package/dist/tui/screens/auto.js.map +1 -0
  514. package/dist/tui/screens/overview.d.ts +9 -0
  515. package/dist/tui/screens/overview.d.ts.map +1 -0
  516. package/dist/tui/screens/overview.js +189 -0
  517. package/dist/tui/screens/overview.js.map +1 -0
  518. package/dist/tui/state.d.ts +93 -0
  519. package/dist/tui/state.d.ts.map +1 -0
  520. package/dist/tui/state.js +169 -0
  521. package/dist/tui/state.js.map +1 -0
  522. package/dist/tui/ticket-output-buffer.d.ts +23 -0
  523. package/dist/tui/ticket-output-buffer.d.ts.map +1 -0
  524. package/dist/tui/ticket-output-buffer.js +60 -0
  525. package/dist/tui/ticket-output-buffer.js.map +1 -0
  526. package/dist/tui/types.d.ts +18 -0
  527. package/dist/tui/types.d.ts.map +1 -0
  528. package/dist/tui/types.js +5 -0
  529. package/dist/tui/types.js.map +1 -0
  530. package/package.json +70 -0
@@ -0,0 +1,859 @@
1
+ /**
2
+ * AutoSessionState — mutable context object for runAutoMode.
3
+ * Replaces ~55 closure variables with a single passable struct.
4
+ */
5
+ import * as fs from 'node:fs';
6
+ import * as path from 'node:path';
7
+ import { createRequire } from 'node:module';
8
+ import chalk from 'chalk';
9
+ const _require = createRequire(import.meta.url);
10
+ const CLI_VERSION = _require('../../package.json').version;
11
+ import { spawnSync } from 'node:child_process';
12
+ import { projects } from '@promptwheel/core/repos';
13
+ import { createGitService } from './git.js';
14
+ import { getAdapter, isInitialized, initSolo, loadConfig, createScoutDeps, } from './solo-config.js';
15
+ import { runPreflightChecks } from './solo-utils.js';
16
+ import { readRunState } from './run-state.js';
17
+ import { getCycleFormula as getCycleFormulaImpl, getCycleCategories as getCycleCategoriesImpl } from './solo-cycle-formula.js';
18
+ import { createMilestoneBranch, cleanupMilestone, pushAndPrMilestone, ensureDirectBranch, cleanupMergedDirectBranch, } from './solo-git.js';
19
+ import { startInteractiveConsole } from './solo-stdin.js';
20
+ import { loadGuidelines } from './guidelines.js';
21
+ import { loadLearnings } from './learnings.js';
22
+ import { loadDedupMemory, } from './dedup-memory.js';
23
+ import { pruneStaleWorktrees, pruneStaleBranches, pruneStaleCodexSessions, gitWorktreePrune, acquireSessionLock, releaseSessionLock } from './retention.js';
24
+ import { resetQaStatsForSession } from './qa-stats.js';
25
+ import { buildCodebaseIndex, } from './codebase-index.js';
26
+ import { detectProjectMetadata, formatMetadataForPrompt } from './project-metadata/index.js';
27
+ import { DEFAULT_AUTO_CONFIG } from './solo-config.js';
28
+ import { loadOrBuildSectors, pickNextSector, } from './sectors.js';
29
+ import { loadTasteProfile } from './taste-profile.js';
30
+ import { loadGoals, measureGoals, pickGoalByGap, recordGoalMeasurement, } from './goals.js';
31
+ import { loadTrajectoryState, loadTrajectory, } from './trajectory.js';
32
+ import { getNextStep as getTrajectoryNextStep } from '@promptwheel/core/trajectory/shared';
33
+ import { SpinnerDisplayAdapter } from './display-adapter-spinner.js';
34
+ import { LogDisplayAdapter } from './display-adapter-log.js';
35
+ import { initMetrics, metric } from './metrics.js';
36
+ /** Parse CLI options into resolved values. Loads formula if specified. */
37
+ async function resolveOptions(options) {
38
+ let activeFormula = null;
39
+ if (options.formula) {
40
+ const { loadFormula, listFormulas } = await import('./formulas.js');
41
+ activeFormula = loadFormula(options.formula);
42
+ if (!activeFormula) {
43
+ const available = listFormulas();
44
+ console.error(chalk.red(`✗ Formula not found: ${options.formula}`));
45
+ console.error(chalk.gray(` Available formulas: ${available.map(f => f.name).join(', ')}`));
46
+ process.exit(1);
47
+ }
48
+ console.log(chalk.cyan(`📜 Using formula: ${activeFormula.name}`));
49
+ console.log(chalk.gray(` ${activeFormula.description}`));
50
+ if (activeFormula.prompt) {
51
+ console.log(chalk.gray(` Prompt: ${activeFormula.prompt.slice(0, 80)}...`));
52
+ }
53
+ console.log();
54
+ }
55
+ const hoursValue = options.hours ? parseFloat(options.hours) : 0;
56
+ const minutesValue = options.minutes ? parseFloat(options.minutes) : 0;
57
+ const totalMinutes = (hoursValue * 60 + minutesValue) || undefined;
58
+ const maxCycles = options.cycles ? parseInt(options.cycles, 10) : 999;
59
+ const explicitWheel = options.wheel || options.continuous;
60
+ const impliedWheel = totalMinutes !== undefined || (options.cycles && maxCycles > 1);
61
+ const runMode = (explicitWheel || impliedWheel) ? 'wheel' : 'planning';
62
+ const endTime = totalMinutes ? Date.now() + (totalMinutes * 60 * 1000) : undefined;
63
+ const defaultMaxPrs = runMode === 'wheel' ? 999 : 3;
64
+ const maxPrs = parseInt(options.maxPrs || String(activeFormula?.maxPrs ?? defaultMaxPrs), 10);
65
+ const minConfidence = parseInt(options.minConfidence || String(activeFormula?.minConfidence ?? DEFAULT_AUTO_CONFIG.minConfidence), 10);
66
+ const useDraft = options.draft !== false;
67
+ const batchSize = options.batchSize ? parseInt(options.batchSize, 10) : undefined;
68
+ const milestoneMode = batchSize !== undefined && batchSize > 0;
69
+ const userScope = options.scope || activeFormula?.scope;
70
+ const parallelExplicit = options.parallel !== undefined && options.parallel !== '3';
71
+ return {
72
+ activeFormula, totalMinutes, maxCycles, runMode, endTime,
73
+ maxPrs, minConfidence, useDraft, batchSize, milestoneMode,
74
+ userScope, parallelExplicit,
75
+ };
76
+ }
77
+ /**
78
+ * Set up the execution environment: find repo, acquire lock, clean up stale
79
+ * resources, run setup command, QA baseline, preflight checks.
80
+ */
81
+ async function initEnvironment(options, resolved) {
82
+ const git = createGitService();
83
+ const repoRoot = await git.findRepoRoot(process.cwd());
84
+ if (!repoRoot) {
85
+ console.error(chalk.red('✗ Not a git repository'));
86
+ process.exit(1);
87
+ }
88
+ initMetrics(repoRoot);
89
+ metric('session', 'started', { codex: !!options.codex, hours: options.hours });
90
+ // Session lock
91
+ const lockResult = acquireSessionLock(repoRoot);
92
+ if (!lockResult.acquired) {
93
+ console.error(chalk.red('✗ Another PromptWheel session is already running in this repo'));
94
+ process.exit(1);
95
+ }
96
+ if (lockResult.stalePid) {
97
+ console.log(chalk.gray(` Cleaned up stale session lock (PID ${lockResult.stalePid})`));
98
+ }
99
+ const releaseLock = () => releaseSessionLock(repoRoot);
100
+ process.on('exit', releaseLock);
101
+ // Clean up stale resources
102
+ gitWorktreePrune(repoRoot);
103
+ const prunedWorktrees = pruneStaleWorktrees(repoRoot);
104
+ if (prunedWorktrees > 0) {
105
+ console.log(chalk.gray(` Cleaned up ${prunedWorktrees} stale worktree(s)`));
106
+ }
107
+ const prunedBranches = pruneStaleBranches(repoRoot, 7);
108
+ if (prunedBranches > 0) {
109
+ console.log(chalk.gray(` Cleaned up ${prunedBranches} stale branch(es)`));
110
+ }
111
+ const prunedCodexSessions = pruneStaleCodexSessions(7);
112
+ if (prunedCodexSessions > 0) {
113
+ console.log(chalk.gray(` Cleaned up ${prunedCodexSessions} stale codex session(s)`));
114
+ }
115
+ resetQaStatsForSession(repoRoot);
116
+ let config = loadConfig(repoRoot);
117
+ // Project setup command
118
+ if (config?.setup && !options.dryRun) {
119
+ console.log(chalk.gray(` Running setup: ${config.setup}`));
120
+ try {
121
+ const { execSync } = await import('node:child_process');
122
+ execSync(config.setup, { cwd: repoRoot, timeout: 300_000, stdio: 'pipe' });
123
+ console.log(chalk.green(' ✓ Setup complete'));
124
+ }
125
+ catch (err) {
126
+ const msg = err instanceof Error ? err.message : String(err);
127
+ console.log(chalk.yellow(` ⚠ Setup failed: ${msg.split('\n')[0]}`));
128
+ }
129
+ }
130
+ // QA baseline
131
+ let cachedQaBaseline = null;
132
+ if (config?.qa?.commands?.length && !options.dryRun) {
133
+ const { initQaBaseline } = await import('./solo-auto-init-qa.js');
134
+ const qaResult = await initQaBaseline(repoRoot, config, {
135
+ qaFix: !!options.qaFix,
136
+ codex: options.codex,
137
+ codexModel: options.codexModel,
138
+ dryRun: options.dryRun,
139
+ });
140
+ config = qaResult.config;
141
+ cachedQaBaseline = qaResult.qaBaseline;
142
+ }
143
+ // Auto-init if needed (before .gitignore and dirty check so the
144
+ // auto-committed .gitignore doesn't trip the "uncommitted changes" error)
145
+ if (!isInitialized(repoRoot)) {
146
+ console.log(chalk.cyan('First run — initializing PromptWheel...'));
147
+ const { detectedQa } = await initSolo(repoRoot);
148
+ if (detectedQa.length > 0) {
149
+ console.log(chalk.green(` ✓ Detected QA: ${detectedQa.map(q => q.name).join(', ')}`));
150
+ }
151
+ console.log(chalk.green(' ✓ Ready'));
152
+ console.log();
153
+ }
154
+ // Ensure .promptwheel is in .gitignore
155
+ const gitignorePath = path.join(repoRoot, '.gitignore');
156
+ if (fs.existsSync(gitignorePath)) {
157
+ const giContent = fs.readFileSync(gitignorePath, 'utf-8');
158
+ if (!giContent.includes('.promptwheel')) {
159
+ fs.appendFileSync(gitignorePath, '\n# PromptWheel local state\n.promptwheel/\n');
160
+ }
161
+ }
162
+ // Check working tree
163
+ const statusResult = spawnSync('git', ['status', '--porcelain'], { cwd: repoRoot });
164
+ const statusLines = statusResult.stdout?.toString().trim().split('\n').filter(Boolean) || [];
165
+ const modifiedFiles = statusLines.filter(line => !line.startsWith('??'));
166
+ if (modifiedFiles.length > 0 && !options.dryRun) {
167
+ const onlyGitignore = modifiedFiles.length === 1 &&
168
+ modifiedFiles[0].trim().endsWith('.gitignore');
169
+ if (onlyGitignore) {
170
+ const giPath = path.join(repoRoot, '.gitignore');
171
+ const content = fs.readFileSync(giPath, 'utf-8');
172
+ if (content.includes('.promptwheel')) {
173
+ spawnSync('git', ['add', '.gitignore'], { cwd: repoRoot });
174
+ spawnSync('git', ['commit', '-m', 'chore: add .promptwheel to .gitignore'], { cwd: repoRoot });
175
+ console.log(chalk.gray(' Auto-committed .gitignore update'));
176
+ }
177
+ }
178
+ else {
179
+ console.error(chalk.red('✗ Working tree has uncommitted changes'));
180
+ console.error(chalk.gray(' Commit or stash your changes first'));
181
+ process.exit(1);
182
+ }
183
+ }
184
+ // Preflight — delivery mode isn't resolved yet (needs autoConf), so check
185
+ // the raw CLI flags. Config-level delivery defaults to 'direct' which
186
+ // doesn't need PR capabilities, so CLI flags are sufficient here.
187
+ const willCreatePrs = resolved.milestoneMode || options.deliveryMode === 'pr' || options.deliveryMode === 'auto-merge' || options.directFinalize === 'pr';
188
+ const preflight = await runPreflightChecks(repoRoot, { needsPr: willCreatePrs });
189
+ if (!preflight.ok) {
190
+ console.error(chalk.red(`✗ ${preflight.error}`));
191
+ process.exit(1);
192
+ }
193
+ for (const warning of preflight.warnings) {
194
+ console.log(chalk.yellow(`⚠ ${warning}`));
195
+ }
196
+ const autoConf = { ...DEFAULT_AUTO_CONFIG, ...config?.auto };
197
+ const adapter = await getAdapter(repoRoot);
198
+ return { repoRoot, config, autoConf, cachedQaBaseline, adapter };
199
+ }
200
+ /**
201
+ * Load all session data from disk: formulas, guidelines, learnings, dedup
202
+ * memory, codebase index, metadata, sectors, goals, backend settings.
203
+ */
204
+ async function loadSessionData(options, resolved, repoRoot, config, autoConf, cachedQaBaseline, adapter) {
205
+ // Formulas for deep scan and docs audit
206
+ let deepFormula = null;
207
+ let docsAuditFormula = null;
208
+ if (!resolved.activeFormula) {
209
+ const { loadFormula: loadF } = await import('./formulas.js');
210
+ if (resolved.runMode === 'wheel') {
211
+ deepFormula = loadF('deep');
212
+ }
213
+ if (options.docsAudit !== false) {
214
+ docsAuditFormula = loadF('docs-audit');
215
+ }
216
+ }
217
+ // Guidelines
218
+ const guidelinesBackend = [options.scoutBackend, options.executeBackend].find(b => b && b !== 'claude') ?? 'claude';
219
+ const guidelinesOpts = {
220
+ backend: guidelinesBackend,
221
+ autoCreate: config?.auto?.autoCreateGuidelines !== false,
222
+ customPath: config?.auto?.guidelinesPath || undefined,
223
+ };
224
+ const guidelines = loadGuidelines(repoRoot, guidelinesOpts);
225
+ const guidelinesRefreshInterval = config?.auto?.guidelinesRefreshCycles ?? 10;
226
+ if (guidelines) {
227
+ console.log(chalk.gray(` Guidelines loaded: ${guidelines.source}`));
228
+ }
229
+ // Learnings
230
+ const allLearnings = autoConf.learningsEnabled
231
+ ? loadLearnings(repoRoot, autoConf.learningsDecayRate) : [];
232
+ if (allLearnings.length > 0) {
233
+ console.log(chalk.gray(` Learnings loaded: ${allLearnings.length}`));
234
+ }
235
+ // Wheel health summary
236
+ {
237
+ const { getQualityRate } = await import('./run-state.js');
238
+ const qualityRate = getQualityRate(repoRoot);
239
+ const qualityPct = Math.round(qualityRate * 100);
240
+ const confValue = autoConf.minConfidence ?? 20;
241
+ const baselineFailing = cachedQaBaseline
242
+ ? [...cachedQaBaseline.values()].filter(v => !v).length
243
+ : 0;
244
+ const qualityColor = qualityRate < 0.5 ? chalk.yellow : chalk.gray;
245
+ const healthParts = [`Quality rate: ${qualityPct}%`, `Confidence: ${confValue}`];
246
+ if (baselineFailing > 0)
247
+ healthParts.push(`Baseline failing: ${baselineFailing}`);
248
+ console.log(qualityColor(` ${healthParts.join(' | ')}`));
249
+ }
250
+ // Backend settings
251
+ const activeBackendName = options.scoutBackend ?? 'claude';
252
+ const backendConf = activeBackendName === 'codex' ? autoConf.codex : autoConf.claude;
253
+ const { getProvider: getProviderDefaults } = await import('./providers/index.js');
254
+ const activeProviderDefaults = getProviderDefaults(activeBackendName);
255
+ const batchTokenBudget = options.batchTokenBudget
256
+ ? parseInt(options.batchTokenBudget, 10)
257
+ : (backendConf?.batchTokenBudget ?? autoConf.batchTokenBudget ?? activeProviderDefaults.defaultBatchTokenBudget);
258
+ const scoutConcurrency = options.scoutConcurrency
259
+ ? parseInt(options.scoutConcurrency, 10)
260
+ : (backendConf?.scoutConcurrency ?? autoConf.scoutConcurrency ?? activeProviderDefaults.defaultScoutConcurrency);
261
+ const scoutTimeoutMs = options.scoutTimeout
262
+ ? parseInt(options.scoutTimeout, 10) * 1000
263
+ : (autoConf.scoutTimeoutMs ?? activeProviderDefaults.defaultScoutTimeoutMs);
264
+ const maxScoutFiles = options.maxScoutFiles
265
+ ? parseInt(options.maxScoutFiles, 10)
266
+ : autoConf.maxFilesPerCycle;
267
+ // Dedup memory
268
+ const dedupMemory = loadDedupMemory(repoRoot);
269
+ if (dedupMemory.length > 0) {
270
+ console.log(chalk.gray(` Dedup memory loaded: ${dedupMemory.length} titles`));
271
+ }
272
+ // Codebase index
273
+ const excludeDirs = ['node_modules', 'dist', 'build', '.git', '.promptwheel', 'coverage', '__pycache__'];
274
+ let codebaseIndex = null;
275
+ try {
276
+ codebaseIndex = buildCodebaseIndex(repoRoot, excludeDirs, true);
277
+ console.log(chalk.gray(` Codebase index: ${codebaseIndex.modules.length} modules, ${codebaseIndex.untested_modules.length} untested, ${codebaseIndex.large_files.length} hotspots`));
278
+ }
279
+ catch {
280
+ // Non-fatal
281
+ }
282
+ // Project metadata
283
+ const projectMeta = detectProjectMetadata(repoRoot);
284
+ const metadataBlock = formatMetadataForPrompt(projectMeta);
285
+ if (projectMeta.languages.length > 0) {
286
+ console.log(chalk.gray(` Project: ${projectMeta.languages.join(', ')}${projectMeta.framework ? ` / ${projectMeta.framework}` : ''}${projectMeta.test_runner ? ` / ${projectMeta.test_runner.name}` : ''}`));
287
+ }
288
+ // Auto-prune
289
+ try {
290
+ const { pruneAllAsync: pruneAllAsyncFn, getRetentionConfig } = await import('./retention.js');
291
+ const retentionConfig = getRetentionConfig(config);
292
+ const pruneReport = await pruneAllAsyncFn(repoRoot, retentionConfig, adapter);
293
+ if (pruneReport.totalPruned > 0) {
294
+ console.log(chalk.gray(` Pruned ${pruneReport.totalPruned} stale item(s)`));
295
+ }
296
+ }
297
+ catch {
298
+ // Non-fatal
299
+ }
300
+ // Sectors
301
+ let sectorState = null;
302
+ if (codebaseIndex) {
303
+ try {
304
+ sectorState = loadOrBuildSectors(repoRoot, codebaseIndex.modules);
305
+ console.log(chalk.gray(` Sectors loaded: ${sectorState.sectors.length} sector(s)`));
306
+ }
307
+ catch {
308
+ // Non-fatal
309
+ }
310
+ }
311
+ // Taste profile
312
+ const tasteProfile = loadTasteProfile(repoRoot);
313
+ // Goals
314
+ const goals = loadGoals(repoRoot);
315
+ let activeGoal = null;
316
+ let activeGoalMeasurement = null;
317
+ if (goals.length > 0 && !options.formula) {
318
+ console.log(chalk.cyan(`🎯 Goals loaded: ${goals.length}`));
319
+ const measurements = measureGoals(goals, repoRoot);
320
+ for (const m of measurements) {
321
+ if (m.current !== null) {
322
+ const arrow = m.direction === 'up' ? '↑' : '↓';
323
+ const statusIcon = m.met ? '✓' : '○';
324
+ console.log(chalk.gray(` ${statusIcon} ${m.goalName}: ${m.current} ${arrow} ${m.target}${m.met ? ' (met)' : ` (gap: ${m.gapPercent}%)`}`));
325
+ }
326
+ else {
327
+ console.log(chalk.yellow(` ⚠ ${m.goalName}: measurement failed${m.error ? ` — ${m.error}` : ''}`));
328
+ }
329
+ recordGoalMeasurement(repoRoot, m);
330
+ }
331
+ const picked = pickGoalByGap(measurements);
332
+ if (picked) {
333
+ activeGoal = goals.find(g => g.name === picked.goalName) ?? null;
334
+ activeGoalMeasurement = picked;
335
+ console.log(chalk.cyan(` → Active goal: ${picked.goalName} (gap: ${picked.gapPercent}%)`));
336
+ }
337
+ else {
338
+ const allMet = measurements.every(m => m.met);
339
+ if (allMet) {
340
+ console.log(chalk.green(` ✓ All goals met!`));
341
+ }
342
+ }
343
+ console.log();
344
+ }
345
+ // Trajectories
346
+ let activeTrajectory = null;
347
+ let activeTrajectoryState = null;
348
+ let currentTrajectoryStep = null;
349
+ {
350
+ const trajState = loadTrajectoryState(repoRoot);
351
+ if (trajState && !trajState.paused) {
352
+ const traj = loadTrajectory(repoRoot, trajState.trajectoryName);
353
+ if (traj) {
354
+ activeTrajectory = traj;
355
+ activeTrajectoryState = trajState;
356
+ const nextStep = getTrajectoryNextStep(traj, trajState.stepStates);
357
+ if (nextStep) {
358
+ currentTrajectoryStep = nextStep;
359
+ activeTrajectoryState.currentStepId = nextStep.id;
360
+ const completed = traj.steps.filter(s => trajState.stepStates[s.id]?.status === 'completed').length;
361
+ console.log(chalk.cyan(`📐 Trajectory: ${traj.name} — step ${completed + 1}/${traj.steps.length}: ${nextStep.title}`));
362
+ }
363
+ else {
364
+ console.log(chalk.green(` ✓ Trajectory "${traj.name}" — all steps complete`));
365
+ activeTrajectory = null;
366
+ activeTrajectoryState = null;
367
+ }
368
+ }
369
+ }
370
+ }
371
+ return {
372
+ deepFormula, docsAuditFormula, guidelines, guidelinesOpts, guidelinesRefreshInterval,
373
+ allLearnings, dedupMemory, codebaseIndex, excludeDirs, metadataBlock,
374
+ sectorState, tasteProfile, goals, activeGoal, activeGoalMeasurement,
375
+ activeTrajectory, activeTrajectoryState, currentTrajectoryStep,
376
+ batchTokenBudget, scoutConcurrency, scoutTimeoutMs, maxScoutFiles, activeBackendName,
377
+ };
378
+ }
379
+ /** Initialize external dependencies: project, scout deps, backends, base branch. */
380
+ async function initDependencies(options, repoRoot, autoConf, adapter) {
381
+ const project = await projects.ensureForRepo(adapter, {
382
+ name: path.basename(repoRoot),
383
+ rootPath: repoRoot,
384
+ });
385
+ const deps = createScoutDeps(adapter, { verbose: options.verbose });
386
+ const { getProvider } = await import('./providers/index.js');
387
+ let scoutBackend;
388
+ let executionBackend;
389
+ const scoutBackendName = options.scoutBackend ?? 'claude';
390
+ const execBackendName = options.executeBackend ?? 'claude';
391
+ const modelForBackend = (name) => {
392
+ if (name === 'codex')
393
+ return options.codexModel;
394
+ if (name === 'kimi')
395
+ return options.kimiModel;
396
+ if (name === 'openai-local')
397
+ return options.localModel;
398
+ return undefined;
399
+ };
400
+ const apiKeyForBackend = (name) => {
401
+ const provider = getProvider(name);
402
+ return provider.apiKeyEnvVar ? process.env[provider.apiKeyEnvVar] : undefined;
403
+ };
404
+ if (scoutBackendName !== 'claude') {
405
+ if (scoutBackendName === 'codex' && options.codexMcp) {
406
+ const { CodexMcpScoutBackend } = await import('@promptwheel/core/scout');
407
+ scoutBackend = new CodexMcpScoutBackend({ apiKey: process.env.OPENAI_API_KEY, model: options.codexModel });
408
+ console.log(chalk.cyan(' Scout: Codex MCP (persistent session)'));
409
+ }
410
+ else {
411
+ const scoutProvider = getProvider(scoutBackendName);
412
+ scoutBackend = await scoutProvider.createScoutBackend({
413
+ apiKey: apiKeyForBackend(scoutBackendName),
414
+ model: modelForBackend(scoutBackendName),
415
+ baseUrl: scoutBackendName === 'openai-local' ? options.localUrl : undefined,
416
+ });
417
+ }
418
+ }
419
+ if (execBackendName !== 'claude') {
420
+ const execProvider = getProvider(execBackendName);
421
+ executionBackend = await execProvider.createExecutionBackend({
422
+ apiKey: apiKeyForBackend(execBackendName),
423
+ model: modelForBackend(execBackendName),
424
+ unsafeBypassSandbox: options.codexUnsafeFullAccess,
425
+ baseUrl: execBackendName === 'openai-local' ? options.localUrl : undefined,
426
+ maxIterations: options.localMaxIterations ? parseInt(options.localMaxIterations, 10) : undefined,
427
+ });
428
+ if (!autoConf.timeoutMultiplier) {
429
+ autoConf.timeoutMultiplier = 1.5;
430
+ }
431
+ }
432
+ // Detect base branch
433
+ let detectedBaseBranch = 'master';
434
+ try {
435
+ const { gitExec } = await import('./solo-git.js');
436
+ const remoteHead = (await gitExec('git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null || echo "refs/remotes/origin/master"', { cwd: repoRoot })).trim();
437
+ detectedBaseBranch = remoteHead.replace('refs/remotes/origin/', '');
438
+ }
439
+ catch {
440
+ // Fall back to master
441
+ }
442
+ return { project, deps, scoutBackend, executionBackend, detectedBaseBranch };
443
+ }
444
+ /** Initialize milestone or direct branches. */
445
+ async function initBranches(options, resolved, deliveryMode, directBranch, repoRoot, detectedBaseBranch) {
446
+ let milestoneBranch;
447
+ let milestoneWorktreePath;
448
+ let milestoneNumber = 0;
449
+ if (!options.dryRun) {
450
+ if (resolved.milestoneMode) {
451
+ const ms = await createMilestoneBranch(repoRoot, detectedBaseBranch);
452
+ milestoneBranch = ms.milestoneBranch;
453
+ milestoneWorktreePath = ms.milestoneWorktreePath;
454
+ milestoneNumber = 1;
455
+ console.log(chalk.cyan(`Milestone branch: ${milestoneBranch}`));
456
+ console.log();
457
+ }
458
+ else if (deliveryMode === 'direct') {
459
+ const cleaned = await cleanupMergedDirectBranch(repoRoot, directBranch);
460
+ if (cleaned)
461
+ console.log(chalk.gray(` Cleaned up merged direct branch: ${directBranch}`));
462
+ await ensureDirectBranch(repoRoot, directBranch, detectedBaseBranch);
463
+ console.log(chalk.cyan(`Direct branch: ${directBranch}`));
464
+ console.log();
465
+ }
466
+ }
467
+ return { milestoneBranch, milestoneWorktreePath, milestoneNumber };
468
+ }
469
+ /** Print the session header to console. */
470
+ function printSessionHeader(resolved, deliveryMode, directBranch, directFinalize, autoConf, cachedQaBaseline, getCycleFormula, getCycleCategories) {
471
+ const { runMode, totalMinutes, endTime, userScope, milestoneMode, batchSize, maxPrs, useDraft } = resolved;
472
+ const initialCategories = getCycleCategories(getCycleFormula(1));
473
+ {
474
+ console.log(chalk.blue(`🧵 PromptWheel Auto v${CLI_VERSION}`));
475
+ console.log();
476
+ if (runMode === 'wheel') {
477
+ console.log(chalk.gray(' Mode: Wheel (Ctrl+C to stop gracefully)'));
478
+ if (totalMinutes) {
479
+ const endDate = new Date(endTime);
480
+ const budgetLabel = totalMinutes < 60
481
+ ? `${Math.round(totalMinutes)} minutes`
482
+ : totalMinutes % 60 === 0
483
+ ? `${totalMinutes / 60} hours`
484
+ : `${Math.floor(totalMinutes / 60)}h ${Math.round(totalMinutes % 60)}m`;
485
+ console.log(chalk.gray(` Time budget: ${budgetLabel} (until ${endDate.toLocaleTimeString()})`));
486
+ if ((totalMinutes ?? 0) >= 360) {
487
+ console.log(chalk.gray(` Tip: For always-on improvement, try: promptwheel solo daemon start`));
488
+ }
489
+ }
490
+ }
491
+ else {
492
+ console.log(chalk.gray(' Mode: Planning (scout all → roadmap → approve → execute)'));
493
+ }
494
+ }
495
+ console.log(chalk.gray(` Scope: ${userScope || (runMode === 'wheel' ? 'rotating' : 'all sectors')}`));
496
+ const catDisplay = initialCategories.allow.join(', ');
497
+ const baselineFailCount = cachedQaBaseline
498
+ ? [...cachedQaBaseline.values()].filter(v => !v).length
499
+ : 0;
500
+ if (baselineFailCount > 0 && !initialCategories.allow.includes('fix')) {
501
+ console.log(chalk.gray(` Categories: ${catDisplay} (+fix for baseline healing)`));
502
+ }
503
+ else {
504
+ console.log(chalk.gray(` Categories: ${catDisplay}`));
505
+ }
506
+ {
507
+ const finalizeLabel = directFinalize === 'none' ? 'no PR' : directFinalize;
508
+ console.log(chalk.gray(` Delivery: ${deliveryMode}${deliveryMode === 'direct' ? ` (branch: ${directBranch}, finalize: ${finalizeLabel})` : ''}`));
509
+ }
510
+ if (milestoneMode) {
511
+ console.log(chalk.gray(` Milestone mode: batch size ${batchSize}, max PRs ${maxPrs}`));
512
+ console.log(chalk.gray(` Draft PRs: ${useDraft ? 'yes' : 'no'}`));
513
+ }
514
+ else if (deliveryMode === 'pr' || deliveryMode === 'auto-merge') {
515
+ console.log(chalk.gray(` Max PRs: ${maxPrs}`));
516
+ }
517
+ console.log();
518
+ }
519
+ /**
520
+ * Patch closures on state that need a back-reference to the state object.
521
+ * Called after the state object is constructed.
522
+ */
523
+ function patchStateClosures(state, shutdownRef) {
524
+ // Redirect shutdown handler to read/write state flags directly.
525
+ Object.assign(shutdownRef, { shutdownRequested: state.shutdownRequested, currentlyProcessing: state.currentlyProcessing });
526
+ // Reassigning shutdownRef won't work here (local binding), so the caller
527
+ // passes the original object and we need to redirect at the call site.
528
+ // Instead, the caller will do: shutdownRef = state; after this call.
529
+ // Patch formula helpers to read from state
530
+ const stateFormulaCtx = () => ({
531
+ activeFormula: state.activeFormula,
532
+ sessionPhase: state.sessionPhase,
533
+ deepFormula: state.deepFormula,
534
+ docsAuditFormula: state.docsAuditFormula,
535
+ isContinuous: state.runMode === 'wheel',
536
+ repoRoot: state.repoRoot,
537
+ options: state.options,
538
+ config: state.config,
539
+ sectorProductionFileCount: state.currentSectorId
540
+ ? state.sectorState?.sectors.find(s => s.path === state.currentSectorId)?.productionFileCount
541
+ : undefined,
542
+ });
543
+ state.getCycleFormula = (cycle) => {
544
+ if (state.activeGoal && !state.options.formula) {
545
+ return state.activeGoal;
546
+ }
547
+ return getCycleFormulaImpl(stateFormulaCtx(), cycle);
548
+ };
549
+ state.getCycleCategories = (formula) => getCycleCategoriesImpl(stateFormulaCtx(), formula);
550
+ // Milestone helpers
551
+ state.finalizeMilestone = async () => {
552
+ if (!state.milestoneMode || !state.milestoneBranch || !state.milestoneWorktreePath)
553
+ return;
554
+ if (state.milestoneTicketCount === 0)
555
+ return;
556
+ console.log(chalk.cyan(`\nFinalizing milestone #${state.milestoneNumber} (${state.milestoneTicketCount} tickets)...`));
557
+ const prUrl = await pushAndPrMilestone(state.repoRoot, state.milestoneBranch, state.milestoneWorktreePath, state.milestoneNumber, state.milestoneTicketCount, [...state.milestoneTicketSummaries]);
558
+ if (prUrl) {
559
+ state.allPrUrls.push(prUrl);
560
+ console.log(chalk.green(` ✓ Milestone PR: ${prUrl}`));
561
+ }
562
+ else {
563
+ console.log(chalk.yellow(` ⚠ Milestone pushed but PR creation failed`));
564
+ }
565
+ state.totalMilestonePrs++;
566
+ };
567
+ state.startNewMilestone = async () => {
568
+ if (!state.milestoneMode)
569
+ return;
570
+ await cleanupMilestone(state.repoRoot);
571
+ state.milestoneTicketCount = 0;
572
+ state.milestoneTicketSummaries.length = 0;
573
+ const ms = await createMilestoneBranch(state.repoRoot, state.detectedBaseBranch);
574
+ state.milestoneBranch = ms.milestoneBranch;
575
+ state.milestoneWorktreePath = ms.milestoneWorktreePath;
576
+ state.milestoneNumber++;
577
+ console.log(chalk.cyan(`New milestone branch: ${state.milestoneBranch}`));
578
+ };
579
+ }
580
+ /** Start the interactive console (wheel mode only, not in daemon mode). */
581
+ function initInteractiveConsole(state) {
582
+ if (state.runMode !== 'wheel' || state.options.daemon)
583
+ return;
584
+ state.interactiveConsole = startInteractiveConsole({
585
+ repoRoot: state.repoRoot,
586
+ onQuit: () => {
587
+ state.shutdownRequested = true;
588
+ },
589
+ onStatus: () => {
590
+ const elapsed = Math.floor((Date.now() - state.startTime) / 1000);
591
+ const mins = Math.floor(elapsed / 60);
592
+ const secs = elapsed % 60;
593
+ console.log(chalk.cyan('\n 📊 Session Status:'));
594
+ console.log(chalk.gray(` Cycle: ${state.cycleCount}`));
595
+ console.log(chalk.gray(` Elapsed: ${mins}m ${secs}s`));
596
+ if (state.milestoneMode) {
597
+ console.log(chalk.gray(` Tickets this milestone: ${state.milestoneTicketCount}`));
598
+ console.log(chalk.gray(` Milestone PRs: ${state.totalMilestonePrs}/${state.maxPrs}`));
599
+ }
600
+ else if (state.deliveryMode === 'direct') {
601
+ console.log(chalk.gray(` Completed tickets: ${state.completedDirectTickets.length}`));
602
+ }
603
+ else {
604
+ console.log(chalk.gray(` PRs created: ${state.totalPrsCreated}/${state.maxPrs}`));
605
+ }
606
+ console.log(chalk.gray(` Failed: ${state.totalFailed}`));
607
+ if (state.endTime) {
608
+ const remaining = Math.max(0, Math.floor((state.endTime - Date.now()) / 60000));
609
+ console.log(chalk.gray(` Time remaining: ${remaining}m`));
610
+ }
611
+ console.log();
612
+ },
613
+ });
614
+ }
615
+ // ── Init ────────────────────────────────────────────────────────────────────
616
+ export async function initSession(options) {
617
+ const resolved = await resolveOptions(options);
618
+ const env = await initEnvironment(options, resolved);
619
+ const { repoRoot, config, autoConf, cachedQaBaseline, adapter } = env;
620
+ const sessionData = await loadSessionData(options, resolved, repoRoot, config, autoConf, cachedQaBaseline, adapter);
621
+ const depsResult = await initDependencies(options, repoRoot, autoConf, adapter);
622
+ // Shutdown handler — mutable reference that gets redirected to state after construction
623
+ let shutdownRef = {
624
+ shutdownRequested: false,
625
+ currentlyProcessing: false,
626
+ };
627
+ const shutdownHandler = () => {
628
+ if (shutdownRef.shutdownRequested) {
629
+ console.log(chalk.red('\nForce quit. Exiting immediately.'));
630
+ process.exit(1);
631
+ }
632
+ shutdownRef.shutdownRequested = true;
633
+ if (shutdownRef.currentlyProcessing) {
634
+ console.log(chalk.yellow('\nShutdown requested. Finishing current ticket then finalizing...'));
635
+ }
636
+ else {
637
+ console.log(chalk.yellow('\nShutdown requested. Finalizing session...'));
638
+ }
639
+ };
640
+ // In daemon mode, the daemon loop handles signals itself
641
+ if (!options.daemon) {
642
+ process.on('SIGINT', shutdownHandler);
643
+ process.on('SIGTERM', shutdownHandler);
644
+ }
645
+ // Temporary formula helpers for header printing (before state exists)
646
+ const sessionPhase = 'deep';
647
+ const tmpFormulaCtx = () => ({
648
+ activeFormula: resolved.activeFormula,
649
+ sessionPhase,
650
+ deepFormula: sessionData.deepFormula,
651
+ docsAuditFormula: sessionData.docsAuditFormula,
652
+ isContinuous: resolved.runMode === 'wheel',
653
+ repoRoot,
654
+ options,
655
+ config,
656
+ sectorProductionFileCount: undefined,
657
+ });
658
+ const tmpGetCycleFormula = (cycle) => getCycleFormulaImpl(tmpFormulaCtx(), cycle);
659
+ const tmpGetCycleCategories = (formula) => getCycleCategoriesImpl(tmpFormulaCtx(), formula);
660
+ // Delivery mode — need autoConf for defaults
661
+ const deliveryMode = options.deliveryMode ?? autoConf.deliveryMode ?? 'direct';
662
+ const directBranch = options.directBranch ?? autoConf.directBranch ?? 'promptwheel-direct';
663
+ const directFinalize = options.directFinalize ?? autoConf.directFinalize ?? 'merge';
664
+ printSessionHeader(resolved, deliveryMode, directBranch, directFinalize, autoConf, cachedQaBaseline, tmpGetCycleFormula, tmpGetCycleCategories);
665
+ const branches = await initBranches(options, resolved, deliveryMode, directBranch, repoRoot, depsResult.detectedBaseBranch);
666
+ // Display adapter
667
+ let displayAdapter;
668
+ if (options.daemon) {
669
+ displayAdapter = new LogDisplayAdapter();
670
+ }
671
+ else {
672
+ const useTui = options.tui !== false && process.stdout.isTTY;
673
+ displayAdapter = new SpinnerDisplayAdapter();
674
+ if (useTui) {
675
+ const { TuiDisplayAdapter } = await import('./display-adapter-tui.js');
676
+ displayAdapter = new TuiDisplayAdapter({
677
+ repoRoot,
678
+ onQuit: () => { shutdownRef.shutdownRequested = true; },
679
+ onStatus: () => {
680
+ // Will be patched after state is created
681
+ },
682
+ });
683
+ }
684
+ }
685
+ const pullInterval = config?.auto?.pullEveryNCycles ?? 5;
686
+ const pullPolicy = config?.auto?.pullPolicy ?? 'halt';
687
+ // Build state object
688
+ const state = {
689
+ options,
690
+ config,
691
+ autoConf,
692
+ repoRoot,
693
+ activeFormula: resolved.activeFormula,
694
+ deepFormula: sessionData.deepFormula,
695
+ docsAuditFormula: sessionData.docsAuditFormula,
696
+ currentFormulaName: 'default',
697
+ runMode: resolved.runMode,
698
+ totalMinutes: resolved.totalMinutes,
699
+ endTime: resolved.endTime,
700
+ startTime: Date.now(),
701
+ maxPrs: resolved.maxPrs,
702
+ maxCycles: resolved.maxCycles,
703
+ minConfidence: resolved.minConfidence,
704
+ useDraft: resolved.useDraft,
705
+ milestoneMode: resolved.milestoneMode,
706
+ batchSize: resolved.batchSize,
707
+ milestoneBranch: branches.milestoneBranch,
708
+ milestoneWorktreePath: branches.milestoneWorktreePath,
709
+ milestoneTicketCount: 0,
710
+ milestoneNumber: branches.milestoneNumber,
711
+ totalMilestonePrs: 0,
712
+ milestoneTicketSummaries: [],
713
+ deliveryMode,
714
+ directBranch,
715
+ directFinalize,
716
+ completedDirectTickets: [],
717
+ allTraceAnalyses: [],
718
+ totalPrsCreated: 0,
719
+ totalFailed: 0,
720
+ cycleCount: 0,
721
+ allPrUrls: [],
722
+ totalMergedPrs: 0,
723
+ totalClosedPrs: 0,
724
+ pendingPrUrls: [],
725
+ sectorState: sessionData.sectorState,
726
+ currentSectorId: null,
727
+ currentSectorCycle: 0,
728
+ sessionScannedSectors: new Set(),
729
+ effectiveMinConfidence: autoConf.minConfidence ?? 20,
730
+ consecutiveLowYieldCycles: 0,
731
+ sessionPhase,
732
+ allTicketOutcomes: [],
733
+ cycleOutcomes: [],
734
+ prMetaMap: new Map(),
735
+ guidelines: sessionData.guidelines,
736
+ guidelinesOpts: sessionData.guidelinesOpts,
737
+ guidelinesRefreshInterval: sessionData.guidelinesRefreshInterval,
738
+ allLearnings: sessionData.allLearnings,
739
+ dedupMemory: sessionData.dedupMemory,
740
+ codebaseIndex: sessionData.codebaseIndex,
741
+ excludeDirs: sessionData.excludeDirs,
742
+ metadataBlock: sessionData.metadataBlock,
743
+ tasteProfile: sessionData.tasteProfile,
744
+ goals: sessionData.goals,
745
+ activeGoal: sessionData.activeGoal,
746
+ activeGoalMeasurement: sessionData.activeGoalMeasurement,
747
+ activeTrajectory: sessionData.activeTrajectory,
748
+ activeTrajectoryState: sessionData.activeTrajectoryState,
749
+ currentTrajectoryStep: sessionData.currentTrajectoryStep,
750
+ qaBaseline: cachedQaBaseline,
751
+ batchTokenBudget: sessionData.batchTokenBudget,
752
+ scoutConcurrency: sessionData.scoutConcurrency,
753
+ scoutTimeoutMs: sessionData.scoutTimeoutMs,
754
+ maxScoutFiles: sessionData.maxScoutFiles,
755
+ activeBackendName: sessionData.activeBackendName,
756
+ scoutBackend: depsResult.scoutBackend,
757
+ executionBackend: depsResult.executionBackend,
758
+ adapter,
759
+ project: depsResult.project,
760
+ deps: depsResult.deps,
761
+ detectedBaseBranch: depsResult.detectedBaseBranch,
762
+ shutdownRequested: shutdownRef.shutdownRequested,
763
+ currentlyProcessing: false,
764
+ pullInterval,
765
+ pullPolicy,
766
+ cyclesSinceLastPull: 0,
767
+ scoutRetries: 0,
768
+ scoutedDirs: [],
769
+ parallelExplicit: resolved.parallelExplicit,
770
+ userScope: resolved.userScope,
771
+ interactiveConsole: undefined,
772
+ displayAdapter,
773
+ getCycleFormula: null,
774
+ getCycleCategories: null,
775
+ finalizeMilestone: null,
776
+ startNewMilestone: null,
777
+ };
778
+ // Redirect shutdown handler to state
779
+ shutdownRef = state;
780
+ // Patch closures that need state reference
781
+ patchStateClosures(state, shutdownRef);
782
+ // Start interactive console
783
+ initInteractiveConsole(state);
784
+ return state;
785
+ }
786
+ // ── Helpers ─────────────────────────────────────────────────────────────────
787
+ export function shouldContinue(state) {
788
+ if (state.shutdownRequested)
789
+ return false;
790
+ // PR limits only apply to PR-based workflows, not direct mode
791
+ if (state.milestoneMode) {
792
+ if (state.totalMilestonePrs >= state.maxPrs)
793
+ return false;
794
+ }
795
+ else if (state.deliveryMode === 'pr' || state.deliveryMode === 'auto-merge') {
796
+ if (state.totalPrsCreated >= state.maxPrs)
797
+ return false;
798
+ }
799
+ // Direct mode: no PR limit, just time/cycles
800
+ if (state.endTime && Date.now() >= state.endTime)
801
+ return false;
802
+ if (state.cycleCount >= state.maxCycles && state.runMode !== 'wheel')
803
+ return false;
804
+ return true;
805
+ }
806
+ /**
807
+ * Check if a sector has files modified since its last scan.
808
+ * Uses `git diff --name-only` against the sector's scope.
809
+ */
810
+ function sectorHasChanges(repoRoot, sector) {
811
+ if (sector.lastScannedAt === 0)
812
+ return true; // never scanned = always scan
813
+ try {
814
+ const sinceDate = new Date(sector.lastScannedAt).toISOString();
815
+ const result = spawnSync('git', ['log', '--since', sinceDate, '--name-only', '--pretty=format:', '--', `${sector.path}/**`], {
816
+ cwd: repoRoot,
817
+ encoding: 'utf-8',
818
+ timeout: 5000,
819
+ });
820
+ const changedFiles = (result.stdout ?? '').trim();
821
+ return changedFiles.length > 0;
822
+ }
823
+ catch {
824
+ return true; // on error, assume changes exist
825
+ }
826
+ }
827
+ export function getNextScope(state) {
828
+ if (state.userScope)
829
+ return state.userScope;
830
+ if (state.sectorState) {
831
+ const rs = readRunState(state.repoRoot);
832
+ state.currentSectorCycle = rs.totalCycles;
833
+ // Keep picking sectors until we find one with changes (or unscanned)
834
+ const tried = new Set();
835
+ while (tried.size < state.sectorState.sectors.length) {
836
+ const pick = pickNextSector(state.sectorState, state.currentSectorCycle);
837
+ if (!pick)
838
+ break;
839
+ if (tried.has(pick.sector.path))
840
+ break; // looped back
841
+ tried.add(pick.sector.path);
842
+ // Always scan each sector at least once per session; after that, only on changes
843
+ const scannedThisSession = state.sessionScannedSectors.has(pick.sector.path);
844
+ if (pick.sector.scanCount === 0 || !scannedThisSession || sectorHasChanges(state.repoRoot, pick.sector)) {
845
+ state.sessionScannedSectors.add(pick.sector.path);
846
+ state.currentSectorId = pick.sector.path;
847
+ return pick.scope;
848
+ }
849
+ // Mark as "just scanned" so pickNextSector moves to the next one
850
+ pick.sector.lastScannedCycle = state.currentSectorCycle;
851
+ }
852
+ // All sectors scanned and no changes detected
853
+ state.currentSectorId = null;
854
+ return null;
855
+ }
856
+ state.currentSectorId = null;
857
+ return '**';
858
+ }
859
+ //# sourceMappingURL=solo-auto-state.js.map