@joshuafolkken/kit 1.3092.0 → 1.3099.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 (124) hide show
  1. package/dist/.inputs-verified.json +1 -1
  2. package/dist/commands/backlog-drive-cli.js +17 -17
  3. package/dist/commands/backlogrun-cli.js +21 -20
  4. package/dist/commands/check-related.js +18 -18
  5. package/dist/commands/{chunk-VXE3V3OC.js → chunk-2CNVIA35.js} +2 -2
  6. package/dist/commands/{chunk-374XGAWD.js → chunk-36XHHYNU.js} +1 -1
  7. package/dist/commands/{chunk-W3MDLQZF.js → chunk-3LUPGBW4.js} +1 -1
  8. package/dist/commands/{chunk-T6OUNP7E.js → chunk-3VLDFM5I.js} +6 -6
  9. package/dist/commands/{chunk-4K7KLR7L.js → chunk-6AHAY5VZ.js} +1 -1
  10. package/dist/commands/{chunk-ET6IRQ3L.js → chunk-6FN37DER.js} +3 -3
  11. package/dist/commands/{chunk-LBMAJDGN.js → chunk-6JD4VNO4.js} +2 -2
  12. package/dist/commands/{chunk-KD3SEAMV.js → chunk-7HYYHCTN.js} +2 -2
  13. package/dist/commands/{chunk-4GUGC4IW.js → chunk-7K5ITPHR.js} +2 -2
  14. package/dist/commands/{chunk-XTJA34ND.js → chunk-7ULYLGUK.js} +10 -10
  15. package/dist/commands/{chunk-IEKW3ON6.js → chunk-ABM2MZBF.js} +1 -1
  16. package/dist/commands/{chunk-IOKOHB7P.js → chunk-BBLEC4YQ.js} +1 -1
  17. package/dist/commands/{chunk-V2T5DP3B.js → chunk-C7FGDZWP.js} +1 -1
  18. package/dist/commands/{chunk-MHXIJKGP.js → chunk-EHPTXSAT.js} +20 -9
  19. package/dist/commands/{chunk-PF3PMT2Q.js → chunk-EPICTV2P.js} +1 -1
  20. package/dist/commands/{chunk-GVDRRBHZ.js → chunk-EVVQJJFV.js} +2 -2
  21. package/dist/commands/{chunk-NOSG3RUP.js → chunk-F57LACNC.js} +2 -2
  22. package/dist/commands/{chunk-BAEDHPXW.js → chunk-FA7CN75F.js} +4 -4
  23. package/dist/commands/{chunk-62NYXZCC.js → chunk-FDASVHZD.js} +1 -1
  24. package/dist/commands/{chunk-YMAEYY5R.js → chunk-FEYZ575X.js} +1 -1
  25. package/dist/commands/{chunk-PILH72AV.js → chunk-FTAWHAI7.js} +1 -1
  26. package/dist/commands/{chunk-MK4CARBI.js → chunk-G3BBCAAH.js} +1 -1
  27. package/dist/commands/{chunk-Z6QLFPFB.js → chunk-GABDPTDK.js} +4 -4
  28. package/dist/commands/{chunk-VHLDQ3PH.js → chunk-HHS3LYLV.js} +2 -2
  29. package/dist/commands/{chunk-EE4VOZJP.js → chunk-HQZ65PJE.js} +3 -3
  30. package/dist/commands/{chunk-KHGDZQRG.js → chunk-HSZECERZ.js} +2 -2
  31. package/dist/commands/{chunk-BLUAO4QW.js → chunk-IY3DSDRW.js} +1 -1
  32. package/dist/commands/{chunk-2XZF3YFY.js → chunk-J2RUI4KN.js} +1 -1
  33. package/dist/commands/{chunk-2Q7MGFYB.js → chunk-J3PCRUVY.js} +27 -12
  34. package/dist/commands/{chunk-RDUFVQVJ.js → chunk-JU2MAYQ3.js} +7 -7
  35. package/dist/commands/{chunk-ZEUKX3RZ.js → chunk-KJPZPTS4.js} +1 -1
  36. package/dist/commands/{chunk-7E43YW53.js → chunk-MHF6BDQI.js} +1 -1
  37. package/dist/commands/{chunk-BE6F4YK2.js → chunk-OHN3QARP.js} +10 -10
  38. package/dist/commands/{chunk-AT46EY7H.js → chunk-OKBZGLD5.js} +1 -1
  39. package/dist/commands/{chunk-XCCT6GKA.js → chunk-OZN4HOZT.js} +2 -2
  40. package/dist/commands/{chunk-ZJ5S4VFD.js → chunk-RAQ3E6OT.js} +1 -1
  41. package/dist/commands/{chunk-XSKJAG72.js → chunk-S5GX3H4P.js} +1 -1
  42. package/dist/commands/{chunk-HESWKELD.js → chunk-SC57VV6A.js} +1 -1
  43. package/dist/commands/{chunk-EZYW54OQ.js → chunk-SOETJZWH.js} +221 -118
  44. package/dist/commands/{chunk-HNFBEB4L.js → chunk-UUA63LCI.js} +1 -1
  45. package/dist/commands/{chunk-ZGBXUY7R.js → chunk-UZDKCGDC.js} +1 -1
  46. package/dist/commands/{chunk-B5XYAWNN.js → chunk-VPRQFM2T.js} +1 -1
  47. package/dist/commands/{chunk-M4WG74Q7.js → chunk-VUCDGQ6Y.js} +1 -1
  48. package/dist/commands/{chunk-UX3HCPLX.js → chunk-W7X7MZZN.js} +1 -1
  49. package/dist/commands/{chunk-EN65ZS3S.js → chunk-WORHUJ6T.js} +1 -1
  50. package/dist/commands/chunk-WRHMYSW7.js +36 -0
  51. package/dist/commands/{chunk-K5H3CLZZ.js → chunk-YANDBVAT.js} +1 -1
  52. package/dist/commands/{chunk-GWTBIGYC.js → chunk-YD7XK2TX.js} +1 -1
  53. package/dist/commands/{chunk-M5HA2ZCG.js → chunk-YT5JR2CB.js} +2 -2
  54. package/dist/commands/{chunk-EWCUT7U2.js → chunk-Z2NUK47W.js} +1 -1
  55. package/dist/commands/{chunk-4MGTNY2L.js → chunk-ZI3SABMH.js} +1 -1
  56. package/dist/commands/{chunk-TTTZZN7F.js → chunk-ZJJLROJY.js} +3 -3
  57. package/dist/commands/disposition-cli.js +15 -15
  58. package/dist/commands/git-followup-workflow.js +18 -7
  59. package/dist/commands/inputs.json +1637 -1632
  60. package/dist/commands/issue-already-done-cli.js +8 -8
  61. package/dist/commands/issue-measured-cli.js +9 -9
  62. package/dist/commands/issue-plan-cli.js +16 -16
  63. package/dist/commands/issue-premise-unmet-cli.js +8 -8
  64. package/dist/commands/lane-breakdown-cli.js +17 -17
  65. package/dist/commands/lane-cli.js +20 -20
  66. package/dist/commands/lane-measure-cli.js +23 -23
  67. package/dist/commands/lane-plan-cli.js +15 -15
  68. package/dist/commands/lane-restart-cli.js +20 -20
  69. package/dist/commands/lane-why-cli.js +4 -4
  70. package/dist/commands/lint-parallel-main.js +2 -2
  71. package/dist/commands/lint-related.js +6 -6
  72. package/dist/commands/lint-rule.js +2 -2
  73. package/dist/commands/plan-scaffold-cli.js +20 -20
  74. package/dist/commands/pre-commit-type-check.js +7 -7
  75. package/dist/commands/pre-push-unit.js +9 -9
  76. package/dist/commands/prose-stale-cli.js +5 -5
  77. package/dist/commands/review-brief-main.js +23 -23
  78. package/dist/commands/review-pair-cli.js +19 -19
  79. package/dist/commands/review-record-main.js +19 -19
  80. package/dist/commands/review-round2-cli.js +4 -4
  81. package/dist/commands/review-submit-cli.js +23 -23
  82. package/dist/commands/run-board-main.js +2 -1
  83. package/dist/commands/run-chain-cli.js +19 -19
  84. package/dist/commands/run-cut-cli.js +19 -19
  85. package/dist/commands/run-entry-cli.js +27 -27
  86. package/dist/commands/run-hold-main.js +7 -7
  87. package/dist/commands/run-next-cli.js +20 -20
  88. package/dist/commands/run-park-cli.js +8 -8
  89. package/dist/commands/run-pause-cli.js +8 -8
  90. package/dist/commands/run-prep-main.js +20 -20
  91. package/dist/commands/run-prime-cli.js +10 -10
  92. package/dist/commands/run-review-cli.js +26 -26
  93. package/dist/commands/run-ship-cli.js +29 -29
  94. package/dist/commands/run-ship-evidence-cli.js +4 -4
  95. package/dist/commands/run-ship-wait-main.js +5 -5
  96. package/dist/commands/run-split-cli.js +8 -8
  97. package/dist/commands/run-step-cli.js +27 -27
  98. package/dist/commands/run-wake-main.js +19 -19
  99. package/dist/commands/selfcheck-cli.js +8 -8
  100. package/dist/commands/stop-guard.js +7 -7
  101. package/dist/commands/test-e2e-guard.js +6 -6
  102. package/dist/commands/test-pinned-main.js +8 -8
  103. package/dist/commands/test-reach-cli.js +4 -4
  104. package/dist/commands/{test-related-Z6YY2GFH.js → test-related-XBDH2IOH.js} +11 -11
  105. package/dist/commands/test-related-main.js +13 -13
  106. package/dist/commands/verification-gate.js +17 -17
  107. package/dist/hooks/inputs.json +571 -570
  108. package/dist/hooks/stop-guard.js +68 -59
  109. package/dist/inputs.json +78 -78
  110. package/package.json +1 -1
  111. package/scripts/followup/git-followup-finish.ts +16 -1
  112. package/scripts/gate/verification-inputs.ts +2 -1
  113. package/scripts/run/board/run-board-layout.ts +9 -4
  114. package/scripts/run/board/run-board-read.ts +29 -69
  115. package/scripts/run/board/run-board-render-lanes.ts +26 -9
  116. package/scripts/run/board/run-board-render-lead.ts +9 -0
  117. package/scripts/run/board/run-board-root-layout.ts +69 -0
  118. package/scripts/run/board/run-board-single.ts +69 -4
  119. package/scripts/run/board/run-board-span-read.ts +85 -0
  120. package/scripts/run/board/run-board-tick.ts +12 -4
  121. package/scripts/run/hold/run-hold-ended.ts +50 -0
  122. package/scripts/test/test-pinned-cache-logic.ts +13 -7
  123. package/scripts/test/test-pinned-cache.ts +33 -11
  124. package/scripts/test/test-runner-config.ts +19 -0
@@ -2051,10 +2051,10 @@ function next_tail(descriptor, snapshot2, previous) {
2051
2051
  const length = readSync(descriptor, bytes, 0, bytes.length, from);
2052
2052
  return grow(base, snapshot2, from, bytes.subarray(0, length));
2053
2053
  }
2054
- function read_tail(path12, previous) {
2054
+ function read_tail(path13, previous) {
2055
2055
  try {
2056
- if (!stamp_file.is_own_regular_file(path12)) return void 0;
2057
- const descriptor = openSync(path12, READ_FLAGS);
2056
+ if (!stamp_file.is_own_regular_file(path13)) return void 0;
2057
+ const descriptor = openSync(path13, READ_FLAGS);
2058
2058
  try {
2059
2059
  return next_tail(descriptor, snapshot_of(fstatSync(descriptor)), previous);
2060
2060
  } finally {
@@ -2065,20 +2065,20 @@ function read_tail(path12, previous) {
2065
2065
  }
2066
2066
  }
2067
2067
  var tails = /* @__PURE__ */ new Map();
2068
- function read2(path12) {
2069
- const tail = read_tail(path12, tails.get(path12));
2068
+ function read2(path13) {
2069
+ const tail = read_tail(path13, tails.get(path13));
2070
2070
  if (tail === void 0) {
2071
- tails.delete(path12);
2071
+ tails.delete(path13);
2072
2072
  return EMPTY;
2073
2073
  }
2074
- tails.set(path12, tail);
2074
+ tails.set(path13, tail);
2075
2075
  return tail.entries;
2076
2076
  }
2077
2077
  var lane_ledger_tail = { read: read2 };
2078
2078
 
2079
2079
  // scripts/lane/lane-ledger.ts
2080
- function read_entries(path12) {
2081
- return lane_ledger_tail.read(path12);
2080
+ function read_entries(path13) {
2081
+ return lane_ledger_tail.read(path13);
2082
2082
  }
2083
2083
  var {
2084
2084
  CI_WAIT_STAGE,
@@ -2337,9 +2337,9 @@ async function take(context = {}) {
2337
2337
  return entry;
2338
2338
  }
2339
2339
  async function newest_load(ledger_path) {
2340
- const path12 = ledger_path ?? await lane_ledger.target();
2341
- if (path12 === void 0) return void 0;
2342
- return lane_ledger.read_entries(path12).findLast((entry) => entry.kind === lane_ledger.KIND.LOAD);
2340
+ const path13 = ledger_path ?? await lane_ledger.target();
2341
+ if (path13 === void 0) return void 0;
2342
+ return lane_ledger.read_entries(path13).findLast((entry) => entry.kind === lane_ledger.KIND.LOAD);
2343
2343
  }
2344
2344
  function counter_growth(previous, current2) {
2345
2345
  if (previous.booted_ms !== current2.booted_ms) return 0;
@@ -3059,7 +3059,7 @@ function units_of(files, added) {
3059
3059
  return sources2.flatMap((file) => {
3060
3060
  const partner = partners.get(file);
3061
3061
  const unit = partner === void 0 ? [file] : [file, partner];
3062
- const generated = files.filter((path12) => unit.includes(artifacts.get(path12) ?? ""));
3062
+ const generated = files.filter((path13) => unit.includes(artifacts.get(path13) ?? ""));
3063
3063
  return partner !== void 0 && sources2.indexOf(partner) < sources2.indexOf(file) ? [] : [[...unit, ...generated]];
3064
3064
  });
3065
3065
  }
@@ -4016,12 +4016,12 @@ var comment_schema = external_exports.object({
4016
4016
  html_url: external_exports.string()
4017
4017
  });
4018
4018
  async function read_ledger() {
4019
- const path12 = await lane_ledger.target();
4020
- return path12 === void 0 ? [] : lane_ledger.read_entries(path12);
4019
+ const path13 = await lane_ledger.target();
4020
+ return path13 === void 0 ? [] : lane_ledger.read_entries(path13);
4021
4021
  }
4022
4022
  async function read4(source) {
4023
- const path12 = `${git_gh_api_path.issues_api_path(source.repo)}/comments/${source.comment}`;
4024
- const raw = await git_gh_exec.exec_gh_api({ path: path12 });
4023
+ const path13 = `${git_gh_api_path.issues_api_path(source.repo)}/comments/${source.comment}`;
4024
+ const raw = await git_gh_exec.exec_gh_api({ path: path13 });
4025
4025
  const comment = parse_json.parse_json_object_or_undefined(raw, comment_schema);
4026
4026
  if (comment?.html_url !== source.url) return void 0;
4027
4027
  const author = { ...gh_author_association.author_of(comment), repo: source.repo };
@@ -4091,10 +4091,10 @@ var DEFAULT_PORTS = {
4091
4091
  closing: read_closing_source,
4092
4092
  ledger_path: lane_ledger.target
4093
4093
  };
4094
- function merges_of(path12) {
4094
+ function merges_of(path13) {
4095
4095
  return function merges() {
4096
- if (path12 === void 0) return [];
4097
- return lane_ledger.read_entries(path12).filter((entry) => entry.kind === lane_ledger.KIND.MERGE);
4096
+ if (path13 === void 0) return [];
4097
+ return lane_ledger.read_entries(path13).filter((entry) => entry.kind === lane_ledger.KIND.MERGE);
4098
4098
  };
4099
4099
  }
4100
4100
  async function remember2(condition, ports) {
@@ -5122,8 +5122,8 @@ var epic_fetch = {
5122
5122
  };
5123
5123
 
5124
5124
  // scripts/epic/epic-report.ts
5125
- function to_path_field(path12) {
5126
- return path12 === void 0 ? {} : { path: path12 };
5125
+ function to_path_field(path13) {
5126
+ return path13 === void 0 ? {} : { path: path13 };
5127
5127
  }
5128
5128
  function bundle_by_repo(children, paths = /* @__PURE__ */ new Map()) {
5129
5129
  const grouped2 = /* @__PURE__ */ new Map();
@@ -5315,16 +5315,16 @@ function parse_events(raw) {
5315
5315
  if (events === void 0) throw new Error(UNPARSED_TIMELINE_MESSAGE);
5316
5316
  return events;
5317
5317
  }
5318
- async function read_timeline(path12) {
5319
- return parse_events(await git_gh_etag_read.read_listing(path12, TIMELINE_PAGE));
5318
+ async function read_timeline(path13) {
5319
+ return parse_events(await git_gh_etag_read.read_listing(path13, TIMELINE_PAGE));
5320
5320
  }
5321
5321
  function is_in_progress_labeling(event) {
5322
5322
  return event.event === LABELED_EVENT && event.label?.name.toLowerCase() === IN_PROGRESS_LABEL;
5323
5323
  }
5324
5324
  async function read_labeled_at(issue, repo) {
5325
5325
  try {
5326
- const path12 = `${git_gh_api_path.issue_api_path(String(issue), repo)}/timeline?per_page=${String(TIMELINE_PAGE)}`;
5327
- const events = timeline_schema.parse(await read_timeline(path12));
5326
+ const path13 = `${git_gh_api_path.issue_api_path(String(issue), repo)}/timeline?per_page=${String(TIMELINE_PAGE)}`;
5327
+ const events = timeline_schema.parse(await read_timeline(path13));
5328
5328
  const at = events.findLast((event) => is_in_progress_labeling(event))?.created_at;
5329
5329
  return typeof at === "string" ? { kind: "at", at } : { kind: "absent" };
5330
5330
  } catch {
@@ -6113,8 +6113,8 @@ var issue_not_before_label = { change_of, sweep, sync, with_label: with_label2 }
6113
6113
  // scripts/lane/lane-implement-rate-read.ts
6114
6114
  var PERIOD_DAYS = 3;
6115
6115
  async function read_ledger2(context) {
6116
- const path12 = context.ledger_path ?? await lane_ledger.target();
6117
- return path12 === void 0 ? [] : lane_ledger.read_entries(path12);
6116
+ const path13 = context.ledger_path ?? await lane_ledger.target();
6117
+ return path13 === void 0 ? [] : lane_ledger.read_entries(path13);
6118
6118
  }
6119
6119
  async function implement_rate(context = {}, now_ms = Date.now()) {
6120
6120
  const window = lane_stats.window_of(PERIOD_DAYS, now_ms);
@@ -6926,7 +6926,7 @@ var GATE_PATHS = [
6926
6926
  "cspell.config"
6927
6927
  ];
6928
6928
  function names_gate_path(body) {
6929
- return GATE_PATHS.some((path12) => body.includes(path12));
6929
+ return GATE_PATHS.some((path13) => body.includes(path13));
6930
6930
  }
6931
6931
  function lane_reason(child) {
6932
6932
  if (!has_label_name(child.labels, BUG_LABEL)) return `it carries no \`${BUG_LABEL}\` label`;
@@ -8046,8 +8046,8 @@ function shorten(text2) {
8046
8046
  function to_hit(output_line) {
8047
8047
  const groups = GREP_LINE.exec(output_line)?.groups;
8048
8048
  if (groups === void 0) return void 0;
8049
- const { path: path12, line, text: text2 } = groups;
8050
- return { path: path12, line, excerpt: shorten(text2) };
8049
+ const { path: path13, line, text: text2 } = groups;
8050
+ return { path: path13, line, excerpt: shorten(text2) };
8051
8051
  }
8052
8052
  function parse3(stdout) {
8053
8053
  const hits = stdout.split("\n").map((line) => to_hit(line));
@@ -8133,8 +8133,8 @@ async function grep(target3) {
8133
8133
  async function find_files(target3) {
8134
8134
  try {
8135
8135
  const stdout = await git_spawn.read(["ls-files", "--", `${FILE_PATHSPEC}${target3}`]);
8136
- const paths = stdout.split("\n").filter((path12) => path12 !== "");
8137
- return paths.slice(0, MAX_FILES_PER_TARGET).map((path12) => ({ path: path12, ...FILE_HIT }));
8136
+ const paths = stdout.split("\n").filter((path13) => path13 !== "");
8137
+ return paths.slice(0, MAX_FILES_PER_TARGET).map((path13) => ({ path: path13, ...FILE_HIT }));
8138
8138
  } catch {
8139
8139
  return [];
8140
8140
  }
@@ -9396,8 +9396,8 @@ async function real_emit_stall(text2) {
9396
9396
  return await run_event_stream_emit.emit_once_since(STALL, text2, CHILD_LAUNCH);
9397
9397
  }
9398
9398
  async function read_real_ledger() {
9399
- const path12 = await lane_ledger.target();
9400
- return path12 === void 0 ? [] : lane_ledger.read_entries(path12);
9399
+ const path13 = await lane_ledger.target();
9400
+ return path13 === void 0 ? [] : lane_ledger.read_entries(path13);
9401
9401
  }
9402
9402
  async function real_mark_offerable(is_offerable) {
9403
9403
  await lane_ledger_write.record_offerable(is_offerable);
@@ -10456,8 +10456,8 @@ var ACCEPTANCE_MAP_HEADING = "PR \u672C\u6587\u306E\u53D7\u3051\u5165\u308C\u676
10456
10456
  var REMOVED_TESTS_HEADING = "PR \u672C\u6587\u306E\u6D88\u3048\u305F\u30C6\u30B9\u30C8\u306E\u51E6\u7F6E";
10457
10457
  var CHILD_SUMMARY_PATH = ".claude/skills/workflow-commands/backlogrun-child.md";
10458
10458
  var CHILD_SUMMARY_HEADING = "What the summary carries, and how long it may be";
10459
- function section_pointer(path12, heading) {
10460
- return `${path12} \u2192 "${heading}" (read it: pnpm josh doc:section ${path12} '${heading}')`;
10459
+ function section_pointer(path13, heading) {
10460
+ return `${path13} \u2192 "${heading}" (read it: pnpm josh doc:section ${path13} '${heading}')`;
10461
10461
  }
10462
10462
  function pointer(heading) {
10463
10463
  return section_pointer(REPORT_FORMAT_PATH, heading);
@@ -10904,7 +10904,7 @@ var review_finding_text = {
10904
10904
 
10905
10905
  // scripts/gate/verification-inputs.ts
10906
10906
  import { readFileSync as readFileSync3 } from "node:fs";
10907
- import path7 from "node:path";
10907
+ import path8 from "node:path";
10908
10908
 
10909
10909
  // eslint/config-fingerprint.js
10910
10910
  import { createHash as createHash2 } from "node:crypto";
@@ -11019,19 +11019,28 @@ var config_fingerprint = {
11019
11019
  list_reachable_modules
11020
11020
  };
11021
11021
 
11022
+ // scripts/test/test-runner-config.ts
11023
+ import path7 from "node:path";
11024
+ var PREFIXES = ["vitest.config.", "vitest.workspace.", "vite.config."];
11025
+ function is_config(relative) {
11026
+ if (path7.dirname(relative) !== ".") return false;
11027
+ return PREFIXES.some((prefix) => relative.startsWith(prefix));
11028
+ }
11029
+ var test_runner_config = { is_config, PREFIXES };
11030
+
11022
11031
  // scripts/gate/verification-inputs.ts
11023
11032
  var GIT_IGNORE = ".gitignore";
11024
11033
  var PRETTIER_IGNORE = ".prettierignore";
11025
11034
  var PRETTIER_IGNORE_FILES = [GIT_IGNORE, PRETTIER_IGNORE];
11026
11035
  var MANIFEST = "package.json";
11027
11036
  var TOOLCHAIN_FILES = /* @__PURE__ */ new Set([
11028
- ...toolchain_inputs.PACKAGE_FILES.map((relative) => path7.basename(relative)),
11037
+ ...toolchain_inputs.PACKAGE_FILES.map((relative) => path8.basename(relative)),
11029
11038
  ".editorconfig",
11030
11039
  ...PRETTIER_IGNORE_FILES
11031
11040
  ]);
11032
11041
  var PRETTIER_CONFIG_PREFIX = ".prettierrc";
11033
11042
  var COMPILER_CONFIG_PREFIXES = ["tsconfig", "svelte.config."];
11034
- var TEST_CONFIG_PREFIXES = [...COMPILER_CONFIG_PREFIXES, "vitest.config.", "vite.config."];
11043
+ var TEST_CONFIG_PREFIXES = [...COMPILER_CONFIG_PREFIXES, ...test_runner_config.PREFIXES];
11035
11044
  var LINT_CONFIG_PREFIXES = ["eslint.config.", "prettier.config.", ...COMPILER_CONFIG_PREFIXES];
11036
11045
  var LINT_CONFIG_DIRECTORIES = /* @__PURE__ */ new Set(["prettier", "tsconfig"]);
11037
11046
  var SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([
@@ -11052,7 +11061,7 @@ var MARKDOWN_EXTENSION = ".md";
11052
11061
  var COMMON_ENV = ["NODE_ENV"];
11053
11062
  var ABSENT2 = "absent";
11054
11063
  function is_source(relative) {
11055
- return SOURCE_EXTENSIONS.has(path7.extname(relative));
11064
+ return SOURCE_EXTENSIONS.has(path8.extname(relative));
11056
11065
  }
11057
11066
  async function is_lint_input(relative, is_ignored) {
11058
11067
  if (is_source(relative)) return true;
@@ -11063,14 +11072,14 @@ async function is_source_input(relative) {
11063
11072
  return is_source(relative);
11064
11073
  }
11065
11074
  async function is_metrics_input(relative) {
11066
- return is_source(relative) || path7.extname(relative) === MARKDOWN_EXTENSION;
11075
+ return is_source(relative) || path8.extname(relative) === MARKDOWN_EXTENSION;
11067
11076
  }
11068
11077
  function configures_toolchain(relative) {
11069
- const name = path7.basename(relative);
11078
+ const name = path8.basename(relative);
11070
11079
  return TOOLCHAIN_FILES.has(name) || name.startsWith(PRETTIER_CONFIG_PREFIX);
11071
11080
  }
11072
11081
  function names_any(relative, prefixes) {
11073
- const name = path7.basename(relative);
11082
+ const name = path8.basename(relative);
11074
11083
  return configures_toolchain(relative) || prefixes.some((prefix) => name.startsWith(prefix));
11075
11084
  }
11076
11085
  function configures_compiler(relative) {
@@ -11082,7 +11091,7 @@ function configures_tests(relative) {
11082
11091
  function read_lint_config_modules(root) {
11083
11092
  const entries = config_fingerprint.list_config_entries(root);
11084
11093
  const modules = [...config_fingerprint.list_reachable_modules(entries)];
11085
- return new Set(modules.map((file) => path7.relative(root, file).split(path7.sep).join("/")));
11094
+ return new Set(modules.map((file) => path8.relative(root, file).split(path8.sep).join("/")));
11086
11095
  }
11087
11096
  var lint_config_modules_by_root = /* @__PURE__ */ new Map();
11088
11097
  function lint_config_modules(root) {
@@ -11151,7 +11160,7 @@ function configures(label2, relatives, root = PROJECT_ROOT) {
11151
11160
  function tool_version(root, tool) {
11152
11161
  try {
11153
11162
  const manifest = JSON.parse(
11154
- readFileSync3(path7.join(root, "node_modules", tool, MANIFEST), "utf8")
11163
+ readFileSync3(path8.join(root, "node_modules", tool, MANIFEST), "utf8")
11155
11164
  );
11156
11165
  return typeof manifest === "object" && manifest !== null && "version" in manifest ? String(manifest.version) : ABSENT2;
11157
11166
  } catch {
@@ -11459,7 +11468,7 @@ var review_readers_scan = {
11459
11468
 
11460
11469
  // scripts/review/review-round-one-blobs.ts
11461
11470
  import { existsSync as existsSync2 } from "node:fs";
11462
- import path8 from "node:path";
11471
+ import path9 from "node:path";
11463
11472
  var ABSENT3 = review_tree.ABSENT_DIGEST;
11464
11473
  var SUCCESS_EXIT_CODE6 = 0;
11465
11474
  var NUL = "\0";
@@ -11473,7 +11482,7 @@ function repository_root() {
11473
11482
  return git_spawn_sync.read(["rev-parse", "--show-toplevel"]);
11474
11483
  }
11475
11484
  function hash_paths(root, paths, flags) {
11476
- const present = paths.filter((relative) => existsSync2(path8.join(root, relative)));
11485
+ const present = paths.filter((relative) => existsSync2(path9.join(root, relative)));
11477
11486
  const output2 = present.length === 0 ? "" : git_spawn_sync.read(["hash-object", ...flags, "--", ...present], { cwd: root });
11478
11487
  if (output2 === void 0) return void 0;
11479
11488
  const hashes = output2.split(NEWLINE);
@@ -11638,7 +11647,7 @@ var review_fix_hunks = { block: block2, resumed_block, RESUMED_HEADING };
11638
11647
  // scripts/review/review-code-tree.ts
11639
11648
  import { readFileSync as readFileSync4 } from "node:fs";
11640
11649
  import { createRequire as createRequire3 } from "node:module";
11641
- import path9 from "node:path";
11650
+ import path10 from "node:path";
11642
11651
 
11643
11652
  // scripts/review/comment-ranges.ts
11644
11653
  var COMMENT_OPENINGS = ["//", "/*"];
@@ -11783,7 +11792,7 @@ function is_source2(relative) {
11783
11792
  }
11784
11793
  function load_typescript(root) {
11785
11794
  try {
11786
- return createRequire3(path9.join(root, PACKAGE_JSON))(TYPESCRIPT_MODULE);
11795
+ return createRequire3(path10.join(root, PACKAGE_JSON))(TYPESCRIPT_MODULE);
11787
11796
  } catch {
11788
11797
  return void 0;
11789
11798
  }
@@ -11797,7 +11806,7 @@ function inert_digest(api) {
11797
11806
  }
11798
11807
  function code_digest(digest, root, relative) {
11799
11808
  try {
11800
- return digest(readFileSync4(path9.join(root, relative), "utf8"), relative);
11809
+ return digest(readFileSync4(path10.join(root, relative), "utf8"), relative);
11801
11810
  } catch {
11802
11811
  return void 0;
11803
11812
  }
@@ -11929,8 +11938,8 @@ var INERT_PATHS = [
11929
11938
  ];
11930
11939
  var INERT_PREFIXES = [];
11931
11940
  var INERT_SUFFIXES = [".code-workspace"];
11932
- function is_inert(path12) {
11933
- const normalized2 = path12.trim();
11941
+ function is_inert(path13) {
11942
+ const normalized2 = path13.trim();
11934
11943
  return INERT_PATHS.includes(normalized2) || INERT_PREFIXES.some((prefix) => normalized2.startsWith(prefix)) || INERT_SUFFIXES.some((suffix) => normalized2.endsWith(suffix));
11935
11944
  }
11936
11945
  function is_reduced_path(relative) {
@@ -11940,13 +11949,13 @@ function is_tiny(changed_lines2) {
11940
11949
  return changed_lines2 !== void 0 && changed_lines2 >= 0 && changed_lines2 <= TINY_CHANGE_LINES;
11941
11950
  }
11942
11951
  function level_for(paths, changed_lines2) {
11943
- const changed = paths.map((path12) => path12.trim()).filter((path12) => path12 !== "");
11952
+ const changed = paths.map((path13) => path13.trim()).filter((path13) => path13 !== "");
11944
11953
  if (changed.length === 0) return DEFAULT_LEVEL;
11945
11954
  if (changed.every((relative) => is_reduced_path(relative))) return REDUCED_LEVEL;
11946
11955
  return is_tiny(changed_lines2) ? REDUCED_LEVEL : DEFAULT_LEVEL;
11947
11956
  }
11948
11957
  function deciding_paths(paths) {
11949
- return paths.map((path12) => path12.trim()).filter((path12) => path12 !== "" && !is_reduced_path(path12));
11958
+ return paths.map((path13) => path13.trim()).filter((path13) => path13 !== "" && !is_reduced_path(path13));
11950
11959
  }
11951
11960
  function format_reason(paths, level) {
11952
11961
  if (level === REDUCED_LEVEL) {
@@ -12199,7 +12208,7 @@ var review_round = {
12199
12208
 
12200
12209
  // scripts/review/review-untouched-readers.ts
12201
12210
  import { readFileSync as readFileSync5 } from "node:fs";
12202
- import path10 from "node:path";
12211
+ import path11 from "node:path";
12203
12212
  var SOURCE_FILE = /\.(?:ts|js)$/u;
12204
12213
  var SEARCH_PATHS = ["*.ts", "*.js", "*.svelte", ":(exclude)*.snap"];
12205
12214
  var WORD_FLAG = "-w";
@@ -12217,7 +12226,7 @@ async function file_edits(request, relative) {
12217
12226
  const diff = await git_spawn.read(["-C", root, "diff", "-U0", "--no-color", base, "--", relative]);
12218
12227
  if (diff.length === 0) return { relative, edits: [] };
12219
12228
  try {
12220
- const source = readFileSync5(path10.join(root, relative), "utf8");
12229
+ const source = readFileSync5(path11.join(root, relative), "utf8");
12221
12230
  return { relative, edits: review_readers_scan.edited(source, diff) };
12222
12231
  } catch {
12223
12232
  return { relative, edits: [] };
@@ -13203,7 +13212,7 @@ var run_cut_report = {
13203
13212
  };
13204
13213
 
13205
13214
  // scripts/run/carry/run-carry-ended.ts
13206
- import path11 from "node:path";
13215
+ import path12 from "node:path";
13207
13216
  var ENDED_PREFIX = durable_state.PREFIX.ENDED;
13208
13217
  var TRANSCRIPT_SUFFIX = ".jsonl";
13209
13218
  var ended_run_schema = external_exports.object({
@@ -13218,7 +13227,7 @@ function ended_path(git_directory) {
13218
13227
  return durable_state.path(ENDED_PREFIX, git_directory);
13219
13228
  }
13220
13229
  function session_of(transcript) {
13221
- return transcript === void 0 ? void 0 : path11.basename(transcript, TRANSCRIPT_SUFFIX);
13230
+ return transcript === void 0 ? void 0 : path12.basename(transcript, TRANSCRIPT_SUFFIX);
13222
13231
  }
13223
13232
  function stop_of(transcript, stopped) {
13224
13233
  return stopped === void 0 ? {} : { stopped, session: session_of(transcript) };
package/dist/inputs.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "digest": "48e93136a21552f245f7f4c5ac6a88ddd2b0357ff4a840ccfd645243f344aadd",
2
+ "digest": "8d86405e2474435eedcb3c5756bbe508a8319b749fef5d075646dfe15cd375c8",
3
3
  "inputs": [
4
4
  "scripts/build/build-hooks.ts",
5
5
  "scripts/build/build-bin.ts",
@@ -38,25 +38,15 @@
38
38
  "scripts/josh/command-usage.ts",
39
39
  "scripts/josh/josh-gh-usage.ts",
40
40
  "scripts/josh/josh-logic.ts",
41
- "scripts/version/kit-descriptor.ts",
42
41
  "scripts/josh/josh-command-map.ts",
42
+ "scripts/josh/josh-aliases.ts",
43
+ "scripts/version/kit-descriptor.ts",
43
44
  "scripts/git/git-spawn-sync.ts",
44
45
  "scripts/lib/json-value.ts",
45
46
  "scripts/lib/package-manifest.ts",
46
47
  "scripts/lib/read-file.ts",
47
48
  "scripts/lib/timeouts.ts",
48
- "scripts/josh/josh-aliases.ts",
49
- "scripts/issue/issue-number-shape.ts",
50
49
  "scripts/josh/run-github-prerequisite.ts",
51
- "scripts/gh/gh-core-rate-limit.ts",
52
- "scripts/gh/gh-request-tally.ts",
53
- "scripts/gh/gh-usage-event.ts",
54
- "scripts/gh/git-gh-exec.ts",
55
- "scripts/josh/josh-commands-workflow.ts",
56
- "scripts/build/local-bin.ts",
57
- "scripts/gate/core-budget.ts",
58
- "scripts/hooks/hook-lap.ts",
59
- "scripts/lib/schemas.ts",
60
50
  "scripts/lib/spawn-exit.ts",
61
51
  "scripts/josh/command-suggest.ts",
62
52
  "scripts/josh/josh-composite-arguments.ts",
@@ -64,27 +54,25 @@
64
54
  "scripts/josh/josh-in-process.ts",
65
55
  "scripts/josh/kit-only.ts",
66
56
  "scripts/josh/package-directory.ts",
67
- "scripts/josh/josh-commands-lint.ts",
68
- "scripts/josh/josh-commands-ai.ts",
69
- "scripts/josh/josh-commands-clone.ts",
70
- "scripts/josh/josh-commands-development.ts",
71
- "scripts/josh/josh-commands-hooks.ts",
72
- "scripts/josh/josh-commands-project.ts",
73
- "scripts/josh/josh-commands-maintenance.ts",
74
- "scripts/josh/josh-commands-versioning.ts",
75
- "scripts/git/git-location-environment.ts",
76
- "scripts/git/constants.ts",
77
- "scripts/lib/ancestor-directories.ts",
78
- "scripts/gh/gh-call-kind.ts",
79
- "scripts/gh/gh-usage-log.ts",
57
+ "scripts/gate/core-budget.ts",
58
+ "scripts/build/local-bin.ts",
59
+ "scripts/lib/schemas.ts",
60
+ "scripts/issue/issue-number-shape.ts",
61
+ "scripts/hooks/hook-lap.ts",
62
+ "scripts/gh/gh-core-rate-limit.ts",
63
+ "scripts/gh/gh-request-tally.ts",
64
+ "scripts/gh/gh-usage-event.ts",
65
+ "scripts/gh/git-gh-exec.ts",
80
66
  "scripts/discovery/repo-origin.ts",
81
67
  "scripts/josh/josh-command-types.ts",
82
- "scripts/lib/pnpm-reach.ts",
83
- "scripts/lib/error-message.ts",
84
- "scripts/run/carry/run-carry.ts",
85
- "scripts/run/startup/run-startup.ts",
68
+ "scripts/lib/ancestor-directories.ts",
86
69
  "scripts/gate/machine-capacity.ts",
70
+ "scripts/lib/pnpm-reach.ts",
71
+ "scripts/run/ship/run-ship-lap.ts",
72
+ "scripts/gh/gh-call-kind.ts",
73
+ "scripts/gh/gh-usage-log.ts",
87
74
  "scripts/gh/git-gh-spawn-width.ts",
75
+ "ports/index.js",
88
76
  "scripts/josh/platform-temporary.ts",
89
77
  "scripts/josh/process-identity.ts",
90
78
  "scripts/josh/stamp-file.ts",
@@ -94,83 +82,95 @@
94
82
  "scripts/gate/core-budget-poll.ts",
95
83
  "scripts/gate/core-budget-timing.ts",
96
84
  "scripts/gate/core-reservation.ts",
97
- "scripts/josh/josh-commands-test-check.ts",
98
85
  "scripts/gate/core-wait.ts",
99
- "scripts/lib/bounded-pool.ts",
100
- "scripts/josh/agent-session-environment.ts",
101
86
  "scripts/gate/core-wait-record.ts",
87
+ "scripts/gate/core-weights.ts",
88
+ "scripts/gate/held-mark.ts",
89
+ "scripts/run/startup/run-startup.ts",
90
+ "scripts/lib/error-message.ts",
91
+ "scripts/run/carry/run-carry.ts",
92
+ "scripts/git/git-execa-error.ts",
93
+ "scripts/josh/agent-session-environment.ts",
94
+ "scripts/lib/bounded-pool.ts",
102
95
  "scripts/lib/token-shape.ts",
103
96
  "scripts/gh/git-gh-check.ts",
104
- "scripts/gate/core-weights.ts",
105
97
  "scripts/gh/git-gh-failure.ts",
106
- "scripts/gate/held-mark.ts",
107
98
  "scripts/gh/git-gh-retry.ts",
108
- "scripts/git/git-execa-error.ts",
109
- "scripts/run/ship/run-ship-lap.ts",
110
- "ports/index.js",
111
- "scripts/gate/gate-plan.ts",
112
- "scripts/josh/josh-commands-agent-hooks.ts",
113
- "scripts/josh/josh-commands-ship.ts",
114
- "scripts/josh/josh-commands-backlog.ts",
115
- "scripts/josh/josh-commands-document.ts",
116
- "scripts/josh/josh-commands-epic.ts",
117
- "scripts/josh/josh-commands-issue.ts",
118
- "scripts/josh/josh-commands-review.ts",
119
- "scripts/josh/josh-commands-run.ts",
120
- "scripts/rules/gh-api.ts",
121
- "scripts/run/carry/run-carry-session.ts",
122
- "scripts/run/startup/run-startup-store.ts",
99
+ "scripts/josh/durable-state.ts",
123
100
  "scripts/lib/atomic-write.ts",
124
- "scripts/test/unit-run-marker.ts",
125
101
  "scripts/gate/busy-average.ts",
126
102
  "scripts/gate/core-priority.ts",
103
+ "scripts/lane/lane-paths.ts",
127
104
  "scripts/lane/lane-ledger-write.ts",
128
- "scripts/git/parse-json-array.ts",
129
- "scripts/gate/gate-labels.ts",
130
- "scripts/josh/josh-commands-issue-write.ts",
131
- "scripts/josh/josh-commands-progress.ts",
132
- "scripts/git/repository-lock.ts",
105
+ "scripts/run/startup/run-startup-store.ts",
106
+ "scripts/run/carry/run-carry-session.ts",
107
+ "scripts/init/init-paths.ts",
108
+ "scripts/josh/process-owner.ts",
109
+ "scripts/lane/lane-ledger-kind.ts",
110
+ "scripts/lib/inherited-scope.ts",
111
+ "scripts/run/startup/run-startup-schema.ts",
133
112
  "scripts/agent/agent-provider.ts",
134
113
  "scripts/git/git-command.ts",
135
- "scripts/josh/durable-state.ts",
136
114
  "scripts/run/run-invocation.ts",
137
115
  "scripts/run/carry/run-carry-added.ts",
138
116
  "scripts/run/carry/run-carry-change.ts",
139
117
  "scripts/run/carry/run-carry-conversation.ts",
140
- "scripts/lane/lane-ledger-kind.ts",
141
- "scripts/lib/inherited-scope.ts",
142
- "scripts/run/startup/run-startup-schema.ts",
143
- "scripts/init/init-paths.ts",
118
+ "scripts/test/unit-run-marker.ts",
144
119
  "scripts/test/unit-lane-count.ts",
145
- "scripts/josh/process-owner.ts",
146
- "scripts/josh/josh-verdict.ts",
147
- "scripts/gate/gate-checks.ts",
148
- "scripts/josh/josh-commands-pause.ts",
149
- "scripts/josh/josh-commands-prime.ts",
150
- "scripts/lane/lane-paths.ts",
120
+ "scripts/git/repository-lock.ts",
121
+ "scripts/rules/gh-api.ts",
122
+ "scripts/git/parse-json-array.ts",
123
+ "scripts/josh/durable-state-root.ts",
151
124
  "scripts/rules/git-argv.ts",
152
125
  "scripts/run/run-headless-keys.ts",
153
- "scripts/issue/issue-body-keys.ts",
154
- "scripts/lane/lane-child-marker.ts",
155
- "scripts/git/git-common-directory.ts",
156
126
  "scripts/git/git-spawn.ts",
157
- "scripts/josh/durable-state-root.ts",
158
127
  "scripts/lib/cli-flags.ts",
159
128
  "scripts/run/carry/run-carry-streak.ts",
160
129
  "scripts/cost-runtime/own-session.ts",
161
- "scripts/lane/lane-state-record.ts",
162
- "scripts/lib/status-icons.ts",
130
+ "scripts/git/git-common-directory.ts",
131
+ "scripts/josh/durable-state-migrate.ts",
132
+ "scripts/lane/lane-child-marker.ts",
133
+ "scripts/git/constants.ts",
163
134
  "scripts/git/git-diff-reads.ts",
164
135
  "scripts/git/git-pre-push-hook.ts",
165
136
  "scripts/git/git-push-transport.ts",
166
- "scripts/josh/durable-state-migrate.ts",
167
137
  "scripts/cost-runtime/cost-transcript.ts",
138
+ "scripts/cost-runtime/cost-usage.ts",
139
+ "scripts/git/git-ssh-keepalive.ts",
168
140
  "scripts/discovery/git-directory.ts",
169
- "scripts/josh/session-language.ts",
141
+ "scripts/lane/lane-state-record.ts",
142
+ "scripts/git/git-location-environment.ts",
170
143
  "scripts/lane/lane-child-mark-keys.ts",
171
- "scripts/git/git-ssh-keepalive.ts",
172
- "scripts/cost-runtime/cost-usage.ts",
173
- "scripts/time-runtime/time-instant.ts"
144
+ "scripts/time-runtime/time-instant.ts",
145
+ "scripts/josh/josh-commands-workflow.ts",
146
+ "scripts/josh/josh-commands-ai.ts",
147
+ "scripts/josh/josh-commands-clone.ts",
148
+ "scripts/josh/josh-commands-development.ts",
149
+ "scripts/josh/josh-commands-hooks.ts",
150
+ "scripts/josh/josh-commands-lint.ts",
151
+ "scripts/josh/josh-commands-maintenance.ts",
152
+ "scripts/josh/josh-commands-project.ts",
153
+ "scripts/josh/josh-commands-versioning.ts",
154
+ "scripts/josh/josh-commands-ship.ts",
155
+ "scripts/josh/josh-commands-test-check.ts",
156
+ "scripts/josh/josh-commands-backlog.ts",
157
+ "scripts/josh/josh-commands-document.ts",
158
+ "scripts/josh/josh-commands-epic.ts",
159
+ "scripts/josh/josh-commands-issue.ts",
160
+ "scripts/josh/josh-commands-review.ts",
161
+ "scripts/josh/josh-commands-run.ts",
162
+ "scripts/gate/gate-plan.ts",
163
+ "scripts/josh/josh-commands-agent-hooks.ts",
164
+ "scripts/josh/josh-commands-issue-write.ts",
165
+ "scripts/josh/josh-commands-progress.ts",
166
+ "scripts/gate/gate-labels.ts",
167
+ "scripts/josh/josh-commands-pause.ts",
168
+ "scripts/josh/josh-commands-prime.ts",
169
+ "scripts/josh/josh-verdict.ts",
170
+ "scripts/gate/gate-checks.ts",
171
+ "scripts/lib/status-icons.ts",
172
+ "scripts/issue/issue-body-keys.ts",
173
+ "scripts/josh/session-language.ts"
174
174
  ],
175
175
  "outputs": [
176
176
  "josh.js"
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.3092.0",
2
+ "version": "1.3099.0",
3
3
  "name": "@joshuafolkken/kit",
4
4
  "description": "Hand-off kit for Claude Code and Codex: backlogrun takes your GitHub Issues to tested, reviewed, merged PRs — in parallel and unattended — with the rules, hooks and checks that keep the agent on track",
5
5
  "keywords": [
@@ -2,10 +2,12 @@ import { git_command } from '#scripts/git/git-command'
2
2
  import { git_next_issues } from '#scripts/issue/git-next-issues'
3
3
  import { issue_watch } from '#scripts/issue/issue-watch'
4
4
  import { josh_command } from '#scripts/josh/josh-run'
5
+ import { lane_paths } from '#scripts/lane/lane-paths'
5
6
  import { lane_registry } from '#scripts/lane/lane-registry'
6
7
  import { review_attest } from '#scripts/review/review-attest'
7
8
  import { review_stamps } from '#scripts/review/review-stamps'
8
9
  import { run_hold } from '#scripts/run/hold/run-hold'
10
+ import { run_hold_ended } from '#scripts/run/hold/run-hold-ended'
9
11
  import { run_progress_clock } from '#scripts/run/progress/run-progress-clock'
10
12
  import { parse_completed_issue_number } from './followup-issue-number'
11
13
  import { git_followup_cleanup, type CleanupStep } from './git-followup-cleanup'
@@ -133,13 +135,26 @@ async function clear_review_records(should_merge: boolean): Promise<void> {
133
135
  // It swallows its own failure for the same reason the gate's in-flight marker does: the record must
134
136
  // never decide whether a merged run reports success. A record that survives anyway expires on its own
135
137
  // eight hours later, which is what covers an abnormally ended run.
138
+ //
139
+ // A run outside a lane is recorded before its hold goes, so `run:board` lists it in `✅ done`
140
+ // (joshuafolkken/kit#7525); a lane's hold is its `backlogrun` child's, which the board reads elsewhere.
141
+ function keep_ended(directory: string, target: string): void {
142
+ if (lane_paths.lane_issue_of(process.cwd()) !== undefined) return
143
+
144
+ run_hold_ended.record_ended(run_hold_ended.ended_path(directory), run_hold.read_hold(target))
145
+ }
146
+
136
147
  async function release_worktree_hold(should_merge: boolean): Promise<void> {
137
148
  if (!should_merge) return
138
149
 
139
150
  try {
140
151
  const directory = await run_hold.worktree_directory()
141
152
 
142
- if (directory !== undefined) run_hold.release_hold(run_hold.hold_path(directory))
153
+ if (directory === undefined) return
154
+ const target = run_hold.hold_path(directory)
155
+
156
+ keep_ended(directory, target)
157
+ run_hold.release_hold(target)
143
158
  } catch {
144
159
  /* the record expires on its own, and `pnpm josh run:release --force` clears it early */
145
160
  }