@joshuafolkken/kit 1.1094.0 → 1.1136.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 (177) hide show
  1. package/.claude/agents/investigator.md +17 -0
  2. package/.claude/settings.json +1 -0
  3. package/.claude/skills/workflow-commands/SKILL.md +1 -1
  4. package/.claude/skills/workflow-commands/background-commands.md +36 -85
  5. package/.claude/skills/workflow-commands/backlogrun-progress.md +31 -34
  6. package/.claude/skills/workflow-commands/backlogrun-steps.md +2 -2
  7. package/.claude/skills/workflow-commands/delegation.md +5 -1
  8. package/.claude/skills/workflow-commands/fullrun.md +5 -4
  9. package/.claude/skills/workflow-commands/halfrun.md +5 -4
  10. package/.claude/skills/workflow-commands/latest-gate.md +7 -15
  11. package/.claude/skills/workflow-commands/pre-gate-cut.md +4 -8
  12. package/.claude/skills/workflow-commands/split-assessment.md +4 -18
  13. package/.github/actions/setup-node/action.yml +33 -0
  14. package/.github/actions/setup-pnpm/action.yml +4 -4
  15. package/.github/workflows/auto-tag.yml +2 -3
  16. package/.github/workflows/ci.yml +7 -8
  17. package/.github/workflows/dependabot-auto-merge.yml +1 -0
  18. package/.github/workflows/pr-classification.yml +1 -3
  19. package/.github/workflows/production.yml +1 -0
  20. package/.github/workflows/publish.yml +10 -9
  21. package/.github/workflows/sonar-qube.yml +17 -13
  22. package/.pnpmfile.mjs +29 -0
  23. package/AGENTS.md +4 -11
  24. package/CLAUDE.md +24 -17
  25. package/GEMINI.md +4 -13
  26. package/README.md +8 -3
  27. package/SECURITY.md +2 -0
  28. package/cspell/index.yaml +4 -0
  29. package/dist/CLAUDE.basic.md +6 -6
  30. package/dist/CLAUDE.md +24 -17
  31. package/dist/CLAUDE.static.md +6 -6
  32. package/dist/config-merge/index.js +33 -9
  33. package/dist/hooks/batch-guard.js +4 -4
  34. package/dist/hooks/{chunk-OIZUHPJI.js → chunk-FO2I7UT7.js} +1 -1
  35. package/dist/hooks/{chunk-NKOG3XAV.js → chunk-GDU26K3J.js} +11 -3
  36. package/dist/hooks/{chunk-O4LL4HTI.js → chunk-HANSKHES.js} +2 -2
  37. package/dist/hooks/{chunk-3C4YCCEF.js → chunk-HBKZLITF.js} +4 -4
  38. package/dist/hooks/{chunk-UD24EAIL.js → chunk-JKKTVDAG.js} +1984 -146
  39. package/dist/hooks/{chunk-M2XDCUKD.js → chunk-KBXZLMRH.js} +89 -1803
  40. package/dist/hooks/{chunk-IL27YTPH.js → chunk-KOKOAV6D.js} +2 -2
  41. package/dist/hooks/{chunk-7ZPFAVR7.js → chunk-LJBLGHEH.js} +59 -19
  42. package/dist/hooks/{chunk-E54KGFEQ.js → chunk-NFZGFGOR.js} +1 -1
  43. package/dist/hooks/{chunk-KHWHKJOM.js → chunk-RFWWUI5F.js} +4 -4
  44. package/dist/hooks/codex-hook-adapter.js +12 -47
  45. package/dist/hooks/duplicate-read-guard.js +5 -5
  46. package/dist/hooks/format-edited.js +2 -2
  47. package/dist/hooks/inputs.json +175 -173
  48. package/dist/hooks/investigation-guard.js +5 -5
  49. package/dist/hooks/pretool-guard.js +9 -9
  50. package/dist/hooks/stop-guard.js +17 -12
  51. package/dist/josh.js +87 -31
  52. package/dist/version/index.js +36 -20
  53. package/eslint/rules/unicorn.js +3 -2
  54. package/package.json +23 -5
  55. package/pnpm-workspace.yaml +5 -7
  56. package/prompts/collaboration-workflow/glossary.md +17 -0
  57. package/prompts/collaboration-workflow/issue-template.md +1 -1
  58. package/prompts/collaboration-workflow/operating-rules.md +1 -1
  59. package/prompts/collaboration-workflow/principles.md +9 -0
  60. package/prompts/collaboration-workflow.md +1 -0
  61. package/scripts/backlog/backlog-arrival.ts +30 -10
  62. package/scripts/backlog/backlog-budget-cli.ts +15 -16
  63. package/scripts/backlog/backlog-offer-cli.ts +6 -14
  64. package/scripts/backlog/backlog-plan.ts +29 -18
  65. package/scripts/backlog/backlog-ready.ts +20 -7
  66. package/scripts/config-merge/parse-jsonc.ts +33 -3
  67. package/scripts/config-merge/patch-json-key.ts +13 -6
  68. package/scripts/cost-runtime/cost-cli.ts +3 -7
  69. package/scripts/delegation/delegation-policy.ts +9 -1
  70. package/scripts/delegation/investigation-guard.ts +1 -1
  71. package/scripts/delegation/investigation-reads.ts +105 -19
  72. package/scripts/doctor/doctor-consumer.ts +3 -5
  73. package/scripts/doctor/doctor-io.ts +9 -13
  74. package/scripts/document/backlogrun-parent-read-set.ts +12 -1
  75. package/scripts/document/capped-print.ts +74 -0
  76. package/scripts/document/document-byte-budget.ts +1 -0
  77. package/scripts/document/document-section-cli.ts +4 -3
  78. package/scripts/document/entry-read-budget.ts +13 -7
  79. package/scripts/document/entry-read-set.ts +32 -8
  80. package/scripts/document/lane-child-read-set.ts +7 -0
  81. package/scripts/document/read-set-point-of-use.ts +8 -3
  82. package/scripts/document/read-set-trim.ts +3 -1
  83. package/scripts/epic/epic-audit.ts +3 -18
  84. package/scripts/gate/scoped-green.ts +25 -14
  85. package/scripts/gh/git-gh-issue-list.ts +12 -11
  86. package/scripts/gh/git-gh-issue-write.ts +4 -1
  87. package/scripts/gh/git-gh-pr-auto-merge.ts +4 -1
  88. package/scripts/git/git-command.ts +6 -1
  89. package/scripts/git/git-spawn-sync.ts +65 -0
  90. package/scripts/git/git-spawn.ts +5 -4
  91. package/scripts/git/stash/stash-pop-args.ts +1 -6
  92. package/scripts/init/claude-kit-only-settings.ts +29 -0
  93. package/scripts/init/init-copy-content.ts +8 -2
  94. package/scripts/init/init-file-action.ts +54 -0
  95. package/scripts/init/init-logic-migrate.ts +35 -17
  96. package/scripts/init/init-logic-secretlint.ts +1 -1
  97. package/scripts/init/init-logic.ts +6 -22
  98. package/scripts/init/init.ts +11 -68
  99. package/scripts/init/initial-commit.ts +24 -0
  100. package/scripts/init/kit-written-paths.ts +2 -0
  101. package/scripts/init/project-profile.ts +3 -6
  102. package/scripts/init/start-exec.ts +16 -3
  103. package/scripts/init/start-steps.ts +10 -13
  104. package/scripts/issue/defect-rate-cli.ts +61 -20
  105. package/scripts/issue/issue-backlinks.ts +7 -14
  106. package/scripts/issue/issue-cite.ts +12 -6
  107. package/scripts/issue/issue-file.ts +5 -12
  108. package/scripts/issue/issue-read-cli.ts +1 -0
  109. package/scripts/issue/issue-report-failures.ts +6 -2
  110. package/scripts/issue/issue-state-cli.ts +1 -1
  111. package/scripts/issue/markdown-section.ts +21 -6
  112. package/scripts/issue/measure-rerun-cli.ts +73 -14
  113. package/scripts/josh/josh-commands-lane.ts +1 -1
  114. package/scripts/josh/josh-commands-project.ts +8 -1
  115. package/scripts/josh/josh-commands-workflow.ts +1 -1
  116. package/scripts/josh/run-github-prerequisite.ts +3 -6
  117. package/scripts/lane/lane-await.ts +89 -15
  118. package/scripts/lane/lane-cli.ts +11 -13
  119. package/scripts/lane/lane-close.ts +4 -1
  120. package/scripts/lane/lane-launch-cli.ts +10 -16
  121. package/scripts/lane/openai-review-broker.ts +4 -1
  122. package/scripts/lib/cli-flags.ts +31 -2
  123. package/scripts/lib/error-message.ts +12 -1
  124. package/scripts/lines/line-targets.ts +0 -11
  125. package/scripts/lines/lines-command.ts +5 -3
  126. package/scripts/propagate/propagate-git.ts +3 -8
  127. package/scripts/refactor/refactor-scan.ts +2 -1
  128. package/scripts/registry-migration/migrate-logic.ts +28 -19
  129. package/scripts/registry-migration/migrate.ts +6 -5
  130. package/scripts/release/github-release-cli.ts +14 -3
  131. package/scripts/release/github-release-environment.ts +1 -0
  132. package/scripts/release/github-release.ts +103 -17
  133. package/scripts/release/release-publish.ts +36 -2
  134. package/scripts/release/release-worktree.ts +97 -2
  135. package/scripts/review/review-checkout.ts +3 -2
  136. package/scripts/review/review-record-cli.ts +9 -16
  137. package/scripts/rules/early-heartbeat.ts +4 -3
  138. package/scripts/rules/lane-park.ts +9 -0
  139. package/scripts/rules/stop-rules.ts +7 -4
  140. package/scripts/run/run-carry-args.ts +8 -12
  141. package/scripts/run/run-carry-cli.ts +3 -1
  142. package/scripts/run/run-carry-conversation.ts +94 -0
  143. package/scripts/run/run-carry-reclaim.ts +37 -0
  144. package/scripts/run/run-carry.ts +21 -5
  145. package/scripts/run/run-cut-args.ts +1 -6
  146. package/scripts/run/run-ending-cli.ts +1 -5
  147. package/scripts/run/run-entry-cli.ts +40 -9
  148. package/scripts/run/run-entry-stop.ts +104 -0
  149. package/scripts/run/run-event-stream-emit.ts +7 -2
  150. package/scripts/run/run-hold.ts +4 -1
  151. package/scripts/run/run-liveness-cli.ts +1 -5
  152. package/scripts/run/run-merge-cli.ts +2 -10
  153. package/scripts/run/run-merge-steps.ts +4 -1
  154. package/scripts/run/run-parent-cut-hook.ts +4 -1
  155. package/scripts/run/run-prep-cli.ts +4 -1
  156. package/scripts/run/run-progress-args.ts +20 -4
  157. package/scripts/run/run-progress-cli.ts +31 -29
  158. package/scripts/run/run-progress-clock.ts +4 -1
  159. package/scripts/run/run-ship-cli.ts +8 -16
  160. package/scripts/run/run-ship-probe.ts +4 -1
  161. package/scripts/run/run-status-cli.ts +2 -15
  162. package/scripts/run/run-tidy-lanes.ts +4 -1
  163. package/scripts/run/run-wake-cli.ts +2 -10
  164. package/scripts/run/run-watcher-guard.ts +9 -5
  165. package/scripts/safe-chain/pack-hook.ts +92 -0
  166. package/scripts/sync/sync-ai-files.ts +4 -0
  167. package/scripts/test/test-declared-changed.ts +13 -16
  168. package/scripts/test/test-declared.ts +3 -7
  169. package/scripts/test/test-related.ts +1 -6
  170. package/scripts/test/test-unit-guard.ts +21 -7
  171. package/scripts/time-runtime/time-spans.ts +4 -0
  172. package/scripts/version/version-commands.ts +11 -1
  173. package/templates/CLAUDE.basic.md +6 -6
  174. package/templates/workflows/ci.yml +16 -82
  175. package/templates/workflows/dependabot-auto-merge.yml +1 -0
  176. package/templates/workflows/github-release.yml +14 -28
  177. package/tsconfig.sonar.json +4 -22
@@ -1,32 +1,29 @@
1
1
  import {
2
2
  ALREADY_DONE_LABEL,
3
- BREAKING_CHANGE_LABEL,
4
- BUGFIX_LABEL,
5
3
  CONTEXT_CUT_THRESHOLD,
6
- ENHANCEMENT_LABEL,
7
- FULL_PAGE_QUERY,
8
4
  IN_PROGRESS_LABEL,
9
5
  NEEDS_DECISION_LABEL,
10
6
  NEEDS_HUMAN_REVIEW_LABEL,
7
+ PORCELAIN_FLAG,
11
8
  RECENT_REQUEST_WINDOW,
12
- RELEASE_CLASSIFICATION_NAMES,
13
9
  agent_role_profile,
14
- agent_session_environment,
15
10
  bash_triggers,
11
+ cli_flags,
16
12
  error_text,
17
13
  filing_cap,
18
- gh_failure,
19
14
  git_command,
20
15
  git_common_directory,
21
- git_gh_api_path,
22
- git_gh_exec,
16
+ git_gh_command,
17
+ git_gh_issue_read,
18
+ git_gh_pr_read,
19
+ git_spawn_sync,
23
20
  has_any_label,
24
- has_stderr_field,
25
21
  issue_cite,
26
22
  lane_background,
27
23
  lane_park,
28
24
  lane_registry,
29
- parse_json_array_or_undefined,
25
+ open_issue_schema,
26
+ own_session,
30
27
  parse_json_object_safe,
31
28
  read_json_listing,
32
29
  repo_origin,
@@ -38,31 +35,31 @@ import {
38
35
  run_tail,
39
36
  shell_segments,
40
37
  tail_commands
41
- } from "./chunk-UD24EAIL.js";
38
+ } from "./chunk-JKKTVDAG.js";
42
39
  import {
43
40
  find_local_bin_upwards
44
41
  } from "./chunk-3V37IID6.js";
45
42
  import {
46
43
  batch_outcome
47
- } from "./chunk-IL27YTPH.js";
44
+ } from "./chunk-KOKOAV6D.js";
48
45
  import {
49
46
  investigation_refusal
50
- } from "./chunk-KHWHKJOM.js";
47
+ } from "./chunk-RFWWUI5F.js";
51
48
  import {
52
49
  duplicate_read_outcome
53
- } from "./chunk-3C4YCCEF.js";
50
+ } from "./chunk-HBKZLITF.js";
54
51
  import {
55
52
  investigation_reads
56
- } from "./chunk-7ZPFAVR7.js";
53
+ } from "./chunk-LJBLGHEH.js";
57
54
  import {
58
55
  lane_guard_policy,
59
56
  time_batch_guard
60
- } from "./chunk-O4LL4HTI.js";
57
+ } from "./chunk-HANSKHES.js";
61
58
  import {
62
59
  hook_decision,
63
60
  lane_child_marker,
64
61
  run_issue_number
65
- } from "./chunk-E54KGFEQ.js";
62
+ } from "./chunk-NFZGFGOR.js";
66
63
  import {
67
64
  PLATFORM_TEMP_ROOT,
68
65
  cost_attribute,
@@ -74,7 +71,7 @@ import {
74
71
  lane_paths,
75
72
  stamp_file,
76
73
  time_shell
77
- } from "./chunk-NKOG3XAV.js";
74
+ } from "./chunk-GDU26K3J.js";
78
75
 
79
76
  // scripts/rules/direct-filing.ts
80
77
  var DIRECT_FILING_REASON = '\u26D4 direct filing: an Issue is filed with `pnpm josh issue:file "<title>" --body-file <path> --depth <0|1|2> [--route <route>] [--label <name>] [--repo <owner/repo>]`, never with `gh api \u2026/issues` or `gh issue create`. The command runs every filing step in order \u2014 the duplicate scout, the body lint and its classification labels, the depth and `route:` labels, the `## Origin` check when filing into another repository, and `epic:bundle` after the create \u2014 so none of them is a step to remember. When the scout prints candidates it holds the filing: read each, then reissue with `--distinct <N,\u2026>` for the ones that are separate deliverables. Reference: `docs/josh-commands-automation.md` \u2192 "`josh issue:file`". **This rule fires on every occurrence, not once per run.**';
@@ -298,7 +295,8 @@ function is_life_fresh(target, threshold_ms) {
298
295
  try {
299
296
  const pinged_ms = parse_pinged_at(raw);
300
297
  return pinged_ms !== void 0 && Date.now() - pinged_ms < threshold_ms;
301
- } catch {
298
+ } catch (error) {
299
+ error_text.trace_swallowed("run_progress_clock.is_life_fresh", error);
302
300
  return false;
303
301
  }
304
302
  }
@@ -442,7 +440,7 @@ function decide(call, run2, can_record) {
442
440
  if (can_record) ARM_RECORD.record(target, lands_ms);
443
441
  return false;
444
442
  }
445
- var EARLY_HEARTBEAT_REASON = '\u26D4 early heartbeat: this call arms a wait timer of its own, and the progress clock is not yours to keep. `pnpm josh run:progress --wait` waits the interval out for you (`JOSH_PROGRESS_INTERVAL_MINUTES`, or `josh.progress_interval_minutes` in `package.json`, default 20 minutes), prints the five labelled lines and exits \u2014 start it in the background, relay the lines it printed when it exits, and start the next one. Two timers armed at once is what produced reports 3\u20135 minutes apart on a 15-minute setting (joshuafolkken/kit#1570): a new one was armed on the turn a timer fired and again on the turn a child\'s completion woke the run, and `--mark` recorded each report without anything refusing the early ones. **An explicit ask is not a heartbeat**: if the person asked for progress now, run `pnpm josh run:progress --once`, which prints the five labelled lines whatever the clock says. If you are waiting on something rather than on a clock, wait on the thing itself \u2014 `pnpm josh followup` waits for CI. The procedure is `.claude/skills/workflow-commands/backlogrun.md` \u2192 "Progress while the run is quiet". **This rule fires on every early arm, not once per run**, so reissuing the same sleep will be refused again.';
443
+ var EARLY_HEARTBEAT_REASON = "\u26D4 early heartbeat: this call arms a wait timer of its own, and the progress clock is not yours to keep. `pnpm josh run:progress --wait` keeps it for you (`JOSH_PROGRESS_INTERVAL_MINUTES`, or `josh.progress_interval_minutes` in `package.json`, default 20 minutes): start it once in the background and it reports the five labelled lines to the run's event stream on its own, without waking you \u2014 relay nothing, and start it again only after it exits, which it does when newly runnable work arrives. Two timers armed at once is what produced reports 3\u20135 minutes apart on a 15-minute setting (joshuafolkken/kit#1570): a new one was armed on the turn a timer fired and again on the turn a child's completion woke the run, and `--mark` recorded each report without anything refusing the early ones. **An explicit ask is not a heartbeat**: if the person asked for progress now, run `pnpm josh run:progress --once`, which prints the five labelled lines whatever the clock says. If you are waiting on something rather than on a clock, wait on the thing itself \u2014 `pnpm josh followup` waits for CI. The procedure is `.claude/skills/workflow-commands/backlogrun.md` \u2192 \"Progress while the run is quiet\". **This rule fires on every early arm, not once per run**, so reissuing the same sleep will be refused again.";
446
444
  var PROGRESS_NAMES = /* @__PURE__ */ new Set(["run:progress"]);
447
445
  var WATCH_FLAG = /(?:^|\s)--(?:wait|once)(?=\s|$)/u;
448
446
  function is_progress_watch_segment(segment) {
@@ -671,7 +669,6 @@ var git_force = {
671
669
 
672
670
  // scripts/cost-runtime/cost-cli.ts
673
671
  import { fileURLToPath } from "node:url";
674
- import { parseArgs } from "node:util";
675
672
 
676
673
  // scripts/cost-runtime/codex-usage.ts
677
674
  import { globSync, readFileSync as readFileSync2 } from "node:fs";
@@ -896,25 +893,6 @@ var cost_verdict = {
896
893
  report_over
897
894
  };
898
895
 
899
- // scripts/cost-runtime/own-session.ts
900
- var NOT_FOUND = -1;
901
- function session_id_of(environment) {
902
- const value = environment[agent_session_environment.SESSION_ID_KEY];
903
- return value === void 0 || value === "" ? void 0 : value;
904
- }
905
- function select_own_session(files, environment) {
906
- const session_id = session_id_of(environment);
907
- if (session_id === void 0) {
908
- return { kind: "own", index: cost_transcript.latest_own_index(files) };
909
- }
910
- const index = files.findIndex((file) => file.session_id === session_id);
911
- return index === NOT_FOUND ? { kind: "absent", session_id } : { kind: "own", index };
912
- }
913
- var own_session = {
914
- session_id_of,
915
- select_own_session
916
- };
917
-
918
896
  // scripts/cost-runtime/transcript-cwd.ts
919
897
  import path3 from "node:path";
920
898
  function resolve(target, cwd) {
@@ -958,12 +936,8 @@ var PARSE_ARGS_OPTIONS = {
958
936
  path: { type: "string" }
959
937
  };
960
938
  function parse_options(argv) {
961
- try {
962
- const { values } = parseArgs({ args: [...argv], options: PARSE_ARGS_OPTIONS, strict: true });
963
- return to_options(values);
964
- } catch {
965
- return void 0;
966
- }
939
+ const values = cli_flags.values_of(argv, PARSE_ARGS_OPTIONS);
940
+ return values === void 0 ? void 0 : to_options(values);
967
941
  }
968
942
  function report_empty(cwd, session_id) {
969
943
  const searched = cost_transcript.searched_directories(cost_transcript.transcript_directories(cwd));
@@ -2026,16 +2000,10 @@ import path5 from "node:path";
2026
2000
  import { existsSync as existsSync2 } from "node:fs";
2027
2001
  import path4 from "node:path";
2028
2002
 
2029
- // scripts/lib/spawn-exit.ts
2030
- function read_spawn_stdout(result) {
2031
- return result.stdout ?? "";
2032
- }
2033
-
2034
2003
  // scripts/version/kit-descriptor.ts
2035
2004
  var KIT_PACKAGE_NAME = "@joshuafolkken/kit";
2036
2005
 
2037
2006
  // scripts/doctor/doctor-consumer.ts
2038
- import { execaSync } from "execa";
2039
2007
  import { z as z6 } from "zod";
2040
2008
  var NODE_MODULES = "node_modules";
2041
2009
  var SETTINGS_PATH = path4.join(".claude", "settings.json");
@@ -2077,11 +2045,9 @@ function is_plugin_declared(root) {
2077
2045
  return parsed.success && parsed.data.enabledPlugins?.[PLUGIN_ID] === true;
2078
2046
  }
2079
2047
  function configured_hooks_path(root) {
2080
- const result = execaSync("git", ["-C", root, "config", "--get", "core.hooksPath"], {
2081
- reject: false,
2048
+ const value = git_spawn_sync.read(["-C", root, "config", "--get", "core.hooksPath"], {
2082
2049
  timeout: GIT_TIMEOUT_MS
2083
2050
  });
2084
- const value = read_spawn_stdout(result).trim();
2085
2051
  return value === "" ? void 0 : value;
2086
2052
  }
2087
2053
  function claude_md_state(root) {
@@ -2141,6 +2107,7 @@ function report_consumer_setup(root) {
2141
2107
  var doctor_consumer = {
2142
2108
  claude_md_line,
2143
2109
  claude_md_state,
2110
+ configured_hooks_path,
2144
2111
  hooks_path_line,
2145
2112
  is_kit_consumer,
2146
2113
  is_plugin_declared,
@@ -2543,9 +2510,6 @@ var shell_body_trigger = {
2543
2510
  keeps_body_safe
2544
2511
  };
2545
2512
 
2546
- // scripts/test/test-declared-changed.ts
2547
- import { execFileSync } from "node:child_process";
2548
-
2549
2513
  // scripts/gate/project-checks.ts
2550
2514
  import { existsSync as existsSync4, globSync as globSync2, readFileSync as readFileSync4 } from "node:fs";
2551
2515
  import path7 from "node:path";
@@ -2553,7 +2517,6 @@ import path7 from "node:path";
2553
2517
  // scripts/init/project-profile.ts
2554
2518
  import { existsSync as existsSync3, readdirSync, readFileSync as readFileSync3 } from "node:fs";
2555
2519
  import path6 from "node:path";
2556
- import { execaSync as execaSync2 } from "execa";
2557
2520
  var IGNORED_DIRECTORIES = /* @__PURE__ */ new Set([".git", "node_modules", "dist", "build", ".svelte-kit"]);
2558
2521
  var WEB_EXTENSIONS = /* @__PURE__ */ new Set([".html", ".css", ".js", ".jsx", ".mjs", ".cjs"]);
2559
2522
  var TYPESCRIPT_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".tsx"]);
@@ -2644,11 +2607,8 @@ function scan_files(root) {
2644
2607
  return { has_web, has_typescript };
2645
2608
  }
2646
2609
  function has_github_remote(root) {
2647
- const result = execaSync2("git", ["config", "--get", "remote.origin.url"], {
2648
- cwd: root,
2649
- reject: false
2650
- });
2651
- return result.exitCode === 0 && repo_origin.parse_origin_url(result.stdout) !== void 0;
2610
+ const url = git_spawn_sync.origin_url(root);
2611
+ return url !== void 0 && repo_origin.parse_origin_url(url) !== void 0;
2652
2612
  }
2653
2613
  function inspect_project(root, requested) {
2654
2614
  const profile = resolve_profile(root, requested);
@@ -2874,15 +2834,9 @@ function path_of(line) {
2874
2834
  return arrow === -1 ? body : body.slice(arrow + RENAME_ARROW.length);
2875
2835
  }
2876
2836
  function read_changed_paths_sync() {
2877
- try {
2878
- const output = execFileSync("git", ["status", "--porcelain"], {
2879
- encoding: "utf8",
2880
- stdio: ["ignore", "pipe", "ignore"]
2881
- });
2882
- return output.split("\n").filter((line) => line.length > STATUS_PREFIX_LENGTH).map((line) => path_of(line));
2883
- } catch {
2884
- return [];
2885
- }
2837
+ const output = git_spawn_sync.run(["status", PORCELAIN_FLAG], { timeout: 0 });
2838
+ if (output.exit_code !== 0) return [];
2839
+ return output.stdout.split("\n").filter((line) => line.length > STATUS_PREFIX_LENGTH).map((line) => path_of(line));
2886
2840
  }
2887
2841
  var injected = {};
2888
2842
  function source_paths() {
@@ -3344,1680 +3298,11 @@ var delivered_rules = {
3344
3298
  };
3345
3299
 
3346
3300
  // scripts/run/run-watcher-hook.ts
3347
- import { z as z19 } from "zod";
3301
+ import { z as z12 } from "zod";
3348
3302
 
3349
3303
  // scripts/run/run-progress-read.ts
3350
3304
  import { loadavg } from "node:os";
3351
3305
 
3352
- // scripts/gh/git-gh-helpers.ts
3353
- function parse_pr_state_string(result) {
3354
- const trimmed = result.trim();
3355
- return trimmed.length > 0 ? trimmed : void 0;
3356
- }
3357
- function is_pr_already_exists_message(error_message) {
3358
- return error_message.toLowerCase().includes("already exists");
3359
- }
3360
- function get_error_message_with_stderr(error) {
3361
- if (!(error instanceof Error)) return String(error);
3362
- if (has_stderr_field(error) && error.stderr.length > 0) return `${error.message}
3363
- ${error.stderr}`;
3364
- return error.message;
3365
- }
3366
- function handle_pr_create_error(error) {
3367
- const error_message = get_error_message_with_stderr(error);
3368
- if (is_pr_already_exists_message(error_message)) {
3369
- throw new Error("PR_ALREADY_EXISTS");
3370
- }
3371
- throw error;
3372
- }
3373
- var git_gh_helpers = {
3374
- parse_pr_state_string,
3375
- get_error_message_with_stderr,
3376
- handle_pr_create_error
3377
- };
3378
-
3379
- // scripts/git/schemas.ts
3380
- import { z as z8 } from "zod";
3381
- var package_name_schema = z8.object({ name: z8.string().min(1) });
3382
- var rollup_item_schema = z8.looseObject({
3383
- // eslint-disable-next-line @typescript-eslint/naming-convention -- GraphQL field name from GitHub API
3384
- __typename: z8.string().optional(),
3385
- state: z8.string().optional(),
3386
- status: z8.string().optional(),
3387
- conclusion: z8.string().optional(),
3388
- name: z8.string().optional(),
3389
- context: z8.string().optional()
3390
- });
3391
- var pr_raw_schema = z8.object({
3392
- statusCheckRollup: z8.array(rollup_item_schema).optional(),
3393
- mergeStateStatus: z8.string().optional(),
3394
- reviewDecision: z8.string().optional()
3395
- });
3396
- var pull_comment_schema = z8.object({
3397
- body: z8.string().optional(),
3398
- html_url: z8.string().optional(),
3399
- user: z8.object({ login: z8.string().optional() }).optional()
3400
- });
3401
- var ai_review_pull_comment_schema = z8.object({
3402
- body: z8.string().optional(),
3403
- url: z8.string().optional(),
3404
- author: z8.object({ login: z8.string().optional() }).optional()
3405
- });
3406
- var pr_info_schema = z8.object({
3407
- mergeable: z8.union([z8.boolean(), z8.string()]).nullable().optional(),
3408
- mergeStateStatus: z8.string().nullable().optional(),
3409
- state: z8.string().optional()
3410
- });
3411
- var epic_issue_schema = z8.object({
3412
- number: z8.number(),
3413
- body: z8.string().optional()
3414
- });
3415
- var blocking_issue_schema = z8.object({
3416
- number: z8.number(),
3417
- state: z8.string().optional(),
3418
- repository_url: z8.string().optional()
3419
- });
3420
- var blocked_by_schema = z8.object({
3421
- nodes: z8.array(blocking_issue_schema).default([]),
3422
- totalCount: z8.number().optional()
3423
- }).optional();
3424
- var epic_child_schema = z8.object({
3425
- state: z8.string().optional(),
3426
- blockedBy: blocked_by_schema
3427
- });
3428
- var rest_comment_schema = z8.looseObject({
3429
- body: z8.string().nullish(),
3430
- html_url: z8.string().optional(),
3431
- user: z8.looseObject({ login: z8.string().optional() }).nullish()
3432
- });
3433
- var issue_label_schema = z8.object({ name: z8.string() });
3434
- var epic_subject_schema = z8.object({
3435
- number: z8.number(),
3436
- state: z8.string().optional(),
3437
- labels: z8.array(issue_label_schema).optional(),
3438
- body: z8.string().optional()
3439
- });
3440
- var open_issue_schema = z8.object({
3441
- number: z8.number(),
3442
- title: z8.string(),
3443
- labels: z8.array(issue_label_schema).optional(),
3444
- createdAt: z8.string(),
3445
- blockedBy: blocked_by_schema
3446
- });
3447
-
3448
- // scripts/gh/git-gh-issue-rest.ts
3449
- import { z as z9 } from "zod";
3450
-
3451
- // scripts/gh/git-gh-rest-state.ts
3452
- var MERGED_STATE = "MERGED";
3453
- function to_gh_state(state) {
3454
- return state?.toUpperCase();
3455
- }
3456
-
3457
- // scripts/gh/git-gh-issue-rest.ts
3458
- var rest_issue_schema = z9.looseObject({
3459
- number: z9.number(),
3460
- issue_dependencies_summary: z9.looseObject({ total_blocked_by: z9.number().optional() }).nullish(),
3461
- // Present only on a pull request, which this endpoint serves as readily as an issue.
3462
- pull_request: z9.looseObject({ merged_at: z9.string().nullish() }).nullish()
3463
- });
3464
- var REPOSITORY_URL = /\/repos\/([\w.-]+\/[\w.-]+)$/u;
3465
- var REPOSITORY_URL_GROUP = 1;
3466
- var BLOCKED_BY_FIELD = "blockedBy";
3467
- var BLOCKED_BY_COUNT_FIELD = "blocked_by_count";
3468
- var STATE_FIELD = "state";
3469
- var BODY_FIELD = "body";
3470
- var FIELD_SEPARATOR = ",";
3471
- var EMPTY_BODY = "";
3472
- var REST_FIELD_NAMES = /* @__PURE__ */ new Map([
3473
- ["url", "html_url"],
3474
- ["createdAt", "created_at"]
3475
- ]);
3476
- var NOT_AN_ISSUE_MESSAGE = "gh api answered something other than an issue object";
3477
- var NOT_AN_ISSUE_LISTING_MESSAGE = "gh api answered something other than an issue listing";
3478
- var NOT_A_BLOCKER_LISTING_MESSAGE = "gh api answered something other than a blocked-by listing";
3479
- function rest_field_name(field) {
3480
- return REST_FIELD_NAMES.get(field) ?? field;
3481
- }
3482
- function split_fields(fields) {
3483
- return fields.split(FIELD_SEPARATOR).map((field) => field.trim()).filter((field) => field.length > 0);
3484
- }
3485
- function to_issue_state(rest, value) {
3486
- if (typeof rest.pull_request?.merged_at === "string") return MERGED_STATE;
3487
- return typeof value === "string" ? to_gh_state(value) : value;
3488
- }
3489
- function total_blocked_by(rest) {
3490
- return rest.issue_dependencies_summary?.total_blocked_by;
3491
- }
3492
- function to_gh_field_value(field, rest) {
3493
- if (field === BLOCKED_BY_COUNT_FIELD) return total_blocked_by(rest);
3494
- const value = rest[rest_field_name(field)];
3495
- if (field === STATE_FIELD) return to_issue_state(rest, value);
3496
- return field === BODY_FIELD ? value ?? EMPTY_BODY : value;
3497
- }
3498
- function parse_rest_issue(rest_json) {
3499
- const parsed = parse_json_object_safe(rest_json, rest_issue_schema);
3500
- if (parsed === void 0) throw new Error(NOT_AN_ISSUE_MESSAGE);
3501
- return parsed;
3502
- }
3503
- function is_pull_request(rest) {
3504
- return rest.pull_request !== void 0 && rest.pull_request !== null;
3505
- }
3506
- function parse_rest_issues(rest_json) {
3507
- const parsed = parse_json_array_or_undefined(rest_json, rest_issue_schema);
3508
- if (parsed === void 0) throw new Error(NOT_AN_ISSUE_LISTING_MESSAGE);
3509
- return parsed;
3510
- }
3511
- function empty_blocked_by() {
3512
- return { nodes: [], totalCount: 0 };
3513
- }
3514
- function repo_of_url(repository_url) {
3515
- const match = REPOSITORY_URL.exec(repository_url ?? "");
3516
- return match?.[REPOSITORY_URL_GROUP];
3517
- }
3518
- function to_blocked_by(blockers_json, exact_total) {
3519
- const parsed = parse_json_array_or_undefined(blockers_json, blocking_issue_schema);
3520
- if (parsed === void 0) throw new Error(NOT_A_BLOCKER_LISTING_MESSAGE);
3521
- const nodes = parsed.map((blocker) => ({ ...blocker, state: to_gh_state(blocker.state) }));
3522
- return { nodes, totalCount: exact_total ?? nodes.length };
3523
- }
3524
- function to_gh_issue(rest, fields, blocked_by) {
3525
- return Object.fromEntries(
3526
- fields.map((field) => [
3527
- field,
3528
- field === BLOCKED_BY_FIELD ? blocked_by : to_gh_field_value(field, rest)
3529
- ])
3530
- );
3531
- }
3532
- function to_field_text(value) {
3533
- if (typeof value === "string") return value;
3534
- return value === void 0 || value === null ? EMPTY_BODY : JSON.stringify(value);
3535
- }
3536
- var CLOSED = "CLOSED";
3537
- function reference_of_blocker(node, fallback_repo) {
3538
- const repo = repo_of_url(node.repository_url) ?? fallback_repo;
3539
- if (node.state === void 0) return { repo, number: node.number };
3540
- return { repo, number: node.number, state: node.state.toUpperCase() === CLOSED ? CLOSED : "OPEN" };
3541
- }
3542
- var git_gh_issue_rest = {
3543
- empty_blocked_by,
3544
- repo_of_url,
3545
- reference_of_blocker,
3546
- split_fields,
3547
- is_pull_request,
3548
- parse_rest_issue,
3549
- parse_rest_issues,
3550
- total_blocked_by,
3551
- to_blocked_by,
3552
- to_gh_issue,
3553
- to_field_text
3554
- };
3555
-
3556
- // scripts/gh/git-gh-reachability.ts
3557
- var RATE_LIMITED_STATUS = 429;
3558
- var SERVER_ERROR_FLOOR = 500;
3559
- function is_retryable_status(status) {
3560
- if (status >= SERVER_ERROR_FLOOR) return true;
3561
- return status === RATE_LIMITED_STATUS;
3562
- }
3563
- function classify_status(status) {
3564
- if (status === void 0) return "unreachable";
3565
- return is_retryable_status(status) ? "unreachable" : "reachable";
3566
- }
3567
- var gh_reachability = { classify_status };
3568
-
3569
- // scripts/gh/git-gh-issue-read.ts
3570
- async function read_blocked_by_listing(issue_number, repo, exact_total) {
3571
- const json = await git_gh_exec.exec_gh_api({
3572
- path: `${git_gh_api_path.blocked_by_api_path(issue_number, repo)}${git_gh_api_path.FULL_PAGE_QUERY}`
3573
- });
3574
- return git_gh_issue_rest.to_blocked_by(json, exact_total);
3575
- }
3576
- async function read_blocked_by(issue_number, rest, repo) {
3577
- if (git_gh_issue_rest.is_pull_request(rest)) return git_gh_issue_rest.empty_blocked_by();
3578
- const exact_total = git_gh_issue_rest.total_blocked_by(rest);
3579
- if (exact_total === 0) return git_gh_issue_rest.empty_blocked_by();
3580
- return await read_blocked_by_listing(issue_number, repo, exact_total);
3581
- }
3582
- function mark_followup(error) {
3583
- if (!(error instanceof Error)) return error;
3584
- const failure = gh_failure.failure_of(error);
3585
- if (failure === void 0) return error;
3586
- return gh_failure.attach(error, { ...failure, is_followup: true });
3587
- }
3588
- async function read_relations(issue_number, rest, repo) {
3589
- try {
3590
- return await read_blocked_by(issue_number, rest, repo);
3591
- } catch (error) {
3592
- throw mark_followup(error);
3593
- }
3594
- }
3595
- async function read_issue_fields(issue_number, fields, repo) {
3596
- const rest = git_gh_issue_rest.parse_rest_issue(
3597
- await git_gh_exec.exec_gh_api({ path: git_gh_api_path.issue_api_path(issue_number, repo) })
3598
- );
3599
- const requested = git_gh_issue_rest.split_fields(fields);
3600
- const blocked_by = requested.includes(BLOCKED_BY_FIELD) ? await read_relations(issue_number, rest, repo) : void 0;
3601
- return git_gh_issue_rest.to_gh_issue(rest, requested, blocked_by);
3602
- }
3603
- var NOT_FOUND_STATUS = 404;
3604
- function is_number_unresolved(failure) {
3605
- return failure.status === NOT_FOUND_STATUS && failure.is_followup !== true;
3606
- }
3607
- function to_unreadable_reason(status) {
3608
- return gh_reachability.classify_status(status) === "unreachable" ? "unreachable" : "rejected";
3609
- }
3610
- function to_read_failure(error) {
3611
- const failure = gh_failure.failure_of(error);
3612
- if (failure === void 0) return { kind: "unreadable", reason: "malformed", status: void 0 };
3613
- if (is_number_unresolved(failure)) return { kind: "missing" };
3614
- return {
3615
- kind: "unreadable",
3616
- reason: to_unreadable_reason(failure.status),
3617
- status: failure.status
3618
- };
3619
- }
3620
- async function issue_view_json_classified(issue_number, fields, repo) {
3621
- try {
3622
- const issue = await read_issue_fields(issue_number, fields, repo);
3623
- return { kind: "read", json: JSON.stringify(issue) };
3624
- } catch (error) {
3625
- return to_read_failure(error);
3626
- }
3627
- }
3628
- async function issue_view_field_classified(issue_number, field, repo) {
3629
- try {
3630
- const issue = await read_issue_fields(issue_number, field, repo);
3631
- return { kind: "read", text: git_gh_issue_rest.to_field_text(issue[field]) };
3632
- } catch (error) {
3633
- return to_read_failure(error);
3634
- }
3635
- }
3636
- async function issue_view_field(issue_number, field, repo) {
3637
- const read2 = await issue_view_field_classified(issue_number, field, repo);
3638
- return read2.kind === "read" ? read2.text : void 0;
3639
- }
3640
- async function issue_get_title(issue_number, repo) {
3641
- const result = await issue_view_field(issue_number, "title", repo);
3642
- return result === void 0 ? void 0 : git_gh_helpers.parse_pr_state_string(result);
3643
- }
3644
- async function issue_get_body(issue_number, repo) {
3645
- return await issue_view_field(issue_number, "body", repo);
3646
- }
3647
- async function issue_get_body_classified(issue_number, repo) {
3648
- return await issue_view_field_classified(issue_number, "body", repo);
3649
- }
3650
- async function issue_view_json(issue_number, fields, repo) {
3651
- const read2 = await issue_view_json_classified(issue_number, fields, repo);
3652
- return read2.kind === "read" ? read2.json : void 0;
3653
- }
3654
- var STATE_AND_RELATIONS_FIELDS = "number,state,labels,blockedBy";
3655
- async function issue_get_state_and_relations(issue_number, repo) {
3656
- return await issue_view_json(issue_number, STATE_AND_RELATIONS_FIELDS, repo);
3657
- }
3658
- async function issue_get_state_and_relations_classified(issue_number, repo) {
3659
- return await issue_view_json_classified(issue_number, STATE_AND_RELATIONS_FIELDS, repo);
3660
- }
3661
- function is_unreachable_read(failure) {
3662
- return failure.kind === "unreadable" && failure.reason === "unreachable";
3663
- }
3664
- var PLAN_FIELDS = "number,title,body,state,url,labels,blockedBy";
3665
- async function issue_get_plan_fields(issue_number) {
3666
- return await issue_view_json(issue_number, PLAN_FIELDS);
3667
- }
3668
- async function issue_get_plan_fields_classified(issue_number) {
3669
- return await issue_view_json_classified(issue_number, PLAN_FIELDS);
3670
- }
3671
- async function issue_get_labels_and_body(issue_number) {
3672
- return await issue_view_json(issue_number, "number,state,labels,body");
3673
- }
3674
- async function issue_list_comments(issue_number) {
3675
- const path10 = `${git_gh_api_path.issue_comments_api_path(issue_number)}${git_gh_api_path.FULL_PAGE_QUERY}`;
3676
- try {
3677
- return await git_gh_exec.exec_gh_api({ path: path10, should_paginate: true });
3678
- } catch {
3679
- return void 0;
3680
- }
3681
- }
3682
- async function has_no_relations_endpoint(issue_number, repo) {
3683
- const status = await git_gh_exec.exec_gh_api_status(
3684
- git_gh_api_path.blocked_by_api_path(issue_number, repo)
3685
- );
3686
- return status === NOT_FOUND_STATUS;
3687
- }
3688
- async function issue_blocked_by_references(issue_number, own_repo, repo) {
3689
- try {
3690
- const listing = await read_blocked_by_listing(issue_number, repo);
3691
- return listing.nodes.map((blocker) => git_gh_issue_rest.reference_of_blocker(blocker, own_repo));
3692
- } catch (error) {
3693
- if (await has_no_relations_endpoint(issue_number, repo)) return [];
3694
- throw error;
3695
- }
3696
- }
3697
- async function issue_blocked_by_numbers(issue_number, repo) {
3698
- const references = await issue_blocked_by_references(issue_number, "", repo);
3699
- return references.map((blocker) => blocker.number);
3700
- }
3701
- var git_gh_issue_read = {
3702
- issue_blocked_by_numbers,
3703
- issue_blocked_by_references,
3704
- issue_get_title,
3705
- issue_get_body,
3706
- issue_get_body_classified,
3707
- issue_view_json,
3708
- issue_view_json_classified,
3709
- issue_get_state_and_relations,
3710
- issue_get_state_and_relations_classified,
3711
- is_unreachable_read,
3712
- issue_get_plan_fields,
3713
- issue_get_plan_fields_classified,
3714
- issue_get_labels_and_body,
3715
- issue_list_comments
3716
- };
3717
-
3718
- // scripts/gh/git-gh-issue-list.ts
3719
- var PER_PAGE = 100;
3720
- var FIRST_PAGE = 1;
3721
- var DEFAULT_STATE = "open";
3722
- var DEFAULT_SORT = "created";
3723
- var LISTING_DIRECTION = "direction=desc";
3724
- function listing_query(request) {
3725
- const state = request.state ?? DEFAULT_STATE;
3726
- const sort = request.sort ?? DEFAULT_SORT;
3727
- return `state=${state}&sort=${sort}&${LISTING_DIRECTION}`;
3728
- }
3729
- function listing_path(request, page) {
3730
- const label = request.label === void 0 ? "" : `&labels=${encodeURIComponent(request.label)}`;
3731
- const paging = `&per_page=${String(PER_PAGE)}&page=${String(page)}`;
3732
- return `${git_gh_api_path.issues_api_path(request.repo)}?${listing_query(request)}${label}${paging}`;
3733
- }
3734
- var DIGIT_PATTERN = /\d/u;
3735
- function has_token_occurrence(body, term) {
3736
- let index = body.indexOf(term);
3737
- while (index !== -1) {
3738
- if (!DIGIT_PATTERN.test(body.charAt(index + term.length))) return true;
3739
- index = body.indexOf(term, index + 1);
3740
- }
3741
- return false;
3742
- }
3743
- function matches_body(rest, term) {
3744
- if (term === void 0) return true;
3745
- const { body } = rest;
3746
- return typeof body === "string" && has_token_occurrence(body, term);
3747
- }
3748
- function is_selected(rest, request) {
3749
- return !git_gh_issue_rest.is_pull_request(rest) && matches_body(rest, request.body_term);
3750
- }
3751
- async function fetch_page(request, page) {
3752
- const path10 = listing_path(request, page);
3753
- const rows = git_gh_issue_rest.parse_rest_issues(await git_gh_exec.exec_gh_api({ path: path10 }));
3754
- return {
3755
- selected: rows.filter((row) => is_selected(row, request)),
3756
- is_full: rows.length >= PER_PAGE
3757
- };
3758
- }
3759
- var MAX_PAGES = 5;
3760
- var MAX_SCANNED = MAX_PAGES * PER_PAGE;
3761
- function wants_more(has_more, selected_count, limit) {
3762
- return has_more && selected_count < limit;
3763
- }
3764
- async function fetch_selected(request) {
3765
- const selected = [];
3766
- let page = FIRST_PAGE;
3767
- let has_more = true;
3768
- while (page <= MAX_PAGES && wants_more(has_more, selected.length, request.limit)) {
3769
- const result = await fetch_page(request, page);
3770
- selected.push(...result.selected);
3771
- has_more = result.is_full;
3772
- page += 1;
3773
- }
3774
- return {
3775
- rows: selected.slice(0, request.limit),
3776
- is_capped: wants_more(has_more, selected.length, request.limit)
3777
- };
3778
- }
3779
- async function read_relations2(rows, repo) {
3780
- const relations = [];
3781
- for (const row of rows) {
3782
- relations.push(await read_blocked_by(String(row.number), row, repo));
3783
- }
3784
- return relations;
3785
- }
3786
- async function issue_list(request) {
3787
- try {
3788
- const { rows, is_capped } = await fetch_selected(request);
3789
- const fields = git_gh_issue_rest.split_fields(request.json_fields);
3790
- const relations = fields.includes(BLOCKED_BY_FIELD) ? await read_relations2(rows, request.repo) : void 0;
3791
- const mapped = rows.map(
3792
- (row, index) => git_gh_issue_rest.to_gh_issue(row, fields, relations?.[index])
3793
- );
3794
- return { json: JSON.stringify(mapped), is_capped };
3795
- } catch {
3796
- return { json: void 0, is_capped: false };
3797
- }
3798
- }
3799
- var git_gh_issue_list = {
3800
- issue_list
3801
- };
3802
-
3803
- // scripts/gh/git-gh-issue-write.ts
3804
- var PATCH_METHOD = "PATCH";
3805
- var DELETE_METHOD2 = "DELETE";
3806
- var HTML_URL_FILTER = ".html_url";
3807
- var ID_FILTER = ".id";
3808
- var LABELS_SEGMENT = "/labels";
3809
- var COMMENTS_SEGMENT = "/comments";
3810
- var CLOSED_STATE = "closed";
3811
- var COLOR_HASH = "#";
3812
- async function did_write_succeed(write) {
3813
- try {
3814
- await write();
3815
- return true;
3816
- } catch {
3817
- return false;
3818
- }
3819
- }
3820
- async function issue_edit_body(issue_number, body) {
3821
- return await git_gh_exec.exec_gh_api({
3822
- path: git_gh_api_path.issue_api_path(issue_number),
3823
- method: PATCH_METHOD,
3824
- body: JSON.stringify({ body }),
3825
- jq_filter: HTML_URL_FILTER
3826
- });
3827
- }
3828
- async function issue_comment(issue_number, body) {
3829
- return await git_gh_exec.exec_gh_api({
3830
- path: `${git_gh_api_path.issue_api_path(issue_number)}${COMMENTS_SEGMENT}`,
3831
- body: JSON.stringify({ body }),
3832
- jq_filter: HTML_URL_FILTER
3833
- });
3834
- }
3835
- async function issue_try_comment(issue_number, body) {
3836
- return await did_write_succeed(async () => await issue_comment(issue_number, body));
3837
- }
3838
- async function issue_close(issue_number, comment) {
3839
- return await did_write_succeed(async () => {
3840
- if (comment !== void 0) await issue_comment(issue_number, comment);
3841
- await git_gh_exec.exec_gh_api({
3842
- path: git_gh_api_path.issue_api_path(issue_number),
3843
- method: PATCH_METHOD,
3844
- body: JSON.stringify({ state: CLOSED_STATE })
3845
- });
3846
- });
3847
- }
3848
- function to_label_color(color) {
3849
- return color.startsWith(COLOR_HASH) ? color.slice(COLOR_HASH.length) : color;
3850
- }
3851
- async function label_ensure(input) {
3852
- try {
3853
- await git_gh_exec.exec_gh_api({
3854
- path: `${git_gh_api_path.repo_api_path()}${LABELS_SEGMENT}`,
3855
- body: JSON.stringify({
3856
- name: input.name,
3857
- color: to_label_color(input.color),
3858
- description: input.description
3859
- })
3860
- });
3861
- } catch {
3862
- }
3863
- }
3864
- function issue_create_request(input) {
3865
- const { labels } = input;
3866
- return {
3867
- path: git_gh_api_path.issues_api_path(input.repo),
3868
- body: JSON.stringify({
3869
- title: input.title,
3870
- ...labels !== void 0 && { labels },
3871
- body: input.body
3872
- }),
3873
- jq_filter: HTML_URL_FILTER
3874
- };
3875
- }
3876
- async function issue_create_with_label(input) {
3877
- return await git_gh_exec.exec_gh_api(
3878
- issue_create_request({ title: input.title, body: input.body, labels: [input.label] })
3879
- );
3880
- }
3881
- async function issue_add_label(issue_number, label) {
3882
- return await did_write_succeed(
3883
- async () => await git_gh_exec.exec_gh_api({
3884
- path: `${git_gh_api_path.issue_api_path(issue_number)}${LABELS_SEGMENT}`,
3885
- body: JSON.stringify({ labels: [label] })
3886
- })
3887
- );
3888
- }
3889
- async function issue_remove_label(issue_number, label) {
3890
- const labels_path = `${git_gh_api_path.issue_api_path(issue_number)}${LABELS_SEGMENT}`;
3891
- await git_gh_exec.exec_gh_api({
3892
- path: `${labels_path}/${encodeURIComponent(label)}`,
3893
- method: DELETE_METHOD2
3894
- });
3895
- }
3896
- async function read_issue_id(issue_number) {
3897
- const raw = await git_gh_exec.exec_gh_api({
3898
- path: git_gh_api_path.issue_api_path(issue_number),
3899
- jq_filter: ID_FILTER
3900
- });
3901
- const issue_id = Number(raw.trim());
3902
- if (!Number.isSafeInteger(issue_id) || issue_id <= 0) {
3903
- throw new Error(`gh api answered no database id for issue #${issue_number}`);
3904
- }
3905
- return issue_id;
3906
- }
3907
- async function issue_add_blocked_by(issue_number, blocker) {
3908
- return await did_write_succeed(async () => {
3909
- const issue_id = await read_issue_id(blocker);
3910
- await git_gh_exec.exec_gh_api({
3911
- path: git_gh_api_path.blocked_by_api_path(issue_number),
3912
- body: JSON.stringify({ issue_id })
3913
- });
3914
- });
3915
- }
3916
- async function issue_remove_blocked_by(issue_number, blocker) {
3917
- return await did_write_succeed(async () => {
3918
- const issue_id = await read_issue_id(blocker);
3919
- const relations_path = git_gh_api_path.blocked_by_api_path(issue_number);
3920
- await git_gh_exec.exec_gh_api({
3921
- path: `${relations_path}/${String(issue_id)}`,
3922
- method: DELETE_METHOD2
3923
- });
3924
- });
3925
- }
3926
- var git_gh_issue_write = {
3927
- issue_edit_body,
3928
- issue_comment,
3929
- issue_try_comment,
3930
- issue_close,
3931
- label_ensure,
3932
- issue_create_request,
3933
- issue_create_with_label,
3934
- issue_add_label,
3935
- issue_remove_label,
3936
- issue_add_blocked_by,
3937
- issue_remove_blocked_by
3938
- };
3939
-
3940
- // scripts/gh/git-gh-issue.ts
3941
- var NUMBER_AND_BODY_FIELDS = "number,body";
3942
- var BACKLOG_SCAN_FIELDS = `number,title,body,${BLOCKED_BY_COUNT_FIELD}`;
3943
- var NUMBER_TITLE_AND_LABELS_FIELDS = "number,title,labels";
3944
- var SUMMARY_FIELDS = "number,title,labels,createdAt";
3945
- var PICKUP_FIELDS = `${SUMMARY_FIELDS},blockedBy`;
3946
- var { issue_list: issue_list2 } = git_gh_issue_list;
3947
- async function issue_list_recent(limit) {
3948
- return await issue_list2({ json_fields: SUMMARY_FIELDS, limit });
3949
- }
3950
- async function issue_list_open_bodies(limit) {
3951
- return await issue_list2({ json_fields: BACKLOG_SCAN_FIELDS, limit });
3952
- }
3953
- async function issue_list_recently_closed(limit) {
3954
- return await issue_list2({
3955
- json_fields: NUMBER_TITLE_AND_LABELS_FIELDS,
3956
- limit,
3957
- state: "closed",
3958
- sort: "updated"
3959
- });
3960
- }
3961
- async function issue_search_body(term, limit) {
3962
- return await issue_list2({
3963
- json_fields: NUMBER_AND_BODY_FIELDS,
3964
- limit,
3965
- body_term: term
3966
- });
3967
- }
3968
- async function issue_list_by_label(label, limit) {
3969
- return await issue_list2({ json_fields: NUMBER_AND_BODY_FIELDS, limit, label });
3970
- }
3971
- async function issue_list_by_label_summary(label, limit, options) {
3972
- return await issue_list2({
3973
- json_fields: options?.json_fields ?? PICKUP_FIELDS,
3974
- limit,
3975
- label
3976
- });
3977
- }
3978
- async function issue_list_by_label_in_repo(label, limit, repo) {
3979
- return await issue_list2({ json_fields: SUMMARY_FIELDS, limit, label, repo });
3980
- }
3981
- var git_gh_issue = {
3982
- ...git_gh_issue_read,
3983
- ...git_gh_issue_write,
3984
- issue_list_recent,
3985
- issue_list_by_label,
3986
- issue_list_by_label_in_repo,
3987
- issue_list_by_label_summary,
3988
- issue_search_body,
3989
- issue_list_open_bodies,
3990
- issue_list_recently_closed
3991
- };
3992
-
3993
- // scripts/ci/pr-classification.ts
3994
- import { readFileSync as readFileSync5 } from "node:fs";
3995
- import { fileURLToPath as fileURLToPath2 } from "node:url";
3996
- import { z as z10 } from "zod";
3997
- var CLASSIFICATION_SET = new Set(RELEASE_CLASSIFICATION_NAMES);
3998
- var ISSUE_BUG_LABEL = "bug";
3999
- var DECLARATION_PREFIX = "- \u30EA\u30EA\u30FC\u30B9\u5206\u985E: ";
4000
- var DECLARATION = new RegExp(`^${DECLARATION_PREFIX}(.+)$`, "gmu");
4001
- var LEGACY_LABELS = /* @__PURE__ */ new Set(["semver-major", "semver-minor"]);
4002
- var LABEL = z10.object({ name: z10.string() });
4003
- var USER = z10.object({ login: z10.string() });
4004
- var PULL_REQUEST = z10.object({ number: z10.number(), user: USER });
4005
- var EVENT = z10.object({
4006
- pull_request: PULL_REQUEST,
4007
- repository: z10.object({ full_name: z10.string() })
4008
- });
4009
- function classification_error(labels, author) {
4010
- const legacy = labels.filter((label) => LEGACY_LABELS.has(label.toLowerCase()));
4011
- if (legacy.length > 0) return `Remove legacy release labels: ${legacy.join(", ")}`;
4012
- const selected = labels.filter((label) => CLASSIFICATION_SET.has(label.toLowerCase()));
4013
- if (selected.length > 1) {
4014
- return `Choose exactly one release classification; found: ${selected.join(", ")}`;
4015
- }
4016
- if (selected.length === 1 || author.endsWith("[bot]")) return void 0;
4017
- return `Choose one release classification: ${RELEASE_CLASSIFICATION_NAMES.join(", ")}`;
4018
- }
4019
- function declaration(label) {
4020
- return `${DECLARATION_PREFIX}${label}`;
4021
- }
4022
- function is_classification(value) {
4023
- return CLASSIFICATION_SET.has(value);
4024
- }
4025
- function release_candidates(candidates) {
4026
- if (!candidates.includes(BREAKING_CHANGE_LABEL)) return candidates;
4027
- return candidates.filter((candidate) => candidate !== ENHANCEMENT_LABEL);
4028
- }
4029
- function issue_candidates(issue_json) {
4030
- const issue = z10.object({ labels: z10.array(LABEL), body: z10.string().nullable() }).parse(JSON.parse(issue_json));
4031
- const names = issue.labels.map((label) => label.name.toLowerCase());
4032
- const declared = [...(issue.body ?? "").matchAll(DECLARATION)].map((match) => match[1] ?? "");
4033
- const candidates = [...release_candidates([...names, ...declared].filter(is_classification))];
4034
- const unknown = declared.filter((value) => !is_classification(value));
4035
- if (unknown.length > 0) throw new Error(`Unknown release classification: ${unknown.join(", ")}`);
4036
- if (names.includes(ISSUE_BUG_LABEL) && !candidates.includes(BREAKING_CHANGE_LABEL)) {
4037
- candidates.push(BUGFIX_LABEL);
4038
- }
4039
- return candidates;
4040
- }
4041
- function select_issue_classification(issue_json) {
4042
- const candidates = issue_candidates(issue_json);
4043
- const selected = [...new Set(candidates)];
4044
- const [label] = selected;
4045
- if (label === void 0 || selected.length > 1) {
4046
- throw new Error(
4047
- `Choose one release classification before opening the PR: ${RELEASE_CLASSIFICATION_NAMES.join(", ")}; found: ${selected.join(", ") || "none"}. Add "${DECLARATION_PREFIX}<label>" to the Issue body.`
4048
- );
4049
- }
4050
- return label;
4051
- }
4052
- function fetch_current_labels(repository, pull_number) {
4053
- const path10 = `repos/${repository}/issues/${String(pull_number)}/labels`;
4054
- try {
4055
- const names = git_gh_exec.exec_gh_api_sync({ path: path10, jq_filter: ".[].name" });
4056
- return names.split("\n").filter((name) => name !== "");
4057
- } catch (error) {
4058
- const detail = error_text.message_of(error);
4059
- throw new Error(`Could not read the pull request labels: ${detail}`, { cause: error });
4060
- }
4061
- }
4062
- function check_event(event_path, read_labels = fetch_current_labels) {
4063
- const event = EVENT.parse(JSON.parse(readFileSync5(event_path, "utf8")));
4064
- const labels = read_labels(event.repository.full_name, event.pull_request.number);
4065
- return classification_error(labels, event.pull_request.user.login);
4066
- }
4067
- if (process.argv[1] === fileURLToPath2(import.meta.url)) {
4068
- const event_path = process.env["GITHUB_EVENT_PATH"];
4069
- if (!event_path) throw new Error("GITHUB_EVENT_PATH is required");
4070
- const error = check_event(event_path);
4071
- if (error) {
4072
- console.error(`::error::${error}`);
4073
- process.exitCode = 1;
4074
- }
4075
- }
4076
- var pr_classification = {
4077
- classification_error,
4078
- check_event,
4079
- fetch_current_labels,
4080
- declaration,
4081
- is_classification,
4082
- select_issue_classification
4083
- };
4084
-
4085
- // scripts/lib/poll.ts
4086
- async function sleep(duration_ms) {
4087
- await new Promise((resolve2) => {
4088
- setTimeout(resolve2, duration_ms);
4089
- });
4090
- }
4091
- async function wait_between(wait, interval_ms, attempt, attempts) {
4092
- if (attempt < attempts - 1) await wait(interval_ms);
4093
- }
4094
- async function poll_until(is_done, options) {
4095
- const wait = options.sleeper ?? sleep;
4096
- for (let attempt = 0; attempt < options.attempts; attempt += 1) {
4097
- if (await is_done()) return true;
4098
- await wait_between(wait, options.interval_ms, attempt, options.attempts);
4099
- }
4100
- return false;
4101
- }
4102
- var poll = { poll_until, sleep };
4103
-
4104
- // scripts/gh/git-gh-pr.ts
4105
- import { z as z14 } from "zod";
4106
-
4107
- // scripts/gh/git-gh-pr-rest.ts
4108
- import { z as z11 } from "zod";
4109
- var rest_repo_schema = z11.looseObject({ full_name: z11.string().optional() }).nullish();
4110
- var rest_pull_side_schema = z11.looseObject({ repo: rest_repo_schema });
4111
- var rest_pull_schema = z11.looseObject({
4112
- number: z11.number(),
4113
- html_url: z11.string().optional(),
4114
- body: z11.string().nullish(),
4115
- state: z11.string().optional(),
4116
- merged: z11.boolean().nullish(),
4117
- merged_at: z11.string().nullish(),
4118
- mergeable: z11.boolean().nullish(),
4119
- mergeable_state: z11.string().optional(),
4120
- // `sha` is the head commit, which is what both halves of the merge-gate rollup are keyed by —
4121
- // REST hangs the check runs and the status contexts off the commit rather than off the pull
4122
- // request (joshuafolkken/kit#1028).
4123
- head: z11.looseObject({ ref: z11.string().optional(), sha: z11.string().optional(), repo: rest_repo_schema }).nullish(),
4124
- base: rest_pull_side_schema.nullish(),
4125
- // `node_id` is what the GraphQL auto-merge mutation addresses a pull request by, and `auto_merge`
4126
- // is `null` until auto-merge is enabled — both read by `git-gh-pr-auto-merge.ts`
4127
- // (joshuafolkken/kit#2497).
4128
- node_id: z11.string().optional(),
4129
- auto_merge: z11.looseObject({}).nullish()
4130
- });
4131
- var NOT_A_PULL_MESSAGE = "gh api answered something other than a pull request object";
4132
- var NOT_A_PULL_LISTING_MESSAGE = "gh api answered something other than a pull request listing";
4133
- var NOT_A_COMMENT_LISTING_MESSAGE = "gh api answered something other than a comment listing";
4134
- var OPEN_STATE2 = "open";
4135
- var EMPTY_BODY2 = "";
4136
- function parse_rest_pull(rest_json) {
4137
- const parsed = parse_json_object_safe(rest_json, rest_pull_schema);
4138
- if (parsed === void 0) throw new Error(NOT_A_PULL_MESSAGE);
4139
- return parsed;
4140
- }
4141
- function parse_rest_pulls(rest_json) {
4142
- const parsed = parse_json_array_or_undefined(rest_json, rest_pull_schema);
4143
- if (parsed === void 0) throw new Error(NOT_A_PULL_LISTING_MESSAGE);
4144
- return parsed;
4145
- }
4146
- function select_pull(pulls) {
4147
- return pulls.find((pull) => pull.state === OPEN_STATE2) ?? pulls[0];
4148
- }
4149
- function is_merged(pull) {
4150
- return pull.merged === true || typeof pull.merged_at === "string";
4151
- }
4152
- function to_pr_state(pull) {
4153
- return is_merged(pull) ? MERGED_STATE : to_gh_state(pull.state);
4154
- }
4155
- function to_repo_name(side) {
4156
- return side?.repo?.full_name;
4157
- }
4158
- function is_same_repository_head(pull) {
4159
- const head_repo = to_repo_name(pull.head);
4160
- return head_repo !== void 0 && head_repo === to_repo_name(pull.base);
4161
- }
4162
- function to_pr_info(pull) {
4163
- return {
4164
- mergeable: pull.mergeable,
4165
- mergeStateStatus: to_gh_state(pull.mergeable_state),
4166
- state: to_pr_state(pull)
4167
- };
4168
- }
4169
- function to_pr_comments(rest_json) {
4170
- const parsed = parse_json_array_or_undefined(rest_json, rest_comment_schema);
4171
- if (parsed === void 0) throw new Error(NOT_A_COMMENT_LISTING_MESSAGE);
4172
- return parsed.map((comment) => ({
4173
- body: comment.body ?? EMPTY_BODY2,
4174
- url: comment.html_url,
4175
- author: { login: comment.user?.login }
4176
- }));
4177
- }
4178
- var git_gh_pr_rest = {
4179
- parse_rest_pull,
4180
- parse_rest_pulls,
4181
- select_pull,
4182
- is_same_repository_head,
4183
- is_merged,
4184
- to_pr_state,
4185
- to_pr_info,
4186
- to_pr_comments
4187
- };
4188
-
4189
- // scripts/gh/git-gh-pr-read.ts
4190
- var pr_number_by_branch = /* @__PURE__ */ new Map();
4191
- var LOOKUP_QUERY = "state=all&sort=created&direction=desc&per_page=100";
4192
- var COMMENTS_QUERY = FULL_PAGE_QUERY;
4193
- var OWNER_PLACEHOLDER = "{owner}";
4194
- var NO_PULL_REQUEST_MESSAGE = "gh api found no pull request for branch";
4195
- var UNREADABLE_PULL_REQUEST_MESSAGE = "gh api could not read the pull requests for branch";
4196
- function lookup_path(branch_name) {
4197
- const head = `${OWNER_PLACEHOLDER}:${encodeURIComponent(branch_name)}`;
4198
- return `${git_gh_api_path.pulls_api_path()}?head=${head}&${LOOKUP_QUERY}`;
4199
- }
4200
- async function fetch_pr_number(branch_name) {
4201
- const json = await git_gh_exec.exec_gh_api({ path: lookup_path(branch_name) });
4202
- return git_gh_pr_rest.select_pull(git_gh_pr_rest.parse_rest_pulls(json))?.number;
4203
- }
4204
- var pending_pr_number_by_branch = /* @__PURE__ */ new Map();
4205
- async function fetch_pr_number_read(branch_name) {
4206
- try {
4207
- const pr_number = await fetch_pr_number(branch_name);
4208
- if (pr_number === void 0) return { kind: "missing" };
4209
- pr_number_by_branch.set(branch_name, pr_number);
4210
- return { kind: "read", pr_number };
4211
- } catch (error) {
4212
- return { kind: "unreadable", cause: error };
4213
- }
4214
- }
4215
- async function start_pr_number_read(branch_name) {
4216
- const pending = pending_pr_number_by_branch.get(branch_name);
4217
- if (pending !== void 0) return await pending;
4218
- const lookup = fetch_pr_number_read(branch_name);
4219
- pending_pr_number_by_branch.set(branch_name, lookup);
4220
- try {
4221
- return await lookup;
4222
- } finally {
4223
- pending_pr_number_by_branch.delete(branch_name);
4224
- }
4225
- }
4226
- function forget_pr_numbers() {
4227
- pr_number_by_branch.clear();
4228
- pending_pr_number_by_branch.clear();
4229
- }
4230
- async function read_pr_number(branch_name) {
4231
- const cached = pr_number_by_branch.get(branch_name);
4232
- if (cached !== void 0) return { kind: "read", pr_number: cached };
4233
- return await start_pr_number_read(branch_name);
4234
- }
4235
- async function resolve_pr_number(branch_name) {
4236
- const read2 = await read_pr_number(branch_name);
4237
- return read2.kind === "read" ? read2.pr_number : void 0;
4238
- }
4239
- function to_unreadable_error(branch_name, cause) {
4240
- return new Error(`${UNREADABLE_PULL_REQUEST_MESSAGE}: ${branch_name}`, { cause });
4241
- }
4242
- async function require_pr_number(branch_name) {
4243
- const read2 = await read_pr_number(branch_name);
4244
- if (read2.kind === "read") return read2.pr_number;
4245
- if (read2.kind === "missing") throw new Error(`${NO_PULL_REQUEST_MESSAGE}: ${branch_name}`);
4246
- throw to_unreadable_error(branch_name, read2.cause);
4247
- }
4248
- async function read_pull(pr_number) {
4249
- const json = await git_gh_exec.exec_gh_api({
4250
- path: git_gh_api_path.pull_api_path(String(pr_number))
4251
- });
4252
- return git_gh_pr_rest.parse_rest_pull(json);
4253
- }
4254
- async function read_pull_of_branch(branch_name) {
4255
- const pr_number = await resolve_pr_number(branch_name);
4256
- if (pr_number === void 0) return void 0;
4257
- try {
4258
- return await read_pull(pr_number);
4259
- } catch {
4260
- return void 0;
4261
- }
4262
- }
4263
- async function pr_exists(branch_name) {
4264
- const read2 = await read_pr_number(branch_name);
4265
- if (read2.kind === "unreadable") throw to_unreadable_error(branch_name, read2.cause);
4266
- return read2.kind === "read";
4267
- }
4268
- async function pr_get_number(branch_name) {
4269
- return await resolve_pr_number(branch_name);
4270
- }
4271
- async function pr_get_url(branch_name) {
4272
- const pull = await read_pull_of_branch(branch_name);
4273
- if (pull?.html_url === void 0) return void 0;
4274
- return git_gh_helpers.parse_pr_state_string(pull.html_url);
4275
- }
4276
- async function pr_get_merge_state(branch_name) {
4277
- const pull = await read_pull_of_branch(branch_name);
4278
- if (pull === void 0) return void 0;
4279
- return {
4280
- is_merged: git_gh_pr_rest.is_merged(pull),
4281
- merged_at: pull.merged_at ?? void 0,
4282
- head_sha: pull.head?.sha
4283
- };
4284
- }
4285
- async function pr_get_body(branch_name) {
4286
- const pull = await read_pull_of_branch(branch_name);
4287
- const body = pull?.body;
4288
- return typeof body === "string" && body.length > 0 ? body : void 0;
4289
- }
4290
- async function pr_view(branch_name) {
4291
- const pull = await read_pull_of_branch(branch_name);
4292
- if (pull === void 0) return "";
4293
- return JSON.stringify(git_gh_pr_rest.to_pr_info(pull));
4294
- }
4295
- async function read_comments(branch_name, to_path, to_json) {
4296
- const pr_number = await resolve_pr_number(branch_name);
4297
- if (pr_number === void 0) return void 0;
4298
- const path10 = `${to_path(String(pr_number))}${COMMENTS_QUERY}`;
4299
- try {
4300
- return to_json(await git_gh_exec.exec_gh_api({ path: path10, should_paginate: true }));
4301
- } catch {
4302
- return void 0;
4303
- }
4304
- }
4305
- function to_comments_json(raw) {
4306
- return JSON.stringify(git_gh_pr_rest.to_pr_comments(raw));
4307
- }
4308
- function as_served(raw) {
4309
- return raw;
4310
- }
4311
- async function pr_get_comments(branch_name) {
4312
- return await read_comments(branch_name, git_gh_api_path.issue_comments_api_path, to_comments_json);
4313
- }
4314
- async function pr_get_review_comments(branch_name) {
4315
- return await read_comments(branch_name, git_gh_api_path.pull_comments_api_path, as_served);
4316
- }
4317
- var git_gh_pr_read = {
4318
- pr_exists,
4319
- pr_get_number,
4320
- pr_get_url,
4321
- pr_get_body,
4322
- pr_get_merge_state,
4323
- pr_view,
4324
- pr_get_comments,
4325
- pr_get_review_comments
4326
- };
4327
-
4328
- // scripts/gh/git-gh-pr-review.ts
4329
- import { z as z12 } from "zod";
4330
- var REVIEW_APPROVED = "APPROVED";
4331
- var REVIEW_CHANGES_REQUESTED = "CHANGES_REQUESTED";
4332
- var REVIEW_NONE = "";
4333
- var STATE_CHANGING_REVIEWS = /* @__PURE__ */ new Set([REVIEW_APPROVED, REVIEW_CHANGES_REQUESTED]);
4334
- var rest_review_schema = z12.looseObject({
4335
- state: z12.string().optional(),
4336
- user: z12.looseObject({ login: z12.string().optional() }).nullish()
4337
- });
4338
- var NOT_A_REVIEW_LISTING = "gh api answered something other than a review listing";
4339
- function parse_rest_reviews(reviews_json) {
4340
- const parsed = parse_json_array_or_undefined(reviews_json, rest_review_schema);
4341
- if (parsed === void 0) throw new Error(NOT_A_REVIEW_LISTING);
4342
- return parsed;
4343
- }
4344
- var UNATTRIBUTED_REVIEWER = "(no author)";
4345
- function read_reviewer(review) {
4346
- const login = review.user?.login;
4347
- return typeof login === "string" && login.length > 0 ? login : UNATTRIBUTED_REVIEWER;
4348
- }
4349
- function read_state_changing(review) {
4350
- const state = review.state?.toUpperCase();
4351
- return state !== void 0 && STATE_CHANGING_REVIEWS.has(state) ? state : void 0;
4352
- }
4353
- function fold_latest_states(reviews) {
4354
- const latest = /* @__PURE__ */ new Map();
4355
- for (const review of reviews) {
4356
- const state = read_state_changing(review);
4357
- if (state !== void 0) latest.set(read_reviewer(review), state);
4358
- }
4359
- return latest;
4360
- }
4361
- function to_review_decision(reviews_json) {
4362
- const latest = new Set(fold_latest_states(parse_rest_reviews(reviews_json)).values());
4363
- if (latest.has(REVIEW_CHANGES_REQUESTED)) return REVIEW_CHANGES_REQUESTED;
4364
- return latest.has(REVIEW_APPROVED) ? REVIEW_APPROVED : REVIEW_NONE;
4365
- }
4366
- var git_gh_pr_review = { to_review_decision };
4367
-
4368
- // scripts/gh/git-gh-pr-rollup.ts
4369
- import { z as z13 } from "zod";
4370
- var STATUS_CONTEXT_TYPE_NAME = "StatusContext";
4371
- var TYPE_NAME_KEY = "__typename";
4372
- var rollup_element_schema = z13.looseObject({});
4373
- var check_runs_page_schema = z13.looseObject({
4374
- // Required, not optional: GitHub always names the key, and accepting a page without one would
4375
- // answer an empty rollup — which `git-pr-followup.ts` reports as "this branch has no checks".
4376
- check_runs: z13.array(rollup_element_schema)
4377
- });
4378
- var id_holder_schema = z13.object({ id: z13.number() });
4379
- var status_page_schema = z13.looseObject({
4380
- statuses: z13.array(rollup_element_schema)
4381
- });
4382
- var NOT_A_CHECK_RUNS_LISTING = "gh api answered something other than a check run listing";
4383
- var NOT_A_STATUS_LISTING = "gh api answered something other than a commit status listing";
4384
- function read_pages(raw_json, schema, message) {
4385
- const pages = parse_json_array_or_undefined(raw_json, schema);
4386
- if (pages === void 0) throw new Error(message);
4387
- return pages;
4388
- }
4389
- var NO_SUITE = -1;
4390
- function read_id(value) {
4391
- const parsed = id_holder_schema.safeParse(value);
4392
- return parsed.success ? parsed.data.id : void 0;
4393
- }
4394
- function check_run_group_key(run2) {
4395
- const { name, app } = run2;
4396
- if (typeof name !== "string") return void 0;
4397
- return JSON.stringify([name, read_id(app)]);
4398
- }
4399
- function read_rank(run2) {
4400
- const id = read_id(run2);
4401
- if (id === void 0) return void 0;
4402
- return { suite: read_id(run2["check_suite"]) ?? NO_SUITE, run: id };
4403
- }
4404
- function is_ranked_above(candidate, current) {
4405
- if (candidate.suite !== current.suite) return candidate.suite > current.suite;
4406
- return candidate.run > current.run;
4407
- }
4408
- function should_replace(previous, rank) {
4409
- const previous_rank = previous === void 0 ? void 0 : read_rank(previous);
4410
- return previous_rank === void 0 || is_ranked_above(rank, previous_rank);
4411
- }
4412
- function remember_newest_run(run2, newest) {
4413
- const key = check_run_group_key(run2);
4414
- const rank = read_rank(run2);
4415
- if (key === void 0 || rank === void 0) return;
4416
- if (should_replace(newest.get(key), rank)) newest.set(key, run2);
4417
- }
4418
- function is_newest_run(run2, newest) {
4419
- const key = check_run_group_key(run2);
4420
- if (key === void 0 || read_rank(run2) === void 0) return true;
4421
- return newest.get(key) === run2;
4422
- }
4423
- function to_check_run_items(check_runs_json) {
4424
- const pages = read_pages(check_runs_json, check_runs_page_schema, NOT_A_CHECK_RUNS_LISTING);
4425
- const runs = pages.flatMap((page) => page.check_runs);
4426
- const newest = /* @__PURE__ */ new Map();
4427
- for (const run2 of runs) remember_newest_run(run2, newest);
4428
- return runs.filter((run2) => is_newest_run(run2, newest));
4429
- }
4430
- function to_status_context_items(status_json) {
4431
- const pages = read_pages(status_json, status_page_schema, NOT_A_STATUS_LISTING);
4432
- return pages.flatMap((page) => page.statuses).map((status) => ({ ...status, [TYPE_NAME_KEY]: STATUS_CONTEXT_TYPE_NAME }));
4433
- }
4434
- function to_status_check_rollup(input) {
4435
- return [
4436
- ...to_check_run_items(input.check_runs_json),
4437
- ...to_status_context_items(input.status_json)
4438
- ];
4439
- }
4440
- var git_gh_pr_rollup = {
4441
- to_status_check_rollup
4442
- };
4443
-
4444
- // scripts/gh/git-gh-pr-snapshot.ts
4445
- var NO_HEAD_SHA_MESSAGE = "gh api answered a pull request with no head commit";
4446
- async function read_object_pages(path10) {
4447
- return await git_gh_exec.exec_gh_api({
4448
- path: `${path10}${FULL_PAGE_QUERY}`,
4449
- should_paginate: true,
4450
- should_slurp: true
4451
- });
4452
- }
4453
- async function read_array_pages(path10) {
4454
- return await git_gh_exec.exec_gh_api({
4455
- path: `${path10}${FULL_PAGE_QUERY}`,
4456
- should_paginate: true
4457
- });
4458
- }
4459
- function read_head_sha(pull) {
4460
- const sha = pull.head?.sha;
4461
- if (sha === void 0) throw new Error(NO_HEAD_SHA_MESSAGE);
4462
- return sha;
4463
- }
4464
- async function read_status_check_rollup(commit_sha) {
4465
- const [check_runs_json, status_json] = await Promise.all([
4466
- read_object_pages(git_gh_api_path.commit_check_runs_api_path(commit_sha)),
4467
- read_object_pages(git_gh_api_path.commit_status_api_path(commit_sha))
4468
- ]);
4469
- return git_gh_pr_rollup.to_status_check_rollup({ check_runs_json, status_json });
4470
- }
4471
- async function pr_get_review_decision(pr_number) {
4472
- const path10 = git_gh_api_path.pull_reviews_api_path(String(pr_number));
4473
- return git_gh_pr_review.to_review_decision(await read_array_pages(path10));
4474
- }
4475
- async function build_checks_fields(pull) {
4476
- return {
4477
- statusCheckRollup: await read_status_check_rollup(read_head_sha(pull)),
4478
- mergeStateStatus: to_gh_state(pull.mergeable_state)
4479
- };
4480
- }
4481
- async function resolve_pull(branch_name) {
4482
- const pr_number = await require_pr_number(branch_name);
4483
- return { pr_number, pull: await read_pull(pr_number) };
4484
- }
4485
- async function pr_get_checks_snapshot(branch_name) {
4486
- const { pr_number, pull } = await resolve_pull(branch_name);
4487
- return { pr_number, snapshot_json: JSON.stringify(await build_checks_fields(pull)) };
4488
- }
4489
- async function pr_get_state_snapshot(branch_name) {
4490
- const { pr_number, pull } = await resolve_pull(branch_name);
4491
- const [fields, review_decision] = await Promise.all([
4492
- build_checks_fields(pull),
4493
- pr_get_review_decision(pr_number)
4494
- ]);
4495
- return JSON.stringify({ ...fields, reviewDecision: review_decision });
4496
- }
4497
- var git_gh_pr_snapshot = {
4498
- pr_get_state_snapshot,
4499
- pr_get_checks_snapshot,
4500
- pr_get_review_decision
4501
- };
4502
-
4503
- // scripts/gh/git-gh-pr.ts
4504
- var HTML_URL_FILTER2 = ".html_url";
4505
- var PUT_METHOD = "PUT";
4506
- var PATCH_METHOD2 = "PATCH";
4507
- var MERGE_COMMIT_METHOD = "merge";
4508
- var MERGE_REQUEST_TIMEOUT_MS = 18e4;
4509
- var MERGE_UNCONFIRMED_MESSAGE = "gh api could not read the pull request back after the merge request failed";
4510
- var MERGE_READ_BACK_ATTEMPTS = 3;
4511
- var MERGE_READ_BACK_INTERVAL_MS = 1e3;
4512
- var PR_NUMBER_PATTERN = /\/pull\/([1-9]\d*)$/u;
4513
- var LABELS_SEGMENT2 = "/labels";
4514
- var PR_LABELS = z14.array(z14.object({ name: z14.string() }));
4515
- async function add_pr_classification(number, label) {
4516
- await git_gh_exec.exec_gh_api({
4517
- path: `${git_gh_api_path.issue_api_path(number)}${LABELS_SEGMENT2}`,
4518
- body: JSON.stringify({ labels: [label] })
4519
- });
4520
- }
4521
- async function pr_get_classification(branch_name) {
4522
- const number = await require_pr_number(branch_name);
4523
- const response = await git_gh_exec.exec_gh_api({
4524
- path: `${git_gh_api_path.issue_api_path(String(number))}${LABELS_SEGMENT2}`
4525
- });
4526
- const names = PR_LABELS.parse(JSON.parse(response)).map((label) => label.name.toLowerCase());
4527
- const selected = names.filter((name) => pr_classification.is_classification(name));
4528
- if (selected.length === 0) return void 0;
4529
- const error = pr_classification.classification_error(names, "human");
4530
- if (error !== void 0) throw new Error(error);
4531
- return selected[0];
4532
- }
4533
- async function pr_ensure_classification(branch_name, label) {
4534
- if (await pr_get_classification(branch_name) !== void 0) return;
4535
- const number = await require_pr_number(branch_name);
4536
- await add_pr_classification(String(number), label);
4537
- }
4538
- async function post_pull_request(title, body) {
4539
- const base = await git_command.get_default_branch();
4540
- const head = await git_command.branch();
4541
- forget_pr_numbers();
4542
- try {
4543
- return await git_gh_exec.exec_gh_api({
4544
- path: git_gh_api_path.pulls_api_path(),
4545
- body: JSON.stringify({ title, body, head, base }),
4546
- jq_filter: HTML_URL_FILTER2
4547
- });
4548
- } catch (error) {
4549
- return git_gh_helpers.handle_pr_create_error(error);
4550
- }
4551
- }
4552
- async function pr_create(title, body, label) {
4553
- const classification_error2 = pr_classification.classification_error([label], "human");
4554
- if (classification_error2 !== void 0) throw new Error(classification_error2);
4555
- const url = await post_pull_request(title, body);
4556
- const number = PR_NUMBER_PATTERN.exec(url)?.[1];
4557
- if (number === void 0) throw new Error(`Could not identify the created pull request: ${url}`);
4558
- await add_pr_classification(number, label);
4559
- return url;
4560
- }
4561
- async function pr_comment(branch_name, body) {
4562
- const pr_number = await require_pr_number(branch_name);
4563
- return await git_gh_issue_write.issue_comment(String(pr_number), body);
4564
- }
4565
- async function pr_update_body(branch_name, body) {
4566
- const pr_number = await require_pr_number(branch_name);
4567
- await git_gh_exec.exec_gh_api({
4568
- path: git_gh_api_path.pull_api_path(String(pr_number)),
4569
- method: PATCH_METHOD2,
4570
- body: JSON.stringify({ body })
4571
- });
4572
- }
4573
- async function put_merge(pr_number) {
4574
- await git_gh_exec.exec_gh_api({
4575
- path: git_gh_api_path.pull_merge_api_path(String(pr_number)),
4576
- method: PUT_METHOD,
4577
- body: JSON.stringify({ merge_method: MERGE_COMMIT_METHOD }),
4578
- timeout_ms: MERGE_REQUEST_TIMEOUT_MS
4579
- });
4580
- }
4581
- async function read_merge_state(pr_number) {
4582
- try {
4583
- return git_gh_pr_rest.is_merged(await read_pull(pr_number));
4584
- } catch (error) {
4585
- console.warn(`Could not read the pull request back: ${String(error)}`);
4586
- return void 0;
4587
- }
4588
- }
4589
- async function sleep_between_read_backs(attempt) {
4590
- if (attempt < MERGE_READ_BACK_ATTEMPTS - 1) await poll.sleep(MERGE_READ_BACK_INTERVAL_MS);
4591
- }
4592
- async function has_merge_landed(pr_number, merge_error) {
4593
- for (let attempt = 0; attempt < MERGE_READ_BACK_ATTEMPTS; attempt += 1) {
4594
- const is_merged2 = await read_merge_state(pr_number);
4595
- if (is_merged2 !== void 0) return is_merged2;
4596
- await sleep_between_read_backs(attempt);
4597
- }
4598
- throw new Error(MERGE_UNCONFIRMED_MESSAGE, { cause: merge_error });
4599
- }
4600
- async function pr_merge(branch_name) {
4601
- const pr_number = await require_pr_number(branch_name);
4602
- try {
4603
- await put_merge(pr_number);
4604
- } catch (error) {
4605
- if (!await has_merge_landed(pr_number, error)) throw error;
4606
- }
4607
- }
4608
- var git_gh_pr = {
4609
- ...git_gh_pr_read,
4610
- ...git_gh_pr_snapshot,
4611
- pr_create,
4612
- pr_get_classification,
4613
- pr_ensure_classification,
4614
- pr_comment,
4615
- pr_merge,
4616
- pr_update_body
4617
- };
4618
-
4619
- // scripts/gh/git-gh-pr-auto-merge.ts
4620
- var GRAPHQL_PATH = "graphql";
4621
- var OPEN_PULLS_QUERY = `${git_gh_api_path.FULL_PAGE_QUERY}&state=open`;
4622
- var MISSING_NODE_ID_MESSAGE = "gh api answered a pull request without a node_id";
4623
- var ENABLE_AUTO_MERGE_MUTATION = "mutation($id: ID!) { enablePullRequestAutoMerge(input: { pullRequestId: $id, mergeMethod: MERGE }) { clientMutationId } }";
4624
- async function pr_enable_auto_merge(branch_name) {
4625
- const pull = await read_pull(await require_pr_number(branch_name));
4626
- if (pull.node_id === void 0) throw new Error(MISSING_NODE_ID_MESSAGE);
4627
- await git_gh_exec.exec_gh_api({
4628
- path: GRAPHQL_PATH,
4629
- body: JSON.stringify({ query: ENABLE_AUTO_MERGE_MUTATION, variables: { id: pull.node_id } })
4630
- });
4631
- }
4632
- async function pr_is_merged(branch_name) {
4633
- try {
4634
- return git_gh_pr_rest.is_merged(await read_pull(await require_pr_number(branch_name)));
4635
- } catch {
4636
- return false;
4637
- }
4638
- }
4639
- function head_reference_of(pull) {
4640
- return pull.head?.ref ?? "";
4641
- }
4642
- function has_head_prefix(pull, prefix) {
4643
- return git_gh_pr_rest.is_same_repository_head(pull) && head_reference_of(pull).startsWith(prefix);
4644
- }
4645
- function to_open_pull(pull) {
4646
- return {
4647
- number: pull.number,
4648
- head_ref: head_reference_of(pull),
4649
- has_auto_merge: pull.auto_merge !== null && pull.auto_merge !== void 0
4650
- };
4651
- }
4652
- async function pr_list_open_with_head_prefix(prefix) {
4653
- const json = await git_gh_exec.exec_gh_api({
4654
- path: `${git_gh_api_path.pulls_api_path()}${OPEN_PULLS_QUERY}`,
4655
- should_paginate: true
4656
- });
4657
- return git_gh_pr_rest.parse_rest_pulls(json).filter((pull) => has_head_prefix(pull, prefix)).map((pull) => to_open_pull(pull));
4658
- }
4659
- var git_gh_pr_auto_merge = {
4660
- pr_enable_auto_merge,
4661
- pr_is_merged,
4662
- pr_list_open_with_head_prefix
4663
- };
4664
-
4665
- // scripts/gh/git-gh-repo.ts
4666
- async function repo_get_name_with_owner() {
4667
- try {
4668
- const result = await git_gh_exec.exec_gh_api({
4669
- path: git_gh_api_path.repo_api_path(),
4670
- jq_filter: ".full_name"
4671
- });
4672
- return git_gh_helpers.parse_pr_state_string(result);
4673
- } catch {
4674
- return void 0;
4675
- }
4676
- }
4677
- var git_gh_repo = {
4678
- repo_get_name_with_owner
4679
- };
4680
-
4681
- // scripts/gh/git-pr-checks-parse.ts
4682
- var CHECK_STATUS_PASS = "pass";
4683
- var CHECK_STATUS_PENDING = "pending";
4684
- var CHECK_STATUS_FAIL = "fail";
4685
- var CHECK_STATUS_MISSING = "missing";
4686
- var PASSING_CONCLUSIONS = /* @__PURE__ */ new Set(["success", "skipped", "neutral"]);
4687
- var KEY_TYPE_NAME = "__typename";
4688
- var KEY_STATE = "state";
4689
- var KEY_STATUS = "status";
4690
- var KEY_CONCLUSION = "conclusion";
4691
- var KEY_NAME = "name";
4692
- var KEY_CONTEXT = "context";
4693
- function read_string(value) {
4694
- if (typeof value !== "string") return void 0;
4695
- const trimmed = value.trim();
4696
- if (trimmed.length === 0) return void 0;
4697
- return trimmed;
4698
- }
4699
- var PENDING_STATUS_STATES = /* @__PURE__ */ new Set(["pending", "expected"]);
4700
- function parse_status_context(item) {
4701
- const state = read_string(item[KEY_STATE])?.toLowerCase();
4702
- if (state === "success") return CHECK_STATUS_PASS;
4703
- if (state !== void 0 && PENDING_STATUS_STATES.has(state)) return CHECK_STATUS_PENDING;
4704
- return CHECK_STATUS_FAIL;
4705
- }
4706
- function is_passing_conclusion(item) {
4707
- const conclusion = read_string(item[KEY_CONCLUSION])?.toLowerCase();
4708
- return conclusion !== void 0 && PASSING_CONCLUSIONS.has(conclusion);
4709
- }
4710
- function parse_check_run(item) {
4711
- const status = read_string(item[KEY_STATUS])?.toLowerCase();
4712
- if (status !== "completed") return CHECK_STATUS_PENDING;
4713
- return is_passing_conclusion(item) ? CHECK_STATUS_PASS : CHECK_STATUS_FAIL;
4714
- }
4715
- function parse_rollup_status(item) {
4716
- const type_name = read_string(item[KEY_TYPE_NAME]);
4717
- if (type_name === "StatusContext") return parse_status_context(item);
4718
- return parse_check_run(item);
4719
- }
4720
- function read_rollup_array(parsed) {
4721
- const result = pr_raw_schema.safeParse(parsed);
4722
- if (!result.success) return [];
4723
- return result.data.statusCheckRollup ?? [];
4724
- }
4725
- function parse_rollup_item(item) {
4726
- const name = read_string(item[KEY_NAME]) ?? read_string(item[KEY_CONTEXT]);
4727
- if (name === void 0) return void 0;
4728
- return { name, status: parse_rollup_status(item) };
4729
- }
4730
- function parse_rollup_checks(raw_json) {
4731
- const parsed = json_value.parse_or_undefined(raw_json);
4732
- const rollup = read_rollup_array(parsed);
4733
- const checks = [];
4734
- for (const item of rollup) {
4735
- const parsed_item = parse_rollup_item(item);
4736
- if (parsed_item !== void 0) checks.push(parsed_item);
4737
- }
4738
- return checks;
4739
- }
4740
- function parse_pr_state_snapshot(raw_json) {
4741
- const parsed = json_value.parse_or_undefined(raw_json);
4742
- const result = pr_raw_schema.safeParse(parsed);
4743
- const data = result.success ? result.data : void 0;
4744
- return {
4745
- rollup: parse_rollup_checks(raw_json),
4746
- merge_state_status: read_string(data?.mergeStateStatus),
4747
- review_decision: read_string(data?.reviewDecision)
4748
- };
4749
- }
4750
-
4751
- // scripts/gh/git-pr-checks-eval.ts
4752
- var DEFAULT_REQUIRED_CHECKS = ["SonarQube"];
4753
- var CODERABBIT_CHECK_NAME = "CodeRabbit";
4754
- var REQUIRED_CHECKS_ENV_VAR = "JOSH_REQUIRED_CHECKS";
4755
- function parse_required_checks() {
4756
- const raw = process.env[REQUIRED_CHECKS_ENV_VAR];
4757
- if (!raw) return DEFAULT_REQUIRED_CHECKS;
4758
- return raw.split(",").map((check4) => check4.trim()).filter((check4) => check4.length > 0);
4759
- }
4760
- var REQUIRED_CHECKS = parse_required_checks();
4761
- var MERGE_STATE_CLEAN = "CLEAN";
4762
- var MERGE_STATE_UNSTABLE = "UNSTABLE";
4763
- var MERGE_STATE_DIRTY = "DIRTY";
4764
- var REVIEW_CHANGES_REQUESTED2 = "CHANGES_REQUESTED";
4765
- var CHECK_SUITE_SEPARATOR = " / ";
4766
- var FAILURE_MESSAGE_PREFIX = "PR checks failed";
4767
- var FAILURE_REASON_REVIEW = "review requested changes";
4768
- var FAILURE_REASON_CHECKS = "failed checks";
4769
- var FAILURE_REASON_CONFLICT = "merge conflict";
4770
- function is_required_match(check_name, required_name) {
4771
- if (check_name === required_name) return true;
4772
- return check_name.startsWith(`${required_name}${CHECK_SUITE_SEPARATOR}`);
4773
- }
4774
- function find_required_check(checks, required_name) {
4775
- return checks.find((check4) => is_required_match(check4.name, required_name));
4776
- }
4777
- function read_required_statuses(checks) {
4778
- return REQUIRED_CHECKS.map(
4779
- (name) => find_required_check(checks, name)?.status ?? CHECK_STATUS_MISSING
4780
- );
4781
- }
4782
- function is_review_blocked(review_decision) {
4783
- return review_decision === REVIEW_CHANGES_REQUESTED2;
4784
- }
4785
- function is_merge_conflict(merge_state_status) {
4786
- return merge_state_status === MERGE_STATE_DIRTY;
4787
- }
4788
- function evaluate_failure_state(input) {
4789
- if (is_merge_conflict(input.merge_state_status) || is_review_blocked(input.review_decision) || input.failed_checks.length > 0) {
4790
- return "failure";
4791
- }
4792
- return void 0;
4793
- }
4794
- function is_merge_state_clean(merge_state_status) {
4795
- return merge_state_status === MERGE_STATE_CLEAN;
4796
- }
4797
- function is_every_required_passing(statuses) {
4798
- return statuses.every((status) => status === CHECK_STATUS_PASS);
4799
- }
4800
- function is_coderabbit_check(check_name) {
4801
- return is_required_match(check_name, CODERABBIT_CHECK_NAME);
4802
- }
4803
- function is_unstable_only_from_coderabbit(snapshot) {
4804
- if (snapshot.merge_state_status !== MERGE_STATE_UNSTABLE) return false;
4805
- const non_passing = snapshot.rollup.filter((check4) => check4.status !== CHECK_STATUS_PASS);
4806
- if (non_passing.length === 0) return false;
4807
- return non_passing.every((check4) => is_coderabbit_check(check4.name));
4808
- }
4809
- function is_required_check(check_name) {
4810
- return REQUIRED_CHECKS.some((required) => is_required_match(check_name, required));
4811
- }
4812
- function is_blocking_failure(check4) {
4813
- if (check4.status !== CHECK_STATUS_FAIL) return false;
4814
- return !is_coderabbit_check(check4.name) || is_required_check(check4.name);
4815
- }
4816
- function collect_blocking_failures(snapshot) {
4817
- return snapshot.rollup.filter((check4) => is_blocking_failure(check4)).map((check4) => check4.name);
4818
- }
4819
- function is_mergeable_state(snapshot) {
4820
- if (is_merge_state_clean(snapshot.merge_state_status)) return true;
4821
- return is_unstable_only_from_coderabbit(snapshot);
4822
- }
4823
- function collect_failure_reasons(snapshot) {
4824
- const reasons = [];
4825
- if (is_merge_conflict(snapshot.merge_state_status)) reasons.push(FAILURE_REASON_CONFLICT);
4826
- if (is_review_blocked(snapshot.review_decision)) reasons.push(FAILURE_REASON_REVIEW);
4827
- const failed = collect_blocking_failures(snapshot);
4828
- if (failed.length > 0) reasons.push(`${FAILURE_REASON_CHECKS}: ${failed.join(", ")}`);
4829
- return reasons;
4830
- }
4831
- function describe_pr_failure(snapshot) {
4832
- const reasons = collect_failure_reasons(snapshot);
4833
- if (reasons.length === 0) return `${FAILURE_MESSAGE_PREFIX}.`;
4834
- return `${FAILURE_MESSAGE_PREFIX} (${reasons.join("; ")}).`;
4835
- }
4836
- function evaluate_pr_state(snapshot) {
4837
- const statuses = read_required_statuses(snapshot.rollup);
4838
- const failure = evaluate_failure_state({
4839
- review_decision: snapshot.review_decision,
4840
- failed_checks: collect_blocking_failures(snapshot),
4841
- merge_state_status: snapshot.merge_state_status
4842
- });
4843
- if (failure !== void 0) return failure;
4844
- if (is_mergeable_state(snapshot) && is_every_required_passing(statuses)) {
4845
- return "success";
4846
- }
4847
- return "pending";
4848
- }
4849
- function is_review_decision_decisive(snapshot) {
4850
- return evaluate_pr_state(snapshot) !== "pending";
4851
- }
4852
-
4853
- // scripts/gh/git-pr-checks.ts
4854
- var SECONDS_TO_MS = 1e3;
4855
- var CHECK_WAIT_INTERVAL_MS = 1e4;
4856
- var DEFAULT_TIMEOUT_SECONDS = 1920;
4857
- function compute_max_attempts(timeout_seconds, interval_ms) {
4858
- return Math.ceil(timeout_seconds / (interval_ms / SECONDS_TO_MS)) + 1;
4859
- }
4860
- var DEFAULT_MAX_ATTEMPTS = compute_max_attempts(DEFAULT_TIMEOUT_SECONDS, CHECK_WAIT_INTERVAL_MS);
4861
- function get_configured_max_attempts() {
4862
- const environment_seconds = Number(process.env["JOSH_CI_TIMEOUT_SECONDS"]);
4863
- return Number.isFinite(environment_seconds) && environment_seconds > 0 ? compute_max_attempts(environment_seconds, CHECK_WAIT_INTERVAL_MS) : DEFAULT_MAX_ATTEMPTS;
4864
- }
4865
- var CHECK_MAX_ATTEMPTS = get_configured_max_attempts();
4866
- var DEFAULT_STABLE_READS = 2;
4867
- var MAX_CONSECUTIVE_READ_FAILURES = 3;
4868
- var PR_CHECKS_TIMEOUT_MESSAGE = "Timed out while waiting for PR checks to complete.";
4869
- function is_pr_checks_timeout(error) {
4870
- return error instanceof Error && error.message === PR_CHECKS_TIMEOUT_MESSAGE;
4871
- }
4872
- var SHOULD_ALWAYS_READ_REVIEW_DECISION = () => true;
4873
- var MERGE_GATE_EVALUATOR = {
4874
- evaluate: evaluate_pr_state,
4875
- describe: describe_pr_failure,
4876
- should_read_review_decision: is_review_decision_decisive
4877
- };
4878
- function advance_stable_count(previous, state) {
4879
- return state === "success" ? previous + 1 : 0;
4880
- }
4881
- function classify_poll_result(input) {
4882
- const state = input.evaluator.evaluate(input.snapshot);
4883
- if (state === "failure") throw new Error(input.evaluator.describe(input.snapshot));
4884
- const next_stable_count = advance_stable_count(input.stable_count, state);
4885
- return {
4886
- is_done: next_stable_count >= input.required_stable_reads,
4887
- next_stable_count
4888
- };
4889
- }
4890
- async function read_pr_state(input, evaluator) {
4891
- try {
4892
- const snapshot = await input.options.fetcher(
4893
- input.options.branch_name,
4894
- evaluator.should_read_review_decision ?? SHOULD_ALWAYS_READ_REVIEW_DECISION
4895
- );
4896
- return { kind: "read", snapshot };
4897
- } catch (error) {
4898
- return { kind: "unreadable", cause: error };
4899
- }
4900
- }
4901
- async function sleep_before_next_attempt(input) {
4902
- if (input.attempt < input.options.max_attempts - 1) {
4903
- await poll.sleep(input.options.interval_ms);
4904
- }
4905
- }
4906
- async function retry_after_unreadable(input, cause) {
4907
- const next_failure_count = input.failure_count + 1;
4908
- if (next_failure_count >= MAX_CONSECUTIVE_READ_FAILURES) throw cause;
4909
- console.warn(
4910
- `Could not read the PR state (${String(next_failure_count)}/${String(MAX_CONSECUTIVE_READ_FAILURES)}); asking again on the next poll: ${String(cause)}`
4911
- );
4912
- await sleep_before_next_attempt(input);
4913
- return { next_stable_count: 0, next_failure_count, read_failure: cause };
4914
- }
4915
- function to_exhaustion_error(last_read_failure) {
4916
- return last_read_failure ?? new Error(PR_CHECKS_TIMEOUT_MESSAGE);
4917
- }
4918
- async function attempt_pr_success_poll(input) {
4919
- const evaluator = input.options.evaluator ?? MERGE_GATE_EVALUATOR;
4920
- const read2 = await read_pr_state(input, evaluator);
4921
- if (read2.kind === "unreadable") return await retry_after_unreadable(input, read2.cause);
4922
- const classification = classify_poll_result({
4923
- snapshot: read2.snapshot,
4924
- stable_count: input.stable_count,
4925
- required_stable_reads: input.options.required_stable_reads,
4926
- evaluator
4927
- });
4928
- if (classification.is_done) {
4929
- return { snapshot: read2.snapshot, next_stable_count: 0, next_failure_count: 0 };
4930
- }
4931
- await sleep_before_next_attempt(input);
4932
- return { next_stable_count: classification.next_stable_count, next_failure_count: 0 };
4933
- }
4934
- async function wait_for_pr_success(options) {
4935
- let carried = { next_stable_count: 0, next_failure_count: 0 };
4936
- for (let attempt = 0; attempt < options.max_attempts; attempt += 1) {
4937
- console.info(`Checking PR status\u2026 (${String(attempt + 1)}/${String(options.max_attempts)})`);
4938
- carried = await attempt_pr_success_poll({
4939
- options,
4940
- stable_count: carried.next_stable_count,
4941
- failure_count: carried.next_failure_count,
4942
- attempt
4943
- });
4944
- if (carried.snapshot !== void 0) return carried.snapshot;
4945
- }
4946
- throw to_exhaustion_error(carried.read_failure);
4947
- }
4948
- async function default_fetch_pr_state(branch_name, should_read_review_decision = SHOULD_ALWAYS_READ_REVIEW_DECISION) {
4949
- const checks = await git_gh_pr_snapshot.pr_get_checks_snapshot(branch_name);
4950
- const snapshot = parse_pr_state_snapshot(checks.snapshot_json);
4951
- if (!should_read_review_decision(snapshot)) return snapshot;
4952
- const decision = await git_gh_pr_snapshot.pr_get_review_decision(checks.pr_number);
4953
- return { ...snapshot, review_decision: read_string(decision) };
4954
- }
4955
-
4956
- // scripts/gh/git-pr-checks-watch.ts
4957
- var PR_CHECKS_WATCH_TIMEOUT_MS = 12e4;
4958
- var WATCH_TIMED_OUT_NOTE = "\u23F1\uFE0F pr checks --watch timed out.";
4959
- var NO_CHECKS_MESSAGE = "gh api reported no checks on the branch";
4960
- var CHECKS_FAILED_MESSAGE = "gh api reported a failing check on the branch";
4961
- function is_awaited_check(check4) {
4962
- return !is_coderabbit_check(check4.name) || is_required_check(check4.name);
4963
- }
4964
- function evaluate_checks_settled(snapshot) {
4965
- const awaited = snapshot.rollup.filter((check4) => is_awaited_check(check4));
4966
- const considered = awaited.length === 0 ? snapshot.rollup : awaited;
4967
- if (considered.length === 0 || considered.some((check4) => check4.status === CHECK_STATUS_PENDING)) {
4968
- return "pending";
4969
- }
4970
- return snapshot.rollup.some((check4) => check4.status === CHECK_STATUS_FAIL) ? "failure" : "success";
4971
- }
4972
- function describe_checks_failure(snapshot) {
4973
- const failed = snapshot.rollup.filter((check4) => check4.status === CHECK_STATUS_FAIL);
4974
- return `${CHECKS_FAILED_MESSAGE}: ${failed.map((check4) => check4.name).join(", ")}`;
4975
- }
4976
- var SHOULD_NEVER_READ_REVIEW_DECISION = () => false;
4977
- var CHECKS_SETTLED_EVALUATOR = {
4978
- evaluate: evaluate_checks_settled,
4979
- describe: describe_checks_failure,
4980
- should_read_review_decision: SHOULD_NEVER_READ_REVIEW_DECISION
4981
- };
4982
- async function watch_until_settled(branch_name) {
4983
- await wait_for_pr_success({
4984
- branch_name,
4985
- fetcher: default_fetch_pr_state,
4986
- interval_ms: CHECK_WAIT_INTERVAL_MS,
4987
- max_attempts: compute_max_attempts(
4988
- PR_CHECKS_WATCH_TIMEOUT_MS / SECONDS_TO_MS,
4989
- CHECK_WAIT_INTERVAL_MS
4990
- ),
4991
- required_stable_reads: DEFAULT_STABLE_READS,
4992
- evaluator: CHECKS_SETTLED_EVALUATOR
4993
- });
4994
- }
4995
- async function fail_when_no_checks(branch_name) {
4996
- const snapshot = await default_fetch_pr_state(branch_name, SHOULD_NEVER_READ_REVIEW_DECISION);
4997
- if (snapshot.rollup.length === 0) throw new Error(NO_CHECKS_MESSAGE);
4998
- }
4999
- async function pr_checks_watch(branch_name) {
5000
- try {
5001
- await watch_until_settled(branch_name);
5002
- return { timed_out: false };
5003
- } catch (error) {
5004
- if (!is_pr_checks_timeout(error)) throw error;
5005
- await fail_when_no_checks(branch_name);
5006
- console.info(WATCH_TIMED_OUT_NOTE);
5007
- return { timed_out: true };
5008
- }
5009
- }
5010
- var git_pr_checks_watch = { pr_checks_watch };
5011
-
5012
- // scripts/gh/git-gh-command.ts
5013
- var git_gh_command = {
5014
- ...git_gh_pr,
5015
- ...git_gh_pr_auto_merge,
5016
- pr_checks_watch: git_pr_checks_watch.pr_checks_watch,
5017
- ...git_gh_issue,
5018
- ...git_gh_repo
5019
- };
5020
-
5021
3306
  // scripts/epic/epic-busy.ts
5022
3307
  var LISTING_LIMIT = 100;
5023
3308
  var PARKED_LABELS = /* @__PURE__ */ new Set([NEEDS_DECISION_LABEL, ALREADY_DONE_LABEL]);
@@ -5080,30 +3365,30 @@ var epic_busy = {
5080
3365
  };
5081
3366
 
5082
3367
  // scripts/run/run-liveness.ts
5083
- import { readFileSync as readFileSync6, realpathSync, statSync } from "node:fs";
3368
+ import { readFileSync as readFileSync5, realpathSync, statSync } from "node:fs";
5084
3369
  import { homedir, tmpdir } from "node:os";
5085
3370
  import path8 from "node:path";
5086
- import { setTimeout as sleep2 } from "node:timers/promises";
3371
+ import { setTimeout as sleep } from "node:timers/promises";
5087
3372
 
5088
3373
  // scripts/agent/agent-event.ts
5089
- import { z as z16 } from "zod";
3374
+ import { z as z9 } from "zod";
5090
3375
 
5091
3376
  // scripts/agent/claude-result-event.ts
5092
- import { z as z15 } from "zod";
5093
- var RESULT_EVENT_SCHEMA = z15.looseObject({
5094
- type: z15.literal("result"),
5095
- is_error: z15.unknown().optional(),
5096
- subtype: z15.unknown().optional(),
5097
- num_turns: z15.unknown().optional(),
5098
- permission_denials: z15.unknown().optional(),
5099
- result: z15.unknown().optional(),
5100
- session_id: z15.unknown().optional(),
5101
- usage: z15.unknown().optional()
3377
+ import { z as z8 } from "zod";
3378
+ var RESULT_EVENT_SCHEMA = z8.looseObject({
3379
+ type: z8.literal("result"),
3380
+ is_error: z8.unknown().optional(),
3381
+ subtype: z8.unknown().optional(),
3382
+ num_turns: z8.unknown().optional(),
3383
+ permission_denials: z8.unknown().optional(),
3384
+ result: z8.unknown().optional(),
3385
+ session_id: z8.unknown().optional(),
3386
+ usage: z8.unknown().optional()
5102
3387
  });
5103
- var USAGE_SCHEMA = z15.looseObject({
5104
- input_tokens: z15.unknown().optional(),
5105
- cache_read_input_tokens: z15.unknown().optional(),
5106
- output_tokens: z15.unknown().optional()
3388
+ var USAGE_SCHEMA = z8.looseObject({
3389
+ input_tokens: z8.unknown().optional(),
3390
+ cache_read_input_tokens: z8.unknown().optional(),
3391
+ output_tokens: z8.unknown().optional()
5107
3392
  });
5108
3393
  function usable_reason(value) {
5109
3394
  return typeof value === "string" && value.trim() !== "" ? value : void 0;
@@ -5142,31 +3427,31 @@ function decode(value) {
5142
3427
  var claude_result_event = { decode };
5143
3428
 
5144
3429
  // scripts/agent/agent-event.ts
5145
- var TEXT_BLOCK_SCHEMA = z16.looseObject({ type: z16.literal("text"), text: z16.string() });
5146
- var CLAUDE_MESSAGE_SCHEMA = z16.looseObject({ content: z16.array(z16.unknown()).optional() });
5147
- var CLAUDE_INIT_SCHEMA = z16.looseObject({ type: z16.literal("system"), subtype: z16.literal("init") });
5148
- var CLAUDE_ASSISTANT_SCHEMA = z16.looseObject({
5149
- type: z16.literal("assistant"),
3430
+ var TEXT_BLOCK_SCHEMA = z9.looseObject({ type: z9.literal("text"), text: z9.string() });
3431
+ var CLAUDE_MESSAGE_SCHEMA = z9.looseObject({ content: z9.array(z9.unknown()).optional() });
3432
+ var CLAUDE_INIT_SCHEMA = z9.looseObject({ type: z9.literal("system"), subtype: z9.literal("init") });
3433
+ var CLAUDE_ASSISTANT_SCHEMA = z9.looseObject({
3434
+ type: z9.literal("assistant"),
5150
3435
  message: CLAUDE_MESSAGE_SCHEMA
5151
3436
  });
5152
- var USAGE_SCHEMA2 = z16.looseObject({
5153
- input_tokens: z16.number().optional(),
5154
- cached_input_tokens: z16.number().optional(),
5155
- output_tokens: z16.number().optional()
3437
+ var USAGE_SCHEMA2 = z9.looseObject({
3438
+ input_tokens: z9.number().optional(),
3439
+ cached_input_tokens: z9.number().optional(),
3440
+ output_tokens: z9.number().optional()
5156
3441
  });
5157
- var CODEX_START_SCHEMA = z16.looseObject({ type: z16.enum(["thread.started", "turn.started"]) });
5158
- var CODEX_PROGRESS_SCHEMA = z16.looseObject({
5159
- type: z16.enum(["item.started", "item.updated", "item.completed"]),
5160
- item: z16.looseObject({ type: z16.string(), text: z16.string().optional() }).optional()
3442
+ var CODEX_START_SCHEMA = z9.looseObject({ type: z9.enum(["thread.started", "turn.started"]) });
3443
+ var CODEX_PROGRESS_SCHEMA = z9.looseObject({
3444
+ type: z9.enum(["item.started", "item.updated", "item.completed"]),
3445
+ item: z9.looseObject({ type: z9.string(), text: z9.string().optional() }).optional()
5161
3446
  });
5162
- var CODEX_COMPLETE_SCHEMA = z16.looseObject({
5163
- type: z16.literal("turn.completed"),
3447
+ var CODEX_COMPLETE_SCHEMA = z9.looseObject({
3448
+ type: z9.literal("turn.completed"),
5164
3449
  usage: USAGE_SCHEMA2.optional()
5165
3450
  });
5166
- var CODEX_FAILURE_SCHEMA = z16.looseObject({
5167
- type: z16.enum(["turn.failed", "error"]),
5168
- error: z16.looseObject({ message: z16.string().optional() }).optional(),
5169
- message: z16.string().optional()
3451
+ var CODEX_FAILURE_SCHEMA = z9.looseObject({
3452
+ type: z9.enum(["turn.failed", "error"]),
3453
+ error: z9.looseObject({ message: z9.string().optional() }).optional(),
3454
+ message: z9.string().optional()
5170
3455
  });
5171
3456
  var EMPTY_STATE = {
5172
3457
  provider: void 0,
@@ -5257,7 +3542,7 @@ function describe(state) {
5257
3542
  var agent_event = { describe, read };
5258
3543
 
5259
3544
  // scripts/issue/issue-state.ts
5260
- import { z as z17 } from "zod";
3545
+ import { z as z10 } from "zod";
5261
3546
  var NO_LABELS = "(none)";
5262
3547
  var LABEL_SEPARATOR = ", ";
5263
3548
  var STATE_LABEL = "state: ";
@@ -5267,9 +3552,9 @@ var YES = "yes";
5267
3552
  var NO = "no";
5268
3553
  var ISSUE_LABEL = "issue: ";
5269
3554
  var HUMAN_REVIEW_LABELS = /* @__PURE__ */ new Set([NEEDS_HUMAN_REVIEW_LABEL]);
5270
- var label_schema = z17.looseObject({ name: z17.string() });
5271
- var issue_state_schema = z17.looseObject({
5272
- state: z17.string(),
3555
+ var label_schema = z10.looseObject({ name: z10.string() });
3556
+ var issue_state_schema = z10.looseObject({
3557
+ state: z10.string(),
5273
3558
  labels: label_schema.array().optional()
5274
3559
  });
5275
3560
  function parse_issue_state(json) {
@@ -5317,7 +3602,7 @@ var DEFAULT_SILENT_MINUTES = 30;
5317
3602
  var DEFAULT_GAP_SECONDS = 5;
5318
3603
  var MS_PER_MINUTE3 = 6e4;
5319
3604
  var MS_PER_SECOND2 = 1e3;
5320
- var OPEN_STATE3 = "OPEN";
3605
+ var OPEN_STATE2 = "OPEN";
5321
3606
  var STATE_FIELDS = "state,labels";
5322
3607
  var REASONS = {
5323
3608
  [ALIVE_VERDICT]: "The unit is still working: its output moved, or a process of the child is alive.",
@@ -5405,7 +3690,7 @@ function read_agent_state(output_path) {
5405
3690
  const safe_path = to_safe_path(output_path);
5406
3691
  if (safe_path === void 0) return void 0;
5407
3692
  try {
5408
- const state = agent_event.read(readFileSync6(safe_path, "utf8"));
3693
+ const state = agent_event.read(readFileSync5(safe_path, "utf8"));
5409
3694
  return state.provider === void 0 ? void 0 : state;
5410
3695
  } catch {
5411
3696
  return void 0;
@@ -5419,7 +3704,7 @@ async function read_output_frozen(request) {
5419
3704
  const first = sample_output(request.output_path);
5420
3705
  if (first === void 0) return void 0;
5421
3706
  if (request.now_ms - first.mtime_ms < request.silent_window_ms) return false;
5422
- await sleep2(request.gap_ms);
3707
+ await sleep(request.gap_ms);
5423
3708
  const second = sample_output(request.output_path);
5424
3709
  if (second === void 0) return void 0;
5425
3710
  return second.mtime_ms === first.mtime_ms && second.size === first.size;
@@ -5436,7 +3721,7 @@ async function read_child_settled(issue, repo) {
5436
3721
  if (json === void 0) return void 0;
5437
3722
  const state = issue_state.parse_issue_state(json);
5438
3723
  if (state === void 0) return void 0;
5439
- return state.state !== OPEN_STATE3 || carries_settled_label(state.labels);
3724
+ return state.state !== OPEN_STATE2 || carries_settled_label(state.labels);
5440
3725
  }
5441
3726
  async function read_traces(request) {
5442
3727
  const [is_initial_child_settled, is_output_frozen, is_tree_dirty] = await Promise.all([
@@ -5476,14 +3761,14 @@ var run_liveness = {
5476
3761
 
5477
3762
  // scripts/lane/lane-report.ts
5478
3763
  var NO_LANES2 = "No lanes are open.";
5479
- var OPEN_STATE4 = "open";
3764
+ var OPEN_STATE3 = "open";
5480
3765
  var STRANDED_STATE = "stranded";
5481
3766
  var UNREADABLE_STATE = "unreadable";
5482
3767
  var UNKNOWN_VALUE = "-";
5483
3768
  var COLUMN_SEPARATOR = " ";
5484
3769
  function lane_state(lane) {
5485
3770
  if (lane.is_stranded) return STRANDED_STATE;
5486
- return lane.seat === void 0 ? UNREADABLE_STATE : OPEN_STATE4;
3771
+ return lane.seat === void 0 ? UNREADABLE_STATE : OPEN_STATE3;
5487
3772
  }
5488
3773
  function value_or_unknown(value) {
5489
3774
  return value === void 0 ? UNKNOWN_VALUE : String(value);
@@ -5527,7 +3812,7 @@ function describe_opened(lane) {
5527
3812
  }
5528
3813
  var lane_report = {
5529
3814
  NO_LANES: NO_LANES2,
5530
- OPEN_STATE: OPEN_STATE4,
3815
+ OPEN_STATE: OPEN_STATE3,
5531
3816
  STRANDED_STATE,
5532
3817
  UNREADABLE_STATE,
5533
3818
  describe_lane,
@@ -5537,7 +3822,7 @@ var lane_report = {
5537
3822
  };
5538
3823
 
5539
3824
  // scripts/run/run-preflight.ts
5540
- import { z as z18 } from "zod";
3825
+ import { z as z11 } from "zod";
5541
3826
  var CLEAN_VERDICT = "clean";
5542
3827
  var RECLAIM_VERDICT = "reclaim";
5543
3828
  var RESUME_VERDICT = "resume";
@@ -5547,7 +3832,7 @@ var OPEN_PR = "open";
5547
3832
  var MERGED_PR = "merged";
5548
3833
  var CLOSED_PR = "closed";
5549
3834
  var NO_CHILD_WORK = { branch_name: void 0, pr_state: NO_PR };
5550
- var pr_info_schema2 = z18.object({ state: z18.string().optional() });
3835
+ var pr_info_schema = z11.object({ state: z11.string().optional() });
5551
3836
  var GH_PR_STATES = /* @__PURE__ */ new Map([
5552
3837
  ["CLOSED", CLOSED_PR],
5553
3838
  ["MERGED", MERGED_PR],
@@ -5626,12 +3911,12 @@ function decide5(tree, child, issue) {
5626
3911
  }
5627
3912
  function read_pr_field(raw) {
5628
3913
  try {
5629
- return pr_info_schema2.parse(JSON.parse(raw)).state;
3914
+ return pr_info_schema.parse(JSON.parse(raw)).state;
5630
3915
  } catch {
5631
3916
  return void 0;
5632
3917
  }
5633
3918
  }
5634
- function to_pr_state2(raw) {
3919
+ function to_pr_state(raw) {
5635
3920
  const state = read_pr_field(raw);
5636
3921
  return (state === void 0 ? void 0 : GH_PR_STATES.get(state)) ?? NO_PR;
5637
3922
  }
@@ -5643,17 +3928,17 @@ async function read_tree_state() {
5643
3928
  ]);
5644
3929
  return { branch: current, default_branch, is_dirty };
5645
3930
  }
5646
- async function read_pr_state2(branch_name) {
3931
+ async function read_pr_state(branch_name) {
5647
3932
  if (!await git_gh_pr_read.pr_exists(branch_name)) return NO_PR;
5648
3933
  const raw = await git_gh_pr_read.pr_view(branch_name);
5649
3934
  if (raw === "") throw new Error(`${UNREADABLE_PR_MESSAGE}${branch_name}`);
5650
- return to_pr_state2(raw);
3935
+ return to_pr_state(raw);
5651
3936
  }
5652
3937
  function is_pr_open(state) {
5653
3938
  return state === OPEN_PR;
5654
3939
  }
5655
3940
  async function read_pr_of_branch(branch_name) {
5656
- return { branch_name, pr_state: await read_pr_state2(branch_name) };
3941
+ return { branch_name, pr_state: await read_pr_state(branch_name) };
5657
3942
  }
5658
3943
  function pick_child_state(reads) {
5659
3944
  const decided = reads.find((read2) => is_pr_decided(read2.pr_state));
@@ -5728,8 +4013,8 @@ var run_preflight = {
5728
4013
  check: check2,
5729
4014
  decide: decide5,
5730
4015
  read_child_state,
5731
- read_pr_state: read_pr_state2,
5732
- to_pr_state: to_pr_state2
4016
+ read_pr_state,
4017
+ to_pr_state
5733
4018
  };
5734
4019
 
5735
4020
  // scripts/run/run-progress-read.ts
@@ -5829,7 +4114,7 @@ var TICK_MULTIPLIER = 3;
5829
4114
  var MS_PER_SECOND3 = 1e3;
5830
4115
  var STALE_THRESHOLD_MS = WATCHER_TICK_MS * TICK_MULTIPLIER;
5831
4116
  var STALE_THRESHOLD_S = STALE_THRESHOLD_MS / MS_PER_SECOND3;
5832
- var STALE_NOTE = `Lane children are in-flight but the progress watcher has not pinged in the last ${String(STALE_THRESHOLD_S)}s \u2014 run \`pnpm josh run:progress --wait\` in the background before proceeding`;
4117
+ var STALE_NOTE = `Lane children are in-flight but the progress watcher has not pinged in the last ${String(STALE_THRESHOLD_S)}s \u2014 run \`pnpm josh run:progress --wait\` in the background before proceeding. It reports to the run event stream on its own and exits only when newly runnable work arrives, so start it once and relay nothing`;
5833
4118
  var OK_RESULT = { kind: "ok" };
5834
4119
  async function owes_watcher() {
5835
4120
  if (!await run_headless.is_backlog_parent()) return false;
@@ -5849,7 +4134,7 @@ var run_watcher_guard = {
5849
4134
  // scripts/run/run-watcher-hook.ts
5850
4135
  var SWITCH_ENV_KEY2 = "JOSH_WATCHER_GUARD";
5851
4136
  var STAMP_PREFIX2 = "josh-watcher-guard-";
5852
- var payload_schema = z19.object({ transcript_path: z19.string().min(1) });
4137
+ var payload_schema = z12.object({ transcript_path: z12.string().min(1) });
5853
4138
  function transcript_of(raw_payload) {
5854
4139
  try {
5855
4140
  const parsed = payload_schema.safeParse(JSON.parse(raw_payload));
@@ -5910,7 +4195,8 @@ async function refusal_for(transcript, now_ms, state) {
5910
4195
  function is_unit_call(raw_payload) {
5911
4196
  try {
5912
4197
  return (hook_decision.parse_hook_payload(raw_payload)?.agent_id ?? "") !== "";
5913
- } catch {
4198
+ } catch (error) {
4199
+ error_text.trace_swallowed("run_parent_cut_hook.is_unit_call", error);
5914
4200
  return false;
5915
4201
  }
5916
4202
  }