@joshuafolkken/kit 1.1387.0 → 1.1435.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 (236) hide show
  1. package/.claude/skills/epic-commands/SKILL.md +1 -1
  2. package/.claude/skills/epic-commands/epic-bundle.md +5 -0
  3. package/.claude/skills/workflow-commands/backlogrun-lanes.md +5 -3
  4. package/.claude/skills/workflow-commands/backlogrun-steps.md +4 -3
  5. package/.claude/skills/workflow-commands/backlogrun.md +1 -0
  6. package/.claude/skills/workflow-commands/chain-rule.md +4 -2
  7. package/.claude/skills/workflow-commands/issue-comments.md +6 -0
  8. package/.claude/skills/workflow-commands/observation-ledger.md +3 -2
  9. package/.claude/skills/workflow-commands/pre-gate-cut.md +5 -3
  10. package/README.md +25 -0
  11. package/dist/hooks/audit-provision.js +2 -2
  12. package/dist/hooks/batch-guard.js +7 -7
  13. package/dist/hooks/{chunk-IYVOLN6A.js → chunk-2G5F2YCD.js} +3 -3
  14. package/dist/hooks/{chunk-2YSW3CXH.js → chunk-3LE6VLSR.js} +17 -6
  15. package/dist/hooks/{chunk-J3KSS7II.js → chunk-4BHUPFKF.js} +1 -1
  16. package/dist/hooks/{chunk-EAQEGME7.js → chunk-5SJSSCJG.js} +1 -1
  17. package/dist/hooks/{chunk-FZ6FUSBM.js → chunk-723HKZO5.js} +1 -1
  18. package/dist/hooks/{chunk-LMWBRJIP.js → chunk-7KMN5QB5.js} +3 -3
  19. package/dist/hooks/{chunk-NEC4AT4Z.js → chunk-DGT54IH5.js} +4 -0
  20. package/dist/hooks/{chunk-STDSEPWU.js → chunk-EMB55BDF.js} +4 -4
  21. package/dist/hooks/{chunk-JBBMAPC4.js → chunk-IX6TTTI6.js} +4 -0
  22. package/dist/hooks/{chunk-GJ7JPIHN.js → chunk-JXQBK323.js} +2674 -187
  23. package/dist/hooks/{chunk-DCY2GWHC.js → chunk-MSYSUSY6.js} +5 -5
  24. package/dist/hooks/{chunk-EBSHN25W.js → chunk-MU4LJFIV.js} +4 -4
  25. package/dist/hooks/{chunk-WNFJLBXI.js → chunk-QL6QTPWN.js} +3 -3
  26. package/dist/hooks/{chunk-SL4GQ2XP.js → chunk-XER6SSIB.js} +91 -18
  27. package/dist/hooks/{chunk-U32VSRNG.js → chunk-YW452ZAX.js} +89 -34
  28. package/dist/hooks/{chunk-GNDJ7NJ7.js → chunk-YZXYOAZ3.js} +202 -55
  29. package/dist/hooks/codex-hook-adapter.js +15 -15
  30. package/dist/hooks/duplicate-read-guard.js +8 -8
  31. package/dist/hooks/format-edited.js +5 -5
  32. package/dist/hooks/inputs.json +288 -229
  33. package/dist/hooks/investigation-guard.js +8 -8
  34. package/dist/hooks/pretool-guard.js +14 -14
  35. package/dist/hooks/session-lang.js +69 -16
  36. package/dist/hooks/stop-guard.js +13 -38
  37. package/dist/josh.js +62 -9
  38. package/package.json +4 -3
  39. package/prompts/review.md +22 -0
  40. package/scripts/agent/claude-agent-argv.ts +13 -1
  41. package/scripts/auth/auth-setup-cli.ts +101 -0
  42. package/scripts/auth/claude-token-output.ts +78 -0
  43. package/scripts/auth/claude-token.ts +68 -0
  44. package/scripts/backlog/backlog-drive-epic.ts +24 -8
  45. package/scripts/backlog/backlog-drive-launch.ts +3 -0
  46. package/scripts/backlog/backlog-drive-named-offer.ts +7 -2
  47. package/scripts/backlog/backlog-drive-named.ts +4 -2
  48. package/scripts/backlog/backlog-drive-unread.ts +56 -0
  49. package/scripts/backlog/backlog-drive.ts +16 -8
  50. package/scripts/backlog/backlog-overlap.ts +22 -5
  51. package/scripts/backlog/backlog-ready.ts +1 -3
  52. package/scripts/backlog/backlogrun-args.ts +13 -2
  53. package/scripts/backlog/backlogrun-cli.ts +91 -19
  54. package/scripts/backlog/backlogrun-launch.ts +24 -0
  55. package/scripts/backlog/backlogrun-replace.ts +166 -0
  56. package/scripts/backlog/backlogrun-stop.ts +178 -0
  57. package/scripts/behavior/behavior-cli.ts +6 -1
  58. package/scripts/doctor/doctor-io.ts +60 -9
  59. package/scripts/doctor/doctor.ts +20 -1
  60. package/scripts/document/document-byte-budget.ts +3 -3
  61. package/scripts/epic/epic-bundle-cli.ts +8 -8
  62. package/scripts/epic/epic-bundle-referenced.ts +2 -5
  63. package/scripts/epic/epic-bundle.ts +39 -4
  64. package/scripts/exports/unused-members-cli.ts +2 -1
  65. package/scripts/followup/followup-checks-event.ts +82 -0
  66. package/scripts/followup/git-followup-finish.ts +16 -2
  67. package/scripts/followup/git-followup-workflow.ts +5 -2
  68. package/scripts/followup/git-pr-followup-checks.ts +18 -4
  69. package/scripts/followup/git-pr-followup-wrapup.ts +5 -0
  70. package/scripts/followup/git-pr-followup.ts +4 -1
  71. package/scripts/fresh-machine/fresh-machine-cli.ts +204 -0
  72. package/scripts/fresh-machine/fresh-machine-docker.ts +65 -0
  73. package/scripts/fresh-machine/fresh-machine-image.ts +62 -0
  74. package/scripts/fresh-machine/fresh-machine-log.ts +61 -0
  75. package/scripts/fresh-machine/fresh-machine-patterns.ts +130 -0
  76. package/scripts/fresh-machine/fresh-machine-run.ts +215 -0
  77. package/scripts/fresh-machine/fresh-machine-script.ts +45 -0
  78. package/scripts/fresh-machine/fresh-machine-spec.ts +57 -0
  79. package/scripts/fresh-machine/specs/kit-test-backlogrun-python.json +34 -0
  80. package/scripts/fresh-machine/specs/kit-test-backlogrun.json +31 -0
  81. package/scripts/gate/gate-report.ts +70 -15
  82. package/scripts/gate/project-checks.ts +13 -2
  83. package/scripts/gate/scoped-green.ts +2 -1
  84. package/scripts/gate/verification-gate.ts +4 -3
  85. package/scripts/gh/gh-author-association.ts +14 -0
  86. package/scripts/gh/git-gh-conditional.ts +66 -0
  87. package/scripts/gh/git-gh-exec.ts +1 -1
  88. package/scripts/gh/git-gh-issue-read.ts +6 -3
  89. package/scripts/gh/git-gh-issue-write.ts +5 -1
  90. package/scripts/gh/git-gh-issue.ts +4 -1
  91. package/scripts/gh/git-pr-checks-eval.ts +13 -0
  92. package/scripts/gh/git-pr-checks-parse.ts +8 -1
  93. package/scripts/gh/git-pr-checks-watch.ts +11 -4
  94. package/scripts/gh/git-pr-checks.ts +36 -2
  95. package/scripts/git/git-command.ts +16 -4
  96. package/scripts/git/git-schemas.ts +1 -0
  97. package/scripts/git/git-spawn-sync.ts +1 -1
  98. package/scripts/hooks/pretool-guard.ts +3 -1
  99. package/scripts/init/hook-command-rewrite.ts +31 -0
  100. package/scripts/init/init-actions.ts +4 -1
  101. package/scripts/init/init-ai-copy.ts +33 -10
  102. package/scripts/init/init-basic.ts +8 -3
  103. package/scripts/init/init-logic-toolchain.ts +76 -0
  104. package/scripts/init/init-logic.ts +2 -0
  105. package/scripts/init/init.ts +5 -23
  106. package/scripts/init/project-profile.ts +36 -7
  107. package/scripts/init/start-exec.ts +27 -1
  108. package/scripts/init/start-plan.ts +15 -0
  109. package/scripts/init/start-steps.ts +46 -0
  110. package/scripts/init/start.ts +1 -0
  111. package/scripts/init/workflow-mark.ts +35 -0
  112. package/scripts/issue/issue-ack-cli.ts +84 -0
  113. package/scripts/issue/issue-labels.ts +40 -8
  114. package/scripts/issue/issue-state-cli.ts +14 -4
  115. package/scripts/issue/issue-watch-diff.ts +152 -0
  116. package/scripts/issue/issue-watch-gate.ts +81 -0
  117. package/scripts/issue/issue-watch-hook.ts +54 -0
  118. package/scripts/issue/issue-watch.ts +240 -0
  119. package/scripts/issue/measure-rerun-cli.ts +3 -4
  120. package/scripts/josh/josh-command-map.ts +4 -0
  121. package/scripts/josh/josh-commands-backlog.ts +2 -2
  122. package/scripts/josh/josh-commands-development.ts +1 -1
  123. package/scripts/josh/josh-commands-issue.ts +7 -0
  124. package/scripts/josh/josh-commands-lane.ts +11 -2
  125. package/scripts/josh/josh-commands-project.ts +24 -0
  126. package/scripts/josh/josh-verdict.ts +33 -4
  127. package/scripts/lane/claude-lane-broker.ts +142 -0
  128. package/scripts/lane/lane-await.ts +6 -2
  129. package/scripts/lane/lane-cache.ts +37 -7
  130. package/scripts/lane/lane-capacity.ts +8 -6
  131. package/scripts/lane/lane-child-invocation.ts +1 -0
  132. package/scripts/lane/lane-cli.ts +15 -1
  133. package/scripts/lane/lane-close.ts +15 -6
  134. package/scripts/lane/lane-dispatch.ts +36 -10
  135. package/scripts/lane/lane-environment.ts +1 -1
  136. package/scripts/lane/lane-launch-cli.ts +13 -4
  137. package/scripts/lane/lane-ledger.ts +21 -3
  138. package/scripts/lane/lane-measure-cli.ts +10 -2
  139. package/scripts/lane/lane-open.ts +9 -1
  140. package/scripts/lane/lane-preserve.ts +49 -0
  141. package/scripts/lane/lane-reap.ts +20 -5
  142. package/scripts/lane/lane-registry.ts +6 -0
  143. package/scripts/lane/lane-restart-cli.ts +51 -0
  144. package/scripts/lane/lane-restart.ts +175 -0
  145. package/scripts/lane/{openai-review-broker.ts → lane-session-broker.ts} +106 -28
  146. package/scripts/lane/lane-spent.ts +195 -0
  147. package/scripts/lane/lane-stage-stats.ts +27 -3
  148. package/scripts/lane/lane-stop-stats.ts +96 -0
  149. package/scripts/lane/openai-lane-supervisor.ts +2 -2
  150. package/scripts/lane/process-tools.ts +31 -0
  151. package/scripts/lib/buffered-process.ts +36 -2
  152. package/scripts/lib/pnpm-reach.ts +27 -0
  153. package/scripts/lib/status-icons.ts +5 -1
  154. package/scripts/lint/lint-parallel.ts +19 -2
  155. package/scripts/observations/observation-ledger-home.ts +1 -0
  156. package/scripts/review/review-attest-cli.ts +21 -6
  157. package/scripts/review/review-brief-cli.ts +2 -2
  158. package/scripts/review/review-comment-round.ts +114 -0
  159. package/scripts/review/review-record-cli.ts +39 -17
  160. package/scripts/rules/implementation-cut.ts +3 -3
  161. package/scripts/rules/pre-gate-cut.ts +1 -1
  162. package/scripts/run/board/run-board-checks.ts +42 -0
  163. package/scripts/run/board/run-board-cli.ts +2 -0
  164. package/scripts/run/board/run-board-every.ts +3 -1
  165. package/scripts/run/board/run-board-fit.ts +16 -5
  166. package/scripts/run/board/run-board-fresh.ts +64 -0
  167. package/scripts/run/board/run-board-header.ts +129 -53
  168. package/scripts/run/board/run-board-labels.ts +47 -4
  169. package/scripts/run/board/run-board-lane-event.ts +66 -0
  170. package/scripts/run/board/run-board-layout.ts +57 -9
  171. package/scripts/run/board/run-board-now.ts +234 -0
  172. package/scripts/run/board/run-board-operation-read.ts +75 -0
  173. package/scripts/run/board/run-board-operation.ts +150 -0
  174. package/scripts/run/board/run-board-phase.ts +26 -1
  175. package/scripts/run/board/run-board-plan.ts +4 -6
  176. package/scripts/run/board/run-board-read.ts +49 -3
  177. package/scripts/run/board/run-board-reason.ts +124 -0
  178. package/scripts/run/board/run-board-render-checks.ts +55 -0
  179. package/scripts/run/board/run-board-render-legend.ts +12 -3
  180. package/scripts/run/board/run-board-render-slot.ts +2 -2
  181. package/scripts/run/board/run-board-render-tail.ts +128 -0
  182. package/scripts/run/board/run-board-render-thanks.ts +50 -0
  183. package/scripts/run/board/run-board-render-title.ts +58 -0
  184. package/scripts/run/board/run-board-render.ts +96 -80
  185. package/scripts/run/board/run-board-row-yield.ts +32 -0
  186. package/scripts/run/board/run-board-setup.ts +61 -13
  187. package/scripts/run/board/run-board-state.ts +10 -0
  188. package/scripts/run/board/run-board-status.ts +66 -7
  189. package/scripts/run/board/run-board-thanks-csv.ts +71 -0
  190. package/scripts/run/board/run-board-thanks-read.ts +112 -0
  191. package/scripts/run/board/run-board-thanks.ts +53 -0
  192. package/scripts/run/board/run-board-tick.ts +50 -21
  193. package/scripts/run/board/run-board-usual.ts +44 -0
  194. package/scripts/run/carry/run-carry-args.ts +9 -1
  195. package/scripts/run/carry/run-carry-cli.ts +2 -45
  196. package/scripts/run/carry/run-carry-end.ts +73 -0
  197. package/scripts/run/carry/run-carry.ts +8 -1
  198. package/scripts/run/entry/run-entry-cli.ts +5 -0
  199. package/scripts/run/event/run-event-checks.ts +54 -0
  200. package/scripts/run/event/run-event-render.ts +2 -0
  201. package/scripts/run/event/run-event-scope.ts +1 -0
  202. package/scripts/run/event/run-event-setup.ts +55 -11
  203. package/scripts/run/event/run-event-stream.ts +27 -11
  204. package/scripts/run/merge/run-merge-cli.ts +7 -4
  205. package/scripts/run/merge/run-merge-ship.ts +61 -0
  206. package/scripts/run/merge/run-merge-steps.ts +7 -14
  207. package/scripts/run/merge/run-merge-token.ts +16 -2
  208. package/scripts/run/run-headless.ts +1 -0
  209. package/scripts/run/run-step.ts +2 -0
  210. package/scripts/run/ship/run-ship-cli.ts +22 -2
  211. package/scripts/run/ship/run-ship-return.ts +31 -13
  212. package/scripts/run/ship/run-ship-review-steps.ts +17 -4
  213. package/scripts/run/ship/run-ship-stage.ts +1 -0
  214. package/scripts/run/wake/run-wake-await.ts +130 -0
  215. package/scripts/run/wake/run-wake-cli.ts +60 -71
  216. package/scripts/run/wake/run-wake-describe.ts +34 -2
  217. package/scripts/run/wake/run-wake-driver.ts +11 -4
  218. package/scripts/run/wake/run-wake-session.ts +20 -3
  219. package/scripts/run/wake/run-wake-stop.ts +37 -0
  220. package/scripts/run/wake/run-wake-supervise.ts +44 -0
  221. package/scripts/sync/claude-settings-merge.ts +144 -0
  222. package/scripts/sync/sync-ai-files.ts +28 -3
  223. package/scripts/sync/sync.ts +15 -0
  224. package/scripts/test/project-test-script.ts +73 -0
  225. package/scripts/test/skip-marker.ts +14 -1
  226. package/scripts/test/test-related.ts +3 -2
  227. package/scripts/test/test-unit-guard.ts +78 -14
  228. package/scripts/time-runtime/time-reported-failure.ts +11 -3
  229. package/scripts/uninstall/distributed-files.ts +92 -0
  230. package/scripts/uninstall/uninstall-plan.ts +119 -0
  231. package/scripts/uninstall/uninstall-report.ts +61 -0
  232. package/scripts/uninstall/uninstall.ts +206 -0
  233. package/templates/AGENTS.basic.md +4 -0
  234. package/templates/GEMINI.basic.md +6 -0
  235. package/dist/hooks/chunk-6V5OPIUU.js +0 -13
  236. package/scripts/run/board/run-board-track.ts +0 -22
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  duplicate_read_outcome
3
- } from "./chunk-DCY2GWHC.js";
3
+ } from "./chunk-MSYSUSY6.js";
4
4
  import {
5
5
  ALREADY_DONE_LABEL,
6
6
  CONTEXT_CUT_THRESHOLD,
@@ -9,10 +9,14 @@ import {
9
9
  NEEDS_HUMAN_REVIEW_LABEL,
10
10
  bash_triggers,
11
11
  filing_cap,
12
+ git_gh_api_path,
12
13
  git_gh_command,
14
+ git_gh_exec,
13
15
  git_gh_issue_read,
14
16
  git_gh_pr_read,
15
17
  has_any_label,
18
+ has_stdout_field,
19
+ issue_watch_diff,
16
20
  lane_background,
17
21
  lane_park,
18
22
  parse_json_object_or_undefined,
@@ -25,11 +29,15 @@ import {
25
29
  session_cite,
26
30
  shell_segments,
27
31
  tail_commands
28
- } from "./chunk-GNDJ7NJ7.js";
32
+ } from "./chunk-YZXYOAZ3.js";
29
33
  import {
30
34
  ancestor_directories,
31
- find_local_bin_upwards
32
- } from "./chunk-JBBMAPC4.js";
35
+ find_local_bin_upwards,
36
+ json_object_schema,
37
+ string_array_schema,
38
+ string_record_schema,
39
+ vscode_settings_schema
40
+ } from "./chunk-IX6TTTI6.js";
33
41
  import {
34
42
  agent_role_profile,
35
43
  agent_session_role,
@@ -40,26 +48,27 @@ import {
40
48
  run_event_scope,
41
49
  run_event_stream,
42
50
  run_event_stream_emit,
43
- run_headless
44
- } from "./chunk-U32VSRNG.js";
51
+ run_headless,
52
+ session_language
53
+ } from "./chunk-YW452ZAX.js";
45
54
  import {
46
55
  error_text
47
56
  } from "./chunk-CDY4NFQG.js";
48
57
  import {
49
58
  batch_outcome
50
- } from "./chunk-LMWBRJIP.js";
59
+ } from "./chunk-7KMN5QB5.js";
51
60
  import {
52
61
  investigation_refusal
53
- } from "./chunk-IYVOLN6A.js";
62
+ } from "./chunk-2G5F2YCD.js";
54
63
  import {
55
64
  investigation_reads
56
- } from "./chunk-WNFJLBXI.js";
65
+ } from "./chunk-QL6QTPWN.js";
57
66
  import {
58
67
  lane_guard_policy
59
- } from "./chunk-EAQEGME7.js";
68
+ } from "./chunk-5SJSSCJG.js";
60
69
  import {
61
70
  hook_decision
62
- } from "./chunk-EBSHN25W.js";
71
+ } from "./chunk-MU4LJFIV.js";
63
72
  import {
64
73
  cost_attribute,
65
74
  cost_blocks,
@@ -67,11 +76,12 @@ import {
67
76
  time_batch_guard,
68
77
  time_density_hook,
69
78
  time_shell
70
- } from "./chunk-SL4GQ2XP.js";
79
+ } from "./chunk-XER6SSIB.js";
71
80
  import {
72
81
  lane_child_marker
73
- } from "./chunk-J3KSS7II.js";
82
+ } from "./chunk-4BHUPFKF.js";
74
83
  import {
84
+ GIT_LOCATION_VARIABLES,
75
85
  PORCELAIN_FLAG,
76
86
  cli_flags,
77
87
  cost_transcript,
@@ -84,13 +94,424 @@ import {
84
94
  lane_paths,
85
95
  own_session,
86
96
  run_carry
87
- } from "./chunk-2YSW3CXH.js";
97
+ } from "./chunk-3LE6VLSR.js";
88
98
  import {
89
99
  PLATFORM_TEMP_ROOT,
90
100
  PROBE_TIMEOUT_MS,
101
+ PROJECT_ROOT,
102
+ package_path,
91
103
  platform_temporary,
92
104
  stamp_file
93
- } from "./chunk-NEC4AT4Z.js";
105
+ } from "./chunk-DGT54IH5.js";
106
+
107
+ // scripts/gh/git-gh-conditional.ts
108
+ var NOT_MODIFIED_STATUS = 304;
109
+ var OK_STATUS = 200;
110
+ var INCLUDE_FLAG = "--include";
111
+ var HEADER_FLAG = "-H";
112
+ var IF_NONE_MATCH = "If-None-Match: ";
113
+ var HEADER_BODY_SEPARATOR = /\r?\n\r?\n/u;
114
+ var ETAG_HEADER = /^etag: *(?<etag>[^\r\n]+)/imu;
115
+ var UNCHANGED = { kind: "unchanged" };
116
+ var UNREADABLE = { kind: "unreadable" };
117
+ function to_args(path15, etag) {
118
+ const header = etag === void 0 ? [] : [HEADER_FLAG, `${IF_NONE_MATCH}${etag}`];
119
+ return ["api", INCLUDE_FLAG, ...header, path15];
120
+ }
121
+ function to_changed(output) {
122
+ const [headers = "", ...rest] = output.split(HEADER_BODY_SEPARATOR);
123
+ const etag = ETAG_HEADER.exec(headers)?.groups?.["etag"];
124
+ return { kind: "changed", etag, body: rest.join("\n\n") };
125
+ }
126
+ function to_read(output) {
127
+ return git_gh_exec.parse_status_line(output) === OK_STATUS ? to_changed(output) : UNREADABLE;
128
+ }
129
+ function failure_status(error) {
130
+ const cause = error instanceof Error ? error.cause : void 0;
131
+ return has_stdout_field(cause) ? git_gh_exec.parse_status_line(cause.stdout) : void 0;
132
+ }
133
+ async function read_conditional(path15, etag, timeout_ms) {
134
+ try {
135
+ return to_read(await git_gh_exec.exec_gh_command(to_args(path15, etag), timeout_ms));
136
+ } catch (error) {
137
+ return failure_status(error) === NOT_MODIFIED_STATUS ? UNCHANGED : UNREADABLE;
138
+ }
139
+ }
140
+ var git_gh_conditional = { read_conditional, to_args };
141
+
142
+ // scripts/issue/issue-watch.ts
143
+ import { z } from "zod";
144
+ var RECORD_PREFIX = "josh-issue-watch-";
145
+ var CLOSED_STATE = "closed";
146
+ var record_schema = z.object({
147
+ issue: z.string(),
148
+ body: z.string(),
149
+ last_comment_id: z.number(),
150
+ acknowledged_at: z.string(),
151
+ checked_at: z.string(),
152
+ etag: z.string().optional(),
153
+ pending: z.string().optional(),
154
+ shown: z.string().optional()
155
+ });
156
+ var issue_schema = z.looseObject({ body: z.string().nullish(), state: z.string() });
157
+ var UNREADABLE2 = { kind: "unreadable" };
158
+ function record_path(root = PROJECT_ROOT) {
159
+ return stamp_file.stamp_path(RECORD_PREFIX, root);
160
+ }
161
+ function read_record(root) {
162
+ const raw = stamp_file.read_stamp_text(record_path(root));
163
+ return raw === void 0 ? void 0 : json_value.parse_with(raw, record_schema);
164
+ }
165
+ function write_record(record, root) {
166
+ stamp_file.replace_stamp(record_path(root), record);
167
+ return record;
168
+ }
169
+ function clear(root) {
170
+ stamp_file.remove_stamp(record_path(root));
171
+ }
172
+ async function read_snapshot(request2, body, etag) {
173
+ const comments = issue_watch_diff.parse_comments(
174
+ await git_gh_issue_read.issue_list_comments(request2.issue, request2.timeout_ms)
175
+ );
176
+ return comments === void 0 ? UNREADABLE2 : { kind: "read", snapshot: { body, comments }, etag };
177
+ }
178
+ async function fetch_issue(request2) {
179
+ const read2 = await git_gh_conditional.read_conditional(
180
+ git_gh_api_path.issue_api_path(request2.issue),
181
+ request2.etag,
182
+ request2.timeout_ms
183
+ );
184
+ if (read2.kind !== "changed") return read2;
185
+ const fields = json_value.parse_with(read2.body, issue_schema);
186
+ if (fields === void 0) return UNREADABLE2;
187
+ if (fields.state === CLOSED_STATE) return { kind: "closed" };
188
+ return await read_snapshot(request2, fields.body ?? "", read2.etag);
189
+ }
190
+ function fresh_record(issue, fetched, now, acknowledged_at = now.toISOString()) {
191
+ const baseline = issue_watch_diff.baseline_of(fetched.snapshot);
192
+ const checked_at = now.toISOString();
193
+ return { issue, ...baseline, acknowledged_at, checked_at, etag: fetched.etag };
194
+ }
195
+ async function record_baseline(issue, root, now = /* @__PURE__ */ new Date()) {
196
+ const fetched = await fetch_issue({ issue });
197
+ if (fetched.kind !== "read") return false;
198
+ write_record(fresh_record(issue, fetched, now), root);
199
+ return true;
200
+ }
201
+ async function record_baseline_here(issue) {
202
+ return await record_baseline(issue, await git_command.repository_root());
203
+ }
204
+ async function clear_here() {
205
+ clear(await git_command.repository_root());
206
+ }
207
+ function with_fetched(record, fetched, checked_at) {
208
+ if (fetched.kind !== "read") return { ...record, checked_at };
209
+ const pending = issue_watch_diff.unread_diff(record, fetched.snapshot);
210
+ return { ...record, checked_at, etag: fetched.etag, pending };
211
+ }
212
+ function is_due(record, options, now) {
213
+ return now.getTime() - Date.parse(record.checked_at) >= options.interval_ms;
214
+ }
215
+ async function refresh(record, options, now, root) {
216
+ const fetched = await fetch_issue({
217
+ issue: record.issue,
218
+ etag: record.etag,
219
+ timeout_ms: options.timeout_ms
220
+ });
221
+ if (fetched.kind === "closed") {
222
+ clear(root);
223
+ return void 0;
224
+ }
225
+ return write_record(with_fetched(record, fetched, now.toISOString()), root);
226
+ }
227
+ async function poll(options, root) {
228
+ const record = read_record(root);
229
+ const now = options.now ?? /* @__PURE__ */ new Date();
230
+ if (record === void 0 || !is_due(record, options, now)) return record;
231
+ return await refresh(record, options, now, root);
232
+ }
233
+ function mark_shown(record, root) {
234
+ return write_record({ ...record, shown: record.pending }, root);
235
+ }
236
+ async function acknowledge(root, now = /* @__PURE__ */ new Date()) {
237
+ const record = read_record(root);
238
+ if (record === void 0) return void 0;
239
+ const fetched = await fetch_issue({ issue: record.issue });
240
+ if (fetched.kind !== "read") return void 0;
241
+ const diff = issue_watch_diff.unread_diff(record, fetched.snapshot);
242
+ const acknowledged_at = diff === void 0 ? record.acknowledged_at : now.toISOString();
243
+ write_record(fresh_record(record.issue, fetched, now, acknowledged_at), root);
244
+ return { issue: record.issue, diff };
245
+ }
246
+ var issue_watch = {
247
+ acknowledge,
248
+ clear,
249
+ clear_here,
250
+ mark_shown,
251
+ poll,
252
+ read_record,
253
+ record_baseline,
254
+ record_baseline_here,
255
+ record_path
256
+ };
257
+
258
+ // scripts/review/review-attest.ts
259
+ import { randomBytes } from "node:crypto";
260
+ import { lstatSync } from "node:fs";
261
+
262
+ // scripts/review/review-checkout.ts
263
+ async function read_checkout() {
264
+ const [root, branch, head] = await Promise.all([
265
+ git_command.repository_root(),
266
+ git_command.branch(),
267
+ git_command.head_commit()
268
+ ]);
269
+ return { root, branch, head };
270
+ }
271
+ function is_same_checkout(expected, actual) {
272
+ return expected.root === actual.root && expected.branch === actual.branch && expected.head === actual.head;
273
+ }
274
+ function describe_checkout(checkout) {
275
+ return `${checkout.root} (branch ${checkout.branch}, HEAD ${checkout.head})`;
276
+ }
277
+ var review_checkout = { describe_checkout, is_same_checkout, read_checkout };
278
+
279
+ // scripts/review/review-attest.ts
280
+ var POINTER_PREFIX = "josh-review-target-";
281
+ var EXPECT_PREFIX = "josh-review-expect-";
282
+ var ATTEST_PREFIX = "josh-review-attest-";
283
+ var NONCE_BYTES = 8;
284
+ var HOURS_BEFORE_STALE = 8;
285
+ var MILLISECONDS_PER_HOUR = 36e5;
286
+ var STALE_AFTER_MS = HOURS_BEFORE_STALE * MILLISECONDS_PER_HOUR;
287
+ function pointer_path(root = PROJECT_ROOT) {
288
+ return stamp_file.stamp_path(POINTER_PREFIX, root);
289
+ }
290
+ function expect_path(nonce) {
291
+ return stamp_file.stamp_path(EXPECT_PREFIX, nonce);
292
+ }
293
+ function attest_path(nonce) {
294
+ return stamp_file.stamp_path(ATTEST_PREFIX, nonce);
295
+ }
296
+ function read_json(source) {
297
+ const raw = stamp_file.read_stamp_text(source);
298
+ return raw === void 0 ? void 0 : json_value.parse_or_undefined(raw);
299
+ }
300
+ function string_field(value, key) {
301
+ const field = value[key];
302
+ return typeof field === "string" ? field : void 0;
303
+ }
304
+ function to_checkout(value) {
305
+ if (!json_value.is_record(value)) return void 0;
306
+ const root = string_field(value, "root");
307
+ const branch = string_field(value, "branch");
308
+ const head = string_field(value, "head");
309
+ if (root === void 0 || branch === void 0 || head === void 0) return void 0;
310
+ return { root, branch, head };
311
+ }
312
+ function to_pointer(value) {
313
+ if (!json_value.is_record(value)) return void 0;
314
+ const nonce = string_field(value, "nonce");
315
+ const taken_at = string_field(value, "taken_at");
316
+ if (nonce !== void 0 && taken_at !== void 0) return { nonce, taken_at };
317
+ return void 0;
318
+ }
319
+ function read_pointer(root) {
320
+ return to_pointer(read_json(pointer_path(root)));
321
+ }
322
+ function read_expectation(nonce) {
323
+ return to_checkout(read_json(expect_path(nonce)));
324
+ }
325
+ function read_attestation(nonce) {
326
+ return to_checkout(read_json(attest_path(nonce)));
327
+ }
328
+ function drop_records(pointer) {
329
+ if (pointer === void 0) return;
330
+ stamp_file.remove_stamp(expect_path(pointer.nonce));
331
+ stamp_file.remove_stamp(attest_path(pointer.nonce));
332
+ }
333
+ function is_stale(taken_at, now) {
334
+ const taken = Date.parse(taken_at);
335
+ return Number.isNaN(taken) || now - taken > STALE_AFTER_MS;
336
+ }
337
+ function record_target(checkout, root) {
338
+ const nonce = randomBytes(NONCE_BYTES).toString("hex");
339
+ const taken_at = (/* @__PURE__ */ new Date()).toISOString();
340
+ drop_records(read_pointer(root));
341
+ stamp_file.write_stamp(expect_path(nonce), { ...checkout, taken_at });
342
+ stamp_file.write_stamp(pointer_path(root), { nonce, taken_at });
343
+ return nonce;
344
+ }
345
+ function attest(nonce, actual) {
346
+ const expected = read_expectation(nonce);
347
+ if (expected === void 0) return { status: "missing", nonce, actual };
348
+ stamp_file.write_stamp(attest_path(nonce), { ...actual, taken_at: (/* @__PURE__ */ new Date()).toISOString() });
349
+ if (review_checkout.is_same_checkout(expected, actual)) {
350
+ return { status: "ok", nonce, expected, actual };
351
+ }
352
+ return { status: "mismatch", nonce, expected, actual };
353
+ }
354
+ function not_required() {
355
+ return { status: "not-required" };
356
+ }
357
+ function verdict_for(nonce) {
358
+ const expected = read_expectation(nonce);
359
+ if (expected === void 0) return { status: "missing", nonce };
360
+ const actual = read_attestation(nonce);
361
+ if (actual === void 0) return { status: "missing", nonce, expected };
362
+ if (review_checkout.is_same_checkout(expected, actual)) {
363
+ return { status: "ok", nonce, expected, actual };
364
+ }
365
+ return { status: "mismatch", nonce, expected, actual };
366
+ }
367
+ function check(now = Date.now(), root) {
368
+ const pointer = read_pointer(root);
369
+ if (pointer === void 0) return not_required();
370
+ const verdict = verdict_for(pointer.nonce);
371
+ if (verdict.status === "missing" && is_stale(pointer.taken_at, now)) return not_required();
372
+ return verdict;
373
+ }
374
+ function is_written_since(source, taken_at) {
375
+ try {
376
+ const stats = lstatSync(source);
377
+ return stats.isFile() && stats.mtimeMs >= Date.parse(taken_at);
378
+ } catch {
379
+ return false;
380
+ }
381
+ }
382
+ function is_reviewed_on(checkout, findings_path, root) {
383
+ const pointer = read_pointer(root);
384
+ if (pointer === void 0) return false;
385
+ const verdict = verdict_for(pointer.nonce);
386
+ if (verdict.status !== "ok" || verdict.expected?.branch !== checkout.branch) return false;
387
+ return is_written_since(findings_path, pointer.taken_at);
388
+ }
389
+ function is_briefed_since(written_at, root) {
390
+ const pointer = read_pointer(root);
391
+ return pointer !== void 0 && written_at >= pointer.taken_at;
392
+ }
393
+ async function check_here(now = Date.now()) {
394
+ return check(now, await git_command.repository_root());
395
+ }
396
+ function clear2(root) {
397
+ const pointer = read_pointer(root);
398
+ stamp_file.remove_stamp(pointer_path(root));
399
+ drop_records(pointer);
400
+ }
401
+ async function clear_here2() {
402
+ clear2(await git_command.repository_root());
403
+ }
404
+ var MISMATCH_VERDICT = "REVIEW TARGET MISMATCH";
405
+ function describe_side(label, checkout) {
406
+ if (checkout === void 0) return `${label}: unknown`;
407
+ return `${label}: ${review_checkout.describe_checkout(checkout)}`;
408
+ }
409
+ var MISSING_REASON = "The review left no attestation, so there is no evidence it read this checkout at all. A review that read the wrong tree finds nothing wrong and reports no findings, which is indistinguishable from a clean review \u2014 so an absent attestation is treated as no review (joshuafolkken/kit#1522).";
410
+ var MISMATCH_REASON = `${MISMATCH_VERDICT}: the review attested a different checkout from the one it was briefed on. Its findings \u2014 including "no findings" \u2014 describe another tree.`;
411
+ var REMEDY = "Re-run `/code-review` with the brief `pnpm josh review:brief` prints, against the checkout named above, and let it run `pnpm josh review:attest <nonce>` from there before it reports.";
412
+ function refusal_message(verdict) {
413
+ const reason = verdict.status === "mismatch" ? MISMATCH_REASON : MISSING_REASON;
414
+ return [
415
+ reason,
416
+ describe_side("Briefed on", verdict.expected),
417
+ describe_side("Reviewed", verdict.actual),
418
+ REMEDY
419
+ ].join("\n");
420
+ }
421
+ var review_attest = {
422
+ attest,
423
+ attest_path,
424
+ check,
425
+ check_here,
426
+ clear: clear2,
427
+ clear_here: clear_here2,
428
+ expect_path,
429
+ is_briefed_since,
430
+ is_reviewed_on,
431
+ MISMATCH_VERDICT,
432
+ MISSING_REASON,
433
+ pointer_path,
434
+ read_attestation,
435
+ read_expectation,
436
+ read_pointer,
437
+ record_target,
438
+ refusal_message,
439
+ STALE_AFTER_MS
440
+ };
441
+
442
+ // scripts/issue/issue-watch-gate.ts
443
+ var EVERY_CALL_MS = 0;
444
+ function ack_command(issue) {
445
+ return `pnpm josh issue:ack ${issue}`;
446
+ }
447
+ function unread_message(record) {
448
+ return [
449
+ `A person updated issue ${session_cite.issue(record.issue)} after this run read it, and the run has not taken the update in:`,
450
+ record.pending ?? "",
451
+ `Read it, compare it with the acceptance criteria, fix what it changes, then run \`${ack_command(record.issue)}\` to record that it was read.`
452
+ ].join("\n\n");
453
+ }
454
+ function review_message(record, briefed_at) {
455
+ return [
456
+ `Issue ${session_cite.issue(record.issue)} was updated after the review was briefed (taken in at ${record.acknowledged_at}, briefed at ${briefed_at}), so the review read the earlier specification.`,
457
+ "Re-run `/code-review` with a fresh `pnpm josh review:brief`, so the review reads the change against the updated issue."
458
+ ].join("\n");
459
+ }
460
+ async function polled(root) {
461
+ return await issue_watch.poll({ interval_ms: EVERY_CALL_MS }, root);
462
+ }
463
+ async function unread_refusal(root) {
464
+ const record = await polled(root);
465
+ return record?.pending === void 0 ? void 0 : unread_message(record);
466
+ }
467
+ async function review_refusal(root) {
468
+ const record = await polled(root);
469
+ if (record === void 0) return void 0;
470
+ if (record.pending !== void 0) return unread_message(record);
471
+ const pointer = review_attest.read_pointer(root);
472
+ if (pointer === void 0 || record.acknowledged_at <= pointer.taken_at) return void 0;
473
+ return review_message(record, pointer.taken_at);
474
+ }
475
+ async function review_refusal_here() {
476
+ return await review_refusal(await git_command.repository_root());
477
+ }
478
+ async function assert_read_here() {
479
+ const refusal = await unread_refusal(await git_command.repository_root());
480
+ if (refusal !== void 0) throw new Error(refusal);
481
+ }
482
+ var issue_watch_gate = {
483
+ assert_read_here,
484
+ review_refusal,
485
+ review_refusal_here,
486
+ unread_message,
487
+ unread_refusal
488
+ };
489
+
490
+ // scripts/issue/issue-watch-hook.ts
491
+ var POLL_INTERVAL_MS = 18e4;
492
+ var POLL_TIMEOUT_MS = 5e3;
493
+ function is_new_to_run(record) {
494
+ return record?.pending !== void 0 && record.pending !== record.shown;
495
+ }
496
+ async function new_update_reason(now) {
497
+ const record = await issue_watch.poll({
498
+ interval_ms: POLL_INTERVAL_MS,
499
+ timeout_ms: POLL_TIMEOUT_MS,
500
+ now
501
+ });
502
+ if (!is_new_to_run(record)) return void 0;
503
+ issue_watch.mark_shown(record);
504
+ return issue_watch_gate.unread_message(record);
505
+ }
506
+ async function watch_reason(now = /* @__PURE__ */ new Date()) {
507
+ try {
508
+ return await new_update_reason(now);
509
+ } catch (error) {
510
+ error_text.trace_swallowed("issue_watch_hook.watch_reason", error);
511
+ return void 0;
512
+ }
513
+ }
514
+ var issue_watch_hook = { POLL_INTERVAL_MS, watch_reason };
94
515
 
95
516
  // scripts/run/event/run-event-plan.ts
96
517
  var KIND = run_event_stream.EVENT_KIND.PLAN;
@@ -224,7 +645,7 @@ function format_line(observations, timing) {
224
645
  next: format_next_report(timing.now_ms, timing.interval_ms)
225
646
  });
226
647
  }
227
- function is_due(last_report_ms, now_ms, interval_ms) {
648
+ function is_due2(last_report_ms, now_ms, interval_ms) {
228
649
  return now_ms - last_report_ms >= interval_ms;
229
650
  }
230
651
  function minutes_from(raw) {
@@ -255,14 +676,14 @@ var run_progress = {
255
676
  format_next_report,
256
677
  format_report,
257
678
  is_disabled,
258
- is_due,
679
+ is_due: is_due2,
259
680
  minutes_from,
260
681
  next_state,
261
682
  observation_key
262
683
  };
263
684
 
264
685
  // scripts/run/progress/run-progress-clock.ts
265
- import { z } from "zod";
686
+ import { z as z2 } from "zod";
266
687
  var PROGRESS_PREFIX = "josh-run-progress-";
267
688
  var LIFE_PREFIX = "josh-run-progress-life-";
268
689
  var LOG_SUFFIX = ".log";
@@ -271,7 +692,7 @@ var MS_PER_MINUTE2 = 6e4;
271
692
  var LOG_STALE_MINUTES = 90;
272
693
  var LOG_STALE_MS = LOG_STALE_MINUTES * MS_PER_MINUTE2;
273
694
  var BLOCK_SEPARATOR = "\n\n";
274
- var report_stamp_schema = z.object({ reported_at: z.string(), line: z.string().optional() });
695
+ var report_stamp_schema = z2.object({ reported_at: z2.string(), line: z2.string().optional() });
275
696
  function parse_stamp(raw) {
276
697
  const parsed = report_stamp_schema.safeParse(JSON.parse(raw));
277
698
  if (!parsed.success) return void 0;
@@ -326,7 +747,7 @@ function stamp_target_of(git_directory) {
326
747
  function life_target_of(git_directory) {
327
748
  return stamp_file.stamp_path(LIFE_PREFIX, git_directory);
328
749
  }
329
- var life_schema = z.object({ alive: z.literal(true), pinged_at: z.string().optional() });
750
+ var life_schema = z2.object({ alive: z2.literal(true), pinged_at: z2.string().optional() });
330
751
  function begin_life(target) {
331
752
  stamp_file.write_stamp(target, { alive: true, pinged_at: (/* @__PURE__ */ new Date()).toISOString() });
332
753
  }
@@ -386,10 +807,10 @@ var run_progress_clock = {
386
807
  // scripts/run/progress/run-progress-config.ts
387
808
  import { readFileSync } from "node:fs";
388
809
  import path from "node:path";
389
- import { z as z2 } from "zod";
810
+ import { z as z3 } from "zod";
390
811
  var PACKAGE_FILE = "package.json";
391
- var package_schema = z2.object({
392
- josh: z2.object({ progress_interval_minutes: z2.number().positive() }).optional()
812
+ var package_schema = z3.object({
813
+ josh: z3.object({ progress_interval_minutes: z3.number().positive() }).optional()
393
814
  });
394
815
  function read_declared_minutes(directory) {
395
816
  try {
@@ -707,18 +1128,18 @@ import { fileURLToPath } from "node:url";
707
1128
  // scripts/cost-runtime/codex-usage.ts
708
1129
  import { globSync, readFileSync as readFileSync2 } from "node:fs";
709
1130
  import path2 from "node:path";
710
- import { z as z3 } from "zod";
1131
+ import { z as z4 } from "zod";
711
1132
  var THREAD_ID_PATTERN = /^[A-Za-z0-9-]+$/u;
712
- var SESSION_META_SCHEMA = z3.looseObject({
713
- type: z3.literal("session_meta"),
714
- payload: z3.looseObject({ id: z3.string(), cwd: z3.string() })
1133
+ var SESSION_META_SCHEMA = z4.looseObject({
1134
+ type: z4.literal("session_meta"),
1135
+ payload: z4.looseObject({ id: z4.string(), cwd: z4.string() })
715
1136
  });
716
- var TOTAL_USAGE_SCHEMA = z3.looseObject({ input_tokens: z3.number().nonnegative() });
717
- var TOKEN_COUNT_SCHEMA = z3.looseObject({
718
- type: z3.literal("event_msg"),
719
- payload: z3.looseObject({
720
- type: z3.literal("token_count"),
721
- info: z3.looseObject({
1137
+ var TOTAL_USAGE_SCHEMA = z4.looseObject({ input_tokens: z4.number().nonnegative() });
1138
+ var TOKEN_COUNT_SCHEMA = z4.looseObject({
1139
+ type: z4.literal("event_msg"),
1140
+ payload: z4.looseObject({
1141
+ type: z4.literal("token_count"),
1142
+ info: z4.looseObject({
722
1143
  total_token_usage: TOTAL_USAGE_SCHEMA,
723
1144
  last_token_usage: TOTAL_USAGE_SCHEMA
724
1145
  })
@@ -948,8 +1369,8 @@ function selected_threshold(values) {
948
1369
  function threshold_option(over) {
949
1370
  return over === void 0 ? {} : { over };
950
1371
  }
951
- function path_option(path10) {
952
- return path10 === void 0 ? {} : { path: path10 };
1372
+ function path_option(path15) {
1373
+ return path15 === void 0 ? {} : { path: path15 };
953
1374
  }
954
1375
  function to_options(values) {
955
1376
  if (values.cut === true && values.over !== void 0) return void 0;
@@ -1088,7 +1509,7 @@ var cost_format = {
1088
1509
  };
1089
1510
 
1090
1511
  // scripts/rules/implementation-cut-verdict.ts
1091
- import { z as z4 } from "zod";
1512
+ import { z as z5 } from "zod";
1092
1513
  var VERDICT_CACHE_PREFIX = "josh-impl-cut-verdict-";
1093
1514
  var VERDICT_REUSE_MS = 5e3;
1094
1515
  var VERDICT_VALUES = [
@@ -1096,7 +1517,7 @@ var VERDICT_VALUES = [
1096
1517
  "under",
1097
1518
  "unmeasurable"
1098
1519
  ];
1099
- var cache_schema = z4.object({ read_at_ms: z4.number(), verdict: z4.enum(VERDICT_VALUES) });
1520
+ var cache_schema = z5.object({ read_at_ms: z5.number(), verdict: z5.enum(VERDICT_VALUES) });
1100
1521
  function cache_path(directory) {
1101
1522
  return stamp_file.stamp_path(VERDICT_CACHE_PREFIX, directory);
1102
1523
  }
@@ -1173,7 +1594,7 @@ function is_over_threshold_edit(call, state = current_state()) {
1173
1594
  return warrants_the_cut(state);
1174
1595
  }
1175
1596
  var THRESHOLD_TEXT = `${cost_format.format_tokens(CONTEXT_CUT_THRESHOLD)}-token`;
1176
- var IMPLEMENTATION_CUT_REASON = `\u26D4 implementation-phase cut: this checkout is a lane dispatched for this issue, or a run holds it for this issue (joshuafolkken/kit#2760), and its recent-context cost has crossed the shared ${THRESHOLD_TEXT} threshold mid-implementation, so the thinking accumulated so far is now re-read on every later request. Take the cut before this edit. First write a handoff file at \`${run_cut_handoff.HANDOFF_PATH}\` (ignored, so it is never committed) with the Write tool \u2014 the user\u2019s instruction verbatim, what you have completed, what remains, and what you deliberately did not touch, as ${run_cut_handoff.HANDOFF_FORMAT} (Markdown is refused) \u2014 and pass it as \`--handoff <path>\`, so the fresh process resumes on the original instruction rather than the working tree alone (joshuafolkken/kit#2354); a resume that finds no instruction is refused \`incomplete\` rather than continuing blind. \`pnpm josh run:cut --impl <N> --handoff <path>\` ends this process and relaunches a fresh one that resumes back into implementation (\`resume-impl\`), dropping the accumulated context rather than carrying it \u2014 joshuafolkken/kit#1933 built the boundary and joshuafolkken/kit#2310 measured it firing 0 times because the verdict was only ever read at session entry, where the context has not yet grown. The verdict is \`pnpm josh cost --cut\`'s exactly \u2014 the same per-request billed-input statistic against the same threshold, never a second measurement. Issue \`pnpm josh run:cut --impl <N> --handoff <path>\` now and read the verdict: on \`cut\`, **end the turn immediately** \u2014 in a lane the fresh process owns the run and continues implementing, so it must not be waited for; outside a lane nothing is relaunched, so first send the \`confirmation\` Telegram naming the resume command \`fullrun #<N>\` and keep the hold; on \`not-a-lane\`, \`unready\`, \`busy\`, \`failed\` or \`unknown\`, this process carries the run on and the edit is simply the next call. Never relaunch a second process after \`busy\`. This fired because the dispatch mark names this lane or the run hold names this issue; a person working here carries no mark and holds no run, so sees no refusal, so there is no human-or-child judgement left to make. The procedure is \`.claude/skills/workflow-commands/pre-gate-cut.md\`. Reissue this edit once the cut has answered \u2014 an edit reissued right after this refusal passes, so \`busy\` / \`failed\` cannot wedge the run edit after edit; this fires again on the next threshold crossing rather than once per run.`;
1597
+ var IMPLEMENTATION_CUT_REASON = `\u26D4 implementation-phase cut: this checkout is a lane dispatched for this issue, or a run holds it for this issue (joshuafolkken/kit#2760), and its recent-context cost has crossed the shared ${THRESHOLD_TEXT} threshold mid-implementation, so the thinking accumulated so far is now re-read on every later request. Take the cut before this edit. First write a handoff file at \`${run_cut_handoff.HANDOFF_PATH}\` (ignored, so it is never committed) with the Write tool \u2014 the user\u2019s instruction verbatim, what you have completed, what remains, and what you deliberately did not touch, as ${run_cut_handoff.HANDOFF_FORMAT} (Markdown is refused) \u2014 and pass it as \`--handoff <path>\`, so the fresh process resumes on the original instruction rather than the working tree alone (joshuafolkken/kit#2354); a resume that finds no instruction is refused \`incomplete\` rather than continuing blind. \`pnpm josh run:cut --impl <N> --handoff <path>\` ends this process and relaunches a fresh one that resumes back into implementation (\`resume-impl\`), dropping the accumulated context rather than carrying it \u2014 joshuafolkken/kit#1933 built the boundary and joshuafolkken/kit#2310 measured it firing 0 times because the verdict was only ever read at session entry, where the context has not yet grown. The verdict is \`pnpm josh cost --cut\`'s exactly \u2014 the same per-request billed-input statistic against the same threshold, never a second measurement. Issue \`pnpm josh run:cut --impl <N> --handoff <path>\` now and read the verdict: on \`cut\`, read what the command printed. Where it relaunched a fresh process, **end the turn immediately** \u2014 that process owns the run and continues implementing, so it must not be waited for, and **no Telegram is owed**: a cut that resumes itself leaves a person nothing to act on. Where it printed that nothing was relaunched, do what it prints, then end the turn; on \`not-a-lane\`, \`unready\`, \`busy\`, \`failed\` or \`unknown\`, this process carries the run on and the edit is simply the next call. Never relaunch a second process after \`busy\`. This fired because the dispatch mark names this lane or the run hold names this issue; a person working here carries no mark and holds no run, so sees no refusal, so there is no human-or-child judgement left to make. The procedure is \`.claude/skills/workflow-commands/pre-gate-cut.md\`. Reissue this edit once the cut has answered \u2014 an edit reissued right after this refusal passes, so \`busy\` / \`failed\` cannot wedge the run edit after edit; this fires again on the next threshold crossing rather than once per run.`;
1177
1598
  var REISSUE_WINDOW_MS = 9e4;
1178
1599
  function is_reissued_refusal(now_ms, delivered_at_ms) {
1179
1600
  return now_ms - delivered_at_ms < REISSUE_WINDOW_MS;
@@ -1395,20 +1816,20 @@ var lane_carry_conflict = {
1395
1816
  };
1396
1817
 
1397
1818
  // scripts/agent/interactive-ask.ts
1398
- import { z as z5 } from "zod";
1819
+ import { z as z6 } from "zod";
1399
1820
  var INTERACTIVE_TOOLS = /* @__PURE__ */ new Set(["AskUserQuestion"]);
1400
1821
  function is_interactive_tool(name) {
1401
1822
  return INTERACTIVE_TOOLS.has(name);
1402
1823
  }
1403
- var OPTION_SCHEMA = z5.looseObject({ label: z5.string().optional() });
1404
- var QUESTION_SCHEMA = z5.looseObject({
1405
- question: z5.string().optional(),
1406
- options: z5.array(OPTION_SCHEMA).optional()
1824
+ var OPTION_SCHEMA = z6.looseObject({ label: z6.string().optional() });
1825
+ var QUESTION_SCHEMA = z6.looseObject({
1826
+ question: z6.string().optional(),
1827
+ options: z6.array(OPTION_SCHEMA).optional()
1407
1828
  });
1408
- var ASK_INPUT_SCHEMA = z5.looseObject({ questions: z5.array(QUESTION_SCHEMA).optional() });
1409
- var DENIAL_SCHEMA = z5.looseObject({
1410
- tool_name: z5.string().optional(),
1411
- tool_input: z5.unknown().optional()
1829
+ var ASK_INPUT_SCHEMA = z6.looseObject({ questions: z6.array(QUESTION_SCHEMA).optional() });
1830
+ var DENIAL_SCHEMA = z6.looseObject({
1831
+ tool_name: z6.string().optional(),
1832
+ tool_input: z6.unknown().optional()
1412
1833
  });
1413
1834
  var UNKNOWN_QUESTION = "(question text unavailable)";
1414
1835
  var OPTION_SEPARATOR = " / ";
@@ -2301,20 +2722,20 @@ import path4 from "node:path";
2301
2722
  var KIT_PACKAGE_NAME = "@joshuafolkken/kit";
2302
2723
 
2303
2724
  // scripts/doctor/doctor-consumer.ts
2304
- import { z as z6 } from "zod";
2725
+ import { z as z7 } from "zod";
2305
2726
  var NODE_MODULES = "node_modules";
2306
2727
  var SETTINGS_PATH = path4.join(".claude", "settings.json");
2307
2728
  var CLAUDE_MD = "CLAUDE.md";
2308
2729
  var PLUGIN_ID = "kit@kit";
2309
2730
  var CLAUDE_MD_POINTER = `@${NODE_MODULES}/${KIT_PACKAGE_NAME}/dist/${CLAUDE_MD}`;
2310
2731
  var SECRETLINT_BIN = path4.join(NODE_MODULES, ".bin", "secretlint");
2311
- var manifest_schema = z6.object({
2312
- name: z6.string().optional(),
2313
- dependencies: z6.record(z6.string(), z6.string()).optional(),
2314
- devDependencies: z6.record(z6.string(), z6.string()).optional()
2732
+ var manifest_schema = z7.object({
2733
+ name: z7.string().optional(),
2734
+ dependencies: z7.record(z7.string(), z7.string()).optional(),
2735
+ devDependencies: z7.record(z7.string(), z7.string()).optional()
2315
2736
  });
2316
- var settings_schema = z6.object({
2317
- enabledPlugins: z6.record(z6.string(), z6.boolean()).optional()
2737
+ var settings_schema = z7.object({
2738
+ enabledPlugins: z7.record(z7.string(), z7.boolean()).optional()
2318
2739
  });
2319
2740
  var STATE_OK = "ok";
2320
2741
  var STATE_TARGET_MISSING = "target-missing";
@@ -2358,9 +2779,9 @@ function is_secretlint_runnable(root) {
2358
2779
  function status_line(is_ok, ok_text, warn_text) {
2359
2780
  return is_ok ? ` \u2713 ${ok_text}` : ` \u26A0 ${warn_text}`;
2360
2781
  }
2361
- function plugin_line(is_declared2) {
2782
+ function plugin_line(is_declared3) {
2362
2783
  return status_line(
2363
- is_declared2,
2784
+ is_declared3,
2364
2785
  "kit plugin declared (skills load in a trusted workspace; headless from its second session)",
2365
2786
  "kit plugin not declared in .claude/settings.json \u2014 run `pnpm josh sync`"
2366
2787
  );
@@ -2653,7 +3074,7 @@ function is_uncut_gate(command, state = current_state2()) {
2653
3074
  if (!runs_the_gate(command) || uncut_lane_issue(state) === void 0) return false;
2654
3075
  return warrants_the_cut2(state.context_verdict());
2655
3076
  }
2656
- var PRE_GATE_CUT_REASON = "\u26D4 pre-gate cut: this checkout is a lane dispatched for this issue and the gate is the boundary to cut at, so take the cut before running it. `pnpm josh run:cut <N>` ends this process and relaunches a fresh one that resumes from the gate, dropping the thinking built up while implementing rather than carrying it on every later request \u2014 joshuafolkken/kit#1839 measured 176K of 204K output riding across that boundary, and joshuafolkken/kit#1864 measured the step itself firing 0 times in 6 lane children while it was carried as prose. Issue `pnpm josh run:cut <N>` now, and read the verdict: on `cut`, **end the turn immediately** \u2014 the fresh process owns the run from there and must not be waited for; on `not-a-lane`, `unready`, `busy`, `failed` or `unknown`, this process carries the run on and the gate is simply the next call. Never relaunch a second process after `busy`. This fired because the dispatch mark names this lane; a person working here carries no mark and sees no refusal, so there is no human-or-child judgement left to make. The procedure is `.claude/skills/workflow-commands/pre-gate-cut.md`. Reissue the gate once the cut has answered \u2014 this fires once per run, so it cannot repeat on the call in hand.";
3077
+ var PRE_GATE_CUT_REASON = "\u26D4 pre-gate cut: this checkout is a lane dispatched for this issue and the gate is the boundary to cut at, so take the cut before running it. `pnpm josh run:cut <N>` ends this process and relaunches a fresh one that resumes from the gate, dropping the thinking built up while implementing rather than carrying it on every later request \u2014 joshuafolkken/kit#1839 measured 176K of 204K output riding across that boundary, and joshuafolkken/kit#1864 measured the step itself firing 0 times in 6 lane children while it was carried as prose. Issue `pnpm josh run:cut <N>` now, and read the verdict: on `cut`, **end the turn immediately** \u2014 the fresh process owns the run from there and must not be waited for, and **no Telegram is owed** for a cut that resumes itself; on `not-a-lane`, `unready`, `busy`, `failed` or `unknown`, this process carries the run on and the gate is simply the next call. Never relaunch a second process after `busy`. This fired because the dispatch mark names this lane; a person working here carries no mark and sees no refusal, so there is no human-or-child judgement left to make. The procedure is `.claude/skills/workflow-commands/pre-gate-cut.md`. Reissue the gate once the cut has answered \u2014 this fires once per run, so it cannot repeat on the call in hand.";
2657
3078
  function reaches_the_pre_gate_boundary(call, _turn, run2) {
2658
3079
  if (!bash_triggers.on_bash_command(asks_about_the_cut)(call)) return false;
2659
3080
  return run2.some((issued) => bash_triggers.on_bash_command(claims_the_hold)(issued));
@@ -2701,7 +3122,7 @@ var MIN_APPENDED_PROSE = 120;
2701
3122
  function adds_rule_prose(old_text, new_text) {
2702
3123
  return prose_of(new_text).length - prose_of(old_text).length >= MIN_APPENDED_PROSE;
2703
3124
  }
2704
- function string_field(input, key) {
3125
+ function string_field2(input, key) {
2705
3126
  const value = input[key];
2706
3127
  return typeof value === "string" ? value : "";
2707
3128
  }
@@ -2711,13 +3132,13 @@ function read_existing(file_path) {
2711
3132
  function texts_of(name, input, read2) {
2712
3133
  if (name === WRITE_TOOL) {
2713
3134
  return {
2714
- old_text: read2(string_field(input, "file_path")),
2715
- new_text: string_field(input, "content")
3135
+ old_text: read2(string_field2(input, "file_path")),
3136
+ new_text: string_field2(input, "content")
2716
3137
  };
2717
3138
  }
2718
3139
  return {
2719
- old_text: string_field(input, "old_string"),
2720
- new_text: string_field(input, "new_string")
3140
+ old_text: string_field2(input, "old_string"),
3141
+ new_text: string_field2(input, "new_string")
2721
3142
  };
2722
3143
  }
2723
3144
  function is_edit_tool2(name) {
@@ -2725,7 +3146,7 @@ function is_edit_tool2(name) {
2725
3146
  }
2726
3147
  function rule_document_input(call) {
2727
3148
  if (!is_edit_tool2(call.name) || !json_value.is_record(call.input)) return void 0;
2728
- return is_rule_document(string_field(call.input, "file_path")) ? call.input : void 0;
3149
+ return is_rule_document(string_field2(call.input, "file_path")) ? call.input : void 0;
2729
3150
  }
2730
3151
  function writes_rule_prose(call, read2 = read_existing) {
2731
3152
  const input = rule_document_input(call);
@@ -2838,12 +3259,2054 @@ var shell_body_trigger = {
2838
3259
  };
2839
3260
 
2840
3261
  // scripts/gate/project-checks.ts
2841
- import { existsSync as existsSync4, globSync as globSync2, readFileSync as readFileSync4 } from "node:fs";
2842
- import path7 from "node:path";
3262
+ import { existsSync as existsSync6, globSync as globSync2, readFileSync as readFileSync6 } from "node:fs";
3263
+ import path12 from "node:path";
2843
3264
 
2844
3265
  // scripts/init/project-profile.ts
2845
- import { existsSync as existsSync3, readdirSync, readFileSync as readFileSync3 } from "node:fs";
3266
+ import { existsSync as existsSync5, readdirSync, readFileSync as readFileSync5 } from "node:fs";
3267
+ import path11 from "node:path";
3268
+
3269
+ // scripts/safe-chain/pack-hook.ts
3270
+ import { z as z8 } from "zod";
3271
+ var PACK_HOOK_FILE = ".pnpmfile.mjs";
3272
+ var manifest_schema2 = z8.looseObject({ private: z8.boolean().optional() });
3273
+ var MESSAGES = {
3274
+ written: ` \u2714 synced ${PACK_HOOK_FILE} (run \`pnpm install\` to refresh pnpmfileChecksum)`,
3275
+ unchanged: ` \u2714 unchanged ${PACK_HOOK_FILE}`,
3276
+ private: void 0,
3277
+ owned: ` \u26A0 skipped ${PACK_HOOK_FILE} \u2014 the project has its own pnpmfile; strip the safe-chain preinstall at pack time there`,
3278
+ withdrawn: ` \u26A0 removed ${PACK_HOOK_FILE} \u2014 it shadowed the project's own pnpmfile; strip the safe-chain preinstall at pack time there`
3279
+ };
3280
+
3281
+ // scripts/lib/yaml-document.ts
3282
+ import { load, loadAll, YAMLException } from "js-yaml";
3283
+ var EMPTY_YAML_REASON = "expected a document, but the input is empty";
3284
+ function load_yaml_or_empty(content) {
3285
+ try {
3286
+ return load(content);
3287
+ } catch (error) {
3288
+ if (error instanceof YAMLException && error.reason === EMPTY_YAML_REASON) return {};
3289
+ throw error;
3290
+ }
3291
+ }
3292
+ function parse_yaml(content) {
3293
+ const raw = load_yaml_or_empty(content);
3294
+ if (raw === null || raw === void 0) return {};
3295
+ return json_object_schema.parse(raw);
3296
+ }
3297
+ function is_mapping_document(value) {
3298
+ return json_value.is_record(value);
3299
+ }
3300
+ function parse_yaml_documents(content) {
3301
+ if (content.trim().length === 0) return [];
3302
+ return loadAll(content).filter(is_mapping_document);
3303
+ }
3304
+ var yaml_document = { is_mapping_document, parse_yaml, parse_yaml_documents };
3305
+
3306
+ // scripts/version/release-age.ts
3307
+ import semver from "semver";
3308
+ import { z as z9 } from "zod";
3309
+ var workspace_age_schema = z9.object({ minimumReleaseAge: z9.number().int().nonnegative() });
3310
+ var release_times_schema = z9.record(z9.string(), z9.string());
3311
+
3312
+ // scripts/safe-chain/project-config.ts
3313
+ import { dump } from "js-yaml";
3314
+ import { z as z10 } from "zod";
3315
+ var PROJECT_CONFIG_FILE = ".aikido";
3316
+ var workspace_schema = z10.object({ minimumReleaseAgeExclude: z10.array(z10.string()).optional() });
3317
+
3318
+ // scripts/config-merge/json-format.ts
3319
+ var PRINT_WIDTH = 100;
3320
+ var TAB_WIDTH = 2;
3321
+ var ARRAY_CLOSE = /^\t*\],?$/u;
3322
+ function is_array_open(line) {
3323
+ return line.endsWith("[");
3324
+ }
3325
+ function is_leaf_element(line) {
3326
+ return !line.endsWith("{") && !line.endsWith("[");
3327
+ }
3328
+ function line_width(line) {
3329
+ const tabs = line.length - line.trimStart().length;
3330
+ return tabs * TAB_WIDTH + (line.length - tabs);
3331
+ }
3332
+ function flatten_elements(elements) {
3333
+ const scalars = elements.map((line) => line.trim().replace(/,$/u, ""));
3334
+ return `[${scalars.join(", ")}]`;
3335
+ }
3336
+ function collect_block(lines, start) {
3337
+ const close = lines.findIndex((line, index) => index > start && ARRAY_CLOSE.test(line));
3338
+ if (close === -1) return void 0;
3339
+ const elements = lines.slice(start + 1, close);
3340
+ if (elements.some((line) => !is_leaf_element(line))) return void 0;
3341
+ return { elements, close: lines[close] ?? "", end: close };
3342
+ }
3343
+ function try_inline(open, block) {
3344
+ const trailing_comma = block.close.trimStart() === "]," ? "," : "";
3345
+ const inlined = `${open.slice(0, -1)}${flatten_elements(block.elements)}${trailing_comma}`;
3346
+ return line_width(inlined) <= PRINT_WIDTH ? inlined : void 0;
3347
+ }
3348
+ function rewrite_at(lines, index, line) {
3349
+ const verbatim = { lines: [line], next: index + 1 };
3350
+ const block = is_array_open(line) ? collect_block(lines, index) : void 0;
3351
+ if (block === void 0) return verbatim;
3352
+ const inlined = try_inline(line, block);
3353
+ if (inlined === void 0) return verbatim;
3354
+ return { lines: [inlined], next: block.end + 1 };
3355
+ }
3356
+ function inline_short_arrays(text) {
3357
+ const lines = text.split("\n");
3358
+ const output = [];
3359
+ let index = 0;
3360
+ while (index < lines.length) {
3361
+ const rewrite = rewrite_at(lines, index, lines[index] ?? "");
3362
+ output.push(...rewrite.lines);
3363
+ index = rewrite.next;
3364
+ }
3365
+ return output.join("\n");
3366
+ }
3367
+ function format_json(value) {
3368
+ return `${inline_short_arrays(JSON.stringify(value, void 0, " "))}
3369
+ `;
3370
+ }
3371
+ function format_package_json(value) {
3372
+ return `${JSON.stringify(value, void 0, " ")}
3373
+ `;
3374
+ }
3375
+ var json_format = {
3376
+ format_json,
3377
+ format_package_json
3378
+ };
3379
+
3380
+ // scripts/safe-chain/preinstall-command.ts
3381
+ var INSTALL_GUIDE_ANCHOR = "installing-safe-chain";
3382
+ var INSTALL_GUIDE_URL = `https://github.com/joshuafolkken/kit/blob/main/SECURITY.md#${INSTALL_GUIDE_ANCHOR}`;
3383
+ var INTEGRATION_HINT = `Warning: safe-chain (@aikidosec/safe-chain) is not scanning this install because its shell integration is not active. Install it with the hash-verified steps at ${INSTALL_GUIDE_URL} - then restart your terminal.`;
3384
+ var LOCAL_INTEGRATION_CHECK_SOURCE = `if(!process.env.CI&&!process.env.GLOBAL_AGENT_HTTP_PROXY)console.warn('${INTEGRATION_HINT}')`;
3385
+ var SAFE_CHAIN_CMD = `node -e "${LOCAL_INTEGRATION_CHECK_SOURCE}"`;
3386
+ var LEGACY_PREINSTALL_RE = /^pnpm dlx @aikidosec\/safe-chain(?:@\S+)? setup-ci(?: && node -e "[^"]*")?$/u;
3387
+ function migrate_preinstall(value) {
3388
+ return LEGACY_PREINSTALL_RE.test(value) ? SAFE_CHAIN_CMD : value;
3389
+ }
3390
+ var safe_chain_preinstall = {
3391
+ SAFE_CHAIN_CMD,
3392
+ LOCAL_INTEGRATION_CHECK_SOURCE,
3393
+ INTEGRATION_HINT,
3394
+ INSTALL_GUIDE_ANCHOR,
3395
+ migrate_preinstall
3396
+ };
3397
+
3398
+ // scripts/init/distributed-paths.ts
3399
+ var KIT_PACKAGE_PATH_PREFIX = "node_modules/@joshuafolkken/kit/";
3400
+ var PROMPTS_PACKAGE_PREFIX = `${KIT_PACKAGE_PATH_PREFIX}prompts/`;
3401
+ var ESLINT_PACKAGE_PREFIX = `${KIT_PACKAGE_PATH_PREFIX}eslint/`;
3402
+ var GITHUB_REPO_BLOB_BASE = "https://github.com/joshuafolkken/kit/blob/main/";
3403
+ var GITHUB_REPO_TREE_BASE = "https://github.com/joshuafolkken/kit/tree/main/";
3404
+ var CLAUDE_MD_IMPORT_LINE = "@node_modules/@joshuafolkken/kit/dist/CLAUDE.md";
3405
+ var OLD_CLAUDE_MD_BOOTSTRAP = "> Fresh checkout: if kit is not installed, run `pnpm install` first, then reread this file before doing any other work.";
3406
+ var CLAUDE_MD_BOOTSTRAP = '> Fresh checkout: before `pnpm install`, run `pnpm config get "@joshuafolkken:registry"` from the project root to check the effective registry, including user-level settings. If it points to GitHub Packages, [set up authentication](https://github.com/joshuafolkken/kit/blob/main/docs/authentication.md#1-get-a-token-from-the-gh-cli) first. Then run `pnpm install` and reread this file before doing any other work.';
3407
+ function transform_prompt_paths(content) {
3408
+ return content.replaceAll(
3409
+ /`prompts\/([^`*]+)`/gu,
3410
+ (_match, prompt_path) => `\`${PROMPTS_PACKAGE_PREFIX}${prompt_path}\``
3411
+ );
3412
+ }
3413
+ function transform_eslint_paths(content) {
3414
+ return content.replaceAll(
3415
+ /`eslint\/([^`*]+)`/gu,
3416
+ (_match, eslint_path) => `\`${ESLINT_PACKAGE_PREFIX}${eslint_path}\``
3417
+ );
3418
+ }
3419
+ function transform_test_file_paths(content) {
3420
+ return content.replaceAll(
3421
+ /`([^`*]+\.(?:test|spec)\.ts)`/gu,
3422
+ (_match, test_path) => `\`${GITHUB_REPO_BLOB_BASE}${test_path}\``
3423
+ );
3424
+ }
3425
+ function github_url_base(reference_path) {
3426
+ return reference_path.endsWith("/") ? GITHUB_REPO_TREE_BASE : GITHUB_REPO_BLOB_BASE;
3427
+ }
3428
+ function transform_documentation_paths(content) {
3429
+ return content.replaceAll(
3430
+ /`(docs\/[^`*]*)`/gu,
3431
+ (_match, documentation_path) => `\`${github_url_base(documentation_path)}${documentation_path}\``
3432
+ );
3433
+ }
3434
+ function transform_distributed_paths(content) {
3435
+ const with_prompts = transform_prompt_paths(content);
3436
+ const with_eslint = transform_eslint_paths(with_prompts);
3437
+ const with_tests = transform_test_file_paths(with_eslint);
3438
+ return transform_documentation_paths(with_tests);
3439
+ }
3440
+ function ensure_claude_md_import(existing) {
3441
+ if (existing === void 0) return `${CLAUDE_MD_BOOTSTRAP}
3442
+
3443
+ ${CLAUDE_MD_IMPORT_LINE}
3444
+ `;
3445
+ const updated = existing.replace(OLD_CLAUDE_MD_BOOTSTRAP, () => CLAUDE_MD_BOOTSTRAP);
3446
+ if (updated.includes(CLAUDE_MD_IMPORT_LINE)) {
3447
+ if (updated.includes(CLAUDE_MD_BOOTSTRAP)) return updated;
3448
+ return `${CLAUDE_MD_BOOTSTRAP}
3449
+
3450
+ ${updated}`;
3451
+ }
3452
+ return `${CLAUDE_MD_BOOTSTRAP}
3453
+
3454
+ ${CLAUDE_MD_IMPORT_LINE}
3455
+
3456
+ ${updated}`;
3457
+ }
3458
+ var FULL_CLAUDE_MD_LINES = /* @__PURE__ */ new Set([
3459
+ CLAUDE_MD_BOOTSTRAP,
3460
+ OLD_CLAUDE_MD_BOOTSTRAP,
3461
+ CLAUDE_MD_IMPORT_LINE
3462
+ ]);
3463
+ function remove_claude_md_import(content) {
3464
+ const lines = content.split("\n");
3465
+ return lines.filter((line, index) => {
3466
+ if (FULL_CLAUDE_MD_LINES.has(line)) return false;
3467
+ return line !== "" || !FULL_CLAUDE_MD_LINES.has(lines[index - 1] ?? "");
3468
+ }).join("\n");
3469
+ }
3470
+ var distributed_paths = {
3471
+ transform_prompt_paths,
3472
+ transform_distributed_paths,
3473
+ ensure_claude_md_import,
3474
+ remove_claude_md_import,
3475
+ CLAUDE_MD_IMPORT_LINE
3476
+ };
3477
+
3478
+ // scripts/init/init-logic-deploy-vps.ts
3479
+ import semver2 from "semver";
3480
+ var PNPM_INSTALL_PATTERN = /npm install -g pnpm@\d[\d.]{0,19}/gu;
3481
+ var PNPM12_INSTALL = "npm install -g pnpm@12.6.0";
3482
+ var MINIMUM_PNPM_VERSION = "12.1.0";
3483
+ var OLD_PNPM_CHECK_PATTERN = /^([ \t]*)if ! command -v pnpm &> \/dev\/null(?: \|\| \[ "\$PNPM_MAJOR" -lt \d+ \])?; then$/mu;
3484
+ var OLD_MAJOR_LINE_PATTERN = /^[ \t]*PNPM_MAJOR=\$\(pnpm --version 2>\/dev\/null \| cut -d\. -f1 \|\| echo "0"\)\n/mu;
3485
+ var VERSION_CHECK_MARKER = '[ "$PNPM_MINOR" -lt 1 ]';
3486
+ function replace_outdated_install(command) {
3487
+ const version = command.slice("npm install -g pnpm@".length);
3488
+ const valid_version = semver2.valid(version);
3489
+ if (valid_version === null) return command;
3490
+ return semver2.lt(valid_version, MINIMUM_PNPM_VERSION) ? PNPM12_INSTALL : command;
3491
+ }
3492
+ function build_version_check(indent) {
3493
+ return [
3494
+ `${indent}PNPM_VERSION=$(pnpm --version 2>/dev/null || echo "0.0.0")`,
3495
+ `${indent}PNPM_MAJOR=$(echo "$PNPM_VERSION" | cut -d. -f1)`,
3496
+ `${indent}PNPM_MINOR=$(echo "$PNPM_VERSION" | cut -d. -f2)`,
3497
+ `${indent}if [ "$PNPM_MAJOR" -lt 12 ] || { [ "$PNPM_MAJOR" -eq 12 ] && [ "$PNPM_MINOR" -lt 1 ]; }; then`
3498
+ ].join("\n");
3499
+ }
3500
+ function patch_deploy_vps_pnpm(content) {
3501
+ const with_pnpm12 = content.replaceAll(
3502
+ PNPM_INSTALL_PATTERN,
3503
+ (command) => replace_outdated_install(command)
3504
+ );
3505
+ if (with_pnpm12.includes(VERSION_CHECK_MARKER)) return with_pnpm12;
3506
+ if (!OLD_PNPM_CHECK_PATTERN.test(with_pnpm12)) return with_pnpm12;
3507
+ return with_pnpm12.replace(OLD_MAJOR_LINE_PATTERN, "").replace(OLD_PNPM_CHECK_PATTERN, (_, indent) => build_version_check(indent));
3508
+ }
3509
+ var init_logic_deploy_vps = { patch_deploy_vps_pnpm };
3510
+
3511
+ // scripts/config-merge/list-patch.ts
3512
+ function is_matching(entry, matchers) {
3513
+ return matchers.some(
3514
+ (matcher) => typeof matcher === "string" ? matcher === entry : matcher.test(entry)
3515
+ );
3516
+ }
3517
+ function apply_remove(existing, remove) {
3518
+ if (remove === void 0 || remove.length === 0) return existing;
3519
+ return existing.filter((entry) => !is_matching(entry, remove));
3520
+ }
3521
+ function collect_additions(kept, ensure) {
3522
+ if (ensure === void 0) return [];
3523
+ return ensure.filter((entry) => !kept.includes(entry));
3524
+ }
3525
+ function apply_list_patch(existing, patch) {
3526
+ const kept = apply_remove(existing, patch.remove);
3527
+ const additions = collect_additions(kept, patch.ensure);
3528
+ const is_changed = additions.length > 0 || kept.length !== existing.length;
3529
+ return { next: [...additions, ...kept], is_changed };
3530
+ }
3531
+ var list_patch = {
3532
+ is_matching,
3533
+ apply_list_patch
3534
+ };
3535
+
3536
+ // scripts/config-merge/parse-jsonc.ts
3537
+ import { parseTree, printParseErrorCode } from "jsonc-parser";
3538
+ function property_key(property) {
3539
+ return String(property.children?.[0]?.value);
3540
+ }
3541
+ function node_value(node) {
3542
+ if (node === void 0) return void 0;
3543
+ const children = node.children ?? [];
3544
+ if (node.type === "array") return children.map((child) => node_value(child));
3545
+ if (node.type !== "object") return node.value;
3546
+ return Object.fromEntries(
3547
+ children.map((property) => [property_key(property), node_value(property.children?.[1])])
3548
+ );
3549
+ }
3550
+ function parse_jsonc(content) {
3551
+ const errors = [];
3552
+ const tree = parseTree(content, errors, { allowTrailingComma: true });
3553
+ const [first_error] = errors;
3554
+ if (first_error !== void 0) {
3555
+ throw new SyntaxError(
3556
+ `Invalid JSONC: ${printParseErrorCode(first_error.error)} at offset ${String(first_error.offset)}`
3557
+ );
3558
+ }
3559
+ return json_object_schema.parse(node_value(tree));
3560
+ }
3561
+
3562
+ // scripts/config-merge/patch-json-key.ts
3563
+ import {
3564
+ createScanner,
3565
+ findNodeAtLocation,
3566
+ getNodeValue,
3567
+ parseTree as parseTree2,
3568
+ stripComments
3569
+ } from "jsonc-parser";
3570
+ var DOCUMENT_SUFFIX = "\n}\n";
3571
+ var DEFAULT_INDENT = " ";
3572
+ var LEADING_BLANKS = /^[\t ]*/u;
3573
+ var PREVIOUS_LINE_OFFSET = 2;
3574
+ var CRLF = "\r\n";
3575
+ var COMMA_PROBE_VALUE = 0;
3576
+ function render_value(key, value, has_trailing_comma) {
3577
+ const probe_key = `${key} `;
3578
+ const probe = has_trailing_comma ? { [key]: value, [probe_key]: COMMA_PROBE_VALUE } : { [key]: value };
3579
+ const document = json_format.format_json(probe);
3580
+ const prefix = `{
3581
+ ${JSON.stringify(key)}: `;
3582
+ const suffix = has_trailing_comma ? `,
3583
+ ${JSON.stringify(probe_key)}: ${String(COMMA_PROBE_VALUE)}${DOCUMENT_SUFFIX}` : DOCUMENT_SUFFIX;
3584
+ return document.slice(prefix.length, document.length - suffix.length);
3585
+ }
3586
+ function parse_root(content) {
3587
+ const root = parseTree2(content);
3588
+ return root?.type === "object" ? root : void 0;
3589
+ }
3590
+ function replace_range(content, range, text) {
3591
+ return content.slice(0, range.offset) + text + content.slice(range.offset + range.length);
3592
+ }
3593
+ function insert_at(content, offset, text) {
3594
+ return replace_range(content, { offset, length: 0 }, text);
3595
+ }
3596
+ function render_indent(value_text, unit) {
3597
+ if (unit === DEFAULT_INDENT || unit.length === 0) return value_text;
3598
+ return value_text.replaceAll(/^\t+/gmu, (tabs) => unit.repeat(tabs.length));
3599
+ }
3600
+ function eol_of(content) {
3601
+ return content.includes(CRLF) ? CRLF : "\n";
3602
+ }
3603
+ function fit_value(content, value_text, indent) {
3604
+ const indented = render_indent(value_text, indent);
3605
+ if (eol_of(content) === "\n") return indented;
3606
+ return indented.split("\n").join(CRLF);
3607
+ }
3608
+ function line_indent(content, offset) {
3609
+ const line_start = content.lastIndexOf("\n", offset - 1) + 1;
3610
+ return LEADING_BLANKS.exec(content.slice(line_start, offset))?.[0] ?? "";
3611
+ }
3612
+ function line_end(content, offset) {
3613
+ const index = content.indexOf("\n", offset);
3614
+ if (index === -1) return content.length;
3615
+ return index > offset && content[index - 1] === "\r" ? index - 1 : index;
3616
+ }
3617
+ function render_property(content, key, value_text, indent) {
3618
+ return `${JSON.stringify(key)}: ${fit_value(content, value_text, indent)}`;
3619
+ }
3620
+ function insertion_offset(content, root, value_end) {
3621
+ return Math.min(line_end(content, value_end), root.offset + root.length - 1);
3622
+ }
3623
+ function separator_offset(content, offset, limit) {
3624
+ const scanner = createScanner(content, true);
3625
+ scanner.setPosition(offset);
3626
+ scanner.scan();
3627
+ const at = scanner.getTokenOffset();
3628
+ return at < limit && content[at] === "," ? at : -1;
3629
+ }
3630
+ function has_separator_after(content, offset, limit) {
3631
+ return separator_offset(content, offset, limit) !== -1;
3632
+ }
3633
+ function property_key2(property) {
3634
+ const key = property.children?.[0]?.value;
3635
+ return typeof key === "string" ? key : void 0;
3636
+ }
3637
+ function target_value_end(property) {
3638
+ const value_node = property?.children?.[1];
3639
+ return value_node === void 0 ? void 0 : value_node.offset + value_node.length;
3640
+ }
3641
+ function contains_comment(content, node) {
3642
+ const text = content.slice(node.offset, node.offset + node.length);
3643
+ return stripComments(text) !== text;
3644
+ }
3645
+ function rebalanced_value(content, key, value_node, has_trailing_comma) {
3646
+ if (contains_comment(content, value_node)) return void 0;
3647
+ const indent = line_indent(content, value_node.offset);
3648
+ const rendered = fit_value(
3649
+ content,
3650
+ render_value(key, getNodeValue(value_node), has_trailing_comma),
3651
+ indent
3652
+ );
3653
+ const current = content.slice(value_node.offset, value_node.offset + value_node.length);
3654
+ return rendered === current ? void 0 : rendered;
3655
+ }
3656
+ function rebalance(content, property, has_trailing_comma) {
3657
+ const key = property_key2(property);
3658
+ const value_node = property.children?.[1];
3659
+ if (key === void 0 || value_node === void 0) return content;
3660
+ const rendered = rebalanced_value(content, key, value_node, has_trailing_comma);
3661
+ return rendered === void 0 ? content : replace_range(content, value_node, rendered);
3662
+ }
3663
+ function append_after(content, root, last, property) {
3664
+ const value_end = last.offset + last.length;
3665
+ const closing_brace = root.offset + root.length - 1;
3666
+ const separator = has_separator_after(content, value_end, closing_brace) ? "" : ",";
3667
+ const with_property = insert_at(content, insertion_offset(content, root, value_end), property);
3668
+ return insert_at(with_property, value_end, separator);
3669
+ }
3670
+ function insert_only_property(content, root, property) {
3671
+ const closing_brace = root.offset + root.length - 1;
3672
+ const lead = content[closing_brace - 1] === "\n" ? "" : eol_of(content);
3673
+ return insert_at(content, closing_brace, `${lead}${DEFAULT_INDENT}${property}${eol_of(content)}`);
3674
+ }
3675
+ function insert_property(content, root, key, value_text) {
3676
+ const last = root.children?.at(-1);
3677
+ if (last === void 0) {
3678
+ const only = render_property(content, key, value_text, DEFAULT_INDENT);
3679
+ return insert_only_property(content, root, only);
3680
+ }
3681
+ const indent = line_indent(content, last.offset);
3682
+ const property = `${eol_of(content)}${indent}${render_property(content, key, value_text, indent)}`;
3683
+ return rebalance(append_after(content, root, last, property), last, true);
3684
+ }
3685
+ function end_of_trailing_comment(content, end) {
3686
+ const stop = line_end(content, end);
3687
+ return content.slice(end, stop).trimStart().startsWith("//") ? stop : end;
3688
+ }
3689
+ function start_of_leading_comments(content, line_start, floor) {
3690
+ let start = line_start;
3691
+ while (start > floor) {
3692
+ const previous = content.lastIndexOf("\n", start - PREVIOUS_LINE_OFFSET) + 1;
3693
+ const is_comment_line = content.slice(previous, start).trimStart().startsWith("//");
3694
+ if (!is_comment_line || previous < floor) return start;
3695
+ start = previous;
3696
+ }
3697
+ return start;
3698
+ }
3699
+ function end_of_line_break(content, offset) {
3700
+ if (content[offset] === "\r" && content[offset + 1] === "\n") return offset + PREVIOUS_LINE_OFFSET;
3701
+ return content[offset] === "\n" ? offset + 1 : offset;
3702
+ }
3703
+ function body_range(content, root, target, separator_limit) {
3704
+ const value_end = target.offset + target.length;
3705
+ const comma = separator_limit === -1 ? -1 : separator_offset(content, value_end, separator_limit);
3706
+ const end = end_of_trailing_comment(content, comma === -1 ? value_end : comma + 1);
3707
+ const line_start = content.lastIndexOf("\n", target.offset - 1) + 1;
3708
+ const is_own_line = content.slice(line_start, target.offset).trim().length === 0;
3709
+ if (!is_own_line) return { offset: target.offset, length: end - target.offset };
3710
+ const start = start_of_leading_comments(content, line_start, root.offset + 1);
3711
+ return { offset: start, length: end_of_line_break(content, end) - start };
3712
+ }
3713
+ function ranges_for_last_property(content, root, previous, target) {
3714
+ const comma = separator_offset(content, previous.offset + previous.length, target.offset);
3715
+ const body = body_range(content, root, target, -1);
3716
+ return comma === -1 ? [body] : [{ offset: comma, length: 1 }, body];
3717
+ }
3718
+ function removal_ranges(content, root, index) {
3719
+ const children = root.children ?? [];
3720
+ const target = children[index];
3721
+ if (target === void 0) return [];
3722
+ const next = children[index + 1];
3723
+ if (next !== void 0) return [body_range(content, root, target, next.offset)];
3724
+ const previous = children[index - 1];
3725
+ if (previous === void 0) return [{ offset: root.offset, length: root.length }];
3726
+ return ranges_for_last_property(content, root, previous, target);
3727
+ }
3728
+ function property_index(root, key) {
3729
+ return (root.children ?? []).findIndex((child) => child.children?.[0]?.value === key);
3730
+ }
3731
+ function with_trailing_newline(content) {
3732
+ return content.endsWith("\n") ? content : `${content}
3733
+ `;
3734
+ }
3735
+ function is_followed_by_comma(content, root, key) {
3736
+ const children = root.children ?? [];
3737
+ const index = property_index(root, key);
3738
+ if (index < 0) return false;
3739
+ if (index < children.length - 1) return true;
3740
+ const value_end = target_value_end(children[index]);
3741
+ return value_end !== void 0 && has_separator_after(content, value_end, root.offset + root.length);
3742
+ }
3743
+ function set_json_key(content, key, value) {
3744
+ const root = parse_root(content);
3745
+ if (root === void 0) return content;
3746
+ const existing = findNodeAtLocation(root, [key]);
3747
+ const value_text = render_value(
3748
+ key,
3749
+ value,
3750
+ existing !== void 0 && is_followed_by_comma(content, root, key)
3751
+ );
3752
+ if (existing === void 0) {
3753
+ return with_trailing_newline(insert_property(content, root, key, value_text));
3754
+ }
3755
+ const indented = fit_value(content, value_text, line_indent(content, existing.offset));
3756
+ return with_trailing_newline(replace_range(content, existing, indented));
3757
+ }
3758
+ function resolve_parent(content, path15) {
3759
+ const root = parse_root(content);
3760
+ if (root === void 0) return void 0;
3761
+ const parent = path15.length > 1 ? findNodeAtLocation(root, path15.slice(0, -1)) : root;
3762
+ return parent?.type === "object" ? parent : void 0;
3763
+ }
3764
+ function cut_ranges(content, parent, ranges) {
3765
+ const ordered = ranges.toSorted((left, right) => right.offset - left.offset);
3766
+ let next = content;
3767
+ for (const range of ordered) {
3768
+ next = replace_range(next, range, range.offset === parent.offset ? "{}" : "");
3769
+ }
3770
+ return next;
3771
+ }
3772
+ function rebalance_new_last(content, path15) {
3773
+ const parent = resolve_parent(content, path15);
3774
+ const last = parent?.children?.at(-1);
3775
+ if (parent === void 0 || last === void 0) return content;
3776
+ return rebalance(content, last, has_separator_after(content, parent.offset, parent.offset));
3777
+ }
3778
+ function cut_property(content, parent, path15) {
3779
+ const index = property_index(parent, path15.at(-1) ?? "");
3780
+ const ranges = removal_ranges(content, parent, index);
3781
+ if (ranges.length === 0) return content;
3782
+ const cut = cut_ranges(content, parent, ranges);
3783
+ const did_end_object = index === (parent.children ?? []).length - 1;
3784
+ return did_end_object ? rebalance_new_last(cut, path15) : cut;
3785
+ }
3786
+ function remove_json_path(content, path15) {
3787
+ const parent = resolve_parent(content, path15);
3788
+ if (parent === void 0) return content;
3789
+ const next = cut_property(content, parent, path15);
3790
+ return next === content ? content : with_trailing_newline(next);
3791
+ }
3792
+ function remove_json_key(content, key) {
3793
+ return remove_json_path(content, [key]);
3794
+ }
3795
+ var patch_json_key = {
3796
+ set_json_key,
3797
+ remove_json_key,
3798
+ remove_json_path,
3799
+ eol_of,
3800
+ fit_value,
3801
+ line_indent
3802
+ };
3803
+
3804
+ // scripts/config-merge/patch-json-list.ts
3805
+ function normalize_list(value) {
3806
+ if (typeof value === "string") return [value];
3807
+ if (Array.isArray(value)) return value.map(String);
3808
+ return [];
3809
+ }
3810
+ function patch_json_list_field(content, options) {
3811
+ const parsed = parse_jsonc(content);
3812
+ const existing = normalize_list(parsed[options.field]);
3813
+ const { next, is_changed } = list_patch.apply_list_patch(existing, options);
3814
+ if (!is_changed) return content;
3815
+ return patch_json_key.set_json_key(content, options.field, [...next]);
3816
+ }
3817
+ var json_list = {
3818
+ patch_json_list_field
3819
+ };
3820
+
3821
+ // scripts/config-merge/patch-yaml-list.ts
3822
+ import { dump as dump2 } from "js-yaml";
3823
+ var { parse_yaml: parse_yaml2 } = yaml_document;
3824
+ function read_yaml_list_field(content, field) {
3825
+ const raw = parse_yaml2(content)[field];
3826
+ if (typeof raw === "string") return [raw];
3827
+ return Array.isArray(raw) ? string_array_schema.parse(raw) : [];
3828
+ }
3829
+ function replace_field(parsed, field, value) {
3830
+ return Object.fromEntries(
3831
+ Object.entries(parsed).map(([key, entry]) => [key, key === field ? [...value] : entry])
3832
+ );
3833
+ }
3834
+ function insert_after(parsed, field, value, anchor) {
3835
+ const entries = Object.entries(parsed);
3836
+ const index = entries.findIndex(([key]) => key === anchor);
3837
+ if (index === -1) return { ...parsed, [field]: [...value] };
3838
+ return Object.fromEntries([
3839
+ ...entries.slice(0, index + 1),
3840
+ [field, [...value]],
3841
+ ...entries.slice(index + 1)
3842
+ ]);
3843
+ }
3844
+ function insert_new_field(parsed, field, value, position) {
3845
+ if (position === "front") return { [field]: [...value], ...parsed };
3846
+ if (position === "end") return { ...parsed, [field]: [...value] };
3847
+ return insert_after(parsed, field, value, position.after);
3848
+ }
3849
+ function place_field(parsed, field, value, position) {
3850
+ if (Object.hasOwn(parsed, field)) return replace_field(parsed, field, value);
3851
+ return insert_new_field(parsed, field, value, position);
3852
+ }
3853
+ function patch_yaml_list_field(content, options) {
3854
+ const parsed = parse_yaml2(content);
3855
+ const existing = read_yaml_list_field(content, options.field);
3856
+ const { next, is_changed } = list_patch.apply_list_patch(existing, options);
3857
+ if (!is_changed) return content;
3858
+ const placed = place_field(parsed, options.field, next, options.position ?? "front");
3859
+ return dump2(placed, options.quote_style === void 0 ? {} : { quoteStyle: options.quote_style });
3860
+ }
3861
+ var yaml_list = {
3862
+ patch_yaml_list_field,
3863
+ read_yaml_list_field
3864
+ };
3865
+
3866
+ // scripts/config-merge/index.ts
3867
+ var config_merge = {
3868
+ patch_yaml_list_field: yaml_list.patch_yaml_list_field,
3869
+ read_yaml_list_field: yaml_list.read_yaml_list_field,
3870
+ patch_json_list_field: json_list.patch_json_list_field
3871
+ };
3872
+
3873
+ // scripts/init/init-logic-migrate.ts
3874
+ var PREINSTALL_KEY = "preinstall";
3875
+ var JF_PREFIX = "jf-";
3876
+ var JOSH_PREFIX = "josh ";
3877
+ var PRE_JOSH_SCRIPT_VALUES = /* @__PURE__ */ new Map([
3878
+ ["lint", "pnpm lint:prettier && pnpm lint:eslint"],
3879
+ ["lint:prettier", "prettier --check ."],
3880
+ ["lint:eslint", "eslint . --cache --cache-strategy content"],
3881
+ ["format", "pnpm format:prettier && pnpm format:eslint"],
3882
+ ["format:prettier", "prettier --write ."],
3883
+ ["format:eslint", "eslint . --fix --cache --cache-strategy content"],
3884
+ ["cspell", 'cspell lint --no-must-find-files --no-progress "**/*.{ts,js,md,yaml,yml,json}"'],
3885
+ ["cspell:dot", "pnpm cspell . --dot"],
3886
+ ["test:unit", "vitest run"],
3887
+ ["lefthook:install", "lefthook install"],
3888
+ ["lefthook:uninstall", "lefthook uninstall"],
3889
+ ["lefthook:commit", "lefthook run pre-commit"],
3890
+ ["lefthook:push", "lefthook run pre-push"],
3891
+ ["main:sync", "git checkout main && git pull"],
3892
+ ["main:merge", "git pull origin main"],
3893
+ ["check:ci", "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --threshold error"]
3894
+ ]);
3895
+ var RETIRED_MANAGED_SCRIPTS = /* @__PURE__ */ new Set([
3896
+ "git",
3897
+ "git:followup",
3898
+ "telegram:test",
3899
+ "audit:security",
3900
+ "prep",
3901
+ "issue:prep",
3902
+ "prevent-main-commit",
3903
+ "check-commit-message",
3904
+ "version:major",
3905
+ "version:minor",
3906
+ "version:patch",
3907
+ "version:current",
3908
+ "overrides:check",
3909
+ "test:e2e",
3910
+ "test",
3911
+ "latest",
3912
+ "latest:corepack",
3913
+ "latest:update",
3914
+ "check",
3915
+ "check:svelte",
3916
+ "check:svelte:ci",
3917
+ ...PRE_JOSH_SCRIPT_VALUES.keys()
3918
+ ]);
3919
+ function migrate_jf_value(value) {
3920
+ if (!value.startsWith(JF_PREFIX)) return value;
3921
+ return `${JOSH_PREFIX}${value.slice(JF_PREFIX.length)}`;
3922
+ }
3923
+ function migrate_script(key, value) {
3924
+ const migrated = migrate_jf_value(value);
3925
+ return key === PREINSTALL_KEY ? safe_chain_preinstall.migrate_preinstall(migrated) : migrated;
3926
+ }
3927
+ function apply_jf_migrations(scripts) {
3928
+ return Object.fromEntries(
3929
+ Object.entries(scripts).map(([key, value]) => [key, migrate_script(key, value)])
3930
+ );
3931
+ }
3932
+ function is_kit_written(key, value) {
3933
+ if (value.startsWith(JOSH_PREFIX) || value.startsWith(JF_PREFIX)) return true;
3934
+ return PRE_JOSH_SCRIPT_VALUES.get(key) === value;
3935
+ }
3936
+ function is_retired_script(key, value) {
3937
+ return RETIRED_MANAGED_SCRIPTS.has(key) && is_kit_written(key, value);
3938
+ }
3939
+ function remove_retired_scripts(scripts) {
3940
+ return Object.fromEntries(
3941
+ Object.entries(scripts).filter(([key, value]) => !is_retired_script(key, value))
3942
+ );
3943
+ }
3944
+
3945
+ // scripts/init/init-logic-package-key-order.ts
3946
+ var PACKAGE_JSON_KEY_ORDER = [
3947
+ "name",
3948
+ "version",
3949
+ "description",
3950
+ "keywords",
3951
+ "homepage",
3952
+ "bugs",
3953
+ "license",
3954
+ "author",
3955
+ "contributors",
3956
+ "funding",
3957
+ "files",
3958
+ "main",
3959
+ "browser",
3960
+ "exports",
3961
+ "imports",
3962
+ "bin",
3963
+ "man",
3964
+ "directories",
3965
+ "repository",
3966
+ "type",
3967
+ "types",
3968
+ "typings",
3969
+ "typesVersions",
3970
+ "publishConfig",
3971
+ "private",
3972
+ "scripts",
3973
+ "config",
3974
+ "dependencies",
3975
+ "devDependencies",
3976
+ "peerDependencies",
3977
+ "peerDependenciesMeta",
3978
+ "bundleDependencies",
3979
+ "bundledDependencies",
3980
+ "optionalDependencies",
3981
+ "overrides",
3982
+ "resolutions",
3983
+ "packageManager",
3984
+ "engines",
3985
+ "devEngines",
3986
+ "os",
3987
+ "cpu",
3988
+ "size-limit",
3989
+ "pnpm"
3990
+ ];
3991
+
3992
+ // scripts/init/kit-base-preset.ts
3993
+ var KIT_LEFTHOOK_PRESET = /@joshuafolkken\/[^/]+\/lefthook\//u;
3994
+ var KIT_CSPELL_PRESET = /@joshuafolkken\/[^/]+\/cspell(?:\/|$)/u;
3995
+ var KIT_TSCONFIG_PRESET = /@joshuafolkken\/[^/]+\/tsconfig\//u;
3996
+ var SVELTEKIT_PRESET = /(?<![\w-])sveltekit(?![\w-])/u;
3997
+ function has_match(entries, pattern) {
3998
+ return entries.some((entry) => pattern.test(entry));
3999
+ }
4000
+ function is_base_present(entries, subsystem_pattern) {
4001
+ return has_match(entries, subsystem_pattern) || has_match(entries, SVELTEKIT_PRESET);
4002
+ }
4003
+ function is_lefthook_base_present(entries) {
4004
+ return is_base_present(entries, KIT_LEFTHOOK_PRESET);
4005
+ }
4006
+ function is_cspell_base_present(entries) {
4007
+ return is_base_present(entries, KIT_CSPELL_PRESET);
4008
+ }
4009
+ function is_tsconfig_base_present(entries) {
4010
+ return is_base_present(entries, KIT_TSCONFIG_PRESET);
4011
+ }
4012
+ var kit_base_preset = {
4013
+ is_lefthook_base_present,
4014
+ is_cspell_base_present,
4015
+ is_tsconfig_base_present
4016
+ };
4017
+
4018
+ // scripts/init/tsconfig-preset-migration.ts
4019
+ import { existsSync as existsSync3 } from "node:fs";
2846
4020
  import path6 from "node:path";
4021
+ var LEGACY_PRESET_ENTRY = /@joshuafolkken\/[^/]+\/tsconfig\/[^/]+\.jsonc$/u;
4022
+ var LEGACY_SUFFIX = ".jsonc";
4023
+ var CURRENT_SUFFIX = ".json";
4024
+ var EXTENDS_FIELD = "extends";
4025
+ function is_migration_target_present(base_directory, entry) {
4026
+ return existsSync3(path6.resolve(base_directory, entry));
4027
+ }
4028
+ function migrate_entry(base_directory, entry) {
4029
+ if (!LEGACY_PRESET_ENTRY.test(entry)) return entry;
4030
+ const migrated = `${entry.slice(0, -LEGACY_SUFFIX.length)}${CURRENT_SUFFIX}`;
4031
+ return is_migration_target_present(base_directory, migrated) ? migrated : entry;
4032
+ }
4033
+ function migrate_extends_value(base_directory, raw) {
4034
+ if (typeof raw === "string") return migrate_entry(base_directory, raw);
4035
+ if (Array.isArray(raw)) {
4036
+ return string_array_schema.parse(raw).map((entry) => migrate_entry(base_directory, entry));
4037
+ }
4038
+ return raw;
4039
+ }
4040
+ function migrate_preset_paths(content, base_directory) {
4041
+ const parsed = parse_jsonc(content);
4042
+ const raw = parsed[EXTENDS_FIELD];
4043
+ const migrated = migrate_extends_value(base_directory, raw);
4044
+ if (JSON.stringify(migrated) === JSON.stringify(raw)) return content;
4045
+ return patch_json_key.set_json_key(content, EXTENDS_FIELD, migrated);
4046
+ }
4047
+ var tsconfig_preset_migration = {
4048
+ migrate_preset_paths
4049
+ };
4050
+
4051
+ // scripts/init/init-logic-json-merge.ts
4052
+ function merge_json_extends(content, entry) {
4053
+ return config_merge.patch_json_list_field(content, { field: EXTENDS_FIELD, ensure: [entry] });
4054
+ }
4055
+ function read_extends_entries(content) {
4056
+ const raw = parse_jsonc(content)[EXTENDS_FIELD];
4057
+ if (typeof raw === "string") return [raw];
4058
+ if (Array.isArray(raw)) return string_array_schema.parse(raw);
4059
+ return [];
4060
+ }
4061
+ function merge_tsconfig_extends(content, entry, base_directory) {
4062
+ const migrated = tsconfig_preset_migration.migrate_preset_paths(content, base_directory);
4063
+ if (kit_base_preset.is_tsconfig_base_present(read_extends_entries(migrated))) return migrated;
4064
+ return merge_json_extends(migrated, entry);
4065
+ }
4066
+ function extract_compiler_options(content) {
4067
+ const parsed = parse_jsonc(content);
4068
+ const raw = parsed["compilerOptions"];
4069
+ if (raw === void 0) return {};
4070
+ return json_object_schema.parse(raw);
4071
+ }
4072
+ function is_redundant_option(value, key, base_options) {
4073
+ if (!Object.hasOwn(base_options, key)) return false;
4074
+ return JSON.stringify(base_options[key]) === JSON.stringify(value);
4075
+ }
4076
+ var COMPILER_OPTIONS_FIELD = "compilerOptions";
4077
+ function drop_redundant_options(content, redundant) {
4078
+ let current = content;
4079
+ for (const key of redundant) {
4080
+ current = patch_json_key.remove_json_path(current, [COMPILER_OPTIONS_FIELD, key]);
4081
+ }
4082
+ return current;
4083
+ }
4084
+ function serialize_stripped(content, kept, redundant) {
4085
+ if (Object.keys(kept).length === 0) {
4086
+ return patch_json_key.remove_json_key(content, COMPILER_OPTIONS_FIELD);
4087
+ }
4088
+ return drop_redundant_options(content, redundant);
4089
+ }
4090
+ function redundant_option_keys(current, base_options) {
4091
+ return Object.entries(current).filter(([key, value]) => is_redundant_option(value, key, base_options)).map(([key]) => key);
4092
+ }
4093
+ function strip_redundant_compiler_options(content, base_options) {
4094
+ const raw = parse_jsonc(content)[COMPILER_OPTIONS_FIELD];
4095
+ if (raw === void 0) return content;
4096
+ const current = json_object_schema.parse(raw);
4097
+ const redundant = redundant_option_keys(current, base_options);
4098
+ if (redundant.length === 0) return content;
4099
+ const kept = Object.entries(current).filter(([key]) => !redundant.includes(key));
4100
+ return serialize_stripped(content, Object.fromEntries(kept), redundant);
4101
+ }
4102
+ function merge_json_array_field(content, key, values) {
4103
+ const parsed = parse_jsonc(content);
4104
+ const existing = Object.hasOwn(parsed, key) ? string_array_schema.parse(parsed[key]) : [];
4105
+ const to_add = values.filter((value) => !existing.includes(value));
4106
+ if (to_add.length === 0) return content;
4107
+ return patch_json_key.set_json_key(content, key, [...existing, ...to_add]);
4108
+ }
4109
+ function missing_entries(existing, additions) {
4110
+ return Object.entries(additions).filter(([key]) => !Object.hasOwn(existing, key));
4111
+ }
4112
+ function merge_owned_entries(current, update) {
4113
+ const current_object = json_object_schema.safeParse(current);
4114
+ const update_object = json_object_schema.safeParse(update);
4115
+ if (!current_object.success || !update_object.success) return void 0;
4116
+ const owned = current_object.data;
4117
+ const missing = missing_entries(owned, update_object.data);
4118
+ if (missing.length === 0) return void 0;
4119
+ return { ...owned, ...Object.fromEntries(missing) };
4120
+ }
4121
+ function collect_applicable_updates(parsed, updates) {
4122
+ const resolved = Object.entries(updates).map(([key, value]) => [
4123
+ key,
4124
+ Object.hasOwn(parsed, key) ? merge_owned_entries(parsed[key], value) : value
4125
+ ]);
4126
+ return Object.fromEntries(resolved.filter(([, merged]) => merged !== void 0));
4127
+ }
4128
+ function merge_json_object(content, updates) {
4129
+ const parsed = parse_jsonc(content);
4130
+ const applicable = collect_applicable_updates(parsed, updates);
4131
+ if (Object.keys(applicable).length === 0) return content;
4132
+ let current = content;
4133
+ for (const [key, value] of Object.entries(applicable)) {
4134
+ current = patch_json_key.set_json_key(current, key, value);
4135
+ }
4136
+ return current;
4137
+ }
4138
+ function serialize_package_json(value) {
4139
+ return json_format.format_package_json(value);
4140
+ }
4141
+ var SCRIPTS_PREPEND_KEYS = /* @__PURE__ */ new Set(["preinstall"]);
4142
+ function merge_package_scripts(content, scripts) {
4143
+ const parsed = parse_jsonc(content);
4144
+ const raw = parsed["scripts"];
4145
+ const existing = raw === void 0 ? {} : string_record_schema.parse(raw);
4146
+ const migrated = remove_retired_scripts(apply_jf_migrations(existing));
4147
+ const to_add = missing_entries(migrated, scripts);
4148
+ const did_migrate = JSON.stringify(migrated) !== JSON.stringify(existing);
4149
+ if (!did_migrate && to_add.length === 0) return content;
4150
+ const prepend = Object.fromEntries(to_add.filter(([k]) => SCRIPTS_PREPEND_KEYS.has(k)));
4151
+ const append = Object.fromEntries(to_add.filter(([k]) => !SCRIPTS_PREPEND_KEYS.has(k)));
4152
+ return serialize_package_json({ ...parsed, scripts: { ...prepend, ...migrated, ...append } });
4153
+ }
4154
+ function upgrade_safe_chain_preinstall(content) {
4155
+ const parsed = parse_jsonc(content);
4156
+ const raw = parsed["scripts"];
4157
+ if (raw === void 0) return content;
4158
+ const scripts = string_record_schema.parse(raw);
4159
+ const current = scripts["preinstall"];
4160
+ if (current === void 0) return content;
4161
+ const migrated = safe_chain_preinstall.migrate_preinstall(current);
4162
+ if (migrated === current) return content;
4163
+ return serialize_package_json({ ...parsed, scripts: { ...scripts, preinstall: migrated } });
4164
+ }
4165
+ function merge_development_dependencies(content, additions) {
4166
+ const parsed = parse_jsonc(content);
4167
+ const raw = parsed["devDependencies"];
4168
+ const existing = raw === void 0 ? {} : string_record_schema.parse(raw);
4169
+ const to_add = missing_entries(existing, additions);
4170
+ if (to_add.length === 0) return content;
4171
+ return serialize_package_json({
4172
+ ...parsed,
4173
+ devDependencies: { ...existing, ...Object.fromEntries(to_add) }
4174
+ });
4175
+ }
4176
+ function merge_package_manager(content, value) {
4177
+ if (value.length === 0) return content;
4178
+ const parsed = parse_jsonc(content);
4179
+ if ("packageManager" in parsed) return content;
4180
+ return serialize_package_json({ ...parsed, packageManager: value });
4181
+ }
4182
+ function merge_development_engines(content, value) {
4183
+ const parsed = parse_jsonc(content);
4184
+ if ("devEngines" in parsed) return content;
4185
+ return serialize_package_json({ ...parsed, devEngines: value });
4186
+ }
4187
+ function has_package_scripts_marker(content, marker) {
4188
+ const parsed = parse_jsonc(content);
4189
+ const raw = parsed["scripts"];
4190
+ if (raw === void 0) return false;
4191
+ const scripts = string_record_schema.parse(raw);
4192
+ return Object.values(scripts).some((cmd) => cmd.includes(marker));
4193
+ }
4194
+ function merge_package_script_suffix(content, key, cmd) {
4195
+ const parsed = parse_jsonc(content);
4196
+ const raw = parsed["scripts"];
4197
+ if (raw === void 0) return content;
4198
+ const scripts = string_record_schema.parse(raw);
4199
+ const existing = scripts[key];
4200
+ if (existing === void 0 || existing.includes(cmd)) return content;
4201
+ const updated_value = existing.trim().length === 0 ? cmd : `${existing} && ${cmd}`;
4202
+ return serialize_package_json({ ...parsed, scripts: { ...scripts, [key]: updated_value } });
4203
+ }
4204
+ function replace_in_package_script(content, key, from, to) {
4205
+ const parsed = parse_jsonc(content);
4206
+ const raw = parsed["scripts"];
4207
+ if (raw === void 0) return content;
4208
+ const scripts = string_record_schema.parse(raw);
4209
+ const existing = scripts[key];
4210
+ if (!existing?.includes(from)) return content;
4211
+ return serialize_package_json({
4212
+ ...parsed,
4213
+ // The replacer is a function so `to` is inserted verbatim: passed as a string, a `$&` or `$1`
4214
+ // inside it would be read as a substitution pattern rather than as the text it is.
4215
+ scripts: { ...scripts, [key]: existing.replace(from, () => to) }
4216
+ });
4217
+ }
4218
+ function remove_script_with_marker(content, key, marker) {
4219
+ const parsed = parse_jsonc(content);
4220
+ const raw = parsed["scripts"];
4221
+ if (raw === void 0) return content;
4222
+ const scripts = string_record_schema.parse(raw);
4223
+ if (!scripts[key]?.includes(marker)) return content;
4224
+ const rest = Object.fromEntries(Object.entries(scripts).filter(([k]) => k !== key));
4225
+ return serialize_package_json({ ...parsed, scripts: rest });
4226
+ }
4227
+ function sort_package_json_keys(content) {
4228
+ const parsed = parse_jsonc(content);
4229
+ const all_keys = Object.keys(parsed);
4230
+ const known = PACKAGE_JSON_KEY_ORDER.filter((k) => Object.hasOwn(parsed, k));
4231
+ const unknown = all_keys.filter((k) => !PACKAGE_JSON_KEY_ORDER.includes(k));
4232
+ const ordered = Object.fromEntries([...known, ...unknown].map((k) => [k, parsed[k]]));
4233
+ const serialized = serialize_package_json(ordered);
4234
+ const current = serialize_package_json(parsed);
4235
+ if (serialized === current) return content;
4236
+ return serialized;
4237
+ }
4238
+ var init_logic_json_merge = {
4239
+ merge_json_extends,
4240
+ merge_tsconfig_extends,
4241
+ extract_compiler_options,
4242
+ strip_redundant_compiler_options,
4243
+ merge_json_array_field,
4244
+ merge_json_object,
4245
+ merge_package_scripts,
4246
+ upgrade_safe_chain_preinstall,
4247
+ merge_package_script_suffix,
4248
+ replace_in_package_script,
4249
+ remove_script_with_marker,
4250
+ has_package_scripts_marker,
4251
+ merge_development_dependencies,
4252
+ merge_package_manager,
4253
+ merge_development_engines,
4254
+ sort_package_json_keys
4255
+ };
4256
+
4257
+ // scripts/init/kit-development-versions.ts
4258
+ import { readFileSync as readFileSync3 } from "node:fs";
4259
+ import { z as z11 } from "zod";
4260
+ var PACKAGE_JSON = "package.json";
4261
+ var kit_manifest_schema = z11.object({
4262
+ peerDependencies: z11.record(z11.string(), z11.string()).default({}),
4263
+ devDependencies: z11.record(z11.string(), z11.string())
4264
+ });
4265
+ function read_kit_manifest() {
4266
+ const content = readFileSync3(package_path(PACKAGE_JSON), "utf8");
4267
+ return kit_manifest_schema.parse(JSON.parse(content));
4268
+ }
4269
+ function versions_of(names) {
4270
+ const { devDependencies: versions } = read_kit_manifest();
4271
+ const entries = names.map((name) => {
4272
+ const version = versions[name];
4273
+ if (version === void 0) throw new Error(`Missing development version for ${name}`);
4274
+ return [name, version];
4275
+ });
4276
+ return Object.fromEntries(entries);
4277
+ }
4278
+ function peer_names() {
4279
+ return Object.keys(read_kit_manifest().peerDependencies);
4280
+ }
4281
+ var kit_development_versions = { peer_names, versions_of };
4282
+
4283
+ // scripts/init/init-logic-secretlint.ts
4284
+ var SECRETLINT_CONFIG_FILENAME = ".secretlintrc.json";
4285
+ var SECRETLINT_RULE_PRESET = "@secretlint/secretlint-rule-preset-recommend";
4286
+ var SECRETLINT_PACKAGES = ["secretlint", SECRETLINT_RULE_PRESET];
4287
+ function generate_secretlint_config() {
4288
+ const config = { rules: [{ id: SECRETLINT_RULE_PRESET }] };
4289
+ return `${JSON.stringify(config, void 0, " ")}
4290
+ `;
4291
+ }
4292
+ function get_secretlint_config_filename() {
4293
+ return SECRETLINT_CONFIG_FILENAME;
4294
+ }
4295
+ function merge_secretlint_development_deps(content) {
4296
+ return init_logic_json_merge.merge_development_dependencies(
4297
+ content,
4298
+ kit_development_versions.versions_of(SECRETLINT_PACKAGES)
4299
+ );
4300
+ }
4301
+ var init_logic_secretlint = {
4302
+ generate_secretlint_config,
4303
+ get_secretlint_config_filename,
4304
+ merge_secretlint_development_deps
4305
+ };
4306
+
4307
+ // scripts/init/init-logic-sonar.ts
4308
+ var SONAR_PROJECT_KEY_PLACEHOLDER = "{{PROJECT_KEY}}";
4309
+ var SONAR_ORGANIZATION_PLACEHOLDER = "{{ORGANIZATION}}";
4310
+ var SONAR_TEMPLATE_SRC = "templates/sonar-project.properties";
4311
+ var SONAR_TEMPLATE_DEST = "sonar-project.properties";
4312
+ var PROPERTY_LINE_PATTERN = /^([\w.]+)=/u;
4313
+ var MULTICRITERIA_KEY = "sonar.issue.ignore.multicriteria";
4314
+ var MULTICRITERIA_LINE_PATTERN = /^sonar\.issue\.ignore\.multicriteria=(.*)$/mu;
4315
+ function apply_sonar_template(content, project_key, organization) {
4316
+ return content.replaceAll(SONAR_PROJECT_KEY_PLACEHOLDER, () => project_key).replaceAll(SONAR_ORGANIZATION_PLACEHOLDER, () => organization);
4317
+ }
4318
+ function derive_sonar_identifiers(name_with_owner) {
4319
+ const [organization, repository, ...extra] = name_with_owner.trim().split("/");
4320
+ if (!organization || !repository || extra.length > 0) {
4321
+ throw new Error(`Invalid GitHub repository nameWithOwner: ${name_with_owner}`);
4322
+ }
4323
+ return {
4324
+ organization,
4325
+ project_key: `${organization}_${repository}`
4326
+ };
4327
+ }
4328
+ function get_sonar_template_source() {
4329
+ return SONAR_TEMPLATE_SRC;
4330
+ }
4331
+ function get_sonar_template_destination() {
4332
+ return SONAR_TEMPLATE_DEST;
4333
+ }
4334
+ function extract_properties_keys(content) {
4335
+ const keys = /* @__PURE__ */ new Set();
4336
+ for (const line of content.split("\n")) {
4337
+ const match = PROPERTY_LINE_PATTERN.exec(line);
4338
+ if (match?.[1] !== void 0) keys.add(match[1]);
4339
+ }
4340
+ return keys;
4341
+ }
4342
+ function get_multicriteria_value(content) {
4343
+ return MULTICRITERIA_LINE_PATTERN.exec(content)?.[1];
4344
+ }
4345
+ function get_multicriteria_ids(content) {
4346
+ return (get_multicriteria_value(content) ?? "").split(",").map((id) => id.trim()).filter(Boolean);
4347
+ }
4348
+ function get_property_value(content, key) {
4349
+ return content.split("\n").find((line) => line.startsWith(`${key}=`))?.slice(key.length + 1);
4350
+ }
4351
+ function has_criterion_conflict(existing, template, id) {
4352
+ return ["ruleKey", "resourceKey"].some((field) => {
4353
+ const key = `${MULTICRITERIA_KEY}.${id}.${field}`;
4354
+ const existing_value = get_property_value(existing, key);
4355
+ const template_value = get_property_value(template, key);
4356
+ return existing_value !== void 0 && template_value !== void 0 && existing_value !== template_value;
4357
+ });
4358
+ }
4359
+ function criterion_matches(existing, template, existing_id, template_id) {
4360
+ const template_prefix = `${MULTICRITERIA_KEY}.${template_id}`;
4361
+ const existing_prefix = `${MULTICRITERIA_KEY}.${existing_id}`;
4362
+ const rule = get_property_value(template, `${template_prefix}.ruleKey`);
4363
+ const resource = get_property_value(template, `${template_prefix}.resourceKey`);
4364
+ if (rule === void 0 || resource === void 0) return false;
4365
+ return rule === get_property_value(existing, `${existing_prefix}.ruleKey`) && resource === get_property_value(existing, `${existing_prefix}.resourceKey`);
4366
+ }
4367
+ function allocate_criterion_id(used_ids) {
4368
+ let next_index = 1;
4369
+ for (const id of used_ids) {
4370
+ const numeric_id = /^e(\d+)$/u.exec(id)?.[1];
4371
+ if (numeric_id !== void 0) next_index = Math.max(next_index, Number(numeric_id) + 1);
4372
+ }
4373
+ return `e${next_index.toString()}`;
4374
+ }
4375
+ function rename_criterion(template, id, replacement_id) {
4376
+ const ids = get_multicriteria_ids(template).map(
4377
+ (entry) => entry === id ? replacement_id : entry
4378
+ );
4379
+ const updated_list = template.replace(
4380
+ MULTICRITERIA_LINE_PATTERN,
4381
+ () => `${MULTICRITERIA_KEY}=${ids.join(",")}`
4382
+ );
4383
+ return updated_list.replaceAll(
4384
+ `${MULTICRITERIA_KEY}.${id}.`,
4385
+ () => `${MULTICRITERIA_KEY}.${replacement_id}.`
4386
+ );
4387
+ }
4388
+ function find_matching_criterion(existing, template, ids, id) {
4389
+ return ids.find((candidate) => criterion_matches(existing, template, candidate, id));
4390
+ }
4391
+ function resolve_multicriteria_conflicts(existing, template) {
4392
+ const existing_ids = get_multicriteria_ids(existing);
4393
+ const template_ids = get_multicriteria_ids(template);
4394
+ const reusable_ids = existing_ids.filter((id) => !template_ids.includes(id));
4395
+ let resolved = template;
4396
+ for (const id of template_ids) {
4397
+ if (!existing_ids.includes(id) || !has_criterion_conflict(existing, resolved, id)) continue;
4398
+ const matching_id = find_matching_criterion(existing, resolved, reusable_ids, id);
4399
+ const replacement_id = matching_id ?? allocate_criterion_id(/* @__PURE__ */ new Set([...existing_ids, ...get_multicriteria_ids(resolved)]));
4400
+ resolved = rename_criterion(resolved, id, replacement_id);
4401
+ }
4402
+ return resolved;
4403
+ }
4404
+ function merge_multicriteria_ids(existing, template_content) {
4405
+ const existing_value = get_multicriteria_value(existing);
4406
+ if (existing_value === void 0) return existing;
4407
+ const template_value = get_multicriteria_value(template_content);
4408
+ if (template_value === void 0) return existing;
4409
+ const existing_ids = get_multicriteria_ids(existing);
4410
+ const template_ids = get_multicriteria_ids(template_content);
4411
+ const merged_ids = [.../* @__PURE__ */ new Set([...existing_ids, ...template_ids])];
4412
+ if (merged_ids.join(",") === existing_value) return existing;
4413
+ return existing.replace(
4414
+ MULTICRITERIA_LINE_PATTERN,
4415
+ () => `${MULTICRITERIA_KEY}=${merged_ids.join(",")}`
4416
+ );
4417
+ }
4418
+ function merge_sonar_properties(existing, template_content) {
4419
+ const resolved_template = resolve_multicriteria_conflicts(existing, template_content);
4420
+ const merged_existing = merge_multicriteria_ids(existing, resolved_template);
4421
+ const existing_keys = extract_properties_keys(merged_existing);
4422
+ const lines_to_add = resolved_template.split("\n").filter((line) => {
4423
+ const key = PROPERTY_LINE_PATTERN.exec(line)?.[1];
4424
+ return key !== void 0 && !existing_keys.has(key);
4425
+ });
4426
+ if (lines_to_add.length === 0) return merged_existing;
4427
+ const normalized2 = merged_existing.endsWith("\n") ? merged_existing : `${merged_existing}
4428
+ `;
4429
+ return `${normalized2}
4430
+ ${lines_to_add.join("\n")}
4431
+ `;
4432
+ }
4433
+ var init_logic_sonar = {
4434
+ apply_sonar_template,
4435
+ derive_sonar_identifiers,
4436
+ get_sonar_template_source,
4437
+ get_sonar_template_destination,
4438
+ merge_sonar_properties
4439
+ };
4440
+
4441
+ // scripts/init/init-logic-templates.ts
4442
+ import { existsSync as existsSync4, readFileSync as readFileSync4 } from "node:fs";
4443
+ import path7 from "node:path";
4444
+ var ESLINT_VANILLA = `import { create_vanilla_config } from '@joshuafolkken/kit/eslint/vanilla'
4445
+
4446
+ export default create_vanilla_config({
4447
+ gitignore_path: new URL('./.gitignore', import.meta.url),
4448
+ tsconfig_root_dir: import.meta.dirname,
4449
+ })
4450
+ `;
4451
+ var DEFAULT_TAILWIND_STYLESHEET = "./src/routes/layout.css";
4452
+ var TAILWIND_STYLESHEET_PATTERN = /tailwindStylesheet"?:\s*['"]([^'"]+)['"]/u;
4453
+ var KIT_ESLINT_IMPORT_MARKER = "@joshuafolkken/kit/eslint/";
4454
+ var VANILLA_ESLINT_MARKERS = [
4455
+ "js.configs.recommended",
4456
+ "ts.configs.recommended",
4457
+ "svelte.configs.recommended"
4458
+ ];
4459
+ var RULES_BLOCK_PATTERN = /rules\s*:\s*\{/gu;
4460
+ var RULES_INDENT_DEPTH = 3;
4461
+ var RULES_INDENT = " ".repeat(RULES_INDENT_DEPTH);
4462
+ var PLAYWRIGHT_TEMPLATE_PATH = package_path("playwright.config.ts");
4463
+ var VANILLA_WITH_RULES_TPL = `import { create_vanilla_config } from '@joshuafolkken/kit/eslint/vanilla'
4464
+
4465
+ export default [
4466
+ ...create_vanilla_config({
4467
+ gitignore_path: new URL('./.gitignore', import.meta.url),
4468
+ tsconfig_root_dir: import.meta.dirname,
4469
+ }),
4470
+ {
4471
+ rules: {
4472
+ $RULES
4473
+ },
4474
+ },
4475
+ ]
4476
+ `;
4477
+ var RULES_PLACEHOLDER = "$RULES";
4478
+ var NOT_FOUND = -1;
4479
+ function generate_eslint_config() {
4480
+ return ESLINT_VANILLA;
4481
+ }
4482
+ function is_vanilla_eslint_config(existing) {
4483
+ if (existing.includes(KIT_ESLINT_IMPORT_MARKER)) return false;
4484
+ return VANILLA_ESLINT_MARKERS.some((marker) => existing.includes(marker));
4485
+ }
4486
+ function update_brace_depth(char, depth) {
4487
+ if (char === "{") return depth + 1;
4488
+ if (char === "}") return depth - 1;
4489
+ return depth;
4490
+ }
4491
+ function find_matching_close_brace(source, open_index) {
4492
+ let depth = 0;
4493
+ for (let index = open_index; index < source.length; index += 1) {
4494
+ depth = update_brace_depth(source[index], depth);
4495
+ if (depth === 0 && source[index] === "}") return index;
4496
+ }
4497
+ return NOT_FOUND;
4498
+ }
4499
+ function extract_block_from_open(source, open_index) {
4500
+ const close = find_matching_close_brace(source, open_index);
4501
+ if (close === NOT_FOUND) return void 0;
4502
+ const inner = source.slice(open_index + 1, close).trim();
4503
+ return inner.length > 0 ? inner : void 0;
4504
+ }
4505
+ function extract_rules_inner_blocks(existing) {
4506
+ const blocks = [];
4507
+ for (const match of existing.matchAll(RULES_BLOCK_PATTERN)) {
4508
+ const open = match.index + match[0].length - 1;
4509
+ const inner = extract_block_from_open(existing, open);
4510
+ if (inner !== void 0) blocks.push(inner);
4511
+ }
4512
+ return blocks;
4513
+ }
4514
+ function indent_block(text, indent) {
4515
+ return text.split("\n").map((line) => line.length === 0 ? line : `${indent}${line.trimStart()}`).join("\n");
4516
+ }
4517
+ function apply_rules_template(rules_body) {
4518
+ const rules_block = indent_block(rules_body, RULES_INDENT);
4519
+ return VANILLA_WITH_RULES_TPL.replace(RULES_PLACEHOLDER, () => rules_block);
4520
+ }
4521
+ function merge_eslint_config(existing) {
4522
+ if (!is_vanilla_eslint_config(existing)) return existing;
4523
+ const rules_blocks = extract_rules_inner_blocks(existing);
4524
+ if (rules_blocks.length === 0) return generate_eslint_config();
4525
+ return apply_rules_template(rules_blocks.join(",\n"));
4526
+ }
4527
+ function detect_tailwind_stylesheet(project_root2) {
4528
+ return existsSync4(path7.join(project_root2, DEFAULT_TAILWIND_STYLESHEET)) ? DEFAULT_TAILWIND_STYLESHEET : void 0;
4529
+ }
4530
+ function generate_prettier_config(stylesheet) {
4531
+ const stylesheet_line = stylesheet === void 0 ? "" : ` tailwindStylesheet: '${stylesheet}',
4532
+ `;
4533
+ return `import { config } from '@joshuafolkken/kit/prettier'
4534
+
4535
+ export default {
4536
+ ...config,
4537
+ ${stylesheet_line}}
4538
+ `;
4539
+ }
4540
+ function existing_stylesheet(existing, project_root2) {
4541
+ const named = TAILWIND_STYLESHEET_PATTERN.exec(existing)?.[1];
4542
+ return named !== void 0 && existsSync4(path7.resolve(project_root2, named)) ? named : void 0;
4543
+ }
4544
+ function merge_prettier_config(existing, project_root2) {
4545
+ const stylesheet = existing_stylesheet(existing, project_root2) ?? detect_tailwind_stylesheet(project_root2);
4546
+ return generate_prettier_config(stylesheet);
4547
+ }
4548
+ function generate_playwright_config() {
4549
+ return readFileSync4(PLAYWRIGHT_TEMPLATE_PATH, "utf8");
4550
+ }
4551
+ var init_logic_templates = {
4552
+ generate_eslint_config,
4553
+ merge_eslint_config,
4554
+ detect_tailwind_stylesheet,
4555
+ generate_prettier_config,
4556
+ merge_prettier_config,
4557
+ generate_playwright_config
4558
+ };
4559
+
4560
+ // scripts/init/init-logic-toolchain.ts
4561
+ var CONSUMER_RESOLVED_TOOLS = [
4562
+ "eslint",
4563
+ "prettier",
4564
+ "typescript",
4565
+ "@playwright/test",
4566
+ "@ianvs/prettier-plugin-sort-imports",
4567
+ "prettier-plugin-svelte",
4568
+ "prettier-plugin-tailwindcss",
4569
+ "cspell",
4570
+ "@types/node"
4571
+ ];
4572
+ var LEFTHOOK_DEVELOPMENT_DEPENDENCY = "lefthook";
4573
+ var DECLARING_FIELDS = [
4574
+ "dependencies",
4575
+ "devDependencies",
4576
+ "peerDependencies",
4577
+ "optionalDependencies"
4578
+ ];
4579
+ function consumer_resolved_names(has_git2) {
4580
+ return has_git2 ? [...CONSUMER_RESOLVED_TOOLS, LEFTHOOK_DEVELOPMENT_DEPENDENCY] : CONSUMER_RESOLVED_TOOLS;
4581
+ }
4582
+ function get_toolchain_development_dependencies(has_git2) {
4583
+ return kit_development_versions.versions_of([
4584
+ ...kit_development_versions.peer_names(),
4585
+ ...consumer_resolved_names(has_git2)
4586
+ ]);
4587
+ }
4588
+ function is_declared(manifest, name) {
4589
+ return DECLARING_FIELDS.some((field) => {
4590
+ const dependencies = manifest[field];
4591
+ return json_value.is_record(dependencies) && Object.hasOwn(dependencies, name);
4592
+ });
4593
+ }
4594
+ function merge_consumer_resolved_development_deps(content, has_git2) {
4595
+ const manifest = parse_jsonc(content);
4596
+ const missing = consumer_resolved_names(has_git2).filter((name) => !is_declared(manifest, name));
4597
+ return init_logic_json_merge.merge_development_dependencies(
4598
+ content,
4599
+ kit_development_versions.versions_of(missing)
4600
+ );
4601
+ }
4602
+ var init_logic_toolchain = {
4603
+ consumer_resolved_names,
4604
+ get_toolchain_development_dependencies,
4605
+ merge_consumer_resolved_development_deps
4606
+ };
4607
+
4608
+ // scripts/init/init-logic-workspace.ts
4609
+ function extract_yaml_top_level_keys(content) {
4610
+ return content.split("\n").flatMap((line) => {
4611
+ const key = /^([a-zA-Z][a-zA-Z0-9_-]*):/u.exec(line)?.[1];
4612
+ return key ?? [];
4613
+ });
4614
+ }
4615
+ function extract_yaml_block(content, key) {
4616
+ const pattern = new RegExp(String.raw`(^${key}:[^\n]*\n(?:(?:[ \t][^\n]*|)\n)*)`, "mu");
4617
+ return pattern.exec(content)?.[1]?.trimEnd() ?? "";
4618
+ }
4619
+ function append_user_blocks(base, user_keys, existing) {
4620
+ const user_blocks = user_keys.map((k) => extract_yaml_block(existing, k)).filter(Boolean).join("\n");
4621
+ const normalized2 = base.endsWith("\n") ? base : `${base}
4622
+ `;
4623
+ return `${normalized2}
4624
+ ${user_blocks}
4625
+ `;
4626
+ }
4627
+ var DEPRECATED_KEYS = /* @__PURE__ */ new Set(["onlyBuiltDependencies"]);
4628
+ function remove_deprecated_yaml_key(content, key) {
4629
+ const block = extract_yaml_block(content, key);
4630
+ if (block.length === 0) return content;
4631
+ const removed = content.replaceAll(`${block}
4632
+ `, "");
4633
+ return removed.replaceAll(/\n{3,}/gu, "\n\n");
4634
+ }
4635
+ function remove_deprecated_yaml_keys(content) {
4636
+ let result = content;
4637
+ for (const key of DEPRECATED_KEYS) {
4638
+ result = remove_deprecated_yaml_key(result, key);
4639
+ }
4640
+ return `${result.trimEnd()}
4641
+ `;
4642
+ }
4643
+ var BUILD_PLACEHOLDER_PATTERN = /^([ \t]+)([^\s:#][^:#]*): set this to true or false$/gmu;
4644
+ var TEMPLATE_BUILD_PATTERN = /^[ \t]+(?<key>[^\s:#][^:#]*):[ \t]*(?<value>true|false)\b/u;
4645
+ function unquote(key) {
4646
+ return key.trim().replaceAll(/^['"]|['"]$/gu, "");
4647
+ }
4648
+ function template_build_values(template) {
4649
+ const lines = extract_yaml_block(template, "allowBuilds").split("\n");
4650
+ return new Map(
4651
+ lines.flatMap((line) => {
4652
+ const { key, value } = TEMPLATE_BUILD_PATTERN.exec(line)?.groups ?? {};
4653
+ return key && value ? [[unquote(key), value]] : [];
4654
+ })
4655
+ );
4656
+ }
4657
+ function answer_build_placeholders(existing, template) {
4658
+ const values = template_build_values(template);
4659
+ return existing.replaceAll(BUILD_PLACEHOLDER_PATTERN, (line, indent, key) => {
4660
+ const value = values.get(unquote(key));
4661
+ return value === void 0 ? line : `${indent}${key}: ${value}`;
4662
+ });
4663
+ }
4664
+ var BUILD_ENTRY_KEY_PATTERN = /^[ \t]+(?<key>[^\s:#][^:#]*):/u;
4665
+ function build_entry_key(line) {
4666
+ const key = BUILD_ENTRY_KEY_PATTERN.exec(line)?.groups?.["key"];
4667
+ return key === void 0 ? void 0 : unquote(key);
4668
+ }
4669
+ function build_entry_keys(block) {
4670
+ return new Set(block.split("\n").flatMap((line) => build_entry_key(line) ?? []));
4671
+ }
4672
+ var BLOCK_MAPPING_HEADER_PATTERN = /^allowBuilds:[ \t]*(?:#[^\n]*)?(?:\n|$)/u;
4673
+ var LEADING_INDENT_PATTERN = /^[ \t]+/u;
4674
+ function block_entry_indent(block) {
4675
+ const entry = block.split("\n").find((line) => build_entry_key(line) !== void 0);
4676
+ return entry === void 0 ? void 0 : LEADING_INDENT_PATTERN.exec(entry)?.[0];
4677
+ }
4678
+ function reindent(line, indent) {
4679
+ return indent === void 0 ? line : line.replace(LEADING_INDENT_PATTERN, () => indent);
4680
+ }
4681
+ function add_missing_build_entries(existing, template) {
4682
+ const block = extract_yaml_block(existing, "allowBuilds");
4683
+ if (!BLOCK_MAPPING_HEADER_PATTERN.test(block)) return existing;
4684
+ const present = build_entry_keys(block);
4685
+ const indent = block_entry_indent(block);
4686
+ const missing = extract_yaml_block(template, "allowBuilds").split("\n").filter((line) => {
4687
+ const key = build_entry_key(line);
4688
+ return key !== void 0 && !present.has(key);
4689
+ }).map((line) => reindent(line, indent));
4690
+ if (missing.length === 0) return existing;
4691
+ return existing.replace(block, () => [block, ...missing].join("\n"));
4692
+ }
4693
+ var MOVED_NPMRC_SETTINGS = [
4694
+ { npmrc_key: "minimum-release-age", workspace_key: "minimumReleaseAge", value_pattern: /^\d+$/u },
4695
+ { npmrc_key: "engine-strict", workspace_key: "engineStrict", value_pattern: /^(?:true|false)$/u }
4696
+ ];
4697
+ function npmrc_value(npmrc, key) {
4698
+ const pattern = new RegExp(String.raw`^[ \t]*${key}[ \t]*=[ \t]*(\S+)[ \t]*$`, "gmu");
4699
+ return [...npmrc.matchAll(pattern)].at(-1)?.[1];
4700
+ }
4701
+ function carry_npmrc_setting(template, npmrc, setting) {
4702
+ const value = npmrc_value(npmrc, setting.npmrc_key);
4703
+ if (value === void 0 || !setting.value_pattern.test(value)) return template;
4704
+ const line_pattern = new RegExp(`^${setting.workspace_key}:.*$`, "mu");
4705
+ return template.replace(line_pattern, () => `${setting.workspace_key}: ${value}`);
4706
+ }
4707
+ function carry_npmrc_settings(template, npmrc) {
4708
+ let result = template;
4709
+ for (const setting of MOVED_NPMRC_SETTINGS) {
4710
+ result = carry_npmrc_setting(result, npmrc, setting);
4711
+ }
4712
+ return result;
4713
+ }
4714
+ function merge_workspace_yaml(existing, template) {
4715
+ if (!existing.trim()) return template;
4716
+ const normalized2 = existing.endsWith("\n") ? existing : `${existing}
4717
+ `;
4718
+ const answered = answer_build_placeholders(remove_deprecated_yaml_keys(normalized2), template);
4719
+ const cleaned = add_missing_build_entries(answered, template);
4720
+ if (!cleaned.trim()) return template;
4721
+ const existing_keys = new Set(extract_yaml_top_level_keys(cleaned));
4722
+ const new_keys = extract_yaml_top_level_keys(template).filter((k) => !existing_keys.has(k));
4723
+ if (new_keys.length === 0) return cleaned;
4724
+ return append_user_blocks(cleaned, new_keys, template);
4725
+ }
4726
+ var init_logic_workspace = { carry_npmrc_settings, merge_workspace_yaml, template_build_values };
4727
+
4728
+ // scripts/init/init-logic-yaml-merge.ts
4729
+ var CSPELL_IMPORT_FIELD = "import";
4730
+ var LEFTHOOK_EXTENDS_FIELD = "extends";
4731
+ var CSPELL_IMPORT_POSITION = { after: "version" };
4732
+ var CSPELL_QUOTE_STYLE = "double";
4733
+ function merge_yaml_list_entry(content, key, value) {
4734
+ return config_merge.patch_yaml_list_field(content, {
4735
+ field: key,
4736
+ ensure: [value],
4737
+ position: "front"
4738
+ });
4739
+ }
4740
+ function merge_lefthook_extends(content, value) {
4741
+ const entries = config_merge.read_yaml_list_field(content, LEFTHOOK_EXTENDS_FIELD);
4742
+ if (kit_base_preset.is_lefthook_base_present(entries)) return content;
4743
+ return merge_yaml_list_entry(content, LEFTHOOK_EXTENDS_FIELD, value);
4744
+ }
4745
+ function merge_cspell_import(content, value) {
4746
+ const entries = config_merge.read_yaml_list_field(content, CSPELL_IMPORT_FIELD);
4747
+ if (kit_base_preset.is_cspell_base_present(entries)) return content;
4748
+ return config_merge.patch_yaml_list_field(content, {
4749
+ field: CSPELL_IMPORT_FIELD,
4750
+ ensure: [value],
4751
+ position: CSPELL_IMPORT_POSITION,
4752
+ quote_style: CSPELL_QUOTE_STYLE
4753
+ });
4754
+ }
4755
+ var init_logic_yaml_merge = {
4756
+ merge_yaml_list_entry,
4757
+ merge_lefthook_extends,
4758
+ merge_cspell_import
4759
+ };
4760
+
4761
+ // scripts/init/init-logic.ts
4762
+ var DEV_ENGINES_VALUE = {
4763
+ packageManager: { name: "pnpm", version: ">=12.1.0", onFail: "download" }
4764
+ };
4765
+ var LEGACY_NPMRC_LINES = /* @__PURE__ */ new Set([
4766
+ "engine-strict=true",
4767
+ "minimum-release-age=1440",
4768
+ "confirmModulesPurge=false",
4769
+ "lockfile-include-tarball-url=true"
4770
+ ]);
4771
+ var CSPELL_IMPORT = "@joshuafolkken/kit/cspell";
4772
+ var LEFTHOOK_INSTALL_CMD = "lefthook install";
4773
+ var { SAFE_CHAIN_CMD: SAFE_CHAIN_CMD2 } = safe_chain_preinstall;
4774
+ var FIX_GH_PACKAGES_CMD = "tsx node_modules/@joshuafolkken/kit/scripts/gh/fix-gh-packages.ts";
4775
+ var FIX_GH_PACKAGES_MARKER = "fix-gh-packages";
4776
+ var PREPARE_KEY = "prepare";
4777
+ var LEGACY_POSTINSTALL_KEY = "postinstall";
4778
+ var HOOK_INSTALL_WARNING = "lefthook install failed: git hooks are NOT installed. A set core.hooksPath is the usual cause. See https://github.com/joshuafolkken/kit/blob/main/docs/init.md#corehookspath-stops-lefthook-installing-anything";
4779
+ var LEFTHOOK_BINARY_GUARD = "command -v lefthook >/dev/null 2>&1";
4780
+ var GUARDED_LEFTHOOK_CMD = `${LEFTHOOK_BINARY_GUARD} && { ${LEFTHOOK_INSTALL_CMD} || echo '${HOOK_INSTALL_WARNING}' >&2; }`;
4781
+ var LEGACY_GUARDED_LEFTHOOK_CMD = `${LEFTHOOK_BINARY_GUARD} && ${LEFTHOOK_INSTALL_CMD}`;
4782
+ var GUARDED_FIX_GH_PACKAGES_CMD = `command -v tsx >/dev/null 2>&1 && ${FIX_GH_PACKAGES_CMD}`;
4783
+ var PREPARE_CMD = `(${GUARDED_LEFTHOOK_CMD} || true) && (${GUARDED_FIX_GH_PACKAGES_CMD} || true)`;
4784
+ var AI_COPY_FILES = [
4785
+ "AGENTS.md",
4786
+ "GEMINI.md",
4787
+ "CODE_OF_CONDUCT.md",
4788
+ ".cursorrules",
4789
+ ".coderabbit.yaml",
4790
+ ".gitattributes",
4791
+ ".mcp.json",
4792
+ ".ncurc.json",
4793
+ ".prettierignore",
4794
+ "SECURITY.md",
4795
+ "pnpm-workspace.yaml",
4796
+ "tsconfig.sonar.json",
4797
+ ".github/workflows/auto-tag.yml",
4798
+ ".github/workflows/production.yml",
4799
+ ".github/workflows/sonar-qube.yml",
4800
+ ".github/workflows/pr-classification.yml",
4801
+ // Called by `ci.yml` and `pr-classification.yml` as `uses: ./.github/actions/setup-pnpm`; without
4802
+ // it the consumer's jobs cannot resolve the action and their checks fail.
4803
+ ".github/actions/setup-pnpm/action.yml",
4804
+ // The one place the workflows' Node.js version is written, called by every distributed workflow
4805
+ // that sets Node.js up.
4806
+ ".github/actions/setup-node/action.yml",
4807
+ ".github/pull_request_template.md",
4808
+ ".github/release.yml",
4809
+ ".github/dependabot.yml",
4810
+ ".claude/settings.json",
4811
+ ".codex/config.toml",
4812
+ ".codex/hooks.json"
4813
+ ];
4814
+ var AI_COPY_FILE_MAPPINGS = [
4815
+ { src: "templates/workflows/ci.yml", dest: ".github/workflows/ci.yml" },
4816
+ // The counterpart to the distributed `.github/dependabot.yml`: without it a consumer receives
4817
+ // the machinery that opens Dependabot pull requests and none of the machinery that closes them,
4818
+ // so every github-actions bump sits green and unmerged.
4819
+ {
4820
+ src: "templates/workflows/dependabot-auto-merge.yml",
4821
+ dest: ".github/workflows/dependabot-auto-merge.yml"
4822
+ },
4823
+ // A template rather than a copy of kit's own file: kit releases from its publish.yml, so the file
4824
+ // must not run in kit as well.
4825
+ { src: "templates/workflows/github-release.yml", dest: ".github/workflows/github-release.yml" }
4826
+ ];
4827
+ var AI_COPY_DIRECTORIES = [];
4828
+ var LEFTHOOK_EXTENDS = "node_modules/@joshuafolkken/kit/lefthook/vanilla.yml";
4829
+ var TSCONFIG_EXTENDS = "./node_modules/@joshuafolkken/kit/tsconfig/base.json";
4830
+ var TSCONFIG_PRESET_FILENAME = "base.json";
4831
+ var TSCONFIG_EXCLUDE_FIELD = "exclude";
4832
+ var TSCONFIG_GENERATED_OUTPUT_EXCLUDE = [
4833
+ "node_modules",
4834
+ "build",
4835
+ "dist",
4836
+ "playwright-report",
4837
+ "test-results"
4838
+ ];
4839
+ var TSCONFIG_SVELTEKIT_EXCLUDE = [
4840
+ "src/service-worker.js",
4841
+ "src/service-worker/**/*.js",
4842
+ "src/service-worker.ts",
4843
+ "src/service-worker/**/*.ts",
4844
+ "src/service-worker.d.ts",
4845
+ "src/service-worker/**/*.d.ts"
4846
+ ];
4847
+ var TSCONFIG_EXCLUDE = [
4848
+ ...TSCONFIG_GENERATED_OUTPUT_EXCLUDE,
4849
+ ...TSCONFIG_SVELTEKIT_EXCLUDE
4850
+ ];
4851
+ var VSCODE_EXTENSIONS_FILENAME = "extensions.json";
4852
+ var VSCODE_SETTINGS_FILENAME = "settings.json";
4853
+ var KIT_ONLY_VSCODE_SETTINGS_KEYS = /* @__PURE__ */ new Set([
4854
+ "sonarlint.connectedMode.project"
4855
+ ]);
4856
+ var SUGGESTED_SCRIPTS_COMMON = {
4857
+ preinstall: SAFE_CHAIN_CMD2,
4858
+ prepare: PREPARE_CMD,
4859
+ josh: "josh"
4860
+ };
4861
+ function generate_tsconfig() {
4862
+ return json_format.format_json({
4863
+ extends: TSCONFIG_EXTENDS,
4864
+ compilerOptions: { types: ["node"] },
4865
+ [TSCONFIG_EXCLUDE_FIELD]: TSCONFIG_EXCLUDE
4866
+ });
4867
+ }
4868
+ function merge_tsconfig_exclude(content) {
4869
+ const field = TSCONFIG_EXCLUDE_FIELD;
4870
+ return init_logic_json_merge.merge_json_array_field(content, field, TSCONFIG_EXCLUDE);
4871
+ }
4872
+ function generate_lefthook_config() {
4873
+ return `extends:
4874
+ - ${LEFTHOOK_EXTENDS}
4875
+ `;
4876
+ }
4877
+ function generate_cspell_config() {
4878
+ return `version: "0.2"
4879
+ import:
4880
+ - "${CSPELL_IMPORT}"
4881
+ words: []
4882
+ ignorePaths: []
4883
+ `;
4884
+ }
4885
+ function append_missing_lines(existing, missing) {
4886
+ if (missing.length === 0) return existing;
4887
+ const prefix = existing.length > 0 && !existing.endsWith("\n") ? `${existing}
4888
+ ` : existing;
4889
+ return `${prefix}${missing.join("\n")}
4890
+ `;
4891
+ }
4892
+ function merge_npmrc(content) {
4893
+ const lines = content.split("\n");
4894
+ const kept = lines.filter((line) => !LEGACY_NPMRC_LINES.has(line.trim()));
4895
+ return kept.length === lines.length ? content : kept.join("\n");
4896
+ }
4897
+ function is_gitignore_pattern(line) {
4898
+ const trimmed = line.trim();
4899
+ return trimmed.length > 0 && !trimmed.startsWith("#");
4900
+ }
4901
+ function merge_gitignore(existing, template) {
4902
+ const existing_lines = new Set(existing.split("\n"));
4903
+ const missing = template.split("\n").filter((line) => is_gitignore_pattern(line) && !existing_lines.has(line));
4904
+ return append_missing_lines(existing, missing);
4905
+ }
4906
+ function get_tsconfig_extends_entry() {
4907
+ return TSCONFIG_EXTENDS;
4908
+ }
4909
+ function get_tsconfig_preset_filename() {
4910
+ return TSCONFIG_PRESET_FILENAME;
4911
+ }
4912
+ function get_tsconfig_exclude_entries() {
4913
+ return TSCONFIG_EXCLUDE;
4914
+ }
4915
+ function get_lefthook_extends_value() {
4916
+ return LEFTHOOK_EXTENDS;
4917
+ }
4918
+ function get_cspell_import_value() {
4919
+ return CSPELL_IMPORT;
4920
+ }
4921
+ function get_vscode_settings_filename() {
4922
+ return VSCODE_SETTINGS_FILENAME;
4923
+ }
4924
+ function strip_kit_only_vscode_settings(settings) {
4925
+ const entries = Object.entries(settings).filter(
4926
+ ([key]) => !KIT_ONLY_VSCODE_SETTINGS_KEYS.has(key)
4927
+ );
4928
+ return Object.fromEntries(entries);
4929
+ }
4930
+ function strip_kit_only_vscode_settings_content(raw) {
4931
+ const parsed = vscode_settings_schema.parse(JSON.parse(raw));
4932
+ const stripped = strip_kit_only_vscode_settings(parsed);
4933
+ if (Object.keys(stripped).length === Object.keys(parsed).length) return raw;
4934
+ return json_format.format_json(stripped);
4935
+ }
4936
+ function get_development_engines_value() {
4937
+ return DEV_ENGINES_VALUE;
4938
+ }
4939
+ function get_ai_copy_files() {
4940
+ return AI_COPY_FILES;
4941
+ }
4942
+ function get_ai_copy_file_mappings() {
4943
+ return AI_COPY_FILE_MAPPINGS;
4944
+ }
4945
+ function get_ai_copy_directories() {
4946
+ return AI_COPY_DIRECTORIES;
4947
+ }
4948
+ function get_suggested_scripts() {
4949
+ return SUGGESTED_SCRIPTS_COMMON;
4950
+ }
4951
+ function get_suggested_scripts_for_content(content) {
4952
+ const scripts = get_suggested_scripts();
4953
+ const has_fix = init_logic_json_merge.has_package_scripts_marker(content, FIX_GH_PACKAGES_MARKER);
4954
+ if (!has_fix) return scripts;
4955
+ return Object.fromEntries(Object.entries(scripts).filter(([key]) => key !== PREPARE_KEY));
4956
+ }
4957
+ function upgrade_prepare_lefthook_warning(content) {
4958
+ return init_logic_json_merge.replace_in_package_script(
4959
+ content,
4960
+ PREPARE_KEY,
4961
+ LEGACY_GUARDED_LEFTHOOK_CMD,
4962
+ GUARDED_LEFTHOOK_CMD
4963
+ );
4964
+ }
4965
+ function merge_prepare_lifecycle_cmd(content) {
4966
+ const has_fix = init_logic_json_merge.has_package_scripts_marker(content, FIX_GH_PACKAGES_MARKER);
4967
+ if (has_fix) return content;
4968
+ return init_logic_json_merge.merge_package_script_suffix(content, PREPARE_KEY, PREPARE_CMD);
4969
+ }
4970
+ function strip_managed_postinstall(content) {
4971
+ return init_logic_json_merge.remove_script_with_marker(
4972
+ content,
4973
+ LEGACY_POSTINSTALL_KEY,
4974
+ FIX_GH_PACKAGES_CMD
4975
+ );
4976
+ }
4977
+ var init_logic = {
4978
+ ...init_logic_templates,
4979
+ ...init_logic_workspace,
4980
+ ...init_logic_sonar,
4981
+ ...init_logic_json_merge,
4982
+ ...init_logic_secretlint,
4983
+ ...init_logic_toolchain,
4984
+ ...init_logic_yaml_merge,
4985
+ ...init_logic_deploy_vps,
4986
+ ...distributed_paths,
4987
+ generate_tsconfig,
4988
+ merge_tsconfig_exclude,
4989
+ get_tsconfig_exclude_entries,
4990
+ generate_lefthook_config,
4991
+ generate_cspell_config,
4992
+ merge_npmrc,
4993
+ merge_gitignore,
4994
+ get_tsconfig_extends_entry,
4995
+ get_tsconfig_preset_filename,
4996
+ get_lefthook_extends_value,
4997
+ get_cspell_import_value,
4998
+ get_vscode_settings_filename,
4999
+ strip_kit_only_vscode_settings,
5000
+ strip_kit_only_vscode_settings_content,
5001
+ VSCODE_EXTENSIONS_FILENAME,
5002
+ SAFE_CHAIN_CMD: SAFE_CHAIN_CMD2,
5003
+ GUARDED_LEFTHOOK_CMD,
5004
+ upgrade_prepare_lefthook_warning,
5005
+ get_development_engines_value,
5006
+ get_ai_copy_files,
5007
+ get_ai_copy_file_mappings,
5008
+ get_ai_copy_directories,
5009
+ get_suggested_scripts,
5010
+ get_suggested_scripts_for_content,
5011
+ merge_prepare_lifecycle_cmd,
5012
+ strip_managed_postinstall
5013
+ };
5014
+
5015
+ // scripts/sync/plugin-skill-directories.ts
5016
+ var PLUGIN_SKILL_DIRECTORIES = [
5017
+ ".claude/skills/workflow-commands",
5018
+ ".claude/skills/epic-commands",
5019
+ ".claude/skills/dependency-update",
5020
+ ".claude/skills/verify-ui"
5021
+ ];
5022
+
5023
+ // scripts/sync/synced-paths.ts
5024
+ var SYNCED_ARTIFACT_PATHS = [
5025
+ "prettier.config.js",
5026
+ "playwright.config.ts",
5027
+ ".github/workflows/deploy-vps.yml"
5028
+ ];
5029
+ var SYNCED_CONFIG_PATHS = [
5030
+ ".npmrc",
5031
+ ".gitignore",
5032
+ "eslint.config.js",
5033
+ "tsconfig.json",
5034
+ "cspell.config.yaml",
5035
+ "lefthook.yml",
5036
+ ".secretlintrc.json",
5037
+ ".vscode/extensions.json",
5038
+ ".vscode/settings.json",
5039
+ ".vscode/tasks.json"
5040
+ ];
5041
+ function get_synced_paths() {
5042
+ return [
5043
+ ...SYNCED_ARTIFACT_PATHS,
5044
+ ...SYNCED_CONFIG_PATHS,
5045
+ init_logic.get_sonar_template_destination()
5046
+ ];
5047
+ }
5048
+ var synced_paths = { get_synced_paths };
5049
+
5050
+ // scripts/sync/managed-config-scope.ts
5051
+ var AI_COPY_FILES_LIST = "AI_COPY_FILES";
5052
+ var AI_COPY_FILE_MAPPINGS_LIST = "AI_COPY_FILE_MAPPINGS";
5053
+ var AI_COPY_DIRECTORIES_LIST = "AI_COPY_DIRECTORIES";
5054
+ var SYNCED_PATHS_LIST = "SYNCED_PATHS";
5055
+ var PLUGIN_SKILL_DIRECTORIES_LIST = "PLUGIN_SKILL_DIRECTORIES";
5056
+ var PATH_SEPARATOR = "/";
5057
+ function is_inside(path15, directory) {
5058
+ return path15 === directory || path15.startsWith(`${directory}${PATH_SEPARATOR}`);
5059
+ }
5060
+ function matches_file(path15) {
5061
+ return init_logic.get_ai_copy_files().includes(path15);
5062
+ }
5063
+ function matches_mapping(path15) {
5064
+ return init_logic.get_ai_copy_file_mappings().some((mapping) => mapping.src === path15 || mapping.dest === path15);
5065
+ }
5066
+ function matches_directory(path15) {
5067
+ return init_logic.get_ai_copy_directories().some((directory) => is_inside(path15, directory));
5068
+ }
5069
+ function matches_plugin_skill(path15) {
5070
+ return PLUGIN_SKILL_DIRECTORIES.some((directory) => is_inside(path15, directory));
5071
+ }
5072
+ function matches_synced_path(path15) {
5073
+ return synced_paths.get_synced_paths().includes(path15);
5074
+ }
5075
+ var MATCHERS = [
5076
+ { list: AI_COPY_FILES_LIST, matches: matches_file },
5077
+ { list: AI_COPY_FILE_MAPPINGS_LIST, matches: matches_mapping },
5078
+ { list: AI_COPY_DIRECTORIES_LIST, matches: matches_directory },
5079
+ { list: PLUGIN_SKILL_DIRECTORIES_LIST, matches: matches_plugin_skill },
5080
+ { list: SYNCED_PATHS_LIST, matches: matches_synced_path }
5081
+ ];
5082
+ function find_list(path15) {
5083
+ return MATCHERS.find((matcher) => matcher.matches(path15))?.list;
5084
+ }
5085
+ function to_hit(path15) {
5086
+ const list = find_list(path15);
5087
+ return list === void 0 ? void 0 : { path: path15, list };
5088
+ }
5089
+ function find_managed_paths(paths) {
5090
+ return paths.flatMap((path15) => to_hit(path15) ?? []);
5091
+ }
5092
+ function has_managed_path(paths) {
5093
+ return paths.some((path15) => find_list(path15) !== void 0);
5094
+ }
5095
+ function format_hit(hit) {
5096
+ return `${hit.path} (${hit.list})`;
5097
+ }
5098
+ function format_hits(hits) {
5099
+ return hits.map((hit) => format_hit(hit)).join("\n");
5100
+ }
5101
+ var managed_config_scope = {
5102
+ find_managed_paths,
5103
+ has_managed_path,
5104
+ format_hit,
5105
+ format_hits
5106
+ };
5107
+
5108
+ // scripts/init/session-language-environment.ts
5109
+ import path8 from "node:path";
5110
+ var CLAUDE_SETTINGS_PATH = path8.join(".claude", "settings.json");
5111
+ var KEY_LINE_PATTERN = new RegExp(
5112
+ String.raw`^\s*(?:export\s+)?${session_language.ENV_KEY}\s*=`,
5113
+ "mu"
5114
+ );
5115
+
5116
+ // scripts/config-merge/patch-json-array.ts
5117
+ import { findNodeAtLocation as findNodeAtLocation2, getNodeValue as getNodeValue2, parseTree as parseTree3 } from "jsonc-parser";
5118
+
5119
+ // scripts/init/vscode-tasks.ts
5120
+ import { z as z12 } from "zod";
5121
+ var task_array_schema = z12.array(json_object_schema);
5122
+
5123
+ // scripts/init/init-actions.ts
5124
+ var BASIC_PRETTIER_CONFIG = "prettier.config.mjs";
5125
+
5126
+ // scripts/managed-marker/managed-marker-logic.ts
5127
+ var MARKER_TOKEN = "josh-managed-workflow:";
5128
+ var MARKER_PREFIX = `# ${MARKER_TOKEN}`;
5129
+
5130
+ // scripts/init/claude-plugin-config.ts
5131
+ import path9 from "node:path";
5132
+ var MARKETPLACE_NAME = "kit";
5133
+ var PLUGIN_ID2 = "kit@kit";
5134
+ var MARKETPLACE_PATH = "./node_modules/@joshuafolkken/kit";
5135
+ var CLAUDE_SETTINGS_DESTINATION = path9.join(".claude", "settings.json");
5136
+ var PLUGIN_SETTINGS = {
5137
+ extraKnownMarketplaces: {
5138
+ [MARKETPLACE_NAME]: { source: { source: "directory", path: MARKETPLACE_PATH } }
5139
+ },
5140
+ enabledPlugins: { [PLUGIN_ID2]: true }
5141
+ };
5142
+ function inject_plugin_config(content) {
5143
+ return init_logic_json_merge.merge_json_object(content, PLUGIN_SETTINGS);
5144
+ }
5145
+ function apply_plugin_config_for_destination(destination_path, content) {
5146
+ return destination_path.endsWith(CLAUDE_SETTINGS_DESTINATION) ? inject_plugin_config(content) : content;
5147
+ }
5148
+ var claude_plugin_config = {
5149
+ PLUGIN_ID: PLUGIN_ID2,
5150
+ MARKETPLACE_PATH,
5151
+ CLAUDE_SETTINGS_DESTINATION,
5152
+ inject_plugin_config,
5153
+ apply_plugin_config_for_destination
5154
+ };
5155
+
5156
+ // scripts/init/hook-launch.ts
5157
+ var HOOK_DIST_DIR = "dist/hooks";
5158
+ var RUN_HOOK_SCRIPT = "scripts/hooks/run-hook.sh";
5159
+ var UNSET_OPTIONS = GIT_LOCATION_VARIABLES.map((name) => `-u ${name}`).join(" ");
5160
+ var ROOT_LOOKUP = "git rev-parse --show-toplevel";
5161
+ var PROJECT_ROOT_PREFIX = `project_root="$(env ${UNSET_OPTIONS} ${ROOT_LOOKUP} 2>/dev/null || ${ROOT_LOOKUP})" && cd "$project_root" && `;
5162
+ function hook_launch_command(name) {
5163
+ return `${PROJECT_ROOT_PREFIX}sh ${RUN_HOOK_SCRIPT} ${name}`;
5164
+ }
5165
+ function fallback_command(name) {
5166
+ return name.replace("-", ":");
5167
+ }
5168
+ var hook_launch = {
5169
+ fallback_command,
5170
+ HOOK_DIST_DIR,
5171
+ hook_launch_command,
5172
+ PROJECT_ROOT_PREFIX,
5173
+ RUN_HOOK_SCRIPT
5174
+ };
5175
+
5176
+ // scripts/init/hook-command-rewrite.ts
5177
+ var PNPM_JOSH_PREFIX = "pnpm josh ";
5178
+ var BUNDLE_INVOCATION = `node ${claude_plugin_config.MARKETPLACE_PATH}/dist/josh.js `;
5179
+ var RUN_HOOK_INVOCATION = `sh ${hook_launch.RUN_HOOK_SCRIPT} `;
5180
+ var CONSUMER_RUN_HOOK_INVOCATION = `sh ${claude_plugin_config.MARKETPLACE_PATH}/${hook_launch.RUN_HOOK_SCRIPT} `;
5181
+ var CONSUMER_PACKAGE_MANIFEST = `${claude_plugin_config.MARKETPLACE_PATH}/package.json`;
5182
+ var MISSING_INSTALL_NOTICE = "kit hooks inactive: run pnpm install, then reread CLAUDE.md";
5183
+ var MISSING_INSTALL_GUARD = `if [ ! -f ${CONSUMER_PACKAGE_MANIFEST} ]; then echo '${MISSING_INSTALL_NOTICE}' >&2; exit 0; fi; `;
5184
+ var PLAIN_KIT_COMMANDS = new Set(
5185
+ [
5186
+ "audit:provision",
5187
+ "batch:guard",
5188
+ "format:edited",
5189
+ "investigation:guard",
5190
+ "rule:guard",
5191
+ "session:lang"
5192
+ ].map((command) => `${PNPM_JOSH_PREFIX}${command}`)
5193
+ );
5194
+ var PROJECT_ROOT_PREFIX2 = JSON.stringify(hook_launch.PROJECT_ROOT_PREFIX).slice(1, -1);
5195
+
5196
+ // scripts/init/security-policy.ts
5197
+ import path10 from "node:path";
5198
+ var SECURITY_MD = "SECURITY.md";
5199
+ var SECURITY_TEMPLATE = "templates/SECURITY.md";
5200
+ var REPOSITORY_PLACEHOLDER = "{{REPOSITORY}}";
5201
+ var KIT_ADVISORY_URL = "https://github.com/joshuafolkken/kit/security/advisories/new";
5202
+ var UNRESOLVED_REASON = "`origin` is not a GitHub repository `owner/repo` can be read from";
5203
+ var LINK_DELIMITER = /[\s()<>[\]]+/u;
5204
+ function repository_at(root) {
5205
+ const url = git_spawn_sync.origin_url(root);
5206
+ const identity = url === void 0 ? void 0 : repo_origin.parse_origin_url(url);
5207
+ return identity === void 0 ? void 0 : `${identity.owner}/${identity.repo}`;
5208
+ }
5209
+ function apply_repository(content, repository) {
5210
+ return content.replaceAll(REPOSITORY_PLACEHOLDER, () => repository);
5211
+ }
5212
+ function apply_repository_for_destination(destination_path, content) {
5213
+ if (path10.basename(destination_path) !== SECURITY_MD) return content;
5214
+ const repository = repository_at(path10.dirname(destination_path));
5215
+ if (repository === void 0) {
5216
+ throw new Error(`${SECURITY_MD} needs a GitHub origin to name the repository it reports to`);
5217
+ }
5218
+ return apply_repository(content, repository);
5219
+ }
5220
+ function does_report_to_kit(root) {
5221
+ const existing = file_reader.read_if_readable(path10.join(root, SECURITY_MD)) ?? "";
5222
+ return new Set(existing.split(LINK_DELIMITER)).has(KIT_ADVISORY_URL);
5223
+ }
5224
+ function unresolved_warning(root) {
5225
+ if (!does_report_to_kit(root)) return ` \u26A0 skipped ${SECURITY_MD} (${UNRESOLVED_REASON})`;
5226
+ return ` \u26A0 stale ${SECURITY_MD} still reports vulnerabilities to joshuafolkken/kit \u2014 replace it with your own policy or delete it (${UNRESOLVED_REASON})`;
5227
+ }
5228
+ function did_skip_unresolved(filename, root) {
5229
+ if (filename !== SECURITY_MD || repository_at(root) !== void 0) return false;
5230
+ console.warn(unresolved_warning(root));
5231
+ return true;
5232
+ }
5233
+ var security_policy = {
5234
+ SECURITY_MD,
5235
+ SECURITY_TEMPLATE,
5236
+ REPOSITORY_PLACEHOLDER,
5237
+ KIT_ADVISORY_URL,
5238
+ repository_at,
5239
+ apply_repository_for_destination,
5240
+ did_skip_unresolved
5241
+ };
5242
+
5243
+ // scripts/init/init-ai-copy.ts
5244
+ var WORKSPACE_YAML = "pnpm-workspace.yaml";
5245
+ var CLAUDE_MD_FILENAME = "CLAUDE.md";
5246
+ var PRETTIER_IGNORE = ".prettierignore";
5247
+ var GIT_ATTRIBUTES = ".gitattributes";
5248
+ var CODE_OF_CONDUCT = "CODE_OF_CONDUCT.md";
5249
+ var { SECURITY_MD: SECURITY_MD2 } = security_policy;
5250
+ var AGENTS_MD = "AGENTS.md";
5251
+ var GEMINI_MD = "GEMINI.md";
5252
+ var BASIC_AI_FILES = [
5253
+ AGENTS_MD,
5254
+ GEMINI_MD,
5255
+ PRETTIER_IGNORE,
5256
+ GIT_ATTRIBUTES,
5257
+ CODE_OF_CONDUCT,
5258
+ SECURITY_MD2,
5259
+ WORKSPACE_YAML
5260
+ ];
5261
+ var BASIC_SOURCES = {
5262
+ [AGENTS_MD]: "templates/AGENTS.basic.md",
5263
+ [GEMINI_MD]: "templates/GEMINI.basic.md",
5264
+ [PRETTIER_IGNORE]: "templates/prettierignore.basic",
5265
+ [WORKSPACE_YAML]: "templates/pnpm-workspace.basic.yaml"
5266
+ };
5267
+ var CONSUMER_SOURCES = {
5268
+ [SECURITY_MD2]: security_policy.SECURITY_TEMPLATE
5269
+ };
5270
+ var BASIC_WORKFLOW_AI_FILES = [...BASIC_AI_FILES, ".claude/settings.json"];
5271
+
5272
+ // scripts/init/kit-written-paths.ts
5273
+ var MANIFEST_FILE = "package.json";
5274
+ var LOCKFILE = "pnpm-lock.yaml";
5275
+ var SETUP_ONLY_PATHS = /* @__PURE__ */ new Set([
5276
+ CLAUDE_MD_FILENAME,
5277
+ BASIC_PRETTIER_CONFIG,
5278
+ PROJECT_CONFIG_FILE,
5279
+ PACK_HOOK_FILE,
5280
+ MANIFEST_FILE,
5281
+ LOCKFILE
5282
+ ]);
5283
+ function is_kit_written2(file_path) {
5284
+ return SETUP_ONLY_PATHS.has(file_path) || managed_config_scope.has_managed_path([file_path]);
5285
+ }
5286
+ function select(paths) {
5287
+ return paths.filter((file_path) => is_kit_written2(file_path));
5288
+ }
5289
+ var kit_written_paths = { is_kit_written: is_kit_written2, select };
5290
+
5291
+ // scripts/init/workflow-mark.ts
5292
+ var WORKFLOW_ENV = "JOSH_WORKFLOW";
5293
+ var GITHUB_WORKFLOW = "github";
5294
+ function is_requested(environment = process.env) {
5295
+ return environment[WORKFLOW_ENV] === GITHUB_WORKFLOW;
5296
+ }
5297
+ function is_recorded(manifest) {
5298
+ const josh = manifest?.["josh"];
5299
+ return json_value.is_record(josh) && josh["workflow"] === GITHUB_WORKFLOW;
5300
+ }
5301
+ function request(environment = process.env) {
5302
+ environment[WORKFLOW_ENV] = GITHUB_WORKFLOW;
5303
+ }
5304
+ function recorded_fields(has_workflow2) {
5305
+ return has_workflow2 ? { workflow: GITHUB_WORKFLOW } : {};
5306
+ }
5307
+ var workflow_mark = { is_requested, is_recorded, request, recorded_fields };
5308
+
5309
+ // scripts/init/project-profile.ts
2847
5310
  var IGNORED_DIRECTORIES = /* @__PURE__ */ new Set([".git", "node_modules", "dist", "build", ".svelte-kit"]);
2848
5311
  var WEB_EXTENSIONS = /* @__PURE__ */ new Set([".html", ".css", ".js", ".jsx", ".mjs", ".cjs"]);
2849
5312
  var TYPESCRIPT_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx"]);
@@ -2875,9 +5338,9 @@ function requested_profile(args, usage = "josh init [--profile basic|full]") {
2875
5338
  throw new Error("Profile must be basic or full");
2876
5339
  }
2877
5340
  function read_manifest(root) {
2878
- const filename = path6.join(root, "package.json");
2879
- if (!existsSync3(filename)) return void 0;
2880
- const parsed = JSON.parse(readFileSync3(filename, "utf8"));
5341
+ const filename = path11.join(root, "package.json");
5342
+ if (!existsSync5(filename)) return void 0;
5343
+ const parsed = JSON.parse(readFileSync5(filename, "utf8"));
2881
5344
  if (!json_value.is_record(parsed)) throw new Error("package.json must contain an object");
2882
5345
  return parsed;
2883
5346
  }
@@ -2915,17 +5378,21 @@ function should_visit(entry) {
2915
5378
  function scan_directory(directory, pending) {
2916
5379
  const entries = readdirSync(directory, { withFileTypes: true });
2917
5380
  pending.push(
2918
- ...entries.filter((entry) => should_visit(entry)).map((entry) => path6.join(directory, entry.name))
5381
+ ...entries.filter((entry) => should_visit(entry)).map((entry) => path11.join(directory, entry.name))
2919
5382
  );
2920
- return entries.filter((entry) => entry.isFile()).map((entry) => path6.extname(entry.name));
5383
+ return entries.filter((entry) => entry.isFile()).map((entry) => path11.join(directory, entry.name));
5384
+ }
5385
+ function is_project_file(root, file) {
5386
+ const relative_path = path11.relative(root, file).split(path11.sep).join(path11.posix.sep);
5387
+ return !kit_written_paths.is_kit_written(relative_path);
2921
5388
  }
2922
5389
  function file_extensions(root) {
2923
5390
  const pending = [root];
2924
- const extensions = [];
5391
+ const files = [];
2925
5392
  for (const directory of pending) {
2926
- extensions.push(...scan_directory(directory, pending));
5393
+ files.push(...scan_directory(directory, pending));
2927
5394
  }
2928
- return extensions;
5395
+ return files.filter((file) => is_project_file(root, file)).map((file) => path11.extname(file));
2929
5396
  }
2930
5397
  function scan_files(root) {
2931
5398
  const extensions = file_extensions(root);
@@ -2937,15 +5404,28 @@ function has_github_remote(root) {
2937
5404
  const url = git_spawn_sync.origin_url(root);
2938
5405
  return url !== void 0 && repo_origin.parse_origin_url(url) !== void 0;
2939
5406
  }
5407
+ function has_git(root) {
5408
+ return existsSync5(path11.join(root, ".git"));
5409
+ }
5410
+ function has_workflow(root) {
5411
+ return workflow_mark.is_requested() || workflow_mark.is_recorded(read_manifest(root));
5412
+ }
2940
5413
  function inspect_project(root, requested) {
2941
5414
  const profile = resolve_profile(root, requested);
2942
5415
  const files = scan_files(root);
2943
- const has_git = existsSync3(path6.join(root, ".git"));
2944
- return { ...profile, ...files, has_git, has_github: has_git && has_github_remote(root) };
5416
+ const is_git = has_git(root);
5417
+ return {
5418
+ ...profile,
5419
+ ...files,
5420
+ has_git: is_git,
5421
+ has_github: is_git && has_github_remote(root),
5422
+ has_workflow: has_workflow(root)
5423
+ };
2945
5424
  }
2946
5425
  var project_profile = {
2947
5426
  parse_profile,
2948
5427
  resolve_profile,
5428
+ has_git,
2949
5429
  inspect_project,
2950
5430
  requested_profile,
2951
5431
  with_legacy_profile_names
@@ -2953,10 +5433,11 @@ var project_profile = {
2953
5433
 
2954
5434
  // scripts/test/skip-marker.ts
2955
5435
  var SKIP_MARKER = "\u2014 skipping";
5436
+ var NOT_USED_MARKER = "which this project does not use";
2956
5437
 
2957
5438
  // scripts/gate/project-checks.ts
2958
- import { z as z7 } from "zod";
2959
- var PACKAGE_JSON = "package.json";
5439
+ import { z as z13 } from "zod";
5440
+ var PACKAGE_JSON2 = "package.json";
2960
5441
  var IGNORED_DIRS = /* @__PURE__ */ new Set([
2961
5442
  "node_modules",
2962
5443
  ".git",
@@ -2990,11 +5471,11 @@ var CSPELL_CONFIGS = [
2990
5471
  ];
2991
5472
  var TYPE_CONFIGS = ["tsconfig.json", "jsconfig.json"];
2992
5473
  var DEPENDENCY_FIELDS = ["dependencies", "devDependencies"];
2993
- var object_schema = z7.record(z7.string(), z7.unknown());
5474
+ var object_schema = z13.record(z13.string(), z13.unknown());
2994
5475
  function project_root(directory) {
2995
5476
  return ancestor_directories.nearest(
2996
5477
  directory,
2997
- (candidate) => existsSync4(path7.join(candidate, PACKAGE_JSON))
5478
+ (candidate) => existsSync6(path12.join(candidate, PACKAGE_JSON2))
2998
5479
  ) ?? directory;
2999
5480
  }
3000
5481
  function is_kit_repository(directory) {
@@ -3007,7 +5488,7 @@ function has_files(directory, pattern) {
3007
5488
  return globSync2(pattern, { cwd: project_root(directory), exclude: is_ignored }).length > 0;
3008
5489
  }
3009
5490
  function has_config(directory, names) {
3010
- return names.some((name) => existsSync4(path7.join(project_root(directory), name)));
5491
+ return names.some((name) => existsSync6(path12.join(project_root(directory), name)));
3011
5492
  }
3012
5493
  function has_bin(directory, bin_name) {
3013
5494
  return find_local_bin_upwards(directory, bin_name) !== void 0;
@@ -3022,8 +5503,8 @@ function is_basic_manifest(manifest) {
3022
5503
  }
3023
5504
  function read_manifest2(directory) {
3024
5505
  try {
3025
- const manifest_path = path7.join(project_root(directory), PACKAGE_JSON);
3026
- return json_value.parse_or_undefined(readFileSync4(manifest_path, "utf8"));
5506
+ const manifest_path = path12.join(project_root(directory), PACKAGE_JSON2);
5507
+ return json_value.parse_or_undefined(readFileSync6(manifest_path, "utf8"));
3027
5508
  } catch {
3028
5509
  return void 0;
3029
5510
  }
@@ -3031,7 +5512,7 @@ function read_manifest2(directory) {
3031
5512
  function is_basic(directory) {
3032
5513
  return is_basic_manifest(read_manifest2(directory));
3033
5514
  }
3034
- function is_declared(directory, package_name) {
5515
+ function is_declared2(directory, package_name) {
3035
5516
  const manifest = object_schema.safeParse(read_manifest2(directory));
3036
5517
  if (!manifest.success) return false;
3037
5518
  return DEPENDENCY_FIELDS.some((field) => {
@@ -3040,11 +5521,14 @@ function is_declared(directory, package_name) {
3040
5521
  });
3041
5522
  }
3042
5523
  function missing_tool_reason(directory, package_name, bin_name) {
3043
- if (has_bin(directory, bin_name) || is_declared(directory, package_name)) return void 0;
5524
+ if (has_bin(directory, bin_name) || is_declared2(directory, package_name)) return void 0;
3044
5525
  return `${package_name} is not installed`;
3045
5526
  }
3046
- function skip_notice(check4, reason) {
3047
- return `josh ${check4}: ${reason} ${SKIP_MARKER} ${check4}.`;
5527
+ function skip_notice(check5, reason) {
5528
+ return `josh ${check5}: ${reason} ${SKIP_MARKER} ${check5}, ${NOT_USED_MARKER}.`;
5529
+ }
5530
+ function ran_notice(check5) {
5531
+ return `josh ${check5}: ran and reported no problems.`;
3048
5532
  }
3049
5533
  function type_check_skip_reason(directory) {
3050
5534
  if (!is_basic(directory)) return void 0;
@@ -3076,6 +5560,8 @@ var project_checks = {
3076
5560
  is_kit_repository,
3077
5561
  prettier_skip_reason,
3078
5562
  project_root,
5563
+ ran_notice,
5564
+ read_manifest: read_manifest2,
3079
5565
  skip_notice,
3080
5566
  type_check_skip_reason
3081
5567
  };
@@ -3104,40 +5590,40 @@ var BASIC_REQUIRED_SUFFIXES = [
3104
5590
  ".toml"
3105
5591
  ];
3106
5592
  function normalize(paths) {
3107
- return paths.map((path10) => path10.trim()).filter((path10) => path10 !== "");
5593
+ return paths.map((path15) => path15.trim()).filter((path15) => path15 !== "");
3108
5594
  }
3109
- function is_test_file(path10) {
3110
- return TEST_SUFFIXES.some((suffix) => path10.endsWith(suffix));
5595
+ function is_test_file(path15) {
5596
+ return TEST_SUFFIXES.some((suffix) => path15.endsWith(suffix));
3111
5597
  }
3112
- function is_basic_manual(path10, is_basic2) {
3113
- const lower = path10.toLowerCase();
5598
+ function is_basic_manual(path15, is_basic2) {
5599
+ const lower = path15.toLowerCase();
3114
5600
  return is_basic2 && BASIC_REQUIRED_SUFFIXES.every((suffix) => !lower.endsWith(suffix));
3115
5601
  }
3116
- function is_basic_visual(path10) {
3117
- const lower = path10.toLowerCase();
5602
+ function is_basic_visual(path15) {
5603
+ const lower = path15.toLowerCase();
3118
5604
  return BASIC_VISUAL_SUFFIXES.some((suffix) => lower.endsWith(suffix));
3119
5605
  }
3120
- function is_exempt(path10, is_basic2 = false) {
3121
- if (EXEMPT_PATHS.includes(path10) || is_basic_manual(path10, is_basic2)) return true;
3122
- return EXEMPT_SUFFIXES.some((suffix) => path10.endsWith(suffix)) || EXEMPT_PREFIXES.some((prefix) => path10.startsWith(prefix));
5606
+ function is_exempt(path15, is_basic2 = false) {
5607
+ if (EXEMPT_PATHS.includes(path15) || is_basic_manual(path15, is_basic2)) return true;
5608
+ return EXEMPT_SUFFIXES.some((suffix) => path15.endsWith(suffix)) || EXEMPT_PREFIXES.some((prefix) => path15.startsWith(prefix));
3123
5609
  }
3124
- function is_runtime(path10, is_basic2 = false) {
3125
- return !is_test_file(path10) && !is_exempt(path10, is_basic2);
5610
+ function is_runtime(path15, is_basic2 = false) {
5611
+ return !is_test_file(path15) && !is_exempt(path15, is_basic2);
3126
5612
  }
3127
- function verdict_for(paths, is_basic2 = false) {
5613
+ function verdict_for2(paths, is_basic2 = false) {
3128
5614
  const changed = normalize(paths);
3129
- if (changed.some((path10) => is_test_file(path10))) return "satisfied";
3130
- if (changed.some((path10) => is_runtime(path10, is_basic2))) return "required";
5615
+ if (changed.some((path15) => is_test_file(path15))) return "satisfied";
5616
+ if (changed.some((path15) => is_runtime(path15, is_basic2))) return "required";
3131
5617
  return "exempt";
3132
5618
  }
3133
5619
  function runtime_files(paths, is_basic2 = false) {
3134
- return normalize(paths).filter((path10) => is_runtime(path10, is_basic2));
5620
+ return normalize(paths).filter((path15) => is_runtime(path15, is_basic2));
3135
5621
  }
3136
5622
  function exempt_files(paths, is_basic2 = false) {
3137
- return normalize(paths).filter((path10) => is_exempt(path10, is_basic2));
5623
+ return normalize(paths).filter((path15) => is_exempt(path15, is_basic2));
3138
5624
  }
3139
5625
  function manual_check_files(paths, is_basic2) {
3140
- return normalize(paths).filter((path10) => is_exempt(path10, is_basic2) && !is_exempt(path10));
5626
+ return normalize(paths).filter((path15) => is_exempt(path15, is_basic2) && !is_exempt(path15));
3141
5627
  }
3142
5628
  var test_declared_logic = {
3143
5629
  EXEMPT_PATHS,
@@ -3150,7 +5636,7 @@ var test_declared_logic = {
3150
5636
  is_test_file,
3151
5637
  manual_check_files,
3152
5638
  runtime_files,
3153
- verdict_for
5639
+ verdict_for: verdict_for2
3154
5640
  };
3155
5641
 
3156
5642
  // scripts/test/test-declared-changed.ts
@@ -3492,30 +5978,30 @@ var epic_busy = {
3492
5978
  };
3493
5979
 
3494
5980
  // scripts/run/run-liveness.ts
3495
- import { readFileSync as readFileSync5, realpathSync, statSync } from "node:fs";
5981
+ import { readFileSync as readFileSync7, realpathSync, statSync } from "node:fs";
3496
5982
  import { homedir, tmpdir } from "node:os";
3497
- import path8 from "node:path";
5983
+ import path13 from "node:path";
3498
5984
  import { setTimeout as sleep } from "node:timers/promises";
3499
5985
 
3500
5986
  // scripts/agent/agent-event.ts
3501
- import { z as z9 } from "zod";
5987
+ import { z as z15 } from "zod";
3502
5988
 
3503
5989
  // scripts/agent/claude-result-event.ts
3504
- import { z as z8 } from "zod";
3505
- var RESULT_EVENT_SCHEMA = z8.looseObject({
3506
- type: z8.literal("result"),
3507
- is_error: z8.unknown().optional(),
3508
- subtype: z8.unknown().optional(),
3509
- num_turns: z8.unknown().optional(),
3510
- permission_denials: z8.unknown().optional(),
3511
- result: z8.unknown().optional(),
3512
- session_id: z8.unknown().optional(),
3513
- usage: z8.unknown().optional()
5990
+ import { z as z14 } from "zod";
5991
+ var RESULT_EVENT_SCHEMA = z14.looseObject({
5992
+ type: z14.literal("result"),
5993
+ is_error: z14.unknown().optional(),
5994
+ subtype: z14.unknown().optional(),
5995
+ num_turns: z14.unknown().optional(),
5996
+ permission_denials: z14.unknown().optional(),
5997
+ result: z14.unknown().optional(),
5998
+ session_id: z14.unknown().optional(),
5999
+ usage: z14.unknown().optional()
3514
6000
  });
3515
- var USAGE_SCHEMA = z8.looseObject({
3516
- input_tokens: z8.unknown().optional(),
3517
- cache_read_input_tokens: z8.unknown().optional(),
3518
- output_tokens: z8.unknown().optional()
6001
+ var USAGE_SCHEMA = z14.looseObject({
6002
+ input_tokens: z14.unknown().optional(),
6003
+ cache_read_input_tokens: z14.unknown().optional(),
6004
+ output_tokens: z14.unknown().optional()
3519
6005
  });
3520
6006
  function usable_reason(value) {
3521
6007
  return typeof value === "string" && value.trim() !== "" ? value : void 0;
@@ -3554,31 +6040,31 @@ function decode(value) {
3554
6040
  var claude_result_event = { decode };
3555
6041
 
3556
6042
  // scripts/agent/agent-event.ts
3557
- var TEXT_BLOCK_SCHEMA = z9.looseObject({ type: z9.literal("text"), text: z9.string() });
3558
- var CLAUDE_MESSAGE_SCHEMA = z9.looseObject({ content: z9.array(z9.unknown()).optional() });
3559
- var CLAUDE_INIT_SCHEMA = z9.looseObject({ type: z9.literal("system"), subtype: z9.literal("init") });
3560
- var CLAUDE_ASSISTANT_SCHEMA = z9.looseObject({
3561
- type: z9.literal("assistant"),
6043
+ var TEXT_BLOCK_SCHEMA = z15.looseObject({ type: z15.literal("text"), text: z15.string() });
6044
+ var CLAUDE_MESSAGE_SCHEMA = z15.looseObject({ content: z15.array(z15.unknown()).optional() });
6045
+ var CLAUDE_INIT_SCHEMA = z15.looseObject({ type: z15.literal("system"), subtype: z15.literal("init") });
6046
+ var CLAUDE_ASSISTANT_SCHEMA = z15.looseObject({
6047
+ type: z15.literal("assistant"),
3562
6048
  message: CLAUDE_MESSAGE_SCHEMA
3563
6049
  });
3564
- var USAGE_SCHEMA2 = z9.looseObject({
3565
- input_tokens: z9.number().optional(),
3566
- cached_input_tokens: z9.number().optional(),
3567
- output_tokens: z9.number().optional()
6050
+ var USAGE_SCHEMA2 = z15.looseObject({
6051
+ input_tokens: z15.number().optional(),
6052
+ cached_input_tokens: z15.number().optional(),
6053
+ output_tokens: z15.number().optional()
3568
6054
  });
3569
- var CODEX_START_SCHEMA = z9.looseObject({ type: z9.enum(["thread.started", "turn.started"]) });
3570
- var CODEX_PROGRESS_SCHEMA = z9.looseObject({
3571
- type: z9.enum(["item.started", "item.updated", "item.completed"]),
3572
- item: z9.looseObject({ type: z9.string(), text: z9.string().optional() }).optional()
6055
+ var CODEX_START_SCHEMA = z15.looseObject({ type: z15.enum(["thread.started", "turn.started"]) });
6056
+ var CODEX_PROGRESS_SCHEMA = z15.looseObject({
6057
+ type: z15.enum(["item.started", "item.updated", "item.completed"]),
6058
+ item: z15.looseObject({ type: z15.string(), text: z15.string().optional() }).optional()
3573
6059
  });
3574
- var CODEX_COMPLETE_SCHEMA = z9.looseObject({
3575
- type: z9.literal("turn.completed"),
6060
+ var CODEX_COMPLETE_SCHEMA = z15.looseObject({
6061
+ type: z15.literal("turn.completed"),
3576
6062
  usage: USAGE_SCHEMA2.optional()
3577
6063
  });
3578
- var CODEX_FAILURE_SCHEMA = z9.looseObject({
3579
- type: z9.enum(["turn.failed", "error"]),
3580
- error: z9.looseObject({ message: z9.string().optional() }).optional(),
3581
- message: z9.string().optional()
6064
+ var CODEX_FAILURE_SCHEMA = z15.looseObject({
6065
+ type: z15.enum(["turn.failed", "error"]),
6066
+ error: z15.looseObject({ message: z15.string().optional() }).optional(),
6067
+ message: z15.string().optional()
3582
6068
  });
3583
6069
  var EMPTY_STATE = {
3584
6070
  provider: void 0,
@@ -3669,7 +6155,7 @@ function describe(state) {
3669
6155
  var agent_event = { describe, read };
3670
6156
 
3671
6157
  // scripts/issue/issue-state.ts
3672
- import { z as z10 } from "zod";
6158
+ import { z as z16 } from "zod";
3673
6159
  var NO_LABELS = "(none)";
3674
6160
  var LABEL_SEPARATOR = ", ";
3675
6161
  var STATE_LABEL = "state: ";
@@ -3679,9 +6165,9 @@ var YES = "yes";
3679
6165
  var NO = "no";
3680
6166
  var ISSUE_LABEL = "issue: ";
3681
6167
  var HUMAN_REVIEW_LABELS = /* @__PURE__ */ new Set([NEEDS_HUMAN_REVIEW_LABEL]);
3682
- var label_schema = z10.looseObject({ name: z10.string() });
3683
- var issue_state_schema = z10.looseObject({
3684
- state: z10.string(),
6168
+ var label_schema = z16.looseObject({ name: z16.string() });
6169
+ var issue_state_schema = z16.looseObject({
6170
+ state: z16.string(),
3685
6171
  labels: label_schema.array().optional()
3686
6172
  });
3687
6173
  function parse_issue_state(json) {
@@ -3798,12 +6284,12 @@ var ALLOWED_ROOTS = [
3798
6284
  )
3799
6285
  ];
3800
6286
  function is_within(candidate, root) {
3801
- const relative = path8.relative(root, candidate);
3802
- return relative !== "" && !relative.startsWith("..") && !path8.isAbsolute(relative);
6287
+ const relative = path13.relative(root, candidate);
6288
+ return relative !== "" && !relative.startsWith("..") && !path13.isAbsolute(relative);
3803
6289
  }
3804
6290
  function to_safe_path(output_path) {
3805
- const normalized2 = path8.normalize(output_path);
3806
- if (!path8.isAbsolute(normalized2)) return void 0;
6291
+ const normalized2 = path13.normalize(output_path);
6292
+ if (!path13.isAbsolute(normalized2)) return void 0;
3807
6293
  return ALLOWED_ROOTS.some((root) => is_within(normalized2, root)) ? normalized2 : void 0;
3808
6294
  }
3809
6295
  function sample_output(output_path) {
@@ -3817,7 +6303,7 @@ function read_agent_state(output_path) {
3817
6303
  const safe_path = to_safe_path(output_path);
3818
6304
  if (safe_path === void 0) return void 0;
3819
6305
  try {
3820
- const state = agent_event.read(readFileSync5(safe_path, "utf8"));
6306
+ const state = agent_event.read(readFileSync7(safe_path, "utf8"));
3821
6307
  return state.provider === void 0 ? void 0 : state;
3822
6308
  } catch {
3823
6309
  return void 0;
@@ -3827,12 +6313,12 @@ function describe_agent_state(output_path) {
3827
6313
  const state = read_agent_state(output_path);
3828
6314
  return state === void 0 ? void 0 : `agent: ${state.provider ?? "unknown"} ${agent_event.describe(state)}`;
3829
6315
  }
3830
- async function read_output_frozen(request) {
3831
- const first = sample_output(request.output_path);
6316
+ async function read_output_frozen(request2) {
6317
+ const first = sample_output(request2.output_path);
3832
6318
  if (first === void 0) return void 0;
3833
- if (request.now_ms - first.mtime_ms < request.silent_window_ms) return false;
3834
- await sleep(request.gap_ms);
3835
- const second = sample_output(request.output_path);
6319
+ if (request2.now_ms - first.mtime_ms < request2.silent_window_ms) return false;
6320
+ await sleep(request2.gap_ms);
6321
+ const second = sample_output(request2.output_path);
3836
6322
  if (second === void 0) return void 0;
3837
6323
  return second.mtime_ms === first.mtime_ms && second.size === first.size;
3838
6324
  }
@@ -3850,34 +6336,34 @@ async function read_child_settled(issue, repo) {
3850
6336
  if (state === void 0) return void 0;
3851
6337
  return state.state !== OPEN_STATE || carries_settled_label(state.labels);
3852
6338
  }
3853
- async function read_traces(request) {
6339
+ async function read_traces(request2) {
3854
6340
  const [is_initial_child_settled, is_output_frozen, is_tree_dirty] = await Promise.all([
3855
- read_child_settled(request.issue, request.repo),
6341
+ read_child_settled(request2.issue, request2.repo),
3856
6342
  read_output_frozen({
3857
- gap_ms: request.gap_ms ?? DEFAULT_GAP_SECONDS * MS_PER_SECOND2,
6343
+ gap_ms: request2.gap_ms ?? DEFAULT_GAP_SECONDS * MS_PER_SECOND2,
3858
6344
  now_ms: Date.now(),
3859
- output_path: request.output_path,
3860
- silent_window_ms: request.silent_window_ms ?? DEFAULT_SILENT_MINUTES * MS_PER_MINUTE3
6345
+ output_path: request2.output_path,
6346
+ silent_window_ms: request2.silent_window_ms ?? DEFAULT_SILENT_MINUTES * MS_PER_MINUTE3
3861
6347
  }),
3862
6348
  run_hold.is_tree_dirty()
3863
6349
  ]);
3864
- const agent_state = read_agent_state(request.output_path);
3865
- const is_latest_child_settled = is_agent_state_finished(agent_state) ? await read_child_settled(request.issue, request.repo) : void 0;
6350
+ const agent_state = read_agent_state(request2.output_path);
6351
+ const is_latest_child_settled = is_agent_state_finished(agent_state) ? await read_child_settled(request2.issue, request2.repo) : void 0;
3866
6352
  const is_child_settled = is_latest_child_settled ?? is_initial_child_settled;
3867
6353
  return {
3868
6354
  agent_state,
3869
6355
  is_child_settled,
3870
6356
  is_output_frozen,
3871
6357
  is_tree_dirty,
3872
- process_trace: request.process_trace
6358
+ process_trace: request2.process_trace
3873
6359
  };
3874
6360
  }
3875
- async function check(request) {
3876
- issue_number_shape.require_issue_number(request.issue);
3877
- return decide5(await read_traces(request));
6361
+ async function check2(request2) {
6362
+ issue_number_shape.require_issue_number(request2.issue);
6363
+ return decide5(await read_traces(request2));
3878
6364
  }
3879
6365
  var run_liveness = {
3880
- check,
6366
+ check: check2,
3881
6367
  decide: decide5,
3882
6368
  describe_agent_state,
3883
6369
  read_child_settled,
@@ -3949,7 +6435,7 @@ var lane_report = {
3949
6435
  };
3950
6436
 
3951
6437
  // scripts/run/run-preflight.ts
3952
- import { z as z11 } from "zod";
6438
+ import { z as z17 } from "zod";
3953
6439
  var CLEAN_VERDICT = "clean";
3954
6440
  var RECLAIM_VERDICT = "reclaim";
3955
6441
  var RESUME_VERDICT = "resume";
@@ -3959,7 +6445,7 @@ var OPEN_PR = "open";
3959
6445
  var MERGED_PR = "merged";
3960
6446
  var CLOSED_PR = "closed";
3961
6447
  var NO_CHILD_WORK = { branch_name: void 0, pr_state: NO_PR };
3962
- var pr_info_schema = z11.object({ state: z11.string().optional() });
6448
+ var pr_info_schema = z17.object({ state: z17.string().optional() });
3963
6449
  var GH_PR_STATES = /* @__PURE__ */ new Map([
3964
6450
  ["CLOSED", CLOSED_PR],
3965
6451
  ["MERGED", MERGED_PR],
@@ -4122,7 +6608,7 @@ async function read_child_state(issue) {
4122
6608
  );
4123
6609
  return pick_child_state(reads.filter((read2) => read2 !== void 0));
4124
6610
  }
4125
- async function check2(issue) {
6611
+ async function check3(issue) {
4126
6612
  require_issue_number(issue);
4127
6613
  const tree = await read_tree_state();
4128
6614
  if (needs_reclaim(tree)) return decide6(tree, NO_CHILD_WORK, issue);
@@ -4133,7 +6619,7 @@ var run_preflight = {
4133
6619
  RESUME_ADVICE,
4134
6620
  MERGED_PR,
4135
6621
  STASH_LABEL_PREFIX,
4136
- check: check2,
6622
+ check: check3,
4137
6623
  decide: decide6,
4138
6624
  read_child_state,
4139
6625
  read_pr_state,
@@ -4204,16 +6690,16 @@ async function has_run_record() {
4204
6690
  async function has_run_started(lanes) {
4205
6691
  return lanes.length > 0 || await has_run_record();
4206
6692
  }
4207
- async function read_observations(request) {
4208
- const [children, lanes] = await Promise.all([read_children(request.repo), read_lanes()]);
6693
+ async function read_observations(request2) {
6694
+ const [children, lanes] = await Promise.all([read_children(request2.repo), read_lanes()]);
4209
6695
  if (children === void 0) return UNREADABLE_READ;
4210
6696
  if (children.length === 0 && !await has_run_started(lanes)) return IDLE_READ;
4211
6697
  const observations = {
4212
- repo: request.repo,
6698
+ repo: request2.repo,
4213
6699
  children,
4214
6700
  lanes,
4215
6701
  load_average: loadavg()[FIRST_LOAD_AVERAGE] ?? 0,
4216
- record_age_ms: read_record_age(request.output_paths, request.now_ms)
6702
+ record_age_ms: read_record_age(request2.output_paths, request2.now_ms)
4217
6703
  };
4218
6704
  return { kind: "observed", observations };
4219
6705
  }
@@ -4232,7 +6718,7 @@ var run_progress_read = {
4232
6718
  };
4233
6719
 
4234
6720
  // scripts/run/run-watcher-hook.ts
4235
- import { z as z12 } from "zod";
6721
+ import { z as z18 } from "zod";
4236
6722
 
4237
6723
  // scripts/run/run-watcher-guard.ts
4238
6724
  var WATCHER_TICK_MS = 3e4;
@@ -4246,7 +6732,7 @@ async function owes_watcher() {
4246
6732
  if (run_headless.is_headless() || !await run_headless.is_backlog_parent()) return false;
4247
6733
  return await lane_registry.has_lanes_in_flight();
4248
6734
  }
4249
- async function check3(life_target) {
6735
+ async function check4(life_target) {
4250
6736
  if (!await owes_watcher()) return OK_RESULT;
4251
6737
  if (run_progress_clock.is_life_fresh(life_target, STALE_THRESHOLD_MS)) return OK_RESULT;
4252
6738
  return { kind: "stale", note: STALE_NOTE };
@@ -4254,13 +6740,13 @@ async function check3(life_target) {
4254
6740
  var run_watcher_guard = {
4255
6741
  STALE_NOTE,
4256
6742
  STALE_THRESHOLD_MS,
4257
- check: check3
6743
+ check: check4
4258
6744
  };
4259
6745
 
4260
6746
  // scripts/run/run-watcher-hook.ts
4261
6747
  var SWITCH_ENV_KEY2 = "JOSH_WATCHER_GUARD";
4262
6748
  var STAMP_PREFIX2 = "josh-watcher-guard-";
4263
- var payload_schema = z12.object({ transcript_path: z12.string().min(1) });
6749
+ var payload_schema = z18.object({ transcript_path: z18.string().min(1) });
4264
6750
  function transcript_of(raw_payload) {
4265
6751
  return json_value.parse_with(raw_payload, payload_schema)?.transcript_path;
4266
6752
  }
@@ -4298,7 +6784,7 @@ function current_state3() {
4298
6784
  }
4299
6785
  var THRESHOLD_TEXT2 = `${cost_format.format_tokens(CONTEXT_CUT_THRESHOLD)}-token`;
4300
6786
  var PARENT_CUT_REASON = `\u26D4 backlogrun parent hand-off: this session drives a \`backlogrun\` (it owns the live carry record) and its recent-context cost has crossed the shared ${THRESHOLD_TEXT2} threshold between merges, so every later request re-reads the accumulated context (joshuafolkken/kit#2947). Take the hand-off now rather than at the next merge: follow \`.claude/skills/workflow-commands/backlogrun-progress.md\` \u2192 "The hand-off" from its \`over\` branch \u2014 open no new lane and take no new child, read \`pnpm josh lane:list\`, make sure every lane in flight records an output path, then run \`pnpm josh run:carry --cut --owner "$PPID"\` and, unless it answers \`capped\`, \`pnpm josh run:wake\`, post the progress comment and end the turn. A lane nobody can poll means the cut does not happen; carry on and this asks again later. Reissue this call when the hand-off is done or cannot be taken \u2014 the guard stays quiet for a while after it refuses, so the hand-off calls themselves are not refused.`;
4301
- async function is_due2(state) {
6787
+ async function is_due3(state) {
4302
6788
  const carry = await state.carry();
4303
6789
  if (carry === void 0 || run_headless.is_cut_capped(carry)) return false;
4304
6790
  return state.verdict() === cost_verdict.OVER_VERDICT;
@@ -4310,7 +6796,7 @@ function is_quiet(target, now_ms) {
4310
6796
  async function refusal_for(transcript, now_ms, state) {
4311
6797
  const stamp = hook_decision.create_refusal_stamp(STAMP_PREFIX3);
4312
6798
  const target = stamp.path(transcript);
4313
- if (is_quiet(target, now_ms) || !await is_due2(state)) return void 0;
6799
+ if (is_quiet(target, now_ms) || !await is_due3(state)) return void 0;
4314
6800
  return stamp.record(target, now_ms) ? PARENT_CUT_REASON : void 0;
4315
6801
  }
4316
6802
  function is_unit_call(raw_payload) {
@@ -4338,7 +6824,7 @@ var run_parent_cut_hook = {
4338
6824
  };
4339
6825
 
4340
6826
  // scripts/hooks/step-zero-notice.ts
4341
- import path9 from "node:path";
6827
+ import path14 from "node:path";
4342
6828
  var STAMP_PREFIX4 = "josh-step-zero-notice-";
4343
6829
  var EDIT_TOOLS3 = /* @__PURE__ */ new Set(["Edit", "Write"]);
4344
6830
  var PARENT_PREFIX = "..";
@@ -4353,9 +6839,9 @@ function edited_paths(tool_input) {
4353
6839
  );
4354
6840
  }
4355
6841
  function is_runtime_file(file_path, root) {
4356
- const relative = path9.relative(root, path9.resolve(root, file_path));
4357
- if (relative.startsWith(PARENT_PREFIX) || path9.isAbsolute(relative)) return false;
4358
- return !test_declared_logic.is_exempt(relative.split(path9.sep).join("/"));
6842
+ const relative = path14.relative(root, path14.resolve(root, file_path));
6843
+ if (relative.startsWith(PARENT_PREFIX) || path14.isAbsolute(relative)) return false;
6844
+ return !test_declared_logic.is_exempt(relative.split(path14.sep).join("/"));
4359
6845
  }
4360
6846
  function is_candidate2(raw_payload, root) {
4361
6847
  const payload = hook_decision.parse_hook_payload(raw_payload);
@@ -4412,7 +6898,8 @@ async function mark_phase(outcome) {
4412
6898
  }
4413
6899
  async function async_reason(raw_payload) {
4414
6900
  const watcher = await run_watcher_hook.watcher_hook_reason(raw_payload);
4415
- return watcher ?? await run_parent_cut_hook.parent_cut_reason(raw_payload);
6901
+ const cut = watcher ?? await run_parent_cut_hook.parent_cut_reason(raw_payload);
6902
+ return cut ?? await issue_watch_hook.watch_reason();
4416
6903
  }
4417
6904
  async function pretool_outcome_async(raw_payload) {
4418
6905
  const base = guard_outcome(raw_payload);