dsh-pstack 0.1.0 → 0.2.0-beta.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 (312) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +92 -117
  3. package/assets/agents/comment-sicko.md +1 -1
  4. package/assets/agents/poteto-agent.md +2 -2
  5. package/assets/docs/guide/01-setup.md +9 -9
  6. package/assets/docs/guide/02-poteto-mode.md +4 -4
  7. package/assets/docs/guide/05-build-and-clean.md +3 -3
  8. package/assets/docs/guide/06-verify-and-ship.md +2 -2
  9. package/assets/docs/guide/07-overnight.md +10 -12
  10. package/assets/docs/guide/09-make-it-yours.md +2 -6
  11. package/assets/docs/guide/10-recipes-and-pitfalls.md +3 -3
  12. package/assets/docs/guide/README.md +1 -1
  13. package/assets/docs/guide/images/design.jpg +0 -0
  14. package/assets/docs/guide/images/overnight.jpg +0 -0
  15. package/assets/docs/guide/images/recipes.jpg +0 -0
  16. package/assets/docs/guide/images/router.jpg +0 -0
  17. package/assets/docs/guide/images/understanding.jpg +0 -0
  18. package/assets/docs/guide/images/verification.jpg +0 -0
  19. package/assets/docs/harness/dsh.md +60 -65
  20. package/assets/docs/pstack-models.example.md +40 -9
  21. package/assets/skills/architect/SKILL.md +12 -12
  22. package/assets/skills/arena/SKILL.md +11 -11
  23. package/assets/skills/automate-me/SKILL.md +15 -14
  24. package/assets/skills/benchmark-checklist/SKILL.md +0 -2
  25. package/assets/skills/blast-radius/SKILL.md +5 -5
  26. package/assets/skills/bro/SKILL.md +0 -2
  27. package/assets/skills/correct/SKILL.md +0 -2
  28. package/assets/skills/create-formal-verification-skill/SKILL.md +2 -2
  29. package/assets/skills/create-verification-skill/SKILL.md +2 -2
  30. package/assets/skills/figure-it-out/SKILL.md +13 -13
  31. package/assets/skills/how/SKILL.md +6 -6
  32. package/assets/skills/how/references/explainer-prompt.md +1 -1
  33. package/assets/skills/in-your-own-words/SKILL.md +0 -2
  34. package/assets/skills/interrogate/SKILL.md +9 -7
  35. package/assets/skills/interrogate/references/rubric.md +1 -1
  36. package/assets/skills/ketchup/SKILL.md +4 -4
  37. package/assets/skills/maintain-formal-verification-skill/SKILL.md +2 -2
  38. package/assets/skills/maintain-verification-skill/SKILL.md +3 -3
  39. package/assets/skills/no-comments/SKILL.md +7 -7
  40. package/assets/skills/poteto-help/SKILL.md +32 -31
  41. package/assets/skills/poteto-help/references/prompting.md +1 -1
  42. package/assets/skills/poteto-help/references/recipes.md +1 -1
  43. package/assets/skills/poteto-mode/SKILL.md +17 -19
  44. package/assets/skills/poteto-mode/playbooks/authoring-a-skill.md +3 -3
  45. package/assets/skills/poteto-mode/playbooks/autonomous-run.md +6 -4
  46. package/assets/skills/poteto-mode/playbooks/autopilot-full.md +6 -6
  47. package/assets/skills/poteto-mode/playbooks/autopilot-stack.md +2 -2
  48. package/assets/skills/poteto-mode/playbooks/babysit.md +3 -3
  49. package/assets/skills/poteto-mode/playbooks/bug-fix.md +7 -7
  50. package/assets/skills/poteto-mode/playbooks/eval.md +3 -3
  51. package/assets/skills/poteto-mode/playbooks/feature.md +8 -8
  52. package/assets/skills/poteto-mode/playbooks/hillclimb.md +3 -3
  53. package/assets/skills/poteto-mode/playbooks/investigation.md +2 -2
  54. package/assets/skills/poteto-mode/playbooks/multi-phase-plan.md +21 -21
  55. package/assets/skills/poteto-mode/playbooks/opening-a-pr.md +6 -6
  56. package/assets/skills/poteto-mode/playbooks/orchestrate.md +13 -13
  57. package/assets/skills/poteto-mode/playbooks/pause-safely.md +2 -2
  58. package/assets/skills/poteto-mode/playbooks/perf-issue.md +6 -6
  59. package/assets/skills/poteto-mode/playbooks/prototype.md +4 -4
  60. package/assets/skills/poteto-mode/playbooks/refactoring.md +9 -9
  61. package/assets/skills/poteto-mode/playbooks/runtime-forensics.md +3 -3
  62. package/assets/skills/poteto-mode/playbooks/session-pickup.md +2 -2
  63. package/assets/skills/poteto-mode/playbooks/shipping.md +2 -2
  64. package/assets/skills/poteto-mode/playbooks/trace-forensics.md +2 -2
  65. package/assets/skills/poteto-mode/playbooks/visual-parity.md +5 -5
  66. package/assets/skills/poteto-mode/playbooks/worktree-cleanup.md +14 -6
  67. package/assets/skills/poteto-mode/scripts/check-plan.mjs +85 -70
  68. package/assets/skills/poteto-mode/scripts/check-plan.test.mjs +343 -0
  69. package/assets/skills/poteto-mode/scripts/orch/orch.mjs +4282 -0
  70. package/assets/skills/poteto-mode/scripts/orch/orch.test.mjs +2042 -0
  71. package/assets/skills/poteto-mode/scripts/watch-pr/cli.test.mjs +5101 -0
  72. package/assets/skills/poteto-mode/scripts/watch-pr/github.test.mjs +1177 -0
  73. package/assets/skills/poteto-mode/scripts/watch-pr/policy.test.mjs +1441 -0
  74. package/assets/skills/poteto-mode/scripts/watch-pr/watch-pr.mjs +4601 -0
  75. package/assets/skills/poteto-mode/scripts/worktree-audit.mjs +675 -0
  76. package/assets/skills/principle-attack-the-premise/SKILL.md +0 -2
  77. package/assets/skills/principle-boundary-discipline/SKILL.md +0 -2
  78. package/assets/skills/principle-build-the-lever/SKILL.md +0 -3
  79. package/assets/skills/principle-encode-lessons-in-structure/SKILL.md +0 -2
  80. package/assets/skills/principle-exhaust-the-design-space/SKILL.md +0 -2
  81. package/assets/skills/principle-experience-first/SKILL.md +0 -2
  82. package/assets/skills/principle-explain-the-number/SKILL.md +0 -2
  83. package/assets/skills/principle-fix-root-causes/SKILL.md +0 -2
  84. package/assets/skills/principle-foundational-thinking/SKILL.md +0 -2
  85. package/assets/skills/principle-guard-the-context-window/SKILL.md +0 -2
  86. package/assets/skills/principle-laziness-protocol/SKILL.md +0 -2
  87. package/assets/skills/principle-make-operations-idempotent/SKILL.md +0 -2
  88. package/assets/skills/principle-migrate-callers-then-delete-legacy-apis/SKILL.md +0 -2
  89. package/assets/skills/principle-minimize-reader-load/SKILL.md +0 -2
  90. package/assets/skills/principle-model-the-domain/SKILL.md +0 -2
  91. package/assets/skills/principle-never-block-on-the-human/SKILL.md +0 -2
  92. package/assets/skills/principle-outcome-oriented-execution/SKILL.md +0 -2
  93. package/assets/skills/principle-prove-it-works/SKILL.md +2 -2
  94. package/assets/skills/principle-redesign-from-first-principles/SKILL.md +0 -2
  95. package/assets/skills/principle-separate-before-serializing-shared-state/SKILL.md +0 -2
  96. package/assets/skills/principle-sequence-verifiable-units/SKILL.md +0 -2
  97. package/assets/skills/principle-subtract-before-you-add/SKILL.md +0 -2
  98. package/assets/skills/principle-test-behavior-not-implementation/SKILL.md +0 -2
  99. package/assets/skills/principle-type-system-discipline/SKILL.md +0 -2
  100. package/assets/skills/recall/SKILL.md +9 -9
  101. package/assets/skills/reflect/SKILL.md +20 -21
  102. package/assets/skills/reflect/references/divergent-reviewer.md +4 -4
  103. package/assets/skills/reflect/references/judgment-reviewer.md +2 -2
  104. package/assets/skills/reflect/references/synthesizer.md +6 -6
  105. package/assets/skills/reflect/references/tooling-reviewer.md +2 -2
  106. package/assets/skills/setup-pstack/SKILL.md +28 -37
  107. package/assets/skills/sharpen/SKILL.md +0 -2
  108. package/assets/skills/show-me-your-work/SKILL.md +9 -9
  109. package/assets/skills/show-me-your-work/scripts/log.mjs +108 -0
  110. package/assets/skills/swarm/SKILL.md +8 -6
  111. package/assets/skills/tdd/SKILL.md +0 -2
  112. package/assets/skills/teach/SKILL.md +2 -2
  113. package/assets/skills/technical-writing/SKILL.md +2 -2
  114. package/assets/skills/typescript-best-practices/SKILL.md +6 -4
  115. package/assets/skills/unslop/SKILL.md +0 -2
  116. package/assets/skills/why/SKILL.md +9 -9
  117. package/cordis.patch.yml +33 -14
  118. package/dist/frontmatter-BQX3ekwP.mjs +229 -0
  119. package/dist/frontmatter-BQX3ekwP.mjs.map +1 -0
  120. package/dist/history.d.mts +429 -0
  121. package/dist/history.mjs +1129 -0
  122. package/dist/history.mjs.map +1 -0
  123. package/dist/host-contract-o47JH_r8.d.mts +527 -0
  124. package/dist/index.d.mts +273 -11
  125. package/dist/index.mjs +248 -148
  126. package/dist/index.mjs.map +1 -1
  127. package/dist/paths-D_JlVmBk.mjs +42 -0
  128. package/dist/paths-D_JlVmBk.mjs.map +1 -0
  129. package/dist/script.d.mts +193 -0
  130. package/dist/script.mjs +782 -0
  131. package/dist/script.mjs.map +1 -0
  132. package/dist/subagent.d.mts +306 -100
  133. package/dist/subagent.mjs +1309 -343
  134. package/dist/subagent.mjs.map +1 -1
  135. package/locale/en.json +6 -0
  136. package/locale/zh.json +6 -0
  137. package/package.json +55 -41
  138. package/static/icon.png +0 -0
  139. package/assets/skills/poteto-mode/scripts/bootstrap.ts +0 -62
  140. package/assets/skills/poteto-mode/scripts/bun.lock +0 -67
  141. package/assets/skills/poteto-mode/scripts/check-plan.test.ts +0 -96
  142. package/assets/skills/poteto-mode/scripts/orch/orch.test.ts +0 -761
  143. package/assets/skills/poteto-mode/scripts/orch/orch.ts +0 -590
  144. package/assets/skills/poteto-mode/scripts/orch/store.ts +0 -1677
  145. package/assets/skills/poteto-mode/scripts/package.json +0 -16
  146. package/assets/skills/poteto-mode/scripts/watch-pr/cli.test.ts +0 -224
  147. package/assets/skills/poteto-mode/scripts/watch-pr/cli.ts +0 -223
  148. package/assets/skills/poteto-mode/scripts/watch-pr/fakes.test-helper.ts +0 -129
  149. package/assets/skills/poteto-mode/scripts/watch-pr/github.test.ts +0 -436
  150. package/assets/skills/poteto-mode/scripts/watch-pr/github.ts +0 -718
  151. package/assets/skills/poteto-mode/scripts/watch-pr/policy.test.ts +0 -420
  152. package/assets/skills/poteto-mode/scripts/watch-pr/policy.ts +0 -836
  153. package/assets/skills/poteto-mode/scripts/watch-pr/render.ts +0 -169
  154. package/assets/skills/poteto-mode/scripts/watch-pr/tsconfig.json +0 -13
  155. package/assets/skills/poteto-mode/scripts/watch-pr/types.compile.ts +0 -93
  156. package/assets/skills/poteto-mode/scripts/watch-pr/types.ts +0 -413
  157. package/assets/skills/poteto-mode/scripts/watch-pr/watch-pr +0 -6
  158. package/assets/skills/poteto-mode/scripts/worktree-audit.sh +0 -127
  159. package/assets/skills/show-me-your-work/scripts/log.sh +0 -42
  160. package/dist/LICENSE +0 -22
  161. package/dist/README.md +0 -159
  162. package/dist/assets/agents/comment-sicko.md +0 -32
  163. package/dist/assets/agents/poteto-agent.md +0 -8
  164. package/dist/assets/docs/guide/01-setup.md +0 -64
  165. package/dist/assets/docs/guide/02-poteto-mode.md +0 -139
  166. package/dist/assets/docs/guide/03-understand.md +0 -79
  167. package/dist/assets/docs/guide/04-design.md +0 -133
  168. package/dist/assets/docs/guide/05-build-and-clean.md +0 -83
  169. package/dist/assets/docs/guide/06-verify-and-ship.md +0 -152
  170. package/dist/assets/docs/guide/07-overnight.md +0 -122
  171. package/dist/assets/docs/guide/08-principles.md +0 -72
  172. package/dist/assets/docs/guide/09-make-it-yours.md +0 -100
  173. package/dist/assets/docs/guide/10-recipes-and-pitfalls.md +0 -180
  174. package/dist/assets/docs/guide/README.md +0 -38
  175. package/dist/assets/docs/harness/dsh.md +0 -65
  176. package/dist/assets/docs/pstack-models.example.md +0 -23
  177. package/dist/assets/skills/architect/SKILL.md +0 -81
  178. package/dist/assets/skills/architect/references/design-red-flags.md +0 -57
  179. package/dist/assets/skills/architect/references/rationale-template.md +0 -35
  180. package/dist/assets/skills/architect/references/runner-prompt.md +0 -20
  181. package/dist/assets/skills/arena/SKILL.md +0 -50
  182. package/dist/assets/skills/automate-me/SKILL.md +0 -105
  183. package/dist/assets/skills/benchmark-checklist/SKILL.md +0 -41
  184. package/dist/assets/skills/blast-radius/SKILL.md +0 -52
  185. package/dist/assets/skills/bro/SKILL.md +0 -9
  186. package/dist/assets/skills/correct/SKILL.md +0 -34
  187. package/dist/assets/skills/create-formal-verification-skill/SKILL.md +0 -43
  188. package/dist/assets/skills/create-verification-skill/SKILL.md +0 -46
  189. package/dist/assets/skills/create-verification-skill/references/feature-map-example/README.md +0 -47
  190. package/dist/assets/skills/create-verification-skill/references/feature-map-example/create-note.md +0 -39
  191. package/dist/assets/skills/create-verification-skill/references/feature-map-example/search.md +0 -45
  192. package/dist/assets/skills/figure-it-out/SKILL.md +0 -54
  193. package/dist/assets/skills/how/SKILL.md +0 -38
  194. package/dist/assets/skills/how/references/explainer-prompt.md +0 -55
  195. package/dist/assets/skills/how/references/explorer-prompt.md +0 -35
  196. package/dist/assets/skills/in-your-own-words/SKILL.md +0 -9
  197. package/dist/assets/skills/interrogate/SKILL.md +0 -69
  198. package/dist/assets/skills/interrogate/references/code-quality-review.md +0 -47
  199. package/dist/assets/skills/interrogate/references/lead-judgment.md +0 -39
  200. package/dist/assets/skills/interrogate/references/reviewer-prompt.md +0 -62
  201. package/dist/assets/skills/interrogate/references/rubric.md +0 -77
  202. package/dist/assets/skills/ketchup/SKILL.md +0 -45
  203. package/dist/assets/skills/maintain-formal-verification-skill/SKILL.md +0 -60
  204. package/dist/assets/skills/maintain-verification-skill/SKILL.md +0 -41
  205. package/dist/assets/skills/no-comments/SKILL.md +0 -26
  206. package/dist/assets/skills/poteto-help/SKILL.md +0 -161
  207. package/dist/assets/skills/poteto-help/references/prompting.md +0 -51
  208. package/dist/assets/skills/poteto-help/references/recipes.md +0 -51
  209. package/dist/assets/skills/poteto-mode/SKILL.md +0 -153
  210. package/dist/assets/skills/poteto-mode/playbooks/authoring-a-skill.md +0 -12
  211. package/dist/assets/skills/poteto-mode/playbooks/autonomous-run.md +0 -13
  212. package/dist/assets/skills/poteto-mode/playbooks/autopilot-full.md +0 -25
  213. package/dist/assets/skills/poteto-mode/playbooks/autopilot-stack.md +0 -12
  214. package/dist/assets/skills/poteto-mode/playbooks/babysit.md +0 -23
  215. package/dist/assets/skills/poteto-mode/playbooks/bug-fix.md +0 -15
  216. package/dist/assets/skills/poteto-mode/playbooks/eval.md +0 -25
  217. package/dist/assets/skills/poteto-mode/playbooks/feature.md +0 -21
  218. package/dist/assets/skills/poteto-mode/playbooks/hillclimb.md +0 -21
  219. package/dist/assets/skills/poteto-mode/playbooks/investigation.md +0 -14
  220. package/dist/assets/skills/poteto-mode/playbooks/multi-phase-plan.md +0 -155
  221. package/dist/assets/skills/poteto-mode/playbooks/opening-a-pr.md +0 -34
  222. package/dist/assets/skills/poteto-mode/playbooks/orchestrate.md +0 -112
  223. package/dist/assets/skills/poteto-mode/playbooks/pause-safely.md +0 -10
  224. package/dist/assets/skills/poteto-mode/playbooks/perf-issue.md +0 -25
  225. package/dist/assets/skills/poteto-mode/playbooks/prototype.md +0 -14
  226. package/dist/assets/skills/poteto-mode/playbooks/refactoring.md +0 -16
  227. package/dist/assets/skills/poteto-mode/playbooks/runtime-forensics.md +0 -11
  228. package/dist/assets/skills/poteto-mode/playbooks/session-pickup.md +0 -11
  229. package/dist/assets/skills/poteto-mode/playbooks/shipping.md +0 -12
  230. package/dist/assets/skills/poteto-mode/playbooks/trace-forensics.md +0 -14
  231. package/dist/assets/skills/poteto-mode/playbooks/visual-parity.md +0 -11
  232. package/dist/assets/skills/poteto-mode/playbooks/worktree-cleanup.md +0 -12
  233. package/dist/assets/skills/poteto-mode/references/bugbot-triage.md +0 -142
  234. package/dist/assets/skills/poteto-mode/scripts/bootstrap.ts +0 -62
  235. package/dist/assets/skills/poteto-mode/scripts/bun.lock +0 -67
  236. package/dist/assets/skills/poteto-mode/scripts/check-plan.mjs +0 -205
  237. package/dist/assets/skills/poteto-mode/scripts/check-plan.test.ts +0 -96
  238. package/dist/assets/skills/poteto-mode/scripts/orch/orch.test.ts +0 -761
  239. package/dist/assets/skills/poteto-mode/scripts/orch/orch.ts +0 -590
  240. package/dist/assets/skills/poteto-mode/scripts/orch/store.ts +0 -1677
  241. package/dist/assets/skills/poteto-mode/scripts/package.json +0 -16
  242. package/dist/assets/skills/poteto-mode/scripts/watch-pr/cli.test.ts +0 -224
  243. package/dist/assets/skills/poteto-mode/scripts/watch-pr/cli.ts +0 -223
  244. package/dist/assets/skills/poteto-mode/scripts/watch-pr/fakes.test-helper.ts +0 -129
  245. package/dist/assets/skills/poteto-mode/scripts/watch-pr/github.test.ts +0 -436
  246. package/dist/assets/skills/poteto-mode/scripts/watch-pr/github.ts +0 -718
  247. package/dist/assets/skills/poteto-mode/scripts/watch-pr/policy.test.ts +0 -420
  248. package/dist/assets/skills/poteto-mode/scripts/watch-pr/policy.ts +0 -836
  249. package/dist/assets/skills/poteto-mode/scripts/watch-pr/render.ts +0 -169
  250. package/dist/assets/skills/poteto-mode/scripts/watch-pr/tsconfig.json +0 -13
  251. package/dist/assets/skills/poteto-mode/scripts/watch-pr/types.compile.ts +0 -93
  252. package/dist/assets/skills/poteto-mode/scripts/watch-pr/types.ts +0 -413
  253. package/dist/assets/skills/poteto-mode/scripts/watch-pr/watch-pr +0 -6
  254. package/dist/assets/skills/poteto-mode/scripts/worktree-audit.sh +0 -127
  255. package/dist/assets/skills/principle-attack-the-premise/SKILL.md +0 -23
  256. package/dist/assets/skills/principle-boundary-discipline/SKILL.md +0 -36
  257. package/dist/assets/skills/principle-build-the-lever/SKILL.md +0 -26
  258. package/dist/assets/skills/principle-encode-lessons-in-structure/SKILL.md +0 -13
  259. package/dist/assets/skills/principle-exhaust-the-design-space/SKILL.md +0 -11
  260. package/dist/assets/skills/principle-experience-first/SKILL.md +0 -21
  261. package/dist/assets/skills/principle-explain-the-number/SKILL.md +0 -19
  262. package/dist/assets/skills/principle-fix-root-causes/SKILL.md +0 -23
  263. package/dist/assets/skills/principle-foundational-thinking/SKILL.md +0 -23
  264. package/dist/assets/skills/principle-guard-the-context-window/SKILL.md +0 -14
  265. package/dist/assets/skills/principle-laziness-protocol/SKILL.md +0 -12
  266. package/dist/assets/skills/principle-make-operations-idempotent/SKILL.md +0 -24
  267. package/dist/assets/skills/principle-migrate-callers-then-delete-legacy-apis/SKILL.md +0 -16
  268. package/dist/assets/skills/principle-minimize-reader-load/SKILL.md +0 -20
  269. package/dist/assets/skills/principle-model-the-domain/SKILL.md +0 -26
  270. package/dist/assets/skills/principle-never-block-on-the-human/SKILL.md +0 -17
  271. package/dist/assets/skills/principle-outcome-oriented-execution/SKILL.md +0 -23
  272. package/dist/assets/skills/principle-prove-it-works/SKILL.md +0 -24
  273. package/dist/assets/skills/principle-redesign-from-first-principles/SKILL.md +0 -18
  274. package/dist/assets/skills/principle-separate-before-serializing-shared-state/SKILL.md +0 -18
  275. package/dist/assets/skills/principle-sequence-verifiable-units/SKILL.md +0 -19
  276. package/dist/assets/skills/principle-subtract-before-you-add/SKILL.md +0 -20
  277. package/dist/assets/skills/principle-test-behavior-not-implementation/SKILL.md +0 -22
  278. package/dist/assets/skills/principle-type-system-discipline/SKILL.md +0 -15
  279. package/dist/assets/skills/recall/SKILL.md +0 -37
  280. package/dist/assets/skills/reflect/SKILL.md +0 -70
  281. package/dist/assets/skills/reflect/references/divergent-reviewer.md +0 -38
  282. package/dist/assets/skills/reflect/references/judgment-reviewer.md +0 -37
  283. package/dist/assets/skills/reflect/references/synthesizer.md +0 -56
  284. package/dist/assets/skills/reflect/references/tooling-reviewer.md +0 -48
  285. package/dist/assets/skills/setup-pstack/SKILL.md +0 -76
  286. package/dist/assets/skills/sharpen/SKILL.md +0 -18
  287. package/dist/assets/skills/show-me-your-work/SKILL.md +0 -84
  288. package/dist/assets/skills/show-me-your-work/references/decision-log-template.tsv +0 -1
  289. package/dist/assets/skills/show-me-your-work/scripts/log.sh +0 -42
  290. package/dist/assets/skills/swarm/SKILL.md +0 -41
  291. package/dist/assets/skills/tdd/SKILL.md +0 -44
  292. package/dist/assets/skills/teach/SKILL.md +0 -23
  293. package/dist/assets/skills/technical-writing/SKILL.md +0 -108
  294. package/dist/assets/skills/typescript-best-practices/SKILL.md +0 -32
  295. package/dist/assets/skills/typescript-best-practices/references/patterns.md +0 -328
  296. package/dist/assets/skills/unslop/SKILL.md +0 -64
  297. package/dist/assets/skills/why/SKILL.md +0 -100
  298. package/dist/assets/skills/why/references/epistemics.md +0 -71
  299. package/dist/assets/skills/why/references/investigator-prompt.md +0 -84
  300. package/dist/assets/skills/why/references/source-playbook.md +0 -17
  301. package/dist/assets/skills/why/references/sources/code-archaeology.md +0 -51
  302. package/dist/assets/skills/why/references/sources/databricks.md +0 -70
  303. package/dist/assets/skills/why/references/sources/datadog.md +0 -97
  304. package/dist/assets/skills/why/references/sources/incident-postmortem.md +0 -5
  305. package/dist/assets/skills/why/references/sources/linear.md +0 -48
  306. package/dist/assets/skills/why/references/sources/notion.md +0 -55
  307. package/dist/assets/skills/why/references/sources/sentry.md +0 -66
  308. package/dist/assets/skills/why/references/sources/slack.md +0 -17
  309. package/dist/assets/skills/why/references/synthesizer-prompt.md +0 -129
  310. package/dist/cordis.patch.yml +0 -20
  311. package/dist/paths-Bbai4CaT.mjs +0 -16
  312. package/dist/paths-Bbai4CaT.mjs.map +0 -1
@@ -0,0 +1,675 @@
1
+ #!/usr/bin/env node
2
+ import { execFileSync } from "node:child_process";
3
+ import { readFileSync, readdirSync, statSync } from "node:fs";
4
+ import { isAbsolute, resolve, sep } from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ //#region .runtime-sources/skills/poteto-mode/scripts/worktree-audit.ts
7
+ /**
8
+ * Read-only worktree prune audit.
9
+ *
10
+ * A Node replacement for the upstream `scripts/worktree-audit.sh`. The shell
11
+ * script's job was to classify every git worktree by size, age, merge state,
12
+ * uncommitted work, remote/PR state, and the newest supplied session, then print
13
+ * one TSV table sorted by size with a suggested bucket. That job is unchanged; what
14
+ * changed is the toolchain. This file runs under Node alone, needs no `bash`, no
15
+ * `jq`, and no `awk`, and reads the caller's session JSON with `JSON.parse`.
16
+ *
17
+ * Behaviour kept deliberately identical, because the playbook and the tests name
18
+ * the columns:
19
+ *
20
+ * - The header is `# base: <ref>` then one TSV header line, written once.
21
+ * - Columns are SIZE, AGE, MERGED, DIRTY, REMOTE, PR, LAST_CHAT, PINNED, BUCKET,
22
+ * WORKTREE, in that order.
23
+ * - The main worktree is never a candidate. Only `git worktree list` provides
24
+ * paths; nothing is hand-typed.
25
+ * - `MERGED` is `YES` only when the worktree HEAD is an ancestor of the base.
26
+ * Squash merges are not ancestors, so the PR state is the real signal there.
27
+ * - `DIRTY` counts tracked edits as `wip:<n>` and untracked-only as `scratch:<n>`,
28
+ * with `clean` for neither.
29
+ * - `REMOTE` is `pushed`, `ahead<n>`, `detached`, or `no-remote`.
30
+ * - `PR` is `#<number>/<state>` from the forge, or `-`.
31
+ * - `PINNED` is always `unknown`: this host exposes no pinned-state source, so the
32
+ * user's own set decides and the script says so instead of guessing.
33
+ * - `BUCKET` is `hold-wip`, `hold-open-pr`, `unknown-usage`, `verify-recent-chat`,
34
+ * `safe`, or `review`. An unknown usage signal never reaches `safe`.
35
+ * - Rows are sorted by SIZE descending, then kept in the order they were produced.
36
+ * - The session store is never scanned. `--sessions` is the only usage input, and
37
+ * without it the LAST_CHAT column is `-` and the bucket is `unknown-usage`.
38
+ */
39
+ /** The shape `--sessions` takes, repeated in every message about it. */
40
+ const SESSIONS_SHAPE = "a JSON array of {\"sessionId\",\"cwd\",\"lastEventTime\"} objects";
41
+ const PINNED = "unknown";
42
+ const HEADER = [
43
+ "SIZE",
44
+ "AGE",
45
+ "MERGED",
46
+ "DIRTY",
47
+ "REMOTE",
48
+ "PR",
49
+ "LAST_CHAT",
50
+ "PINNED",
51
+ "BUCKET",
52
+ "WORKTREE"
53
+ ];
54
+ /** The bucket for a worktree whose usage signal is missing. */
55
+ const UNKNOWN_USAGE_BUCKET = "unknown-usage";
56
+ /** Raised for a usage problem; the caller prints the message and exits nonzero. */
57
+ var AuditError = class extends Error {
58
+ exitCode;
59
+ constructor(message, exitCode = 1) {
60
+ super(message);
61
+ this.name = "AuditError";
62
+ this.exitCode = exitCode;
63
+ }
64
+ };
65
+ /** How many days a worktree may be untouched and still count as recent. */
66
+ const RECENT_DAYS = 4;
67
+ /**
68
+ * Run git, returning stdout, or `undefined` when it fails.
69
+ *
70
+ * The shell script wrote `2>/dev/null` on most calls and branched on the exit
71
+ * status, so a failure is a normal value here rather than an exception.
72
+ */
73
+ function git(repo, args) {
74
+ try {
75
+ return execFileSync("git", [
76
+ "-C",
77
+ repo,
78
+ ...args
79
+ ], {
80
+ encoding: "utf8",
81
+ stdio: [
82
+ "ignore",
83
+ "pipe",
84
+ "ignore"
85
+ ],
86
+ maxBuffer: 33554432
87
+ });
88
+ } catch {
89
+ return;
90
+ }
91
+ }
92
+ /** Run git without `-C`, for commands that must see the real repository root. */
93
+ function gitHere(cwd, args) {
94
+ try {
95
+ return execFileSync("git", args, {
96
+ cwd,
97
+ encoding: "utf8",
98
+ stdio: [
99
+ "ignore",
100
+ "pipe",
101
+ "ignore"
102
+ ],
103
+ maxBuffer: 33554432
104
+ });
105
+ } catch {
106
+ return;
107
+ }
108
+ }
109
+ /** `git worktree list --porcelain`, parsed into worktree paths in order. */
110
+ function worktreePaths(repo) {
111
+ const out = git(repo, [
112
+ "worktree",
113
+ "list",
114
+ "--porcelain"
115
+ ]);
116
+ if (out === void 0) return [];
117
+ return out.split("\n").filter((line) => line.startsWith("worktree ")).map((line) => line.slice(9));
118
+ }
119
+ /**
120
+ * Human size, matching `du -h`.
121
+ *
122
+ * GNU `du -h` divides by 1024, promotes the unit when the value reaches 1024, and
123
+ * prints one decimal below ten and a rounded integer at or above ten. Verified
124
+ * against `du` on this host: 8.0K for 4096 bytes, 12K for 8192, 1.1M for 1 MiB,
125
+ * 513M for 512 MiB. Reproducing the format keeps the column comparable with the
126
+ * numbers the playbook quotes and removes the dependency on `du` and `awk`.
127
+ */
128
+ function formatSize(bytes) {
129
+ const units = [
130
+ "B",
131
+ "K",
132
+ "M",
133
+ "G",
134
+ "T",
135
+ "P"
136
+ ];
137
+ if (bytes < 1024) return `${bytes}B`;
138
+ let value = bytes / 1024;
139
+ let unit = 1;
140
+ while (value >= 1024 && unit < units.length - 1) {
141
+ value /= 1024;
142
+ unit += 1;
143
+ }
144
+ const suffix = units[unit];
145
+ return `${value < 10 ? value.toFixed(1) : String(Math.round(value))}${suffix}`;
146
+ }
147
+ /**
148
+ * Directory size in bytes as `du -s` counts it: allocated blocks, directories
149
+ * included.
150
+ *
151
+ * Three details make this match `du`, and each was checked against it on this host:
152
+ *
153
+ * - `stat.blocks` is in 512-byte units, not bytes.
154
+ * - A directory consumes blocks of its own, so its `blocks` counts too. Skipping
155
+ * them reads one 4 KiB block low per directory.
156
+ * - `.git` here is a file in a linked worktree, not a directory, so it contributes
157
+ * its own block and nothing is traversed through it.
158
+ *
159
+ * That block accounting is the point of the column: the playbook quotes the space
160
+ * `du` reports before deleting. A symlink contributes its own block and is never
161
+ * traversed, matching `du` without `-L`.
162
+ */
163
+ function directorySize(root) {
164
+ let total = 0;
165
+ const pending = [root];
166
+ while (pending.length > 0) {
167
+ const current = pending.pop();
168
+ let details;
169
+ try {
170
+ details = statSync(current, { throwIfNoEntry: false });
171
+ } catch {
172
+ continue;
173
+ }
174
+ if (details === void 0) continue;
175
+ total += details.blocks === void 0 ? details.size : details.blocks * 512;
176
+ if (!details.isDirectory()) continue;
177
+ let names;
178
+ try {
179
+ names = readdirSync(current);
180
+ } catch {
181
+ continue;
182
+ }
183
+ for (const name of names) pending.push(resolve(current, name));
184
+ }
185
+ return total;
186
+ }
187
+ /** `SIZE` as `du -sh` would print it, or `-` when the directory is gone. */
188
+ function sizeColumn(worktree) {
189
+ try {
190
+ if (!statSync(worktree).isDirectory()) return "-";
191
+ } catch {
192
+ return "-";
193
+ }
194
+ return formatSize(directorySize(worktree));
195
+ }
196
+ /** `AGE` as `<n>d`, or `?` when the HEAD time is unavailable. */
197
+ function ageColumn(headTimestamp, now) {
198
+ if (!(headTimestamp > 0)) return "?";
199
+ return `${Math.floor((now - headTimestamp) / 86400)}d`;
200
+ }
201
+ /**
202
+ * `DIRTY` for one worktree.
203
+ *
204
+ * `git status --porcelain` marks untracked entries with `??`. Anything else is
205
+ * tracked work, which is what a human has to look at before deleting.
206
+ */
207
+ function dirtyColumn(porcelain) {
208
+ const lines = porcelain.split("\n").filter((line) => line !== "");
209
+ if (lines.length === 0) return "clean";
210
+ const tracked = lines.filter((line) => !line.startsWith("??"));
211
+ if (tracked.length > 0) return `wip:${tracked.length}`;
212
+ return `scratch:${lines.filter((line) => line.startsWith("??")).length}`;
213
+ }
214
+ /** `MERGED` for one worktree, from whether HEAD is an ancestor of the base. */
215
+ function mergedColumn(isAncestor) {
216
+ return isAncestor ? "YES" : "no";
217
+ }
218
+ /** `REMOTE` for one worktree. */
219
+ function remoteColumn(input) {
220
+ if (input.branch === void 0 || input.branch === "") return "detached";
221
+ if (!input.hasRemote) return "no-remote";
222
+ if (input.remoteSha !== void 0 && input.head !== void 0 && input.remoteSha === input.head) return "pushed";
223
+ return `ahead${input.aheadCount ?? 0}`;
224
+ }
225
+ /** `PR` for one branch, matching the first entry the forge reported for it. */
226
+ function prColumn(branch, prs) {
227
+ if (branch === void 0 || branch === "") return "-";
228
+ const hit = prs.find((pr) => pr.head === branch);
229
+ return hit === void 0 ? "-" : `#${hit.number}/${hit.state}`;
230
+ }
231
+ /**
232
+ * Whether a session's recorded cwd is this worktree or a directory below it.
233
+ *
234
+ * Both sides go through `resolve` before comparing. `git worktree list` returns
235
+ * platform separators while a session's `cwd` may have been written by a different
236
+ * source, so on Windows `C:\repo\wt` and `C:/repo/wt` name the same checkout but are
237
+ * different strings. The old comparison hardcoded `/`, so it matched nothing there:
238
+ * every `LAST_CHAT` was `-` and every bucket silently degraded to `unknown-usage`.
239
+ *
240
+ * `resolve` also normalises trailing separators and `..` segments, so neither can
241
+ * make one path look like an ancestor of the other by accident.
242
+ */
243
+ function sameOrInside(cwd, worktree) {
244
+ const child = resolve(cwd);
245
+ const parent = resolve(worktree);
246
+ return child === parent || child.startsWith(`${parent}${sep}`);
247
+ }
248
+ /** The newest supplied session whose cwd is this worktree or below it. */
249
+ function lastSession(worktree, sessions) {
250
+ if (sessions === void 0 || sessions.length === 0) return void 0;
251
+ const matches = sessions.filter((session) => sameOrInside(session.cwd ?? "", worktree));
252
+ if (matches.length === 0) return void 0;
253
+ return matches.toSorted((left, right) => (left.lastEventTime ?? 0) - (right.lastEventTime ?? 0))[matches.length - 1];
254
+ }
255
+ /** `LAST_CHAT` for one worktree. */
256
+ function lastChatColumn(session) {
257
+ return session === void 0 ? "-" : session.sessionId ?? "unknown";
258
+ }
259
+ /** Whether a session counts as recent for the bucket decision. */
260
+ function isRecent(session, now) {
261
+ const time = session?.lastEventTime ?? 0;
262
+ if (!(time > 0)) return false;
263
+ return Math.floor((now - time) / 86400) <= 4;
264
+ }
265
+ /**
266
+ * The suggested bucket.
267
+ *
268
+ * Uncommitted tracked work outranks everything, then an open PR, then the usage
269
+ * signal. An unknown usage signal never reaches `safe`: without the caller's
270
+ * session input the bucket stays `unknown-usage`, and the playbook asks the user.
271
+ */
272
+ function bucketFor(input) {
273
+ if (input.dirty.startsWith("wip:")) return "hold-wip";
274
+ if (input.pr.endsWith("/open") || input.pr.endsWith("/draft")) return "hold-open-pr";
275
+ if (!input.usageKnown) return UNKNOWN_USAGE_BUCKET;
276
+ if (input.usedRecently) return "verify-recent-chat";
277
+ if (input.merged === "YES" || input.pr !== "-") return "safe";
278
+ return "review";
279
+ }
280
+ /**
281
+ * Read this user's PRs from whichever forge CLI can answer.
282
+ *
283
+ * `origin` reports `status`, `gh` reports `state`; both are normalized to a
284
+ * lowercase `state` here. An unreachable forge is an empty list, not an error: the
285
+ * PR column is one signal among several and a first pass may run offline.
286
+ */
287
+ function readForgePrs(cwd, run = execFileSync) {
288
+ const origin = tryJson(run, cwd, "origin", [
289
+ "pr",
290
+ "list",
291
+ "--author",
292
+ "@me",
293
+ "--state",
294
+ "all",
295
+ "--limit",
296
+ "1000",
297
+ "--json",
298
+ "number,status,headRef"
299
+ ]);
300
+ if (origin !== void 0) return normalizeOrigin(origin);
301
+ const gh = tryJson(run, cwd, "gh", [
302
+ "pr",
303
+ "list",
304
+ "--author",
305
+ "@me",
306
+ "--state",
307
+ "all",
308
+ "--limit",
309
+ "1000",
310
+ "--json",
311
+ "number,state,headRefName"
312
+ ]);
313
+ if (gh !== void 0) return normalizeGh(gh);
314
+ return [];
315
+ }
316
+ function tryJson(run, cwd, command, args) {
317
+ try {
318
+ const out = run(command, args, {
319
+ cwd,
320
+ encoding: "utf8",
321
+ stdio: [
322
+ "ignore",
323
+ "pipe",
324
+ "ignore"
325
+ ],
326
+ maxBuffer: 33554432
327
+ });
328
+ return JSON.parse(out);
329
+ } catch {
330
+ return;
331
+ }
332
+ }
333
+ /** `[{number, status, headRef}]` from the `origin` CLI. */
334
+ function normalizeOrigin(raw) {
335
+ if (!Array.isArray(raw)) return [];
336
+ const prs = [];
337
+ for (const entry of raw) {
338
+ if (entry === null || typeof entry !== "object") continue;
339
+ const record = entry;
340
+ const number = record["number"];
341
+ const head = record["headRef"];
342
+ if (typeof number !== "number" || typeof head !== "string") continue;
343
+ prs.push({
344
+ number,
345
+ state: String(record["status"] ?? ""),
346
+ head
347
+ });
348
+ }
349
+ return prs;
350
+ }
351
+ /** `[{number, state, headRefName}]` from the `gh` CLI, with a lowercase state. */
352
+ function normalizeGh(raw) {
353
+ if (!Array.isArray(raw)) return [];
354
+ const prs = [];
355
+ for (const entry of raw) {
356
+ if (entry === null || typeof entry !== "object") continue;
357
+ const record = entry;
358
+ const number = record["number"];
359
+ const head = record["headRefName"];
360
+ if (typeof number !== "number" || typeof head !== "string") continue;
361
+ prs.push({
362
+ number,
363
+ state: String(record["state"] ?? "").toLowerCase(),
364
+ head
365
+ });
366
+ }
367
+ return prs;
368
+ }
369
+ /**
370
+ * Pick the base ref when the caller gave no `-b`.
371
+ *
372
+ * `origin/HEAD`, then `origin/main`, then `origin/master`, matching the shell
373
+ * script. An empty result means no base exists and the caller must pass one.
374
+ */
375
+ function resolveBase(repo) {
376
+ const candidates = [];
377
+ const head = git(repo, [
378
+ "symbolic-ref",
379
+ "--short",
380
+ "refs/remotes/origin/HEAD"
381
+ ]);
382
+ if (head !== void 0) candidates.push(head.trim());
383
+ candidates.push("origin/main", "origin/master");
384
+ return candidates.find((candidate) => candidate !== "" && git(repo, [
385
+ "rev-parse",
386
+ "--verify",
387
+ "--quiet",
388
+ `${candidate}^{commit}`
389
+ ]) !== void 0);
390
+ }
391
+ /** Build one row. Every column is a pure function so each has a unit test. */
392
+ function buildRow(worktree, context) {
393
+ const head = git(worktree, ["rev-parse", "HEAD"])?.trim();
394
+ const headTimestamp = Number(git(worktree, [
395
+ "log",
396
+ "-1",
397
+ "--format=%ct",
398
+ "HEAD"
399
+ ])?.trim() ?? 0);
400
+ const isAncestor = head !== void 0 && head !== "" && head !== "0" ? git(worktree, [
401
+ "merge-base",
402
+ "--is-ancestor",
403
+ head,
404
+ context.base
405
+ ]) !== void 0 : false;
406
+ const dirty = dirtyColumn(git(worktree, ["status", "--porcelain"]) ?? "");
407
+ const branchText = git(worktree, [
408
+ "symbolic-ref",
409
+ "--quiet",
410
+ "--short",
411
+ "HEAD"
412
+ ]);
413
+ const branch = branchText === void 0 ? "" : branchText.trim();
414
+ const hasRemote = branch !== "" && git(worktree, [
415
+ "show-ref",
416
+ "--verify",
417
+ "--quiet",
418
+ `refs/remotes/origin/${branch}`
419
+ ]) !== void 0;
420
+ const remoteSha = hasRemote ? git(worktree, ["rev-parse", `origin/${branch}`])?.trim() : void 0;
421
+ const aheadText = hasRemote ? git(worktree, [
422
+ "rev-list",
423
+ "--count",
424
+ `origin/${branch}..HEAD`
425
+ ]) : void 0;
426
+ const remote = remoteColumn({
427
+ branch: branch === "" ? void 0 : branch,
428
+ hasRemote,
429
+ remoteSha,
430
+ head: head?.trim(),
431
+ aheadCount: aheadText === void 0 ? void 0 : Number(aheadText.trim())
432
+ });
433
+ const pr = prColumn(branch === "" ? void 0 : branch, context.prs);
434
+ const session = lastSession(worktree, context.sessions);
435
+ const usageKnown = session !== void 0;
436
+ const sessionsProvided = context.sessions !== void 0;
437
+ const bucket = bucketFor({
438
+ dirty,
439
+ pr,
440
+ merged: mergedColumn(isAncestor),
441
+ usageKnown,
442
+ usedRecently: isRecent(session, context.now)
443
+ });
444
+ return {
445
+ size: sizeColumn(worktree),
446
+ age: ageColumn(headTimestamp, context.now),
447
+ merged: mergedColumn(isAncestor),
448
+ dirty,
449
+ remote,
450
+ pr,
451
+ lastChat: lastChatColumn(session),
452
+ pinned: PINNED,
453
+ bucket,
454
+ note: usageNote({
455
+ usageKnown,
456
+ sessionsProvided
457
+ }),
458
+ worktree
459
+ };
460
+ }
461
+ /**
462
+ * Why a row's usage signal is what it is.
463
+ *
464
+ * Both "nobody supplied a session list" and "a list was supplied but it never
465
+ * mentioned this worktree" produce the `unknown-usage` bucket, and the caller has
466
+ * to fix a different thing in each case: build the list, or widen it. Collapsing
467
+ * them would lose that distinction, which is the only diagnostic the row carries.
468
+ */
469
+ function usageNote(input) {
470
+ if (input.usageKnown) return void 0;
471
+ return input.sessionsProvided ? "no session in the supplied list touched this worktree" : "no session list supplied";
472
+ }
473
+ /** Sort rows by SIZE descending, preserving the original order on a tie. */
474
+ function sortRows(rows) {
475
+ const sizeOf = (row) => {
476
+ const match = /^([\d.]+)([BKMGTP]?)$/.exec(row.size);
477
+ if (match === null) return 0;
478
+ return Number(match[1]) * 1024 ** ({
479
+ "": 0,
480
+ B: 0,
481
+ K: 1,
482
+ M: 2,
483
+ G: 3,
484
+ T: 4,
485
+ P: 5
486
+ }[match[2]] ?? 0);
487
+ };
488
+ return rows.map((row, index) => ({
489
+ row,
490
+ index
491
+ })).sort((left, right) => sizeOf(right.row) - sizeOf(left.row) || left.index - right.index).map((entry) => entry.row);
492
+ }
493
+ /** Render the whole table, header included. */
494
+ function renderTable(rows, base) {
495
+ const lines = [`# base: ${base}`, HEADER.join(" ")];
496
+ for (const row of rows) lines.push([
497
+ row.size,
498
+ row.age,
499
+ row.merged,
500
+ row.dirty,
501
+ row.remote,
502
+ row.pr,
503
+ row.lastChat,
504
+ row.pinned,
505
+ row.bucket,
506
+ row.worktree
507
+ ].join(" "));
508
+ const notes = rows.filter((row) => row.note !== void 0);
509
+ if (notes.length > 0) {
510
+ lines.push("# usage signal unknown for:");
511
+ for (const row of notes) lines.push(`# ${row.worktree}: ${row.note}`);
512
+ }
513
+ return `${lines.join("\n")}\n`;
514
+ }
515
+ /**
516
+ * Read and validate the `--sessions` file.
517
+ *
518
+ * The shell version required a JSON array via `jq -e 'type == "array"'` and pinned
519
+ * the path before changing directory. Both hold here: the path is resolved before
520
+ * any `git -C`, and a non-array is an error rather than an empty list, because a
521
+ * silently ignored usage signal would quietly turn every bucket into
522
+ * `unknown-usage`.
523
+ *
524
+ * Every element is checked, not filtered. The array is a projection the caller
525
+ * builds from `pstack_history` results, so a malformed entry is a real mistake; the
526
+ * previous `filter` dropped such entries and let the row fall through to
527
+ * `unknown-usage`, which is exactly the silent data loss the paragraph above says
528
+ * this function refuses to do.
529
+ */
530
+ function readSessionsFile(path) {
531
+ const absolute = isAbsolute(path) ? path : resolve(process.cwd(), path);
532
+ let text;
533
+ try {
534
+ text = readFileSync(absolute, "utf8");
535
+ } catch {
536
+ throw new AuditError(`cannot read sessions file: ${path}`);
537
+ }
538
+ let parsed;
539
+ try {
540
+ parsed = JSON.parse(text);
541
+ } catch {
542
+ throw new AuditError(`sessions file must be ${SESSIONS_SHAPE}: ${path}`);
543
+ }
544
+ if (!Array.isArray(parsed)) throw new AuditError(`sessions file must be ${SESSIONS_SHAPE}: ${path}. Build it from pstack_history results; the history page itself is not an array.`);
545
+ return parsed.map((entry, index) => {
546
+ if (entry === null || typeof entry !== "object" || Array.isArray(entry)) throw new AuditError(`sessions[${index}] must be an object, got ${JSON.stringify(entry)?.slice(0, 60) ?? "undefined"}`);
547
+ const { sessionId, cwd, lastEventTime } = entry;
548
+ if (typeof sessionId !== "string" || sessionId === "") throw new AuditError(`sessions[${index}].sessionId must be a non-empty string`);
549
+ if (cwd !== void 0 && cwd !== null && typeof cwd !== "string") throw new AuditError(`sessions[${index}].cwd must be a string or null`);
550
+ if (lastEventTime !== void 0 && typeof lastEventTime !== "number") throw new AuditError(`sessions[${index}].lastEventTime must be a number`);
551
+ return {
552
+ sessionId,
553
+ ...cwd === void 0 ? {} : { cwd },
554
+ ...lastEventTime === void 0 ? {} : { lastEventTime }
555
+ };
556
+ });
557
+ }
558
+ /** Usage text, kept close to the shell script's help. */
559
+ const USAGE = [
560
+ "Usage: worktree-audit.mjs [-b|--base <ref>] [-s|--sessions <json>] [repo-path]",
561
+ " repo-path defaults to the current repo.",
562
+ " -b sets the ref the MERGED column checks against (e.g. origin/integration).",
563
+ " Without it the base is origin/HEAD, then origin/main, then origin/master.",
564
+ " -s takes the JSON you produced with `pstack_history`, an array of",
565
+ " {\"sessionId\",\"cwd\",\"lastEventTime\"}. This script never reads the session",
566
+ " store, so without it LAST_CHAT is \"-\" and the bucket is unknown-usage.",
567
+ " PINNED is always \"unknown\": this host exposes no pinned-state source, so the",
568
+ " user's own set decides.",
569
+ ""
570
+ ].join("\n");
571
+ /**
572
+ * Parse the command line.
573
+ *
574
+ * An unknown option and a missing argument value both exit 2, as the shell script
575
+ * did; an unreadable sessions file and a missing base exit 1.
576
+ */
577
+ function parseArgs(argv) {
578
+ let base;
579
+ let sessions;
580
+ const positional = [];
581
+ for (let index = 0; index < argv.length; index += 1) {
582
+ const argument = argv[index];
583
+ if (argument === "-h" || argument === "--help") return { help: true };
584
+ if (argument === "-b" || argument === "--base") {
585
+ const value = argv[index + 1];
586
+ if (value === void 0) throw new AuditError(`${argument} needs a ref`, 2);
587
+ base = value;
588
+ index += 1;
589
+ continue;
590
+ }
591
+ if (argument === "-s" || argument === "--sessions") {
592
+ const value = argv[index + 1];
593
+ if (value === void 0) throw new AuditError(`${argument} needs a JSON file`, 2);
594
+ sessions = value;
595
+ index += 1;
596
+ continue;
597
+ }
598
+ if (argument.startsWith("-")) throw new AuditError(`unknown option: ${argument}`, 2);
599
+ positional.push(argument);
600
+ }
601
+ if (positional.length > 1) throw new AuditError(`expected at most one repo path, received ${positional.length}`, 2);
602
+ return {
603
+ ...base === void 0 ? {} : { base },
604
+ ...sessions === void 0 ? {} : { sessions },
605
+ ...positional[0] === void 0 ? {} : { repo: positional[0] },
606
+ help: false
607
+ };
608
+ }
609
+ /** Run the audit. Returns the process exit code. */
610
+ function main(argv, io = {
611
+ stdout: (value) => process.stdout.write(value),
612
+ stderr: (value) => process.stderr.write(value)
613
+ }, options = {}) {
614
+ try {
615
+ const args = parseArgs(argv);
616
+ if (args.help) {
617
+ io.stdout(USAGE);
618
+ return 0;
619
+ }
620
+ const sessions = args.sessions === void 0 ? void 0 : readSessionsFile(args.sessions);
621
+ const cwd = options.cwd ?? process.cwd();
622
+ const repo = args.repo ?? gitHere(cwd, ["rev-parse", "--show-toplevel"])?.trim() ?? (() => {
623
+ throw new AuditError("not in a git repo; pass a repo path");
624
+ })();
625
+ if (git(repo, ["rev-parse", "--git-dir"]) === void 0) throw new AuditError(`not a git repo: ${repo}`);
626
+ const paths = worktreePaths(repo);
627
+ const mainWorktree = paths[0];
628
+ if (mainWorktree === void 0) throw new AuditError(`not a git repo: ${repo}`);
629
+ let base = args.base;
630
+ if (base === void 0) {
631
+ base = resolveBase(repo);
632
+ if (base === void 0) throw new AuditError("no base ref (origin/HEAD, origin/main, origin/master all missing); pass -b <ref>");
633
+ io.stderr(`warn: no -b given; MERGED checks against ${base}\n`);
634
+ }
635
+ if (base.startsWith("origin/")) {
636
+ if (git(repo, [
637
+ "fetch",
638
+ "origin",
639
+ `+refs/heads/${base.slice(7)}:refs/remotes/${base}`,
640
+ "--quiet"
641
+ ]) === void 0) io.stderr(`warn: could not fetch ${base}; merged column may be stale\n`);
642
+ }
643
+ if (git(repo, [
644
+ "rev-parse",
645
+ "--verify",
646
+ "--quiet",
647
+ `${base}^{commit}`
648
+ ]) === void 0) throw new AuditError(`base ref not found: ${base}`);
649
+ const prs = readForgePrs(repo);
650
+ const now = options.now ?? Math.floor(Date.now() / 1e3);
651
+ const context = {
652
+ base,
653
+ repo,
654
+ mainWorktree,
655
+ prs,
656
+ sessions,
657
+ now
658
+ };
659
+ const rows = paths.filter((path) => path !== mainWorktree).map((path) => buildRow(path, context));
660
+ io.stdout(renderTable(sortRows(rows), base));
661
+ return 0;
662
+ } catch (error) {
663
+ if (error instanceof AuditError) {
664
+ io.stderr(`error: ${error.message}\n`);
665
+ return error.exitCode;
666
+ }
667
+ const message = error instanceof Error ? error.message : String(error);
668
+ io.stderr(`error: ${message}\n`);
669
+ return 1;
670
+ }
671
+ }
672
+ const entryPoint = process.argv[1];
673
+ if (entryPoint !== void 0 && resolve(entryPoint) === fileURLToPath(import.meta.url)) process.exitCode = main(process.argv.slice(2));
674
+ //#endregion
675
+ export { AuditError, HEADER, PINNED, RECENT_DAYS, UNKNOWN_USAGE_BUCKET, USAGE, ageColumn, bucketFor, buildRow, dirtyColumn, formatSize, isRecent, lastChatColumn, lastSession, main, mergedColumn, normalizeGh, normalizeOrigin, parseArgs, prColumn, readForgePrs, readSessionsFile, remoteColumn, renderTable, resolveBase, sameOrInside, sizeColumn, sortRows, usageNote, worktreePaths };
@@ -4,8 +4,6 @@ description: Apply when two or more fixes that share one premise have failed the
4
4
  disable-model-invocation: true
5
5
  ---
6
6
 
7
- > DSH port of pstack. `pstack_subagent` replaces Cursor's `Task` tool, and `role` replaces Cursor model slugs. Full mapping: `../../docs/harness/dsh.md`.
8
-
9
7
  # Attack the Premise
10
8
 
11
9
  When two or more fixes that share one premise have failed the same gate, suspect the premise, not the fixes.
@@ -4,8 +4,6 @@ description: Apply when wiring validation, error handling, or framework adapters
4
4
  disable-model-invocation: true
5
5
  ---
6
6
 
7
- > DSH port of pstack. `pstack_subagent` replaces Cursor's `Task` tool, and `role` replaces Cursor model slugs. Full mapping: `../../docs/harness/dsh.md`.
8
-
9
7
  # Boundary Discipline
10
8
 
11
9
  Place validation, type narrowing, and error handling at system boundaries. Trust internal code unconditionally. Business logic lives in pure functions. The shell is thin and mechanical.
@@ -3,9 +3,6 @@ name: principle-build-the-lever
3
3
  description: "Apply to any non-trivial work, not just bulk work: edits, migrations, analyses, checks. Build the tool that does it or proves it (codemod, script, generator, or a skill your subagents follow) instead of working by hand. The tool is the artifact a reviewer can rerun."
4
4
  disable-model-invocation: true
5
5
  ---
6
-
7
- > DSH port of pstack. `pstack_subagent` replaces Cursor's `Task` tool, and `role` replaces Cursor model slugs. Full mapping: `../../docs/harness/dsh.md`.
8
-
9
6
  # Build the Lever
10
7
 
11
8
  When the work isn't trivial, build the tool that does it instead of doing it by hand.