@joshuafolkken/kit 1.1373.0 → 1.1383.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 (92) hide show
  1. package/.claude/skills/dependency-update/SKILL.md +6 -3
  2. package/.claude/skills/workflow-commands/backlogrun-progress.md +2 -3
  3. package/.claude/skills/workflow-commands/backlogrun-steps.md +2 -4
  4. package/.claude/skills/workflow-commands/retrospective.md +1 -2
  5. package/dist/hooks/batch-guard.js +6 -6
  6. package/dist/hooks/{chunk-UTHMB4O2.js → chunk-2X2ART5G.js} +4 -33
  7. package/dist/hooks/{chunk-NZN2UFI6.js → chunk-4MGHBTOM.js} +162 -233
  8. package/dist/hooks/{chunk-YLBBSSTF.js → chunk-6AC4C2IO.js} +91 -67
  9. package/dist/hooks/{chunk-AKGCP4LX.js → chunk-6MAW7BCM.js} +12 -12
  10. package/dist/hooks/{chunk-JCRDBQXB.js → chunk-7VSZ2N4B.js} +3 -3
  11. package/dist/hooks/{chunk-GG72ANKI.js → chunk-KC6LUZZ2.js} +1 -1
  12. package/dist/hooks/{chunk-BZMPVFDY.js → chunk-KCF2YE7O.js} +5 -5
  13. package/dist/hooks/{chunk-7WKYHEGU.js → chunk-LC56R53A.js} +3 -3
  14. package/dist/hooks/{chunk-V4TKZHER.js → chunk-LOJTBU5V.js} +3 -3
  15. package/dist/hooks/{chunk-JGW24KKM.js → chunk-RYP3TSUJ.js} +3 -3
  16. package/dist/hooks/{chunk-SLSFIWTX.js → chunk-TT742SIO.js} +8 -5
  17. package/dist/hooks/{chunk-Z5TMJIPW.js → chunk-Y5R47QHU.js} +1 -1
  18. package/dist/hooks/{chunk-7UBFU3CL.js → chunk-YKUITFT7.js} +2 -2
  19. package/dist/hooks/codex-hook-adapter.js +13 -13
  20. package/dist/hooks/duplicate-read-guard.js +7 -7
  21. package/dist/hooks/format-edited.js +3 -3
  22. package/dist/hooks/inputs.json +190 -191
  23. package/dist/hooks/investigation-guard.js +7 -7
  24. package/dist/hooks/pretool-guard.js +12 -12
  25. package/dist/hooks/session-lang.js +3 -3
  26. package/dist/hooks/stop-guard.js +19 -15
  27. package/dist/josh.js +40 -5
  28. package/package.json +4 -4
  29. package/prompts/collaboration-workflow/upstream-interrupt.md +1 -1
  30. package/scripts/adopt/adopt-logic.ts +4 -1
  31. package/scripts/adopt/adopt.ts +7 -4
  32. package/scripts/backlog/backlog-budget-cli.ts +2 -20
  33. package/scripts/backlog/backlog-budget.ts +72 -109
  34. package/scripts/backlog/backlog-drive-cli.ts +10 -3
  35. package/scripts/backlog/backlog-drive.ts +5 -2
  36. package/scripts/backlog/backlog-offer-cli.ts +1 -15
  37. package/scripts/cost-runtime/context-cut-payback.ts +9 -4
  38. package/scripts/cost-runtime/cost-pricing.ts +94 -33
  39. package/scripts/document/document-byte-budget.ts +1 -1
  40. package/scripts/document/read-set-pricing.ts +7 -5
  41. package/scripts/epic/epic-candidate-confirm.ts +1 -1
  42. package/scripts/epic/epic-cross-repo.ts +4 -4
  43. package/scripts/epic/epic-next.ts +1 -1
  44. package/scripts/git/git-spawn-sync.ts +9 -1
  45. package/scripts/hooks/stop-guard.ts +20 -9
  46. package/scripts/init/init-ai-copy.ts +10 -3
  47. package/scripts/init/init-copy-content.ts +8 -1
  48. package/scripts/init/security-policy.ts +79 -0
  49. package/scripts/josh/josh-commands-ai.ts +1 -1
  50. package/scripts/josh/josh-commands-maintenance.ts +3 -0
  51. package/scripts/josh/josh-commands-project.ts +1 -1
  52. package/scripts/josh/josh-commands-versioning.ts +2 -1
  53. package/scripts/lane/lane-cli.ts +1 -3
  54. package/scripts/propagate/propagate-run.ts +17 -1
  55. package/scripts/propagate/propagate-steps.ts +9 -1
  56. package/scripts/run/board/run-board-header.ts +107 -84
  57. package/scripts/run/board/run-board-labels.ts +18 -17
  58. package/scripts/run/board/run-board-machine.ts +21 -8
  59. package/scripts/run/board/run-board-render.ts +1 -5
  60. package/scripts/run/board/run-board-span.ts +0 -1
  61. package/scripts/run/board/run-board-status.ts +0 -17
  62. package/scripts/run/board/run-board-tick.ts +1 -0
  63. package/scripts/run/carry/run-carry-cli.ts +8 -62
  64. package/scripts/run/carry/run-carry-ended.ts +1 -1
  65. package/scripts/run/carry/run-carry.ts +22 -68
  66. package/scripts/run/cut/run-cut.ts +4 -4
  67. package/scripts/run/event/run-event-render.ts +0 -1
  68. package/scripts/run/event/run-event-scope.ts +4 -8
  69. package/scripts/run/event/run-event-stream-emit.ts +0 -25
  70. package/scripts/run/event/run-event-stream.ts +23 -31
  71. package/scripts/run/merge/run-merge-collect.ts +1 -1
  72. package/scripts/run/merge/run-merge-steps.ts +1 -1
  73. package/scripts/run/progress/run-progress-read.ts +1 -1
  74. package/scripts/run/run-headless.ts +2 -2
  75. package/scripts/run/run-status-cli.ts +1 -5
  76. package/scripts/run/run-step.ts +2 -9
  77. package/scripts/run/run-stop-notify.ts +1 -1
  78. package/scripts/run/run-stranded-detect.ts +3 -3
  79. package/scripts/run/run-stranded.ts +25 -17
  80. package/scripts/run/wake/run-wake-cli.ts +7 -9
  81. package/scripts/run/wake/run-wake-describe.ts +3 -5
  82. package/scripts/run/wake/run-wake-driver.ts +3 -3
  83. package/scripts/run/wake/run-wake-loop.ts +4 -21
  84. package/scripts/run/wake/run-wake-restart.ts +1 -1
  85. package/scripts/run/wake/run-wake.ts +6 -7
  86. package/scripts/sync/sync-ai-files.ts +2 -0
  87. package/scripts/version/latest-update.ts +20 -6
  88. package/scripts/version/peer-floor.ts +99 -0
  89. package/scripts/version/playwright-browsers.ts +109 -0
  90. package/scripts/version/publishable-range-check.ts +41 -4
  91. package/templates/SECURITY.md +23 -0
  92. package/scripts/backlog/backlog-idle.ts +0 -88
@@ -8,7 +8,7 @@ import {
8
8
  repo_origin,
9
9
  repository_lock,
10
10
  run_ship_stage
11
- } from "./chunk-UTHMB4O2.js";
11
+ } from "./chunk-2X2ART5G.js";
12
12
  import {
13
13
  error_text
14
14
  } from "./chunk-CDY4NFQG.js";
@@ -30,10 +30,10 @@ import {
30
30
  time_density_hook,
31
31
  time_shell,
32
32
  time_transcript_line
33
- } from "./chunk-SLSFIWTX.js";
33
+ } from "./chunk-TT742SIO.js";
34
34
  import {
35
35
  lane_child_marker
36
- } from "./chunk-Z5TMJIPW.js";
36
+ } from "./chunk-Y5R47QHU.js";
37
37
  import {
38
38
  agent_session_environment,
39
39
  backlog_budget,
@@ -42,9 +42,8 @@ import {
42
42
  has_timed_out,
43
43
  json_value,
44
44
  process_identity,
45
- run_carry,
46
- stamp_record
47
- } from "./chunk-NZN2UFI6.js";
45
+ run_carry
46
+ } from "./chunk-4MGHBTOM.js";
48
47
  import {
49
48
  COMMAND_TIMEOUT_MS,
50
49
  stamp_file
@@ -339,6 +338,23 @@ var session_cite = {
339
338
  text
340
339
  };
341
340
 
341
+ // scripts/josh/stamp-record.ts
342
+ var NONE_READ = { kind: "none" };
343
+ var UNREADABLE_READ = { kind: "unreadable" };
344
+ function is_older_than(iso, max_age_ms, now) {
345
+ const at = Date.parse(iso);
346
+ if (Number.isNaN(at)) return true;
347
+ return now.getTime() - at > max_age_ms;
348
+ }
349
+ function classify(raw, spec, now) {
350
+ if (raw === void 0) return NONE_READ;
351
+ const record = spec.parse(raw);
352
+ if (record === void 0) return UNREADABLE_READ;
353
+ const is_expired3 = is_older_than(spec.timestamp_of(record), spec.max_age_ms, now);
354
+ return { kind: is_expired3 ? "expired" : "carried", record };
355
+ }
356
+ var stamp_record = { classify, is_older_than };
357
+
342
358
  // scripts/run/hold/run-hold.ts
343
359
  import { z } from "zod";
344
360
  var HOLD_PREFIX = "josh-run-hold-";
@@ -350,7 +366,7 @@ var RELEASE_COMMAND = "pnpm josh run:release";
350
366
  var FORCE_RELEASE_COMMAND = `${RELEASE_COMMAND} --force`;
351
367
  var NOT_IDLE = 'that is not "nothing is running here"';
352
368
  var FREE_READ = { kind: "free" };
353
- var UNREADABLE_READ = { kind: "unreadable" };
369
+ var UNREADABLE_READ2 = { kind: "unreadable" };
354
370
  function hold_path(git_directory) {
355
371
  return stamp_file.stamp_path(HOLD_PREFIX, git_directory);
356
372
  }
@@ -386,14 +402,14 @@ function is_owner_gone(hold) {
386
402
  function is_stale(hold, now) {
387
403
  return is_expired(hold, now) || is_owner_gone(hold);
388
404
  }
389
- function classify(raw, now) {
405
+ function classify2(raw, now) {
390
406
  if (raw === void 0) return FREE_READ;
391
407
  const hold = parse_hold(raw);
392
- if (hold === void 0) return UNREADABLE_READ;
408
+ if (hold === void 0) return UNREADABLE_READ2;
393
409
  return { kind: is_stale(hold, now) ? "stale" : "held", hold };
394
410
  }
395
411
  function read_hold(target, now = /* @__PURE__ */ new Date()) {
396
- return classify(stamp_file.read_stamp_text(target), now);
412
+ return classify2(stamp_file.read_stamp_text(target), now);
397
413
  }
398
414
  function session_owner(environment = process.env) {
399
415
  const pid = Number(environment[agent_session_environment.AGENT_PID_KEY]);
@@ -475,7 +491,7 @@ var run_hold = {
475
491
  HOLD_MAX_AGE_MS,
476
492
  RELEASE_COMMAND,
477
493
  UNNUMBERED_ISSUE,
478
- classify,
494
+ classify: classify2,
479
495
  create_halfrun_stop_hold,
480
496
  create_stop_hold,
481
497
  HALFRUN_STOP_FIELDS,
@@ -503,29 +519,56 @@ var run_hold = {
503
519
  // scripts/cost-runtime/cost-pricing.ts
504
520
  var CACHE_WRITE_5M_MULTIPLIER = 1.25;
505
521
  var CACHE_WRITE_1H_MULTIPLIER = 2;
506
- var CACHE_READ_MULTIPLIER = 0.1;
522
+ var DEFAULT_CACHE_READ_MULTIPLIER = 0.1;
523
+ var HALVED_CACHE_READ_MULTIPLIER = 0.05;
524
+ var QUARTERED_CACHE_READ_MULTIPLIER = 0.025;
507
525
  var TOKENS_PER_MILLION = 1e6;
526
+ var LONG_PROMPT_SUFFIX = ":long-prompt";
527
+ var LONG_PROMPT_THRESHOLD = 1e5;
508
528
  var MODEL_PRICES = {
529
+ "claude-fable-5-1": {
530
+ input: 10,
531
+ output: 50,
532
+ cache_read_multiplier: QUARTERED_CACHE_READ_MULTIPLIER
533
+ },
534
+ "claude-mythos-5-1": {
535
+ input: 10,
536
+ output: 50,
537
+ cache_read_multiplier: QUARTERED_CACHE_READ_MULTIPLIER
538
+ },
509
539
  "claude-fable-5": { input: 10, output: 50 },
510
540
  "claude-mythos-5": { input: 10, output: 50 },
541
+ "claude-opus-5-5": { input: 4, output: 20, cache_read_multiplier: HALVED_CACHE_READ_MULTIPLIER },
511
542
  "claude-opus-5": { input: 5, output: 25 },
512
543
  "claude-opus-4-8": { input: 5, output: 25 },
513
544
  "claude-opus-4-7": { input: 5, output: 25 },
514
545
  "claude-opus-4-6": { input: 5, output: 25 },
546
+ "claude-sonnet-5-5": {
547
+ input: 2,
548
+ output: 10,
549
+ cache_read_multiplier: HALVED_CACHE_READ_MULTIPLIER
550
+ },
515
551
  "claude-sonnet-5": { input: 2, output: 10 },
516
552
  "claude-sonnet-4-6": { input: 3, output: 15 },
553
+ "claude-haiku-5-5": { input: 0.1, output: 0.5 },
554
+ [`claude-haiku-5-5${LONG_PROMPT_SUFFIX}`]: { input: 0.5, output: 2.5 },
517
555
  "claude-haiku-4-5": { input: 1, output: 5 }
518
556
  };
519
557
  var CONTEXT_MARKER = "[";
520
- function resolve_price(model) {
558
+ var DATE_SUFFIX = /-\d{8}$/u;
559
+ function known_id(model) {
521
560
  const base = model.split(CONTEXT_MARKER)[0] ?? model;
522
- const direct = MODEL_PRICES[base];
523
- if (direct !== void 0) return direct;
524
- const [matched] = Object.keys(MODEL_PRICES).filter((id) => base.startsWith(id)).toSorted((left, right) => right.length - left.length);
525
- return matched === void 0 ? void 0 : MODEL_PRICES[matched];
561
+ return [base, base.replace(DATE_SUFFIX, "")].find((id) => Object.hasOwn(MODEL_PRICES, id));
562
+ }
563
+ function resolve_price(model) {
564
+ const id = known_id(model);
565
+ return id === void 0 ? void 0 : MODEL_PRICES[id];
566
+ }
567
+ function cache_read_multiplier(price) {
568
+ return price.cache_read_multiplier ?? DEFAULT_CACHE_READ_MULTIPLIER;
526
569
  }
527
570
  function estimate_cost(totals, price) {
528
- const weighted_input = totals.input_tokens + totals.cache_write_5m_tokens * CACHE_WRITE_5M_MULTIPLIER + totals.cache_write_1h_tokens * CACHE_WRITE_1H_MULTIPLIER + totals.cache_read_tokens * CACHE_READ_MULTIPLIER;
571
+ const weighted_input = totals.input_tokens + totals.cache_write_5m_tokens * CACHE_WRITE_5M_MULTIPLIER + totals.cache_write_1h_tokens * CACHE_WRITE_1H_MULTIPLIER + totals.cache_read_tokens * cache_read_multiplier(price);
529
572
  return (weighted_input * price.input + totals.output_tokens * price.output) / TOKENS_PER_MILLION;
530
573
  }
531
574
  function priced(tokens, rate) {
@@ -542,7 +585,7 @@ function estimate_composition(totals, price) {
542
585
  totals.cache_write_1h_tokens * CACHE_WRITE_1H_MULTIPLIER,
543
586
  price.input
544
587
  ),
545
- cache_read_usd: priced(totals.cache_read_tokens * CACHE_READ_MULTIPLIER, price.input),
588
+ cache_read_usd: priced(totals.cache_read_tokens * cache_read_multiplier(price), price.input),
546
589
  output_usd: priced(totals.output_tokens, price.output)
547
590
  };
548
591
  }
@@ -551,11 +594,17 @@ function to_model_cost(model, totals) {
551
594
  if (price === void 0) return { model, totals };
552
595
  return { model, totals, cost_usd: estimate_cost(totals, price) };
553
596
  }
597
+ function billed_model(usage) {
598
+ const long_id = `${known_id(usage.model) ?? usage.model}${LONG_PROMPT_SUFFIX}`;
599
+ const is_long = cost_usage.billed_input(usage.totals) > LONG_PROMPT_THRESHOLD;
600
+ return is_long && Object.hasOwn(MODEL_PRICES, long_id) ? long_id : usage.model;
601
+ }
554
602
  function cost_by_model(records) {
555
603
  const grouped = /* @__PURE__ */ new Map();
556
604
  for (const record of records) {
557
- const running = grouped.get(record.model) ?? cost_usage.EMPTY_TOTALS;
558
- grouped.set(record.model, cost_usage.add_totals(running, record.totals));
605
+ const model = billed_model(record);
606
+ const running = grouped.get(model) ?? cost_usage.EMPTY_TOTALS;
607
+ grouped.set(model, cost_usage.add_totals(running, record.totals));
559
608
  }
560
609
  return [...grouped].map(([model, totals]) => to_model_cost(model, totals));
561
610
  }
@@ -571,7 +620,8 @@ function cost_of(records) {
571
620
  var cost_pricing = {
572
621
  CACHE_WRITE_5M_MULTIPLIER,
573
622
  CACHE_WRITE_1H_MULTIPLIER,
574
- CACHE_READ_MULTIPLIER,
623
+ DEFAULT_CACHE_READ_MULTIPLIER,
624
+ LONG_PROMPT_THRESHOLD,
575
625
  resolve_price,
576
626
  estimate_cost,
577
627
  estimate_composition,
@@ -584,7 +634,7 @@ var cost_pricing = {
584
634
  var POST_CUT_CONTEXT = 6e4;
585
635
  var EXPECTED_REMAINING_REQUESTS = 10;
586
636
  function write_over_read() {
587
- return cost_pricing.CACHE_WRITE_5M_MULTIPLIER / cost_pricing.CACHE_READ_MULTIPLIER;
637
+ return cost_pricing.CACHE_WRITE_5M_MULTIPLIER / cost_pricing.DEFAULT_CACHE_READ_MULTIPLIER;
588
638
  }
589
639
  function break_even_context(remaining = EXPECTED_REMAINING_REQUESTS) {
590
640
  if (remaining <= 0) return Infinity;
@@ -692,8 +742,8 @@ var run_cut_handoff = {
692
742
  var CUT_PREFIX = "josh-run-cut-";
693
743
  var { PRE_GATE_PHASE, IMPLEMENTATION_PHASE } = agent_role_profile;
694
744
  var IMPLEMENTATION_CONTEXT_THRESHOLD = CONTEXT_CUT_THRESHOLD;
695
- var CUT_MAX_AGE_MS = backlog_budget.WHOLE_RUN_BUDGET_MS;
696
- var CUT_MAX_AGE_HOURS = backlog_budget.WHOLE_RUN_BUDGET_HOURS;
745
+ var CUT_MAX_AGE_MS = backlog_budget.DEFAULT_IDLE_MS;
746
+ var CUT_MAX_AGE_HOURS = backlog_budget.IDLE_WAIT_HOURS;
697
747
  var END_COMMAND = "pnpm josh run:cut --end";
698
748
  var READ_COMMAND = "pnpm josh run:cut --json";
699
749
  var MAX_HANDOFF_BYTES = 8192;
@@ -728,13 +778,13 @@ var CUT_SPEC = {
728
778
  function is_expired2(cut, now) {
729
779
  return stamp_record.is_older_than(cut_at_of(cut), CUT_MAX_AGE_MS, now);
730
780
  }
731
- function classify2(raw, now) {
781
+ function classify3(raw, now) {
732
782
  const read = stamp_record.classify(raw, CUT_SPEC, now);
733
783
  if (!("record" in read)) return read;
734
784
  return { kind: read.kind, cut: read.record };
735
785
  }
736
786
  function read_cut(target, now = /* @__PURE__ */ new Date()) {
737
- return classify2(stamp_file.read_stamp_text(target), now);
787
+ return classify3(stamp_file.read_stamp_text(target), now);
738
788
  }
739
789
  function worktree_git_directory_sync() {
740
790
  return git_common_directory.own();
@@ -857,7 +907,7 @@ var run_cut = {
857
907
  begin_cut,
858
908
  busy_message,
859
909
  carried_cut_sync,
860
- classify: classify2,
910
+ classify: classify3,
861
911
  classify_resume,
862
912
  current_state,
863
913
  cut_path,
@@ -1082,11 +1132,6 @@ var EVENT_KIND = {
1082
1132
  // The position that hands control back: `run:step` prints the command that
1083
1133
  // shows the stopped report, so the agent fixes it and relaunches rather than rebuilding the context.
1084
1134
  SHIP_STOP: "ship-stop",
1085
- // The idle watch's window — when the run began waiting on an empty backlog and when that wait ends
1086
- // `backlog:offer` writes it whenever the window changes, so `run:board` reads
1087
- // the deadline rather than guessing it. It is a trace: `emit_once`'s drain dedup and `run:step`'s
1088
- // position both read past it, so a watching loop never re-marks the drain it is waiting after.
1089
- IDLE: "idle",
1090
1135
  // An Issue the run filed on its way, written by `issue:file`, so a run started from the command line
1091
1136
  // still surfaces what it found — `run:board`'s findings section reads it.
1092
1137
  FILED: "filed",
@@ -1110,18 +1155,13 @@ var EVENT_KINDS = Object.values(EVENT_KIND);
1110
1155
  var TRACE_KINDS = /* @__PURE__ */ new Set([
1111
1156
  EVENT_KIND.SHIP_STAGE,
1112
1157
  EVENT_KIND.HEARTBEAT,
1113
- EVENT_KIND.IDLE,
1114
1158
  EVENT_KIND.FILED,
1115
1159
  EVENT_KIND.NOTE,
1116
1160
  EVENT_KIND.LANE_PHASE,
1117
1161
  EVENT_KIND.ADD,
1118
1162
  EVENT_KIND.LANE_LIMIT
1119
1163
  ]);
1120
- var DISPOSABLE_KINDS = /* @__PURE__ */ new Set([
1121
- EVENT_KIND.SHIP_STAGE,
1122
- EVENT_KIND.HEARTBEAT,
1123
- EVENT_KIND.IDLE
1124
- ]);
1164
+ var DISPOSABLE_KINDS = /* @__PURE__ */ new Set([EVENT_KIND.SHIP_STAGE, EVENT_KIND.HEARTBEAT]);
1125
1165
  var event_schema = z4.object({
1126
1166
  pos: z4.number(),
1127
1167
  at: z4.string(),
@@ -1140,11 +1180,14 @@ function is_present(event) {
1140
1180
  function parse_line(line) {
1141
1181
  return event_schema.safeParse(json_value.parse_or_undefined(line)).data;
1142
1182
  }
1143
- function read_events(target) {
1183
+ function read_lines(target) {
1144
1184
  const raw = stamp_file.read_stamp_text(target);
1145
1185
  if (raw === void 0) return [];
1146
1186
  return raw.split(LINE_SEPARATOR).map((line) => line.trim()).filter((line) => line.length > 0).map((line) => parse_line(line)).filter(is_present);
1147
1187
  }
1188
+ function read_events(target) {
1189
+ return read_lines(target).filter((event) => is_event_kind(event.kind));
1190
+ }
1148
1191
  function last_position(events) {
1149
1192
  return events[events.length - POSITION_INCREMENT]?.pos ?? FIRST_POSITION;
1150
1193
  }
@@ -1162,15 +1205,12 @@ function is_stage_start(event) {
1162
1205
  if (event.kind !== EVENT_KIND.SHIP_STAGE) return false;
1163
1206
  return event.text.split(WORD_SEPARATOR)[STAGE_PHASE_INDEX] === run_ship_stage.PHASE.START;
1164
1207
  }
1165
- function is_drawn(event) {
1166
- return event.kind === EVENT_KIND.IDLE || is_stage_start(event);
1167
- }
1168
1208
  function droppable(events) {
1169
1209
  const kept = newest_stages(events);
1170
1210
  const disposable = events.filter((event) => DISPOSABLE_KINDS.has(event.kind) && !kept.has(event));
1171
1211
  return [
1172
- ...disposable.filter((event) => !is_drawn(event)),
1173
- ...disposable.filter((event) => is_drawn(event))
1212
+ ...disposable.filter((event) => !is_stage_start(event)),
1213
+ ...disposable.filter((event) => is_stage_start(event))
1174
1214
  ];
1175
1215
  }
1176
1216
  function bounded(events) {
@@ -1183,9 +1223,8 @@ function serialize(events) {
1183
1223
  return `${events.map((event) => JSON.stringify(event)).join(LINE_SEPARATOR)}${LINE_SEPARATOR}`;
1184
1224
  }
1185
1225
  function append_held(target, event) {
1186
- const existing = read_events(target);
1187
- const position = last_position(existing) + POSITION_INCREMENT;
1188
- const events = bounded([...existing, { pos: position, ...event }]);
1226
+ const position = last_position(read_lines(target)) + POSITION_INCREMENT;
1227
+ const events = bounded([...read_events(target), { pos: position, ...event }]);
1189
1228
  stamp_file.replace_text_stamp(target, serialize(events));
1190
1229
  return position;
1191
1230
  }
@@ -1257,10 +1296,8 @@ function scoped_events(events, scope) {
1257
1296
  return events.filter((event) => is_within(event, floor));
1258
1297
  }
1259
1298
  function scope_of(read) {
1260
- if (read.kind === "carried" || read.kind === "expired") {
1261
- return { kind: SINCE_SCOPE, started_at: read.carry.started_at };
1262
- }
1263
- return UNKNOWN_EVENT_SCOPE;
1299
+ if (read.kind !== "carried") return UNKNOWN_EVENT_SCOPE;
1300
+ return { kind: SINCE_SCOPE, started_at: read.carry.started_at };
1264
1301
  }
1265
1302
  function last_scoped_event(events, scope) {
1266
1303
  return scoped_events(events, scope)?.findLast(
@@ -1361,18 +1398,6 @@ async function emit_once(kind, text2) {
1361
1398
  return false;
1362
1399
  }
1363
1400
  }
1364
- async function emit_changed(kind, text2) {
1365
- try {
1366
- const target = await stream_target();
1367
- if (target === void 0) return false;
1368
- const newest = run_event_stream.read_events(target).findLast((event) => event.kind === kind);
1369
- if (newest?.text === text2) return false;
1370
- return run_event_stream.append(target, kind, text2, now_iso()).appended;
1371
- } catch (error) {
1372
- error_text.trace_swallowed("run_event_stream_emit.emit_changed", error);
1373
- return false;
1374
- }
1375
- }
1376
1401
  function invocation_events(repository, target) {
1377
1402
  const events = run_event_stream.read_events(target);
1378
1403
  const scope = run_event_scope.scope_of(run_carry.read_carry(run_carry.carry_path(repository)));
@@ -1427,7 +1452,6 @@ var run_event_stream_emit = {
1427
1452
  all_events,
1428
1453
  current_events,
1429
1454
  emit,
1430
- emit_changed,
1431
1455
  emit_heartbeat,
1432
1456
  emit_once,
1433
1457
  emit_once_since,
@@ -1854,7 +1878,7 @@ var THIRD_PARTY = "third-party";
1854
1878
  var UNKNOWN = "unknown";
1855
1879
  var GH_REPO_ENV_KEY = "GH_REPO";
1856
1880
  var GH_REPO_PATH_SEGMENTS = 2;
1857
- function classify3(session_owner2, target) {
1881
+ function classify4(session_owner2, target) {
1858
1882
  if (session_owner2 === void 0 || target === void 0) return UNKNOWN;
1859
1883
  return session_owner2.toLowerCase() === target.toLowerCase() ? FIRST_PARTY : THIRD_PARTY;
1860
1884
  }
@@ -1878,7 +1902,7 @@ var repo_party = {
1878
1902
  FIRST_PARTY,
1879
1903
  THIRD_PARTY,
1880
1904
  UNKNOWN,
1881
- classify: classify3,
1905
+ classify: classify4,
1882
1906
  current_owner,
1883
1907
  placeholder_owners,
1884
1908
  target_owner
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  duplicate_read_outcome
3
- } from "./chunk-BZMPVFDY.js";
3
+ } from "./chunk-KCF2YE7O.js";
4
4
  import {
5
5
  ALREADY_DONE_LABEL,
6
6
  CONTEXT_CUT_THRESHOLD,
@@ -28,7 +28,7 @@ import {
28
28
  session_cite,
29
29
  shell_segments,
30
30
  tail_commands
31
- } from "./chunk-YLBBSSTF.js";
31
+ } from "./chunk-6AC4C2IO.js";
32
32
  import {
33
33
  ancestor_directories,
34
34
  find_local_bin_upwards
@@ -41,25 +41,25 @@ import {
41
41
  lane_registry,
42
42
  repo_origin,
43
43
  run_headless
44
- } from "./chunk-UTHMB4O2.js";
44
+ } from "./chunk-2X2ART5G.js";
45
45
  import {
46
46
  error_text
47
47
  } from "./chunk-CDY4NFQG.js";
48
48
  import {
49
49
  batch_outcome
50
- } from "./chunk-JGW24KKM.js";
50
+ } from "./chunk-RYP3TSUJ.js";
51
51
  import {
52
52
  investigation_refusal
53
- } from "./chunk-V4TKZHER.js";
53
+ } from "./chunk-LOJTBU5V.js";
54
54
  import {
55
55
  investigation_reads
56
- } from "./chunk-JCRDBQXB.js";
56
+ } from "./chunk-7VSZ2N4B.js";
57
57
  import {
58
58
  lane_guard_policy
59
- } from "./chunk-GG72ANKI.js";
59
+ } from "./chunk-KC6LUZZ2.js";
60
60
  import {
61
61
  hook_decision
62
- } from "./chunk-7WKYHEGU.js";
62
+ } from "./chunk-LC56R53A.js";
63
63
  import {
64
64
  cost_attribute,
65
65
  cost_blocks,
@@ -67,10 +67,10 @@ import {
67
67
  time_batch_guard,
68
68
  time_density_hook,
69
69
  time_shell
70
- } from "./chunk-SLSFIWTX.js";
70
+ } from "./chunk-TT742SIO.js";
71
71
  import {
72
72
  lane_child_marker
73
- } from "./chunk-Z5TMJIPW.js";
73
+ } from "./chunk-Y5R47QHU.js";
74
74
  import {
75
75
  PORCELAIN_FLAG,
76
76
  cli_flags,
@@ -84,7 +84,7 @@ import {
84
84
  lane_paths,
85
85
  own_session,
86
86
  run_carry
87
- } from "./chunk-NZN2UFI6.js";
87
+ } from "./chunk-4MGHBTOM.js";
88
88
  import {
89
89
  PLATFORM_TEMP_ROOT,
90
90
  PROBE_TIMEOUT_MS,
@@ -4188,7 +4188,7 @@ function is_hold_present(read2) {
4188
4188
  return read2.kind === "held" || read2.kind === "stale";
4189
4189
  }
4190
4190
  function is_carry_present(read2) {
4191
- return read2.kind === "carried" || read2.kind === "expired";
4191
+ return read2.kind === "carried";
4192
4192
  }
4193
4193
  function hold_present(worktree) {
4194
4194
  return worktree !== void 0 && is_hold_present(run_hold.read_hold(run_hold.hold_path(worktree)));
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  hook_decision
3
- } from "./chunk-7WKYHEGU.js";
3
+ } from "./chunk-LC56R53A.js";
4
4
  import {
5
5
  cost_blocks,
6
6
  time_batch_guard,
7
7
  time_bundle_call,
8
8
  time_shell,
9
9
  time_spans
10
- } from "./chunk-SLSFIWTX.js";
10
+ } from "./chunk-TT742SIO.js";
11
11
  import {
12
12
  cost_transcript
13
- } from "./chunk-NZN2UFI6.js";
13
+ } from "./chunk-4MGHBTOM.js";
14
14
 
15
15
  // scripts/delegation/investigation-reads.ts
16
16
  import path2 from "node:path";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  lane_child_marker
3
- } from "./chunk-Z5TMJIPW.js";
3
+ } from "./chunk-Y5R47QHU.js";
4
4
 
5
5
  // scripts/lane/lane-guard-policy.ts
6
6
  var DEFAULT_MODE = "refuse";
@@ -1,18 +1,18 @@
1
1
  import {
2
2
  investigation_reads
3
- } from "./chunk-JCRDBQXB.js";
3
+ } from "./chunk-7VSZ2N4B.js";
4
4
  import {
5
5
  lane_guard_policy
6
- } from "./chunk-GG72ANKI.js";
6
+ } from "./chunk-KC6LUZZ2.js";
7
7
  import {
8
8
  hook_decision
9
- } from "./chunk-7WKYHEGU.js";
9
+ } from "./chunk-LC56R53A.js";
10
10
  import {
11
11
  time_spans
12
- } from "./chunk-SLSFIWTX.js";
12
+ } from "./chunk-TT742SIO.js";
13
13
  import {
14
14
  json_value
15
- } from "./chunk-NZN2UFI6.js";
15
+ } from "./chunk-4MGHBTOM.js";
16
16
 
17
17
  // scripts/delegation/duplicate-read-guard.ts
18
18
  import { statSync } from "node:fs";
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  time_density_hook,
3
3
  time_hook_transcript
4
- } from "./chunk-SLSFIWTX.js";
4
+ } from "./chunk-TT742SIO.js";
5
5
  import {
6
6
  josh_environment_file
7
- } from "./chunk-Z5TMJIPW.js";
7
+ } from "./chunk-Y5R47QHU.js";
8
8
  import {
9
9
  json_value
10
- } from "./chunk-NZN2UFI6.js";
10
+ } from "./chunk-4MGHBTOM.js";
11
11
  import {
12
12
  stamp_file
13
13
  } from "./chunk-NEC4AT4Z.js";
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  investigation_reads
3
- } from "./chunk-JCRDBQXB.js";
3
+ } from "./chunk-7VSZ2N4B.js";
4
4
  import {
5
5
  lane_guard_policy
6
- } from "./chunk-GG72ANKI.js";
6
+ } from "./chunk-KC6LUZZ2.js";
7
7
  import {
8
8
  hook_decision
9
- } from "./chunk-7WKYHEGU.js";
9
+ } from "./chunk-LC56R53A.js";
10
10
 
11
11
  // scripts/delegation/investigation-guard.ts
12
12
  import { text } from "node:stream/consumers";
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  lane_guard_policy
3
- } from "./chunk-GG72ANKI.js";
3
+ } from "./chunk-KC6LUZZ2.js";
4
4
  import {
5
5
  hook_decision
6
- } from "./chunk-7WKYHEGU.js";
6
+ } from "./chunk-LC56R53A.js";
7
7
  import {
8
8
  time_batch_guard
9
- } from "./chunk-SLSFIWTX.js";
9
+ } from "./chunk-TT742SIO.js";
10
10
 
11
11
  // scripts/hooks/batch-guard.ts
12
12
  import { text } from "node:stream/consumers";
@@ -6,7 +6,7 @@ import {
6
6
  process_owner_schema,
7
7
  run_carry,
8
8
  time_instant
9
- } from "./chunk-NZN2UFI6.js";
9
+ } from "./chunk-4MGHBTOM.js";
10
10
  import {
11
11
  PLATFORM_TEMP_ROOT,
12
12
  PROBE_TIMEOUT_MS,
@@ -739,7 +739,7 @@ var AI_COMMANDS = {
739
739
  // `.env` rather than the ambient environment: the strand notification needs the Telegram
740
740
  // credentials, the same reason `run:wake` carries these flags.
741
741
  tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
742
- description: "Report whether the run is stranded \u2014 budget handed off, owner gone, and no supervisor watching",
742
+ description: "Report whether the run is stranded \u2014 owner gone, no successor holding the budget, and no supervisor watching",
743
743
  category: "AI tools",
744
744
  reference: ["", "automation", ["processes", "notifications"]]
745
745
  },
@@ -1882,7 +1882,10 @@ var MAINTENANCE_COMMANDS = {
1882
1882
  script: "scripts/version/latest-update.ts",
1883
1883
  description: "Update all dependencies to latest",
1884
1884
  category: "Maintenance",
1885
- reference: ["", "developer", ["files", "network"]]
1885
+ reference: ["", "developer", ["files", "network"]],
1886
+ // `JOSH_PLAYWRIGHT_BROWSERS` widens the browsers a Playwright bump installs, and a project
1887
+ // keeps that setting in its `.env`.
1888
+ tsx_arguments: OPTIONAL_ENV_FILE_FLAGS
1886
1889
  }
1887
1890
  };
1888
1891
 
@@ -1970,7 +1973,7 @@ var PROJECT_COMMANDS = {
1970
1973
  },
1971
1974
  adopt: {
1972
1975
  script: "scripts/adopt/adopt.ts",
1973
- description: "Upgrade every installed @joshuafolkken toolkit here and open the pull request",
1976
+ description: "Upgrade the @joshuafolkken toolkits and other dependencies here, open the PR",
1974
1977
  category: "Project",
1975
1978
  reference: ["[--dry-run]", "developer", ["files", "git", "network", "processes"]]
1976
1979
  }
@@ -1996,7 +1999,7 @@ var VERSIONING_COMMANDS = {
1996
1999
  // before chaining here, exactly as it already does for `latest:update`.
1997
2000
  ranges: {
1998
2001
  script: "scripts/version/publishable-range-check.ts",
1999
- description: "Check that every published dependency range still resolves for a consumer",
2002
+ description: "Check that every published dependency range still resolves for a consumer and no peer range falls below an installed toolkit",
2000
2003
  category: "Versioning",
2001
2004
  reference: ["", "developer", ["network"]]
2002
2005
  },
@@ -2,7 +2,7 @@ import {
2
2
  ENV_FILE_NAME,
3
3
  issue_number_shape,
4
4
  lane_paths
5
- } from "./chunk-NZN2UFI6.js";
5
+ } from "./chunk-4MGHBTOM.js";
6
6
 
7
7
  // scripts/josh/josh-environment-file.ts
8
8
  function load_environment_file() {
@@ -5,11 +5,11 @@ import {
5
5
  import {
6
6
  ESLINT_EDIT_CACHE_FLAGS,
7
7
  time_density_hook
8
- } from "./chunk-SLSFIWTX.js";
8
+ } from "./chunk-TT742SIO.js";
9
9
  import {
10
10
  file_reader,
11
11
  json_value
12
- } from "./chunk-NZN2UFI6.js";
12
+ } from "./chunk-4MGHBTOM.js";
13
13
  import {
14
14
  HOOK_PROCESS_TIMEOUT_MS
15
15
  } from "./chunk-NEC4AT4Z.js";
@@ -1,33 +1,33 @@
1
1
  #!/usr/bin/env tsx
2
2
  import {
3
3
  pretool_guard
4
- } from "./chunk-AKGCP4LX.js";
5
- import "./chunk-BZMPVFDY.js";
4
+ } from "./chunk-6MAW7BCM.js";
5
+ import "./chunk-KCF2YE7O.js";
6
6
  import {
7
7
  bounded_pool
8
- } from "./chunk-YLBBSSTF.js";
8
+ } from "./chunk-6AC4C2IO.js";
9
9
  import {
10
10
  build_envelope,
11
11
  compose_context,
12
12
  format_edited_payload
13
- } from "./chunk-7UBFU3CL.js";
13
+ } from "./chunk-YKUITFT7.js";
14
14
  import "./chunk-JBBMAPC4.js";
15
- import "./chunk-UTHMB4O2.js";
15
+ import "./chunk-2X2ART5G.js";
16
16
  import "./chunk-CDY4NFQG.js";
17
- import "./chunk-JGW24KKM.js";
18
- import "./chunk-V4TKZHER.js";
19
- import "./chunk-JCRDBQXB.js";
20
- import "./chunk-GG72ANKI.js";
17
+ import "./chunk-RYP3TSUJ.js";
18
+ import "./chunk-LOJTBU5V.js";
19
+ import "./chunk-7VSZ2N4B.js";
20
+ import "./chunk-KC6LUZZ2.js";
21
21
  import {
22
22
  hook_decision
23
- } from "./chunk-7WKYHEGU.js";
23
+ } from "./chunk-LC56R53A.js";
24
24
  import {
25
25
  time_density_hook
26
- } from "./chunk-SLSFIWTX.js";
27
- import "./chunk-Z5TMJIPW.js";
26
+ } from "./chunk-TT742SIO.js";
27
+ import "./chunk-Y5R47QHU.js";
28
28
  import {
29
29
  json_value
30
- } from "./chunk-NZN2UFI6.js";
30
+ } from "./chunk-4MGHBTOM.js";
31
31
  import "./chunk-NEC4AT4Z.js";
32
32
 
33
33
  // scripts/hooks/codex-hook-adapter.ts