@joshuafolkken/kit 1.1050.0 → 1.1128.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 (630) hide show
  1. package/.claude/settings.json +9 -8
  2. package/.claude/skills/epic-commands/SKILL.md +5 -7
  3. package/.claude/skills/workflow-commands/SKILL.md +20 -12
  4. package/.claude/skills/workflow-commands/background-commands.md +36 -84
  5. package/.claude/skills/workflow-commands/backlogrun-child.md +1 -1
  6. package/.claude/skills/workflow-commands/backlogrun-lanes.md +8 -6
  7. package/.claude/skills/workflow-commands/backlogrun-progress.md +30 -33
  8. package/.claude/skills/workflow-commands/backlogrun-steps.md +12 -12
  9. package/.claude/skills/workflow-commands/backlogrun.md +2 -2
  10. package/.claude/skills/workflow-commands/chain-rule.md +4 -2
  11. package/.claude/skills/workflow-commands/delegation.md +3 -3
  12. package/.claude/skills/workflow-commands/followup-reference.md +1 -1
  13. package/.claude/skills/workflow-commands/followup.md +7 -3
  14. package/.claude/skills/workflow-commands/fullrun-steps.md +3 -2
  15. package/.claude/skills/workflow-commands/fullrun.md +8 -6
  16. package/.claude/skills/workflow-commands/halfrun.md +19 -21
  17. package/.claude/skills/workflow-commands/issue-comments.md +1 -1
  18. package/.claude/skills/workflow-commands/issue-fold-existing.md +10 -10
  19. package/.claude/skills/workflow-commands/issue-scout.md +1 -1
  20. package/.claude/skills/workflow-commands/kickoff.md +9 -4
  21. package/.claude/skills/workflow-commands/latest-gate.md +8 -16
  22. package/.claude/skills/workflow-commands/needs-human-review.md +1 -1
  23. package/.claude/skills/workflow-commands/observation-filing.md +3 -3
  24. package/.claude/skills/workflow-commands/pre-gate-cut.md +4 -8
  25. package/.claude/skills/workflow-commands/prerequisite.md +1 -1
  26. package/.claude/skills/workflow-commands/prrun.md +36 -0
  27. package/.claude/skills/workflow-commands/retrospective.md +1 -1
  28. package/.claude/skills/workflow-commands/split-assessment.md +4 -18
  29. package/.claude/skills/workflow-commands/working-tree-hold.md +22 -2
  30. package/.codex/hooks.json +16 -20
  31. package/.github/actions/setup-node/action.yml +33 -0
  32. package/.github/actions/setup-pnpm/action.yml +93 -0
  33. package/.github/dependabot.yml +5 -1
  34. package/.github/workflows/auto-tag.yml +2 -3
  35. package/.github/workflows/ci.yml +31 -134
  36. package/.github/workflows/dependabot-auto-merge.yml +1 -0
  37. package/.github/workflows/pr-classification.yml +6 -44
  38. package/.github/workflows/production.yml +1 -0
  39. package/.github/workflows/publish.yml +43 -47
  40. package/.github/workflows/sonar-qube.yml +41 -4
  41. package/.pnpmfile.mjs +29 -0
  42. package/AGENTS.md +5 -2
  43. package/CLAUDE.md +33 -27
  44. package/GEMINI.md +5 -2
  45. package/README.md +66 -20
  46. package/SECURITY.md +37 -6
  47. package/cspell/index.yaml +6 -1
  48. package/dist/CLAUDE.basic.md +6 -6
  49. package/dist/CLAUDE.md +33 -27
  50. package/dist/CLAUDE.static.md +6 -6
  51. package/dist/config-merge/index.js +48 -12
  52. package/dist/hooks/batch-guard.js +4 -4
  53. package/dist/hooks/{chunk-7VPDUBRN.js → chunk-4JZDP5X5.js} +152 -155
  54. package/dist/hooks/{chunk-HJIISEAC.js → chunk-5SD2YM7Z.js} +5 -13
  55. package/dist/hooks/{chunk-NAS4C7GP.js → chunk-77J7IEQM.js} +2 -2
  56. package/dist/hooks/{chunk-DMQN45FN.js → chunk-7HVB7SZG.js} +3 -3
  57. package/dist/hooks/{chunk-RLDX5SOC.js → chunk-AIOIOMPX.js} +4413 -1970
  58. package/dist/hooks/{chunk-5BK3K7V4.js → chunk-M7QKEKWO.js} +873 -2049
  59. package/dist/hooks/{chunk-WQ4OSBSS.js → chunk-MKVGBQPA.js} +2 -2
  60. package/dist/hooks/{chunk-EJDX2TOB.js → chunk-NXYMNPUQ.js} +7 -88
  61. package/dist/hooks/{chunk-NJQOBE6L.js → chunk-QVLT52OV.js} +2 -7
  62. package/dist/hooks/{chunk-GQ7KP45M.js → chunk-XYUIQOW3.js} +2 -2
  63. package/dist/hooks/codex-hook-adapter.js +12 -48
  64. package/dist/hooks/duplicate-read-guard.js +5 -5
  65. package/dist/hooks/format-edited.js +2 -2
  66. package/dist/hooks/inputs.json +280 -0
  67. package/dist/hooks/investigation-guard.js +5 -5
  68. package/dist/hooks/pretool-guard.js +9 -9
  69. package/dist/hooks/session-lang.js +0 -1
  70. package/dist/hooks/stop-guard.js +192 -333
  71. package/dist/josh.js +240 -148
  72. package/dist/managed-marker/index.js +2 -1
  73. package/dist/version/index.js +70 -78
  74. package/eslint/rules/promise.js +5 -0
  75. package/eslint/rules/unicorn.js +3 -2
  76. package/package.json +26 -5
  77. package/pnpm-workspace.yaml +5 -7
  78. package/prompts/collaboration-workflow/glossary.md +17 -0
  79. package/prompts/collaboration-workflow/issue-citation.md +5 -5
  80. package/prompts/collaboration-workflow/issue-template.md +1 -1
  81. package/prompts/collaboration-workflow/operating-rules.md +5 -5
  82. package/prompts/collaboration-workflow/overview.md +13 -1
  83. package/prompts/collaboration-workflow/principles.md +9 -0
  84. package/prompts/collaboration-workflow/report-format.md +1 -1
  85. package/prompts/collaboration-workflow/residency.md +3 -3
  86. package/prompts/collaboration-workflow/rule-delivery.md +1 -1
  87. package/prompts/collaboration-workflow/turn-batching.md +3 -3
  88. package/prompts/collaboration-workflow/upstream-interrupt.md +1 -1
  89. package/prompts/collaboration-workflow/wip-cap.md +25 -22
  90. package/prompts/collaboration-workflow.md +6 -8
  91. package/prompts/review-rubric.md +1 -1
  92. package/prompts/review.md +3 -3
  93. package/prompts/sonar-hotspot-handling.md +11 -3
  94. package/prompts/testing-guide.md +3 -3
  95. package/scripts/adopt/adopt-toolkits.ts +0 -2
  96. package/scripts/adopt/adopt.ts +0 -2
  97. package/scripts/agent/agent-argv.ts +0 -2
  98. package/scripts/agent/agent-diagnostics.ts +1 -1
  99. package/scripts/agent/agent-role-profile.ts +0 -7
  100. package/scripts/agent/claude-agent-argv.ts +0 -2
  101. package/scripts/agent/codex-agent-argv.ts +1 -1
  102. package/scripts/agent/codex-hooks.ts +92 -0
  103. package/scripts/agent/interactive-ask.ts +1 -1
  104. package/scripts/auto-ok/auto-ok-cli.ts +6 -16
  105. package/scripts/backlog/backlog-arrival.ts +30 -10
  106. package/scripts/backlog/backlog-budget-cli.ts +15 -16
  107. package/scripts/backlog/backlog-budget.ts +0 -2
  108. package/scripts/backlog/backlog-defect-priority.ts +2 -2
  109. package/scripts/backlog/backlog-drive-cli.ts +10 -8
  110. package/scripts/backlog/backlog-drive-named-offer.ts +16 -3
  111. package/scripts/backlog/backlog-drive-named.ts +2 -1
  112. package/scripts/backlog/backlog-drive.ts +76 -16
  113. package/scripts/backlog/backlog-named.ts +0 -3
  114. package/scripts/backlog/backlog-next.ts +9 -15
  115. package/scripts/backlog/backlog-offer-cli.ts +6 -19
  116. package/scripts/backlog/backlog-plan-cli.ts +1 -7
  117. package/scripts/backlog/backlog-plan.ts +30 -19
  118. package/scripts/backlog/backlog-pool.ts +3 -6
  119. package/scripts/backlog/backlog-rank.ts +2 -2
  120. package/scripts/backlog/backlog-ready.ts +39 -10
  121. package/scripts/backlog/backlog-scope.ts +1 -3
  122. package/scripts/backlog/backlog-stalled-detect.ts +2 -2
  123. package/scripts/backlog/backlog-stalled.ts +0 -1
  124. package/scripts/backlog/backlog-waves.ts +5 -2
  125. package/scripts/behavior/behavior-cli.ts +1 -1
  126. package/scripts/build/build-codex-hooks.ts +26 -0
  127. package/scripts/build/build-hooks.ts +85 -9
  128. package/scripts/build/hook-bundle-stamp.ts +111 -0
  129. package/scripts/cases/cases-cli.ts +1 -1
  130. package/scripts/cases/cases-logic.ts +1 -1
  131. package/scripts/ci/composite-actions.ts +30 -0
  132. package/scripts/ci/pr-classification.ts +3 -3
  133. package/scripts/claude/workflow-destination.ts +10 -1
  134. package/scripts/clone/clone-fingerprint.ts +0 -1
  135. package/scripts/clone/clone-scan-cli.ts +1 -1
  136. package/scripts/clone/clone-scan.ts +1 -1
  137. package/scripts/config-merge/json-format.ts +0 -1
  138. package/scripts/config-merge/parse-jsonc.ts +33 -3
  139. package/scripts/config-merge/patch-json-key.ts +13 -6
  140. package/scripts/config-merge/patch-yaml-list.ts +1 -1
  141. package/scripts/cost-runtime/codex-usage.ts +2 -9
  142. package/scripts/cost-runtime/cost-attribute.ts +0 -1
  143. package/scripts/cost-runtime/cost-cli.ts +3 -10
  144. package/scripts/cost-runtime/cost-corpus.ts +0 -2
  145. package/scripts/cost-runtime/cost-format.ts +0 -3
  146. package/scripts/cost-runtime/cost-pricing.ts +0 -1
  147. package/scripts/cost-runtime/cost-tokens.ts +0 -1
  148. package/scripts/delegation/delegation-cli.ts +1 -1
  149. package/scripts/delegation/delegation-policy.ts +0 -1
  150. package/scripts/delegation/duplicate-read-guard.ts +0 -8
  151. package/scripts/delegation/fanout-cli.ts +1 -1
  152. package/scripts/delegation/fanout.ts +0 -2
  153. package/scripts/delegation/investigation-reads.ts +1 -164
  154. package/scripts/discovery/repo-map-logic.ts +0 -1
  155. package/scripts/discovery/repo-party-cli.ts +1 -1
  156. package/scripts/doctor/doctor-consumer.ts +6 -10
  157. package/scripts/doctor/doctor-io.ts +9 -13
  158. package/scripts/doctor/doctor-logic.ts +0 -4
  159. package/scripts/doctor/doctor.ts +14 -9
  160. package/scripts/document/backlogrun-parent-read-set.ts +12 -1
  161. package/scripts/document/document-byte-budget.ts +5 -5
  162. package/scripts/document/document-byte-check.ts +0 -1
  163. package/scripts/document/document-read-cli.ts +0 -2
  164. package/scripts/document/document-section-cli.ts +1 -1
  165. package/scripts/document/document-section.ts +0 -3
  166. package/scripts/document/edit-files-cli.ts +0 -1
  167. package/scripts/document/entry-read-budget.ts +21 -7
  168. package/scripts/document/entry-read-set.ts +32 -8
  169. package/scripts/document/lane-child-read-set.ts +8 -6
  170. package/scripts/document/read-files-cli.ts +0 -4
  171. package/scripts/document/read-set-cli.ts +0 -2
  172. package/scripts/document/read-set-point-of-use.ts +9 -3
  173. package/scripts/document/read-set-pricing.ts +0 -1
  174. package/scripts/document/read-set-trim.ts +4 -2
  175. package/scripts/epic/epic-add.ts +1 -1
  176. package/scripts/epic/epic-audit-cli.ts +1 -4
  177. package/scripts/epic/epic-audit-orphans.ts +1 -3
  178. package/scripts/epic/epic-audit-rationale.ts +0 -1
  179. package/scripts/epic/epic-audit-report.ts +0 -2
  180. package/scripts/epic/epic-audit.ts +8 -22
  181. package/scripts/epic/epic-bundle-cli.ts +1 -1
  182. package/scripts/epic/epic-bundle-evidence.ts +0 -1
  183. package/scripts/epic/epic-bundle-referenced.ts +1 -5
  184. package/scripts/epic/epic-bundle.ts +0 -4
  185. package/scripts/epic/epic-busy.ts +4 -5
  186. package/scripts/epic/epic-candidate-confirm.ts +0 -5
  187. package/scripts/epic/epic-classify.ts +2 -2
  188. package/scripts/epic/epic-cli-argv.ts +0 -1
  189. package/scripts/epic/epic-close-comment.ts +1 -1
  190. package/scripts/epic/epic-close.ts +5 -2
  191. package/scripts/epic/epic-cross-repo.ts +2 -4
  192. package/scripts/epic/epic-decision.ts +0 -1
  193. package/scripts/epic/epic-fetch.ts +2 -2
  194. package/scripts/epic/epic-index.ts +2 -3
  195. package/scripts/epic/epic-issue.ts +1 -15
  196. package/scripts/epic/epic-lane-offer.ts +9 -8
  197. package/scripts/epic/epic-nested.ts +1 -1
  198. package/scripts/epic/epic-next-read.ts +1 -3
  199. package/scripts/epic/epic-next-views.ts +0 -1
  200. package/scripts/epic/epic-next.ts +1 -10
  201. package/scripts/epic/epic-parse.ts +0 -1
  202. package/scripts/epic/epic-promote.ts +0 -9
  203. package/scripts/epic/epic-rank.ts +2 -2
  204. package/scripts/epic/epic-read.ts +1 -2
  205. package/scripts/epic/epic-reconcile.ts +1 -1
  206. package/scripts/epic/epic-reference.ts +1 -13
  207. package/scripts/epic/epic-relation-recheck.ts +1 -1
  208. package/scripts/epic/epic-relations.ts +1 -1
  209. package/scripts/epic/epic-remove.ts +1 -1
  210. package/scripts/epic/epic-report.ts +0 -1
  211. package/scripts/epic/epic-run.ts +2 -3
  212. package/scripts/epic/epic-shape.ts +1 -1
  213. package/scripts/epic/epic-solo-stale.ts +107 -0
  214. package/scripts/epic/epic-solo.ts +3 -2
  215. package/scripts/epic/epic-triage.ts +1 -1
  216. package/scripts/epic/epic-validate.ts +1 -1
  217. package/scripts/epic/epic.ts +1 -1
  218. package/scripts/exports/unused-members-cli.ts +53 -0
  219. package/scripts/{git → followup}/followup-issue-number.ts +1 -6
  220. package/scripts/{git → followup}/git-followup-cleanup.ts +2 -1
  221. package/scripts/{git → followup}/git-followup-finish.ts +1 -3
  222. package/scripts/{git → followup}/git-followup-flush.ts +2 -2
  223. package/scripts/{git → followup}/git-followup-issue-close.ts +2 -2
  224. package/scripts/{git → followup}/git-followup-label.ts +4 -4
  225. package/scripts/followup/git-followup-merged.ts +112 -0
  226. package/scripts/{git → followup}/git-followup-pending.ts +1 -1
  227. package/scripts/{git → followup}/git-followup-workflow.ts +19 -11
  228. package/scripts/{git → followup}/git-pr-followup-wrapup.ts +9 -3
  229. package/scripts/{git → followup}/git-pr-followup.ts +53 -16
  230. package/scripts/gate/core-budget.ts +3 -9
  231. package/scripts/gate/gate-plan.ts +7 -4
  232. package/scripts/gate/gate-report.ts +0 -6
  233. package/scripts/gate/gate-tree.ts +1 -1
  234. package/scripts/gate/pre-commit-type-check.ts +0 -6
  235. package/scripts/gate/project-checks.ts +7 -8
  236. package/scripts/gate/scoped-green.ts +0 -1
  237. package/scripts/gate/type-check-step.ts +1 -1
  238. package/scripts/gate/verification-gate.ts +0 -2
  239. package/scripts/gh/fix-gh-packages.ts +15 -12
  240. package/scripts/gh/gh-spawn.ts +2 -2
  241. package/scripts/{git → gh}/git-ai-review-scan.ts +1 -5
  242. package/scripts/{git → gh}/git-gh-check.ts +2 -1
  243. package/scripts/{git → gh}/git-gh-exec.ts +1 -1
  244. package/scripts/{git → gh}/git-gh-failure.ts +1 -1
  245. package/scripts/{git → gh}/git-gh-helpers.ts +0 -1
  246. package/scripts/{git → gh}/git-gh-issue-list.ts +13 -10
  247. package/scripts/{git → gh}/git-gh-issue-read.ts +1 -1
  248. package/scripts/{git → gh}/git-gh-issue-rest.ts +6 -3
  249. package/scripts/{git → gh}/git-gh-issue-write.ts +4 -1
  250. package/scripts/{git → gh}/git-gh-pr-auto-merge.ts +4 -1
  251. package/scripts/{git → gh}/git-gh-pr-read.ts +24 -0
  252. package/scripts/{git → gh}/git-gh-pr-rest.ts +5 -2
  253. package/scripts/{git → gh}/git-gh-pr-review.ts +2 -2
  254. package/scripts/{git → gh}/git-gh-pr-rollup.ts +1 -3
  255. package/scripts/{git → gh}/git-gh-pr.ts +3 -1
  256. package/scripts/{git → gh}/git-pr-ai-review.ts +2 -5
  257. package/scripts/{git → gh}/git-pr-checks-eval.ts +0 -10
  258. package/scripts/{git → gh}/git-pr-checks-parse.ts +4 -20
  259. package/scripts/{git → gh}/git-pr-checks.ts +2 -1
  260. package/scripts/{git → gh}/git-pr-coderabbit.ts +2 -5
  261. package/scripts/{git → gh}/git-pr-confirmation.ts +1 -3
  262. package/scripts/{git → gh}/git-pr-managed-config.ts +2 -3
  263. package/scripts/{git → gh}/git-pr.ts +3 -3
  264. package/scripts/git/changed-file-scope.ts +0 -1
  265. package/scripts/git/git-branch.ts +3 -6
  266. package/scripts/git/git-command.ts +6 -1
  267. package/scripts/git/git-commit.ts +1 -1
  268. package/scripts/git/git-common-directory.ts +80 -24
  269. package/scripts/git/git-error.ts +66 -9
  270. package/scripts/git/git-issue.ts +1 -1
  271. package/scripts/git/git-preflight.ts +2 -2
  272. package/scripts/git/git-prompt.ts +6 -31
  273. package/scripts/git/git-push.ts +1 -1
  274. package/scripts/git/git-spawn-sync.ts +65 -0
  275. package/scripts/git/git-spawn.ts +5 -4
  276. package/scripts/git/git-staging.ts +1 -0
  277. package/scripts/git/git-status.ts +1 -1
  278. package/scripts/git/git-workflow.ts +1 -1
  279. package/scripts/git/gone-branch.ts +1 -0
  280. package/scripts/git/listing-cutoff.ts +1 -1
  281. package/scripts/git/main-merge.ts +1 -1
  282. package/scripts/git/main-sync.ts +19 -1
  283. package/scripts/git/parse-json-array.ts +0 -3
  284. package/scripts/git/repository-lock.ts +16 -16
  285. package/scripts/git/{git-stash.ts → stash/git-stash.ts} +1 -1
  286. package/scripts/git/{stash-pop-args.ts → stash/stash-pop-args.ts} +2 -7
  287. package/scripts/git/{stash-pop-cli.ts → stash/stash-pop-cli.ts} +0 -1
  288. package/scripts/git/{stash-sweep-lock.ts → stash/stash-sweep-lock.ts} +3 -3
  289. package/scripts/hooks/codex-hook-adapter.ts +0 -1
  290. package/scripts/hooks/edited-cspell.ts +1 -1
  291. package/scripts/hooks/format-edited-file.ts +2 -0
  292. package/scripts/hooks/pre-push-unit.ts +0 -4
  293. package/scripts/hooks/pretool-guard.ts +22 -4
  294. package/scripts/hooks/reserved-run.ts +1 -1
  295. package/scripts/hooks/step-zero-notice.ts +76 -0
  296. package/scripts/hooks/stop-guard.ts +47 -21
  297. package/scripts/init/claude-plugin-config.ts +4 -5
  298. package/scripts/init/hook-command-rewrite.ts +16 -8
  299. package/scripts/init/hook-launch.ts +41 -15
  300. package/scripts/init/init-basic.ts +2 -5
  301. package/scripts/init/init-file-action.ts +54 -0
  302. package/scripts/init/init-logic-migrate.ts +35 -17
  303. package/scripts/init/init-logic-secretlint.ts +1 -1
  304. package/scripts/init/init-logic.ts +10 -19
  305. package/scripts/init/init.ts +11 -71
  306. package/scripts/init/kit-written-paths.ts +2 -0
  307. package/scripts/init/project-profile.ts +9 -17
  308. package/scripts/init/start-exec.ts +1 -1
  309. package/scripts/init/start-setup-pr.ts +6 -6
  310. package/scripts/init/start-steps.ts +3 -1
  311. package/scripts/issue/behavior-change-lint.ts +0 -1
  312. package/scripts/issue/defect-rate-cli.ts +64 -23
  313. package/scripts/issue/defect-rate.ts +1 -2
  314. package/scripts/{git → issue}/git-next-issues.ts +3 -3
  315. package/scripts/issue/issue-backlinks-cli.ts +1 -5
  316. package/scripts/issue/issue-backlinks.ts +7 -14
  317. package/scripts/issue/issue-cite-cli.ts +2 -6
  318. package/scripts/issue/issue-cite.ts +12 -8
  319. package/scripts/issue/issue-classification.ts +1 -9
  320. package/scripts/issue/issue-closing-pr.ts +4 -4
  321. package/scripts/issue/issue-comment-cli.ts +2 -2
  322. package/scripts/issue/issue-file-cli.ts +5 -5
  323. package/scripts/issue/issue-file.ts +7 -14
  324. package/scripts/issue/issue-fold-cli.ts +1 -1
  325. package/scripts/issue/issue-fold-existing-cli.ts +1 -1
  326. package/scripts/{git → issue}/issue-labels.ts +8 -0
  327. package/scripts/issue/issue-lint-cli.ts +1 -1
  328. package/scripts/issue/issue-merged.ts +2 -2
  329. package/scripts/{git → issue}/issue-rank.ts +1 -1
  330. package/scripts/issue/issue-read-cli.ts +8 -47
  331. package/scripts/issue/issue-read.ts +0 -2
  332. package/scripts/issue/issue-report-failures.ts +80 -0
  333. package/scripts/issue/issue-scout-cli.ts +1 -7
  334. package/scripts/issue/issue-scout-closed.ts +2 -2
  335. package/scripts/issue/issue-scout.ts +0 -2
  336. package/scripts/issue/issue-state-cli.ts +5 -46
  337. package/scripts/issue/issue-state.ts +1 -5
  338. package/scripts/issue/markdown-section.ts +21 -6
  339. package/scripts/issue/measure-rerun-cli.ts +74 -15
  340. package/scripts/issue/reproduction-measure.ts +1 -1
  341. package/scripts/josh/cli-body.ts +1 -1
  342. package/scripts/josh/file-map-stamp.ts +0 -3
  343. package/scripts/josh/josh-command-map.ts +2 -0
  344. package/scripts/josh/josh-commands-ai.ts +9 -102
  345. package/scripts/josh/josh-commands-backlog.ts +5 -1
  346. package/scripts/josh/josh-commands-development.ts +8 -1
  347. package/scripts/josh/josh-commands-issue.ts +2 -2
  348. package/scripts/josh/josh-commands-maintenance.ts +7 -0
  349. package/scripts/josh/josh-commands-project.ts +7 -1
  350. package/scripts/josh/josh-commands-run.ts +114 -0
  351. package/scripts/josh/josh-commands-versioning.ts +8 -0
  352. package/scripts/josh/josh-commands-workflow.ts +3 -3
  353. package/scripts/josh/path-decision.ts +0 -3
  354. package/scripts/josh/process-owner.ts +16 -0
  355. package/scripts/josh/run-github-prerequisite.ts +3 -6
  356. package/scripts/josh/session-language-cli.ts +0 -1
  357. package/scripts/lane/lane-await.ts +46 -19
  358. package/scripts/lane/lane-capacity.ts +6 -3
  359. package/scripts/lane/lane-child-invocation.ts +20 -7
  360. package/scripts/lane/lane-cli.ts +1 -4
  361. package/scripts/lane/lane-close.ts +5 -4
  362. package/scripts/lane/lane-dispatch.ts +3 -4
  363. package/scripts/lane/lane-environment.ts +0 -9
  364. package/scripts/lane/lane-handoff.ts +38 -0
  365. package/scripts/lane/lane-launch-cli.ts +31 -27
  366. package/scripts/lane/lane-open.ts +0 -3
  367. package/scripts/lane/lane-output.ts +0 -1
  368. package/scripts/lane/lane-registry.ts +9 -0
  369. package/scripts/lane/openai-lane-ship.ts +2 -0
  370. package/scripts/lane/openai-lane-supervisor-decision.ts +2 -1
  371. package/scripts/lane/openai-lane-supervisor.ts +6 -4
  372. package/scripts/lane/openai-review-broker.ts +7 -1
  373. package/scripts/lib/bounded-pool.ts +1 -0
  374. package/scripts/lib/cli-flags.ts +31 -2
  375. package/scripts/lib/error-message.ts +12 -1
  376. package/scripts/lib/json-value.ts +5 -4
  377. package/scripts/lib/poll.ts +3 -1
  378. package/scripts/lib/timed-fetch.ts +15 -0
  379. package/scripts/lib/timeouts.ts +13 -0
  380. package/scripts/{yaml → lib}/yaml-document.ts +3 -1
  381. package/scripts/{bytes → lines}/bytes-command.ts +0 -2
  382. package/scripts/lines/line-targets.ts +0 -11
  383. package/scripts/lines/lines-command.ts +5 -4
  384. package/scripts/lint/lint-related-scope.ts +0 -1
  385. package/scripts/lint/lint-related.ts +1 -1
  386. package/scripts/{git → notify}/telegram-notify.ts +2 -2
  387. package/scripts/{git → notify}/telegram-test.ts +4 -4
  388. package/scripts/observations/observation-ledger-home.ts +0 -1
  389. package/scripts/observations/observation-ledger-line.ts +0 -1
  390. package/scripts/observations/observation-ledger-migrate.ts +1 -1
  391. package/scripts/observations/observations-flush-landing.ts +3 -3
  392. package/scripts/observations/observations-flush.ts +2 -2
  393. package/scripts/overrides/lockfile-overrides.ts +1 -1
  394. package/scripts/overrides/overrides-logic.ts +1 -1
  395. package/scripts/package/package-scout-cli.ts +2 -7
  396. package/scripts/package/package-scout.ts +0 -2
  397. package/scripts/propagate/propagate-git-failure.ts +0 -1
  398. package/scripts/propagate/propagate-git.ts +3 -10
  399. package/scripts/propagate/propagate-publish.ts +2 -3
  400. package/scripts/propagate/propagate-run.ts +0 -2
  401. package/scripts/propagate/propagate-steps.ts +3 -5
  402. package/scripts/propagate/propagate-targets.ts +0 -4
  403. package/scripts/propagate/propagate.ts +0 -4
  404. package/scripts/refactor/import-graph.ts +0 -1
  405. package/scripts/refactor/refactor-lint.ts +0 -2
  406. package/scripts/refactor/refactor-scan.ts +2 -2
  407. package/scripts/refactor/refactor-targets.ts +0 -1
  408. package/scripts/registry-migration/migrate-logic.ts +28 -21
  409. package/scripts/registry-migration/migrate.ts +25 -14
  410. package/scripts/release/github-release-cli.ts +19 -6
  411. package/scripts/release/github-release-environment.ts +46 -0
  412. package/scripts/release/github-release.ts +151 -94
  413. package/scripts/release/release-history.ts +0 -1
  414. package/scripts/release/release-plan.ts +0 -1
  415. package/scripts/release/release-publish.ts +38 -5
  416. package/scripts/release/release-scope-cli.ts +1 -2
  417. package/scripts/release/release-tag.ts +2 -4
  418. package/scripts/release/release-worktree.ts +97 -2
  419. package/scripts/repo/auto-merge-setting-logic.ts +1 -4
  420. package/scripts/repo/repo-setting.ts +1 -1
  421. package/scripts/repo/repository-labels.ts +3 -3
  422. package/scripts/repo/required-checks-logic.ts +206 -0
  423. package/scripts/repo/required-checks-report.ts +71 -0
  424. package/scripts/repo/ruleset-check-cli.ts +53 -0
  425. package/scripts/repo/ruleset-check.ts +147 -0
  426. package/scripts/report/report-lint-cli.ts +0 -4
  427. package/scripts/review/disposition-cli.ts +1 -1
  428. package/scripts/review/live-evidence.ts +1 -1
  429. package/scripts/review/review-attest-cli.ts +0 -6
  430. package/scripts/review/review-attest.ts +4 -16
  431. package/scripts/review/review-brief-cli.ts +23 -6
  432. package/scripts/review/review-brief.ts +21 -8
  433. package/scripts/review/review-checkout.ts +3 -2
  434. package/scripts/review/review-diff-parts.ts +89 -0
  435. package/scripts/review/review-diff-write.ts +97 -0
  436. package/scripts/review/review-finding-ledger.ts +0 -1
  437. package/scripts/review/review-record-cli.ts +10 -17
  438. package/scripts/review/review-record.ts +0 -1
  439. package/scripts/review/review-round2-cli.ts +1 -1
  440. package/scripts/review/review-stamps.ts +0 -3
  441. package/scripts/review/review-tree.ts +14 -2
  442. package/scripts/rules/decision-oracle-stage.ts +18 -0
  443. package/scripts/rules/decision-oracle.ts +10 -7
  444. package/scripts/rules/delivered-rules.ts +9 -1
  445. package/scripts/rules/destructive-command.ts +119 -0
  446. package/scripts/rules/direct-filing.ts +1 -1
  447. package/scripts/rules/early-heartbeat.ts +4 -3
  448. package/scripts/rules/file-body.ts +0 -3
  449. package/scripts/rules/filing-cap.ts +0 -2
  450. package/scripts/rules/gh-api.ts +7 -2
  451. package/scripts/rules/git-argv.ts +18 -7
  452. package/scripts/rules/git-force.ts +0 -2
  453. package/scripts/rules/implementation-cut.ts +0 -1
  454. package/scripts/rules/index-guard.ts +71 -0
  455. package/scripts/rules/issue-citation.ts +50 -25
  456. package/scripts/rules/lane-background.ts +15 -7
  457. package/scripts/rules/lane-park.ts +22 -6
  458. package/scripts/rules/last-prompt.ts +1 -0
  459. package/scripts/rules/oracle-consulted.ts +1 -1
  460. package/scripts/rules/oracle-firing.ts +1 -0
  461. package/scripts/rules/oracle-list-cli.ts +0 -3
  462. package/scripts/rules/permission-guards.ts +14 -0
  463. package/scripts/rules/protected-files.ts +74 -0
  464. package/scripts/rules/reply-language.ts +1 -1
  465. package/scripts/rules/rule-body-guard.ts +0 -3
  466. package/scripts/rules/rule-value-cli.ts +0 -1
  467. package/scripts/rules/shell-body-trigger.ts +0 -1
  468. package/scripts/rules/shell-segments.ts +0 -1
  469. package/scripts/rules/stop-rules.ts +20 -9
  470. package/scripts/rules/tail-commands.ts +1 -1
  471. package/scripts/rules/test-declared-commit.ts +1 -1
  472. package/scripts/rules/third-party-write.ts +0 -1
  473. package/scripts/rules/worktree-guard.ts +26 -9
  474. package/scripts/run/run-carry-args.ts +8 -12
  475. package/scripts/run/run-carry-cli.ts +0 -2
  476. package/scripts/run/run-carry-stash.ts +2 -2
  477. package/scripts/run/run-carry-streak.ts +1 -1
  478. package/scripts/run/run-cut-args.ts +1 -6
  479. package/scripts/run/run-cut-cli.ts +0 -7
  480. package/scripts/run/run-cut.ts +8 -54
  481. package/scripts/run/run-ending-cli.ts +2 -6
  482. package/scripts/run/run-ending.ts +1 -4
  483. package/scripts/run/run-entry-cli.ts +133 -25
  484. package/scripts/run/run-entry-stop.ts +104 -0
  485. package/scripts/run/run-entry.ts +0 -1
  486. package/scripts/run/run-event-cli.ts +0 -2
  487. package/scripts/run/run-event-follow.ts +1 -0
  488. package/scripts/run/run-event-render.ts +1 -1
  489. package/scripts/run/run-event-scope.ts +53 -4
  490. package/scripts/run/run-event-stream-emit.ts +7 -2
  491. package/scripts/run/run-event-stream.ts +0 -3
  492. package/scripts/run/run-event-watch.ts +1 -0
  493. package/scripts/run/run-halfrun-resume.ts +20 -7
  494. package/scripts/run/run-headless.ts +2 -2
  495. package/scripts/run/run-hold-cli.ts +33 -10
  496. package/scripts/run/run-hold.ts +29 -6
  497. package/scripts/run/run-issue-number.ts +1 -1
  498. package/scripts/run/run-liveness-cli.ts +2 -6
  499. package/scripts/run/run-liveness.ts +2 -3
  500. package/scripts/run/run-merge-cli.ts +7 -23
  501. package/scripts/run/run-merge-steps.ts +5 -5
  502. package/scripts/run/run-merge.ts +1 -1
  503. package/scripts/run/run-next-cli.ts +1 -1
  504. package/scripts/run/run-parent-cut-hook.ts +4 -2
  505. package/scripts/run/run-preflight.ts +2 -9
  506. package/scripts/run/run-prep-cli.ts +6 -3
  507. package/scripts/run/run-prep-locate.ts +1 -1
  508. package/scripts/run/run-progress-args.ts +20 -4
  509. package/scripts/run/run-progress-cli.ts +35 -36
  510. package/scripts/run/run-progress-clock.ts +10 -35
  511. package/scripts/run/run-progress-config.ts +0 -4
  512. package/scripts/run/run-progress-read.ts +1 -2
  513. package/scripts/run/run-progress.ts +1 -2
  514. package/scripts/run/run-prrun-resume.ts +117 -0
  515. package/scripts/run/run-report-cli.ts +1 -2
  516. package/scripts/run/run-report.ts +0 -1
  517. package/scripts/run/run-retrospective.ts +1 -1
  518. package/scripts/run/run-review-cli.ts +0 -3
  519. package/scripts/run/run-review-steps.ts +2 -0
  520. package/scripts/run/run-review.ts +0 -2
  521. package/scripts/run/run-ship-cli.ts +29 -19
  522. package/scripts/run/run-ship-detach.ts +1 -0
  523. package/scripts/run/run-ship-next.ts +106 -0
  524. package/scripts/run/run-ship-preflight.ts +1 -1
  525. package/scripts/run/run-ship-probe.ts +4 -1
  526. package/scripts/run/run-ship-return.ts +8 -3
  527. package/scripts/run/run-ship-review-steps.ts +18 -4
  528. package/scripts/run/run-ship-review.ts +11 -0
  529. package/scripts/run/run-ship-scoped.ts +1 -0
  530. package/scripts/run/run-ship-steps.ts +1 -1
  531. package/scripts/run/run-ship.ts +0 -1
  532. package/scripts/run/run-stage-read.ts +62 -0
  533. package/scripts/run/run-stage.ts +160 -0
  534. package/scripts/run/run-status-cli.ts +3 -16
  535. package/scripts/run/run-step-cli.ts +21 -14
  536. package/scripts/run/run-step.ts +1 -1
  537. package/scripts/run/run-stop-notify.ts +1 -3
  538. package/scripts/run/run-stranded-cli.ts +0 -4
  539. package/scripts/run/run-stranded-detect.ts +2 -2
  540. package/scripts/run/run-tail-cli.ts +17 -11
  541. package/scripts/run/run-tail.ts +2 -0
  542. package/scripts/run/run-tidy-lanes.ts +6 -2
  543. package/scripts/run/run-tidy-stashes.ts +12 -12
  544. package/scripts/run/run-wake-cli.ts +4 -13
  545. package/scripts/run/run-wake-loop.ts +2 -2
  546. package/scripts/run/run-wake.ts +2 -4
  547. package/scripts/run/run-watcher-guard-cli.ts +0 -4
  548. package/scripts/run/run-watcher-guard.ts +18 -12
  549. package/scripts/run/run-watcher-hook.ts +1 -1
  550. package/scripts/safe-chain/ci-installer-pin.ts +11 -5
  551. package/scripts/safe-chain/pack-hook.ts +92 -0
  552. package/scripts/safe-chain/project-config.ts +1 -1
  553. package/scripts/security/security-audit-provision-logic.ts +0 -1
  554. package/scripts/security/security-audit-provision.ts +3 -2
  555. package/scripts/security/security-audit.ts +0 -1
  556. package/scripts/security/security-updates-logic.ts +0 -1
  557. package/scripts/sonar/sonar-hotspots-cli.ts +10 -52
  558. package/scripts/sonar/sonar-hotspots.ts +0 -1
  559. package/scripts/sonar/sonar-new-code-cli.ts +150 -0
  560. package/scripts/sonar/sonar-new-code.ts +79 -0
  561. package/scripts/sonar/sonar-project.ts +97 -0
  562. package/scripts/split/split-assess-cli.ts +1 -1
  563. package/scripts/split/split-assess.ts +2 -5
  564. package/scripts/sync/managed-config-scope-cli.ts +1 -1
  565. package/scripts/sync/skill-migration.ts +0 -1
  566. package/scripts/sync/sync-ai-files.ts +4 -0
  567. package/scripts/sync/sync-hook-safety.ts +2 -3
  568. package/scripts/sync/sync.ts +1 -8
  569. package/scripts/sync/template-source-logic.ts +0 -1
  570. package/scripts/sync/workflow-pin-logic.ts +16 -28
  571. package/scripts/test/test-declared-changed.ts +13 -16
  572. package/scripts/test/test-declared-logic.ts +0 -1
  573. package/scripts/test/test-declared.ts +3 -9
  574. package/scripts/test/test-red-commit.ts +2 -2
  575. package/scripts/test/test-red.ts +14 -7
  576. package/scripts/test/test-type-logic.ts +1 -1
  577. package/scripts/test/unit-worker-share.ts +7 -16
  578. package/scripts/time-runtime/time-batch-guard.ts +1 -2
  579. package/scripts/time-runtime/time-bundle-call.ts +0 -1
  580. package/scripts/time-runtime/time-bundles.ts +0 -4
  581. package/scripts/time-runtime/time-density-hook.ts +0 -2
  582. package/scripts/time-runtime/time-followup-stage.ts +1 -1
  583. package/scripts/time-runtime/time-format.ts +0 -73
  584. package/scripts/time-runtime/time-round-trips.ts +0 -4
  585. package/scripts/time-runtime/time-single-check.ts +1 -1
  586. package/scripts/time-runtime/time-spans.ts +1 -1
  587. package/scripts/time-runtime/time-transcript-line.ts +1 -2
  588. package/scripts/ui/ui-routes-cli.ts +0 -5
  589. package/scripts/ui/ui-routes.ts +0 -5
  590. package/scripts/version/effective-upstream.ts +2 -2
  591. package/scripts/version/latest-corepack.ts +7 -9
  592. package/scripts/version/latest-scope-cli.ts +0 -2
  593. package/scripts/version/latest-update.ts +0 -2
  594. package/scripts/version/npm-registry.ts +2 -2
  595. package/scripts/version/publishable-range-check.ts +1 -1
  596. package/scripts/version/release-hold.ts +0 -4
  597. package/scripts/version/running-binary.ts +2 -2
  598. package/scripts/version/version-check-logic.ts +0 -2
  599. package/scripts/version/version-commands.ts +11 -1
  600. package/scripts/version/version-remote.ts +3 -3
  601. package/scripts/version/version-targets.ts +4 -4
  602. package/templates/CLAUDE.basic.md +6 -6
  603. package/templates/sonar-project.properties +28 -1
  604. package/templates/workflows/ci.yml +16 -82
  605. package/templates/workflows/dependabot-auto-merge.yml +6 -3
  606. package/templates/workflows/github-release.yml +79 -0
  607. package/tsconfig.sonar.json +4 -22
  608. package/prompts/collaboration-workflow/cross-repo-epic.md +0 -5
  609. package/prompts/collaboration-workflow/epic-audit.md +0 -5
  610. package/prompts/collaboration-workflow/epic-bundle.md +0 -5
  611. package/scripts/init/plugin-install-hint.ts +0 -47
  612. package/scripts/version/parse-json.ts +0 -13
  613. /package/scripts/{git → followup}/git-followup-stages.ts +0 -0
  614. /package/scripts/{git → gh}/git-gh-api-path.ts +0 -0
  615. /package/scripts/{git → gh}/git-gh-command.ts +0 -0
  616. /package/scripts/{git → gh}/git-gh-issue.ts +0 -0
  617. /package/scripts/{git → gh}/git-gh-pr-snapshot.ts +0 -0
  618. /package/scripts/{git → gh}/git-gh-reachability.ts +0 -0
  619. /package/scripts/{git → gh}/git-gh-repo.ts +0 -0
  620. /package/scripts/{git → gh}/git-gh-rest-state.ts +0 -0
  621. /package/scripts/{git → gh}/git-pr-checks-watch.ts +0 -0
  622. /package/scripts/{git → gh}/git-pr-error.ts +0 -0
  623. /package/scripts/{git → gh}/git-pr-messages.ts +0 -0
  624. /package/scripts/{git → gh}/github-issue-url.ts +0 -0
  625. /package/scripts/git/{stash-orphans.ts → stash/stash-orphans.ts} +0 -0
  626. /package/scripts/{git → issue}/issue-reference.ts +0 -0
  627. /package/scripts/{git → lib}/animation-helpers.ts +0 -0
  628. /package/scripts/{git → lib}/git-animation.ts +0 -0
  629. /package/scripts/{git → notify}/git-notify.ts +0 -0
  630. /package/scripts/{git → notify}/telegram-test-logic.ts +0 -0
@@ -13,9 +13,10 @@ const PLUGIN_ID = 'kit@kit'
13
13
  const MARKETPLACE_PATH = './node_modules/@joshuafolkken/kit'
14
14
  const CLAUDE_SETTINGS_DESTINATION = path.join('.claude', 'settings.json')
15
15
 
16
- // `enabledPlugins` declares the plugin; `extraKnownMarketplaces` says where to find it. The CLI does
17
- // not auto-install from these alone — a consumer runs `claude plugin install kit@kit` once — so the
18
- // declaration is what makes that one command resolve without further arguments.
16
+ // `enabledPlugins` declares the plugin; `extraKnownMarketplaces` says where to find it. Nothing needs
17
+ // installing: in a trusted workspace Claude Code registers the marketplace from this declaration and
18
+ // loads the skills — an interactive session from its first session, a headless one (`claude -p`) from
19
+ // its second (joshuafolkken/kit#2990).
19
20
  const PLUGIN_SETTINGS: Record<string, unknown> = {
20
21
  extraKnownMarketplaces: {
21
22
  [MARKETPLACE_NAME]: { source: { source: 'directory', path: MARKETPLACE_PATH } },
@@ -39,11 +40,9 @@ function apply_plugin_config_for_destination(destination_path: string, content:
39
40
  }
40
41
 
41
42
  const claude_plugin_config = {
42
- MARKETPLACE_NAME,
43
43
  PLUGIN_ID,
44
44
  MARKETPLACE_PATH,
45
45
  CLAUDE_SETTINGS_DESTINATION,
46
- PLUGIN_SETTINGS,
47
46
  inject_plugin_config,
48
47
  apply_plugin_config_for_destination,
49
48
  }
@@ -1,4 +1,3 @@
1
- import { GIT_LOCATION_VARIABLES } from '#scripts/git/git-location-environment'
2
1
  import { claude_plugin_config } from './claude-plugin-config'
3
2
  import { hook_launch } from './hook-launch'
4
3
 
@@ -27,8 +26,11 @@ const MISSING_INSTALL_NOTICE = 'kit hooks inactive: run pnpm install, then rerea
27
26
  const MISSING_INSTALL_GUARD = `if [ ! -f ${CONSUMER_PACKAGE_MANIFEST} ]; then echo '${MISSING_INSTALL_NOTICE}' >&2; exit 0; fi; `
28
27
  const CODEX_ADAPTER_BUNDLE = `node ${CONSUMER_HOOK_BUNDLE_DIR}codex-hook-adapter.js`
29
28
  const CODEX_HOOKS_DESTINATION = '.codex/hooks.json'
30
- const GIT_UNSET_OPTIONS = GIT_LOCATION_VARIABLES.map((name) => `-u ${name}`).join(' ')
31
- const PROJECT_ROOT_PREFIX = String.raw`if project_root=\"$(env ${GIT_UNSET_OPTIONS} git rev-parse --show-toplevel 2>/dev/null)\"; then unset ${GIT_LOCATION_VARIABLES.join(' ')}; else project_root=\"$(git rev-parse --show-toplevel)\" || exit 1; fi; cd \"$project_root\" && `
29
+ // The values below are matched inside raw JSON text, so the root prefix is taken in its escaped form.
30
+ const PROJECT_ROOT_PREFIX = JSON.stringify(hook_launch.PROJECT_ROOT_PREFIX).slice(1, -1)
31
+ // The installed package ships its bundles built, so they cannot be stale against a source the consumer
32
+ // never has: the ready gate kit's own commands pass (joshuafolkken/kit#2984) becomes a presence check.
33
+ const CONSUMER_READY_GATE = `[ -d ${CONSUMER_HOOK_BUNDLE_DIR} ]`
32
34
  // Capture the value of every `"command"` field, escapes and all, so the rewrites below touch command
33
35
  // values alone — never an echo reminder's prose or a `"description"` that merely mentions the string.
34
36
  const COMMAND_FIELD = /("command":\s*")((?:[^"\\]|\\.)*)(")/gu
@@ -49,6 +51,8 @@ function rebase_bundle_directory(value: string): string {
49
51
  // holds no `pnpm josh `), so the whole rewrite is safe to run more than once.
50
52
  function rewrite_command_value(value: string): string {
51
53
  const rewritten = rebase_bundle_directory(value)
54
+ .split(hook_launch.BUNDLE_READY_GATE)
55
+ .join(CONSUMER_READY_GATE)
52
56
  .split(PNPM_JOSH_PREFIX)
53
57
  .join(BUNDLE_INVOCATION)
54
58
  .split(CODEX_ADAPTER_SOURCE)
@@ -60,12 +64,18 @@ function rewrite_command_value(value: string): string {
60
64
  return `${MISSING_INSTALL_GUARD}${rewritten}`
61
65
  }
62
66
 
67
+ // kit's own commands already start from the root (`hook-launch.ts`), and so does an already-rewritten
68
+ // value. The prefix is taken off before the rewrite and put back after it, so the install guard sits
69
+ // behind the `cd` it depends on and a second pass never doubles the prefix.
70
+ function without_root_prefix(value: string): string {
71
+ return value.startsWith(PROJECT_ROOT_PREFIX) ? value.slice(PROJECT_ROOT_PREFIX.length) : value
72
+ }
73
+
63
74
  function rewrite_hook_commands(content: string, is_codex = false): string {
64
75
  return content.replaceAll(COMMAND_FIELD, (_match, open: string, value: string, close: string) => {
65
- const rewritten = rewrite_command_value(value)
76
+ const rewritten = rewrite_command_value(without_root_prefix(value))
66
77
  const should_select_root = is_codex || rewritten.includes(claude_plugin_config.MARKETPLACE_PATH)
67
- const prefix =
68
- should_select_root && !rewritten.startsWith(PROJECT_ROOT_PREFIX) ? PROJECT_ROOT_PREFIX : ''
78
+ const prefix = should_select_root ? PROJECT_ROOT_PREFIX : ''
69
79
 
70
80
  return `${open}${prefix}${rewritten}${close}`
71
81
  })
@@ -89,8 +99,6 @@ function apply_hook_command_rewrite_for_destination(
89
99
 
90
100
  const hook_command_rewrite = {
91
101
  apply_hook_command_rewrite_for_destination,
92
- BUNDLE_INVOCATION,
93
- PNPM_JOSH_PREFIX,
94
102
  rewrite_hook_commands,
95
103
  }
96
104
 
@@ -1,31 +1,57 @@
1
+ import { GIT_LOCATION_VARIABLES } from '#scripts/git/git-location-environment'
2
+
1
3
  // The shell command a Claude Code hook is launched with, so it starts without a `pnpm` wrapper — and,
2
4
  // for a consumer, without the `dist/josh.js` dispatcher re-spawning `tsx` for the hook's `.ts`
3
5
  // (joshuafolkken/kit#2023). Each hook is pre-built to its own `dist/hooks/<name>.js`
4
6
  // (`scripts/build/build-hooks.ts`) and launched directly with `node`.
5
7
  //
6
- // **The fallback is a real branch, not a courtesy.** A fresh clone has no `dist/hooks/` until
7
- // `pnpm build` runs, so the command prefers the bundle and drops to `pnpm josh <command>` (the live
8
- // `tsx` source) when the bundle is absent, rather than passing silently. **An `if`/`else`, never
9
- // `&&`/`||`**: a guard's refusal is a non-zero exit, and a `node … || pnpm josh …` chain would read
10
- // that refusal as a missing bundle and run the hook twice. `[ -f ]` decides on the file alone and
11
- // leaves the chosen branch's exit code untouched.
12
-
13
- // Relative to the working directory a hook runs in — kit's own root, where the built `dist/hooks/`
14
- // sits. The consumer rewrite (`hook-command-rewrite.ts`) rebases this onto the installed package.
8
+ // **The command starts from the project root, never from wherever the session happens to be**
9
+ // (joshuafolkken/kit#2984). Every path after the prefix is relative, so a hook fired from a
10
+ // subdirectory would otherwise miss its bundle. The root is git's, with the location variables a git
11
+ // hook exports cleared first — the same resolution the consumer rewrite (`hook-command-rewrite.ts`)
12
+ // applies, so both sides stay one mechanism for Claude Code and Codex alike.
13
+ //
14
+ // **The bundle runs only once the ready gate passes** (`scripts/hooks/hook-bundle-ready.ts`): it
15
+ // rebuilds `dist/hooks/` when the source beside it has changed, so an edited guard is never shadowed by
16
+ // its old bundle. The gate failing — a checkout that cannot build — drops to the fallback, the live
17
+ // source. **An `if`/`else`, never `&&`/`||`**: a guard's refusal is a non-zero exit, and a
18
+ // `node … || pnpm josh …` chain would read that refusal as a missing bundle and run the hook twice.
19
+
15
20
  const HOOK_DIST_DIR = 'dist/hooks'
21
+ const UNSET_OPTIONS = GIT_LOCATION_VARIABLES.map((name) => `-u ${name}`).join(' ')
22
+ const PROJECT_ROOT_PREFIX = `if project_root="$(env ${UNSET_OPTIONS} git rev-parse --show-toplevel 2>/dev/null)"; then unset ${GIT_LOCATION_VARIABLES.join(' ')}; else project_root="$(git rev-parse --show-toplevel)" || exit 1; fi; cd "$project_root" && `
23
+ // Plain `node` runs the gate's TypeScript directly; the flag keeps Node 22's type-stripping notice off
24
+ // every hook's stderr.
25
+ const BUNDLE_READY_GATE =
26
+ 'node --disable-warning=ExperimentalWarning scripts/hooks/hook-bundle-ready.ts'
16
27
 
17
- // Prefer `primary_path` (run as `node <path>`) when it exists, else run `fallback_command` verbatim.
18
- // Kept generic so a test can exercise the branch selection with stub commands rather than real hooks.
19
- function launch_command(primary_path: string, fallback_command: string): string {
20
- return `if [ -f ${primary_path} ]; then node ${primary_path}; else ${fallback_command}; fi`
28
+ // Run `primary_command` when `gate` exits 0, else `fallback_command` — both verbatim. Kept generic so
29
+ // a test can exercise the branch selection with stub commands rather than real hooks.
30
+ function launch_command(gate: string, primary_command: string, fallback_command: string): string {
31
+ return `if ${gate}; then ${primary_command}; else ${fallback_command}; fi`
32
+ }
33
+
34
+ // `invocation` is the hook's file under `dist/hooks` plus any arguments (e.g. `pretool-guard.js`);
35
+ // `fallback_command` runs the same hook from source.
36
+ function bundle_launch_command(invocation: string, fallback_command: string): string {
37
+ const primary = `node ${HOOK_DIST_DIR}/${invocation}`
38
+
39
+ return `${PROJECT_ROOT_PREFIX}${launch_command(BUNDLE_READY_GATE, primary, fallback_command)}`
21
40
  }
22
41
 
23
42
  // `bundle` is the hook's file under `dist/hooks` (e.g. `pretool-guard.js`); `command` is the josh
24
43
  // subcommand the fallback runs (e.g. `pretool:guard`).
25
44
  function hook_launch_command(bundle: string, command: string): string {
26
- return launch_command(`${HOOK_DIST_DIR}/${bundle}`, `pnpm josh ${command}`)
45
+ return bundle_launch_command(bundle, `pnpm josh ${command}`)
27
46
  }
28
47
 
29
- const hook_launch = { HOOK_DIST_DIR, hook_launch_command, launch_command }
48
+ const hook_launch = {
49
+ BUNDLE_READY_GATE,
50
+ bundle_launch_command,
51
+ HOOK_DIST_DIR,
52
+ hook_launch_command,
53
+ launch_command,
54
+ PROJECT_ROOT_PREFIX,
55
+ }
30
56
 
31
57
  export { hook_launch }
@@ -1,4 +1,5 @@
1
1
  import { json_format } from '#scripts/config-merge/json-format'
2
+ import { json_value } from '#scripts/lib/json-value'
2
3
  import { z } from 'zod'
3
4
  import { init_logic } from './init-logic'
4
5
  import type { ProjectShape } from './project-profile'
@@ -6,10 +7,6 @@ import type { ProjectShape } from './project-profile'
6
7
  const KIT_PACKAGE_NAME = '@joshuafolkken/kit'
7
8
  const record_schema = z.record(z.string(), z.unknown())
8
9
 
9
- function is_record(value: unknown): value is Record<string, unknown> {
10
- return typeof value === 'object' && value !== null && !Array.isArray(value)
11
- }
12
-
13
10
  interface BasicVersions {
14
11
  kit: string
15
12
  prettier: string
@@ -23,7 +20,7 @@ function with_recorded_profile(content: string, profile: ProjectShape['profile']
23
20
  const parsed: unknown = JSON.parse(content)
24
21
  const manifest = record_schema.parse(parsed)
25
22
  const existing = manifest['josh']
26
- const josh = is_record(existing) ? existing : {}
23
+ const josh = json_value.is_record(existing) ? existing : {}
27
24
 
28
25
  manifest['josh'] = { ...josh, profile }
29
26
 
@@ -0,0 +1,54 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
2
+ import path from 'node:path'
3
+ import type { FileAction } from './init-actions'
4
+
5
+ const SAMPLE_INDENT_WIDTH = 4
6
+ const SAMPLE_INDENT = ' '.repeat(SAMPLE_INDENT_WIDTH)
7
+
8
+ function write_new_file(action: FileAction, destination_path: string): void {
9
+ mkdirSync(path.dirname(destination_path), { recursive: true })
10
+ writeFileSync(destination_path, action.create())
11
+ console.info(` ✔ created ${action.dest}`)
12
+ }
13
+
14
+ function show_sample(action: FileAction): void {
15
+ console.info(` ⚠ exists ${action.dest} — add manually:`)
16
+ console.info('')
17
+ console.info(action.create().replaceAll(/^/gmu, () => SAMPLE_INDENT))
18
+ }
19
+
20
+ // A file that already holds the sample needs nothing added, so only one that differs gets it shown —
21
+ // for a create-only file (no merge) as for a merge that only migrates a kit-written line (#3069).
22
+ function report_unchanged(action: FileAction, existing: string): void {
23
+ const is_sample_missing = existing !== action.create()
24
+ const should_show_sample =
25
+ action.merge === undefined || action.should_show_sample_when_unchanged === true
26
+
27
+ if (is_sample_missing && should_show_sample) show_sample(action)
28
+ else console.info(` ✔ unchanged ${action.dest}`)
29
+ }
30
+
31
+ function merge_existing_file(action: FileAction, destination_path: string): void {
32
+ const existing = readFileSync(destination_path, 'utf8')
33
+ const merged = action.merge === undefined ? existing : action.merge(existing)
34
+
35
+ if (merged === existing) {
36
+ report_unchanged(action, existing)
37
+
38
+ return
39
+ }
40
+
41
+ writeFileSync(destination_path, merged)
42
+ console.info(` ✔ updated ${action.dest}`)
43
+ }
44
+
45
+ function execute_file_action(action: FileAction, project_root: string): void {
46
+ const destination_path = path.join(project_root, action.dest)
47
+
48
+ if (existsSync(destination_path)) merge_existing_file(action, destination_path)
49
+ else write_new_file(action, destination_path)
50
+ }
51
+
52
+ const init_file_action = { execute_file_action }
53
+
54
+ export { init_file_action }
@@ -4,6 +4,27 @@ const PREINSTALL_KEY = 'preinstall'
4
4
  const JF_PREFIX = 'jf-'
5
5
  const JOSH_PREFIX = 'josh '
6
6
 
7
+ // The plain values kit wrote before its scripts became josh subcommands (#80). `check` is left out:
8
+ // its value is the one `sv create` writes itself, so it cannot be told apart from the project's own.
9
+ const PRE_JOSH_SCRIPT_VALUES: ReadonlyMap<string, string> = new Map([
10
+ ['lint', 'pnpm lint:prettier && pnpm lint:eslint'],
11
+ ['lint:prettier', 'prettier --check .'],
12
+ ['lint:eslint', 'eslint . --cache --cache-strategy content'],
13
+ ['format', 'pnpm format:prettier && pnpm format:eslint'],
14
+ ['format:prettier', 'prettier --write .'],
15
+ ['format:eslint', 'eslint . --fix --cache --cache-strategy content'],
16
+ ['cspell', 'cspell lint --no-must-find-files --no-progress "**/*.{ts,js,md,yaml,yml,json}"'],
17
+ ['cspell:dot', 'pnpm cspell . --dot'],
18
+ ['test:unit', 'vitest run'],
19
+ ['lefthook:install', 'lefthook install'],
20
+ ['lefthook:uninstall', 'lefthook uninstall'],
21
+ ['lefthook:commit', 'lefthook run pre-commit'],
22
+ ['lefthook:push', 'lefthook run pre-push'],
23
+ ['main:sync', 'git checkout main && git pull'],
24
+ ['main:merge', 'git pull origin main'],
25
+ ['check:ci', 'svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --threshold error'],
26
+ ])
27
+
7
28
  const RETIRED_MANAGED_SCRIPTS = new Set<string>([
8
29
  'git',
9
30
  'git:followup',
@@ -18,30 +39,15 @@ const RETIRED_MANAGED_SCRIPTS = new Set<string>([
18
39
  'version:patch',
19
40
  'version:current',
20
41
  'overrides:check',
21
- 'lint',
22
- 'lint:prettier',
23
- 'lint:eslint',
24
- 'format',
25
- 'format:prettier',
26
- 'format:eslint',
27
- 'cspell',
28
- 'cspell:dot',
29
- 'test:unit',
30
42
  'test:e2e',
31
43
  'test',
32
- 'lefthook:install',
33
- 'lefthook:uninstall',
34
- 'lefthook:commit',
35
- 'lefthook:push',
36
- 'main:sync',
37
- 'main:merge',
38
44
  'latest',
39
45
  'latest:corepack',
40
46
  'latest:update',
41
47
  'check',
42
- 'check:ci',
43
48
  'check:svelte',
44
49
  'check:svelte:ci',
50
+ ...PRE_JOSH_SCRIPT_VALUES.keys(),
45
51
  ])
46
52
 
47
53
  function migrate_jf_value(value: string): string {
@@ -62,9 +68,21 @@ function apply_jf_migrations(scripts: Record<string, string>): Record<string, st
62
68
  )
63
69
  }
64
70
 
71
+ function is_kit_written(key: string, value: string): boolean {
72
+ if (value.startsWith(JOSH_PREFIX) || value.startsWith(JF_PREFIX)) return true
73
+
74
+ return PRE_JOSH_SCRIPT_VALUES.get(key) === value
75
+ }
76
+
77
+ // A retired name alone does not make a script kit's: `sv create` writes its own `check`, which must
78
+ // survive `josh init` (joshuafolkken/kit#3069). Only a value kit itself wrote is retired.
79
+ function is_retired_script(key: string, value: string): boolean {
80
+ return RETIRED_MANAGED_SCRIPTS.has(key) && is_kit_written(key, value)
81
+ }
82
+
65
83
  function remove_retired_scripts(scripts: Record<string, string>): Record<string, string> {
66
84
  return Object.fromEntries(
67
- Object.entries(scripts).filter(([key]) => !RETIRED_MANAGED_SCRIPTS.has(key)),
85
+ Object.entries(scripts).filter(([key, value]) => !is_retired_script(key, value)),
68
86
  )
69
87
  }
70
88
 
@@ -5,7 +5,7 @@ const SECRETLINT_RULE_PRESET = '@secretlint/secretlint-rule-preset-recommend'
5
5
 
6
6
  // secretlint resolves both its CLI and every rule package from the project it runs in, not
7
7
  // transitively through the kit — the same constraint that forces the prettier plugins into
8
- // consumer devDependencies (see PRETTIER_PLUGIN_DEV_DEPS in init-logic.ts). Omitting either
8
+ // consumer devDependencies (as kit peers, see init.ts). Omitting either
9
9
  // entry makes the pre-commit hook fail with "Cannot find module". Versions mirror the kit's
10
10
  // own devDependencies.
11
11
  const SECRETLINT_DEV_DEPS: Record<string, string> = {
@@ -92,6 +92,13 @@ const AI_COPY_FILES: ReadonlyArray<string> = [
92
92
  '.github/workflows/production.yml',
93
93
  '.github/workflows/sonar-qube.yml',
94
94
  '.github/workflows/pr-classification.yml',
95
+ // Called by `ci.yml` and `pr-classification.yml` as `uses: ./.github/actions/setup-pnpm`; without
96
+ // it the consumer's jobs cannot resolve the action and their checks fail (joshuafolkken/kit#3013,
97
+ // joshuafolkken/kit#3095).
98
+ '.github/actions/setup-pnpm/action.yml',
99
+ // The one place the workflows' Node.js version is written, called by every distributed workflow
100
+ // that sets Node.js up (joshuafolkken/kit#3084).
101
+ '.github/actions/setup-node/action.yml',
95
102
  '.github/pull_request_template.md',
96
103
  '.github/release.yml',
97
104
  '.github/dependabot.yml',
@@ -118,6 +125,9 @@ const AI_COPY_FILE_MAPPINGS: ReadonlyArray<FileCopyMapping> = [
118
125
  src: 'templates/workflows/dependabot-auto-merge.yml',
119
126
  dest: '.github/workflows/dependabot-auto-merge.yml',
120
127
  },
128
+ // A template rather than a copy of kit's own file: kit releases from its publish.yml, so the file
129
+ // must not run in kit as well (joshuafolkken/kit#3007).
130
+ { src: 'templates/workflows/github-release.yml', dest: '.github/workflows/github-release.yml' },
121
131
  ]
122
132
 
123
133
  // Empty since joshuafolkken/kit#1879: the five skill directories kit used to copy whole
@@ -213,20 +223,6 @@ const SUGGESTED_SCRIPTS_COMMON: Record<string, string> = {
213
223
  josh: 'josh',
214
224
  }
215
225
 
216
- // prettier resolves its `plugins[]` from the consumer project, not transitively through the kit,
217
- // so every package that uses the kit prettier preset must declare these as devDependencies. The
218
- // preset references all three unconditionally (prettier/index.js → plugins), hence all three are
219
- // added regardless of project — omitting any breaks `prettier`/`josh lint` with a
220
- // "Cannot find package" error. Versions mirror the kit's own devDependencies.
221
- const SORT_IMPORTS_PLUGIN_KEY = '@ianvs/prettier-plugin-sort-imports'
222
- const PRETTIER_SVELTE_PLUGIN_KEY = 'prettier-plugin-svelte'
223
- const PRETTIER_TAILWIND_PLUGIN_KEY = 'prettier-plugin-tailwindcss'
224
- const PRETTIER_PLUGIN_DEV_DEPS: Record<string, string> = {
225
- [SORT_IMPORTS_PLUGIN_KEY]: '^4.7.1',
226
- [PRETTIER_SVELTE_PLUGIN_KEY]: '^4.1.1',
227
- [PRETTIER_TAILWIND_PLUGIN_KEY]: '^0.8.0',
228
- }
229
-
230
226
  // format_json rather than JSON.stringify: it lays arrays out the way prettier does — inline while
231
227
  // they fit within printWidth, one element per line once they do not — so the file kit writes is
232
228
  // `prettier --check`-clean in the consumer whatever the entry count happens to be (#660).
@@ -426,10 +422,6 @@ function strip_managed_postinstall(content: string): string {
426
422
  )
427
423
  }
428
424
 
429
- function merge_prettier_plugin_development_deps(content: string): string {
430
- return init_logic_json_merge.merge_development_dependencies(content, PRETTIER_PLUGIN_DEV_DEPS)
431
- }
432
-
433
425
  const init_logic = {
434
426
  ...init_logic_templates,
435
427
  ...init_logic_workspace,
@@ -447,7 +439,6 @@ const init_logic = {
447
439
  generate_npmrc,
448
440
  merge_npmrc,
449
441
  merge_gitignore,
450
- merge_prettier_plugin_development_deps,
451
442
  get_tsconfig_extends_entry,
452
443
  get_tsconfig_preset_filename,
453
444
  get_lefthook_extends_value,
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env tsx
2
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
2
+ import { existsSync, readFileSync, writeFileSync } from 'node:fs'
3
3
  import path from 'node:path'
4
4
  import { fileURLToPath } from 'node:url'
5
5
  import { resolve_local_bin } from '#scripts/build/local-bin'
@@ -7,6 +7,7 @@ import { doctor_io } from '#scripts/doctor/doctor-io'
7
7
  import { error_text } from '#scripts/lib/error-message'
8
8
  import { package_version_schema, with_package_manager_schema } from '#scripts/lib/schemas'
9
9
  import { auto_merge_setting } from '#scripts/repo/auto-merge-setting'
10
+ import { pack_hook } from '#scripts/safe-chain/pack-hook'
10
11
  import { project_config } from '#scripts/safe-chain/project-config'
11
12
  import { security_updates } from '#scripts/security/security-updates'
12
13
  import { did_refuse_self_run } from '#scripts/self-sync-guard/self-sync-refusal'
@@ -14,83 +15,24 @@ import { sync } from '#scripts/sync/sync'
14
15
  import { package_manager_version } from '#scripts/version/package-manager-version'
15
16
  import { execaSync } from 'execa'
16
17
  import { z } from 'zod'
17
- import { init_actions, PRETTIER_CONFIG_JS, type FileAction } from './init-actions'
18
+ import { init_actions, PRETTIER_CONFIG_JS } from './init-actions'
18
19
  import { init_ai_copy } from './init-ai-copy'
19
20
  import { init_basic } from './init-basic'
20
21
  import { init_bootstrap } from './init-bootstrap'
22
+ import { init_file_action } from './init-file-action'
21
23
  import { init_install } from './init-install'
22
24
  import { init_logic } from './init-logic'
23
25
  import { PACKAGE_DIR, PROJECT_ROOT } from './init-paths'
24
26
  import { kit_setup_state } from './kit-setup-state'
25
- import { plugin_install_hint_module } from './plugin-install-hint'
26
27
  import { project_profile, type ProjectProfile, type ProjectShape } from './project-profile'
27
28
 
28
29
  const PACKAGE_JSON = 'package.json'
29
30
  const KIT_PACKAGE_NAME = '@joshuafolkken/kit'
30
31
  const LEFTHOOK_BIN = 'lefthook'
31
- const SAMPLE_INDENT_WIDTH = 4
32
32
  const ARGUMENT_START_INDEX = 2
33
- const SAMPLE_INDENT = ' '.repeat(SAMPLE_INDENT_WIDTH)
34
33
  const INSTALL_HINT = '→ run `pnpm install` to install what package.json lists'
35
34
  const INIT_USAGE = 'josh init [--profile basic|full] [--no-install]'
36
35
 
37
- function write_new_file(action: FileAction, destination_path: string): void {
38
- mkdirSync(path.dirname(destination_path), { recursive: true })
39
- writeFileSync(destination_path, action.create())
40
- console.info(` ✔ created ${action.dest}`)
41
- }
42
-
43
- function show_sample(action: FileAction): void {
44
- console.info(` ⚠ exists ${action.dest} — add manually:`)
45
- console.info('')
46
- console.info(action.create().replaceAll(/^/gmu, () => SAMPLE_INDENT))
47
- }
48
-
49
- // A file that already holds the sample needs nothing added, so only one that differs gets it shown.
50
- function report_unchanged(action: FileAction, existing: string): void {
51
- const is_sample_missing = existing !== action.create()
52
-
53
- if (is_sample_missing && action.should_show_sample_when_unchanged === true) show_sample(action)
54
- else console.info(` ✔ unchanged ${action.dest}`)
55
- }
56
-
57
- function merge_existing_file(
58
- merge_function: (existing: string) => string,
59
- destination_path: string,
60
- action: FileAction,
61
- ): void {
62
- const existing = readFileSync(destination_path, 'utf8')
63
- const merged = merge_function(existing)
64
-
65
- if (merged === existing) {
66
- report_unchanged(action, existing)
67
-
68
- return
69
- }
70
-
71
- writeFileSync(destination_path, merged)
72
- console.info(` ✔ updated ${action.dest}`)
73
- }
74
-
75
- function execute_file_action(action: FileAction): void {
76
- const destination_path = path.join(PROJECT_ROOT, action.dest)
77
- const is_existing = existsSync(destination_path)
78
-
79
- if (!is_existing) {
80
- write_new_file(action, destination_path)
81
-
82
- return
83
- }
84
-
85
- if (action.merge === undefined) {
86
- show_sample(action)
87
-
88
- return
89
- }
90
-
91
- merge_existing_file(action.merge, destination_path, action)
92
- }
93
-
94
36
  const engine_pin_schema = z.looseObject({ name: z.string(), version: z.string() })
95
37
 
96
38
  const published_development_engines_schema = z.looseObject({
@@ -125,10 +67,10 @@ function get_kit_self_dependency(): Record<string, string> {
125
67
  }
126
68
 
127
69
  // Each config `init` generates runs a CLI or imports types the consumer has to resolve itself:
128
- // `prettier.config.js` → prettier, `cspell.config.yaml` → cspell, `playwright.config.ts` →
129
- // @types/node (with @playwright/test among the peers), `lefthook.yml` → lefthook. Without them the
130
- // first `josh gate` after `pnpm install` fails (joshuafolkken/kit#2710).
131
- const TOOL_DEVELOPMENT_DEPENDENCIES = ['prettier', 'cspell', '@types/node']
70
+ // `cspell.config.yaml` → cspell, `playwright.config.ts` → @types/node, `lefthook.yml` → lefthook.
71
+ // Prettier, its preset plugins and @playwright/test come in as peers. Without them the first
72
+ // `josh gate` after `pnpm install` fails (joshuafolkken/kit#2710).
73
+ const TOOL_DEVELOPMENT_DEPENDENCIES = ['cspell', '@types/node']
132
74
  const LEFTHOOK_DEVELOPMENT_DEPENDENCY = 'lefthook'
133
75
 
134
76
  function tool_dependency_names(has_git: boolean): ReadonlyArray<string> {
@@ -165,9 +107,8 @@ function apply_dependency_merges(content: string, has_git = true): string {
165
107
  ? suggested
166
108
  : Object.fromEntries(Object.entries(suggested).filter(([key]) => key !== 'prepare')),
167
109
  )
168
- const with_prettier = init_logic.merge_prettier_plugin_development_deps(merged)
169
110
  const with_toolchain = init_logic.merge_development_dependencies(
170
- with_prettier,
111
+ merged,
171
112
  get_toolchain_development_dependencies(has_git),
172
113
  )
173
114
  const with_secretlint = init_logic.merge_secretlint_development_deps(with_toolchain)
@@ -263,7 +204,7 @@ function run_config_file_actions(shape: ProjectShape): void {
263
204
  }
264
205
 
265
206
  for (const action of init_actions.build_file_actions(shape)) {
266
- execute_file_action(action)
207
+ init_file_action.execute_file_action(action, PROJECT_ROOT)
267
208
  }
268
209
  }
269
210
 
@@ -295,8 +236,6 @@ function run_ai_file_actions(shape: ProjectShape): void {
295
236
  const name_with_owner = init_ai_copy.run_ai_copies(shape)
296
237
 
297
238
  if (shape.has_github) report_repository_settings(name_with_owner)
298
-
299
- if (shape.profile === 'full') plugin_install_hint_module.report_plugin_install_hint()
300
239
  }
301
240
 
302
241
  function initialize_project(shape: ProjectShape): void {
@@ -308,6 +247,7 @@ function initialize_project(shape: ProjectShape): void {
308
247
  merge_project_package_json(shape)
309
248
 
310
249
  run_ai_file_actions(shape)
250
+ pack_hook.sync_pack_hook(PROJECT_ROOT, PACKAGE_DIR)
311
251
  if (shape.profile === 'full') project_config.sync_project_config(PROJECT_ROOT)
312
252
  }
313
253
 
@@ -1,3 +1,4 @@
1
+ import { PACK_HOOK_FILE } from '#scripts/safe-chain/pack-hook'
1
2
  import { PROJECT_CONFIG_FILE } from '#scripts/safe-chain/project-config'
2
3
  import { managed_config_scope } from '#scripts/sync/managed-config-scope'
3
4
  import { BASIC_PRETTIER_CONFIG } from './init-actions'
@@ -13,6 +14,7 @@ const SETUP_ONLY_PATHS: ReadonlySet<string> = new Set([
13
14
  CLAUDE_MD_FILENAME,
14
15
  BASIC_PRETTIER_CONFIG,
15
16
  PROJECT_CONFIG_FILE,
17
+ PACK_HOOK_FILE,
16
18
  MANIFEST_FILE,
17
19
  LOCKFILE,
18
20
  ])
@@ -1,8 +1,9 @@
1
1
  import { existsSync, readdirSync, readFileSync, type Dirent } from 'node:fs'
2
2
  import path from 'node:path'
3
3
  import { repo_origin } from '#scripts/discovery/repo-origin'
4
+ import { git_spawn_sync } from '#scripts/git/git-spawn-sync'
5
+ import { json_value } from '#scripts/lib/json-value'
4
6
  import { KIT_PACKAGE_NAME } from '#scripts/version/kit-descriptor'
5
- import { execaSync } from 'execa'
6
7
 
7
8
  type ProjectProfile = 'basic' | 'full'
8
9
 
@@ -73,32 +74,26 @@ function read_manifest(root: string): Record<string, unknown> | undefined {
73
74
  if (!existsSync(filename)) return undefined
74
75
  const parsed: unknown = JSON.parse(readFileSync(filename, 'utf8'))
75
76
 
76
- if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
77
- throw new Error('package.json must contain an object')
78
- }
79
-
80
- return parsed as Record<string, unknown>
81
- }
77
+ if (!json_value.is_record(parsed)) throw new Error('package.json must contain an object')
82
78
 
83
- function is_record(value: unknown): value is Record<string, unknown> {
84
- return typeof value === 'object' && value !== null && !Array.isArray(value)
79
+ return parsed
85
80
  }
86
81
 
87
82
  function recorded_profile(manifest: Record<string, unknown>): ProjectProfile | undefined {
88
83
  const { josh } = manifest
89
84
 
90
- return is_record(josh) ? parse_profile(josh['profile']) : undefined
85
+ return json_value.is_record(josh) ? parse_profile(josh['profile']) : undefined
91
86
  }
92
87
 
93
88
  function has_build_script(value: unknown): boolean {
94
- return is_record(value) && ('build' in value || 'dev' in value)
89
+ return json_value.is_record(value) && ('build' in value || 'dev' in value)
95
90
  }
96
91
 
97
92
  // kit itself is not evidence of a Node toolchain: `pnpm add -D @joshuafolkken/kit` before
98
93
  // `josh init` is the documented order, and it must still leave an `index.html` site on the basic
99
94
  // profile (joshuafolkken/kit#2693).
100
95
  function has_project_dependencies(value: unknown): boolean {
101
- if (!is_record(value)) return false
96
+ if (!json_value.is_record(value)) return false
102
97
 
103
98
  return Object.keys(value).some((name) => name !== KIT_PACKAGE_NAME)
104
99
  }
@@ -164,12 +159,9 @@ function scan_files(root: string): { has_web: boolean; has_typescript: boolean }
164
159
  }
165
160
 
166
161
  function has_github_remote(root: string): boolean {
167
- const result = execaSync('git', ['config', '--get', 'remote.origin.url'], {
168
- cwd: root,
169
- reject: false,
170
- })
162
+ const url = git_spawn_sync.origin_url(root)
171
163
 
172
- return result.exitCode === 0 && repo_origin.parse_origin_url(result.stdout) !== undefined
164
+ return url !== undefined && repo_origin.parse_origin_url(url) !== undefined
173
165
  }
174
166
 
175
167
  function inspect_project(root: string, requested?: ProjectProfile): ProjectShape {
@@ -1,4 +1,4 @@
1
- import { git_gh_exec } from '#scripts/git/git-gh-exec'
1
+ import { git_gh_exec } from '#scripts/gh/git-gh-exec'
2
2
  import { execaSync } from 'execa'
3
3
 
4
4
  // The three spawn shapes every `josh start` step uses, shared by `start-steps.ts`, the setup pull
@@ -1,10 +1,10 @@
1
- import { git_gh_api_path } from '#scripts/git/git-gh-api-path'
2
- import { git_gh_exec } from '#scripts/git/git-gh-exec'
3
- import { git_gh_issue_write } from '#scripts/git/git-gh-issue-write'
1
+ import { git_gh_api_path } from '#scripts/gh/git-gh-api-path'
2
+ import { git_gh_exec } from '#scripts/gh/git-gh-exec'
3
+ import { git_gh_issue_write } from '#scripts/gh/git-gh-issue-write'
4
+ import { git_pr } from '#scripts/gh/git-pr'
5
+ import { github_issue_url } from '#scripts/gh/github-issue-url'
4
6
  import { git_issue, type IssueInfo } from '#scripts/git/git-issue'
5
- import { git_pr } from '#scripts/git/git-pr'
6
- import { github_issue_url } from '#scripts/git/github-issue-url'
7
- import { IGNORE_FOR_RELEASE_LABEL } from '#scripts/git/issue-labels'
7
+ import { IGNORE_FOR_RELEASE_LABEL } from '#scripts/issue/issue-labels'
8
8
  import { KIT_PACKAGE_NAME } from '#scripts/version/kit-descriptor'
9
9
  import { kit_written_paths } from './kit-written-paths'
10
10
  import { start_exec } from './start-exec'