@joshuafolkken/kit 1.1229.0 → 1.1370.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (939) hide show
  1. package/.claude/agents/investigator.md +1 -0
  2. package/.claude/settings.json +4 -0
  3. package/.claude/skills/dependency-update/SKILL.md +5 -3
  4. package/.claude/skills/epic-commands/SKILL.md +82 -113
  5. package/.claude/skills/epic-commands/epic-bundle.md +38 -63
  6. package/.claude/skills/epic-commands/execution-waves.md +30 -51
  7. package/.claude/skills/verify-ui/SKILL.md +13 -20
  8. package/.claude/skills/workflow-commands/SKILL.md +10 -10
  9. package/.claude/skills/workflow-commands/background-commands.md +4 -4
  10. package/.claude/skills/workflow-commands/backlogrun-child.md +30 -105
  11. package/.claude/skills/workflow-commands/backlogrun-handoff-report.md +29 -0
  12. package/.claude/skills/workflow-commands/backlogrun-lanes.md +45 -131
  13. package/.claude/skills/workflow-commands/backlogrun-park.md +36 -53
  14. package/.claude/skills/workflow-commands/backlogrun-progress.md +81 -331
  15. package/.claude/skills/workflow-commands/backlogrun-recovery.md +29 -83
  16. package/.claude/skills/workflow-commands/backlogrun-steps.md +105 -424
  17. package/.claude/skills/workflow-commands/backlogrun.md +50 -61
  18. package/.claude/skills/workflow-commands/chain-rule.md +36 -40
  19. package/.claude/skills/workflow-commands/entry-sequence.md +6 -6
  20. package/.claude/skills/workflow-commands/followup.md +24 -20
  21. package/.claude/skills/workflow-commands/fullrun-steps.md +23 -27
  22. package/.claude/skills/workflow-commands/fullrun.md +10 -10
  23. package/.claude/skills/workflow-commands/halfrun.md +9 -8
  24. package/.claude/skills/workflow-commands/into-target.md +12 -18
  25. package/.claude/skills/workflow-commands/issue-comments.md +11 -26
  26. package/.claude/skills/workflow-commands/kickoff.md +27 -16
  27. package/.claude/skills/workflow-commands/latest-gate.md +18 -29
  28. package/.claude/skills/workflow-commands/needs-human-review.md +13 -24
  29. package/.claude/skills/workflow-commands/observation-filing.md +37 -28
  30. package/.claude/skills/workflow-commands/observation-ledger.md +48 -38
  31. package/.claude/skills/workflow-commands/pre-gate-cut.md +9 -9
  32. package/.claude/skills/workflow-commands/prerequisite.md +23 -15
  33. package/.claude/skills/workflow-commands/progress-watcher.md +17 -11
  34. package/.claude/skills/workflow-commands/prrun.md +3 -3
  35. package/.claude/skills/workflow-commands/retrospective.md +13 -18
  36. package/.claude/skills/workflow-commands/split-assessment.md +6 -4
  37. package/.claude/skills/workflow-commands/target-repository.md +25 -28
  38. package/.claude/skills/workflow-commands/working-tree-hold.md +11 -17
  39. package/.gitattributes +2 -1
  40. package/.github/workflows/ci.yml +14 -0
  41. package/.github/workflows/publish.yml +2 -0
  42. package/.vscode/tasks.json +14 -0
  43. package/CLAUDE.md +10 -61
  44. package/README.md +38 -57
  45. package/SECURITY.md +1 -1
  46. package/dist/CLAUDE.md +10 -61
  47. package/dist/commands/document-section-cli.js +42 -10
  48. package/dist/config-merge/index.js +11 -2
  49. package/dist/hooks/audit-provision.js +2 -2
  50. package/dist/hooks/batch-guard.js +7 -7
  51. package/dist/hooks/{chunk-FIVDHQGT.js → chunk-43G45XJF.js} +18 -20
  52. package/dist/hooks/{chunk-JUDKDCDP.js → chunk-4TW4MQUL.js} +284 -362
  53. package/dist/hooks/{chunk-5VMKCCC4.js → chunk-76RK6E3H.js} +13 -11
  54. package/dist/hooks/{chunk-RNWHN5BP.js → chunk-DZWZ3DKY.js} +4 -4
  55. package/dist/hooks/{chunk-5VNDSNG3.js → chunk-FZ6FUSBM.js} +1 -1
  56. package/dist/hooks/{chunk-VC3PZPZO.js → chunk-GG72ANKI.js} +1 -1
  57. package/dist/hooks/{chunk-6HJJXRBX.js → chunk-KPM4YIIX.js} +8 -44
  58. package/dist/hooks/chunk-MXVQMLDP.js +3705 -0
  59. package/dist/hooks/{chunk-ELCN5LCH.js → chunk-NEC4AT4Z.js} +34 -12
  60. package/dist/hooks/{chunk-TQNPDZNH.js → chunk-NZBHG6FW.js} +7 -5
  61. package/dist/hooks/chunk-NZN2UFI6.js +2409 -0
  62. package/dist/hooks/{chunk-F56MFS4B.js → chunk-R6CRQEAL.js} +4 -4
  63. package/dist/hooks/chunk-SYSRHRWU.js +1589 -0
  64. package/dist/hooks/{chunk-55HHG5PX.js → chunk-TLJYAGZK.js} +799 -903
  65. package/dist/hooks/chunk-Z5TMJIPW.js +45 -0
  66. package/dist/hooks/codex-hook-adapter.js +26 -21
  67. package/dist/hooks/duplicate-read-guard.js +8 -8
  68. package/dist/hooks/format-edited.js +4 -4
  69. package/dist/hooks/inputs.json +213 -197
  70. package/dist/hooks/investigation-guard.js +8 -8
  71. package/dist/hooks/pretool-guard.js +15 -15
  72. package/dist/hooks/session-lang.js +406 -8
  73. package/dist/hooks/stop-guard.js +122 -201
  74. package/dist/josh.js +540 -137
  75. package/dist/version/index.js +15 -13
  76. package/eslint/base.js +43 -5
  77. package/eslint/rules/english-only-prose.js +3 -3
  78. package/eslint/rules/import.js +12 -0
  79. package/eslint/rules/namespace-object-export.js +2 -2
  80. package/package.json +16 -10
  81. package/pnpm-workspace.yaml +2 -4
  82. package/prompts/coding-standards.md +14 -48
  83. package/prompts/collaboration-workflow/file-edits.md +1 -1
  84. package/prompts/collaboration-workflow/issue-citation.md +1 -1
  85. package/prompts/collaboration-workflow/issue-template.md +4 -10
  86. package/prompts/collaboration-workflow/operating-rules.md +7 -8
  87. package/prompts/collaboration-workflow/output-bounds.md +1 -1
  88. package/prompts/collaboration-workflow/overview.md +1 -1
  89. package/prompts/collaboration-workflow/plan-comment.md +2 -1
  90. package/prompts/collaboration-workflow/principles.md +21 -3
  91. package/prompts/collaboration-workflow/report-format.md +16 -29
  92. package/prompts/collaboration-workflow/residency.md +1 -1
  93. package/prompts/collaboration-workflow/rule-delivery.md +7 -95
  94. package/prompts/collaboration-workflow/shell-body.md +3 -23
  95. package/prompts/collaboration-workflow/turn-batching.md +4 -13
  96. package/prompts/collaboration-workflow/wip-cap.md +5 -11
  97. package/prompts/refactoring.md +1 -1
  98. package/prompts/review-rubric.md +3 -22
  99. package/prompts/review.md +15 -38
  100. package/prompts/testing-guide.md +2 -4
  101. package/scripts/adopt/adopt-logic.ts +5 -5
  102. package/scripts/adopt/adopt-toolkits.ts +4 -5
  103. package/scripts/adopt/adopt.ts +2 -3
  104. package/scripts/agent/agent-argv.ts +7 -7
  105. package/scripts/agent/agent-diagnostics.ts +2 -2
  106. package/scripts/agent/agent-exit-record.ts +1 -1
  107. package/scripts/agent/agent-headless.ts +1 -1
  108. package/scripts/agent/agent-launch-environment.ts +6 -1
  109. package/scripts/agent/agent-role-profile.ts +49 -22
  110. package/scripts/agent/agent-session-role.ts +32 -0
  111. package/scripts/agent/api-outage.ts +1 -1
  112. package/scripts/agent/claude-agent-argv.ts +4 -4
  113. package/scripts/agent/claude-result-event.ts +4 -4
  114. package/scripts/agent/codex-hooks.ts +2 -2
  115. package/scripts/agent/interactive-ask.ts +3 -6
  116. package/scripts/auto-ok/auto-ok-cli.ts +46 -60
  117. package/scripts/backlog/backlog-arrival-added.ts +34 -0
  118. package/scripts/backlog/backlog-arrival.ts +54 -17
  119. package/scripts/backlog/backlog-budget-cli.ts +34 -6
  120. package/scripts/backlog/backlog-budget.ts +17 -24
  121. package/scripts/backlog/backlog-defect-priority.ts +1 -1
  122. package/scripts/backlog/backlog-drive-args.ts +5 -4
  123. package/scripts/backlog/backlog-drive-cli.ts +14 -10
  124. package/scripts/backlog/backlog-drive-epic.ts +85 -0
  125. package/scripts/backlog/backlog-drive-launch.ts +1 -1
  126. package/scripts/backlog/backlog-drive-named-offer.ts +60 -9
  127. package/scripts/backlog/backlog-drive-named.ts +39 -9
  128. package/scripts/backlog/backlog-drive-offer-argv.ts +1 -1
  129. package/scripts/backlog/backlog-drive-restore.ts +1 -1
  130. package/scripts/backlog/backlog-drive-retrospective.ts +2 -2
  131. package/scripts/backlog/backlog-drive.ts +43 -28
  132. package/scripts/backlog/backlog-idle.ts +88 -0
  133. package/scripts/backlog/backlog-named.ts +11 -15
  134. package/scripts/backlog/backlog-next.ts +26 -30
  135. package/scripts/backlog/backlog-offer-cli.ts +28 -23
  136. package/scripts/backlog/backlog-offer.ts +7 -7
  137. package/scripts/backlog/backlog-overlap.ts +178 -0
  138. package/scripts/backlog/backlog-plan-cli.ts +14 -90
  139. package/scripts/backlog/backlog-plan-read.ts +111 -0
  140. package/scripts/backlog/backlog-plan.ts +11 -10
  141. package/scripts/backlog/backlog-pool.ts +13 -14
  142. package/scripts/backlog/backlog-rank.ts +11 -11
  143. package/scripts/backlog/backlog-ready.ts +15 -10
  144. package/scripts/backlog/backlog-scope.ts +14 -15
  145. package/scripts/backlog/backlog-stalled-cli.ts +2 -2
  146. package/scripts/backlog/backlog-stalled-detect.ts +4 -4
  147. package/scripts/backlog/backlog-stalled.ts +5 -6
  148. package/scripts/backlog/backlog-waves.ts +4 -4
  149. package/scripts/backlog/backlogrun-args.ts +74 -0
  150. package/scripts/backlog/backlogrun-cli.ts +113 -0
  151. package/scripts/backlog/backlogrun-launch.ts +178 -0
  152. package/scripts/behavior/behavior-assertion.ts +6 -8
  153. package/scripts/behavior/behavior-cli.ts +1 -1
  154. package/scripts/behavior/behavior-rules.ts +3 -3
  155. package/scripts/build/build-claude-md.ts +4 -4
  156. package/scripts/build/build-codex-hooks.ts +2 -2
  157. package/scripts/build/build-commands.ts +1 -1
  158. package/scripts/build/build-hooks.ts +5 -5
  159. package/scripts/build/build.ts +1 -1
  160. package/scripts/build/hook-bundle-stamp.ts +109 -7
  161. package/scripts/build/local-bin.ts +2 -2
  162. package/scripts/cases/cases-cli.ts +1 -1
  163. package/scripts/cases/cases-logic.ts +2 -2
  164. package/scripts/ci/composite-actions.ts +1 -2
  165. package/scripts/ci/pr-classification.ts +2 -2
  166. package/scripts/claude/workflow-destination.ts +1 -1
  167. package/scripts/clone/clone-aggregate.ts +1 -1
  168. package/scripts/clone/clone-fingerprint.ts +1 -1
  169. package/scripts/clone/clone-scan-cli.ts +1 -1
  170. package/scripts/clone/clone-scan.ts +1 -1
  171. package/scripts/config-merge/index.ts +1 -1
  172. package/scripts/config-merge/json-format.ts +1 -3
  173. package/scripts/config-merge/patch-json-array.ts +90 -0
  174. package/scripts/config-merge/patch-json-key.ts +6 -3
  175. package/scripts/config-merge/patch-json-list.ts +1 -1
  176. package/scripts/cost-runtime/codex-usage.ts +1 -1
  177. package/scripts/cost-runtime/context-cut-payback.ts +4 -5
  178. package/scripts/cost-runtime/context-cut-threshold.ts +4 -6
  179. package/scripts/cost-runtime/cost-attribute.ts +3 -3
  180. package/scripts/cost-runtime/cost-blocks.ts +3 -4
  181. package/scripts/cost-runtime/cost-cli.ts +14 -11
  182. package/scripts/cost-runtime/cost-corpus.ts +11 -11
  183. package/scripts/cost-runtime/cost-pricing.ts +4 -4
  184. package/scripts/cost-runtime/cost-tokens.ts +1 -2
  185. package/scripts/cost-runtime/cost-transcript.ts +29 -29
  186. package/scripts/cost-runtime/cost-usage.ts +6 -7
  187. package/scripts/cost-runtime/cost-verdict.ts +10 -11
  188. package/scripts/cost-runtime/own-session.ts +1 -1
  189. package/scripts/cost-runtime/transcript-cwd.ts +2 -2
  190. package/scripts/delegation/delegation-cli.ts +4 -4
  191. package/scripts/delegation/delegation-policy.ts +13 -15
  192. package/scripts/delegation/duplicate-read-guard.ts +9 -10
  193. package/scripts/delegation/fanout-cli.ts +1 -1
  194. package/scripts/delegation/fanout.ts +1 -1
  195. package/scripts/delegation/investigation-guard.ts +18 -22
  196. package/scripts/delegation/investigation-reads.ts +48 -238
  197. package/scripts/discovery/repo-discovery.ts +1 -1
  198. package/scripts/discovery/repo-map-logic.ts +1 -2
  199. package/scripts/discovery/repo-origin.ts +3 -3
  200. package/scripts/discovery/repo-party-cli.ts +2 -2
  201. package/scripts/discovery/repo-party.ts +2 -2
  202. package/scripts/doctor/doctor-consumer.ts +1 -1
  203. package/scripts/doctor/doctor-io.ts +6 -7
  204. package/scripts/doctor/doctor-logic.ts +1 -1
  205. package/scripts/doctor/doctor-ports.ts +1 -1
  206. package/scripts/doctor/doctor.ts +8 -9
  207. package/scripts/document/backlogrun-parent-read-set.ts +5 -6
  208. package/scripts/document/bash-output-cap.ts +5 -7
  209. package/scripts/document/capped-print-part.ts +1 -1
  210. package/scripts/document/capped-print.ts +1 -1
  211. package/scripts/document/document-byte-budget.ts +33 -64
  212. package/scripts/document/document-byte-check.ts +4 -4
  213. package/scripts/document/document-reachability.ts +7 -8
  214. package/scripts/document/document-read-cli.ts +2 -2
  215. package/scripts/document/document-scan.ts +26 -2
  216. package/scripts/document/document-section-cli.ts +6 -8
  217. package/scripts/document/document-section.ts +8 -12
  218. package/scripts/document/edit-files-cli.ts +3 -4
  219. package/scripts/document/entry-read-budget.ts +8 -70
  220. package/scripts/document/entry-read-set.ts +51 -34
  221. package/scripts/document/lane-child-read-set.ts +9 -9
  222. package/scripts/document/read-files-cli.ts +1 -2
  223. package/scripts/document/read-set-cli.ts +16 -19
  224. package/scripts/document/read-set-cost.ts +4 -4
  225. package/scripts/document/read-set-point-of-use.ts +28 -38
  226. package/scripts/document/read-set-pricing.ts +1 -1
  227. package/scripts/document/read-set-trim.ts +3 -3
  228. package/scripts/document/resident-budget.ts +8 -10
  229. package/scripts/epic/epic-add-body.ts +15 -18
  230. package/scripts/epic/epic-add-plan.ts +26 -28
  231. package/scripts/epic/epic-add.ts +32 -25
  232. package/scripts/epic/epic-audit-checks.ts +27 -37
  233. package/scripts/epic/epic-audit-cli.ts +21 -22
  234. package/scripts/epic/epic-audit-orphans.ts +16 -17
  235. package/scripts/epic/epic-audit-rationale.ts +10 -15
  236. package/scripts/epic/epic-audit-report.ts +2 -5
  237. package/scripts/epic/epic-audit.ts +18 -14
  238. package/scripts/epic/epic-body.ts +10 -10
  239. package/scripts/epic/epic-bundle-cli.ts +36 -34
  240. package/scripts/epic/epic-bundle-evidence.ts +5 -5
  241. package/scripts/epic/epic-bundle-gaps.ts +6 -9
  242. package/scripts/epic/epic-bundle-poll.ts +1 -1
  243. package/scripts/epic/epic-bundle-referenced.ts +11 -14
  244. package/scripts/epic/epic-bundle.ts +19 -20
  245. package/scripts/epic/epic-busy.ts +44 -21
  246. package/scripts/epic/epic-candidate-confirm.ts +15 -18
  247. package/scripts/epic/epic-chains.ts +18 -23
  248. package/scripts/epic/epic-classify.ts +11 -12
  249. package/scripts/epic/epic-cli-argv.ts +5 -6
  250. package/scripts/epic/epic-cli-remove.ts +9 -4
  251. package/scripts/epic/epic-cli.ts +38 -26
  252. package/scripts/epic/epic-close-comment.ts +14 -15
  253. package/scripts/epic/epic-close.ts +25 -29
  254. package/scripts/epic/epic-cross-repo.ts +18 -21
  255. package/scripts/epic/epic-decision.ts +14 -18
  256. package/scripts/epic/epic-fetch.ts +25 -31
  257. package/scripts/epic/epic-graph.ts +15 -17
  258. package/scripts/epic/epic-index.ts +14 -16
  259. package/scripts/epic/epic-issue.ts +9 -11
  260. package/scripts/epic/epic-label-age.ts +74 -0
  261. package/scripts/epic/epic-lane-offer.ts +35 -24
  262. package/scripts/epic/epic-nested.ts +1 -1
  263. package/scripts/epic/epic-next-read.ts +8 -8
  264. package/scripts/epic/epic-next-views.ts +12 -12
  265. package/scripts/epic/epic-next.ts +29 -33
  266. package/scripts/epic/epic-outside-blocker.ts +11 -10
  267. package/scripts/epic/epic-parse.ts +22 -24
  268. package/scripts/epic/epic-promote.ts +3 -2
  269. package/scripts/epic/epic-rank.ts +1 -1
  270. package/scripts/epic/epic-read.ts +10 -8
  271. package/scripts/epic/epic-reconcile.ts +8 -6
  272. package/scripts/epic/epic-reference.ts +5 -4
  273. package/scripts/epic/epic-relation-recheck.ts +10 -11
  274. package/scripts/epic/epic-relations.ts +9 -8
  275. package/scripts/epic/epic-remove-plan.ts +4 -5
  276. package/scripts/epic/epic-remove.ts +7 -5
  277. package/scripts/epic/epic-report.ts +18 -20
  278. package/scripts/epic/epic-run.ts +6 -5
  279. package/scripts/epic/epic-sections.ts +2 -2
  280. package/scripts/epic/epic-shape.ts +3 -3
  281. package/scripts/epic/epic-solo-stale.ts +3 -2
  282. package/scripts/epic/epic-solo.ts +8 -8
  283. package/scripts/epic/epic-triage.ts +5 -4
  284. package/scripts/epic/epic-validate.ts +8 -7
  285. package/scripts/epic/epic.ts +5 -5
  286. package/scripts/exports/unused-members-cli.ts +1 -1
  287. package/scripts/followup/followup-issue-number.ts +1 -2
  288. package/scripts/followup/git-followup-cleanup.ts +6 -7
  289. package/scripts/followup/git-followup-finish.ts +11 -13
  290. package/scripts/followup/git-followup-flush.ts +11 -7
  291. package/scripts/followup/git-followup-issue-close.ts +16 -13
  292. package/scripts/followup/git-followup-label.ts +9 -6
  293. package/scripts/followup/git-followup-merged.ts +1 -1
  294. package/scripts/followup/git-followup-pending.ts +7 -9
  295. package/scripts/followup/git-followup-stages.ts +28 -17
  296. package/scripts/followup/git-followup-workflow.ts +19 -21
  297. package/scripts/followup/git-pr-followup-checks.ts +13 -20
  298. package/scripts/followup/git-pr-followup-wrapup.ts +7 -7
  299. package/scripts/followup/git-pr-followup.ts +18 -17
  300. package/scripts/gate/core-admission.ts +162 -0
  301. package/scripts/gate/core-budget.ts +134 -91
  302. package/scripts/gate/gate-ledger.ts +114 -0
  303. package/scripts/gate/gate-log.ts +7 -9
  304. package/scripts/gate/gate-plan.ts +103 -35
  305. package/scripts/gate/gate-report.ts +39 -21
  306. package/scripts/gate/gate-skip.ts +11 -13
  307. package/scripts/gate/gate-steps.ts +5 -1
  308. package/scripts/gate/gate-tree.ts +3 -4
  309. package/scripts/gate/hook-gate-reuse.ts +9 -9
  310. package/scripts/gate/machine-capacity.ts +313 -0
  311. package/scripts/gate/pre-commit-type-check.ts +4 -4
  312. package/scripts/gate/project-checks.ts +12 -4
  313. package/scripts/gate/scoped-green.ts +11 -18
  314. package/scripts/gate/type-check-command.ts +2 -2
  315. package/scripts/gate/type-check-step.ts +4 -4
  316. package/scripts/gate/verification-gate.ts +60 -53
  317. package/scripts/gh/gh-spawn.ts +2 -2
  318. package/scripts/gh/git-ai-review-scan.ts +3 -2
  319. package/scripts/gh/git-gh-api-path.ts +10 -11
  320. package/scripts/gh/git-gh-exec.ts +43 -48
  321. package/scripts/gh/git-gh-failure.ts +6 -9
  322. package/scripts/gh/git-gh-helpers.ts +1 -1
  323. package/scripts/gh/git-gh-issue-list.ts +15 -19
  324. package/scripts/gh/git-gh-issue-read.ts +43 -60
  325. package/scripts/gh/git-gh-issue-rest.ts +14 -15
  326. package/scripts/gh/git-gh-issue-write.ts +52 -40
  327. package/scripts/gh/git-gh-issue.ts +23 -24
  328. package/scripts/gh/git-gh-pr-auto-merge.ts +3 -3
  329. package/scripts/gh/git-gh-pr-read.ts +46 -50
  330. package/scripts/gh/git-gh-pr-rest.ts +23 -26
  331. package/scripts/gh/git-gh-pr-review.ts +2 -2
  332. package/scripts/gh/git-gh-pr-rollup.ts +4 -4
  333. package/scripts/gh/git-gh-pr-snapshot.ts +8 -10
  334. package/scripts/gh/git-gh-pr.ts +16 -16
  335. package/scripts/gh/git-gh-reachability.ts +11 -12
  336. package/scripts/gh/git-gh-repo.ts +2 -3
  337. package/scripts/gh/git-gh-rest-state.ts +1 -1
  338. package/scripts/gh/git-pr-ai-review.ts +6 -5
  339. package/scripts/gh/git-pr-checks-eval.ts +28 -30
  340. package/scripts/gh/git-pr-checks-parse.ts +14 -16
  341. package/scripts/gh/git-pr-checks-watch.ts +17 -17
  342. package/scripts/gh/git-pr-checks.ts +20 -23
  343. package/scripts/gh/git-pr-coderabbit.ts +8 -6
  344. package/scripts/gh/git-pr-confirmation.ts +5 -5
  345. package/scripts/gh/git-pr-managed-config.ts +7 -9
  346. package/scripts/gh/git-pr-messages.ts +1 -1
  347. package/scripts/gh/git-pr.ts +15 -16
  348. package/scripts/gh/github-issue-url.ts +8 -9
  349. package/scripts/git/base-tree.ts +66 -0
  350. package/scripts/git/change-base.ts +42 -2
  351. package/scripts/git/changed-file-scope.ts +5 -5
  352. package/scripts/git/changed-paths.ts +1 -2
  353. package/scripts/git/constants.ts +2 -2
  354. package/scripts/git/git-branch.ts +1 -1
  355. package/scripts/git/git-closes-keyword.ts +3 -3
  356. package/scripts/git/git-command.ts +53 -41
  357. package/scripts/git/git-common-directory.ts +3 -3
  358. package/scripts/git/git-diff-reads.ts +14 -15
  359. package/scripts/git/git-error.ts +1 -1
  360. package/scripts/git/git-execa-error.ts +1 -2
  361. package/scripts/git/git-issue.ts +10 -8
  362. package/scripts/git/git-location-environment.ts +3 -4
  363. package/scripts/git/git-ls-remote.ts +6 -8
  364. package/scripts/git/git-pre-push-hook.ts +11 -10
  365. package/scripts/git/git-preflight.ts +5 -5
  366. package/scripts/git/git-push-transport.ts +2 -2
  367. package/scripts/git/git-remote-branch.ts +1 -2
  368. package/scripts/git/git-schemas.ts +16 -23
  369. package/scripts/git/git-spawn-sync.ts +1 -1
  370. package/scripts/git/git-spawn.ts +37 -14
  371. package/scripts/git/git-ssh-keepalive.ts +12 -5
  372. package/scripts/git/git-staging.ts +7 -8
  373. package/scripts/git/git-workflow.ts +1 -1
  374. package/scripts/git/git-worktree.ts +35 -27
  375. package/scripts/git/gone-branch.ts +2 -2
  376. package/scripts/git/listing-cutoff.ts +1 -2
  377. package/scripts/git/lockfile-sync.ts +65 -0
  378. package/scripts/git/main-merge-guard.ts +1 -2
  379. package/scripts/git/main-merge.ts +7 -7
  380. package/scripts/git/main-sync.ts +23 -8
  381. package/scripts/git/parse-json-array.ts +18 -23
  382. package/scripts/git/repository-lock.ts +34 -2
  383. package/scripts/git/stash/git-stash.ts +4 -5
  384. package/scripts/git/stash/stash-orphans.ts +5 -3
  385. package/scripts/git/stash/stash-pop-args.ts +1 -1
  386. package/scripts/git/stash/stash-pop-cli.ts +3 -3
  387. package/scripts/git/stash/stash-sweep-lock.ts +2 -2
  388. package/scripts/hooks/batch-guard.ts +11 -13
  389. package/scripts/hooks/check-commit-message.ts +12 -9
  390. package/scripts/hooks/codex-hook-adapter.ts +16 -10
  391. package/scripts/hooks/edited-cspell.ts +3 -4
  392. package/scripts/hooks/format-edited-cli.ts +1 -1
  393. package/scripts/hooks/format-edited-file.ts +11 -17
  394. package/scripts/hooks/format-rewrite-notice.ts +19 -17
  395. package/scripts/hooks/pre-push-unit.ts +10 -14
  396. package/scripts/hooks/pretool-guard-cli.ts +4 -4
  397. package/scripts/hooks/pretool-guard.ts +93 -18
  398. package/scripts/hooks/reserved-run.ts +2 -2
  399. package/scripts/hooks/step-zero-notice.ts +1 -1
  400. package/scripts/hooks/stop-guard.ts +21 -10
  401. package/scripts/init/basic-path-migration.ts +2 -2
  402. package/scripts/init/claude-kit-only-settings.ts +2 -2
  403. package/scripts/init/claude-plugin-config.ts +2 -2
  404. package/scripts/init/distributed-paths.ts +4 -4
  405. package/scripts/init/hook-command-rewrite.ts +3 -3
  406. package/scripts/init/hook-launch.ts +5 -5
  407. package/scripts/init/init-actions.ts +13 -0
  408. package/scripts/init/init-ai-copy.ts +11 -11
  409. package/scripts/init/init-bootstrap.ts +3 -3
  410. package/scripts/init/init-copy-content.ts +4 -4
  411. package/scripts/init/init-logic-json-merge.ts +7 -9
  412. package/scripts/init/init-logic-migrate.ts +1 -1
  413. package/scripts/init/init-logic-templates.ts +1 -1
  414. package/scripts/init/init-logic-workspace.ts +4 -4
  415. package/scripts/init/init-logic-yaml-merge.ts +2 -2
  416. package/scripts/init/init-logic.ts +19 -22
  417. package/scripts/init/init.ts +12 -8
  418. package/scripts/init/kit-base-preset.ts +1 -1
  419. package/scripts/init/kit-setup-state.ts +1 -1
  420. package/scripts/init/kit-written-paths.ts +1 -2
  421. package/scripts/init/package-manager-pin.ts +35 -0
  422. package/scripts/init/project-profile-cli.ts +1 -1
  423. package/scripts/init/project-profile.ts +3 -3
  424. package/scripts/init/session-language-environment.ts +1 -1
  425. package/scripts/init/start-exec.ts +3 -4
  426. package/scripts/init/start-plan.ts +2 -2
  427. package/scripts/init/start-setup-pr.ts +3 -2
  428. package/scripts/init/start-steps.ts +2 -2
  429. package/scripts/init/tsconfig-preset-migration.ts +1 -1
  430. package/scripts/init/vscode-tasks.ts +62 -0
  431. package/scripts/issue/baseline-measure.ts +2 -2
  432. package/scripts/issue/behavior-change-lint.ts +2 -2
  433. package/scripts/issue/defect-rate-cli.ts +6 -7
  434. package/scripts/issue/defect-rate.ts +37 -27
  435. package/scripts/issue/git-next-issues.ts +9 -8
  436. package/scripts/issue/issue-auto-ok.ts +49 -11
  437. package/scripts/issue/issue-backlinks-cli.ts +5 -5
  438. package/scripts/issue/issue-backlinks.ts +6 -6
  439. package/scripts/issue/issue-cite-cli.ts +20 -18
  440. package/scripts/issue/issue-cite.ts +18 -8
  441. package/scripts/issue/issue-closing-pr.ts +4 -4
  442. package/scripts/issue/issue-comment-cli.ts +6 -4
  443. package/scripts/issue/issue-file-cli.ts +75 -15
  444. package/scripts/issue/issue-file-fold.ts +155 -0
  445. package/scripts/issue/issue-file.ts +14 -6
  446. package/scripts/issue/issue-fold-cli.ts +14 -9
  447. package/scripts/issue/issue-fold.ts +23 -8
  448. package/scripts/issue/issue-labels.ts +46 -37
  449. package/scripts/issue/issue-lint-cli.ts +2 -2
  450. package/scripts/issue/issue-lint.ts +1 -1
  451. package/scripts/issue/issue-merged.ts +10 -4
  452. package/scripts/issue/issue-number-shape.ts +27 -0
  453. package/scripts/issue/issue-rank.ts +1 -1
  454. package/scripts/issue/issue-read-cli.ts +4 -5
  455. package/scripts/issue/issue-read.ts +4 -5
  456. package/scripts/issue/issue-reference.ts +5 -5
  457. package/scripts/issue/issue-release-cli.ts +165 -0
  458. package/scripts/issue/issue-release.ts +58 -0
  459. package/scripts/issue/issue-report-failures.ts +7 -4
  460. package/scripts/issue/issue-scout-cli.ts +11 -11
  461. package/scripts/issue/issue-scout-closed.ts +4 -4
  462. package/scripts/issue/issue-scout.ts +4 -5
  463. package/scripts/issue/issue-state-cli.ts +17 -10
  464. package/scripts/issue/issue-state.ts +12 -13
  465. package/scripts/issue/issue-wip.ts +7 -7
  466. package/scripts/issue/markdown-section.ts +3 -3
  467. package/scripts/issue/measure-rerun-cli.ts +10 -9
  468. package/scripts/issue/reproduction-measure.ts +3 -3
  469. package/scripts/issue/session-cite.ts +56 -0
  470. package/scripts/josh/agent-session-environment.ts +10 -8
  471. package/scripts/josh/cli-body.ts +2 -2
  472. package/scripts/josh/command-suggest.ts +1 -1
  473. package/scripts/josh/file-map-stamp.ts +20 -23
  474. package/scripts/josh/hook-decision.ts +24 -28
  475. package/scripts/josh/josh-command-map.ts +4 -1
  476. package/scripts/josh/josh-command-types.ts +32 -34
  477. package/scripts/josh/josh-commands-ai.ts +6 -6
  478. package/scripts/josh/josh-commands-backlog.ts +15 -3
  479. package/scripts/josh/josh-commands-clone.ts +1 -1
  480. package/scripts/josh/josh-commands-development.ts +33 -4
  481. package/scripts/josh/josh-commands-document.ts +3 -3
  482. package/scripts/josh/josh-commands-guard.ts +3 -3
  483. package/scripts/josh/josh-commands-issue.ts +11 -5
  484. package/scripts/josh/josh-commands-lane.ts +16 -5
  485. package/scripts/josh/josh-commands-lint.ts +1 -1
  486. package/scripts/josh/josh-commands-maintenance.ts +2 -2
  487. package/scripts/josh/josh-commands-run.ts +20 -6
  488. package/scripts/josh/josh-commands-split.ts +1 -2
  489. package/scripts/josh/josh-commands-versioning.ts +5 -5
  490. package/scripts/josh/josh-commands-workflow.ts +30 -22
  491. package/scripts/josh/josh-environment-file.ts +1 -1
  492. package/scripts/josh/josh-in-process.ts +3 -3
  493. package/scripts/josh/josh-logic.ts +10 -10
  494. package/scripts/josh/josh-run.ts +3 -3
  495. package/scripts/josh/josh-verdict.ts +9 -12
  496. package/scripts/josh/josh.ts +3 -3
  497. package/scripts/josh/kit-only.ts +2 -2
  498. package/scripts/josh/path-decision.ts +3 -3
  499. package/scripts/josh/platform-temporary.ts +7 -5
  500. package/scripts/josh/process-identity.ts +24 -6
  501. package/scripts/josh/process-owner.ts +4 -4
  502. package/scripts/josh/session-language-cli.ts +53 -11
  503. package/scripts/josh/session-language.ts +1 -1
  504. package/scripts/josh/stamp-file.ts +48 -29
  505. package/scripts/josh/stamp-record.ts +57 -0
  506. package/scripts/lane/lane-await.ts +35 -11
  507. package/scripts/lane/lane-cache.ts +6 -6
  508. package/scripts/lane/lane-capacity.ts +32 -17
  509. package/scripts/lane/lane-child-invocation.ts +17 -15
  510. package/scripts/lane/lane-child-marker.ts +12 -12
  511. package/scripts/lane/lane-cli.ts +20 -13
  512. package/scripts/lane/lane-close.ts +6 -6
  513. package/scripts/lane/lane-dispatch.ts +61 -72
  514. package/scripts/lane/lane-environment.ts +5 -5
  515. package/scripts/lane/lane-guard-policy.ts +7 -21
  516. package/scripts/lane/lane-handoff.ts +2 -2
  517. package/scripts/lane/lane-install.ts +9 -10
  518. package/scripts/lane/lane-launch-cli.ts +13 -8
  519. package/scripts/lane/lane-ledger.ts +73 -11
  520. package/scripts/lane/lane-leftover.ts +44 -30
  521. package/scripts/lane/lane-limit-cli.ts +160 -0
  522. package/scripts/lane/lane-limit-override.ts +74 -0
  523. package/scripts/lane/lane-load.ts +19 -68
  524. package/scripts/lane/lane-measure-cli.ts +15 -25
  525. package/scripts/lane/lane-occupancy.ts +6 -4
  526. package/scripts/lane/lane-open.ts +25 -24
  527. package/scripts/lane/lane-output.ts +4 -3
  528. package/scripts/lane/lane-paths.ts +22 -8
  529. package/scripts/lane/lane-phase.ts +33 -0
  530. package/scripts/lane/lane-reap.ts +2 -2
  531. package/scripts/lane/lane-registry.ts +27 -15
  532. package/scripts/lane/lane-relaunch.ts +9 -9
  533. package/scripts/lane/lane-report.ts +5 -4
  534. package/scripts/lane/lane-resume.ts +2 -2
  535. package/scripts/lane/lane-sampler.ts +55 -0
  536. package/scripts/lane/lane-seed.ts +7 -7
  537. package/scripts/lane/lane-stage-stats.ts +135 -0
  538. package/scripts/lane/lane-start-point.ts +8 -11
  539. package/scripts/lane/lane-stats.ts +60 -15
  540. package/scripts/lane/lane-stray.ts +140 -0
  541. package/scripts/lane/lane-vacant.ts +1 -1
  542. package/scripts/lane/openai-lane-supervisor-decision.ts +3 -7
  543. package/scripts/lane/openai-lane-supervisor-owner.ts +3 -9
  544. package/scripts/lane/openai-review-broker.ts +2 -4
  545. package/scripts/lib/ancestor-directories.ts +1 -1
  546. package/scripts/lib/bounded-pool.ts +2 -2
  547. package/scripts/lib/buffered-process.ts +4 -6
  548. package/scripts/lib/caddy-logs.sh +0 -0
  549. package/scripts/lib/cli-flags.ts +39 -6
  550. package/scripts/lib/error-message.ts +1 -1
  551. package/scripts/lib/json-value.ts +17 -3
  552. package/scripts/lib/poll.ts +1 -1
  553. package/scripts/lib/status-icons.ts +3 -3
  554. package/scripts/lib/timed-fetch.ts +1 -1
  555. package/scripts/lib/timeouts.ts +1 -1
  556. package/scripts/lines/bytes-command.ts +3 -4
  557. package/scripts/lines/effective-limit.ts +25 -12
  558. package/scripts/lines/line-budget.ts +47 -55
  559. package/scripts/lines/line-targets.ts +6 -2
  560. package/scripts/lines/lines-command.ts +3 -3
  561. package/scripts/lint/cspell-cached.ts +1 -1
  562. package/scripts/lint/cycle-recheck.ts +122 -0
  563. package/scripts/lint/format.ts +1 -2
  564. package/scripts/lint/lint-parallel.ts +34 -19
  565. package/scripts/lint/lint-related-scope.ts +25 -15
  566. package/scripts/lint/lint-related.ts +6 -7
  567. package/scripts/managed-marker/index.ts +1 -1
  568. package/scripts/managed-marker/managed-marker-logic.ts +1 -2
  569. package/scripts/notify/git-notify.ts +9 -7
  570. package/scripts/notify/telegram-notify.ts +53 -37
  571. package/scripts/notify/telegram-test-logic.ts +3 -3
  572. package/scripts/notify/telegram-test.ts +45 -30
  573. package/scripts/observations/observation-ledger-home.ts +14 -8
  574. package/scripts/observations/observation-ledger-line.ts +3 -2
  575. package/scripts/observations/observation-ledger-migrate.ts +3 -4
  576. package/scripts/observations/observation-ledger-prepare.ts +4 -4
  577. package/scripts/observations/observation-ledger.ts +14 -15
  578. package/scripts/observations/observation-record-cli.ts +83 -0
  579. package/scripts/observations/observation-record.ts +91 -0
  580. package/scripts/observations/observations-flush-cli.ts +1 -1
  581. package/scripts/observations/observations-flush-landing.ts +7 -6
  582. package/scripts/observations/observations-flush.ts +26 -27
  583. package/scripts/overrides/overrides-check.ts +18 -8
  584. package/scripts/package/package-scout-cli.ts +1 -1
  585. package/scripts/package/package-scout-format.ts +2 -2
  586. package/scripts/package/package-scout.ts +1 -1
  587. package/scripts/propagate/propagate-git-failure.ts +1 -1
  588. package/scripts/propagate/propagate-git.ts +7 -7
  589. package/scripts/propagate/propagate-plan.ts +2 -2
  590. package/scripts/propagate/propagate-publish.ts +2 -3
  591. package/scripts/propagate/propagate-run.ts +5 -7
  592. package/scripts/propagate/propagate-select.ts +1 -1
  593. package/scripts/propagate/propagate-steps.ts +19 -20
  594. package/scripts/propagate/propagate-targets.ts +6 -10
  595. package/scripts/propagate/propagate.ts +5 -5
  596. package/scripts/refactor/import-graph.ts +1 -1
  597. package/scripts/refactor/refactor-lint.ts +4 -10
  598. package/scripts/refactor/refactor-scan-cli.ts +1 -1
  599. package/scripts/refactor/refactor-scan.ts +2 -2
  600. package/scripts/refactor/refactor-targets.ts +1 -1
  601. package/scripts/release/github-release-cli.ts +25 -3
  602. package/scripts/release/github-release-environment.ts +1 -0
  603. package/scripts/release/github-release-runs.ts +115 -0
  604. package/scripts/release/github-release.ts +13 -67
  605. package/scripts/release/release-cli.ts +21 -4
  606. package/scripts/release/release-history.ts +6 -10
  607. package/scripts/release/release-plan.ts +3 -3
  608. package/scripts/release/release-progress.ts +3 -4
  609. package/scripts/release/release-publish.ts +8 -9
  610. package/scripts/release/release-scope-cli.ts +8 -10
  611. package/scripts/release/release-tag.ts +6 -8
  612. package/scripts/release/release-worktree.ts +5 -5
  613. package/scripts/repo/auto-merge-setting-logic.ts +7 -9
  614. package/scripts/repo/auto-merge-setting.ts +1 -1
  615. package/scripts/repo/repo-setting.ts +4 -4
  616. package/scripts/repo/repository-labels.ts +1 -1
  617. package/scripts/repo/required-checks-logic.ts +3 -3
  618. package/scripts/repo/required-checks-report.ts +1 -1
  619. package/scripts/repo/ruleset-check-cli.ts +1 -1
  620. package/scripts/repo/ruleset-check.ts +1 -1
  621. package/scripts/report/report-format-reference.ts +26 -0
  622. package/scripts/report/report-lint-cli.ts +2 -2
  623. package/scripts/report/report-lint.ts +16 -2
  624. package/scripts/review/disposition-cli.ts +2 -2
  625. package/scripts/review/disposition-logic.ts +1 -1
  626. package/scripts/review/live-evidence.ts +9 -6
  627. package/scripts/review/review-attest-cli.ts +1 -2
  628. package/scripts/review/review-attest.ts +3 -3
  629. package/scripts/review/review-brief-cli.ts +19 -20
  630. package/scripts/review/review-brief.ts +29 -32
  631. package/scripts/review/review-checkout.ts +2 -2
  632. package/scripts/review/review-diff-parts.ts +3 -5
  633. package/scripts/review/review-diff-write.ts +1 -1
  634. package/scripts/review/review-finding-ledger.ts +7 -4
  635. package/scripts/review/review-findings-cli.ts +2 -2
  636. package/scripts/review/review-level.ts +4 -7
  637. package/scripts/review/review-record-cli.ts +73 -16
  638. package/scripts/review/review-record.ts +5 -4
  639. package/scripts/review/review-round2-cli.ts +2 -3
  640. package/scripts/review/review-round2.ts +13 -21
  641. package/scripts/review/review-stamps.ts +9 -71
  642. package/scripts/review/review-tree.ts +4 -5
  643. package/scripts/rules/bash-triggers.ts +4 -4
  644. package/scripts/rules/decision-oracle-batch.ts +5 -6
  645. package/scripts/rules/decision-oracle-stage.ts +1 -1
  646. package/scripts/rules/decision-oracle-tokens.ts +1 -2
  647. package/scripts/rules/decision-oracle.ts +2 -2
  648. package/scripts/rules/delivered-rules.ts +61 -406
  649. package/scripts/rules/destructive-command.ts +2 -2
  650. package/scripts/rules/direct-filing.ts +4 -4
  651. package/scripts/rules/direct-pr-create.ts +2 -2
  652. package/scripts/rules/early-heartbeat.ts +15 -19
  653. package/scripts/rules/file-body.ts +5 -6
  654. package/scripts/rules/filing-cap.ts +6 -7
  655. package/scripts/rules/filing-offer.ts +1 -1
  656. package/scripts/rules/firing-point.ts +6 -6
  657. package/scripts/rules/gh-api.ts +2 -2
  658. package/scripts/rules/git-argv.ts +3 -3
  659. package/scripts/rules/git-force.ts +2 -2
  660. package/scripts/rules/hook-context-line.ts +31 -0
  661. package/scripts/rules/implementation-cut-verdict.ts +5 -8
  662. package/scripts/rules/implementation-cut.ts +35 -32
  663. package/scripts/rules/index-guard.ts +2 -2
  664. package/scripts/rules/issue-citation.ts +7 -7
  665. package/scripts/rules/issue-comments.ts +21 -13
  666. package/scripts/rules/josh-git-bare.ts +2 -2
  667. package/scripts/rules/lane-background.ts +14 -16
  668. package/scripts/rules/lane-carry-conflict.ts +41 -5
  669. package/scripts/rules/lane-interactive-ask.ts +6 -9
  670. package/scripts/rules/lane-park.ts +12 -16
  671. package/scripts/rules/lane-split-park.ts +1 -2
  672. package/scripts/rules/lane-switch-main.ts +10 -13
  673. package/scripts/rules/last-prompt.ts +1 -1
  674. package/scripts/rules/oracle-consulted.ts +5 -5
  675. package/scripts/rules/oracle-firing.ts +6 -9
  676. package/scripts/rules/oracle-list-cli.ts +2 -2
  677. package/scripts/rules/permission-guards.ts +2 -2
  678. package/scripts/rules/piped-verification.ts +79 -9
  679. package/scripts/rules/poll-loop.ts +9 -11
  680. package/scripts/rules/pre-gate-cut.ts +33 -30
  681. package/scripts/rules/prior-comment-read.ts +3 -3
  682. package/scripts/rules/protected-files.ts +25 -13
  683. package/scripts/rules/raw-field-body.ts +3 -4
  684. package/scripts/rules/reply-language.ts +1 -1
  685. package/scripts/rules/rule-body-guard.ts +10 -12
  686. package/scripts/rules/rule-guard.ts +1 -1
  687. package/scripts/rules/rule-list.ts +51 -0
  688. package/scripts/rules/rule-registry-rows.ts +282 -0
  689. package/scripts/rules/rule-registry.ts +109 -0
  690. package/scripts/rules/rule-value-cache.ts +2 -2
  691. package/scripts/rules/rule-value-cli.ts +6 -4
  692. package/scripts/rules/rule-value.ts +61 -22
  693. package/scripts/rules/run-tail-rule.ts +11 -15
  694. package/scripts/rules/shell-body-trigger.ts +7 -7
  695. package/scripts/rules/shell-segments.ts +2 -4
  696. package/scripts/rules/stop-rules.ts +54 -41
  697. package/scripts/rules/tail-commands.ts +1 -1
  698. package/scripts/rules/test-declared-commit.ts +2 -2
  699. package/scripts/rules/third-party-write.ts +3 -3
  700. package/scripts/rules/worktree-guard.ts +12 -5
  701. package/scripts/run/add/run-add-cli.ts +165 -0
  702. package/scripts/run/add/run-add.ts +124 -0
  703. package/scripts/run/board/run-board-cli.ts +207 -0
  704. package/scripts/run/board/run-board-closed.ts +95 -0
  705. package/scripts/run/board/run-board-every.ts +60 -0
  706. package/scripts/run/board/run-board-fetch.ts +38 -0
  707. package/scripts/run/board/run-board-fit.ts +219 -0
  708. package/scripts/run/board/run-board-github.ts +162 -0
  709. package/scripts/run/board/run-board-header.ts +275 -0
  710. package/scripts/run/board/run-board-kind.ts +35 -0
  711. package/scripts/run/board/run-board-labels.ts +299 -0
  712. package/scripts/run/board/run-board-layout.ts +222 -0
  713. package/scripts/run/board/run-board-link.ts +31 -0
  714. package/scripts/run/board/run-board-machine.ts +198 -0
  715. package/scripts/run/board/run-board-notes.ts +103 -0
  716. package/scripts/run/board/run-board-phase.ts +136 -0
  717. package/scripts/run/board/run-board-plan.ts +129 -0
  718. package/scripts/run/board/run-board-read.ts +62 -0
  719. package/scripts/run/board/run-board-render-legend.ts +82 -0
  720. package/scripts/run/board/run-board-render-notes.ts +77 -0
  721. package/scripts/run/board/run-board-render-slot.ts +50 -0
  722. package/scripts/run/board/run-board-render.ts +407 -0
  723. package/scripts/run/board/run-board-scope.ts +17 -0
  724. package/scripts/run/board/run-board-screen.ts +43 -0
  725. package/scripts/run/board/run-board-span.ts +66 -0
  726. package/scripts/run/board/run-board-spin.ts +115 -0
  727. package/scripts/run/board/run-board-state.ts +113 -0
  728. package/scripts/run/board/run-board-status.ts +279 -0
  729. package/scripts/run/board/run-board-tick.ts +210 -0
  730. package/scripts/run/board/run-board-track.ts +22 -0
  731. package/scripts/run/board/run-board-usage-read.ts +255 -0
  732. package/scripts/run/board/run-board-usage-rusage.ts +124 -0
  733. package/scripts/run/board/run-board-usage-text.ts +80 -0
  734. package/scripts/run/board/run-board-usage.ts +165 -0
  735. package/scripts/run/carry/run-carry-added.ts +62 -0
  736. package/scripts/run/carry/run-carry-args.ts +25 -22
  737. package/scripts/run/carry/run-carry-change.ts +1 -1
  738. package/scripts/run/carry/run-carry-cli.ts +71 -48
  739. package/scripts/run/carry/run-carry-conversation.ts +6 -7
  740. package/scripts/run/carry/run-carry-ended.ts +85 -0
  741. package/scripts/run/carry/run-carry-reclaim.ts +1 -1
  742. package/scripts/run/carry/run-carry-stash.ts +3 -2
  743. package/scripts/run/carry/run-carry-streak.ts +8 -10
  744. package/scripts/run/carry/run-carry.ts +85 -89
  745. package/scripts/run/cut/run-cut-args.ts +7 -7
  746. package/scripts/run/cut/run-cut-cli.ts +68 -37
  747. package/scripts/run/cut/run-cut-handoff.ts +15 -15
  748. package/scripts/run/cut/run-cut-report.ts +37 -16
  749. package/scripts/run/cut/run-cut.ts +63 -77
  750. package/scripts/run/detached-launch.ts +35 -50
  751. package/scripts/run/entry/run-entry-cli.ts +48 -27
  752. package/scripts/run/entry/run-entry-stop.ts +7 -9
  753. package/scripts/run/entry/run-entry.ts +5 -6
  754. package/scripts/run/event/run-event-cli.ts +5 -6
  755. package/scripts/run/event/run-event-filed.ts +69 -0
  756. package/scripts/run/event/run-event-follow.ts +3 -3
  757. package/scripts/run/event/run-event-plan.ts +38 -0
  758. package/scripts/run/event/run-event-render.ts +10 -4
  759. package/scripts/run/event/run-event-scope.ts +47 -18
  760. package/scripts/run/event/run-event-stream-emit.ts +64 -11
  761. package/scripts/run/event/run-event-stream.ts +172 -43
  762. package/scripts/run/event/run-event-watch.ts +4 -6
  763. package/scripts/run/hold/run-hold-cli.ts +65 -62
  764. package/scripts/run/hold/run-hold.ts +88 -46
  765. package/scripts/run/merge/run-merge-cli.ts +116 -77
  766. package/scripts/run/merge/run-merge-collect.ts +107 -0
  767. package/scripts/run/merge/run-merge-steps.ts +112 -65
  768. package/scripts/run/merge/run-merge-token.ts +30 -0
  769. package/scripts/run/merge/run-merge.ts +31 -22
  770. package/scripts/run/progress/run-progress-args.ts +4 -4
  771. package/scripts/run/progress/run-progress-cli.ts +39 -50
  772. package/scripts/run/progress/run-progress-clock.ts +25 -32
  773. package/scripts/run/progress/run-progress-config.ts +6 -9
  774. package/scripts/run/progress/run-progress-read.ts +9 -10
  775. package/scripts/run/progress/run-progress.ts +48 -53
  776. package/scripts/run/review/run-review-cli.ts +6 -6
  777. package/scripts/run/review/run-review-steps.ts +6 -6
  778. package/scripts/run/review/run-review.ts +9 -11
  779. package/scripts/run/run-cli-fault.ts +29 -0
  780. package/scripts/run/run-ending-cli.ts +3 -3
  781. package/scripts/run/run-ending.ts +10 -14
  782. package/scripts/run/run-halfrun-resume.ts +6 -8
  783. package/scripts/run/run-headless.ts +25 -12
  784. package/scripts/run/run-invocation.ts +17 -22
  785. package/scripts/run/run-label.ts +7 -5
  786. package/scripts/run/run-liveness-cli.ts +19 -6
  787. package/scripts/run/run-liveness.ts +27 -38
  788. package/scripts/run/run-next-cli.ts +5 -9
  789. package/scripts/run/run-next.ts +4 -5
  790. package/scripts/run/run-parent-cut-hook.ts +10 -12
  791. package/scripts/run/run-preflight.ts +25 -29
  792. package/scripts/run/run-prep-cli.ts +17 -13
  793. package/scripts/run/run-prep-locate.ts +4 -5
  794. package/scripts/run/run-prep.ts +7 -10
  795. package/scripts/run/run-prrun-resume.ts +2 -2
  796. package/scripts/run/run-report-cli.ts +4 -4
  797. package/scripts/run/run-report.ts +9 -14
  798. package/scripts/run/run-retrospective.ts +3 -3
  799. package/scripts/run/run-section.ts +42 -0
  800. package/scripts/run/run-stage-read.ts +2 -2
  801. package/scripts/run/run-stage.ts +6 -4
  802. package/scripts/run/run-status-cli.ts +7 -5
  803. package/scripts/run/run-status.ts +6 -7
  804. package/scripts/run/run-step-cli.ts +13 -15
  805. package/scripts/run/run-step.ts +62 -48
  806. package/scripts/run/run-stop-notify.ts +7 -8
  807. package/scripts/run/run-stranded-cli.ts +1 -1
  808. package/scripts/run/run-stranded-detect.ts +4 -4
  809. package/scripts/run/run-stranded.ts +11 -13
  810. package/scripts/run/run-tail-cli.ts +15 -16
  811. package/scripts/run/run-tail.ts +14 -33
  812. package/scripts/run/run-watcher-guard-cli.ts +3 -4
  813. package/scripts/run/run-watcher-guard.ts +11 -12
  814. package/scripts/run/run-watcher-hook.ts +6 -12
  815. package/scripts/run/ship/run-ship-cli.ts +67 -33
  816. package/scripts/run/ship/run-ship-detach.ts +15 -13
  817. package/scripts/run/ship/run-ship-lock.ts +1 -1
  818. package/scripts/run/ship/run-ship-next.ts +7 -8
  819. package/scripts/run/ship/run-ship-pre-detach.ts +27 -11
  820. package/scripts/run/ship/run-ship-preflight.ts +10 -11
  821. package/scripts/run/ship/run-ship-probe.ts +4 -4
  822. package/scripts/run/ship/run-ship-return.ts +1 -1
  823. package/scripts/run/ship/run-ship-review-steps.ts +43 -24
  824. package/scripts/run/ship/run-ship-review.ts +12 -14
  825. package/scripts/run/ship/run-ship-scoped.ts +15 -6
  826. package/scripts/run/ship/run-ship-stage.ts +80 -26
  827. package/scripts/run/ship/run-ship-steps.ts +26 -16
  828. package/scripts/run/ship/run-ship-stop-text.ts +4 -2
  829. package/scripts/run/ship/run-ship-sync.ts +9 -8
  830. package/scripts/run/ship/run-ship.ts +17 -32
  831. package/scripts/run/tidy/run-tidy-cli.ts +9 -5
  832. package/scripts/run/tidy/run-tidy-lanes.ts +18 -7
  833. package/scripts/run/tidy/run-tidy-stashes.ts +8 -8
  834. package/scripts/run/tidy/run-tidy.ts +4 -3
  835. package/scripts/run/wake/run-wake-cli.ts +27 -33
  836. package/scripts/run/wake/run-wake-describe.ts +76 -29
  837. package/scripts/run/wake/run-wake-driver.ts +14 -14
  838. package/scripts/run/wake/run-wake-handoff.ts +6 -6
  839. package/scripts/run/wake/run-wake-loop.ts +13 -21
  840. package/scripts/run/wake/run-wake-restart.ts +4 -5
  841. package/scripts/run/wake/run-wake-session.ts +23 -27
  842. package/scripts/run/wake/run-wake.ts +57 -328
  843. package/scripts/safe-chain/ci-installer-pin.ts +3 -3
  844. package/scripts/safe-chain/pack-hook.ts +2 -2
  845. package/scripts/safe-chain/preinstall-command.ts +2 -2
  846. package/scripts/security/security-audit-logic.ts +1 -1
  847. package/scripts/security/security-audit-provision-logic.ts +1 -1
  848. package/scripts/security/security-audit-provision.ts +2 -2
  849. package/scripts/security/security-audit.ts +5 -5
  850. package/scripts/security/security-updates-logic.ts +2 -3
  851. package/scripts/security/security-updates.ts +2 -4
  852. package/scripts/self-sync-guard/index.ts +1 -1
  853. package/scripts/self-sync-guard/self-sync-guard-logic.ts +2 -2
  854. package/scripts/self-sync-guard/self-sync-refusal.ts +1 -1
  855. package/scripts/sonar/sonar-hotspots-cli.ts +1 -1
  856. package/scripts/sonar/sonar-hotspots.ts +1 -1
  857. package/scripts/sonar/sonar-new-code-cli.ts +1 -1
  858. package/scripts/sonar/sonar-new-code.ts +1 -1
  859. package/scripts/sonar/sonar-project.ts +1 -1
  860. package/scripts/split/split-assess-cli.ts +1 -1
  861. package/scripts/split/split-assess.ts +3 -3
  862. package/scripts/sync/directory-copy-guard.ts +2 -3
  863. package/scripts/sync/managed-config-scope-cli.ts +1 -2
  864. package/scripts/sync/managed-config-scope.ts +4 -4
  865. package/scripts/sync/plugin-skill-directories.ts +2 -2
  866. package/scripts/sync/reconcile-templates.ts +17 -8
  867. package/scripts/sync/removed-skill-manifest.ts +2 -3
  868. package/scripts/sync/sync-ai-files.ts +7 -7
  869. package/scripts/sync/sync-configs.ts +30 -3
  870. package/scripts/sync/sync-hook-safety.ts +2 -2
  871. package/scripts/sync/sync.ts +23 -10
  872. package/scripts/sync/synced-paths.ts +2 -1
  873. package/scripts/sync/workflow-pin-logic.ts +1 -1
  874. package/scripts/test/test-declared-changed.ts +4 -4
  875. package/scripts/test/test-declared-logic.ts +2 -3
  876. package/scripts/test/test-declared-match.ts +25 -4
  877. package/scripts/test/test-declared.ts +26 -9
  878. package/scripts/test/test-red-commit.ts +3 -2
  879. package/scripts/test/test-red-logic.ts +7 -14
  880. package/scripts/test/test-red.ts +12 -47
  881. package/scripts/test/test-related-scope.ts +2 -3
  882. package/scripts/test/test-related.ts +3 -3
  883. package/scripts/test/test-type-logic.ts +1 -2
  884. package/scripts/test/test-unit-guard.ts +13 -17
  885. package/scripts/test/unit-worker-share.ts +7 -8
  886. package/scripts/time-runtime/time-agent-bundles.ts +2 -4
  887. package/scripts/time-runtime/time-background.ts +17 -21
  888. package/scripts/time-runtime/time-batch-guard.ts +67 -342
  889. package/scripts/time-runtime/time-bundle-call.ts +26 -28
  890. package/scripts/time-runtime/time-bundles.ts +11 -12
  891. package/scripts/time-runtime/time-call-identity.ts +1 -1
  892. package/scripts/time-runtime/time-command-key.ts +2 -2
  893. package/scripts/time-runtime/time-density-hook.ts +8 -11
  894. package/scripts/time-runtime/time-density.ts +5 -5
  895. package/scripts/time-runtime/time-followup-stage.ts +7 -7
  896. package/scripts/time-runtime/time-format.ts +5 -5
  897. package/scripts/time-runtime/time-hook-transcript.ts +3 -3
  898. package/scripts/time-runtime/time-instant.ts +1 -1
  899. package/scripts/time-runtime/time-markers.ts +15 -19
  900. package/scripts/time-runtime/time-phase-names.ts +3 -3
  901. package/scripts/time-runtime/time-reported-failure.ts +15 -19
  902. package/scripts/time-runtime/time-round-trips.ts +20 -23
  903. package/scripts/time-runtime/time-shell.ts +8 -8
  904. package/scripts/time-runtime/time-single-check.ts +1 -2
  905. package/scripts/time-runtime/time-spans.ts +35 -40
  906. package/scripts/time-runtime/time-tool-call.ts +15 -16
  907. package/scripts/time-runtime/time-transcript-line.ts +53 -34
  908. package/scripts/time-runtime/time-writes.ts +5 -5
  909. package/scripts/ui/ui-routes-cli.ts +1 -2
  910. package/scripts/ui/ui-routes.ts +1 -2
  911. package/scripts/version/bump-version.ts +1 -1
  912. package/scripts/version/fresh-metadata-cache.ts +2 -2
  913. package/scripts/version/latest-corepack.ts +129 -98
  914. package/scripts/version/latest-lane-guard.ts +1 -1
  915. package/scripts/version/latest-scope-cli.ts +2 -2
  916. package/scripts/version/latest-stamp.ts +1 -2
  917. package/scripts/version/latest-update.ts +2 -2
  918. package/scripts/version/npm-registry.ts +2 -2
  919. package/scripts/version/package-manager-version.ts +18 -0
  920. package/scripts/version/publishable-range-check.ts +2 -1
  921. package/scripts/version/publishable-range.ts +1 -1
  922. package/scripts/version/release-age.ts +11 -11
  923. package/scripts/version/release-hold.ts +2 -2
  924. package/scripts/version/safe-chain-version-update.ts +3 -3
  925. package/scripts/version/version-check-logic.ts +2 -3
  926. package/scripts/version/version-check.ts +1 -2
  927. package/scripts/version/version-command-config.ts +2 -2
  928. package/scripts/version/version-commands.ts +3 -3
  929. package/scripts/version/version-remote.ts +4 -4
  930. package/scripts/version/version-targets.ts +2 -2
  931. package/templates/gitignore +7 -0
  932. package/templates/workflows/github-release.yml +4 -0
  933. package/dist/hooks/chunk-NV2JRZZO.js +0 -6385
  934. package/dist/hooks/chunk-RKUAD3I6.js +0 -90
  935. package/dist/hooks/chunk-WPALEIRX.js +0 -18
  936. package/scripts/backlog/backlog-restructure.ts +0 -152
  937. package/scripts/rules/issue-fold-rule.ts +0 -72
  938. package/scripts/rules/wip-cap.ts +0 -63
  939. package/scripts/run/run-issue-number.ts +0 -19
@@ -13,16 +13,16 @@ const telegram_environment_schema = z.object({
13
13
  telegram_chat_id: z.string().min(1, { message: 'TELEGRAM_CHAT_ID is required' }),
14
14
  })
15
15
 
16
- // **`warning` is not `failure`** (joshuafolkken/kit#1628). It names a run that finished and merged,
16
+ // **`warning` is not `failure`**. It names a run that finished and merged,
17
17
  // alongside something that did not work — a post-merge cleanup step that could not complete is one.
18
18
  // Sending `failure` (❌) there would say the merge failed, which is false and is
19
19
  // the more expensive lie of the two; sending `completion` (✅) twice says nothing went wrong, which
20
20
  // is the silence this type exists to end.
21
- // **`stalled` is not `warning`** (joshuafolkken/kit#2359). `warning` names a run that *finished* and
21
+ // **`stalled` is not `warning`**. `warning` names a run that *finished* and
22
22
  // merged alongside something that did not work; a stall is the opposite — the run is alive and has not
23
23
  // finished, it has simply stopped advancing while ready work waits for a free lane. The ⏳ icon says
24
24
  // exactly that: not done, not broken, just not moving.
25
- // **`stranded` is not `stalled`** (joshuafolkken/kit#2375). A stall is a *live* run that is not
25
+ // **`stranded` is not `stalled`**. A stall is a *live* run that is not
26
26
  // dispatching; a strand is the step before it — the run's own driver is gone. The session that cut the
27
27
  // budget handed it off and died, no successor claimed it, and no supervisor is watching, so nothing can
28
28
  // take the next step at all. The 🚨 icon says a run needs a hand, not that ready work is merely waiting.
@@ -35,6 +35,7 @@ type TelegramTaskType =
35
35
  | 'confirmation'
36
36
  | 'stalled'
37
37
  | 'stranded'
38
+ | 'progress'
38
39
 
39
40
  interface TelegramSendInput {
40
41
  task_type: TelegramTaskType
@@ -64,6 +65,7 @@ const TASK_DEFINITIONS: Record<TelegramTaskType, TaskDefinition> = {
64
65
  confirmation: { icon: '⏸️', label: 'Confirmation required' },
65
66
  stalled: { icon: '⏳', label: 'Ready work is sitting undispatched' },
66
67
  stranded: { icon: '🚨', label: 'Run stranded — nobody is driving it' },
68
+ progress: { icon: '📊', label: 'Progress' },
67
69
  }
68
70
 
69
71
  const NOTIFY_SWITCH_KEY = 'JOSH_NOTIFY'
@@ -82,9 +84,8 @@ function parse_environment_string(value: string | undefined): string {
82
84
  // so it would pull a subprocess concern into an HTTP one and degrade to exactly this line anyway.
83
85
  // **The `cause` is read, not only the message.** A `fetch` rejection's own message is the bare string
84
86
  // `fetch failed`; what says whether this was DNS, a refused connection or a timeout lives one level
85
- // down. Reporting the top line alone would exit non-zero with nothing a reader can act on, which is
86
- // half of what joshuafolkken/kit#1564 set out to fix. Redaction runs over the joined text, so the
87
- // deeper line is covered exactly as the top one is.
87
+ // down. Reporting the top line alone would exit non-zero with nothing a reader can act on.
88
+ // Redaction runs over the joined text, so the deeper line is covered exactly as the top one is.
88
89
  function join_cause(error: Error): string {
89
90
  const { cause } = error
90
91
 
@@ -114,17 +115,14 @@ function describe_symptom(error: unknown): string {
114
115
 
115
116
  // The request URL carries the bot token in its own path, so an error raised anywhere near the
116
117
  // request can carry a credential into a log. Both values are taken out of the text before it leaves
117
- // this module, so no caller has to remember to do it (joshuafolkken/kit#1564).
118
+ // this module, so no caller has to remember to do it.
118
119
  function redact_credentials(text: string, config: TelegramConfig): string {
119
120
  return text.split(config.bot_token).join(REDACTED).split(config.chat_id).join(REDACTED)
120
121
  }
121
122
 
122
- // **Missing credentials are a failure, not a skip** (joshuafolkken/kit#1564). This used to warn and
123
- // return `undefined`, and `send` then returned quietly — so a run with no credentials was
124
- // indistinguishable from one whose notification arrived. Until this Issue the mandatory
125
- // `--env-file=.env` flag on `josh notify` and `josh followup` made a machine without that file die
126
- // before node started, which was loud by accident; with the flag relaxed to the optional form, this
127
- // is where the noise has to come from instead.
123
+ // **Missing credentials are a failure, not a skip**: a run with no credentials that returned quietly
124
+ // would be indistinguishable from one whose notification arrived. `josh notify` and `josh followup`
125
+ // load `.env` only optionally, so this is where the noise has to come from.
128
126
  //
129
127
  // The message names the variables and never their values — the schema's own messages are the
130
128
  // variable names, so nothing read out of the environment reaches it.
@@ -143,10 +141,10 @@ function load_config(): TelegramConfig {
143
141
  return { bot_token: result.data.telegram_bot_token, chat_id: result.data.telegram_chat_id }
144
142
  }
145
143
 
146
- // **An explicit opt-out is not a missing credential** (joshuafolkken/kit#2821). A consumer who never
147
- // meant to use Telegram had no way to say so, so every stop printed the #1564 failure as noise. Only
148
- // the stated value `off` disables the send: an unset or mistyped switch still falls through to
149
- // `load_config`, so a forgotten setup stays the loud failure #1564 made it.
144
+ // **An explicit opt-out is not a missing credential**: a consumer who never means to use Telegram
145
+ // says so, rather than seeing the missing-credential failure on every stop. Only the stated value
146
+ // `off` disables the send: an unset or mistyped switch still falls through to `load_config`, so a
147
+ // forgotten setup stays a loud failure.
150
148
  function is_notify_disabled(): boolean {
151
149
  return parse_environment_string(process.env[NOTIFY_SWITCH_KEY]).toLowerCase() === NOTIFY_OFF_VALUE
152
150
  }
@@ -204,10 +202,9 @@ function head_of(body: string, kept: number): string {
204
202
  return TRAILING_HIGH_SURROGATE.test(head) ? head.slice(0, -1) : head
205
203
  }
206
204
 
207
- // **The body is cut to fit Telegram's length limit, keeping its head** (joshuafolkken/kit#3242). A
208
- // warning carrying a whole driver stderr ran past 4096 characters and was refused with `400 Bad
209
- // Request`, so it reached nobody. A caller puts the cause first, so the tail is what is dropped, and the
210
- // header and the URLs around the body survive.
205
+ // **The body is cut to fit Telegram's length limit, keeping its head**: a text past the limit is
206
+ // refused with `400 Bad Request` and reaches nobody. A caller puts the cause first, so the tail is
207
+ // what is dropped, and the header and the URLs around the body survive.
211
208
  function build_text(input: TelegramSendInput): string {
212
209
  const text = join_blocks(input)
213
210
  const overflow = text.length - TELEGRAM_TEXT_LIMIT
@@ -230,7 +227,7 @@ async function post_message(config: TelegramConfig, text: string): Promise<void>
230
227
  }
231
228
  }
232
229
 
233
- // **The cause is re-wrapped rather than passed through** (joshuafolkken/kit#1564). The chain is kept,
230
+ // **The cause is re-wrapped rather than passed through**. The chain is kept,
234
231
  // because a symptom error that drops its cause loses where the failure came from — but the original
235
232
  // is the one object on this path nothing has redacted, and `git_error.handle` prints a cause's own
236
233
  // message straight to the console. Both layers therefore carry the same already-redacted text.
@@ -241,9 +238,8 @@ function build_send_failure(error: unknown, config: TelegramConfig): Error {
241
238
  }
242
239
 
243
240
  // **The strict form.** A caller whose whole job is the notification has nothing left to report when
244
- // this fails, so it throws and `pnpm josh notify` exits non-zero. joshuafolkken/kit#1564 measured
245
- // the state this replaces: three notifications lost to a `504 Gateway Time-out`, each one printing a
246
- // warning and exiting 0, so a message that reached nobody looked exactly like one that arrived.
241
+ // this fails, so it throws and `pnpm josh notify` exits non-zero — a warning and exit 0 would make a
242
+ // message that reached nobody look exactly like one that arrived.
247
243
  //
248
244
  // The failure it throws carries a `cause`, and that cause is redacted too — see `build_send_failure`.
249
245
  //
@@ -272,13 +268,12 @@ async function send(input: TelegramSendInput): Promise<void> {
272
268
 
273
269
  // **The tolerant form**, for a caller whose job is something other than the notification.
274
270
  // `followup` sends the completion message on its way to the merge, and a gateway timeout at
275
- // Telegram is not a reason to leave a reviewed, green pull request unmerged — joshuafolkken/kit#1564
276
- // measured exactly that 504 with six lanes running at once. So the failure is reported and the run
277
- // carries on.
271
+ // Telegram is not a reason to leave a reviewed, green pull request unmerged. So the failure is
272
+ // reported and the run carries on.
278
273
  //
279
274
  // **Reported under `❗` on stderr, in its own block, with the caller's own recovery line** — the bar
280
- // joshuafolkken/kit#1539 set for a step that failed and was not allowed to end the run. The `⚠️`
281
- // this used to print is what every routine notice prints, which is how the failure got buried.
275
+ // for a step that failed and was not allowed to end the run. A `⚠️` is what every routine notice
276
+ // prints, so the failure would be buried under one.
282
277
  //
283
278
  // `recovery` is the caller's because only the caller knows one. It is `string | undefined` and not
284
279
  // optional for the reason `CleanupStep.recovery` is: a caller with no command that finishes the job
@@ -326,7 +321,7 @@ interface WarningInput {
326
321
  /**
327
322
  * Warn that something an unattended run depended on did not work.
328
323
  *
329
- * **One function rather than one per caller** (joshuafolkken/kit#1749). Every warning fills in the
324
+ * **One function rather than one per caller**. Every warning fills in the
330
325
  * same four fields the same way — the task type, the repository looked up under the same bound, and
331
326
  * two urls that are never known here — so a second caller composing its own would be free to drift
332
327
  * on the one field that is not obvious: a repository lookup with no timeout hangs the warning behind
@@ -354,8 +349,7 @@ interface ConfirmInput {
354
349
 
355
350
  /**
356
351
  * Push the ⏸️ confirmation type — a state change an unattended run made that a person now has to act
357
- * on, a `backlogrun` that stopped needing a decision being the one this was written for
358
- * (joshuafolkken/kit#2136).
352
+ * on, a `backlogrun` that stopped needing a decision being the one this was written for.
359
353
  *
360
354
  * **One function rather than one per caller, for `warn`'s reason exactly**: the repository lookup
361
355
  * under a timeout is the field a second caller composing the four itself would drift on, and a lookup
@@ -384,8 +378,8 @@ interface StalledInput {
384
378
  }
385
379
 
386
380
  /**
387
- * Push the ⏳ stalled type — ready backlog work with a free lane that nothing has dispatched for a while
388
- * (joshuafolkken/kit#2359). Off-screen is the whole point: the state is invisible on the terminal until
381
+ * Push the ⏳ stalled type — ready backlog work with a free lane that nothing has dispatched for a while.
382
+ * Off-screen is the whole point: the state is invisible on the terminal until
389
383
  * a person asks, so it reaches them where they are not watching.
390
384
  *
391
385
  * **`warn`'s shape exactly** — the repository looked up under the shared bound, the tolerant
@@ -413,8 +407,8 @@ interface StrandedInput {
413
407
  }
414
408
 
415
409
  /**
416
- * Push the 🚨 stranded type — a run whose driver is gone and which nothing can advance
417
- * (joshuafolkken/kit#2375). Off-screen is the whole point, as it is for `stalled`: the state is
410
+ * Push the 🚨 stranded type — a run whose driver is gone and which nothing can advance.
411
+ * Off-screen is the whole point, as it is for `stalled`: the state is
418
412
  * invisible on the terminal because the session that would show it has died, so the person hears about
419
413
  * it where they are not watching, rather than by asking.
420
414
  *
@@ -437,8 +431,30 @@ async function stranded(input: StrandedInput): Promise<boolean> {
437
431
  )
438
432
  }
439
433
 
434
+ /**
435
+ * Push the 📊 progress type — one `run:board` frame a person asked to receive periodically off-screen
436
+ * with `run:board --every`. Never a heartbeat: nothing sends it unasked.
437
+ *
438
+ * **`stranded`'s shape exactly**, with the board's own one-frame answer as the recovery — a frame lost
439
+ * to a Telegram timeout is read again by asking for it.
440
+ */
441
+ async function progress(body: string): Promise<boolean> {
442
+ return await send_or_report(
443
+ {
444
+ task_type: 'progress',
445
+ repo_name: gh_spawn.get_repo_name_with_owner_within(REPO_LOOKUP_TIMEOUT_MS),
446
+ issue_title: undefined,
447
+ body,
448
+ issue_url: undefined,
449
+ pr_url: undefined,
450
+ },
451
+ 'pnpm josh run:board --chat',
452
+ )
453
+ }
454
+
440
455
  const telegram_notify = {
441
456
  confirm,
457
+ progress,
442
458
  send,
443
459
  send_or_report,
444
460
  stalled,
@@ -44,7 +44,7 @@ function parse_task_type(raw: string | undefined): TelegramTaskType {
44
44
 
45
45
  // A flag counts as given only when it carries text, so `--issue-title ''` is not an answer. The
46
46
  // callers that *skip* a lookup because the flag already answered it read the same predicate, or the
47
- // two could disagree about an empty string and leave the field blank (joshuafolkken/kit#903).
47
+ // two could disagree about an empty string and leave the field blank.
48
48
  // It is `cli_body`'s predicate rather than a second copy: the body flags are resolved there, and two
49
49
  // definitions of "given" would let `--body ''` count on one side and not the other.
50
50
  const has_flag_value = cli_body.has_value
@@ -56,8 +56,8 @@ function coalesce(primary: string | undefined, fallback: string | undefined): st
56
56
  }
57
57
 
58
58
  // `--body-file` is the form to reach for whenever the body carries a backtick or a `$`: inside shell
59
- // double quotes those are evaluated before this process starts, and the text runs
60
- // (joshuafolkken/kit#1198). The resolution itself is `cli_body`'s, shared with `josh followup`.
59
+ // double quotes those are evaluated before this process starts, and the text runs.
60
+ // The resolution itself is `cli_body`'s, shared with `josh followup`.
61
61
  function normalize_body(values: CliValues): string | undefined {
62
62
  return cli_body.resolve({
63
63
  inline: values.body,
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env tsx
2
2
  import { fileURLToPath } from 'node:url'
3
- import { parseArgs } from 'node:util'
4
3
  import { git_gh_issue_read } from '#scripts/gh/git-gh-issue-read'
5
4
  import { git_gh_repo } from '#scripts/gh/git-gh-repo'
6
5
  import { github_issue_url, type IssueUrlTarget } from '#scripts/gh/github-issue-url'
7
6
  import { git_error } from '#scripts/git/git-error'
7
+ import { session_cite } from '#scripts/issue/session-cite'
8
8
  import { josh_environment_file } from '#scripts/josh/josh-environment-file'
9
9
  import { cli_flags } from '#scripts/lib/cli-flags'
10
10
  import { telegram_notify } from './telegram-notify'
@@ -12,36 +12,44 @@ import { telegram_test_logic, type CliValues, type ResolvedContext } from './tel
12
12
 
13
13
  const REPO_NAME_SEPARATOR = '/'
14
14
  const ARGV_OFFSET = 2
15
+ const FAILURE_EXIT_CODE = 1
16
+ const USAGE =
17
+ 'Usage: josh notify [--task-type <type>] [--body <text> | --body-file <path>] [--issue-url <url>] [--pr-url <url>] [--issue-title <text>] [--repo-name <name>]'
15
18
 
16
19
  // The free-text values a caller writes, often opening with a Markdown `-` bullet.
17
20
  const FREE_TEXT_FLAGS = ['--body', '--issue-title']
18
21
 
19
- function parse_cli_arguments(): CliValues {
20
- const { values } = parseArgs({
21
- args: [...cli_flags.attach_values(process.argv.slice(ARGV_OFFSET), FREE_TEXT_FLAGS)],
22
- options: {
23
- 'task-type': { type: 'string' },
24
- 'repo-name': { type: 'string' },
25
- 'issue-title': { type: 'string' },
26
- body: { type: 'string' },
27
- 'body-file': { type: 'string' },
28
- 'issue-url': { type: 'string' },
29
- 'pr-url': { type: 'string' },
30
- },
31
- })
32
-
33
- return values
22
+ const OPTIONS = {
23
+ 'task-type': { type: 'string' },
24
+ 'repo-name': { type: 'string' },
25
+ 'issue-title': { type: 'string' },
26
+ body: { type: 'string' },
27
+ 'body-file': { type: 'string' },
28
+ 'issue-url': { type: 'string' },
29
+ 'pr-url': { type: 'string' },
30
+ } as const
31
+
32
+ // `undefined` for a line nobody can read — an unknown flag, or a flag given no value.
33
+ function parse_cli_arguments(): CliValues | undefined {
34
+ return cli_flags.values_of(
35
+ cli_flags.attach_values(process.argv.slice(ARGV_OFFSET), FREE_TEXT_FLAGS),
36
+ OPTIONS,
37
+ )
38
+ }
39
+
40
+ // A refused line sends nothing: the notification a misspelled flag would have produced is not the one
41
+ // the caller wrote, and the non-zero exit is what tells a workflow it never went out.
42
+ function refuse_usage(): void {
43
+ console.error(USAGE)
44
+ process.exitCode = FAILURE_EXIT_CODE
34
45
  }
35
46
 
36
47
  // The repository this notification is about, for the Telegram header.
37
48
  //
38
- // joshuafolkken/kit#1063: this used to spawn `gh repo view --json nameWithOwner` through a
39
- // promisified `execFile`, which is why joshuafolkken/kit#1022's survey never counted it — the
40
- // callee was not `execa` and the file was not `scripts/`. `gh repo view` goes through GraphQL and
41
- // is answered 403 in a cloud session, so the header simply lost its repository name there.
42
- //
43
- // The same fact is already read over REST by `git_gh_repo`, whose failure contract is the
44
- // `undefined` this caller was already handling, so it is read from there rather than from a second
49
+ // Not `gh repo view`: it goes through GraphQL and is answered 403 in a cloud session, which would
50
+ // lose the header's repository name there. The same fact is already read over REST by
51
+ // `git_gh_repo`, whose failure contract is the `undefined` this caller handles, so it is read from
52
+ // there rather than from a second
45
53
  // spawn (`CLAUDE.md` → "No clones").
46
54
  async function fetch_repo_name(): Promise<string | undefined> {
47
55
  const name_with_owner = await git_gh_repo.repo_get_name_with_owner()
@@ -53,8 +61,7 @@ async function fetch_repo_name(): Promise<string | undefined> {
53
61
 
54
62
  // The title is read from the repository the URL names, through the same reader every other
55
63
  // cross-repository read goes through. Read unqualified, `gh` would answer with the issue of that
56
- // number in the working directory's repository — a different issue with a different title
57
- // (joshuafolkken/kit#903).
64
+ // number in the working directory's repository — a different issue with a different title.
58
65
  //
59
66
  // A repository the token cannot read answers the same `undefined` as an issue that does not exist,
60
67
  // and the notification would then go out with no title line at all. Say so, so the gap is visible
@@ -65,7 +72,9 @@ async function fetch_issue_title(target: IssueUrlTarget | undefined): Promise<st
65
72
  const title = await git_gh_issue_read.issue_get_title(target.issue_number, target.name_with_owner)
66
73
 
67
74
  if (title === undefined) {
68
- console.warn(`⚠️ Could not read ${target.name_with_owner}#${target.issue_number}.`)
75
+ console.warn(
76
+ `⚠️ Could not read ${session_cite.issue(target.issue_number, undefined, target.name_with_owner)}.`,
77
+ )
69
78
  }
70
79
 
71
80
  return title
@@ -90,9 +99,8 @@ async function resolve_issue_title(
90
99
  //
91
100
  // `--issue-url` outranks `--pr-url` because it identifies the issue the title is read from as well
92
101
  // as the repository. A pull URL answers the repository half only, which is why it is read for
93
- // `repo_name` and not passed to `resolve_issue_title` — a completion notification carrying only a
94
- // PR link used to go out under the working directory's repository while its link pointed elsewhere
95
- // (joshuafolkken/kit#994).
102
+ // `repo_name` and not passed to `resolve_issue_title` — otherwise a completion notification carrying
103
+ // only a PR link goes out under the working directory's repository while its link points elsewhere.
96
104
  async function resolve_context(values: CliValues): Promise<ResolvedContext> {
97
105
  const target = github_issue_url.parse(values['issue-url'])
98
106
  const pull_target = github_issue_url.parse_pull(values['pr-url'])
@@ -105,13 +113,20 @@ async function resolve_context(values: CliValues): Promise<ResolvedContext> {
105
113
  async function main(): Promise<void> {
106
114
  josh_environment_file.load_environment_file()
107
115
  const values = parse_cli_arguments()
116
+
117
+ if (values === undefined) {
118
+ refuse_usage()
119
+
120
+ return
121
+ }
122
+
108
123
  const context = await resolve_context(values)
109
124
  const input = telegram_test_logic.build_input({ values, context })
110
125
 
111
126
  await telegram_notify.send(input)
112
127
  }
113
128
 
114
- // **A notification nobody received must not read as success** (joshuafolkken/kit#1564). This command
129
+ // **A notification nobody received must not read as success**. This command
115
130
  // *is* the notification, so a failed send is its result and the exit code has to say so — the state
116
131
  // that Issue measured was three lost messages, each printing a warning and exiting 0.
117
132
  //
@@ -7,10 +7,10 @@ import { observation_ledger_migrate } from './observation-ledger-migrate'
7
7
 
8
8
  // Where the observation ledger is read and written, whichever work tree a command runs in.
9
9
  //
10
- // **The ledger lives in the work tree the command runs in — a lane's in a lane** (joshuafolkken/kit#2919).
11
- // It used to resolve to the primary checkout from every lane (joshuafolkken/kit#2419), so a lane's
12
- // lines waited there for a batch-end flush; another run's stash of that checkout took them, the flush
13
- // read `git status` and found nothing, and the lines were lost. Each run now appends to its own
10
+ // **The ledger lives in the work tree the command runs in — a lane's in a lane**.
11
+ // Resolved to the primary checkout from every lane, a lane's lines would wait there for a batch-end
12
+ // flush; another run's stash of that checkout would take them, the flush would read `git status` and
13
+ // find nothing, and the lines would be lost. Each run appends to its own
14
14
  // issue's file in its own tree, `git-staging.ts` commits it with the run, and `pnpm josh followup`
15
15
  // commits whatever was appended after that commit before it merges — so a lane's lines reach the
16
16
  // default branch with the lane's own pull request, and the primary checkout holds none of them.
@@ -21,8 +21,7 @@ function ledger_root(cwd: string = process.cwd()): string {
21
21
  return cwd
22
22
  }
23
23
 
24
- // **Resolving the directory migrates the single-file ledgers first** (joshuafolkken/kit#2724,
25
- // joshuafolkken/kit#2919). Every reader and writer asks here — `review:record --check`,
24
+ // **Resolving the directory migrates the single-file ledgers first**. Every reader and writer asks here — `review:record --check`,
26
25
  // `review:findings`, the retrospective, the stash carry's duplicate check — so none of them can read a
27
26
  // directory without the lines that still sit at an old path, which for the review-record check would
28
27
  // answer `missing` for a round recorded before the move.
@@ -52,6 +51,12 @@ async function current_branch(cwd: string): Promise<string> {
52
51
  }
53
52
  }
54
53
 
54
+ // The `<YYYY-MM-DD>` a ledger line carries, and the name of a date file — one spelling for every
55
+ // writer, so a line and the file it lands in never disagree about the day.
56
+ function ledger_date(now: Date): string {
57
+ return now.toISOString().slice(0, DATE_END)
58
+ }
59
+
55
60
  // **The file a writer that names no issue appends to** — the issue the checked-out branch leads with
56
61
  // (`2919-lane`, `2919-store-the-ledger`), so a lane's lines land in its own issue's file; or the date,
57
62
  // for a line written on the default branch outside any issue's run, which `pnpm josh
@@ -59,7 +64,7 @@ async function current_branch(cwd: string): Promise<string> {
59
64
  async function writer_path(now: Date, cwd: string = process.cwd()): Promise<string> {
60
65
  const issue = git_branch.issue_from_branch(await current_branch(cwd))
61
66
 
62
- return file_path(issue ?? now.toISOString().slice(0, DATE_END), cwd)
67
+ return file_path(issue ?? ledger_date(now), cwd)
63
68
  }
64
69
 
65
70
  // A file whose last line has no newline would otherwise run into the next file's first line.
@@ -104,7 +109,7 @@ async function read(cwd: string = process.cwd()): Promise<string | undefined> {
104
109
 
105
110
  // The one append every ledger writer goes through. A consumer that does not keep the ledger has no
106
111
  // `docs/` at its root, so the parent is created first — the one write path that can bring the ledger
107
- // into existence there (joshuafolkken/kit#2402).
112
+ // into existence there.
108
113
  async function append(target: string, lines: ReadonlyArray<string>): Promise<void> {
109
114
  if (lines.length === 0) return
110
115
 
@@ -115,6 +120,7 @@ async function append(target: string, lines: ReadonlyArray<string>): Promise<voi
115
120
  const observation_ledger_home = {
116
121
  append,
117
122
  issue_path,
123
+ ledger_date,
118
124
  ledger_root,
119
125
  read,
120
126
  writer_path,
@@ -1,8 +1,8 @@
1
1
  // The observation ledger's line grammar (`.claude/skills/workflow-commands/observation-ledger.md`)
2
2
  // is fixed — `- k:<slug> | d<n> | <YYYY-MM-DD> | <where> | <what>` — but the path was collected in
3
3
  // `observation-ledger.ts` without a line ever being parsed, so a malformed append rode a flush
4
- // through unremarked. This validates a ledger entry line and reports why a broken one is broken
5
- // (joshuafolkken/kit#2123). The grammar is the single source's, pinned by the document test.
4
+ // through unremarked. This validates a ledger entry line and reports why a broken one is broken.
5
+ // The grammar is the single source's, pinned by the document test.
6
6
 
7
7
  const KEY_PREFIX = '- k:'
8
8
  const FIELD_SEPARATOR = ' | '
@@ -96,6 +96,7 @@ function missing_lines(candidates: ReadonlyArray<string>, ledger: string): Array
96
96
  const observation_ledger_line = {
97
97
  broken_ledger_lines,
98
98
  is_ledger_entry_line,
99
+ line_reason,
99
100
  missing_lines,
100
101
  }
101
102
 
@@ -19,9 +19,8 @@ import {
19
19
  } from './observation-ledger'
20
20
  import { observation_ledger_line } from './observation-ledger-line'
21
21
 
22
- // Moves the ledger's lines from the single files it was before joshuafolkken/kit#2919 into the
23
- // directory it is now, as `legacy.md` (`observation-ledger.ts` carries why the old paths are still
24
- // recognized). Changing a constant alone splits the appends: a run still on the old code recreates the
22
+ // Moves the ledger's lines from its old single files into the directory, as `legacy.md`
23
+ // (`observation-ledger.ts` carries why the old paths are still recognized). Changing a constant alone splits the appends: a run still on the old code recreates the
25
24
  // old file, and a consumer repository's existing ledger stays where nothing reads it. So resolving the
26
25
  // ledger migrates first (`observation-ledger-home.ts`), and whatever reached an old path lands in the
27
26
  // directory before anything reads or appends.
@@ -164,7 +163,7 @@ function legacy_directory_names(directory: string): ReadonlyArray<string> {
164
163
  }
165
164
  }
166
165
 
167
- // **The old directory moves file by file into the same names** (joshuafolkken/kit#3341), so an
166
+ // **The old directory moves file by file into the same names**, so an
168
167
  // issue's lines stay in that issue's file; the emptied directory is removed when nothing else is left.
169
168
  function migrate_directory(root: string): boolean {
170
169
  const legacy_directory = path.join(root, LEGACY_OBSERVATION_LEDGER_DIRECTORY)
@@ -1,12 +1,12 @@
1
1
  import { observation_ledger_home } from './observation-ledger-home'
2
2
  import { observation_ledger_line, type BrokenLine } from './observation-ledger-line'
3
3
 
4
- // **What has to hold before a ledger line is committed, asked by every path that commits one**
5
- // (joshuafolkken/kit#2763): `pnpm josh observations:flush`, the run's own commit in
4
+ // **What has to hold before a ledger line is committed, asked by every path that commits one**:
5
+ // `pnpm josh observations:flush`, the run's own commit in
6
6
  // `scripts/git/git-staging.ts` and `pnpm josh followup`'s pre-merge ledger commit. Lines still on an
7
- // old path are moved first (joshuafolkken/kit#2724, joshuafolkken/kit#2919), so the commit carries the
7
+ // old path are moved first, so the commit carries the
8
8
  // move and the lines together, and every entry line is then parsed against the grammar
9
- // (joshuafolkken/kit#2123) — each caller decides what a broken line costs it.
9
+ // — each caller decides what a broken line costs it.
10
10
  //
11
11
  // **A ledger that is not there has no line to break** — the change a status saw is then its deletion,
12
12
  // and a commit carries that like any other change to it.
@@ -1,20 +1,20 @@
1
1
  // The observation ledger's one location, named here rather than inside any of the places that act on
2
- // it (joshuafolkken/kit#1756). `git-staging.ts` stages it with the run's own commit when its grammar
3
- // holds (joshuafolkken/kit#2763), `hook-gate-reuse.ts` excludes it from what a hook calls a carried
2
+ // it. `git-staging.ts` stages it with the run's own commit when its grammar
3
+ // holds, `hook-gate-reuse.ts` excludes it from what a hook calls a carried
4
4
  // tree, and `observations-flush.ts` commits what no run carried — so a literal in each would be three
5
5
  // answers to one question, and a rename reaching only some of them would silently split them.
6
6
  //
7
- // **It sits outside `docs/`** (joshuafolkken/kit#3341): its files are machine-written data lines, not
8
- // documents a person reads, and at about forty new files a day they were most of `docs/`.
7
+ // **It sits outside `docs/`**: its files are machine-written data lines, not
8
+ // documents a person reads, and at about forty new files a day they would be most of `docs/`.
9
9
  //
10
- // **It is a directory of one file per issue, not one file** (joshuafolkken/kit#2919). One file every
11
- // run appended to made two lanes' pull requests conflict at its tail, so lanes parked their lines in
12
- // the primary checkout for a batch-end flush — and another run's stash took them from there, and the
13
- // flush never saw them. A run now appends to `<issue>.md` in its own work tree and merges it with its
14
- // own pull request: parallel lanes write different files, so nothing conflicts and nothing waits.
10
+ // **It is a directory of one file per issue, not one file**. One file every run appends to makes two
11
+ // lanes' pull requests conflict at its tail, and parking the lines in the primary checkout for a
12
+ // batch-end flush lets another run's stash take them before the flush sees them. A run appends to
13
+ // `<issue>.md` in its own work tree and merges it with its own pull request: parallel lanes write
14
+ // different files, so nothing conflicts and nothing waits.
15
15
  const OBSERVATION_LEDGER_DIRECTORY = '.josh/observations'
16
16
 
17
- // Where the directory lived until joshuafolkken/kit#3341, a migration source for the same reasons as
17
+ // The directory's previous location, a migration source for the same reasons as
18
18
  // the single-file ledgers below: each `<name>.md` in it moves to the same name in the directory.
19
19
  const LEGACY_OBSERVATION_LEDGER_DIRECTORY = 'docs/maintainers/observations'
20
20
 
@@ -29,10 +29,9 @@ const LEDGER_FILE_EXTENSION = '.md'
29
29
  // lost to the split.
30
30
  const LEGACY_LEDGER_FILE = `legacy${LEDGER_FILE_EXTENSION}`
31
31
 
32
- // Where the ledger lived as one file — `docs/observations.md` before joshuafolkken/kit#2724 and
33
- // `docs/maintainers/observations.md` until joshuafolkken/kit#2919 — kept as migration sources rather
34
- // than forgotten: a run still on the old code, a stash cut before the move and a consumer repository's
35
- // existing ledger all write there, and `observation-ledger-migrate.ts` moves what it finds into the
32
+ // The single-file ledger paths, `docs/observations.md` and `docs/maintainers/observations.md`, kept
33
+ // as migration sources rather than forgotten: a run still on the old code, a stash cut before the
34
+ // move and a consumer repository's existing ledger all write there, and `observation-ledger-migrate.ts` moves what it finds into the
36
35
  // directory. Every place that recognizes the ledger recognizes them, so a line on either path is never
37
36
  // staged into an ordinary commit. Remove them once every repository holding a ledger has migrated.
38
37
  const LEGACY_OBSERVATION_LEDGER_PATHS: ReadonlyArray<string> = [
@@ -105,7 +104,7 @@ function ledger_paths(status_output: string): ReadonlyArray<string> {
105
104
 
106
105
  // **The one place that answers "does this working tree hold a pending observation append?"**
107
106
  // `observations-flush.ts`'s `has_ledger_change` and `pnpm josh followup`'s pre-merge ledger commit
108
- // both ask it (joshuafolkken/kit#1810), so a literal in each would be the clone the header above
107
+ // both ask it, so a literal in each would be the clone the header above
109
108
  // warns against. A blank porcelain line carries no ledger path, so `is_ledger_line` answers false for
110
109
  // it and no filtering is needed.
111
110
  function has_pending_append(status_output: string): boolean {
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env tsx
2
+ import { fileURLToPath } from 'node:url'
3
+ import { cli_flags } from '#scripts/lib/cli-flags'
4
+ import { observation_ledger_home } from './observation-ledger-home'
5
+ import {
6
+ observation_record,
7
+ REFUSED_VERDICT,
8
+ type ObservationEntry,
9
+ type RecordResult,
10
+ } from './observation-record'
11
+
12
+ // `josh observation:record <key> <depth> <where> <what>` — count the key's earlier sightings, append
13
+ // this one, and answer what the run does next. Exactly one token on stdout:
14
+ // `file` on the second sighting, which the promotion rule files; `ledger` on any other, which the line
15
+ // alone records. The earlier sightings and the file written go to stderr, so the Issue a `file` answer
16
+ // opens can quote the first sighting's date from them.
17
+
18
+ const ARGV_OFFSET = 2
19
+ const FAILURE_EXIT_CODE = 1
20
+ const ENTRY_FIELDS = 4
21
+ const USAGE = 'Usage: josh observation:record <key> <depth> <where> <what> [--checkout <path>]'
22
+ const OPTIONS = { checkout: { type: 'string' } } as const
23
+
24
+ interface RecordArguments {
25
+ entry: ObservationEntry
26
+ checkout: string
27
+ }
28
+
29
+ function entry_of(fields: ReadonlyArray<string>): ObservationEntry {
30
+ const [slug = '', depth = '', where = '', what = ''] = fields
31
+
32
+ return { slug, depth, where, what }
33
+ }
34
+
35
+ function parse_arguments(argv: ReadonlyArray<string>): RecordArguments | undefined {
36
+ const parsed = cli_flags.arguments_of(argv, OPTIONS)
37
+
38
+ if (parsed?.positionals.length !== ENTRY_FIELDS) return undefined
39
+
40
+ const { checkout } = parsed.values
41
+
42
+ return {
43
+ entry: entry_of(parsed.positionals),
44
+ checkout: checkout ?? observation_ledger_home.ledger_root(),
45
+ }
46
+ }
47
+
48
+ function report(result: RecordResult): number {
49
+ if (result.verdict === REFUSED_VERDICT) {
50
+ console.error(`Refused: ${result.reason}\n${USAGE}`)
51
+
52
+ return FAILURE_EXIT_CODE
53
+ }
54
+
55
+ const sighting = `${String(result.earlier.length)} earlier sighting(s); appended to ${result.target}`
56
+
57
+ console.error([sighting, ...result.earlier].join('\n'))
58
+ console.info(result.verdict)
59
+
60
+ return 0
61
+ }
62
+
63
+ async function run(argv: ReadonlyArray<string>, now: Date): Promise<number> {
64
+ const parsed = parse_arguments(argv)
65
+
66
+ if (parsed === undefined) {
67
+ console.error(USAGE)
68
+
69
+ return FAILURE_EXIT_CODE
70
+ }
71
+
72
+ return report(await observation_record.record({ ...parsed, now }))
73
+ }
74
+
75
+ async function main(argv: ReadonlyArray<string>): Promise<void> {
76
+ process.exitCode = await run(argv, new Date())
77
+ }
78
+
79
+ const observation_record_cli = { USAGE, run }
80
+
81
+ if (process.argv[1] === fileURLToPath(import.meta.url)) await main(process.argv.slice(ARGV_OFFSET))
82
+
83
+ export { observation_record_cli }