@slope-dev/slope 1.64.0 → 2.0.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 (461) hide show
  1. package/README.md +4 -0
  2. package/dist/cli/commands/agent.d.ts +3 -3
  3. package/dist/cli/commands/agent.d.ts.map +1 -1
  4. package/dist/cli/commands/agent.js +20 -12
  5. package/dist/cli/commands/agent.js.map +1 -1
  6. package/dist/cli/commands/auto-card.d.ts +2 -1
  7. package/dist/cli/commands/auto-card.d.ts.map +1 -1
  8. package/dist/cli/commands/auto-card.js +7 -7
  9. package/dist/cli/commands/auto-card.js.map +1 -1
  10. package/dist/cli/commands/briefing.d.ts.map +1 -1
  11. package/dist/cli/commands/briefing.js +16 -9
  12. package/dist/cli/commands/briefing.js.map +1 -1
  13. package/dist/cli/commands/claim.d.ts.map +1 -1
  14. package/dist/cli/commands/claim.js +6 -4
  15. package/dist/cli/commands/claim.js.map +1 -1
  16. package/dist/cli/commands/commit-ready.d.ts.map +1 -1
  17. package/dist/cli/commands/commit-ready.js.map +1 -1
  18. package/dist/cli/commands/context.d.ts.map +1 -1
  19. package/dist/cli/commands/context.js +2 -1
  20. package/dist/cli/commands/context.js.map +1 -1
  21. package/dist/cli/commands/dashboard.d.ts.map +1 -1
  22. package/dist/cli/commands/dashboard.js +3 -3
  23. package/dist/cli/commands/dashboard.js.map +1 -1
  24. package/dist/cli/commands/distill.d.ts.map +1 -1
  25. package/dist/cli/commands/distill.js +8 -20
  26. package/dist/cli/commands/distill.js.map +1 -1
  27. package/dist/cli/commands/enrich.d.ts.map +1 -1
  28. package/dist/cli/commands/enrich.js +2 -1
  29. package/dist/cli/commands/enrich.js.map +1 -1
  30. package/dist/cli/commands/escalate.d.ts.map +1 -1
  31. package/dist/cli/commands/escalate.js +11 -3
  32. package/dist/cli/commands/escalate.js.map +1 -1
  33. package/dist/cli/commands/extract.d.ts.map +1 -1
  34. package/dist/cli/commands/extract.js +20 -6
  35. package/dist/cli/commands/extract.js.map +1 -1
  36. package/dist/cli/commands/gate.d.ts.map +1 -1
  37. package/dist/cli/commands/gate.js +10 -7
  38. package/dist/cli/commands/gate.js.map +1 -1
  39. package/dist/cli/commands/index-cmd.d.ts.map +1 -1
  40. package/dist/cli/commands/index-cmd.js +2 -1
  41. package/dist/cli/commands/index-cmd.js.map +1 -1
  42. package/dist/cli/commands/init.d.ts.map +1 -1
  43. package/dist/cli/commands/init.js +26 -12
  44. package/dist/cli/commands/init.js.map +1 -1
  45. package/dist/cli/commands/initiative.d.ts.map +1 -1
  46. package/dist/cli/commands/initiative.js +9 -8
  47. package/dist/cli/commands/initiative.js.map +1 -1
  48. package/dist/cli/commands/inspirations.js +5 -5
  49. package/dist/cli/commands/inspirations.js.map +1 -1
  50. package/dist/cli/commands/interview.d.ts.map +1 -1
  51. package/dist/cli/commands/interview.js +2 -2
  52. package/dist/cli/commands/interview.js.map +1 -1
  53. package/dist/cli/commands/issue.d.ts.map +1 -1
  54. package/dist/cli/commands/issue.js +6 -9
  55. package/dist/cli/commands/issue.js.map +1 -1
  56. package/dist/cli/commands/map.d.ts +1 -1
  57. package/dist/cli/commands/map.d.ts.map +1 -1
  58. package/dist/cli/commands/map.js +34 -10
  59. package/dist/cli/commands/map.js.map +1 -1
  60. package/dist/cli/commands/next.js +2 -2
  61. package/dist/cli/commands/next.js.map +1 -1
  62. package/dist/cli/commands/now.d.ts +2 -2
  63. package/dist/cli/commands/now.d.ts.map +1 -1
  64. package/dist/cli/commands/now.js +23 -15
  65. package/dist/cli/commands/now.js.map +1 -1
  66. package/dist/cli/commands/pr.d.ts +3 -3
  67. package/dist/cli/commands/pr.d.ts.map +1 -1
  68. package/dist/cli/commands/pr.js +9 -8
  69. package/dist/cli/commands/pr.js.map +1 -1
  70. package/dist/cli/commands/prep.d.ts.map +1 -1
  71. package/dist/cli/commands/prep.js +2 -1
  72. package/dist/cli/commands/prep.js.map +1 -1
  73. package/dist/cli/commands/release.d.ts.map +1 -1
  74. package/dist/cli/commands/release.js +9 -11
  75. package/dist/cli/commands/release.js.map +1 -1
  76. package/dist/cli/commands/retro.d.ts +1 -1
  77. package/dist/cli/commands/retro.d.ts.map +1 -1
  78. package/dist/cli/commands/retro.js +35 -11
  79. package/dist/cli/commands/retro.js.map +1 -1
  80. package/dist/cli/commands/review-packet.d.ts +2 -2
  81. package/dist/cli/commands/review-packet.d.ts.map +1 -1
  82. package/dist/cli/commands/review-packet.js +3 -3
  83. package/dist/cli/commands/review-packet.js.map +1 -1
  84. package/dist/cli/commands/review-run.d.ts +3 -2
  85. package/dist/cli/commands/review-run.d.ts.map +1 -1
  86. package/dist/cli/commands/review-run.js +4 -4
  87. package/dist/cli/commands/review-run.js.map +1 -1
  88. package/dist/cli/commands/review-state.d.ts.map +1 -1
  89. package/dist/cli/commands/review-state.js +57 -30
  90. package/dist/cli/commands/review-state.js.map +1 -1
  91. package/dist/cli/commands/review.js +6 -6
  92. package/dist/cli/commands/review.js.map +1 -1
  93. package/dist/cli/commands/roadmap.d.ts.map +1 -1
  94. package/dist/cli/commands/roadmap.js +144 -78
  95. package/dist/cli/commands/roadmap.js.map +1 -1
  96. package/dist/cli/commands/session.d.ts.map +1 -1
  97. package/dist/cli/commands/session.js +47 -16
  98. package/dist/cli/commands/session.js.map +1 -1
  99. package/dist/cli/commands/sprint-plan.d.ts.map +1 -1
  100. package/dist/cli/commands/sprint-plan.js +10 -8
  101. package/dist/cli/commands/sprint-plan.js.map +1 -1
  102. package/dist/cli/commands/sprint.d.ts.map +1 -1
  103. package/dist/cli/commands/sprint.js +253 -38
  104. package/dist/cli/commands/sprint.js.map +1 -1
  105. package/dist/cli/commands/standup.d.ts.map +1 -1
  106. package/dist/cli/commands/standup.js +9 -4
  107. package/dist/cli/commands/standup.js.map +1 -1
  108. package/dist/cli/commands/start.js +2 -2
  109. package/dist/cli/commands/start.js.map +1 -1
  110. package/dist/cli/commands/stats.d.ts +4 -4
  111. package/dist/cli/commands/stats.d.ts.map +1 -1
  112. package/dist/cli/commands/stats.js +5 -5
  113. package/dist/cli/commands/stats.js.map +1 -1
  114. package/dist/cli/commands/status.d.ts +1 -1
  115. package/dist/cli/commands/status.d.ts.map +1 -1
  116. package/dist/cli/commands/status.js +12 -8
  117. package/dist/cli/commands/status.js.map +1 -1
  118. package/dist/cli/commands/store.d.ts +37 -0
  119. package/dist/cli/commands/store.d.ts.map +1 -1
  120. package/dist/cli/commands/store.js +262 -12
  121. package/dist/cli/commands/store.js.map +1 -1
  122. package/dist/cli/commands/ticket.d.ts.map +1 -1
  123. package/dist/cli/commands/ticket.js +4 -4
  124. package/dist/cli/commands/ticket.js.map +1 -1
  125. package/dist/cli/commands/tournament.d.ts.map +1 -1
  126. package/dist/cli/commands/tournament.js +7 -6
  127. package/dist/cli/commands/tournament.js.map +1 -1
  128. package/dist/cli/commands/validate.d.ts +13 -1
  129. package/dist/cli/commands/validate.d.ts.map +1 -1
  130. package/dist/cli/commands/validate.js +47 -10
  131. package/dist/cli/commands/validate.js.map +1 -1
  132. package/dist/cli/commands/version.d.ts +1 -1
  133. package/dist/cli/commands/version.d.ts.map +1 -1
  134. package/dist/cli/commands/version.js +13 -10
  135. package/dist/cli/commands/version.js.map +1 -1
  136. package/dist/cli/commands/worktree.d.ts.map +1 -1
  137. package/dist/cli/commands/worktree.js +36 -31
  138. package/dist/cli/commands/worktree.js.map +1 -1
  139. package/dist/cli/guards/claim-required.d.ts.map +1 -1
  140. package/dist/cli/guards/claim-required.js +2 -3
  141. package/dist/cli/guards/claim-required.js.map +1 -1
  142. package/dist/cli/guards/compaction.d.ts.map +1 -1
  143. package/dist/cli/guards/git-utils.d.ts +5 -0
  144. package/dist/cli/guards/git-utils.d.ts.map +1 -1
  145. package/dist/cli/guards/git-utils.js +36 -8
  146. package/dist/cli/guards/git-utils.js.map +1 -1
  147. package/dist/cli/guards/hazard.d.ts.map +1 -1
  148. package/dist/cli/guards/hazard.js +8 -7
  149. package/dist/cli/guards/hazard.js.map +1 -1
  150. package/dist/cli/guards/next-action.d.ts +5 -5
  151. package/dist/cli/guards/next-action.d.ts.map +1 -1
  152. package/dist/cli/guards/next-action.js +8 -8
  153. package/dist/cli/guards/next-action.js.map +1 -1
  154. package/dist/cli/guards/phase-boundary.d.ts.map +1 -1
  155. package/dist/cli/guards/phase-boundary.js +24 -14
  156. package/dist/cli/guards/phase-boundary.js.map +1 -1
  157. package/dist/cli/guards/post-hole-enforcement.d.ts.map +1 -1
  158. package/dist/cli/guards/post-hole-enforcement.js +9 -8
  159. package/dist/cli/guards/post-hole-enforcement.js.map +1 -1
  160. package/dist/cli/guards/post-push.d.ts.map +1 -1
  161. package/dist/cli/guards/post-push.js +7 -3
  162. package/dist/cli/guards/post-push.js.map +1 -1
  163. package/dist/cli/guards/review-stale.d.ts.map +1 -1
  164. package/dist/cli/guards/review-stale.js +6 -4
  165. package/dist/cli/guards/review-stale.js.map +1 -1
  166. package/dist/cli/guards/review-tier.d.ts.map +1 -1
  167. package/dist/cli/guards/review-tier.js +6 -7
  168. package/dist/cli/guards/review-tier.js.map +1 -1
  169. package/dist/cli/guards/roadmap-edit-shipped.d.ts.map +1 -1
  170. package/dist/cli/guards/roadmap-edit-shipped.js +34 -21
  171. package/dist/cli/guards/roadmap-edit-shipped.js.map +1 -1
  172. package/dist/cli/guards/scope-drift.d.ts.map +1 -1
  173. package/dist/cli/guards/scope-drift.js +2 -1
  174. package/dist/cli/guards/scope-drift.js.map +1 -1
  175. package/dist/cli/guards/session-briefing.d.ts.map +1 -1
  176. package/dist/cli/guards/session-briefing.js +34 -13
  177. package/dist/cli/guards/session-briefing.js.map +1 -1
  178. package/dist/cli/guards/sprint-completion.d.ts.map +1 -1
  179. package/dist/cli/guards/sprint-completion.js +32 -16
  180. package/dist/cli/guards/sprint-completion.js.map +1 -1
  181. package/dist/cli/guards/stop-check.d.ts.map +1 -1
  182. package/dist/cli/guards/stop-check.js +8 -10
  183. package/dist/cli/guards/stop-check.js.map +1 -1
  184. package/dist/cli/guards/transcript.d.ts.map +1 -1
  185. package/dist/cli/guards/transcript.js +2 -1
  186. package/dist/cli/guards/transcript.js.map +1 -1
  187. package/dist/cli/guards/workflow-step-gate.d.ts.map +1 -1
  188. package/dist/cli/guards/workflow-step-gate.js +25 -28
  189. package/dist/cli/guards/workflow-step-gate.js.map +1 -1
  190. package/dist/cli/guards/worktree-check.d.ts.map +1 -1
  191. package/dist/cli/guards/worktree-check.js +38 -13
  192. package/dist/cli/guards/worktree-check.js.map +1 -1
  193. package/dist/cli/hooks-config.d.ts.map +1 -1
  194. package/dist/cli/hooks-config.js +6 -4
  195. package/dist/cli/hooks-config.js.map +1 -1
  196. package/dist/cli/index.js +1 -1
  197. package/dist/cli/index.js.map +1 -1
  198. package/dist/cli/loop/executor.d.ts +1 -0
  199. package/dist/cli/loop/executor.d.ts.map +1 -1
  200. package/dist/cli/loop/executor.js +20 -13
  201. package/dist/cli/loop/executor.js.map +1 -1
  202. package/dist/cli/loop/pr-lifecycle.d.ts +2 -1
  203. package/dist/cli/loop/pr-lifecycle.d.ts.map +1 -1
  204. package/dist/cli/loop/pr-lifecycle.js +14 -8
  205. package/dist/cli/loop/pr-lifecycle.js.map +1 -1
  206. package/dist/cli/loop/worktree.d.ts.map +1 -1
  207. package/dist/cli/loop/worktree.js +1 -48
  208. package/dist/cli/loop/worktree.js.map +1 -1
  209. package/dist/cli/pr-closeout.d.ts +3 -2
  210. package/dist/cli/pr-closeout.d.ts.map +1 -1
  211. package/dist/cli/pr-closeout.js +14 -6
  212. package/dist/cli/pr-closeout.js.map +1 -1
  213. package/dist/cli/pr-review-state.d.ts +8 -7
  214. package/dist/cli/pr-review-state.d.ts.map +1 -1
  215. package/dist/cli/pr-review-state.js +3 -2
  216. package/dist/cli/pr-review-state.js.map +1 -1
  217. package/dist/cli/pre-sprint-reality.d.ts +4 -4
  218. package/dist/cli/pre-sprint-reality.d.ts.map +1 -1
  219. package/dist/cli/pre-sprint-reality.js +9 -2
  220. package/dist/cli/pre-sprint-reality.js.map +1 -1
  221. package/dist/cli/registries/api-registry.d.ts +2 -2
  222. package/dist/cli/registries/api-registry.d.ts.map +1 -1
  223. package/dist/cli/registries/api-registry.js +1 -1
  224. package/dist/cli/registries/api-registry.js.map +1 -1
  225. package/dist/cli/registries/file-registry.d.ts +3 -3
  226. package/dist/cli/registries/file-registry.d.ts.map +1 -1
  227. package/dist/cli/registries/file-registry.js +12 -2
  228. package/dist/cli/registries/file-registry.js.map +1 -1
  229. package/dist/cli/registries/index.d.ts +1 -1
  230. package/dist/cli/registries/index.d.ts.map +1 -1
  231. package/dist/cli/registries/index.js +2 -2
  232. package/dist/cli/registries/index.js.map +1 -1
  233. package/dist/cli/registry.d.ts.map +1 -1
  234. package/dist/cli/registry.js +4 -0
  235. package/dist/cli/registry.js.map +1 -1
  236. package/dist/cli/reviewer-agents.d.ts +2 -1
  237. package/dist/cli/reviewer-agents.d.ts.map +1 -1
  238. package/dist/cli/reviewer-agents.js.map +1 -1
  239. package/dist/cli/roadmap-source-migration.d.ts.map +1 -1
  240. package/dist/cli/roadmap-source-migration.js +15 -13
  241. package/dist/cli/roadmap-source-migration.js.map +1 -1
  242. package/dist/cli/roadmap-source-store.d.ts +15 -4
  243. package/dist/cli/roadmap-source-store.d.ts.map +1 -1
  244. package/dist/cli/roadmap-source-store.js +79 -33
  245. package/dist/cli/roadmap-source-store.js.map +1 -1
  246. package/dist/cli/session-heartbeat.d.ts +12 -0
  247. package/dist/cli/session-heartbeat.d.ts.map +1 -0
  248. package/dist/cli/session-heartbeat.js +46 -0
  249. package/dist/cli/session-heartbeat.js.map +1 -0
  250. package/dist/cli/session-scope.d.ts.map +1 -1
  251. package/dist/cli/session-scope.js +4 -16
  252. package/dist/cli/session-scope.js.map +1 -1
  253. package/dist/cli/session-state.js +5 -5
  254. package/dist/cli/session-state.js.map +1 -1
  255. package/dist/cli/sprint-inference.d.ts +5 -5
  256. package/dist/cli/sprint-inference.d.ts.map +1 -1
  257. package/dist/cli/sprint-inference.js +63 -33
  258. package/dist/cli/sprint-inference.js.map +1 -1
  259. package/dist/cli/sprint-resume.d.ts +7 -7
  260. package/dist/cli/sprint-resume.d.ts.map +1 -1
  261. package/dist/cli/sprint-resume.js +43 -21
  262. package/dist/cli/sprint-resume.js.map +1 -1
  263. package/dist/cli/sprint-rollover.d.ts +19 -19
  264. package/dist/cli/sprint-rollover.d.ts.map +1 -1
  265. package/dist/cli/sprint-rollover.js +116 -69
  266. package/dist/cli/sprint-rollover.js.map +1 -1
  267. package/dist/cli/sprint-state.d.ts +8 -6
  268. package/dist/cli/sprint-state.d.ts.map +1 -1
  269. package/dist/cli/sprint-state.js +39 -12
  270. package/dist/cli/sprint-state.js.map +1 -1
  271. package/dist/cli/store.d.ts.map +1 -1
  272. package/dist/cli/store.js +5 -3
  273. package/dist/cli/store.js.map +1 -1
  274. package/dist/cli/workflow-closeout.d.ts +11 -0
  275. package/dist/cli/workflow-closeout.d.ts.map +1 -0
  276. package/dist/cli/workflow-closeout.js +30 -0
  277. package/dist/cli/workflow-closeout.js.map +1 -0
  278. package/dist/cli/workflow-resync.d.ts +13 -9
  279. package/dist/cli/workflow-resync.d.ts.map +1 -1
  280. package/dist/cli/workflow-resync.js +75 -22
  281. package/dist/cli/workflow-resync.js.map +1 -1
  282. package/dist/core/advisor.d.ts.map +1 -1
  283. package/dist/core/advisor.js +5 -2
  284. package/dist/core/advisor.js.map +1 -1
  285. package/dist/core/analytics.d.ts +2 -2
  286. package/dist/core/analytics.d.ts.map +1 -1
  287. package/dist/core/analytics.js +4 -3
  288. package/dist/core/analytics.js.map +1 -1
  289. package/dist/core/analyzers/git.d.ts +3 -2
  290. package/dist/core/analyzers/git.d.ts.map +1 -1
  291. package/dist/core/analyzers/git.js +6 -5
  292. package/dist/core/analyzers/git.js.map +1 -1
  293. package/dist/core/briefing.d.ts +6 -5
  294. package/dist/core/briefing.d.ts.map +1 -1
  295. package/dist/core/briefing.js +52 -36
  296. package/dist/core/briefing.js.map +1 -1
  297. package/dist/core/builder.d.ts +3 -1
  298. package/dist/core/builder.d.ts.map +1 -1
  299. package/dist/core/builder.js +6 -4
  300. package/dist/core/builder.js.map +1 -1
  301. package/dist/core/config.d.ts +2 -1
  302. package/dist/core/config.d.ts.map +1 -1
  303. package/dist/core/config.js +26 -6
  304. package/dist/core/config.js.map +1 -1
  305. package/dist/core/dashboard.d.ts +2 -2
  306. package/dist/core/dashboard.d.ts.map +1 -1
  307. package/dist/core/dashboard.js +2 -1
  308. package/dist/core/dashboard.js.map +1 -1
  309. package/dist/core/deferred.d.ts +7 -6
  310. package/dist/core/deferred.d.ts.map +1 -1
  311. package/dist/core/deferred.js +30 -7
  312. package/dist/core/deferred.js.map +1 -1
  313. package/dist/core/enrich.d.ts +1 -1
  314. package/dist/core/escalation.d.ts +2 -1
  315. package/dist/core/escalation.d.ts.map +1 -1
  316. package/dist/core/escalation.js +3 -1
  317. package/dist/core/escalation.js.map +1 -1
  318. package/dist/core/event-ingestion.d.ts.map +1 -1
  319. package/dist/core/event-ingestion.js +8 -3
  320. package/dist/core/event-ingestion.js.map +1 -1
  321. package/dist/core/findings.d.ts +6 -4
  322. package/dist/core/findings.d.ts.map +1 -1
  323. package/dist/core/findings.js +30 -7
  324. package/dist/core/findings.js.map +1 -1
  325. package/dist/core/formatter.d.ts +2 -1
  326. package/dist/core/formatter.d.ts.map +1 -1
  327. package/dist/core/formatter.js.map +1 -1
  328. package/dist/core/generators/roadmap.js +2 -2
  329. package/dist/core/generators/roadmap.js.map +1 -1
  330. package/dist/core/index.d.ts +8 -5
  331. package/dist/core/index.d.ts.map +1 -1
  332. package/dist/core/index.js +4 -2
  333. package/dist/core/index.js.map +1 -1
  334. package/dist/core/initiative.d.ts +5 -4
  335. package/dist/core/initiative.d.ts.map +1 -1
  336. package/dist/core/initiative.js +39 -11
  337. package/dist/core/initiative.js.map +1 -1
  338. package/dist/core/inspirations.d.ts +4 -3
  339. package/dist/core/inspirations.d.ts.map +1 -1
  340. package/dist/core/inspirations.js +19 -4
  341. package/dist/core/inspirations.js.map +1 -1
  342. package/dist/core/interview-engine.d.ts +2 -1
  343. package/dist/core/interview-engine.d.ts.map +1 -1
  344. package/dist/core/interview-engine.js +26 -17
  345. package/dist/core/interview-engine.js.map +1 -1
  346. package/dist/core/interview-steps.d.ts.map +1 -1
  347. package/dist/core/interview-steps.js +7 -6
  348. package/dist/core/interview-steps.js.map +1 -1
  349. package/dist/core/interview.d.ts +2 -1
  350. package/dist/core/interview.d.ts.map +1 -1
  351. package/dist/core/interview.js +13 -7
  352. package/dist/core/interview.js.map +1 -1
  353. package/dist/core/issue-scout.d.ts +2 -1
  354. package/dist/core/issue-scout.d.ts.map +1 -1
  355. package/dist/core/issue-scout.js.map +1 -1
  356. package/dist/core/loader.d.ts +4 -4
  357. package/dist/core/loader.d.ts.map +1 -1
  358. package/dist/core/loader.js +71 -33
  359. package/dist/core/loader.js.map +1 -1
  360. package/dist/core/memory.d.ts.map +1 -1
  361. package/dist/core/memory.js +16 -6
  362. package/dist/core/memory.js.map +1 -1
  363. package/dist/core/org.d.ts +1 -1
  364. package/dist/core/org.d.ts.map +1 -1
  365. package/dist/core/org.js +2 -1
  366. package/dist/core/org.js.map +1 -1
  367. package/dist/core/pipeline.d.ts +1 -1
  368. package/dist/core/pipeline.d.ts.map +1 -1
  369. package/dist/core/pipeline.js +10 -6
  370. package/dist/core/pipeline.js.map +1 -1
  371. package/dist/core/player.d.ts.map +1 -1
  372. package/dist/core/player.js +2 -1
  373. package/dist/core/player.js.map +1 -1
  374. package/dist/core/prep.d.ts +3 -3
  375. package/dist/core/registry.d.ts +6 -2
  376. package/dist/core/registry.d.ts.map +1 -1
  377. package/dist/core/registry.js +2 -1
  378. package/dist/core/registry.js.map +1 -1
  379. package/dist/core/repo-state-scope.d.ts +27 -0
  380. package/dist/core/repo-state-scope.d.ts.map +1 -0
  381. package/dist/core/repo-state-scope.js +105 -0
  382. package/dist/core/repo-state-scope.js.map +1 -0
  383. package/dist/core/report.d.ts +1 -1
  384. package/dist/core/report.d.ts.map +1 -1
  385. package/dist/core/report.js +2 -1
  386. package/dist/core/report.js.map +1 -1
  387. package/dist/core/retro.d.ts +3 -2
  388. package/dist/core/retro.d.ts.map +1 -1
  389. package/dist/core/retro.js +6 -3
  390. package/dist/core/retro.js.map +1 -1
  391. package/dist/core/roadmap-focus.d.ts +8 -7
  392. package/dist/core/roadmap-focus.d.ts.map +1 -1
  393. package/dist/core/roadmap-focus.js +45 -34
  394. package/dist/core/roadmap-focus.js.map +1 -1
  395. package/dist/core/roadmap-migration.d.ts +2 -1
  396. package/dist/core/roadmap-migration.d.ts.map +1 -1
  397. package/dist/core/roadmap-migration.js +110 -51
  398. package/dist/core/roadmap-migration.js.map +1 -1
  399. package/dist/core/roadmap-source-patch.d.ts +2 -1
  400. package/dist/core/roadmap-source-patch.d.ts.map +1 -1
  401. package/dist/core/roadmap-source-patch.js +9 -4
  402. package/dist/core/roadmap-source-patch.js.map +1 -1
  403. package/dist/core/roadmap-sources.d.ts +2 -1
  404. package/dist/core/roadmap-sources.d.ts.map +1 -1
  405. package/dist/core/roadmap-sources.js +38 -26
  406. package/dist/core/roadmap-sources.js.map +1 -1
  407. package/dist/core/roadmap.d.ts +35 -17
  408. package/dist/core/roadmap.d.ts.map +1 -1
  409. package/dist/core/roadmap.js +167 -86
  410. package/dist/core/roadmap.js.map +1 -1
  411. package/dist/core/session-branch.d.ts +17 -0
  412. package/dist/core/session-branch.d.ts.map +1 -0
  413. package/dist/core/session-branch.js +85 -0
  414. package/dist/core/session-branch.js.map +1 -0
  415. package/dist/core/sprint-id.d.ts +13 -5
  416. package/dist/core/sprint-id.d.ts.map +1 -1
  417. package/dist/core/sprint-id.js +16 -0
  418. package/dist/core/sprint-id.js.map +1 -1
  419. package/dist/core/standup.d.ts +2 -1
  420. package/dist/core/standup.d.ts.map +1 -1
  421. package/dist/core/standup.js.map +1 -1
  422. package/dist/core/store.d.ts +16 -8
  423. package/dist/core/store.d.ts.map +1 -1
  424. package/dist/core/store.js +34 -0
  425. package/dist/core/store.js.map +1 -1
  426. package/dist/core/tournament.d.ts.map +1 -1
  427. package/dist/core/tournament.js +4 -3
  428. package/dist/core/tournament.js.map +1 -1
  429. package/dist/core/types.d.ts +9 -7
  430. package/dist/core/types.d.ts.map +1 -1
  431. package/dist/core/validation.d.ts +2 -1
  432. package/dist/core/validation.d.ts.map +1 -1
  433. package/dist/core/validation.js +2 -1
  434. package/dist/core/validation.js.map +1 -1
  435. package/dist/core/webhooks.d.ts +3 -2
  436. package/dist/core/webhooks.d.ts.map +1 -1
  437. package/dist/core/webhooks.js +9 -2
  438. package/dist/core/webhooks.js.map +1 -1
  439. package/dist/core/workflow-loader.d.ts.map +1 -1
  440. package/dist/core/workflow-loader.js +2 -1
  441. package/dist/core/workflow-loader.js.map +1 -1
  442. package/dist/mcp/index.d.ts +5 -1
  443. package/dist/mcp/index.d.ts.map +1 -1
  444. package/dist/mcp/index.js +97 -59
  445. package/dist/mcp/index.js.map +1 -1
  446. package/dist/mcp/index.test.js +14 -3
  447. package/dist/mcp/index.test.js.map +1 -1
  448. package/dist/mcp/registry.d.ts +1 -1
  449. package/dist/mcp/registry.d.ts.map +1 -1
  450. package/dist/mcp/registry.js +36 -28
  451. package/dist/mcp/registry.js.map +1 -1
  452. package/dist/store/index.d.ts +13 -11
  453. package/dist/store/index.d.ts.map +1 -1
  454. package/dist/store/index.js +217 -36
  455. package/dist/store/index.js.map +1 -1
  456. package/dist/store-pg/index.d.ts +18 -12
  457. package/dist/store-pg/index.d.ts.map +1 -1
  458. package/dist/store-pg/index.js +124 -38
  459. package/dist/store-pg/index.js.map +1 -1
  460. package/package.json +1 -1
  461. package/templates/codex/plugins/slope/.codex-plugin/plugin.json +1 -1
@@ -1,5 +1,6 @@
1
1
  // SLOPE — Roadmap: Strategic planning types and compute functions
2
2
  // Course-level methodology — vision → roadmap → review → iteration
3
+ import { compareSprintIdKeys, parseSprintId, sprintIdKey } from './sprint-id.js';
3
4
  /** Return true for legacy encoded inserted half-sprint ids like 435 => S43.5.
4
5
  * Decimal roadmap ids such as 75.5 are already explicit and are left as-is.
5
6
  * The encoding is intentionally limited to pre-S100-style three-digit ids
@@ -19,6 +20,8 @@ export function sprintOrderValue(id) {
19
20
  }
20
21
  /** Format the numeric portion of a sprint id for human-facing output. */
21
22
  export function formatSprintNumber(id) {
23
+ if (typeof id === 'string')
24
+ return sprintIdKey(id) ?? id;
22
25
  if (isEncodedInsertedSprintId(id)) {
23
26
  return `${Math.floor(id / 10)}.${id % 10}`;
24
27
  }
@@ -91,13 +94,13 @@ export function compareSprintIds(a, b) {
91
94
  }
92
95
  /** Return the next canonical sprint id after a completed sprint/inserted sprint. */
93
96
  export function nextCanonicalSprintId(id) {
94
- if (isEncodedInsertedSprintId(id)) {
95
- return Math.floor(id / 10) + 1;
96
- }
97
- if (!Number.isInteger(id)) {
98
- return Math.floor(id) + 1;
97
+ if (typeof id === 'number' && isEncodedInsertedSprintId(id)) {
98
+ return String(Math.floor(id / 10) + 1);
99
99
  }
100
- return id + 1;
100
+ const parsed = parseSprintId(id);
101
+ if (!parsed)
102
+ return '1';
103
+ return String(parsed.base + 1);
101
104
  }
102
105
  export const ROADMAP_TERMINAL_STATUSES = new Set([
103
106
  'complete',
@@ -107,13 +110,26 @@ export const ROADMAP_TERMINAL_STATUSES = new Set([
107
110
  'cancelled-absorbed',
108
111
  'absorbed',
109
112
  ]);
113
+ /**
114
+ * Statuses that are not durably terminal but are intentionally not offered as
115
+ * the next sprint to work on. A deferred sprint is postponed by choice — it is
116
+ * neither done (so not terminal) nor queued work (so not selectable). It becomes
117
+ * selectable again once its status is edited back to planned/active (GH #660).
118
+ */
119
+ export const ROADMAP_DEFERRED_STATUSES = new Set(['deferred']);
110
120
  /** Return true when a roadmap sprint has a durable terminal disposition. */
111
121
  export function isRoadmapSprintTerminal(sprint) {
112
122
  return ROADMAP_TERMINAL_STATUSES.has(sprint.status ?? '');
113
123
  }
114
- /** Return true when a roadmap sprint should still be considered selectable work. */
124
+ /**
125
+ * Return true when a roadmap sprint should still be considered selectable work —
126
+ * the pool the "next sprint" pickers, rollover target, and current-sprint
127
+ * inference draw from. Excludes both terminal statuses and deferred (a
128
+ * deliberately postponed sprint must not be surfaced as the next thing to do).
129
+ */
115
130
  export function isRoadmapSprintPending(sprint) {
116
- return !isRoadmapSprintTerminal(sprint);
131
+ return !isRoadmapSprintTerminal(sprint)
132
+ && !ROADMAP_DEFERRED_STATUSES.has(sprint.status ?? '');
117
133
  }
118
134
  export function getRoadmapTicketKey(ticket) {
119
135
  const key = ticket.key;
@@ -156,13 +172,31 @@ export function isEncodedInsertedSprintInRoadmap(roadmap, id) {
156
172
  return sprintIds.has(base) || sprintIds.has(base + 1);
157
173
  }
158
174
  export function roadmapSprintOrderValue(roadmap, id) {
159
- return isEncodedInsertedSprintInRoadmap(roadmap, id) ? sprintOrderValue(id) : id;
175
+ const key = roadmapSprintKeyFromId(roadmap, id);
176
+ const parsed = key ? parseSprintId(key) : null;
177
+ if (!parsed)
178
+ return typeof id === 'number' ? id : Number(id);
179
+ if (parsed.insert === null)
180
+ return parsed.base;
181
+ return parsed.base + parsed.insert / (10 ** parsed.insertDigits.length);
160
182
  }
161
183
  export function compareRoadmapSprintIds(roadmap, a, b) {
162
- return roadmapSprintOrderValue(roadmap, a) - roadmapSprintOrderValue(roadmap, b);
184
+ const ka = roadmapSprintKeyFromId(roadmap, a) ?? String(a);
185
+ const kb = roadmapSprintKeyFromId(roadmap, b) ?? String(b);
186
+ return compareSprintIdKeys(ka, kb);
187
+ }
188
+ function areAdjacentSprintKeys(previousKey, currentKey) {
189
+ const previous = parseSprintId(previousKey);
190
+ const current = parseSprintId(currentKey);
191
+ if (!previous || !current)
192
+ return false;
193
+ if (previous.base === current.base) {
194
+ return current.insert !== null && compareSprintIdKeys(previousKey, currentKey) < 0;
195
+ }
196
+ return current.base === previous.base + 1 && current.insert === null;
163
197
  }
164
198
  export function formatRoadmapSprintLabel(roadmap, id) {
165
- return isEncodedInsertedSprintInRoadmap(roadmap, id) ? formatSprintLabel(id) : `S${id}`;
199
+ return `S${roadmapSprintKeyFromId(roadmap, id) ?? id}`;
166
200
  }
167
201
  /**
168
202
  * Canonical string identity for a sprint: the authored `id_key` when present
@@ -177,6 +211,24 @@ export function roadmapSprintKey(roadmap, sprint) {
177
211
  ? formatSprintNumber(sprint.id)
178
212
  : String(sprint.id);
179
213
  }
214
+ /** Resolve a canonical sprint key from either a key or a legacy numeric mirror. */
215
+ export function roadmapSprintKeyFromId(roadmap, id) {
216
+ const inputKey = sprintIdKey(id);
217
+ if (inputKey === null)
218
+ return null;
219
+ const canonical = roadmap.sprints.find(sprint => roadmapSprintKey(roadmap, sprint) === inputKey);
220
+ if (canonical)
221
+ return roadmapSprintKey(roadmap, canonical);
222
+ const mirror = roadmap.sprints.find(sprint => sprint.id === Number(inputKey));
223
+ return mirror ? roadmapSprintKey(roadmap, mirror) : inputKey;
224
+ }
225
+ /** Find one roadmap sprint by canonical key, with numeric mirrors as legacy input. */
226
+ export function findRoadmapSprint(roadmap, id) {
227
+ const key = roadmapSprintKeyFromId(roadmap, id);
228
+ return key == null
229
+ ? undefined
230
+ : roadmap.sprints.find(sprint => roadmapSprintKey(roadmap, sprint) === key);
231
+ }
180
232
  /** Validate a roadmap definition for structural correctness.
181
233
  * Optionally cross-check sprint status against scorecards and/or shipped
182
234
  * sprint commits on main when provided. Caller is responsible for collecting
@@ -185,8 +237,7 @@ export function roadmapSprintKey(roadmap, sprint) {
185
237
  export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
186
238
  const errors = [];
187
239
  const warnings = [];
188
- const sprintIds = new Set(roadmap.sprints.map(s => s.id));
189
- const orderOf = (id) => roadmapSprintOrderValue(roadmap, id);
240
+ const sprintIds = new Set(roadmap.sprints.map(s => roadmapSprintKey(roadmap, s)));
190
241
  const labelOf = (id) => formatRoadmapSprintLabel(roadmap, id);
191
242
  // Canonical identity so 458.10 and 458.1 are distinct sprints with distinct
192
243
  // ticket-key prefixes (GH #635).
@@ -197,12 +248,9 @@ export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
197
248
  return { valid: false, errors, warnings };
198
249
  }
199
250
  // Check: sprint numbering continuity
200
- const sortedIds = [...sprintIds].sort((a, b) => orderOf(a) - orderOf(b));
251
+ const sortedIds = [...sprintIds].sort((a, b) => compareSprintIdKeys(a, b));
201
252
  for (let i = 1; i < sortedIds.length; i++) {
202
- const prev = orderOf(sortedIds[i - 1]);
203
- const current = orderOf(sortedIds[i]);
204
- const allowedInsertedStep = current > prev && current <= Math.floor(prev) + 1;
205
- if (!allowedInsertedStep && current !== prev + 1) {
253
+ if (!areAdjacentSprintKeys(sortedIds[i - 1], sortedIds[i])) {
206
254
  // A long-lived roadmap legitimately skips numbers as sprints are
207
255
  // absorbed, cancelled, or renumbered, so a numbering discontinuity is
208
256
  // informational rather than a structural error. Genuinely-structural
@@ -223,19 +271,20 @@ export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
223
271
  // Build a set of all ticket keys across all sprints for cross-sprint dependency validation
224
272
  const allTicketKeys = new Set(roadmap.sprints.flatMap(s => s.tickets.map(getRoadmapTicketKey).filter((key) => key !== null)));
225
273
  for (const sprint of roadmap.sprints) {
274
+ const sprintKey = roadmapSprintKey(roadmap, sprint);
226
275
  // Check: ticket count (3-4 per sprint)
227
276
  if (sprint.tickets.length < 3) {
228
277
  warnings.push({
229
278
  type: 'warning',
230
- sprint: sprint.id,
231
- message: `${labelOf(sprint.id)} has ${sprint.tickets.length} tickets (recommended 3-4)`,
279
+ sprint: sprintKey,
280
+ message: `${keyLabelOf(sprint)} has ${sprint.tickets.length} tickets (recommended 3-4)`,
232
281
  });
233
282
  }
234
283
  if (sprint.tickets.length > 4) {
235
284
  warnings.push({
236
285
  type: 'warning',
237
- sprint: sprint.id,
238
- message: `${labelOf(sprint.id)} has ${sprint.tickets.length} tickets (recommended 3-4)`,
286
+ sprint: sprintKey,
287
+ message: `${keyLabelOf(sprint)} has ${sprint.tickets.length} tickets (recommended 3-4)`,
239
288
  });
240
289
  }
241
290
  // Check: ticket key format matches sprint
@@ -245,15 +294,15 @@ export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
245
294
  if (!ticketKey) {
246
295
  errors.push({
247
296
  type: 'error',
248
- sprint: sprint.id,
249
- message: `Ticket in ${labelOf(sprint.id)} is missing key/id`,
297
+ sprint: sprintKey,
298
+ message: `Ticket in ${keyLabelOf(sprint)} is missing key/id`,
250
299
  });
251
300
  continue;
252
301
  }
253
302
  if (!ticketKey.startsWith(expected)) {
254
303
  errors.push({
255
304
  type: 'error',
256
- sprint: sprint.id,
305
+ sprint: sprintKey,
257
306
  ticket: ticketKey,
258
307
  message: `Ticket ${ticketKey} does not match sprint ${keyLabelOf(sprint)} (expected prefix ${expected})`,
259
308
  });
@@ -268,7 +317,7 @@ export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
268
317
  if (!allTicketKeys.has(dep)) {
269
318
  errors.push({
270
319
  type: 'error',
271
- sprint: sprint.id,
320
+ sprint: sprintKey,
272
321
  ticket: ticketKey,
273
322
  message: `Ticket ${ticketKey} depends on ${dep} which does not exist in the roadmap`,
274
323
  });
@@ -277,11 +326,12 @@ export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
277
326
  }
278
327
  // Check: sprint dependencies exist
279
328
  for (const dep of sprint.depends_on ?? []) {
280
- if (!sprintIds.has(dep)) {
329
+ const depKey = roadmapSprintKeyFromId(roadmap, dep);
330
+ if (depKey === null || !sprintIds.has(depKey)) {
281
331
  errors.push({
282
332
  type: 'error',
283
- sprint: sprint.id,
284
- message: `${labelOf(sprint.id)} depends on ${labelOf(dep)} which does not exist in the roadmap`,
333
+ sprint: sprintKey,
334
+ message: `${labelOf(roadmapSprintKey(roadmap, sprint))} depends on ${labelOf(dep)} which does not exist in the roadmap`,
285
335
  });
286
336
  }
287
337
  }
@@ -289,8 +339,8 @@ export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
289
339
  if (sprint.par < 3 || sprint.par > 5) {
290
340
  errors.push({
291
341
  type: 'error',
292
- sprint: sprint.id,
293
- message: `${labelOf(sprint.id)} has invalid par ${sprint.par} (must be 3, 4, or 5)`,
342
+ sprint: sprintKey,
343
+ message: `${keyLabelOf(sprint)} has invalid par ${sprint.par} (must be 3, 4, or 5)`,
294
344
  });
295
345
  }
296
346
  }
@@ -304,8 +354,10 @@ export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
304
354
  }
305
355
  // Check: phases reference valid sprint IDs
306
356
  for (const phase of roadmap.phases) {
307
- for (const sid of phase.sprints) {
308
- if (!sprintIds.has(sid)) {
357
+ const phaseSprintIds = phase.sprint_keys ?? phase.sprints;
358
+ for (const sid of phaseSprintIds) {
359
+ const sidKey = roadmapSprintKeyFromId(roadmap, sid);
360
+ if (sidKey === null || !sprintIds.has(sidKey)) {
309
361
  errors.push({
310
362
  type: 'error',
311
363
  message: `Phase "${phase.name}" references ${labelOf(sid)} which does not exist`,
@@ -315,22 +367,22 @@ export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
315
367
  }
316
368
  // Cross-validate sprint status against scorecards when provided
317
369
  if (scorecards) {
318
- const scorecardSprintIds = new Set(scorecards.map(s => s.sprint_number));
370
+ const scorecardSprintIds = new Set(scorecards.map(s => roadmapSprintKeyFromId(roadmap, s.sprint_number)));
319
371
  for (const sprint of roadmap.sprints) {
320
- const hasScorecard = scorecardSprintIds.has(sprint.id);
372
+ const hasScorecard = scorecardSprintIds.has(roadmapSprintKey(roadmap, sprint));
321
373
  const status = sprint.status;
322
374
  if (hasScorecard && status !== 'complete') {
323
375
  warnings.push({
324
376
  type: 'warning',
325
- sprint: sprint.id,
326
- message: `${labelOf(sprint.id)} has a scorecard but roadmap status is "${status ?? 'planned'}" — expected "complete"`,
377
+ sprint: roadmapSprintKey(roadmap, sprint),
378
+ message: `${keyLabelOf(sprint)} has a scorecard but roadmap status is "${status ?? 'planned'}" — expected "complete"`,
327
379
  });
328
380
  }
329
381
  if (!hasScorecard && status === 'complete') {
330
382
  warnings.push({
331
383
  type: 'warning',
332
- sprint: sprint.id,
333
- message: `${labelOf(sprint.id)} is marked "complete" in roadmap but no scorecard exists (phantom sprint)`,
384
+ sprint: roadmapSprintKey(roadmap, sprint),
385
+ message: `${keyLabelOf(sprint)} is marked "complete" in roadmap but no scorecard exists (phantom sprint)`,
334
386
  });
335
387
  }
336
388
  }
@@ -342,21 +394,25 @@ export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
342
394
  // bookkeeping, not a feature ship). Treat those terminal-but-not-complete
343
395
  // statuses as final rather than demanding "complete".
344
396
  const TERMINAL_NOT_COMPLETE = new Set(['superseded', 'skipped', 'cancelled', 'cancelled-absorbed', 'absorbed']);
397
+ const shippedSprintKeys = new Set([...shippedSprintIds]
398
+ .map(id => roadmapSprintKeyFromId(roadmap, id))
399
+ .filter((id) => id !== null));
345
400
  for (const sprint of roadmap.sprints) {
346
401
  const status = sprint.status;
347
- const isShipped = shippedSprintIds.has(sprint.id);
402
+ const key = roadmapSprintKey(roadmap, sprint);
403
+ const isShipped = shippedSprintKeys.has(key);
348
404
  if (isShipped && status !== 'complete' && !TERMINAL_NOT_COMPLETE.has(status ?? '')) {
349
405
  errors.push({
350
406
  type: 'error',
351
- sprint: sprint.id,
352
- message: `${labelOf(sprint.id)} has shipped commits on main but status is "${status ?? 'planned'}" — expected "complete"`,
407
+ sprint: key,
408
+ message: `${keyLabelOf(sprint)} has shipped commits on main but status is "${status ?? 'planned'}" — expected "complete"`,
353
409
  });
354
410
  }
355
411
  if (!isShipped && status === 'complete') {
356
412
  warnings.push({
357
413
  type: 'warning',
358
- sprint: sprint.id,
359
- message: `${labelOf(sprint.id)} is marked "complete" but no shipped commits found on main`,
414
+ sprint: key,
415
+ message: `${keyLabelOf(sprint)} is marked "complete" but no shipped commits found on main`,
360
416
  });
361
417
  }
362
418
  }
@@ -366,29 +422,34 @@ export function validateRoadmap(roadmap, scorecards, shippedSprintIds) {
366
422
  // --- Dependency Graph ---
367
423
  /** Detect cycles in sprint dependency graph. Returns cycle path or null. */
368
424
  function detectCycle(sprints) {
425
+ const roadmap = { name: '', phases: [], sprints };
426
+ const sprintMap = new Map(sprints.map(sprint => [roadmapSprintKey(roadmap, sprint), sprint]));
369
427
  const visited = new Set();
370
428
  const inStack = new Set();
371
429
  const parent = new Map();
372
430
  function dfs(id) {
373
431
  visited.add(id);
374
432
  inStack.add(id);
375
- const sprint = sprints.find(s => s.id === id);
433
+ const sprint = sprintMap.get(id);
376
434
  for (const dep of sprint?.depends_on ?? []) {
377
- if (!visited.has(dep)) {
378
- parent.set(dep, id);
379
- const result = dfs(dep);
435
+ const depKey = roadmapSprintKeyFromId(roadmap, dep);
436
+ if (depKey === null)
437
+ continue;
438
+ if (!visited.has(depKey)) {
439
+ parent.set(depKey, id);
440
+ const result = dfs(depKey);
380
441
  if (result)
381
442
  return result;
382
443
  }
383
- else if (inStack.has(dep)) {
444
+ else if (inStack.has(depKey)) {
384
445
  // Build cycle path
385
- const cycle = [dep];
446
+ const cycle = [depKey];
386
447
  let current = id;
387
- while (current !== dep) {
448
+ while (current !== depKey) {
388
449
  cycle.push(current);
389
450
  current = parent.get(current);
390
451
  }
391
- cycle.push(dep);
452
+ cycle.push(depKey);
392
453
  return cycle.reverse();
393
454
  }
394
455
  }
@@ -396,8 +457,9 @@ function detectCycle(sprints) {
396
457
  return null;
397
458
  }
398
459
  for (const sprint of sprints) {
399
- if (!visited.has(sprint.id)) {
400
- const result = dfs(sprint.id);
460
+ const key = roadmapSprintKey(roadmap, sprint);
461
+ if (!visited.has(key)) {
462
+ const result = dfs(key);
401
463
  if (result)
402
464
  return result;
403
465
  }
@@ -406,7 +468,7 @@ function detectCycle(sprints) {
406
468
  }
407
469
  /** Compute the critical path (longest dependency chain) through the roadmap */
408
470
  export function computeCriticalPath(roadmap) {
409
- const sprintMap = new Map(roadmap.sprints.map(s => [s.id, s]));
471
+ const sprintMap = new Map(roadmap.sprints.map(s => [roadmapSprintKey(roadmap, s), s]));
410
472
  // Compute longest path ending at each sprint via topological order
411
473
  const longestTo = new Map();
412
474
  // Topological sort
@@ -420,7 +482,8 @@ export function computeCriticalPath(roadmap) {
420
482
  else {
421
483
  let best = { length: 0, path: [] };
422
484
  for (const dep of deps) {
423
- const depPath = longestTo.get(dep);
485
+ const depKey = roadmapSprintKeyFromId(roadmap, dep);
486
+ const depPath = depKey ? longestTo.get(depKey) : undefined;
424
487
  if (depPath && depPath.length > best.length) {
425
488
  best = depPath;
426
489
  }
@@ -447,16 +510,22 @@ export function computeCriticalPath(roadmap) {
447
510
  }
448
511
  /** Topological sort of sprints by dependency order */
449
512
  function topologicalSort(sprints) {
513
+ const roadmap = { name: '', phases: [], sprints };
450
514
  const inDegree = new Map();
451
515
  const adjacency = new Map();
452
516
  for (const sprint of sprints) {
453
- inDegree.set(sprint.id, 0);
454
- adjacency.set(sprint.id, []);
517
+ const key = roadmapSprintKey(roadmap, sprint);
518
+ inDegree.set(key, 0);
519
+ adjacency.set(key, []);
455
520
  }
456
521
  for (const sprint of sprints) {
522
+ const key = roadmapSprintKey(roadmap, sprint);
457
523
  for (const dep of sprint.depends_on ?? []) {
458
- adjacency.get(dep)?.push(sprint.id);
459
- inDegree.set(sprint.id, (inDegree.get(sprint.id) ?? 0) + 1);
524
+ const depKey = roadmapSprintKeyFromId(roadmap, dep);
525
+ if (depKey === null)
526
+ continue;
527
+ adjacency.get(depKey)?.push(key);
528
+ inDegree.set(key, (inDegree.get(key) ?? 0) + 1);
460
529
  }
461
530
  }
462
531
  const queue = [];
@@ -491,7 +560,7 @@ export function findParallelOpportunities(roadmap) {
491
560
  for (const [depth, ids] of byDepth) {
492
561
  if (ids.length > 1) {
493
562
  groups.push({
494
- sprints: ids.sort((a, b) => a - b),
563
+ sprints: ids.sort(compareSprintIdKeys),
495
564
  reason: `Same dependency depth (${depth}) — no mutual dependencies`,
496
565
  });
497
566
  }
@@ -500,19 +569,23 @@ export function findParallelOpportunities(roadmap) {
500
569
  }
501
570
  /** Compute the depth (longest path from a root) of each sprint */
502
571
  function computeDepthMap(sprints) {
572
+ const roadmap = { name: '', phases: [], sprints };
503
573
  const depthMap = new Map();
504
- const sprintMap = new Map(sprints.map(s => [s.id, s]));
574
+ const sprintMap = new Map(sprints.map(s => [roadmapSprintKey(roadmap, s), s]));
505
575
  function getDepth(id) {
506
576
  if (depthMap.has(id))
507
577
  return depthMap.get(id);
508
578
  const sprint = sprintMap.get(id);
509
579
  const deps = sprint?.depends_on ?? [];
510
- const depth = deps.length === 0 ? 0 : Math.max(...deps.map(getDepth)) + 1;
580
+ const depKeys = deps
581
+ .map(dep => roadmapSprintKeyFromId(roadmap, dep))
582
+ .filter((dep) => dep !== null);
583
+ const depth = depKeys.length === 0 ? 0 : Math.max(...depKeys.map(getDepth)) + 1;
511
584
  depthMap.set(id, depth);
512
585
  return depth;
513
586
  }
514
587
  for (const sprint of sprints) {
515
- getDepth(sprint.id);
588
+ getDepth(roadmapSprintKey(roadmap, sprint));
516
589
  }
517
590
  return depthMap;
518
591
  }
@@ -580,29 +653,30 @@ export function formatRoadmapSummary(roadmap) {
580
653
  lines.push('');
581
654
  // Phases
582
655
  for (const phase of roadmap.phases) {
583
- const phaseSprintIds = phase.sprints;
584
- const phaseSprints = roadmap.sprints.filter(s => phaseSprintIds.includes(s.id));
656
+ const phaseSprintIds = phase.sprint_keys ?? phase.sprints;
657
+ const phaseSprintKeys = new Set(phaseSprintIds.map(id => roadmapSprintKeyFromId(roadmap, id)));
658
+ const phaseSprints = roadmap.sprints.filter(sprint => phaseSprintKeys.has(roadmapSprintKey(roadmap, sprint)));
585
659
  lines.push(`## ${phase.name}`);
586
660
  lines.push('');
587
661
  for (const sprint of phaseSprints) {
588
662
  const deps = sprint.depends_on?.length
589
- ? ` (depends on: ${sprint.depends_on.map(formatSprintLabel).join(', ')})`
663
+ ? ` (depends on: ${sprint.depends_on.map(id => formatRoadmapSprintLabel(roadmap, id)).join(', ')})`
590
664
  : ' (no dependencies)';
591
- lines.push(`- **${formatSprintLabel(sprint.id)}** — ${sprint.theme} | Par ${sprint.par} | ${sprint.tickets.length} tickets${deps}`);
665
+ lines.push(`- **${formatRoadmapSprintLabel(roadmap, roadmapSprintKey(roadmap, sprint))}** — ${sprint.theme} | Par ${sprint.par} | ${sprint.tickets.length} tickets${deps}`);
592
666
  }
593
667
  lines.push('');
594
668
  }
595
669
  // Critical path
596
670
  lines.push('## Critical Path');
597
671
  lines.push('');
598
- lines.push(`${criticalPath.path.map(formatSprintLabel).join(' → ')} (${criticalPath.length} sprints, par ${criticalPath.totalPar})`);
672
+ lines.push(`${criticalPath.path.map(id => formatRoadmapSprintLabel(roadmap, id)).join(' → ')} (${criticalPath.length} sprints, par ${criticalPath.totalPar})`);
599
673
  lines.push('');
600
674
  // Parallel opportunities
601
675
  if (parallelGroups.length > 0) {
602
676
  lines.push('## Parallel Opportunities');
603
677
  lines.push('');
604
678
  for (const group of parallelGroups) {
605
- lines.push(`- ${group.sprints.map(formatSprintLabel).join(', ')}: ${group.reason}`);
679
+ lines.push(`- ${group.sprints.map(id => formatRoadmapSprintLabel(roadmap, id)).join(', ')}: ${group.reason}`);
606
680
  }
607
681
  lines.push('');
608
682
  }
@@ -617,21 +691,23 @@ export function formatRoadmapSummary(roadmap) {
617
691
  }
618
692
  /** Format strategic context for briefings — concise 3-5 line summary */
619
693
  export function formatStrategicContext(roadmap, currentSprint) {
620
- const currentOrder = roadmapSprintOrderValue(roadmap, currentSprint);
621
- const sprint = roadmap.sprints.find(s => roadmapSprintOrderValue(roadmap, s.id) === currentOrder);
694
+ const sprint = findRoadmapSprint(roadmap, currentSprint);
622
695
  if (!sprint)
623
696
  return null;
624
- const resolvedSprint = sprint.id;
697
+ const resolvedSprint = roadmapSprintKey(roadmap, sprint);
625
698
  const criticalPath = computeCriticalPath(roadmap);
626
- const onCriticalPath = criticalPath.path.some(id => roadmapSprintOrderValue(roadmap, id) === currentOrder);
699
+ const onCriticalPath = criticalPath.path.includes(resolvedSprint);
627
700
  const totalSprints = roadmap.sprints.length;
628
- const sprintIndex = roadmap.sprints.findIndex(s => s.id === resolvedSprint) + 1;
701
+ const sprintIndex = roadmap.sprints.findIndex(s => roadmapSprintKey(roadmap, s) === resolvedSprint) + 1;
629
702
  // Find which phase this sprint belongs to
630
- const phase = roadmap.phases.find(p => p.sprints.some(id => roadmapSprintOrderValue(roadmap, id) === currentOrder));
703
+ const phase = roadmap.phases.find(p => {
704
+ const keys = p.sprint_keys ?? p.sprints;
705
+ return keys.some(id => roadmapSprintKeyFromId(roadmap, id) === resolvedSprint);
706
+ });
631
707
  // Find what depends on this sprint
632
708
  const dependents = roadmap.sprints
633
- .filter(s => s.depends_on?.some(id => roadmapSprintOrderValue(roadmap, id) === currentOrder))
634
- .map(s => formatRoadmapSprintLabel(roadmap, s.id));
709
+ .filter(s => s.depends_on?.some(id => roadmapSprintKeyFromId(roadmap, id) === resolvedSprint))
710
+ .map(s => formatRoadmapSprintLabel(roadmap, roadmapSprintKey(roadmap, s)));
635
711
  const lines = [];
636
712
  lines.push(`Sprint ${sprintIndex} of ${totalSprints} — ${formatRoadmapSprintLabel(roadmap, resolvedSprint)}: ${sprint.theme}`);
637
713
  if (phase) {
@@ -648,14 +724,13 @@ export function formatStrategicContext(roadmap, currentSprint) {
648
724
  if (next) {
649
725
  const blockers = (next.depends_on ?? [])
650
726
  .filter(d => {
651
- const depOrder = roadmapSprintOrderValue(roadmap, d);
652
- const dep = roadmap.sprints.find(s => roadmapSprintOrderValue(roadmap, s.id) === depOrder);
727
+ const dep = findRoadmapSprint(roadmap, d);
653
728
  return !dep || dep.status !== 'complete';
654
729
  });
655
730
  const status = blockers.length === 0
656
731
  ? 'ready'
657
732
  : `blocked by ${blockers.map(id => formatRoadmapSprintLabel(roadmap, id)).join(', ')}`;
658
- lines.push(`Next: ${formatRoadmapSprintLabel(roadmap, next.id)}: ${next.theme} (${status})`);
733
+ lines.push(`Next: ${formatRoadmapSprintLabel(roadmap, roadmapSprintKey(roadmap, next))}: ${next.theme} (${status})`);
659
734
  }
660
735
  return lines.join('\n');
661
736
  }
@@ -665,19 +740,25 @@ export function formatStrategicContext(roadmap, currentSprint) {
665
740
  * Returns null if no candidate found.
666
741
  */
667
742
  export function findNextPlannedSprint(roadmap, currentSprint) {
668
- const currentOrder = roadmapSprintOrderValue(roadmap, currentSprint);
743
+ const currentKey = roadmapSprintKeyFromId(roadmap, currentSprint);
744
+ if (currentKey === null)
745
+ return null;
669
746
  const candidates = roadmap.sprints
670
747
  .filter(s => {
671
- return isRoadmapSprintPending(s) && roadmapSprintOrderValue(roadmap, s.id) > currentOrder;
748
+ return isRoadmapSprintPending(s)
749
+ && compareSprintIdKeys(roadmapSprintKey(roadmap, s), currentKey) > 0;
672
750
  })
673
- .sort((a, b) => compareRoadmapSprintIds(roadmap, a.id, b.id));
751
+ .sort((a, b) => compareSprintIdKeys(roadmapSprintKey(roadmap, a), roadmapSprintKey(roadmap, b)));
674
752
  if (candidates.length === 0)
675
753
  return null;
676
754
  const completedIds = new Set(roadmap.sprints
677
755
  .filter(s => s.status === 'complete')
678
- .map(s => roadmapSprintOrderValue(roadmap, s.id)));
756
+ .map(s => roadmapSprintKey(roadmap, s)));
679
757
  // Prefer the lowest-id candidate whose dependencies are all complete
680
- const ready = candidates.find(s => (s.depends_on ?? []).every(d => completedIds.has(roadmapSprintOrderValue(roadmap, d))));
758
+ const ready = candidates.find(s => (s.depends_on ?? []).every(d => {
759
+ const key = roadmapSprintKeyFromId(roadmap, d);
760
+ return key !== null && completedIds.has(key);
761
+ }));
681
762
  return ready ?? candidates[0];
682
763
  }
683
764
  //# sourceMappingURL=roadmap.js.map