@slope-dev/slope 1.5.1

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 (395) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +243 -0
  3. package/dist/cli/commands/auto-card.d.ts +2 -0
  4. package/dist/cli/commands/auto-card.d.ts.map +1 -0
  5. package/dist/cli/commands/auto-card.js +267 -0
  6. package/dist/cli/commands/auto-card.js.map +1 -0
  7. package/dist/cli/commands/briefing.d.ts +2 -0
  8. package/dist/cli/commands/briefing.d.ts.map +1 -0
  9. package/dist/cli/commands/briefing.js +133 -0
  10. package/dist/cli/commands/briefing.js.map +1 -0
  11. package/dist/cli/commands/card.d.ts +2 -0
  12. package/dist/cli/commands/card.d.ts.map +1 -0
  13. package/dist/cli/commands/card.js +144 -0
  14. package/dist/cli/commands/card.js.map +1 -0
  15. package/dist/cli/commands/claim.d.ts +2 -0
  16. package/dist/cli/commands/claim.d.ts.map +1 -0
  17. package/dist/cli/commands/claim.js +99 -0
  18. package/dist/cli/commands/claim.js.map +1 -0
  19. package/dist/cli/commands/classify.d.ts +2 -0
  20. package/dist/cli/commands/classify.d.ts.map +1 -0
  21. package/dist/cli/commands/classify.js +70 -0
  22. package/dist/cli/commands/classify.js.map +1 -0
  23. package/dist/cli/commands/dashboard.d.ts +4 -0
  24. package/dist/cli/commands/dashboard.d.ts.map +1 -0
  25. package/dist/cli/commands/dashboard.js +156 -0
  26. package/dist/cli/commands/dashboard.js.map +1 -0
  27. package/dist/cli/commands/distill.d.ts +2 -0
  28. package/dist/cli/commands/distill.d.ts.map +1 -0
  29. package/dist/cli/commands/distill.js +91 -0
  30. package/dist/cli/commands/distill.js.map +1 -0
  31. package/dist/cli/commands/escalate.d.ts +2 -0
  32. package/dist/cli/commands/escalate.d.ts.map +1 -0
  33. package/dist/cli/commands/escalate.js +136 -0
  34. package/dist/cli/commands/escalate.js.map +1 -0
  35. package/dist/cli/commands/extract.d.ts +2 -0
  36. package/dist/cli/commands/extract.d.ts.map +1 -0
  37. package/dist/cli/commands/extract.js +147 -0
  38. package/dist/cli/commands/extract.js.map +1 -0
  39. package/dist/cli/commands/flows.d.ts +2 -0
  40. package/dist/cli/commands/flows.d.ts.map +1 -0
  41. package/dist/cli/commands/flows.js +156 -0
  42. package/dist/cli/commands/flows.js.map +1 -0
  43. package/dist/cli/commands/guard.d.ts +15 -0
  44. package/dist/cli/commands/guard.d.ts.map +1 -0
  45. package/dist/cli/commands/guard.js +207 -0
  46. package/dist/cli/commands/guard.js.map +1 -0
  47. package/dist/cli/commands/hook.d.ts +2 -0
  48. package/dist/cli/commands/hook.d.ts.map +1 -0
  49. package/dist/cli/commands/hook.js +299 -0
  50. package/dist/cli/commands/hook.js.map +1 -0
  51. package/dist/cli/commands/init.d.ts +6 -0
  52. package/dist/cli/commands/init.d.ts.map +1 -0
  53. package/dist/cli/commands/init.js +421 -0
  54. package/dist/cli/commands/init.js.map +1 -0
  55. package/dist/cli/commands/map.d.ts +10 -0
  56. package/dist/cli/commands/map.d.ts.map +1 -0
  57. package/dist/cli/commands/map.js +591 -0
  58. package/dist/cli/commands/map.js.map +1 -0
  59. package/dist/cli/commands/next.d.ts +2 -0
  60. package/dist/cli/commands/next.d.ts.map +1 -0
  61. package/dist/cli/commands/next.js +28 -0
  62. package/dist/cli/commands/next.js.map +1 -0
  63. package/dist/cli/commands/plan.d.ts +2 -0
  64. package/dist/cli/commands/plan.d.ts.map +1 -0
  65. package/dist/cli/commands/plan.js +54 -0
  66. package/dist/cli/commands/plan.js.map +1 -0
  67. package/dist/cli/commands/plugin.d.ts +2 -0
  68. package/dist/cli/commands/plugin.d.ts.map +1 -0
  69. package/dist/cli/commands/plugin.js +118 -0
  70. package/dist/cli/commands/plugin.js.map +1 -0
  71. package/dist/cli/commands/release.d.ts +2 -0
  72. package/dist/cli/commands/release.d.ts.map +1 -0
  73. package/dist/cli/commands/release.js +64 -0
  74. package/dist/cli/commands/release.js.map +1 -0
  75. package/dist/cli/commands/report.d.ts +2 -0
  76. package/dist/cli/commands/report.d.ts.map +1 -0
  77. package/dist/cli/commands/report.js +68 -0
  78. package/dist/cli/commands/report.js.map +1 -0
  79. package/dist/cli/commands/review-state.d.ts +11 -0
  80. package/dist/cli/commands/review-state.d.ts.map +1 -0
  81. package/dist/cli/commands/review-state.js +193 -0
  82. package/dist/cli/commands/review-state.js.map +1 -0
  83. package/dist/cli/commands/review.d.ts +2 -0
  84. package/dist/cli/commands/review.d.ts.map +1 -0
  85. package/dist/cli/commands/review.js +53 -0
  86. package/dist/cli/commands/review.js.map +1 -0
  87. package/dist/cli/commands/roadmap.d.ts +2 -0
  88. package/dist/cli/commands/roadmap.d.ts.map +1 -0
  89. package/dist/cli/commands/roadmap.js +283 -0
  90. package/dist/cli/commands/roadmap.js.map +1 -0
  91. package/dist/cli/commands/session.d.ts +2 -0
  92. package/dist/cli/commands/session.d.ts.map +1 -0
  93. package/dist/cli/commands/session.js +232 -0
  94. package/dist/cli/commands/session.js.map +1 -0
  95. package/dist/cli/commands/standup.d.ts +2 -0
  96. package/dist/cli/commands/standup.d.ts.map +1 -0
  97. package/dist/cli/commands/standup.js +117 -0
  98. package/dist/cli/commands/standup.js.map +1 -0
  99. package/dist/cli/commands/status.d.ts +2 -0
  100. package/dist/cli/commands/status.d.ts.map +1 -0
  101. package/dist/cli/commands/status.js +148 -0
  102. package/dist/cli/commands/status.js.map +1 -0
  103. package/dist/cli/commands/tournament.d.ts +2 -0
  104. package/dist/cli/commands/tournament.d.ts.map +1 -0
  105. package/dist/cli/commands/tournament.js +60 -0
  106. package/dist/cli/commands/tournament.js.map +1 -0
  107. package/dist/cli/commands/validate.d.ts +2 -0
  108. package/dist/cli/commands/validate.d.ts.map +1 -0
  109. package/dist/cli/commands/validate.js +74 -0
  110. package/dist/cli/commands/validate.js.map +1 -0
  111. package/dist/cli/config.d.ts +2 -0
  112. package/dist/cli/config.d.ts.map +1 -0
  113. package/dist/cli/config.js +2 -0
  114. package/dist/cli/config.js.map +1 -0
  115. package/dist/cli/guards/commit-nudge.d.ts +7 -0
  116. package/dist/cli/guards/commit-nudge.d.ts.map +1 -0
  117. package/dist/cli/guards/commit-nudge.js +50 -0
  118. package/dist/cli/guards/commit-nudge.js.map +1 -0
  119. package/dist/cli/guards/compaction.d.ts +8 -0
  120. package/dist/cli/guards/compaction.d.ts.map +1 -0
  121. package/dist/cli/guards/compaction.js +79 -0
  122. package/dist/cli/guards/compaction.js.map +1 -0
  123. package/dist/cli/guards/explore.d.ts +8 -0
  124. package/dist/cli/guards/explore.d.ts.map +1 -0
  125. package/dist/cli/guards/explore.js +78 -0
  126. package/dist/cli/guards/explore.js.map +1 -0
  127. package/dist/cli/guards/hazard.d.ts +7 -0
  128. package/dist/cli/guards/hazard.d.ts.map +1 -0
  129. package/dist/cli/guards/hazard.js +43 -0
  130. package/dist/cli/guards/hazard.js.map +1 -0
  131. package/dist/cli/guards/next-action.d.ts +28 -0
  132. package/dist/cli/guards/next-action.d.ts.map +1 -0
  133. package/dist/cli/guards/next-action.js +196 -0
  134. package/dist/cli/guards/next-action.js.map +1 -0
  135. package/dist/cli/guards/push-nudge.d.ts +7 -0
  136. package/dist/cli/guards/push-nudge.d.ts.map +1 -0
  137. package/dist/cli/guards/push-nudge.js +53 -0
  138. package/dist/cli/guards/push-nudge.js.map +1 -0
  139. package/dist/cli/guards/review-tier.d.ts +7 -0
  140. package/dist/cli/guards/review-tier.d.ts.map +1 -0
  141. package/dist/cli/guards/review-tier.js +108 -0
  142. package/dist/cli/guards/review-tier.js.map +1 -0
  143. package/dist/cli/guards/scope-drift.d.ts +7 -0
  144. package/dist/cli/guards/scope-drift.d.ts.map +1 -0
  145. package/dist/cli/guards/scope-drift.js +47 -0
  146. package/dist/cli/guards/scope-drift.js.map +1 -0
  147. package/dist/cli/guards/stop-check.d.ts +7 -0
  148. package/dist/cli/guards/stop-check.d.ts.map +1 -0
  149. package/dist/cli/guards/stop-check.js +34 -0
  150. package/dist/cli/guards/stop-check.js.map +1 -0
  151. package/dist/cli/guards/subagent-gate.d.ts +7 -0
  152. package/dist/cli/guards/subagent-gate.d.ts.map +1 -0
  153. package/dist/cli/guards/subagent-gate.js +39 -0
  154. package/dist/cli/guards/subagent-gate.js.map +1 -0
  155. package/dist/cli/guards/version-check.d.ts +8 -0
  156. package/dist/cli/guards/version-check.d.ts.map +1 -0
  157. package/dist/cli/guards/version-check.js +49 -0
  158. package/dist/cli/guards/version-check.js.map +1 -0
  159. package/dist/cli/guards/workflow-gate.d.ts +7 -0
  160. package/dist/cli/guards/workflow-gate.d.ts.map +1 -0
  161. package/dist/cli/guards/workflow-gate.js +31 -0
  162. package/dist/cli/guards/workflow-gate.js.map +1 -0
  163. package/dist/cli/hooks-config.d.ts +9 -0
  164. package/dist/cli/hooks-config.d.ts.map +1 -0
  165. package/dist/cli/hooks-config.js +21 -0
  166. package/dist/cli/hooks-config.js.map +1 -0
  167. package/dist/cli/index.d.ts +19 -0
  168. package/dist/cli/index.d.ts.map +1 -0
  169. package/dist/cli/index.js +282 -0
  170. package/dist/cli/index.js.map +1 -0
  171. package/dist/cli/loader.d.ts +2 -0
  172. package/dist/cli/loader.d.ts.map +1 -0
  173. package/dist/cli/loader.js +2 -0
  174. package/dist/cli/loader.js.map +1 -0
  175. package/dist/cli/metaphor.d.ts +6 -0
  176. package/dist/cli/metaphor.d.ts.map +1 -0
  177. package/dist/cli/metaphor.js +26 -0
  178. package/dist/cli/metaphor.js.map +1 -0
  179. package/dist/cli/registries/api-registry.d.ts +11 -0
  180. package/dist/cli/registries/api-registry.d.ts.map +1 -0
  181. package/dist/cli/registries/api-registry.js +42 -0
  182. package/dist/cli/registries/api-registry.js.map +1 -0
  183. package/dist/cli/registries/file-registry.d.ts +13 -0
  184. package/dist/cli/registries/file-registry.d.ts.map +1 -0
  185. package/dist/cli/registries/file-registry.js +55 -0
  186. package/dist/cli/registries/file-registry.js.map +1 -0
  187. package/dist/cli/registries/index.d.ts +7 -0
  188. package/dist/cli/registries/index.d.ts.map +1 -0
  189. package/dist/cli/registries/index.js +20 -0
  190. package/dist/cli/registries/index.js.map +1 -0
  191. package/dist/cli/store.d.ts +3 -0
  192. package/dist/cli/store.d.ts.map +1 -0
  193. package/dist/cli/store.js +13 -0
  194. package/dist/cli/store.js.map +1 -0
  195. package/dist/cli/template-generator.d.ts +15 -0
  196. package/dist/cli/template-generator.d.ts.map +1 -0
  197. package/dist/cli/template-generator.js +562 -0
  198. package/dist/cli/template-generator.js.map +1 -0
  199. package/dist/core/advisor.d.ts +63 -0
  200. package/dist/core/advisor.d.ts.map +1 -0
  201. package/dist/core/advisor.js +395 -0
  202. package/dist/core/advisor.js.map +1 -0
  203. package/dist/core/briefing.d.ts +103 -0
  204. package/dist/core/briefing.d.ts.map +1 -0
  205. package/dist/core/briefing.js +380 -0
  206. package/dist/core/briefing.js.map +1 -0
  207. package/dist/core/builder.d.ts +70 -0
  208. package/dist/core/builder.d.ts.map +1 -0
  209. package/dist/core/builder.js +175 -0
  210. package/dist/core/builder.js.map +1 -0
  211. package/dist/core/ci-signals.d.ts +10 -0
  212. package/dist/core/ci-signals.d.ts.map +1 -0
  213. package/dist/core/ci-signals.js +145 -0
  214. package/dist/core/ci-signals.js.map +1 -0
  215. package/dist/core/config.d.ts +48 -0
  216. package/dist/core/config.d.ts.map +1 -0
  217. package/dist/core/config.js +42 -0
  218. package/dist/core/config.js.map +1 -0
  219. package/dist/core/constants.d.ts +14 -0
  220. package/dist/core/constants.d.ts.map +1 -0
  221. package/dist/core/constants.js +44 -0
  222. package/dist/core/constants.js.map +1 -0
  223. package/dist/core/dashboard.d.ts +40 -0
  224. package/dist/core/dashboard.d.ts.map +1 -0
  225. package/dist/core/dashboard.js +413 -0
  226. package/dist/core/dashboard.js.map +1 -0
  227. package/dist/core/dispersion.d.ts +12 -0
  228. package/dist/core/dispersion.d.ts.map +1 -0
  229. package/dist/core/dispersion.js +164 -0
  230. package/dist/core/dispersion.js.map +1 -0
  231. package/dist/core/escalation.d.ts +52 -0
  232. package/dist/core/escalation.d.ts.map +1 -0
  233. package/dist/core/escalation.js +105 -0
  234. package/dist/core/escalation.js.map +1 -0
  235. package/dist/core/flows.d.ts +44 -0
  236. package/dist/core/flows.d.ts.map +1 -0
  237. package/dist/core/flows.js +123 -0
  238. package/dist/core/flows.js.map +1 -0
  239. package/dist/core/formatter.d.ts +23 -0
  240. package/dist/core/formatter.d.ts.map +1 -0
  241. package/dist/core/formatter.js +301 -0
  242. package/dist/core/formatter.js.map +1 -0
  243. package/dist/core/guard.d.ts +124 -0
  244. package/dist/core/guard.d.ts.map +1 -0
  245. package/dist/core/guard.js +185 -0
  246. package/dist/core/guard.js.map +1 -0
  247. package/dist/core/handicap.d.ts +22 -0
  248. package/dist/core/handicap.d.ts.map +1 -0
  249. package/dist/core/handicap.js +111 -0
  250. package/dist/core/handicap.js.map +1 -0
  251. package/dist/core/index.d.ts +55 -0
  252. package/dist/core/index.d.ts.map +1 -0
  253. package/dist/core/index.js +62 -0
  254. package/dist/core/index.js.map +1 -0
  255. package/dist/core/leaderboard.d.ts +32 -0
  256. package/dist/core/leaderboard.d.ts.map +1 -0
  257. package/dist/core/leaderboard.js +98 -0
  258. package/dist/core/leaderboard.js.map +1 -0
  259. package/dist/core/loader.d.ts +17 -0
  260. package/dist/core/loader.d.ts.map +1 -0
  261. package/dist/core/loader.js +68 -0
  262. package/dist/core/loader.js.map +1 -0
  263. package/dist/core/metaphor.d.ts +73 -0
  264. package/dist/core/metaphor.d.ts.map +1 -0
  265. package/dist/core/metaphor.js +73 -0
  266. package/dist/core/metaphor.js.map +1 -0
  267. package/dist/core/metaphors/baseball.d.ts +3 -0
  268. package/dist/core/metaphors/baseball.d.ts.map +1 -0
  269. package/dist/core/metaphors/baseball.js +89 -0
  270. package/dist/core/metaphors/baseball.js.map +1 -0
  271. package/dist/core/metaphors/dnd.d.ts +3 -0
  272. package/dist/core/metaphors/dnd.d.ts.map +1 -0
  273. package/dist/core/metaphors/dnd.js +89 -0
  274. package/dist/core/metaphors/dnd.js.map +1 -0
  275. package/dist/core/metaphors/gaming.d.ts +3 -0
  276. package/dist/core/metaphors/gaming.d.ts.map +1 -0
  277. package/dist/core/metaphors/gaming.js +89 -0
  278. package/dist/core/metaphors/gaming.js.map +1 -0
  279. package/dist/core/metaphors/golf.d.ts +3 -0
  280. package/dist/core/metaphors/golf.d.ts.map +1 -0
  281. package/dist/core/metaphors/golf.js +89 -0
  282. package/dist/core/metaphors/golf.js.map +1 -0
  283. package/dist/core/metaphors/index.d.ts +8 -0
  284. package/dist/core/metaphors/index.d.ts.map +1 -0
  285. package/dist/core/metaphors/index.js +17 -0
  286. package/dist/core/metaphors/index.js.map +1 -0
  287. package/dist/core/metaphors/matrix.d.ts +3 -0
  288. package/dist/core/metaphors/matrix.d.ts.map +1 -0
  289. package/dist/core/metaphors/matrix.js +89 -0
  290. package/dist/core/metaphors/matrix.js.map +1 -0
  291. package/dist/core/metaphors/tennis.d.ts +3 -0
  292. package/dist/core/metaphors/tennis.d.ts.map +1 -0
  293. package/dist/core/metaphors/tennis.js +89 -0
  294. package/dist/core/metaphors/tennis.js.map +1 -0
  295. package/dist/core/pipeline.d.ts +39 -0
  296. package/dist/core/pipeline.d.ts.map +1 -0
  297. package/dist/core/pipeline.js +158 -0
  298. package/dist/core/pipeline.js.map +1 -0
  299. package/dist/core/player.d.ts +51 -0
  300. package/dist/core/player.d.ts.map +1 -0
  301. package/dist/core/player.js +101 -0
  302. package/dist/core/player.js.map +1 -0
  303. package/dist/core/plugins.d.ts +33 -0
  304. package/dist/core/plugins.d.ts.map +1 -0
  305. package/dist/core/plugins.js +176 -0
  306. package/dist/core/plugins.js.map +1 -0
  307. package/dist/core/pr-signals.d.ts +23 -0
  308. package/dist/core/pr-signals.d.ts.map +1 -0
  309. package/dist/core/pr-signals.js +178 -0
  310. package/dist/core/pr-signals.js.map +1 -0
  311. package/dist/core/registry.d.ts +20 -0
  312. package/dist/core/registry.d.ts.map +1 -0
  313. package/dist/core/registry.js +62 -0
  314. package/dist/core/registry.js.map +1 -0
  315. package/dist/core/report.d.ts +50 -0
  316. package/dist/core/report.d.ts.map +1 -0
  317. package/dist/core/report.js +392 -0
  318. package/dist/core/report.js.map +1 -0
  319. package/dist/core/roadmap.d.ts +74 -0
  320. package/dist/core/roadmap.d.ts.map +1 -0
  321. package/dist/core/roadmap.js +389 -0
  322. package/dist/core/roadmap.js.map +1 -0
  323. package/dist/core/roles.d.ts +23 -0
  324. package/dist/core/roles.d.ts.map +1 -0
  325. package/dist/core/roles.js +107 -0
  326. package/dist/core/roles.js.map +1 -0
  327. package/dist/core/standup.d.ts +44 -0
  328. package/dist/core/standup.d.ts.map +1 -0
  329. package/dist/core/standup.js +164 -0
  330. package/dist/core/standup.js.map +1 -0
  331. package/dist/core/store.d.ts +43 -0
  332. package/dist/core/store.d.ts.map +1 -0
  333. package/dist/core/store.js +11 -0
  334. package/dist/core/store.js.map +1 -0
  335. package/dist/core/team-handicap.d.ts +59 -0
  336. package/dist/core/team-handicap.d.ts.map +1 -0
  337. package/dist/core/team-handicap.js +227 -0
  338. package/dist/core/team-handicap.js.map +1 -0
  339. package/dist/core/tournament.d.ts +12 -0
  340. package/dist/core/tournament.d.ts.map +1 -0
  341. package/dist/core/tournament.js +249 -0
  342. package/dist/core/tournament.js.map +1 -0
  343. package/dist/core/types.d.ts +339 -0
  344. package/dist/core/types.d.ts.map +1 -0
  345. package/dist/core/types.js +4 -0
  346. package/dist/core/types.js.map +1 -0
  347. package/dist/core/validation.d.ts +23 -0
  348. package/dist/core/validation.d.ts.map +1 -0
  349. package/dist/core/validation.js +140 -0
  350. package/dist/core/validation.js.map +1 -0
  351. package/dist/index.d.ts +4 -0
  352. package/dist/index.d.ts.map +1 -0
  353. package/dist/index.js +9 -0
  354. package/dist/index.js.map +1 -0
  355. package/dist/mcp/index.d.ts +17 -0
  356. package/dist/mcp/index.d.ts.map +1 -0
  357. package/dist/mcp/index.js +363 -0
  358. package/dist/mcp/index.js.map +1 -0
  359. package/dist/mcp/index.test.d.ts +2 -0
  360. package/dist/mcp/index.test.d.ts.map +1 -0
  361. package/dist/mcp/index.test.js +497 -0
  362. package/dist/mcp/index.test.js.map +1 -0
  363. package/dist/mcp/registry.d.ts +17 -0
  364. package/dist/mcp/registry.d.ts.map +1 -0
  365. package/dist/mcp/registry.js +708 -0
  366. package/dist/mcp/registry.js.map +1 -0
  367. package/dist/mcp/sandbox.d.ts +15 -0
  368. package/dist/mcp/sandbox.d.ts.map +1 -0
  369. package/dist/mcp/sandbox.js +153 -0
  370. package/dist/mcp/sandbox.js.map +1 -0
  371. package/dist/store/index.d.ts +40 -0
  372. package/dist/store/index.d.ts.map +1 -0
  373. package/dist/store/index.js +324 -0
  374. package/dist/store/index.js.map +1 -0
  375. package/dist/tokens/colors.d.ts +47 -0
  376. package/dist/tokens/colors.d.ts.map +1 -0
  377. package/dist/tokens/colors.js +56 -0
  378. package/dist/tokens/colors.js.map +1 -0
  379. package/dist/tokens/css.d.ts +3 -0
  380. package/dist/tokens/css.d.ts.map +1 -0
  381. package/dist/tokens/css.js +58 -0
  382. package/dist/tokens/css.js.map +1 -0
  383. package/dist/tokens/index.d.ts +5 -0
  384. package/dist/tokens/index.d.ts.map +1 -0
  385. package/dist/tokens/index.js +6 -0
  386. package/dist/tokens/index.js.map +1 -0
  387. package/dist/tokens/spacing.d.ts +23 -0
  388. package/dist/tokens/spacing.d.ts.map +1 -0
  389. package/dist/tokens/spacing.js +28 -0
  390. package/dist/tokens/spacing.js.map +1 -0
  391. package/dist/tokens/typography.d.ts +28 -0
  392. package/dist/tokens/typography.d.ts.map +1 -0
  393. package/dist/tokens/typography.js +34 -0
  394. package/dist/tokens/typography.js.map +1 -0
  395. package/package.json +69 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compaction.js","sourceRoot":"","sources":["../../../src/cli/guards/compaction.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { HookInput, GuardResult } from '../../core/index.js';
2
+ /**
3
+ * Explore guard: fires on Read|Glob|Grep (PreToolUse).
4
+ * Suggests checking codebase map before deep exploration.
5
+ * Includes staleness awareness when CODEBASE.md has YAML frontmatter.
6
+ */
7
+ export declare function exploreGuard(input: HookInput, cwd: string): Promise<GuardResult>;
8
+ //# sourceMappingURL=explore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explore.d.ts","sourceRoot":"","sources":["../../../src/cli/guards/explore.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAKlE;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAyCtF"}
@@ -0,0 +1,78 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { execSync } from 'node:child_process';
4
+ import { loadConfig } from '../config.js';
5
+ const DEFAULT_INDEX_PATHS = ['CODEBASE.md', '.slope/index.json', 'docs/architecture.md'];
6
+ /**
7
+ * Explore guard: fires on Read|Glob|Grep (PreToolUse).
8
+ * Suggests checking codebase map before deep exploration.
9
+ * Includes staleness awareness when CODEBASE.md has YAML frontmatter.
10
+ */
11
+ export async function exploreGuard(input, cwd) {
12
+ const config = loadConfig();
13
+ const indexPaths = config.guidance?.indexPaths ?? DEFAULT_INDEX_PATHS;
14
+ // Find which index files exist
15
+ const found = [];
16
+ for (const p of indexPaths) {
17
+ const full = join(cwd, p);
18
+ if (existsSync(full)) {
19
+ found.push(p);
20
+ }
21
+ }
22
+ if (found.length === 0) {
23
+ return {}; // No index — passthrough
24
+ }
25
+ // Check if CODEBASE.md exists and assess staleness
26
+ const mapPath = join(cwd, 'CODEBASE.md');
27
+ if (existsSync(mapPath)) {
28
+ const staleness = checkMapStaleness(mapPath, cwd);
29
+ if (staleness === 'stale') {
30
+ return {
31
+ context: `SLOPE: Codebase map at CODEBASE.md is stale (${getStalenessDetail(mapPath, cwd)}). Run 'slope map' to refresh, or explore if needed.`,
32
+ };
33
+ }
34
+ // Current map — estimate token size
35
+ const content = readFileSync(mapPath, 'utf8');
36
+ const approxTokens = Math.round(content.length / 4 / 1000);
37
+ return {
38
+ context: `SLOPE: Codebase map at CODEBASE.md (~${approxTokens}k tokens). Read it or use search({ module: 'map' }) before exploring.`,
39
+ };
40
+ }
41
+ // Fallback: other index files found but no CODEBASE.md
42
+ return {
43
+ context: `SLOPE: Codebase index available at: ${found.join(', ')} — check before deep exploration.`,
44
+ };
45
+ }
46
+ function checkMapStaleness(mapPath, cwd) {
47
+ try {
48
+ const content = readFileSync(mapPath, 'utf8');
49
+ const metaMatch = content.match(/^---\n([\s\S]*?)\n---/m);
50
+ if (!metaMatch)
51
+ return 'current'; // No metadata — can't check
52
+ const gitShaMatch = metaMatch[1].match(/git_sha:\s*"?([^"\n]+)"?/);
53
+ if (!gitShaMatch)
54
+ return 'current';
55
+ const distance = parseInt(execSync(`git rev-list --count ${gitShaMatch[1]}..HEAD 2>/dev/null`, { cwd, encoding: 'utf8', timeout: 5000 }).trim() || '0', 10);
56
+ return distance > 50 ? 'stale' : 'current';
57
+ }
58
+ catch {
59
+ return 'current'; // Can't determine — assume current
60
+ }
61
+ }
62
+ function getStalenessDetail(mapPath, cwd) {
63
+ try {
64
+ const content = readFileSync(mapPath, 'utf8');
65
+ const metaMatch = content.match(/^---\n([\s\S]*?)\n---/m);
66
+ if (!metaMatch)
67
+ return 'unknown';
68
+ const gitShaMatch = metaMatch[1].match(/git_sha:\s*"?([^"\n]+)"?/);
69
+ if (!gitShaMatch)
70
+ return 'unknown';
71
+ const distance = execSync(`git rev-list --count ${gitShaMatch[1]}..HEAD 2>/dev/null`, { cwd, encoding: 'utf8', timeout: 5000 }).trim();
72
+ return `${distance} commits behind`;
73
+ }
74
+ catch {
75
+ return 'unknown';
76
+ }
77
+ }
78
+ //# sourceMappingURL=explore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"explore.js","sourceRoot":"","sources":["../../../src/cli/guards/explore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { HookInput, GuardResult } from '../../core/index.js';
2
+ /**
3
+ * Hazard guard: fires on Edit|Write (PreToolUse).
4
+ * Warns about known issues in the file area being edited.
5
+ */
6
+ export declare function hazardGuard(input: HookInput, cwd: string): Promise<GuardResult>;
7
+ //# sourceMappingURL=hazard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hazard.d.ts","sourceRoot":"","sources":["../../../src/cli/guards/hazard.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAIlE;;;GAGG;AACH,wBAAsB,WAAW,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAqCrF"}
@@ -0,0 +1,43 @@
1
+ import { readFileSync, existsSync } from 'node:fs';
2
+ import { join, dirname } from 'node:path';
3
+ import { loadConfig } from '../config.js';
4
+ /**
5
+ * Hazard guard: fires on Edit|Write (PreToolUse).
6
+ * Warns about known issues in the file area being edited.
7
+ */
8
+ export async function hazardGuard(input, cwd) {
9
+ const filePath = input.tool_input?.file_path;
10
+ if (!filePath)
11
+ return {};
12
+ const config = loadConfig();
13
+ const recency = config.guidance?.hazardRecency ?? 5;
14
+ // Determine the area from the file path (use directory)
15
+ const area = dirname(filePath).replace(cwd + '/', '').replace(cwd, '');
16
+ if (!area || area === '.')
17
+ return {};
18
+ // Load common issues and find matches
19
+ const warnings = [];
20
+ try {
21
+ const issuesPath = join(cwd, config.commonIssuesPath);
22
+ if (existsSync(issuesPath)) {
23
+ const issues = JSON.parse(readFileSync(issuesPath, 'utf8'));
24
+ const areaLower = area.toLowerCase();
25
+ for (const pattern of issues.recurring_patterns) {
26
+ // Check if pattern is relevant to this area
27
+ const text = `${pattern.title} ${pattern.description} ${pattern.prevention}`.toLowerCase();
28
+ if (text.includes(areaLower) || areaLower.split('/').some(seg => text.includes(seg))) {
29
+ const lastSprint = Math.max(...pattern.sprints_hit);
30
+ warnings.push(`[${pattern.category}] ${pattern.title} (last: S${lastSprint}) — ${pattern.prevention.slice(0, 100)}`);
31
+ }
32
+ }
33
+ }
34
+ }
35
+ catch { /* skip — common issues are optional */ }
36
+ if (warnings.length === 0)
37
+ return {};
38
+ const header = `SLOPE hazard warning for ${area}:`;
39
+ return {
40
+ context: [header, ...warnings.map(w => ` ${w}`)].join('\n'),
41
+ };
42
+ }
43
+ //# sourceMappingURL=hazard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hazard.js","sourceRoot":"","sources":["../../../src/cli/guards/hazard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,KAAgB,EAAE,GAAW;IAC7D,MAAM,QAAQ,GAAG,KAAK,CAAC,UAAU,EAAE,SAA+B,CAAC;IACnE,IAAI,CAAC,QAAQ;QAAE,OAAO,EAAE,CAAC;IAEzB,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,EAAE,aAAa,IAAI,CAAC,CAAC;IAEpD,wDAAwD;IACxD,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,GAAG,GAAG,GAAG,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACvE,IAAI,CAAC,IAAI,IAAI,IAAI,KAAK,GAAG;QAAE,OAAO,EAAE,CAAC;IAErC,sCAAsC;IACtC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAE9B,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,gBAAgB,CAAC,CAAC;QACtD,IAAI,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC3B,MAAM,MAAM,GAAqB,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;YAC9E,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;YAErC,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,kBAAkB,EAAE,CAAC;gBAChD,4CAA4C;gBAC5C,MAAM,IAAI,GAAG,GAAG,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,WAAW,EAAE,CAAC;gBAC3F,IAAI,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;oBACrF,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;oBACpD,QAAQ,CAAC,IAAI,CAAC,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,KAAK,YAAY,UAAU,OAAO,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;gBACvH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAC,uCAAuC,CAAC,CAAC;IAEnD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAErC,MAAM,MAAM,GAAG,4BAA4B,IAAI,GAAG,CAAC;IACnD,OAAO;QACL,OAAO,EAAE,CAAC,MAAM,EAAE,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;KAC7D,CAAC;AACJ,CAAC"}
@@ -0,0 +1,28 @@
1
+ import type { HookInput, GuardResult } from '../../core/index.js';
2
+ /** Sprint state types for next-action detection */
3
+ type SprintState = {
4
+ type: 'mid-sprint';
5
+ sprintNumber: number;
6
+ claimCount: number;
7
+ targets: string[];
8
+ } | {
9
+ type: 'sprint-complete';
10
+ sprintNumber: number;
11
+ } | {
12
+ type: 'needs-review';
13
+ sprintNumber: number;
14
+ } | {
15
+ type: 'between-sprints';
16
+ roadmapContext?: string;
17
+ };
18
+ /**
19
+ * Next-action guard: fires on Stop.
20
+ * Suggests next actions before session end based on sprint state.
21
+ */
22
+ export declare function nextActionGuard(input: HookInput, cwd: string): Promise<GuardResult>;
23
+ /** Detect current sprint state via store then filesystem fallback */
24
+ export declare function detectSprintState(cwd: string): Promise<SprintState>;
25
+ /** Build block reason text from sprint state */
26
+ export declare function buildSuggestions(state: SprintState): string;
27
+ export {};
28
+ //# sourceMappingURL=next-action.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"next-action.d.ts","sourceRoot":"","sources":["../../../src/cli/guards/next-action.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAe,MAAM,qBAAqB,CAAC;AAI/E,mDAAmD;AACnD,KAAK,WAAW,GACZ;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,GACnF;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GACjD;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAC9C;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzD;;;GAGG;AACH,wBAAsB,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAmCzF;AAED,qEAAqE;AACrE,wBAAsB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAiEzE;AAuBD,gDAAgD;AAChD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAqE3D"}
@@ -0,0 +1,196 @@
1
+ import { existsSync, readFileSync, writeFileSync, renameSync, mkdirSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { loadConfig, detectLatestSprint, parseRoadmap, formatStrategicContext } from '../../core/index.js';
4
+ import { resolveStore } from '../store.js';
5
+ /**
6
+ * Next-action guard: fires on Stop.
7
+ * Suggests next actions before session end based on sprint state.
8
+ */
9
+ export async function nextActionGuard(input, cwd) {
10
+ // Re-prompt prevention: check if we already prompted this session
11
+ const slopeDir = join(cwd, '.slope');
12
+ const stateFile = join(slopeDir, '.next-action-prompted');
13
+ if (input.session_id) {
14
+ try {
15
+ if (existsSync(stateFile)) {
16
+ const raw = JSON.parse(readFileSync(stateFile, 'utf8'));
17
+ if (raw.session_id === input.session_id) {
18
+ return {};
19
+ }
20
+ }
21
+ }
22
+ catch { /* corrupted state file — proceed */ }
23
+ }
24
+ // Detect sprint state
25
+ const state = await detectSprintState(cwd);
26
+ // Build suggestion text
27
+ const suggestion = buildSuggestions(state);
28
+ // Write state file atomically
29
+ try {
30
+ mkdirSync(slopeDir, { recursive: true });
31
+ const tmpPath = join(slopeDir, '.next-action-prompted.tmp');
32
+ const json = JSON.stringify({
33
+ session_id: input.session_id,
34
+ prompted_at: new Date().toISOString(),
35
+ });
36
+ writeFileSync(tmpPath, json);
37
+ renameSync(tmpPath, stateFile);
38
+ }
39
+ catch { /* best-effort — don't fail the guard */ }
40
+ return { blockReason: suggestion };
41
+ }
42
+ /** Detect current sprint state via store then filesystem fallback */
43
+ export async function detectSprintState(cwd) {
44
+ // Try store first for active claims
45
+ let claimsFromStore = null;
46
+ try {
47
+ const store = await resolveStore(cwd);
48
+ try {
49
+ const claims = await store.getActiveClaims();
50
+ if (claims.length > 0) {
51
+ const sprintNumber = Math.max(...claims.map(c => c.sprint_number));
52
+ return {
53
+ type: 'mid-sprint',
54
+ sprintNumber,
55
+ claimCount: claims.length,
56
+ targets: claims.map(c => c.target),
57
+ };
58
+ }
59
+ claimsFromStore = claims;
60
+ }
61
+ finally {
62
+ store.close();
63
+ }
64
+ }
65
+ catch {
66
+ // Store unavailable — try filesystem fallback
67
+ try {
68
+ const claimsPath = join(cwd, '.slope', 'claims.json');
69
+ if (existsSync(claimsPath)) {
70
+ const raw = JSON.parse(readFileSync(claimsPath, 'utf8'));
71
+ if (Array.isArray(raw) && raw.length > 0) {
72
+ const sprintNumber = Math.max(...raw.map((c) => c.sprint_number ?? 0));
73
+ return {
74
+ type: 'mid-sprint',
75
+ sprintNumber,
76
+ claimCount: raw.length,
77
+ targets: raw.map((c) => c.target ?? 'unknown'),
78
+ };
79
+ }
80
+ }
81
+ }
82
+ catch { /* filesystem fallback failed */ }
83
+ }
84
+ // Load config and scorecards for remaining checks
85
+ let config;
86
+ try {
87
+ config = loadConfig(cwd);
88
+ }
89
+ catch {
90
+ return { type: 'between-sprints' };
91
+ }
92
+ const latestScoredSprint = detectLatestSprint(config, cwd);
93
+ // If no claims and no scorecards, we're between sprints
94
+ if (latestScoredSprint === 0 && (claimsFromStore === null || claimsFromStore.length === 0)) {
95
+ return buildBetweenSprints(config, cwd, 0);
96
+ }
97
+ // Check if the latest sprint has a review
98
+ if (latestScoredSprint > 0) {
99
+ const retrosDir = join(cwd, config.scorecardDir);
100
+ const reviewPath = join(retrosDir, `sprint-${latestScoredSprint}-review.md`);
101
+ if (!existsSync(reviewPath)) {
102
+ return { type: 'needs-review', sprintNumber: latestScoredSprint };
103
+ }
104
+ }
105
+ // Default: between sprints
106
+ return buildBetweenSprints(config, cwd, latestScoredSprint);
107
+ }
108
+ /** Build between-sprints state with optional roadmap context */
109
+ function buildBetweenSprints(config, cwd, latestSprint) {
110
+ let roadmapContext;
111
+ try {
112
+ if (config.roadmapPath) {
113
+ const roadmapFile = join(cwd, config.roadmapPath);
114
+ if (existsSync(roadmapFile)) {
115
+ const raw = JSON.parse(readFileSync(roadmapFile, 'utf8'));
116
+ const { roadmap } = parseRoadmap(raw);
117
+ if (roadmap) {
118
+ const nextSprint = latestSprint + 1;
119
+ const ctx = formatStrategicContext(roadmap, nextSprint);
120
+ if (ctx)
121
+ roadmapContext = ctx;
122
+ }
123
+ }
124
+ }
125
+ }
126
+ catch { /* roadmap parsing failed — proceed without context */ }
127
+ return { type: 'between-sprints', roadmapContext };
128
+ }
129
+ /** Build block reason text from sprint state */
130
+ export function buildSuggestions(state) {
131
+ const header = 'SLOPE next-action: Before ending this session, present the user with options for what to do next.';
132
+ switch (state.type) {
133
+ case 'mid-sprint': {
134
+ const targetList = state.targets.join(', ');
135
+ return [
136
+ header,
137
+ '',
138
+ `Current state: Mid-sprint — ${state.claimCount} active claim(s) for sprint ${state.sprintNumber}: ${targetList}`,
139
+ '',
140
+ 'Suggested options:',
141
+ '1. Continue with the next ticket',
142
+ '2. Push and take a break — resume later',
143
+ '3. End session — nothing more to do right now',
144
+ '',
145
+ 'Present these using AskUserQuestion. If the user chooses to end the session, stop without further action.',
146
+ ].join('\n');
147
+ }
148
+ case 'sprint-complete':
149
+ return [
150
+ header,
151
+ '',
152
+ `Current state: Sprint ${state.sprintNumber} is complete but unscored`,
153
+ '',
154
+ 'Suggested options:',
155
+ '1. Score the sprint — run post-hole routine',
156
+ '2. Run `slope validate` on the scorecard',
157
+ '3. Distill learnings into common issues',
158
+ '4. End session — nothing more to do right now',
159
+ '',
160
+ 'Present these using AskUserQuestion. If the user chooses to end the session, stop without further action.',
161
+ ].join('\n');
162
+ case 'needs-review': {
163
+ return [
164
+ header,
165
+ '',
166
+ `Current state: Sprint ${state.sprintNumber} has a scorecard but no review`,
167
+ '',
168
+ 'Suggested options:',
169
+ '1. Generate sprint review',
170
+ '2. Distill learnings and update common issues',
171
+ '3. Run `slope review` for the full sprint review',
172
+ '4. End session — nothing more to do right now',
173
+ '',
174
+ 'Present these using AskUserQuestion. If the user chooses to end the session, stop without further action.',
175
+ ].join('\n');
176
+ }
177
+ case 'between-sprints': {
178
+ const contextLine = state.roadmapContext
179
+ ? `\n${state.roadmapContext}\n`
180
+ : '';
181
+ return [
182
+ header,
183
+ '',
184
+ `Current state: No active sprint${contextLine}`,
185
+ 'Suggested options:',
186
+ '1. Check next sprint candidates from the roadmap',
187
+ '2. Start a new sprint',
188
+ '3. Run `slope briefing` for a status overview',
189
+ '4. End session — nothing more to do right now',
190
+ '',
191
+ 'Present these using AskUserQuestion. If the user chooses to end the session, stop without further action.',
192
+ ].join('\n');
193
+ }
194
+ }
195
+ }
196
+ //# sourceMappingURL=next-action.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"next-action.js","sourceRoot":"","sources":["../../../src/cli/guards/next-action.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { HookInput, GuardResult } from '../../core/index.js';
2
+ /**
3
+ * Push nudge guard: fires PostToolUse on Bash.
4
+ * Nudges to push after git commit commands when unpushed count or time is high.
5
+ */
6
+ export declare function pushNudgeGuard(input: HookInput, cwd: string): Promise<GuardResult>;
7
+ //# sourceMappingURL=push-nudge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push-nudge.d.ts","sourceRoot":"","sources":["../../../src/cli/guards/push-nudge.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGlE;;;GAGG;AACH,wBAAsB,cAAc,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAgDxF"}
@@ -0,0 +1,53 @@
1
+ import { execSync } from 'node:child_process';
2
+ import { loadConfig } from '../config.js';
3
+ /**
4
+ * Push nudge guard: fires PostToolUse on Bash.
5
+ * Nudges to push after git commit commands when unpushed count or time is high.
6
+ */
7
+ export async function pushNudgeGuard(input, cwd) {
8
+ const command = input.tool_input?.command ?? '';
9
+ // Only fire after git commit commands
10
+ if (!command.includes('git commit'))
11
+ return {};
12
+ const config = loadConfig();
13
+ const guidance = config.guidance ?? {};
14
+ const pushCommitThreshold = guidance.pushCommitThreshold ?? 5;
15
+ const pushInterval = guidance.pushInterval ?? 30;
16
+ const nudges = [];
17
+ // Check if on main/master — always nudge (should push or switch branch)
18
+ try {
19
+ const branch = execSync('git rev-parse --abbrev-ref HEAD 2>/dev/null', { cwd, encoding: 'utf8' }).trim();
20
+ if (branch === 'main' || branch === 'master') {
21
+ nudges.push(`Committing directly on ${branch} — consider pushing or switching to a feature branch.`);
22
+ }
23
+ }
24
+ catch { /* not a git repo */ }
25
+ // Check unpushed commit count
26
+ try {
27
+ const unpushed = execSync('git log @{u}..HEAD --oneline 2>/dev/null', { cwd, encoding: 'utf8' }).trim();
28
+ if (unpushed) {
29
+ const count = unpushed.split('\n').filter(Boolean).length;
30
+ if (count >= pushCommitThreshold) {
31
+ nudges.push(`${count} unpushed commits — push to preserve your recovery point.`);
32
+ }
33
+ }
34
+ }
35
+ catch { /* no upstream */ }
36
+ // Check time since oldest unpushed commit
37
+ try {
38
+ const oldest = execSync('git log @{u}..HEAD --format=%ct --reverse 2>/dev/null', { cwd, encoding: 'utf8' }).trim().split('\n')[0];
39
+ if (oldest) {
40
+ const minutesSince = (Date.now() / 1000 - parseInt(oldest, 10)) / 60;
41
+ if (minutesSince >= pushInterval) {
42
+ nudges.push(`~${Math.round(minutesSince)} minutes since oldest unpushed commit — push now.`);
43
+ }
44
+ }
45
+ }
46
+ catch { /* no upstream */ }
47
+ if (nudges.length === 0)
48
+ return {};
49
+ return {
50
+ context: `SLOPE push discipline:\n${nudges.map(n => ` ${n}`).join('\n')}`,
51
+ };
52
+ }
53
+ //# sourceMappingURL=push-nudge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"push-nudge.js","sourceRoot":"","sources":["../../../src/cli/guards/push-nudge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAE9C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,KAAgB,EAAE,GAAW;IAChE,MAAM,OAAO,GAAI,KAAK,CAAC,UAAU,EAAE,OAAkB,IAAI,EAAE,CAAC;IAE5D,sCAAsC;IACtC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;QAAE,OAAO,EAAE,CAAC;IAE/C,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC;IACvC,MAAM,mBAAmB,GAAG,QAAQ,CAAC,mBAAmB,IAAI,CAAC,CAAC;IAC9D,MAAM,YAAY,GAAG,QAAQ,CAAC,YAAY,IAAI,EAAE,CAAC;IAEjD,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,wEAAwE;IACxE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,QAAQ,CAAC,6CAA6C,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACzG,IAAI,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC7C,MAAM,CAAC,IAAI,CAAC,0BAA0B,MAAM,uDAAuD,CAAC,CAAC;QACvG,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAC,oBAAoB,CAAC,CAAC;IAEhC,8BAA8B;IAC9B,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,QAAQ,CAAC,0CAA0C,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACxG,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;YAC1D,IAAI,KAAK,IAAI,mBAAmB,EAAE,CAAC;gBACjC,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,2DAA2D,CAAC,CAAC;YACnF,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;IAE7B,0CAA0C;IAC1C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,QAAQ,CAAC,uDAAuD,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAClI,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,YAAY,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,GAAG,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC;YACrE,IAAI,YAAY,IAAI,YAAY,EAAE,CAAC;gBACjC,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,mDAAmD,CAAC,CAAC;YAC/F,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;IAE7B,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEnC,OAAO;QACL,OAAO,EAAE,2BAA2B,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;KAC3E,CAAC;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { HookInput, GuardResult } from '../../core/index.js';
2
+ /**
3
+ * Review-tier guard: fires PreToolUse on ExitPlanMode.
4
+ * Recommends a review tier based on plan scope (context-only, never deny).
5
+ */
6
+ export declare function reviewTierGuard(input: HookInput, cwd: string): Promise<GuardResult>;
7
+ //# sourceMappingURL=review-tier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-tier.d.ts","sourceRoot":"","sources":["../../../src/cli/guards/review-tier.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAQlE;;;GAGG;AACH,wBAAsB,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAuDzF"}
@@ -0,0 +1,108 @@
1
+ import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ /**
4
+ * Review-tier guard: fires PreToolUse on ExitPlanMode.
5
+ * Recommends a review tier based on plan scope (context-only, never deny).
6
+ */
7
+ export async function reviewTierGuard(input, cwd) {
8
+ // Find the plan file
9
+ const planContent = findPlanContent(input, cwd);
10
+ if (!planContent)
11
+ return {};
12
+ // Analyze the plan
13
+ const ticketCount = countTickets(planContent);
14
+ const packageRefs = countPackageRefs(planContent);
15
+ const hasSchemaOrApi = /\b(schema|migration|api|endpoint)\b/i.test(planContent);
16
+ const hasInfra = /\b(infrastructure|new package|new service|architect)\b/i.test(planContent);
17
+ const isResearchOrDocs = /^#+\s*(research|docs|documentation|infra|spike)\b/im.test(planContent)
18
+ && ticketCount === 0;
19
+ // Determine recommended tier
20
+ let tier;
21
+ let rounds;
22
+ if (isResearchOrDocs || ticketCount === 0) {
23
+ tier = 'Skip';
24
+ rounds = 0;
25
+ }
26
+ else if (ticketCount <= 2 && packageRefs <= 1) {
27
+ tier = 'Light';
28
+ rounds = 1;
29
+ }
30
+ else if (ticketCount >= 5 || hasInfra) {
31
+ tier = 'Deep';
32
+ rounds = 3;
33
+ }
34
+ else {
35
+ // 3-4 tickets, or multi-package, or schema/API changes
36
+ tier = 'Standard';
37
+ rounds = 2;
38
+ }
39
+ // Check if review-state.json already matches
40
+ const statePath = join(cwd, '.slope', 'review-state.json');
41
+ if (existsSync(statePath)) {
42
+ try {
43
+ const state = JSON.parse(readFileSync(statePath, 'utf8'));
44
+ if (state.rounds_required >= rounds) {
45
+ // Already set to at least the recommended level — silent passthrough
46
+ return {};
47
+ }
48
+ }
49
+ catch { /* malformed — proceed with recommendation */ }
50
+ }
51
+ // Build context message
52
+ const scopeDesc = [
53
+ `${ticketCount} ticket${ticketCount !== 1 ? 's' : ''}`,
54
+ packageRefs > 1 ? `${packageRefs} packages` : null,
55
+ hasSchemaOrApi ? 'schema/API changes' : null,
56
+ hasInfra ? 'new infrastructure' : null,
57
+ ].filter(Boolean).join(', ');
58
+ return {
59
+ context: `SLOPE review-tier: Plan has ${scopeDesc} — recommend ${tier} review (${rounds} round${rounds !== 1 ? 's' : ''}). Set rounds_required: ${rounds} in .slope/review-state.json`,
60
+ };
61
+ }
62
+ function findPlanContent(input, cwd) {
63
+ // Try to find plan file from tool_input (ExitPlanMode context)
64
+ // Claude Code stores plans in .claude/plans/
65
+ const plansDir = join(cwd, '.claude', 'plans');
66
+ if (existsSync(plansDir)) {
67
+ // Find the most recently modified .md file
68
+ try {
69
+ const files = readdirSync(plansDir)
70
+ .filter(f => f.endsWith('.md'))
71
+ .map(f => ({
72
+ name: f,
73
+ path: join(plansDir, f),
74
+ mtime: (() => { try {
75
+ return statSync(join(plansDir, f)).mtimeMs;
76
+ }
77
+ catch {
78
+ return 0;
79
+ } })(),
80
+ }))
81
+ .sort((a, b) => b.mtime - a.mtime);
82
+ if (files.length > 0) {
83
+ return readFileSync(files[0].path, 'utf8');
84
+ }
85
+ }
86
+ catch { /* no plans dir or can't read */ }
87
+ }
88
+ return null;
89
+ }
90
+ function countTickets(content) {
91
+ // Match ticket patterns: ### S\d+-\d+, ### Ticket, numbered ticket headers
92
+ const ticketHeaders = content.match(/^###\s+S\d+-\d+/gm) ?? [];
93
+ if (ticketHeaders.length > 0)
94
+ return ticketHeaders.length;
95
+ // Fallback: count ### level headers that look like tickets
96
+ const h3Headers = content.match(/^###\s+/gm) ?? [];
97
+ return h3Headers.length;
98
+ }
99
+ function countPackageRefs(content) {
100
+ // Count distinct packages/ references
101
+ const refs = new Set();
102
+ const matches = content.matchAll(/packages\/(\w[\w-]*)/g);
103
+ for (const m of matches) {
104
+ refs.add(m[1]);
105
+ }
106
+ return refs.size;
107
+ }
108
+ //# sourceMappingURL=review-tier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review-tier.js","sourceRoot":"","sources":["../../../src/cli/guards/review-tier.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { HookInput, GuardResult } from '../../core/index.js';
2
+ /**
3
+ * Scope drift guard: fires PreToolUse on Edit|Write.
4
+ * Warns when editing files outside the claimed ticket's scope.
5
+ */
6
+ export declare function scopeDriftGuard(input: HookInput, cwd: string): Promise<GuardResult>;
7
+ //# sourceMappingURL=scope-drift.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scope-drift.d.ts","sourceRoot":"","sources":["../../../src/cli/guards/scope-drift.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAIlE;;;GAGG;AACH,wBAAsB,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAwCzF"}