@joshuafolkken/kit 1.921.0 → 1.947.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 (97) hide show
  1. package/.claude/skills/workflow-commands/background-commands.md +6 -0
  2. package/.claude/skills/workflow-commands/backlogrun-child.md +1 -1
  3. package/.claude/skills/workflow-commands/backlogrun-lanes.md +4 -3
  4. package/.claude/skills/workflow-commands/backlogrun-progress.md +13 -12
  5. package/.claude/skills/workflow-commands/backlogrun-steps.md +2 -1
  6. package/.claude/skills/workflow-commands/observation-filing.md +3 -3
  7. package/.claude/skills/workflow-commands/prerequisite.md +1 -1
  8. package/.github/workflows/ci.yml +26 -8
  9. package/.github/workflows/pr-classification.yml +76 -0
  10. package/README.md +47 -21
  11. package/dist/hooks/batch-guard.js +6 -6
  12. package/dist/hooks/{chunk-LC765SUA.js → chunk-3FWV6CFC.js} +119 -20
  13. package/dist/hooks/{chunk-UULARQ5Q.js → chunk-EYFJ74MJ.js} +13 -15
  14. package/dist/hooks/{chunk-O2FBZPSW.js → chunk-GIX5SAAB.js} +248 -231
  15. package/dist/hooks/{chunk-OLTAGGHH.js → chunk-IA7WC4NS.js} +1 -1
  16. package/dist/hooks/{chunk-UANRLZV7.js → chunk-IBFC25IX.js} +4 -4
  17. package/dist/hooks/{chunk-XMR3BS35.js → chunk-M4U4YNRE.js} +3 -3
  18. package/dist/hooks/{chunk-NWD47MW3.js → chunk-NKVLBB65.js} +3 -3
  19. package/dist/hooks/{chunk-OYU6KPRA.js → chunk-O3PEDF3M.js} +2 -2
  20. package/dist/hooks/{chunk-3HZ5MJIW.js → chunk-OM5VDM6F.js} +2 -2
  21. package/dist/hooks/{chunk-SSX23SJ2.js → chunk-RKUAD3I6.js} +1 -0
  22. package/dist/hooks/{chunk-77RLKZ5V.js → chunk-V7RH56HU.js} +2 -2
  23. package/dist/hooks/{chunk-FXAKJKTB.js → chunk-WPALEIRX.js} +1 -1
  24. package/dist/hooks/codex-hook-adapter.js +12 -12
  25. package/dist/hooks/duplicate-read-guard.js +7 -7
  26. package/dist/hooks/format-edited.js +3 -3
  27. package/dist/hooks/investigation-guard.js +7 -7
  28. package/dist/hooks/pretool-guard.js +11 -11
  29. package/dist/hooks/session-lang.js +2 -2
  30. package/dist/hooks/stop-guard.js +11 -5
  31. package/dist/josh.js +12 -14
  32. package/eslint/base.js +4 -1
  33. package/package.json +21 -6
  34. package/playwright.config.ts +9 -17
  35. package/ports/index.d.ts +1 -0
  36. package/ports/index.js +1 -0
  37. package/ports/web-server.d.ts +5 -0
  38. package/ports/web-server.js +73 -0
  39. package/prompts/collaboration-workflow/issue-template.md +1 -1
  40. package/scripts/agent/agent-role-profile.ts +11 -0
  41. package/scripts/ci/pr-classification.ts +27 -6
  42. package/scripts/document/document-byte-budget.ts +1 -1
  43. package/scripts/gate/hook-gate-reuse.ts +1 -1
  44. package/scripts/gate/project-checks.ts +60 -6
  45. package/scripts/gate/type-check-command.ts +43 -0
  46. package/scripts/git/constants.ts +4 -0
  47. package/scripts/git/git-command.ts +11 -5
  48. package/scripts/git/git-gh-pr-rollup.ts +56 -16
  49. package/scripts/git/git-staging.ts +6 -4
  50. package/scripts/git/git-stash.ts +73 -1
  51. package/scripts/git/stash-orphans.ts +24 -2
  52. package/scripts/git/stash-sweep-lock.ts +141 -0
  53. package/scripts/hooks/stop-guard.ts +2 -0
  54. package/scripts/init/init-actions.ts +3 -2
  55. package/scripts/init/init-ai-copy.ts +8 -5
  56. package/scripts/init/init-logic-migrate.ts +10 -1
  57. package/scripts/init/init-logic-templates.ts +27 -7
  58. package/scripts/init/init-logic-workspace.ts +89 -5
  59. package/scripts/init/init-logic.ts +7 -1
  60. package/scripts/init/init-static.ts +4 -1
  61. package/scripts/init/init.ts +60 -19
  62. package/scripts/init/project-profile.ts +14 -5
  63. package/scripts/issue/issue-merged.ts +75 -0
  64. package/scripts/issue/measure-rerun-cli.ts +2 -2
  65. package/scripts/josh/__snapshots__/josh-command-map.test.ts.snap +10 -0
  66. package/scripts/josh/josh-command-map.ts +1 -0
  67. package/scripts/josh/josh-command-types.ts +0 -3
  68. package/scripts/josh/josh-commands-ai.ts +6 -0
  69. package/scripts/josh/josh-commands-development.ts +6 -19
  70. package/scripts/lint/format.ts +68 -0
  71. package/scripts/lint/lint-parallel.ts +23 -36
  72. package/scripts/observations/observation-ledger-home.ts +22 -2
  73. package/scripts/observations/observation-ledger-line.ts +11 -0
  74. package/scripts/observations/observation-ledger-migrate.ts +146 -0
  75. package/scripts/observations/observation-ledger.ts +51 -3
  76. package/scripts/observations/observations-flush.ts +38 -7
  77. package/scripts/review/review-finding-ledger.ts +1 -1
  78. package/scripts/review/review-record-cli.ts +1 -7
  79. package/scripts/rules/delivered-rules.ts +10 -0
  80. package/scripts/rules/lane-background.ts +111 -0
  81. package/scripts/rules/stop-rules.ts +15 -2
  82. package/scripts/run/run-carry-flush.ts +2 -7
  83. package/scripts/run/run-hold-cli.ts +10 -2
  84. package/scripts/run/run-step-cli.ts +11 -1
  85. package/scripts/run/run-step.ts +36 -8
  86. package/scripts/run/run-tidy-cli.ts +50 -0
  87. package/scripts/run/run-tidy-lanes.ts +110 -0
  88. package/scripts/run/run-tidy-stashes.ts +160 -0
  89. package/scripts/run/run-tidy.ts +101 -0
  90. package/scripts/safe-chain/ci-installer-pin.ts +90 -0
  91. package/scripts/safe-chain/preinstall-command.ts +39 -0
  92. package/scripts/sync/sync.ts +5 -2
  93. package/scripts/test/pilot-files.ts +0 -1
  94. package/scripts/version/preinstall-version-update.ts +2 -0
  95. package/templates/pnpm-workspace.static.yaml +4 -0
  96. package/templates/workflows/ci.yml +21 -7
  97. package/tsconfig/base.json +4 -1
@@ -20,6 +20,7 @@ import {
20
20
  has_any_label,
21
21
  has_label_name,
22
22
  has_stderr_field,
23
+ lane_background,
23
24
  lane_park,
24
25
  lane_registry,
25
26
  parse_json_array_or_undefined,
@@ -30,34 +31,35 @@ import {
30
31
  run_cut,
31
32
  run_hold,
32
33
  run_progress_clock,
34
+ run_tail,
33
35
  run_watcher_guard,
34
36
  shell_segments,
35
37
  tail_commands
36
- } from "./chunk-LC765SUA.js";
38
+ } from "./chunk-3FWV6CFC.js";
37
39
  import {
38
40
  find_local_bin_upwards
39
41
  } from "./chunk-3V37IID6.js";
40
42
  import {
41
43
  batch_outcome
42
- } from "./chunk-77RLKZ5V.js";
44
+ } from "./chunk-V7RH56HU.js";
43
45
  import {
44
46
  investigation_refusal
45
- } from "./chunk-NWD47MW3.js";
47
+ } from "./chunk-NKVLBB65.js";
46
48
  import {
47
49
  duplicate_read_outcome
48
- } from "./chunk-UANRLZV7.js";
50
+ } from "./chunk-IBFC25IX.js";
49
51
  import {
50
52
  investigation_reads
51
- } from "./chunk-XMR3BS35.js";
53
+ } from "./chunk-M4U4YNRE.js";
52
54
  import {
53
55
  lane_guard_policy,
54
56
  time_batch_guard
55
- } from "./chunk-3HZ5MJIW.js";
57
+ } from "./chunk-OM5VDM6F.js";
56
58
  import {
57
59
  hook_decision,
58
60
  lane_child_marker,
59
61
  run_issue_number
60
- } from "./chunk-OYU6KPRA.js";
62
+ } from "./chunk-O3PEDF3M.js";
61
63
  import {
62
64
  PLATFORM_TEMP_ROOT,
63
65
  cost_attribute,
@@ -69,7 +71,7 @@ import {
69
71
  stamp_file,
70
72
  time_density_hook,
71
73
  time_shell
72
- } from "./chunk-UULARQ5Q.js";
74
+ } from "./chunk-EYFJ74MJ.js";
73
75
 
74
76
  // scripts/hooks/pretool-guard.ts
75
77
  import { text } from "node:stream/consumers";
@@ -2124,55 +2126,6 @@ var rule_body_guard = {
2124
2126
  writes_rule_prose
2125
2127
  };
2126
2128
 
2127
- // scripts/rules/run-tail.ts
2128
- var SEGMENT_PREFIX = String.raw`(?:\(\s*)?(?:[A-Za-z_][A-Za-z0-9_]*=\S*\s+)*(?:npx\s+|pnpm\s+(?:exec\s+|run\s+)?)?`;
2129
- var WORD_END = String.raw`(?=\s|$|\))`;
2130
- var PUSH_STEP_SEGMENT = new RegExp(String.raw`^${SEGMENT_PREFIX}josh\s+(?:git|g)${WORD_END}`, "u");
2131
- var CONFIRMED_FLAG = new RegExp(String.raw`(?:^|\s)(?:-y|--yes)${WORD_END}`, "u");
2132
- var SKIPS_THE_PUSH = new RegExp(String.raw`(?:^|\s)--skip-push${WORD_END}`, "u");
2133
- var BACKGROUND_KEY = "run_in_background";
2134
- var QUOTED_SPAN = /"[^"]*"|'[^']*'/gu;
2135
- function flags_of(segment) {
2136
- return segment.replaceAll(QUOTED_SPAN, " ");
2137
- }
2138
- function is_push_step_segment(segment) {
2139
- if (!PUSH_STEP_SEGMENT.test(segment)) return false;
2140
- const flags = flags_of(segment);
2141
- if (SKIPS_THE_PUSH.test(flags)) return false;
2142
- return CONFIRMED_FLAG.test(flags);
2143
- }
2144
- function is_push_step(command) {
2145
- return shell_segments.segments_of(command).some((segment) => is_push_step_segment(segment));
2146
- }
2147
- function is_backgrounded(input) {
2148
- if (!json_value.is_record(input)) return false;
2149
- return input[BACKGROUND_KEY] === true;
2150
- }
2151
- function is_push_step_call(call) {
2152
- if (call.name !== cost_blocks.BASH_TOOL) return false;
2153
- return is_push_step(time_shell.bash_command(call.input));
2154
- }
2155
- function is_backgrounded_push_step(call) {
2156
- if (!is_backgrounded(call.input)) return false;
2157
- return is_push_step_call(call);
2158
- }
2159
- function is_foreground_push_step(call) {
2160
- if (is_backgrounded(call.input)) return false;
2161
- return is_push_step_call(call);
2162
- }
2163
- function decide4() {
2164
- return true;
2165
- }
2166
- var RUN_TAIL_REASON = '\u26D4 run tail: this issues the commit-push-PR step in the foreground, where the harness decides when to stop waiting. Reissue it with `run_in_background` set. In `fullrun #1501` this call was given a 900-second timeout, the harness detached it at its own 600-second cap, and nothing read the output for a further 6m28s \u2014 45m03s of wall clock on about 17 minutes of work (joshuafolkken/kit#1510). **Never give a foreground call a timeout above the harness cap**: the cap decides, not the number. A backgrounded call re-invokes you when it exits, so the completion notification is what resumes the run. **When it arrives, the turn that reads it goes straight through any branch-2 filing and `pnpm josh epic:bundle` to `pnpm josh followup` \u2014 the turn never ends at the push.** CI went green 6m06s before the merge started in that run, and it started only because the person asked; joshuafolkken/kit#1333 had already settled that the merge is issued in the turn the review closes. While the push runs, do the work that writes nothing \u2014 drafting the completion body to a file, deciding the branch-2 disposition. `pnpm josh followup` itself stays in the **foreground** \u2014 nearly every step after it reads its result. But a tail does follow the merge, measured at 3.0 min and 5.9% of a run (joshuafolkken/kit#1462), so empty it beforehand: the steps that read the merge result stay after `followup`, and the rest are composed in the turn that issues it, bar the one exception background-commands.md names. The procedure is `.claude/skills/workflow-commands/background-commands.md`, "A command that can take minutes is issued in the background". **This rule fires on every foreground push, not once per run**, so reissuing the same call in the foreground will be refused again.';
2167
- var run_tail = {
2168
- RUN_TAIL_REASON,
2169
- decide: decide4,
2170
- is_backgrounded_push_step,
2171
- is_foreground_push_step,
2172
- is_push_step,
2173
- is_push_step_call
2174
- };
2175
-
2176
2129
  // scripts/rules/shell-body-trigger.ts
2177
2130
  var FIELD_FLAGS = "(?:-f|-F|--field|--raw-field)";
2178
2131
  var MESSAGE_FLAGS = "(?:--body|--notify-message)";
@@ -2215,7 +2168,7 @@ var BODY_FLAG = new RegExp(
2215
2168
  String.raw`${FIELD_FLAGS}[\s=]*'?"?body=|${MESSAGE_FLAGS}[\s=]|--body-file[\s=]|--notify-message-file[\s=]`,
2216
2169
  "u"
2217
2170
  );
2218
- var QUOTED_SPAN2 = /"[^"]*"|'[^']*'/gu;
2171
+ var QUOTED_SPAN = /"[^"]*"|'[^']*'/gu;
2219
2172
  function inline_body_literals(command) {
2220
2173
  return Array.from(
2221
2174
  command.matchAll(INLINE_BODY_VALUE),
@@ -2224,7 +2177,7 @@ function inline_body_literals(command) {
2224
2177
  }
2225
2178
  function is_safe_body_form(command) {
2226
2179
  if (ANSI_C_BODY.test(command.replaceAll(DOUBLE_QUOTED_SPAN, " "))) return true;
2227
- const flags = command.replaceAll(QUOTED_SPAN2, " ");
2180
+ const flags = command.replaceAll(QUOTED_SPAN, " ");
2228
2181
  if (FILE_FLAG.test(flags) || FIELD_FILE_REFERENCE.test(flags)) return true;
2229
2182
  return inline_body_literals(command).some((literal) => is_body_already_in_a_file(literal));
2230
2183
  }
@@ -2232,7 +2185,7 @@ function keeps_body_safe(command) {
2232
2185
  return is_safe_body_form(command) && !is_shell_evaluated_body(command);
2233
2186
  }
2234
2187
  function carries_a_body(command) {
2235
- if (BODY_FLAG.test(command.replaceAll(QUOTED_SPAN2, " "))) return true;
2188
+ if (BODY_FLAG.test(command.replaceAll(QUOTED_SPAN, " "))) return true;
2236
2189
  return inline_body_literals(command).length > 0;
2237
2190
  }
2238
2191
  var SHELL_BODY_REASON = "\u26D4 shell-evaluated body: this command carries a body inline in double quotes, and that body contains a backtick or a `$`, so the shell runs it \u2014 the text is executed rather than merely mangled (joshuafolkken/kit#1198). Write the body to a file and pass it by path: `pnpm josh issue:comment <N> --body-file <path>`, `pnpm josh followup --notify-message-file <path>`, or `--body-file <path>` wherever offered. `$'\u2026'` quoting is the other safe form; the rule and the trigger's blind spots are in `prompts/collaboration-workflow/shell-body.md`. Reissue this call once the body is in a file \u2014 it fires once per run and cannot repeat on the call in hand.";
@@ -2255,6 +2208,7 @@ import path5 from "node:path";
2255
2208
  var SKIP_MARKER = "\u2014 skipping";
2256
2209
 
2257
2210
  // scripts/gate/project-checks.ts
2211
+ import { z as z5 } from "zod";
2258
2212
  var PACKAGE_JSON = "package.json";
2259
2213
  var IGNORED_DIRS = /* @__PURE__ */ new Set([
2260
2214
  "node_modules",
@@ -2288,6 +2242,8 @@ var CSPELL_CONFIGS = [
2288
2242
  "cspell.yaml"
2289
2243
  ];
2290
2244
  var TYPE_CONFIGS = ["tsconfig.json", "jsconfig.json"];
2245
+ var DEPENDENCY_FIELDS = ["dependencies", "devDependencies"];
2246
+ var object_schema = z5.record(z5.string(), z5.unknown());
2291
2247
  function project_root(directory) {
2292
2248
  let current = directory;
2293
2249
  while (!existsSync3(path5.join(current, PACKAGE_JSON))) {
@@ -2318,15 +2274,29 @@ function is_static_manifest(manifest) {
2318
2274
  if (typeof josh !== "object" || josh === null || !("profile" in josh)) return false;
2319
2275
  return josh.profile === "static";
2320
2276
  }
2321
- function is_static(directory) {
2277
+ function read_manifest(directory) {
2322
2278
  try {
2323
2279
  const manifest_path = path5.join(project_root(directory), PACKAGE_JSON);
2324
- const manifest = JSON.parse(readFileSync5(manifest_path, "utf8"));
2325
- return is_static_manifest(manifest);
2280
+ return JSON.parse(readFileSync5(manifest_path, "utf8"));
2326
2281
  } catch {
2327
- return false;
2282
+ return void 0;
2328
2283
  }
2329
2284
  }
2285
+ function is_static(directory) {
2286
+ return is_static_manifest(read_manifest(directory));
2287
+ }
2288
+ function is_declared(directory, package_name) {
2289
+ const manifest = object_schema.safeParse(read_manifest(directory));
2290
+ if (!manifest.success) return false;
2291
+ return DEPENDENCY_FIELDS.some((field) => {
2292
+ const dependencies = object_schema.safeParse(manifest.data[field]);
2293
+ return dependencies.success && Object.hasOwn(dependencies.data, package_name);
2294
+ });
2295
+ }
2296
+ function missing_tool_reason(directory, package_name, bin_name) {
2297
+ if (has_bin(directory, bin_name) || is_declared(directory, package_name)) return void 0;
2298
+ return `${package_name} is not installed`;
2299
+ }
2330
2300
  function skip_notice(check3, reason) {
2331
2301
  return `josh ${check3}: ${reason} ${SKIP_MARKER} ${check3}.`;
2332
2302
  }
@@ -2334,8 +2304,18 @@ function type_check_skip_reason(directory) {
2334
2304
  if (!is_static(directory)) return void 0;
2335
2305
  if (!has_files(directory, TYPE_FILES)) return "no TypeScript files were found";
2336
2306
  if (!has_config(directory, TYPE_CONFIGS)) return "no TypeScript configuration was found";
2337
- if (!has_bin(directory, "tsc")) return "typescript is not installed";
2338
- return void 0;
2307
+ return missing_tool_reason(directory, "typescript", "tsc");
2308
+ }
2309
+ function prettier_skip_reason(directory) {
2310
+ if (!is_static(directory)) return void 0;
2311
+ if (!has_files(directory, WEB_FILES)) return "no HTML, CSS or JavaScript files were found";
2312
+ return missing_tool_reason(directory, "prettier", "prettier");
2313
+ }
2314
+ function eslint_skip_reason(directory) {
2315
+ if (!is_static(directory)) return void 0;
2316
+ if (!has_files(directory, SCRIPT_FILES)) return "no JavaScript or TypeScript files were found";
2317
+ if (!has_config(directory, ESLINT_CONFIGS)) return "no ESLint configuration was found";
2318
+ return missing_tool_reason(directory, "eslint", "eslint");
2339
2319
  }
2340
2320
  var project_checks = {
2341
2321
  CSPELL_CONFIGS,
@@ -2344,10 +2324,12 @@ var project_checks = {
2344
2324
  TYPE_CONFIGS,
2345
2325
  TYPE_FILES,
2346
2326
  WEB_FILES,
2327
+ eslint_skip_reason,
2347
2328
  has_bin,
2348
2329
  has_config,
2349
2330
  has_files,
2350
2331
  is_static,
2332
+ prettier_skip_reason,
2351
2333
  project_root,
2352
2334
  skip_notice,
2353
2335
  type_check_skip_reason
@@ -2662,6 +2644,15 @@ var DELIVERED_RULES = [
2662
2644
  // verdict is `required`; in the hermetic non-repo suite the git read fails to `exempt`, so
2663
2645
  // `test-declared` claims nothing and the "exactly one rule" invariant over `run-tail`'s fixture holds.
2664
2646
  test_declared_commit.ROW,
2647
+ // **The long-running josh command a lane child backgrounds and loses** (joshuafolkken/kit#2704). A
2648
+ // headless child's background tasks die with its turn, so a backgrounded `josh gate` / `git` /
2649
+ // `followup` is killed before it reports; this refuses the launch and hands back `josh ship
2650
+ // --detach`, whose supervisor outlives the turn. **Listed before `run-tail`, whose push it claims in
2651
+ // a child**: that row answers a foreground push with "reissue it backgrounded", the reissue this row
2652
+ // refuses, so a child is sent to the detached ship on its first refusal instead of through both.
2653
+ // Outside a child it claims nothing. A backgrounded bare `josh git` also trips `josh-git-bare`
2654
+ // below; this row wins, and `ship --detach` satisfies both. It fires on every occurrence.
2655
+ lane_background.ROW,
2665
2656
  // **The one row whose trigger reads a field of the input beside the command**, so it supplies its
2666
2657
  // own tool-name check rather than going through `on_bash_command`: a push step already issued with
2667
2658
  // `run_in_background` is the rule obeyed, and refusing it would charge a run for doing the right
@@ -2873,12 +2864,12 @@ function is_first_delivery(tail, call, delivered_at_ms, run2) {
2873
2864
  return delivered_at_ms === hook_decision.NEVER_MS && !will_batch_guard_refuse(tail, call, run2);
2874
2865
  }
2875
2866
  function delivery_decision(rule) {
2876
- const { decide: decide7, already_satisfied } = rule;
2877
- if (decide7 === void 0 && already_satisfied === void 0) return is_first_delivery;
2867
+ const { decide: decide6, already_satisfied } = rule;
2868
+ if (decide6 === void 0 && already_satisfied === void 0) return is_first_delivery;
2878
2869
  return function should_block(tail, call, delivered_at_ms, run2) {
2879
2870
  if (already_satisfied?.(tail, call) === true) return false;
2880
- if (decide7 === void 0) return is_first_delivery(tail, call, delivered_at_ms, run2);
2881
- return decide7(call, run2, !will_batch_guard_refuse(tail, call, run2), delivered_at_ms);
2871
+ if (decide6 === void 0) return is_first_delivery(tail, call, delivered_at_ms, run2);
2872
+ return decide6(call, run2, !will_batch_guard_refuse(tail, call, run2), delivered_at_ms);
2882
2873
  };
2883
2874
  }
2884
2875
  function guard_of(rule) {
@@ -2934,7 +2925,7 @@ var delivered_rules = {
2934
2925
  };
2935
2926
 
2936
2927
  // scripts/run/run-watcher-hook.ts
2937
- import { z as z16 } from "zod";
2928
+ import { z as z17 } from "zod";
2938
2929
 
2939
2930
  // scripts/run/run-progress-read.ts
2940
2931
  import { loadavg } from "node:os";
@@ -2968,7 +2959,7 @@ var git_gh_helpers = {
2968
2959
  };
2969
2960
 
2970
2961
  // scripts/git/git-gh-issue-rest.ts
2971
- import { z as z6 } from "zod";
2962
+ import { z as z7 } from "zod";
2972
2963
 
2973
2964
  // scripts/git/git-gh-rest-state.ts
2974
2965
  var MERGED_STATE = "MERGED";
@@ -2977,80 +2968,80 @@ function to_gh_state(state) {
2977
2968
  }
2978
2969
 
2979
2970
  // scripts/git/schemas.ts
2980
- import { z as z5 } from "zod";
2981
- var package_name_schema = z5.object({ name: z5.string().min(1) });
2982
- var rollup_item_schema = z5.looseObject({
2971
+ import { z as z6 } from "zod";
2972
+ var package_name_schema = z6.object({ name: z6.string().min(1) });
2973
+ var rollup_item_schema = z6.looseObject({
2983
2974
  // eslint-disable-next-line @typescript-eslint/naming-convention -- GraphQL field name from GitHub API
2984
- __typename: z5.string().optional(),
2985
- state: z5.string().optional(),
2986
- status: z5.string().optional(),
2987
- conclusion: z5.string().optional(),
2988
- name: z5.string().optional(),
2989
- context: z5.string().optional()
2975
+ __typename: z6.string().optional(),
2976
+ state: z6.string().optional(),
2977
+ status: z6.string().optional(),
2978
+ conclusion: z6.string().optional(),
2979
+ name: z6.string().optional(),
2980
+ context: z6.string().optional()
2990
2981
  });
2991
- var pr_raw_schema = z5.object({
2992
- statusCheckRollup: z5.array(rollup_item_schema).optional(),
2993
- mergeStateStatus: z5.string().optional(),
2994
- reviewDecision: z5.string().optional()
2982
+ var pr_raw_schema = z6.object({
2983
+ statusCheckRollup: z6.array(rollup_item_schema).optional(),
2984
+ mergeStateStatus: z6.string().optional(),
2985
+ reviewDecision: z6.string().optional()
2995
2986
  });
2996
- var pull_comment_schema = z5.object({
2997
- body: z5.string().optional(),
2998
- html_url: z5.string().optional(),
2999
- user: z5.object({ login: z5.string().optional() }).optional()
2987
+ var pull_comment_schema = z6.object({
2988
+ body: z6.string().optional(),
2989
+ html_url: z6.string().optional(),
2990
+ user: z6.object({ login: z6.string().optional() }).optional()
3000
2991
  });
3001
- var ai_review_pull_comment_schema = z5.object({
3002
- body: z5.string().optional(),
3003
- url: z5.string().optional(),
3004
- author: z5.object({ login: z5.string().optional() }).optional()
2992
+ var ai_review_pull_comment_schema = z6.object({
2993
+ body: z6.string().optional(),
2994
+ url: z6.string().optional(),
2995
+ author: z6.object({ login: z6.string().optional() }).optional()
3005
2996
  });
3006
- var pr_info_schema = z5.object({
3007
- mergeable: z5.union([z5.boolean(), z5.string()]).nullable().optional(),
3008
- mergeStateStatus: z5.string().nullable().optional(),
3009
- state: z5.string().optional()
2997
+ var pr_info_schema = z6.object({
2998
+ mergeable: z6.union([z6.boolean(), z6.string()]).nullable().optional(),
2999
+ mergeStateStatus: z6.string().nullable().optional(),
3000
+ state: z6.string().optional()
3010
3001
  });
3011
- var epic_issue_schema = z5.object({
3012
- number: z5.number(),
3013
- body: z5.string().optional()
3002
+ var epic_issue_schema = z6.object({
3003
+ number: z6.number(),
3004
+ body: z6.string().optional()
3014
3005
  });
3015
- var blocking_issue_schema = z5.object({
3016
- number: z5.number(),
3017
- state: z5.string().optional(),
3018
- repository_url: z5.string().optional()
3006
+ var blocking_issue_schema = z6.object({
3007
+ number: z6.number(),
3008
+ state: z6.string().optional(),
3009
+ repository_url: z6.string().optional()
3019
3010
  });
3020
- var blocked_by_schema = z5.object({
3021
- nodes: z5.array(blocking_issue_schema).default([]),
3022
- totalCount: z5.number().optional()
3011
+ var blocked_by_schema = z6.object({
3012
+ nodes: z6.array(blocking_issue_schema).default([]),
3013
+ totalCount: z6.number().optional()
3023
3014
  }).optional();
3024
- var epic_child_schema = z5.object({
3025
- state: z5.string().optional(),
3015
+ var epic_child_schema = z6.object({
3016
+ state: z6.string().optional(),
3026
3017
  blockedBy: blocked_by_schema
3027
3018
  });
3028
- var rest_comment_schema = z5.looseObject({
3029
- body: z5.string().nullish(),
3030
- html_url: z5.string().optional(),
3031
- user: z5.looseObject({ login: z5.string().optional() }).nullish()
3019
+ var rest_comment_schema = z6.looseObject({
3020
+ body: z6.string().nullish(),
3021
+ html_url: z6.string().optional(),
3022
+ user: z6.looseObject({ login: z6.string().optional() }).nullish()
3032
3023
  });
3033
- var issue_label_schema = z5.object({ name: z5.string() });
3034
- var epic_subject_schema = z5.object({
3035
- number: z5.number(),
3036
- state: z5.string().optional(),
3037
- labels: z5.array(issue_label_schema).optional(),
3038
- body: z5.string().optional()
3024
+ var issue_label_schema = z6.object({ name: z6.string() });
3025
+ var epic_subject_schema = z6.object({
3026
+ number: z6.number(),
3027
+ state: z6.string().optional(),
3028
+ labels: z6.array(issue_label_schema).optional(),
3029
+ body: z6.string().optional()
3039
3030
  });
3040
- var open_issue_schema = z5.object({
3041
- number: z5.number(),
3042
- title: z5.string(),
3043
- labels: z5.array(issue_label_schema).optional(),
3044
- createdAt: z5.string(),
3031
+ var open_issue_schema = z6.object({
3032
+ number: z6.number(),
3033
+ title: z6.string(),
3034
+ labels: z6.array(issue_label_schema).optional(),
3035
+ createdAt: z6.string(),
3045
3036
  blockedBy: blocked_by_schema
3046
3037
  });
3047
3038
 
3048
3039
  // scripts/git/git-gh-issue-rest.ts
3049
- var rest_issue_schema = z6.looseObject({
3050
- number: z6.number(),
3051
- issue_dependencies_summary: z6.looseObject({ total_blocked_by: z6.number().optional() }).nullish(),
3040
+ var rest_issue_schema = z7.looseObject({
3041
+ number: z7.number(),
3042
+ issue_dependencies_summary: z7.looseObject({ total_blocked_by: z7.number().optional() }).nullish(),
3052
3043
  // Present only on a pull request, which this endpoint serves as readily as an issue.
3053
- pull_request: z6.looseObject({ merged_at: z6.string().nullish() }).nullish()
3044
+ pull_request: z7.looseObject({ merged_at: z7.string().nullish() }).nullish()
3054
3045
  });
3055
3046
  var REPOSITORY_URL = /\/repos\/([\w.-]+\/[\w.-]+)$/u;
3056
3047
  var REPOSITORY_URL_GROUP = 1;
@@ -3584,7 +3575,8 @@ var git_gh_issue = {
3584
3575
  // scripts/ci/pr-classification.ts
3585
3576
  import { readFileSync as readFileSync6 } from "node:fs";
3586
3577
  import { fileURLToPath as fileURLToPath2 } from "node:url";
3587
- import { z as z7 } from "zod";
3578
+ import { execaSync } from "execa";
3579
+ import { z as z8 } from "zod";
3588
3580
  var BUGFIX = "bugfix";
3589
3581
  var BREAKING = "breaking-change";
3590
3582
  var CLASSIFICATION_LABELS2 = [
@@ -3598,11 +3590,12 @@ var CLASSIFICATION_SET = new Set(CLASSIFICATION_LABELS2);
3598
3590
  var ISSUE_BUG_LABEL = "bug";
3599
3591
  var DECLARATION = /^- リリース分類: (.+)$/gmu;
3600
3592
  var LEGACY_LABELS = /* @__PURE__ */ new Set(["semver-major", "semver-minor"]);
3601
- var LABEL = z7.object({ name: z7.string() });
3602
- var USER = z7.object({ login: z7.string() });
3603
- var PULL_REQUEST = z7.object({ user: USER, labels: z7.array(LABEL) });
3604
- var EVENT = z7.object({
3605
- pull_request: PULL_REQUEST
3593
+ var LABEL = z8.object({ name: z8.string() });
3594
+ var USER = z8.object({ login: z8.string() });
3595
+ var PULL_REQUEST = z8.object({ number: z8.number(), user: USER });
3596
+ var EVENT = z8.object({
3597
+ pull_request: PULL_REQUEST,
3598
+ repository: z8.object({ full_name: z8.string() })
3606
3599
  });
3607
3600
  function classification_error(labels, author) {
3608
3601
  const legacy = labels.filter((label) => LEGACY_LABELS.has(label.toLowerCase()));
@@ -3622,7 +3615,7 @@ function release_candidates(candidates) {
3622
3615
  return candidates.filter((candidate) => candidate !== "enhancement");
3623
3616
  }
3624
3617
  function issue_candidates(issue_json) {
3625
- const issue = z7.object({ labels: z7.array(LABEL), body: z7.string().nullable() }).parse(JSON.parse(issue_json));
3618
+ const issue = z8.object({ labels: z8.array(LABEL), body: z8.string().nullable() }).parse(JSON.parse(issue_json));
3626
3619
  const names = issue.labels.map((label) => label.name.toLowerCase());
3627
3620
  const declared = [...(issue.body ?? "").matchAll(DECLARATION)].map((match) => match[1] ?? "");
3628
3621
  const candidates = [...release_candidates([...names, ...declared].filter(is_classification))];
@@ -3644,12 +3637,21 @@ function select_issue_classification(issue_json) {
3644
3637
  }
3645
3638
  return label;
3646
3639
  }
3647
- function check_event(event_path) {
3648
- const event = EVENT.parse(JSON.parse(readFileSync6(event_path, "utf8")));
3649
- return classification_error(
3650
- event.pull_request.labels.map((label) => label.name),
3651
- event.pull_request.user.login
3640
+ function fetch_current_labels(repository, pull_number) {
3641
+ const result = execaSync(
3642
+ "gh",
3643
+ ["api", `repos/${repository}/issues/${String(pull_number)}/labels`, "--jq", ".[].name"],
3644
+ { reject: false }
3652
3645
  );
3646
+ if (result.exitCode !== 0) {
3647
+ throw new Error(`Could not read the pull request labels: ${result.stderr}`);
3648
+ }
3649
+ return result.stdout.split("\n").filter((name) => name !== "");
3650
+ }
3651
+ function check_event(event_path, read_labels = fetch_current_labels) {
3652
+ const event = EVENT.parse(JSON.parse(readFileSync6(event_path, "utf8")));
3653
+ const labels = read_labels(event.repository.full_name, event.pull_request.number);
3654
+ return classification_error(labels, event.pull_request.user.login);
3653
3655
  }
3654
3656
  if (process.argv[1] === fileURLToPath2(import.meta.url)) {
3655
3657
  const event_path = process.env["GITHUB_EVENT_PATH"];
@@ -3687,31 +3689,31 @@ async function poll_until(is_done, options) {
3687
3689
  var poll = { poll_until, sleep };
3688
3690
 
3689
3691
  // scripts/git/git-gh-pr.ts
3690
- import { z as z11 } from "zod";
3692
+ import { z as z12 } from "zod";
3691
3693
 
3692
3694
  // scripts/git/git-gh-pr-rest.ts
3693
- import { z as z8 } from "zod";
3694
- var rest_repo_schema = z8.looseObject({ full_name: z8.string().optional() }).nullish();
3695
- var rest_pull_side_schema = z8.looseObject({ repo: rest_repo_schema });
3696
- var rest_pull_schema = z8.looseObject({
3697
- number: z8.number(),
3698
- html_url: z8.string().optional(),
3699
- body: z8.string().nullish(),
3700
- state: z8.string().optional(),
3701
- merged: z8.boolean().nullish(),
3702
- merged_at: z8.string().nullish(),
3703
- mergeable: z8.boolean().nullish(),
3704
- mergeable_state: z8.string().optional(),
3695
+ import { z as z9 } from "zod";
3696
+ var rest_repo_schema = z9.looseObject({ full_name: z9.string().optional() }).nullish();
3697
+ var rest_pull_side_schema = z9.looseObject({ repo: rest_repo_schema });
3698
+ var rest_pull_schema = z9.looseObject({
3699
+ number: z9.number(),
3700
+ html_url: z9.string().optional(),
3701
+ body: z9.string().nullish(),
3702
+ state: z9.string().optional(),
3703
+ merged: z9.boolean().nullish(),
3704
+ merged_at: z9.string().nullish(),
3705
+ mergeable: z9.boolean().nullish(),
3706
+ mergeable_state: z9.string().optional(),
3705
3707
  // `sha` is the head commit, which is what both halves of the merge-gate rollup are keyed by —
3706
3708
  // REST hangs the check runs and the status contexts off the commit rather than off the pull
3707
3709
  // request (joshuafolkken/kit#1028).
3708
- head: z8.looseObject({ ref: z8.string().optional(), sha: z8.string().optional(), repo: rest_repo_schema }).nullish(),
3710
+ head: z9.looseObject({ ref: z9.string().optional(), sha: z9.string().optional(), repo: rest_repo_schema }).nullish(),
3709
3711
  base: rest_pull_side_schema.nullish(),
3710
3712
  // `node_id` is what the GraphQL auto-merge mutation addresses a pull request by, and `auto_merge`
3711
3713
  // is `null` until auto-merge is enabled — both read by `git-gh-pr-auto-merge.ts`
3712
3714
  // (joshuafolkken/kit#2497).
3713
- node_id: z8.string().optional(),
3714
- auto_merge: z8.looseObject({}).nullish()
3715
+ node_id: z9.string().optional(),
3716
+ auto_merge: z9.looseObject({}).nullish()
3715
3717
  });
3716
3718
  var NOT_A_PULL_MESSAGE = "gh api answered something other than a pull request object";
3717
3719
  var NOT_A_PULL_LISTING_MESSAGE = "gh api answered something other than a pull request listing";
@@ -3911,14 +3913,14 @@ var git_gh_pr_read = {
3911
3913
  };
3912
3914
 
3913
3915
  // scripts/git/git-gh-pr-review.ts
3914
- import { z as z9 } from "zod";
3916
+ import { z as z10 } from "zod";
3915
3917
  var REVIEW_APPROVED = "APPROVED";
3916
3918
  var REVIEW_CHANGES_REQUESTED = "CHANGES_REQUESTED";
3917
3919
  var REVIEW_NONE = "";
3918
3920
  var STATE_CHANGING_REVIEWS = /* @__PURE__ */ new Set([REVIEW_APPROVED, REVIEW_CHANGES_REQUESTED]);
3919
- var rest_review_schema = z9.looseObject({
3920
- state: z9.string().optional(),
3921
- user: z9.looseObject({ login: z9.string().optional() }).nullish()
3921
+ var rest_review_schema = z10.looseObject({
3922
+ state: z10.string().optional(),
3923
+ user: z10.looseObject({ login: z10.string().optional() }).nullish()
3922
3924
  });
3923
3925
  var NOT_A_REVIEW_LISTING = "gh api answered something other than a review listing";
3924
3926
  function parse_rest_reviews(reviews_json) {
@@ -3951,18 +3953,18 @@ function to_review_decision(reviews_json) {
3951
3953
  var git_gh_pr_review = { to_review_decision, parse_rest_reviews };
3952
3954
 
3953
3955
  // scripts/git/git-gh-pr-rollup.ts
3954
- import { z as z10 } from "zod";
3956
+ import { z as z11 } from "zod";
3955
3957
  var STATUS_CONTEXT_TYPE_NAME = "StatusContext";
3956
3958
  var TYPE_NAME_KEY = "__typename";
3957
- var rollup_element_schema = z10.looseObject({});
3958
- var check_runs_page_schema = z10.looseObject({
3959
+ var rollup_element_schema = z11.looseObject({});
3960
+ var check_runs_page_schema = z11.looseObject({
3959
3961
  // Required, not optional: GitHub always names the key, and accepting a page without one would
3960
3962
  // answer an empty rollup — which `git-pr-followup.ts` reports as "this branch has no checks".
3961
- check_runs: z10.array(rollup_element_schema)
3963
+ check_runs: z11.array(rollup_element_schema)
3962
3964
  });
3963
- var check_run_app_schema = z10.object({ id: z10.number() });
3964
- var status_page_schema = z10.looseObject({
3965
- statuses: z10.array(rollup_element_schema)
3965
+ var id_holder_schema = z11.object({ id: z11.number() });
3966
+ var status_page_schema = z11.looseObject({
3967
+ statuses: z11.array(rollup_element_schema)
3966
3968
  });
3967
3969
  var NOT_A_CHECK_RUNS_LISTING = "gh api answered something other than a check run listing";
3968
3970
  var NOT_A_STATUS_LISTING = "gh api answered something other than a commit status listing";
@@ -3971,31 +3973,46 @@ function read_pages(raw_json, schema, message) {
3971
3973
  if (pages === void 0) throw new Error(message);
3972
3974
  return pages;
3973
3975
  }
3976
+ var NO_SUITE = -1;
3977
+ function read_id(value) {
3978
+ const parsed = id_holder_schema.safeParse(value);
3979
+ return parsed.success ? parsed.data.id : void 0;
3980
+ }
3974
3981
  function check_run_group_key(run2) {
3975
- const { name, app: raw_app } = run2;
3982
+ const { name, app } = run2;
3976
3983
  if (typeof name !== "string") return void 0;
3977
- const app = check_run_app_schema.safeParse(raw_app);
3978
- return JSON.stringify([name, app.success ? app.data.id : void 0]);
3984
+ return JSON.stringify([name, read_id(app)]);
3985
+ }
3986
+ function read_rank(run2) {
3987
+ const id = read_id(run2);
3988
+ if (id === void 0) return void 0;
3989
+ return { suite: read_id(run2["check_suite"]) ?? NO_SUITE, run: id };
3990
+ }
3991
+ function is_ranked_above(candidate, current) {
3992
+ if (candidate.suite !== current.suite) return candidate.suite > current.suite;
3993
+ return candidate.run > current.run;
3979
3994
  }
3980
- function remember_newest_run(run2, latest_ids) {
3995
+ function should_replace(previous, rank) {
3996
+ const previous_rank = previous === void 0 ? void 0 : read_rank(previous);
3997
+ return previous_rank === void 0 || is_ranked_above(rank, previous_rank);
3998
+ }
3999
+ function remember_newest_run(run2, newest) {
3981
4000
  const key = check_run_group_key(run2);
3982
- const { id } = run2;
3983
- if (key === void 0 || typeof id !== "number") return;
3984
- const previous_id = latest_ids.get(key);
3985
- if (previous_id === void 0 || id > previous_id) latest_ids.set(key, id);
4001
+ const rank = read_rank(run2);
4002
+ if (key === void 0 || rank === void 0) return;
4003
+ if (should_replace(newest.get(key), rank)) newest.set(key, run2);
3986
4004
  }
3987
- function is_newest_run(run2, latest_ids) {
4005
+ function is_newest_run(run2, newest) {
3988
4006
  const key = check_run_group_key(run2);
3989
- const { id } = run2;
3990
- if (key === void 0 || typeof id !== "number") return true;
3991
- return id === latest_ids.get(key);
4007
+ if (key === void 0 || read_rank(run2) === void 0) return true;
4008
+ return newest.get(key) === run2;
3992
4009
  }
3993
4010
  function to_check_run_items(check_runs_json) {
3994
4011
  const pages = read_pages(check_runs_json, check_runs_page_schema, NOT_A_CHECK_RUNS_LISTING);
3995
4012
  const runs = pages.flatMap((page) => page.check_runs);
3996
- const latest_ids = /* @__PURE__ */ new Map();
3997
- for (const run2 of runs) remember_newest_run(run2, latest_ids);
3998
- return runs.filter((run2) => is_newest_run(run2, latest_ids));
4013
+ const newest = /* @__PURE__ */ new Map();
4014
+ for (const run2 of runs) remember_newest_run(run2, newest);
4015
+ return runs.filter((run2) => is_newest_run(run2, newest));
3999
4016
  }
4000
4017
  function to_status_context_items(status_json) {
4001
4018
  const pages = read_pages(status_json, status_page_schema, NOT_A_STATUS_LISTING);
@@ -4083,7 +4100,7 @@ var MERGE_READ_BACK_ATTEMPTS = 3;
4083
4100
  var MERGE_READ_BACK_INTERVAL_MS = 1e3;
4084
4101
  var PR_NUMBER_PATTERN = /\/pull\/([1-9]\d*)$/u;
4085
4102
  var LABELS_SEGMENT2 = "/labels";
4086
- var PR_LABELS = z11.array(z11.object({ name: z11.string() }));
4103
+ var PR_LABELS = z12.array(z12.object({ name: z12.string() }));
4087
4104
  async function add_pr_classification(number, label) {
4088
4105
  await git_gh_exec.exec_gh_api({
4089
4106
  path: `${git_gh_api_path.issue_api_path(number)}${LABELS_SEGMENT2}`,
@@ -4673,24 +4690,24 @@ import path6 from "node:path";
4673
4690
  import { setTimeout as sleep2 } from "node:timers/promises";
4674
4691
 
4675
4692
  // scripts/agent/agent-event.ts
4676
- import { z as z13 } from "zod";
4693
+ import { z as z14 } from "zod";
4677
4694
 
4678
4695
  // scripts/agent/claude-result-event.ts
4679
- import { z as z12 } from "zod";
4680
- var RESULT_EVENT_SCHEMA = z12.looseObject({
4681
- type: z12.literal("result"),
4682
- is_error: z12.unknown().optional(),
4683
- subtype: z12.unknown().optional(),
4684
- num_turns: z12.unknown().optional(),
4685
- permission_denials: z12.unknown().optional(),
4686
- result: z12.unknown().optional(),
4687
- session_id: z12.unknown().optional(),
4688
- usage: z12.unknown().optional()
4696
+ import { z as z13 } from "zod";
4697
+ var RESULT_EVENT_SCHEMA = z13.looseObject({
4698
+ type: z13.literal("result"),
4699
+ is_error: z13.unknown().optional(),
4700
+ subtype: z13.unknown().optional(),
4701
+ num_turns: z13.unknown().optional(),
4702
+ permission_denials: z13.unknown().optional(),
4703
+ result: z13.unknown().optional(),
4704
+ session_id: z13.unknown().optional(),
4705
+ usage: z13.unknown().optional()
4689
4706
  });
4690
- var USAGE_SCHEMA = z12.looseObject({
4691
- input_tokens: z12.unknown().optional(),
4692
- cache_read_input_tokens: z12.unknown().optional(),
4693
- output_tokens: z12.unknown().optional()
4707
+ var USAGE_SCHEMA = z13.looseObject({
4708
+ input_tokens: z13.unknown().optional(),
4709
+ cache_read_input_tokens: z13.unknown().optional(),
4710
+ output_tokens: z13.unknown().optional()
4694
4711
  });
4695
4712
  function usable_reason(value) {
4696
4713
  return typeof value === "string" && value.trim() !== "" ? value : void 0;
@@ -4729,31 +4746,31 @@ function decode2(value) {
4729
4746
  var claude_result_event = { decode: decode2 };
4730
4747
 
4731
4748
  // scripts/agent/agent-event.ts
4732
- var TEXT_BLOCK_SCHEMA = z13.looseObject({ type: z13.literal("text"), text: z13.string() });
4733
- var CLAUDE_MESSAGE_SCHEMA = z13.looseObject({ content: z13.array(z13.unknown()).optional() });
4734
- var CLAUDE_INIT_SCHEMA = z13.looseObject({ type: z13.literal("system"), subtype: z13.literal("init") });
4735
- var CLAUDE_ASSISTANT_SCHEMA = z13.looseObject({
4736
- type: z13.literal("assistant"),
4749
+ var TEXT_BLOCK_SCHEMA = z14.looseObject({ type: z14.literal("text"), text: z14.string() });
4750
+ var CLAUDE_MESSAGE_SCHEMA = z14.looseObject({ content: z14.array(z14.unknown()).optional() });
4751
+ var CLAUDE_INIT_SCHEMA = z14.looseObject({ type: z14.literal("system"), subtype: z14.literal("init") });
4752
+ var CLAUDE_ASSISTANT_SCHEMA = z14.looseObject({
4753
+ type: z14.literal("assistant"),
4737
4754
  message: CLAUDE_MESSAGE_SCHEMA
4738
4755
  });
4739
- var USAGE_SCHEMA2 = z13.looseObject({
4740
- input_tokens: z13.number().optional(),
4741
- cached_input_tokens: z13.number().optional(),
4742
- output_tokens: z13.number().optional()
4756
+ var USAGE_SCHEMA2 = z14.looseObject({
4757
+ input_tokens: z14.number().optional(),
4758
+ cached_input_tokens: z14.number().optional(),
4759
+ output_tokens: z14.number().optional()
4743
4760
  });
4744
- var CODEX_START_SCHEMA = z13.looseObject({ type: z13.enum(["thread.started", "turn.started"]) });
4745
- var CODEX_PROGRESS_SCHEMA = z13.looseObject({
4746
- type: z13.enum(["item.started", "item.updated", "item.completed"]),
4747
- item: z13.looseObject({ type: z13.string(), text: z13.string().optional() }).optional()
4761
+ var CODEX_START_SCHEMA = z14.looseObject({ type: z14.enum(["thread.started", "turn.started"]) });
4762
+ var CODEX_PROGRESS_SCHEMA = z14.looseObject({
4763
+ type: z14.enum(["item.started", "item.updated", "item.completed"]),
4764
+ item: z14.looseObject({ type: z14.string(), text: z14.string().optional() }).optional()
4748
4765
  });
4749
- var CODEX_COMPLETE_SCHEMA = z13.looseObject({
4750
- type: z13.literal("turn.completed"),
4766
+ var CODEX_COMPLETE_SCHEMA = z14.looseObject({
4767
+ type: z14.literal("turn.completed"),
4751
4768
  usage: USAGE_SCHEMA2.optional()
4752
4769
  });
4753
- var CODEX_FAILURE_SCHEMA = z13.looseObject({
4754
- type: z13.enum(["turn.failed", "error"]),
4755
- error: z13.looseObject({ message: z13.string().optional() }).optional(),
4756
- message: z13.string().optional()
4770
+ var CODEX_FAILURE_SCHEMA = z14.looseObject({
4771
+ type: z14.enum(["turn.failed", "error"]),
4772
+ error: z14.looseObject({ message: z14.string().optional() }).optional(),
4773
+ message: z14.string().optional()
4757
4774
  });
4758
4775
  var EMPTY_STATE = {
4759
4776
  provider: void 0,
@@ -4851,7 +4868,7 @@ function describe(state) {
4851
4868
  var agent_event = { describe, read };
4852
4869
 
4853
4870
  // scripts/issue/issue-state.ts
4854
- import { z as z14 } from "zod";
4871
+ import { z as z15 } from "zod";
4855
4872
  var NO_LABELS = "(none)";
4856
4873
  var LABEL_SEPARATOR = ", ";
4857
4874
  var STATE_LABEL = "state: ";
@@ -4861,9 +4878,9 @@ var YES = "yes";
4861
4878
  var NO = "no";
4862
4879
  var ISSUE_LABEL = "issue: ";
4863
4880
  var HUMAN_REVIEW_LABELS = /* @__PURE__ */ new Set([NEEDS_HUMAN_REVIEW_LABEL]);
4864
- var label_schema = z14.looseObject({ name: z14.string() });
4865
- var issue_state_schema = z14.looseObject({
4866
- state: z14.string(),
4881
+ var label_schema = z15.looseObject({ name: z15.string() });
4882
+ var issue_state_schema = z15.looseObject({
4883
+ state: z15.string(),
4867
4884
  labels: label_schema.array().optional()
4868
4885
  });
4869
4886
  function parse_issue_state(json) {
@@ -4961,7 +4978,7 @@ function to_advice(verdict, has_work_to_stash) {
4961
4978
  if (verdict === UNDETERMINED_VERDICT) return UNDETERMINED_ADVICE;
4962
4979
  return has_work_to_stash ? STOPPED_DIRTY_ADVICE : STOPPED_CLEAN_ADVICE;
4963
4980
  }
4964
- function decide5(traces) {
4981
+ function decide4(traces) {
4965
4982
  const verdict = to_verdict(traces);
4966
4983
  const has_work_to_stash = verdict === STOPPED_VERDICT && traces.is_tree_dirty;
4967
4984
  return {
@@ -5060,11 +5077,11 @@ async function read_traces(request) {
5060
5077
  }
5061
5078
  async function check(request) {
5062
5079
  run_issue_number.require_issue_number(request.issue);
5063
- return decide5(await read_traces(request));
5080
+ return decide4(await read_traces(request));
5064
5081
  }
5065
5082
  var run_liveness = {
5066
5083
  check,
5067
- decide: decide5,
5084
+ decide: decide4,
5068
5085
  describe_agent_state,
5069
5086
  read_child_settled,
5070
5087
  read_agent_state,
@@ -5135,7 +5152,7 @@ var lane_report = {
5135
5152
  };
5136
5153
 
5137
5154
  // scripts/run/run-preflight.ts
5138
- import { z as z15 } from "zod";
5155
+ import { z as z16 } from "zod";
5139
5156
  var CLEAN_VERDICT = "clean";
5140
5157
  var RECLAIM_VERDICT = "reclaim";
5141
5158
  var RESUME_VERDICT = "resume";
@@ -5145,7 +5162,7 @@ var OPEN_PR = "open";
5145
5162
  var MERGED_PR = "merged";
5146
5163
  var CLOSED_PR = "closed";
5147
5164
  var NO_CHILD_WORK = { branch_name: void 0, pr_state: NO_PR };
5148
- var pr_info_schema2 = z15.object({ state: z15.string().optional() });
5165
+ var pr_info_schema2 = z16.object({ state: z16.string().optional() });
5149
5166
  var GH_PR_STATES = /* @__PURE__ */ new Map([
5150
5167
  ["CLOSED", CLOSED_PR],
5151
5168
  ["MERGED", MERGED_PR],
@@ -5214,7 +5231,7 @@ function to_advice2(verdict, issue, tree) {
5214
5231
  if (verdict === PARK_VERDICT) return PARK_ADVICE;
5215
5232
  return CLEAN_ADVICE;
5216
5233
  }
5217
- function decide6(tree, child, issue) {
5234
+ function decide5(tree, child, issue) {
5218
5235
  const verdict = to_verdict2(tree, child);
5219
5236
  return {
5220
5237
  advice: to_advice2(verdict, issue, tree),
@@ -5283,8 +5300,8 @@ async function read_child_state(issue) {
5283
5300
  async function check2(issue) {
5284
5301
  require_issue_number(issue);
5285
5302
  const tree = await read_tree_state();
5286
- if (needs_reclaim(tree)) return decide6(tree, NO_CHILD_WORK, issue);
5287
- return decide6(tree, await read_child_state(issue), issue);
5303
+ if (needs_reclaim(tree)) return decide5(tree, NO_CHILD_WORK, issue);
5304
+ return decide5(tree, await read_child_state(issue), issue);
5288
5305
  }
5289
5306
  var run_preflight = {
5290
5307
  CLEAN_ADVICE,
@@ -5299,7 +5316,7 @@ var run_preflight = {
5299
5316
  MERGED_PR,
5300
5317
  STASH_LABEL_PREFIX,
5301
5318
  check: check2,
5302
- decide: decide6,
5319
+ decide: decide5,
5303
5320
  read_child_state,
5304
5321
  read_pr_state: read_pr_state2,
5305
5322
  to_pr_state: to_pr_state2
@@ -5399,7 +5416,7 @@ var run_progress_read = {
5399
5416
  // scripts/run/run-watcher-hook.ts
5400
5417
  var SWITCH_ENV_KEY2 = "JOSH_WATCHER_GUARD";
5401
5418
  var STAMP_PREFIX2 = "josh-watcher-guard-";
5402
- var payload_schema = z16.object({ transcript_path: z16.string().min(1) });
5419
+ var payload_schema = z17.object({ transcript_path: z17.string().min(1) });
5403
5420
  function transcript_of(raw_payload) {
5404
5421
  try {
5405
5422
  const parsed = payload_schema.safeParse(JSON.parse(raw_payload));