@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,22 @@
1
+ /**
2
+ * Spindle — Failure pattern detectors (command failures, QA ping-pong, file edits)
3
+ *
4
+ * Merged from command-failure.ts, qa-ping-pong.ts, and file-edits.ts.
5
+ * Core detection algorithms live in @promptwheel/core; this module
6
+ * re-exports them and adds CLI-specific state helpers.
7
+ */
8
+ import { shortHash, detectQaPingPong, detectCommandFailure, extractFilesFromDiff, getFileEditWarnings as _getFileEditWarnings, } from '@promptwheel/core/spindle/shared';
9
+ // Re-export shared detectors for consumers
10
+ export { shortHash, detectQaPingPong, detectCommandFailure, extractFilesFromDiff };
11
+ /** Get file edit frequency warnings from CLI SpindleState */
12
+ export function getFileEditWarnings(state, threshold = 3) {
13
+ return _getFileEditWarnings(state.fileEditCounts, threshold);
14
+ }
15
+ /** Record a failing command for spindle tracking */
16
+ export function recordCommandFailure(state, command, error) {
17
+ const sig = shortHash(`${command}::${error.slice(0, 200)}`);
18
+ state.failingCommandSignatures.push(sig);
19
+ if (state.failingCommandSignatures.length > 20)
20
+ state.failingCommandSignatures.shift();
21
+ }
22
+ //# sourceMappingURL=failure-patterns.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"failure-patterns.js","sourceRoot":"","sources":["../../../src/lib/spindle/failure-patterns.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EACL,SAAS,EACT,gBAAgB,EAChB,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,IAAI,oBAAoB,GAC5C,MAAM,kCAAkC,CAAC;AAE1C,2CAA2C;AAC3C,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,CAAC;AAEnF,6DAA6D;AAC7D,MAAM,UAAU,mBAAmB,CAAC,KAAmB,EAAE,YAAoB,CAAC;IAC5E,OAAO,oBAAoB,CAAC,KAAK,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;AAC/D,CAAC;AAED,oDAAoD;AACpD,MAAM,UAAU,oBAAoB,CAAC,KAAmB,EAAE,OAAe,EAAE,KAAa;IACtF,MAAM,GAAG,GAAG,SAAS,CAAC,GAAG,OAAO,KAAK,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IAC5D,KAAK,CAAC,wBAAwB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACzC,IAAI,KAAK,CAAC,wBAAwB,CAAC,MAAM,GAAG,EAAE;QAAE,KAAK,CAAC,wBAAwB,CAAC,KAAK,EAAE,CAAC;AACzF,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Spindle — Result formatting
3
+ */
4
+ import type { SpindleResult } from './types.js';
5
+ /**
6
+ * Format Spindle result for display
7
+ */
8
+ export declare function formatSpindleResult(result: SpindleResult): string;
9
+ //# sourceMappingURL=format.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../../src/lib/spindle/format.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAgCjE"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Spindle — Result formatting
3
+ */
4
+ /**
5
+ * Format Spindle result for display
6
+ */
7
+ export function formatSpindleResult(result) {
8
+ if (!result.shouldAbort && !result.shouldBlock) {
9
+ return 'No spindle loop detected';
10
+ }
11
+ const label = result.shouldBlock ? 'Spindle blocked (needs human)' : 'Spindle loop detected';
12
+ const parts = [`${label}: ${result.reason}`];
13
+ parts.push(`Confidence: ${(result.confidence * 100).toFixed(0)}%`);
14
+ if (result.diagnostics.estimatedTokens) {
15
+ parts.push(`Tokens: ~${result.diagnostics.estimatedTokens}`);
16
+ }
17
+ if (result.diagnostics.iterationsWithoutChange) {
18
+ parts.push(`Iterations without change: ${result.diagnostics.iterationsWithoutChange}`);
19
+ }
20
+ if (result.diagnostics.oscillationPattern) {
21
+ parts.push(`Pattern: ${result.diagnostics.oscillationPattern}`);
22
+ }
23
+ if (result.diagnostics.repeatedPatterns?.length) {
24
+ parts.push(`Repeated: ${result.diagnostics.repeatedPatterns.join(', ')}`);
25
+ }
26
+ if (result.diagnostics.pingPongPattern) {
27
+ parts.push(`Pattern: ${result.diagnostics.pingPongPattern}`);
28
+ }
29
+ if (result.diagnostics.commandSignature) {
30
+ parts.push(`Command signature: ${result.diagnostics.commandSignature}`);
31
+ }
32
+ if (result.diagnostics.fileEditWarnings?.length) {
33
+ parts.push(`File churn: ${result.diagnostics.fileEditWarnings.join(', ')}`);
34
+ }
35
+ return parts.join('\n');
36
+ }
37
+ //# sourceMappingURL=format.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format.js","sourceRoot":"","sources":["../../../src/lib/spindle/format.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAqB;IACvD,IAAI,CAAC,MAAM,CAAC,WAAW,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;QAC/C,OAAO,0BAA0B,CAAC;IACpC,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,+BAA+B,CAAC,CAAC,CAAC,uBAAuB,CAAC;IAC7F,MAAM,KAAK,GAAG,CAAC,GAAG,KAAK,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7C,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,UAAU,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAEnE,IAAI,MAAM,CAAC,WAAW,CAAC,eAAe,EAAE,CAAC;QACvC,KAAK,CAAC,IAAI,CAAC,YAAY,MAAM,CAAC,WAAW,CAAC,eAAe,EAAE,CAAC,CAAC;IAC/D,CAAC;IACD,IAAI,MAAM,CAAC,WAAW,CAAC,uBAAuB,EAAE,CAAC;QAC/C,KAAK,CAAC,IAAI,CAAC,8BAA8B,MAAM,CAAC,WAAW,CAAC,uBAAuB,EAAE,CAAC,CAAC;IACzF,CAAC;IACD,IAAI,MAAM,CAAC,WAAW,CAAC,kBAAkB,EAAE,CAAC;QAC1C,KAAK,CAAC,IAAI,CAAC,YAAY,MAAM,CAAC,WAAW,CAAC,kBAAkB,EAAE,CAAC,CAAC;IAClE,CAAC;IACD,IAAI,MAAM,CAAC,WAAW,CAAC,gBAAgB,EAAE,MAAM,EAAE,CAAC;QAChD,KAAK,CAAC,IAAI,CAAC,aAAa,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC5E,CAAC;IACD,IAAI,MAAM,CAAC,WAAW,CAAC,eAAe,EAAE,CAAC;QACvC,KAAK,CAAC,IAAI,CAAC,YAAY,MAAM,CAAC,WAAW,CAAC,eAAe,EAAE,CAAC,CAAC;IAC/D,CAAC;IACD,IAAI,MAAM,CAAC,WAAW,CAAC,gBAAgB,EAAE,CAAC;QACxC,KAAK,CAAC,IAAI,CAAC,sBAAsB,MAAM,CAAC,WAAW,CAAC,gBAAgB,EAAE,CAAC,CAAC;IAC1E,CAAC;IACD,IAAI,MAAM,CAAC,WAAW,CAAC,gBAAgB,EAAE,MAAM,EAAE,CAAC;QAChD,KAAK,CAAC,IAAI,CAAC,eAAe,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9E,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Spindle Loop Detection
3
+ *
4
+ * Monitors agent execution for unproductive patterns:
5
+ * - Oscillation: Similar diffs being applied and reverted
6
+ * - Spinning: High tool call rate without progress
7
+ * - Stalling: Verbose output without meaningful changes
8
+ * - Repetition: Same errors or phrases repeated
9
+ *
10
+ * Named "Spindle" after the spinning wheel component — when the spindle
11
+ * jams, it spins without producing thread.
12
+ */
13
+ export type { SpindleConfig, SpindleState, SpindleResult } from './types.js';
14
+ export { DEFAULT_SPINDLE_CONFIG, createSpindleState, estimateTokens } from './types.js';
15
+ export { computeSimilarity } from './similarity.js';
16
+ export { detectOscillation } from './oscillation.js';
17
+ export { detectRepetition } from './repetition.js';
18
+ export { detectQaPingPong, detectCommandFailure, recordCommandFailure, shortHash, extractFilesFromDiff, getFileEditWarnings } from './failure-patterns.js';
19
+ export { formatSpindleResult } from './format.js';
20
+ import type { SpindleConfig, SpindleState, SpindleResult } from './types.js';
21
+ /**
22
+ * Check if agent is in a Spindle loop
23
+ *
24
+ * Updates state in-place and returns detection result.
25
+ *
26
+ * @param state - Current Spindle state (will be mutated)
27
+ * @param latestOutput - Agent's latest output text
28
+ * @param latestDiff - Latest git diff (null if no changes)
29
+ * @param config - Spindle configuration
30
+ * @returns Detection result
31
+ */
32
+ export declare function checkSpindleLoop(state: SpindleState, latestOutput: string, latestDiff: string | null, config: SpindleConfig): SpindleResult;
33
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/spindle/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC7E,OAAO,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACxF,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,SAAS,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC3J,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAO7E;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,YAAY,EACnB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GAAG,IAAI,EACzB,MAAM,EAAE,aAAa,GACpB,aAAa,CAwMf"}
@@ -0,0 +1,231 @@
1
+ /**
2
+ * Spindle Loop Detection
3
+ *
4
+ * Monitors agent execution for unproductive patterns:
5
+ * - Oscillation: Similar diffs being applied and reverted
6
+ * - Spinning: High tool call rate without progress
7
+ * - Stalling: Verbose output without meaningful changes
8
+ * - Repetition: Same errors or phrases repeated
9
+ *
10
+ * Named "Spindle" after the spinning wheel component — when the spindle
11
+ * jams, it spins without producing thread.
12
+ */
13
+ export { DEFAULT_SPINDLE_CONFIG, createSpindleState, estimateTokens } from './types.js';
14
+ export { computeSimilarity } from './similarity.js';
15
+ export { detectOscillation } from './oscillation.js';
16
+ export { detectRepetition } from './repetition.js';
17
+ export { detectQaPingPong, detectCommandFailure, recordCommandFailure, shortHash, extractFilesFromDiff, getFileEditWarnings } from './failure-patterns.js';
18
+ export { formatSpindleResult } from './format.js';
19
+ import { estimateTokens } from './types.js';
20
+ import { detectOscillation } from './oscillation.js';
21
+ import { detectRepetition } from './repetition.js';
22
+ import { detectQaPingPong, detectCommandFailure, extractFilesFromDiff, getFileEditWarnings } from './failure-patterns.js';
23
+ import { metric } from '../metrics.js';
24
+ /**
25
+ * Check if agent is in a Spindle loop
26
+ *
27
+ * Updates state in-place and returns detection result.
28
+ *
29
+ * @param state - Current Spindle state (will be mutated)
30
+ * @param latestOutput - Agent's latest output text
31
+ * @param latestDiff - Latest git diff (null if no changes)
32
+ * @param config - Spindle configuration
33
+ * @returns Detection result
34
+ */
35
+ export function checkSpindleLoop(state, latestOutput, latestDiff, config) {
36
+ // If disabled, always pass
37
+ if (!config.enabled) {
38
+ return { shouldAbort: false, shouldBlock: false, confidence: 0, diagnostics: {} };
39
+ }
40
+ // Update state with latest data
41
+ const outputTokens = estimateTokens(latestOutput);
42
+ const diffTokens = estimateTokens(latestDiff ?? '');
43
+ state.estimatedTokens += outputTokens + diffTokens;
44
+ state.totalOutputChars += latestOutput.length;
45
+ state.totalChangeChars += (latestDiff ?? '').length;
46
+ // Store for pattern detection (keep last N)
47
+ state.outputs.push(latestOutput);
48
+ if (state.outputs.length > config.maxSimilarOutputs + 1) {
49
+ state.outputs.shift();
50
+ }
51
+ if (latestDiff) {
52
+ state.diffs.push(latestDiff);
53
+ if (state.diffs.length > 5) {
54
+ state.diffs.shift();
55
+ }
56
+ // Track per-file edit frequency
57
+ const editedFiles = extractFilesFromDiff(latestDiff);
58
+ for (const f of editedFiles) {
59
+ state.fileEditCounts[f] = (state.fileEditCounts[f] ?? 0) + 1;
60
+ }
61
+ // Cap file_edit_counts keys to prevent unbounded growth
62
+ const MAX_FILE_EDIT_KEYS = 200;
63
+ const editKeys = Object.keys(state.fileEditCounts);
64
+ if (editKeys.length > MAX_FILE_EDIT_KEYS) {
65
+ const sorted = Object.entries(state.fileEditCounts)
66
+ .sort((a, b) => b[1] - a[1])
67
+ .slice(0, MAX_FILE_EDIT_KEYS);
68
+ state.fileEditCounts = Object.fromEntries(sorted);
69
+ }
70
+ }
71
+ // Track iterations without changes
72
+ if (!latestDiff || latestDiff.trim() === '') {
73
+ state.iterationsSinceChange++;
74
+ }
75
+ else {
76
+ state.iterationsSinceChange = 0;
77
+ state.lastProgressAt = Date.now();
78
+ }
79
+ // Check 1: Token budget
80
+ if (state.estimatedTokens >= config.tokenBudgetAbort) {
81
+ return triggerSpindle({
82
+ shouldAbort: true,
83
+ shouldBlock: false,
84
+ reason: 'token_budget',
85
+ confidence: 1.0,
86
+ diagnostics: {
87
+ estimatedTokens: state.estimatedTokens,
88
+ },
89
+ });
90
+ }
91
+ // Token budget warning (don't abort, just warn)
92
+ if (state.estimatedTokens >= config.tokenBudgetWarning) {
93
+ const warning = `Approaching token budget: ~${state.estimatedTokens} tokens`;
94
+ if (!state.warnings.includes(warning)) {
95
+ state.warnings.push(warning);
96
+ }
97
+ }
98
+ // Check 2: Stalling (no changes for too many iterations)
99
+ if (state.iterationsSinceChange >= config.maxStallIterations) {
100
+ return triggerSpindle({
101
+ shouldAbort: true,
102
+ shouldBlock: false,
103
+ reason: 'stalling',
104
+ confidence: 0.9,
105
+ diagnostics: {
106
+ iterationsWithoutChange: state.iterationsSinceChange,
107
+ },
108
+ });
109
+ }
110
+ // Check 2b: Time-based stall (wall-clock)
111
+ if (config.maxStallMinutes > 0) {
112
+ const minutesSinceProgress = (Date.now() - state.lastProgressAt) / 60_000;
113
+ if (minutesSinceProgress >= config.maxStallMinutes) {
114
+ return triggerSpindle({
115
+ shouldAbort: true,
116
+ shouldBlock: false,
117
+ reason: 'time_stall',
118
+ confidence: 0.95,
119
+ diagnostics: {
120
+ minutesSinceProgress: Math.round(minutesSinceProgress),
121
+ maxStallMinutes: config.maxStallMinutes,
122
+ },
123
+ });
124
+ }
125
+ }
126
+ // Check 3: Oscillation in diffs
127
+ if (state.diffs.length >= 2) {
128
+ const oscillation = detectOscillation(state.diffs, config.similarityThreshold);
129
+ if (oscillation.detected) {
130
+ return triggerSpindle({
131
+ shouldAbort: true,
132
+ shouldBlock: false,
133
+ reason: 'oscillation',
134
+ confidence: oscillation.confidence,
135
+ diagnostics: {
136
+ oscillationPattern: oscillation.pattern,
137
+ },
138
+ });
139
+ }
140
+ }
141
+ // Check 4: Repetition in outputs
142
+ if (state.outputs.length >= 2) {
143
+ const repetition = detectRepetition(state.outputs.slice(0, -1), latestOutput, config);
144
+ if (repetition.detected) {
145
+ return triggerSpindle({
146
+ shouldAbort: true,
147
+ shouldBlock: false,
148
+ reason: 'repetition',
149
+ confidence: repetition.confidence,
150
+ diagnostics: {
151
+ repeatedPatterns: repetition.patterns,
152
+ similarityScore: repetition.confidence,
153
+ },
154
+ });
155
+ }
156
+ }
157
+ // Check 5: Verbosity ratio (lots of output, few changes)
158
+ if (state.totalOutputChars > 5000 && state.totalChangeChars > 0) {
159
+ const verbosityRatio = state.totalOutputChars / state.totalChangeChars;
160
+ if (verbosityRatio >= config.verbosityThreshold) {
161
+ // Only warn, don't abort on verbosity alone
162
+ const warning = `High verbosity ratio: ${verbosityRatio.toFixed(1)}x output vs changes`;
163
+ if (!state.warnings.includes(warning)) {
164
+ state.warnings.push(warning);
165
+ }
166
+ }
167
+ }
168
+ // Check 6: QA ping-pong — alternating failure signatures
169
+ if (state.failingCommandSignatures.length >= config.maxQaPingPong * 2) {
170
+ const pp = detectQaPingPong(state.failingCommandSignatures, config.maxQaPingPong);
171
+ if (pp) {
172
+ return triggerSpindle({
173
+ shouldAbort: true,
174
+ shouldBlock: false,
175
+ reason: 'qa_ping_pong',
176
+ confidence: 0.9,
177
+ diagnostics: { pingPongPattern: pp },
178
+ });
179
+ }
180
+ }
181
+ // Check 7: Command signature — same command fails N times → block (needs human)
182
+ const cmdFail = detectCommandFailure(state.failingCommandSignatures, config.maxCommandFailures);
183
+ if (cmdFail) {
184
+ return triggerSpindle({
185
+ shouldAbort: false,
186
+ shouldBlock: true,
187
+ reason: 'command_failure',
188
+ confidence: 0.8,
189
+ diagnostics: { commandSignature: cmdFail, commandFailureThreshold: config.maxCommandFailures },
190
+ });
191
+ }
192
+ // Check 8: File edit frequency warnings
193
+ const fileWarnings = getFileEditWarnings(state, config.maxFileEdits);
194
+ if (fileWarnings.length > 0) {
195
+ for (const w of fileWarnings) {
196
+ const warning = `File churn: ${w}`;
197
+ if (!state.warnings.includes(warning)) {
198
+ state.warnings.push(warning);
199
+ }
200
+ }
201
+ }
202
+ // No issues detected
203
+ // Instrument: track spindle check (no trigger)
204
+ metric('spindle', 'check_passed', {
205
+ tokens: state.estimatedTokens,
206
+ iterations: state.iterationsSinceChange,
207
+ });
208
+ return {
209
+ shouldAbort: false,
210
+ shouldBlock: false,
211
+ confidence: 0,
212
+ diagnostics: {
213
+ estimatedTokens: state.estimatedTokens,
214
+ iterationsWithoutChange: state.iterationsSinceChange,
215
+ ...(fileWarnings.length > 0 ? { fileEditWarnings: fileWarnings } : {}),
216
+ },
217
+ };
218
+ }
219
+ /**
220
+ * Helper to record spindle trigger and return result
221
+ */
222
+ function triggerSpindle(result) {
223
+ metric('spindle', 'triggered', {
224
+ reason: result.reason,
225
+ shouldAbort: result.shouldAbort,
226
+ shouldBlock: result.shouldBlock,
227
+ confidence: result.confidence,
228
+ });
229
+ return result;
230
+ }
231
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/spindle/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACxF,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,SAAS,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC3J,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAGlD,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC1H,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAEvC;;;;;;;;;;GAUG;AACH,MAAM,UAAU,gBAAgB,CAC9B,KAAmB,EACnB,YAAoB,EACpB,UAAyB,EACzB,MAAqB;IAErB,2BAA2B;IAC3B,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC;IACpF,CAAC;IAED,gCAAgC;IAChC,MAAM,YAAY,GAAG,cAAc,CAAC,YAAY,CAAC,CAAC;IAClD,MAAM,UAAU,GAAG,cAAc,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC;IAEpD,KAAK,CAAC,eAAe,IAAI,YAAY,GAAG,UAAU,CAAC;IACnD,KAAK,CAAC,gBAAgB,IAAI,YAAY,CAAC,MAAM,CAAC;IAC9C,KAAK,CAAC,gBAAgB,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;IAEpD,4CAA4C;IAC5C,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACjC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,iBAAiB,GAAG,CAAC,EAAE,CAAC;QACxD,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;IAED,IAAI,UAAU,EAAE,CAAC;QACf,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC7B,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACtB,CAAC;QAED,gCAAgC;QAChC,MAAM,WAAW,GAAG,oBAAoB,CAAC,UAAU,CAAC,CAAC;QACrD,KAAK,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC;YAC5B,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QAC/D,CAAC;QACD,wDAAwD;QACxD,MAAM,kBAAkB,GAAG,GAAG,CAAC;QAC/B,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QACnD,IAAI,QAAQ,CAAC,MAAM,GAAG,kBAAkB,EAAE,CAAC;YACzC,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC;iBAChD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;iBAC3B,KAAK,CAAC,CAAC,EAAE,kBAAkB,CAAC,CAAC;YAChC,KAAK,CAAC,cAAc,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;IAED,mCAAmC;IACnC,IAAI,CAAC,UAAU,IAAI,UAAU,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;QAC5C,KAAK,CAAC,qBAAqB,EAAE,CAAC;IAChC,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,qBAAqB,GAAG,CAAC,CAAC;QAChC,KAAK,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACpC,CAAC;IAED,wBAAwB;IACxB,IAAI,KAAK,CAAC,eAAe,IAAI,MAAM,CAAC,gBAAgB,EAAE,CAAC;QACrD,OAAO,cAAc,CAAC;YACpB,WAAW,EAAE,IAAI;YACjB,WAAW,EAAE,KAAK;YAClB,MAAM,EAAE,cAAc;YACtB,UAAU,EAAE,GAAG;YACf,WAAW,EAAE;gBACX,eAAe,EAAE,KAAK,CAAC,eAAe;aACvC;SACF,CAAC,CAAC;IACL,CAAC;IAED,gDAAgD;IAChD,IAAI,KAAK,CAAC,eAAe,IAAI,MAAM,CAAC,kBAAkB,EAAE,CAAC;QACvD,MAAM,OAAO,GAAG,8BAA8B,KAAK,CAAC,eAAe,SAAS,CAAC;QAC7E,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YACtC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,yDAAyD;IACzD,IAAI,KAAK,CAAC,qBAAqB,IAAI,MAAM,CAAC,kBAAkB,EAAE,CAAC;QAC7D,OAAO,cAAc,CAAC;YACpB,WAAW,EAAE,IAAI;YACjB,WAAW,EAAE,KAAK;YAClB,MAAM,EAAE,UAAU;YAClB,UAAU,EAAE,GAAG;YACf,WAAW,EAAE;gBACX,uBAAuB,EAAE,KAAK,CAAC,qBAAqB;aACrD;SACF,CAAC,CAAC;IACL,CAAC;IAED,0CAA0C;IAC1C,IAAI,MAAM,CAAC,eAAe,GAAG,CAAC,EAAE,CAAC;QAC/B,MAAM,oBAAoB,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,cAAc,CAAC,GAAG,MAAM,CAAC;QAC1E,IAAI,oBAAoB,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;YACnD,OAAO,cAAc,CAAC;gBACpB,WAAW,EAAE,IAAI;gBACjB,WAAW,EAAE,KAAK;gBAClB,MAAM,EAAE,YAAY;gBACpB,UAAU,EAAE,IAAI;gBAChB,WAAW,EAAE;oBACX,oBAAoB,EAAE,IAAI,CAAC,KAAK,CAAC,oBAAoB,CAAC;oBACtD,eAAe,EAAE,MAAM,CAAC,eAAe;iBACxC;aACF,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,gCAAgC;IAChC,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QAC5B,MAAM,WAAW,GAAG,iBAAiB,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,mBAAmB,CAAC,CAAC;QAC/E,IAAI,WAAW,CAAC,QAAQ,EAAE,CAAC;YACzB,OAAO,cAAc,CAAC;gBACpB,WAAW,EAAE,IAAI;gBACjB,WAAW,EAAE,KAAK;gBAClB,MAAM,EAAE,aAAa;gBACrB,UAAU,EAAE,WAAW,CAAC,UAAU;gBAClC,WAAW,EAAE;oBACX,kBAAkB,EAAE,WAAW,CAAC,OAAO;iBACxC;aACF,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,iCAAiC;IACjC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QAC9B,MAAM,UAAU,GAAG,gBAAgB,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC;QACtF,IAAI,UAAU,CAAC,QAAQ,EAAE,CAAC;YACxB,OAAO,cAAc,CAAC;gBACpB,WAAW,EAAE,IAAI;gBACjB,WAAW,EAAE,KAAK;gBAClB,MAAM,EAAE,YAAY;gBACpB,UAAU,EAAE,UAAU,CAAC,UAAU;gBACjC,WAAW,EAAE;oBACX,gBAAgB,EAAE,UAAU,CAAC,QAAQ;oBACrC,eAAe,EAAE,UAAU,CAAC,UAAU;iBACvC;aACF,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,yDAAyD;IACzD,IAAI,KAAK,CAAC,gBAAgB,GAAG,IAAI,IAAI,KAAK,CAAC,gBAAgB,GAAG,CAAC,EAAE,CAAC;QAChE,MAAM,cAAc,GAAG,KAAK,CAAC,gBAAgB,GAAG,KAAK,CAAC,gBAAgB,CAAC;QACvE,IAAI,cAAc,IAAI,MAAM,CAAC,kBAAkB,EAAE,CAAC;YAChD,4CAA4C;YAC5C,MAAM,OAAO,GAAG,yBAAyB,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,qBAAqB,CAAC;YACxF,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBACtC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC;IACH,CAAC;IAED,yDAAyD;IACzD,IAAI,KAAK,CAAC,wBAAwB,CAAC,MAAM,IAAI,MAAM,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC;QACtE,MAAM,EAAE,GAAG,gBAAgB,CAAC,KAAK,CAAC,wBAAwB,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC;QAClF,IAAI,EAAE,EAAE,CAAC;YACP,OAAO,cAAc,CAAC;gBACpB,WAAW,EAAE,IAAI;gBACjB,WAAW,EAAE,KAAK;gBAClB,MAAM,EAAE,cAAc;gBACtB,UAAU,EAAE,GAAG;gBACf,WAAW,EAAE,EAAE,eAAe,EAAE,EAAE,EAAE;aACrC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,gFAAgF;IAChF,MAAM,OAAO,GAAG,oBAAoB,CAAC,KAAK,CAAC,wBAAwB,EAAE,MAAM,CAAC,kBAAkB,CAAC,CAAC;IAChG,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,cAAc,CAAC;YACpB,WAAW,EAAE,KAAK;YAClB,WAAW,EAAE,IAAI;YACjB,MAAM,EAAE,iBAAiB;YACzB,UAAU,EAAE,GAAG;YACf,WAAW,EAAE,EAAE,gBAAgB,EAAE,OAAO,EAAE,uBAAuB,EAAE,MAAM,CAAC,kBAAkB,EAAE;SAC/F,CAAC,CAAC;IACL,CAAC;IAED,wCAAwC;IACxC,MAAM,YAAY,GAAG,mBAAmB,CAAC,KAAK,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC;IACrE,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,KAAK,MAAM,CAAC,IAAI,YAAY,EAAE,CAAC;YAC7B,MAAM,OAAO,GAAG,eAAe,CAAC,EAAE,CAAC;YACnC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBACtC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC;IACH,CAAC;IAED,qBAAqB;IACrB,+CAA+C;IAC/C,MAAM,CAAC,SAAS,EAAE,cAAc,EAAE;QAChC,MAAM,EAAE,KAAK,CAAC,eAAe;QAC7B,UAAU,EAAE,KAAK,CAAC,qBAAqB;KACxC,CAAC,CAAC;IAEH,OAAO;QACL,WAAW,EAAE,KAAK;QAClB,WAAW,EAAE,KAAK;QAClB,UAAU,EAAE,CAAC;QACb,WAAW,EAAE;YACX,eAAe,EAAE,KAAK,CAAC,eAAe;YACtC,uBAAuB,EAAE,KAAK,CAAC,qBAAqB;YACpD,GAAG,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,gBAAgB,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACvE;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,cAAc,CAAC,MAAqB;IAC3C,MAAM,CAAC,SAAS,EAAE,WAAW,EAAE;QAC7B,MAAM,EAAE,MAAM,CAAC,MAAM;QACrB,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,UAAU,EAAE,MAAM,CAAC,UAAU;KAC9B,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Spindle — Oscillation detection
3
+ */
4
+ /**
5
+ * Detect oscillation pattern in diffs
6
+ *
7
+ * Looks for add→remove→add or remove→add→remove patterns where similar
8
+ * content is being repeatedly changed back and forth.
9
+ *
10
+ * @returns Object with detected flag and pattern description
11
+ */
12
+ export declare function detectOscillation(diffs: string[], similarityThreshold?: number): {
13
+ detected: boolean;
14
+ pattern?: string;
15
+ confidence: number;
16
+ };
17
+ //# sourceMappingURL=oscillation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oscillation.d.ts","sourceRoot":"","sources":["../../../src/lib/spindle/oscillation.ts"],"names":[],"mappings":"AAAA;;GAEG;AA2BH;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,MAAM,EAAE,EACf,mBAAmB,GAAE,MAAY,GAChC;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAiE7D"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Spindle — Oscillation detection
3
+ */
4
+ import { computeSimilarity } from './similarity.js';
5
+ /**
6
+ * Extract added and removed lines from a unified diff
7
+ */
8
+ function extractDiffLines(diff) {
9
+ const lines = diff.split('\n');
10
+ const added = [];
11
+ const removed = [];
12
+ for (const line of lines) {
13
+ // Skip diff headers
14
+ if (line.startsWith('+++') || line.startsWith('---') || line.startsWith('@@')) {
15
+ continue;
16
+ }
17
+ if (line.startsWith('+')) {
18
+ added.push(line.slice(1).trim());
19
+ }
20
+ else if (line.startsWith('-')) {
21
+ removed.push(line.slice(1).trim());
22
+ }
23
+ }
24
+ return { added, removed };
25
+ }
26
+ /**
27
+ * Detect oscillation pattern in diffs
28
+ *
29
+ * Looks for add→remove→add or remove→add→remove patterns where similar
30
+ * content is being repeatedly changed back and forth.
31
+ *
32
+ * @returns Object with detected flag and pattern description
33
+ */
34
+ export function detectOscillation(diffs, similarityThreshold = 0.8) {
35
+ if (diffs.length < 2) {
36
+ return { detected: false, confidence: 0 };
37
+ }
38
+ // Analyze last 3 diffs (or 2 if only 2 available)
39
+ const recentDiffs = diffs.slice(-3);
40
+ const patterns = recentDiffs.map(d => extractDiffLines(d));
41
+ // With 2 diffs: check if what was added is now removed (or vice versa)
42
+ if (patterns.length >= 2) {
43
+ const [prev, curr] = patterns.slice(-2);
44
+ // Check: lines added in prev are now removed in curr
45
+ for (const addedLine of prev.added) {
46
+ if (addedLine.length < 3)
47
+ continue; // Skip trivial lines
48
+ for (const removedLine of curr.removed) {
49
+ const sim = computeSimilarity(addedLine, removedLine);
50
+ if (sim >= similarityThreshold) {
51
+ return {
52
+ detected: true,
53
+ pattern: `Added then removed: "${addedLine.slice(0, 50)}..."`,
54
+ confidence: sim,
55
+ };
56
+ }
57
+ }
58
+ }
59
+ // Check: lines removed in prev are now added in curr
60
+ for (const removedLine of prev.removed) {
61
+ if (removedLine.length < 3)
62
+ continue;
63
+ for (const addedLine of curr.added) {
64
+ const sim = computeSimilarity(removedLine, addedLine);
65
+ if (sim >= similarityThreshold) {
66
+ return {
67
+ detected: true,
68
+ pattern: `Removed then re-added: "${removedLine.slice(0, 50)}..."`,
69
+ confidence: sim,
70
+ };
71
+ }
72
+ }
73
+ }
74
+ }
75
+ // With 3 diffs: check for A→B→A pattern
76
+ if (patterns.length === 3) {
77
+ const [first, , third] = patterns;
78
+ // Check if first additions match third additions (came back to same state)
79
+ for (const line1 of first.added) {
80
+ if (line1.length < 3)
81
+ continue;
82
+ for (const line3 of third.added) {
83
+ const sim = computeSimilarity(line1, line3);
84
+ if (sim >= similarityThreshold) {
85
+ return {
86
+ detected: true,
87
+ pattern: `Oscillating: same content added in iterations 1 and 3`,
88
+ confidence: sim,
89
+ };
90
+ }
91
+ }
92
+ }
93
+ }
94
+ return { detected: false, confidence: 0 };
95
+ }
96
+ //# sourceMappingURL=oscillation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oscillation.js","sourceRoot":"","sources":["../../../src/lib/spindle/oscillation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Spindle — Repetition detection
3
+ */
4
+ import type { SpindleConfig } from './types.js';
5
+ /**
6
+ * Detect repetition in agent outputs
7
+ *
8
+ * Looks for consecutive similar outputs that indicate the agent is stuck
9
+ * in a loop saying the same things.
10
+ */
11
+ export declare function detectRepetition(outputs: string[], latestOutput: string, config: SpindleConfig): {
12
+ detected: boolean;
13
+ patterns: string[];
14
+ confidence: number;
15
+ };
16
+ //# sourceMappingURL=repetition.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repetition.d.ts","sourceRoot":"","sources":["../../../src/lib/spindle/repetition.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EAAE,EACjB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,aAAa,GACpB;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CA+C/D"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Spindle — Repetition detection
3
+ */
4
+ import { computeSimilarity, findRepeatedPhrases } from './similarity.js';
5
+ /**
6
+ * Detect repetition in agent outputs
7
+ *
8
+ * Looks for consecutive similar outputs that indicate the agent is stuck
9
+ * in a loop saying the same things.
10
+ */
11
+ export function detectRepetition(outputs, latestOutput, config) {
12
+ const patterns = [];
13
+ let maxSimilarity = 0;
14
+ // Compare latest output with recent outputs
15
+ for (const prevOutput of outputs.slice(-config.maxSimilarOutputs)) {
16
+ const sim = computeSimilarity(latestOutput, prevOutput);
17
+ if (sim >= config.similarityThreshold) {
18
+ maxSimilarity = Math.max(maxSimilarity, sim);
19
+ // Extract repeated phrases
20
+ const phrases = findRepeatedPhrases(latestOutput, prevOutput);
21
+ patterns.push(...phrases);
22
+ }
23
+ }
24
+ // Check for common "stuck" phrases
25
+ const stuckPhrases = [
26
+ 'let me try',
27
+ 'i apologize',
28
+ "i'll try again",
29
+ 'let me attempt',
30
+ 'trying again',
31
+ 'one more time',
32
+ 'another approach',
33
+ ];
34
+ const lowerOutput = latestOutput.toLowerCase();
35
+ for (const phrase of stuckPhrases) {
36
+ if (lowerOutput.includes(phrase)) {
37
+ const occurrences = outputs.filter(o => o.toLowerCase().includes(phrase)).length;
38
+ if (occurrences >= 2) {
39
+ patterns.push(`Repeated phrase: "${phrase}" (${occurrences + 1} times)`);
40
+ // Set high similarity since stuck phrases are a strong signal
41
+ maxSimilarity = Math.max(maxSimilarity, 0.85);
42
+ }
43
+ }
44
+ }
45
+ const detected = patterns.length > 0 && maxSimilarity >= config.similarityThreshold;
46
+ return {
47
+ detected,
48
+ patterns: [...new Set(patterns)].slice(0, 5), // Dedupe and limit
49
+ confidence: maxSimilarity,
50
+ };
51
+ }
52
+ //# sourceMappingURL=repetition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repetition.js","sourceRoot":"","sources":["../../../src/lib/spindle/repetition.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAGzE;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAC9B,OAAiB,EACjB,YAAoB,EACpB,MAAqB;IAErB,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,aAAa,GAAG,CAAC,CAAC;IAEtB,4CAA4C;IAC5C,KAAK,MAAM,UAAU,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC,EAAE,CAAC;QAClE,MAAM,GAAG,GAAG,iBAAiB,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;QACxD,IAAI,GAAG,IAAI,MAAM,CAAC,mBAAmB,EAAE,CAAC;YACtC,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;YAE7C,2BAA2B;YAC3B,MAAM,OAAO,GAAG,mBAAmB,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;YAC9D,QAAQ,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,mCAAmC;IACnC,MAAM,YAAY,GAAG;QACnB,YAAY;QACZ,aAAa;QACb,gBAAgB;QAChB,gBAAgB;QAChB,cAAc;QACd,eAAe;QACf,kBAAkB;KACnB,CAAC;IAEF,MAAM,WAAW,GAAG,YAAY,CAAC,WAAW,EAAE,CAAC;IAC/C,KAAK,MAAM,MAAM,IAAI,YAAY,EAAE,CAAC;QAClC,IAAI,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACjC,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CACrC,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CACjC,CAAC,MAAM,CAAC;YACT,IAAI,WAAW,IAAI,CAAC,EAAE,CAAC;gBACrB,QAAQ,CAAC,IAAI,CAAC,qBAAqB,MAAM,MAAM,WAAW,GAAG,CAAC,SAAS,CAAC,CAAC;gBACzE,8DAA8D;gBAC9D,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;YAChD,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,aAAa,IAAI,MAAM,CAAC,mBAAmB,CAAC;IACpF,OAAO;QACL,QAAQ;QACR,QAAQ,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,mBAAmB;QACjE,UAAU,EAAE,aAAa;KAC1B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Spindle — Similarity computation
3
+ */
4
+ /**
5
+ * Compute similarity between two strings using Jaccard index on word tokens
6
+ *
7
+ * @returns Similarity score from 0 (completely different) to 1 (identical)
8
+ */
9
+ export declare function computeSimilarity(a: string, b: string): number;
10
+ /**
11
+ * Find repeated phrases between two texts
12
+ */
13
+ export declare function findRepeatedPhrases(a: string, b: string, maxResults?: number): string[];
14
+ //# sourceMappingURL=similarity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"similarity.d.ts","sourceRoot":"","sources":["../../../src/lib/spindle/similarity.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CA6B9D;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,UAAU,GAAE,MAAU,GAAG,MAAM,EAAE,CAkB1F"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Spindle — Similarity computation
3
+ */
4
+ /**
5
+ * Compute similarity between two strings using Jaccard index on word tokens
6
+ *
7
+ * @returns Similarity score from 0 (completely different) to 1 (identical)
8
+ */
9
+ export function computeSimilarity(a, b) {
10
+ if (!a && !b)
11
+ return 1;
12
+ if (!a || !b)
13
+ return 0;
14
+ // Tokenize on whitespace and punctuation, lowercase
15
+ const tokenize = (s) => {
16
+ const tokens = s
17
+ .toLowerCase()
18
+ .split(/[\s.,;:!?\-()[\]{}"']+/)
19
+ .filter(t => t.length > 0);
20
+ return new Set(tokens);
21
+ };
22
+ const tokensA = tokenize(a);
23
+ const tokensB = tokenize(b);
24
+ if (tokensA.size === 0 && tokensB.size === 0)
25
+ return 1;
26
+ if (tokensA.size === 0 || tokensB.size === 0)
27
+ return 0;
28
+ // Jaccard index: |intersection| / |union|
29
+ let intersectionSize = 0;
30
+ for (const token of tokensA) {
31
+ if (tokensB.has(token)) {
32
+ intersectionSize++;
33
+ }
34
+ }
35
+ const unionSize = tokensA.size + tokensB.size - intersectionSize;
36
+ return intersectionSize / unionSize;
37
+ }
38
+ /**
39
+ * Find repeated phrases between two texts
40
+ */
41
+ export function findRepeatedPhrases(a, b, maxResults = 5) {
42
+ const phrases = [];
43
+ // Split into sentences/fragments
44
+ const fragmentsA = a.split(/[.!?\n]+/).filter(f => f.trim().length > 20);
45
+ const fragmentsB = b.split(/[.!?\n]+/).filter(f => f.trim().length > 20);
46
+ for (const fragA of fragmentsA) {
47
+ for (const fragB of fragmentsB) {
48
+ const sim = computeSimilarity(fragA, fragB);
49
+ if (sim >= 0.9) {
50
+ phrases.push(fragA.trim().slice(0, 60) + '...');
51
+ if (phrases.length >= maxResults)
52
+ return phrases;
53
+ }
54
+ }
55
+ }
56
+ return phrases;
57
+ }
58
+ //# sourceMappingURL=similarity.js.map