@joshuafolkken/kit 1.1435.0 → 1.1455.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 (105) hide show
  1. package/.claude/skills/workflow-commands/backlogrun-handoff-report.md +1 -1
  2. package/.claude/skills/workflow-commands/backlogrun-park.md +2 -0
  3. package/.claude/skills/workflow-commands/backlogrun-steps.md +9 -7
  4. package/.claude/skills/workflow-commands/backlogrun.md +2 -2
  5. package/.claude/skills/workflow-commands/fullrun-steps.md +1 -1
  6. package/.claude/skills/workflow-commands/halfrun.md +3 -2
  7. package/.claude/skills/workflow-commands/kickoff.md +12 -13
  8. package/.claude/skills/workflow-commands/observation-filing.md +1 -1
  9. package/.claude/skills/workflow-commands/prerequisite.md +6 -0
  10. package/.claude/skills/workflow-commands/prrun.md +2 -1
  11. package/.claude/skills/workflow-commands/retrospective.md +5 -5
  12. package/.claude/skills/workflow-commands/split-assessment.md +2 -2
  13. package/CLAUDE.md +1 -1
  14. package/README.md +10 -19
  15. package/dist/CLAUDE.md +1 -1
  16. package/dist/hooks/batch-guard.js +6 -6
  17. package/dist/hooks/{chunk-3LE6VLSR.js → chunk-3C4XRYG6.js} +18 -5
  18. package/dist/hooks/{chunk-7KMN5QB5.js → chunk-5H4SSDSD.js} +3 -3
  19. package/dist/hooks/{chunk-YZXYOAZ3.js → chunk-7WQBPLUN.js} +11 -5
  20. package/dist/hooks/{chunk-2G5F2YCD.js → chunk-D5QBTOCZ.js} +3 -3
  21. package/dist/hooks/{chunk-MU4LJFIV.js → chunk-GPLGZ6IC.js} +3 -3
  22. package/dist/hooks/{chunk-MSYSUSY6.js → chunk-HFGWYGUV.js} +5 -5
  23. package/dist/hooks/{chunk-JXQBK323.js → chunk-HHI6FO3R.js} +132 -105
  24. package/dist/hooks/{chunk-XER6SSIB.js → chunk-LIAFCXL7.js} +17 -7
  25. package/dist/hooks/{chunk-4BHUPFKF.js → chunk-OLMO72ON.js} +1 -1
  26. package/dist/hooks/{chunk-EMB55BDF.js → chunk-TBJFTSUY.js} +2 -2
  27. package/dist/hooks/{chunk-5SJSSCJG.js → chunk-UT7YC3N2.js} +1 -1
  28. package/dist/hooks/{chunk-QL6QTPWN.js → chunk-WNLVGT7E.js} +3 -3
  29. package/dist/hooks/{chunk-YW452ZAX.js → chunk-Z4XI7CZS.js} +2 -2
  30. package/dist/hooks/codex-hook-adapter.js +13 -13
  31. package/dist/hooks/duplicate-read-guard.js +7 -7
  32. package/dist/hooks/format-edited.js +3 -3
  33. package/dist/hooks/inputs.json +229 -226
  34. package/dist/hooks/investigation-guard.js +7 -7
  35. package/dist/hooks/pretool-guard.js +12 -12
  36. package/dist/hooks/session-lang.js +3 -3
  37. package/dist/hooks/stop-guard.js +64 -11
  38. package/dist/josh.js +34 -11
  39. package/package.json +1 -1
  40. package/prompts/collaboration-workflow/issue-template.md +10 -8
  41. package/prompts/collaboration-workflow/shell-body.md +1 -1
  42. package/prompts/review.md +8 -4
  43. package/scripts/auto-ok/auto-ok-judge-cli.ts +125 -0
  44. package/scripts/auto-ok/auto-ok-judge-read.ts +95 -0
  45. package/scripts/auto-ok/auto-ok-judge-write.ts +109 -0
  46. package/scripts/auto-ok/auto-ok-judge.ts +67 -0
  47. package/scripts/backlog/backlog-drive-cli.ts +14 -0
  48. package/scripts/backlog/backlog-drive.ts +22 -3
  49. package/scripts/document/document-byte-budget.ts +1 -1
  50. package/scripts/fresh-machine/fresh-machine-patterns.ts +60 -15
  51. package/scripts/gate/project-checks.ts +5 -2
  52. package/scripts/gh/git-gh-issue-rest.ts +1 -0
  53. package/scripts/gh/git-gh-issue.ts +9 -0
  54. package/scripts/gh/git-pr-ai-review.ts +12 -1
  55. package/scripts/gh/git-pr-confirmation.ts +11 -7
  56. package/scripts/init/init-actions.ts +3 -3
  57. package/scripts/init/init-ai-copy.ts +1 -1
  58. package/scripts/init/init-basic.ts +1 -1
  59. package/scripts/init/init-bootstrap.ts +6 -2
  60. package/scripts/init/init-dry-run-report.ts +150 -0
  61. package/scripts/init/init-dry-run.ts +189 -0
  62. package/scripts/init/init-install.ts +8 -1
  63. package/scripts/init/init.ts +57 -19
  64. package/scripts/init/kit-setup-state.ts +11 -17
  65. package/scripts/init/own-formatter.ts +21 -0
  66. package/scripts/init/project-profile.ts +25 -6
  67. package/scripts/init/start-dry-run.ts +70 -0
  68. package/scripts/init/start-plan.ts +8 -3
  69. package/scripts/init/start-setup-pr.ts +13 -24
  70. package/scripts/init/start-steps.ts +16 -1
  71. package/scripts/init/start.ts +38 -18
  72. package/scripts/init/working-tree.ts +116 -0
  73. package/scripts/issue/issue-auto-ok.ts +68 -99
  74. package/scripts/issue/issue-file-cli.ts +17 -17
  75. package/scripts/issue/issue-file.ts +1 -6
  76. package/scripts/issue/issue-labels.ts +6 -2
  77. package/scripts/issue/issue-release-cli.ts +69 -23
  78. package/scripts/issue/issue-release.ts +3 -1
  79. package/scripts/josh/josh-commands-ai.ts +11 -0
  80. package/scripts/josh/josh-commands-issue.ts +3 -3
  81. package/scripts/josh/josh-commands-project.ts +2 -2
  82. package/scripts/josh/josh-commands-workflow.ts +1 -1
  83. package/scripts/josh/process-identity.ts +32 -6
  84. package/scripts/lane/lane-broker-server.ts +69 -0
  85. package/scripts/lane/lane-session-broker.ts +37 -14
  86. package/scripts/notify/confirmation-options.ts +59 -0
  87. package/scripts/notify/notify-opt-in.ts +33 -0
  88. package/scripts/notify/telegram-notify.ts +25 -8
  89. package/scripts/notify/telegram-test-logic.ts +33 -1
  90. package/scripts/notify/telegram-test.ts +4 -2
  91. package/scripts/observations/observation-ledger-migrate.ts +3 -15
  92. package/scripts/release/release-issue-close.ts +133 -0
  93. package/scripts/release/release-publish.ts +12 -1
  94. package/scripts/repo/repository-labels.ts +11 -1
  95. package/scripts/review/comment-ranges.ts +199 -0
  96. package/scripts/review/review-brief-cli.ts +22 -5
  97. package/scripts/review/review-code-tree.ts +119 -0
  98. package/scripts/review/review-round2-cli.ts +16 -5
  99. package/scripts/review/review-round2.ts +30 -10
  100. package/scripts/review/review-stamps.ts +22 -1
  101. package/scripts/rules/shell-body-trigger.ts +3 -2
  102. package/scripts/rules/stop-rules.ts +2 -1
  103. package/scripts/run/entry/run-entry-stop.ts +6 -3
  104. package/scripts/run/run-stop-notify.ts +2 -0
  105. package/scripts/uninstall/distributed-files.ts +1 -1
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  duplicate_read_outcome
3
- } from "./chunk-MSYSUSY6.js";
3
+ } from "./chunk-HFGWYGUV.js";
4
4
  import {
5
5
  ALREADY_DONE_LABEL,
6
6
  CONTEXT_CUT_THRESHOLD,
@@ -29,7 +29,7 @@ import {
29
29
  session_cite,
30
30
  shell_segments,
31
31
  tail_commands
32
- } from "./chunk-YZXYOAZ3.js";
32
+ } from "./chunk-7WQBPLUN.js";
33
33
  import {
34
34
  ancestor_directories,
35
35
  find_local_bin_upwards,
@@ -50,25 +50,25 @@ import {
50
50
  run_event_stream_emit,
51
51
  run_headless,
52
52
  session_language
53
- } from "./chunk-YW452ZAX.js";
53
+ } from "./chunk-Z4XI7CZS.js";
54
54
  import {
55
55
  error_text
56
56
  } from "./chunk-CDY4NFQG.js";
57
57
  import {
58
58
  batch_outcome
59
- } from "./chunk-7KMN5QB5.js";
59
+ } from "./chunk-5H4SSDSD.js";
60
60
  import {
61
61
  investigation_refusal
62
- } from "./chunk-2G5F2YCD.js";
62
+ } from "./chunk-D5QBTOCZ.js";
63
63
  import {
64
64
  investigation_reads
65
- } from "./chunk-QL6QTPWN.js";
65
+ } from "./chunk-WNLVGT7E.js";
66
66
  import {
67
67
  lane_guard_policy
68
- } from "./chunk-5SJSSCJG.js";
68
+ } from "./chunk-UT7YC3N2.js";
69
69
  import {
70
70
  hook_decision
71
- } from "./chunk-MU4LJFIV.js";
71
+ } from "./chunk-GPLGZ6IC.js";
72
72
  import {
73
73
  cost_attribute,
74
74
  cost_blocks,
@@ -76,10 +76,10 @@ import {
76
76
  time_batch_guard,
77
77
  time_density_hook,
78
78
  time_shell
79
- } from "./chunk-XER6SSIB.js";
79
+ } from "./chunk-LIAFCXL7.js";
80
80
  import {
81
81
  lane_child_marker
82
- } from "./chunk-4BHUPFKF.js";
82
+ } from "./chunk-OLMO72ON.js";
83
83
  import {
84
84
  GIT_LOCATION_VARIABLES,
85
85
  PORCELAIN_FLAG,
@@ -94,7 +94,7 @@ import {
94
94
  lane_paths,
95
95
  own_session,
96
96
  run_carry
97
- } from "./chunk-3LE6VLSR.js";
97
+ } from "./chunk-3C4XRYG6.js";
98
98
  import {
99
99
  PLATFORM_TEMP_ROOT,
100
100
  PROBE_TIMEOUT_MS,
@@ -114,9 +114,9 @@ var HEADER_BODY_SEPARATOR = /\r?\n\r?\n/u;
114
114
  var ETAG_HEADER = /^etag: *(?<etag>[^\r\n]+)/imu;
115
115
  var UNCHANGED = { kind: "unchanged" };
116
116
  var UNREADABLE = { kind: "unreadable" };
117
- function to_args(path15, etag) {
117
+ function to_args(path16, etag) {
118
118
  const header = etag === void 0 ? [] : [HEADER_FLAG, `${IF_NONE_MATCH}${etag}`];
119
- return ["api", INCLUDE_FLAG, ...header, path15];
119
+ return ["api", INCLUDE_FLAG, ...header, path16];
120
120
  }
121
121
  function to_changed(output) {
122
122
  const [headers = "", ...rest] = output.split(HEADER_BODY_SEPARATOR);
@@ -130,9 +130,9 @@ function failure_status(error) {
130
130
  const cause = error instanceof Error ? error.cause : void 0;
131
131
  return has_stdout_field(cause) ? git_gh_exec.parse_status_line(cause.stdout) : void 0;
132
132
  }
133
- async function read_conditional(path15, etag, timeout_ms) {
133
+ async function read_conditional(path16, etag, timeout_ms) {
134
134
  try {
135
- return to_read(await git_gh_exec.exec_gh_command(to_args(path15, etag), timeout_ms));
135
+ return to_read(await git_gh_exec.exec_gh_command(to_args(path16, etag), timeout_ms));
136
136
  } catch (error) {
137
137
  return failure_status(error) === NOT_MODIFIED_STATUS ? UNCHANGED : UNREADABLE;
138
138
  }
@@ -1369,8 +1369,8 @@ function selected_threshold(values) {
1369
1369
  function threshold_option(over) {
1370
1370
  return over === void 0 ? {} : { over };
1371
1371
  }
1372
- function path_option(path15) {
1373
- return path15 === void 0 ? {} : { path: path15 };
1372
+ function path_option(path16) {
1373
+ return path16 === void 0 ? {} : { path: path16 };
1374
1374
  }
1375
1375
  function to_options(values) {
1376
1376
  if (values.cut === true && values.over !== void 0) return void 0;
@@ -3190,7 +3190,7 @@ var rule_body_guard = {
3190
3190
 
3191
3191
  // scripts/rules/shell-body-trigger.ts
3192
3192
  var FIELD_FLAGS = "(?:-f|-F|--field|--raw-field)";
3193
- var MESSAGE_FLAGS = "(?:--body|--notify-message)";
3193
+ var MESSAGE_FLAGS = "(?:--body|--notify-message|--recommended|--alternative)";
3194
3194
  var FIELD_OPENING = String.raw`${FIELD_FLAGS}[\s=]*(?:'?body="|"body=)`;
3195
3195
  var MESSAGE_OPENING = String.raw`${MESSAGE_FLAGS}[\s=]+"`;
3196
3196
  var NESTED_SUBSTITUTION = String.raw`\$\([^()]*\)`;
@@ -3259,12 +3259,28 @@ var shell_body_trigger = {
3259
3259
  };
3260
3260
 
3261
3261
  // scripts/gate/project-checks.ts
3262
- import { existsSync as existsSync6, globSync as globSync2, readFileSync as readFileSync6 } from "node:fs";
3263
- import path12 from "node:path";
3262
+ import { existsSync as existsSync7, globSync as globSync2, readFileSync as readFileSync6 } from "node:fs";
3263
+ import path13 from "node:path";
3264
+
3265
+ // scripts/init/own-formatter.ts
3266
+ import { existsSync as existsSync3 } from "node:fs";
3267
+ import path6 from "node:path";
3268
+ var OWN_FORMATTER_CONFIGS = [
3269
+ "biome.json",
3270
+ "biome.jsonc",
3271
+ "dprint.json",
3272
+ "dprint.jsonc",
3273
+ ".dprint.json",
3274
+ ".dprint.jsonc"
3275
+ ];
3276
+ function find_config(root) {
3277
+ return OWN_FORMATTER_CONFIGS.find((name) => existsSync3(path6.join(root, name)));
3278
+ }
3279
+ var own_formatter = { find_config };
3264
3280
 
3265
3281
  // scripts/init/project-profile.ts
3266
- import { existsSync as existsSync5, readdirSync, readFileSync as readFileSync5 } from "node:fs";
3267
- import path11 from "node:path";
3282
+ import { existsSync as existsSync6, readdirSync, readFileSync as readFileSync5 } from "node:fs";
3283
+ import path12 from "node:path";
3268
3284
 
3269
3285
  // scripts/safe-chain/pack-hook.ts
3270
3286
  import { z as z8 } from "zod";
@@ -3755,10 +3771,10 @@ function set_json_key(content, key, value) {
3755
3771
  const indented = fit_value(content, value_text, line_indent(content, existing.offset));
3756
3772
  return with_trailing_newline(replace_range(content, existing, indented));
3757
3773
  }
3758
- function resolve_parent(content, path15) {
3774
+ function resolve_parent(content, path16) {
3759
3775
  const root = parse_root(content);
3760
3776
  if (root === void 0) return void 0;
3761
- const parent = path15.length > 1 ? findNodeAtLocation(root, path15.slice(0, -1)) : root;
3777
+ const parent = path16.length > 1 ? findNodeAtLocation(root, path16.slice(0, -1)) : root;
3762
3778
  return parent?.type === "object" ? parent : void 0;
3763
3779
  }
3764
3780
  function cut_ranges(content, parent, ranges) {
@@ -3769,24 +3785,24 @@ function cut_ranges(content, parent, ranges) {
3769
3785
  }
3770
3786
  return next;
3771
3787
  }
3772
- function rebalance_new_last(content, path15) {
3773
- const parent = resolve_parent(content, path15);
3788
+ function rebalance_new_last(content, path16) {
3789
+ const parent = resolve_parent(content, path16);
3774
3790
  const last = parent?.children?.at(-1);
3775
3791
  if (parent === void 0 || last === void 0) return content;
3776
3792
  return rebalance(content, last, has_separator_after(content, parent.offset, parent.offset));
3777
3793
  }
3778
- function cut_property(content, parent, path15) {
3779
- const index = property_index(parent, path15.at(-1) ?? "");
3794
+ function cut_property(content, parent, path16) {
3795
+ const index = property_index(parent, path16.at(-1) ?? "");
3780
3796
  const ranges = removal_ranges(content, parent, index);
3781
3797
  if (ranges.length === 0) return content;
3782
3798
  const cut = cut_ranges(content, parent, ranges);
3783
3799
  const did_end_object = index === (parent.children ?? []).length - 1;
3784
- return did_end_object ? rebalance_new_last(cut, path15) : cut;
3800
+ return did_end_object ? rebalance_new_last(cut, path16) : cut;
3785
3801
  }
3786
- function remove_json_path(content, path15) {
3787
- const parent = resolve_parent(content, path15);
3802
+ function remove_json_path(content, path16) {
3803
+ const parent = resolve_parent(content, path16);
3788
3804
  if (parent === void 0) return content;
3789
- const next = cut_property(content, parent, path15);
3805
+ const next = cut_property(content, parent, path16);
3790
3806
  return next === content ? content : with_trailing_newline(next);
3791
3807
  }
3792
3808
  function remove_json_key(content, key) {
@@ -4016,14 +4032,14 @@ var kit_base_preset = {
4016
4032
  };
4017
4033
 
4018
4034
  // scripts/init/tsconfig-preset-migration.ts
4019
- import { existsSync as existsSync3 } from "node:fs";
4020
- import path6 from "node:path";
4035
+ import { existsSync as existsSync4 } from "node:fs";
4036
+ import path7 from "node:path";
4021
4037
  var LEGACY_PRESET_ENTRY = /@joshuafolkken\/[^/]+\/tsconfig\/[^/]+\.jsonc$/u;
4022
4038
  var LEGACY_SUFFIX = ".jsonc";
4023
4039
  var CURRENT_SUFFIX = ".json";
4024
4040
  var EXTENDS_FIELD = "extends";
4025
4041
  function is_migration_target_present(base_directory, entry) {
4026
- return existsSync3(path6.resolve(base_directory, entry));
4042
+ return existsSync4(path7.resolve(base_directory, entry));
4027
4043
  }
4028
4044
  function migrate_entry(base_directory, entry) {
4029
4045
  if (!LEGACY_PRESET_ENTRY.test(entry)) return entry;
@@ -4439,8 +4455,8 @@ var init_logic_sonar = {
4439
4455
  };
4440
4456
 
4441
4457
  // scripts/init/init-logic-templates.ts
4442
- import { existsSync as existsSync4, readFileSync as readFileSync4 } from "node:fs";
4443
- import path7 from "node:path";
4458
+ import { existsSync as existsSync5, readFileSync as readFileSync4 } from "node:fs";
4459
+ import path8 from "node:path";
4444
4460
  var ESLINT_VANILLA = `import { create_vanilla_config } from '@joshuafolkken/kit/eslint/vanilla'
4445
4461
 
4446
4462
  export default create_vanilla_config({
@@ -4525,7 +4541,7 @@ function merge_eslint_config(existing) {
4525
4541
  return apply_rules_template(rules_blocks.join(",\n"));
4526
4542
  }
4527
4543
  function detect_tailwind_stylesheet(project_root2) {
4528
- return existsSync4(path7.join(project_root2, DEFAULT_TAILWIND_STYLESHEET)) ? DEFAULT_TAILWIND_STYLESHEET : void 0;
4544
+ return existsSync5(path8.join(project_root2, DEFAULT_TAILWIND_STYLESHEET)) ? DEFAULT_TAILWIND_STYLESHEET : void 0;
4529
4545
  }
4530
4546
  function generate_prettier_config(stylesheet) {
4531
4547
  const stylesheet_line = stylesheet === void 0 ? "" : ` tailwindStylesheet: '${stylesheet}',
@@ -4539,7 +4555,7 @@ ${stylesheet_line}}
4539
4555
  }
4540
4556
  function existing_stylesheet(existing, project_root2) {
4541
4557
  const named = TAILWIND_STYLESHEET_PATTERN.exec(existing)?.[1];
4542
- return named !== void 0 && existsSync4(path7.resolve(project_root2, named)) ? named : void 0;
4558
+ return named !== void 0 && existsSync5(path8.resolve(project_root2, named)) ? named : void 0;
4543
4559
  }
4544
4560
  function merge_prettier_config(existing, project_root2) {
4545
4561
  const stylesheet = existing_stylesheet(existing, project_root2) ?? detect_tailwind_stylesheet(project_root2);
@@ -5054,23 +5070,23 @@ var AI_COPY_DIRECTORIES_LIST = "AI_COPY_DIRECTORIES";
5054
5070
  var SYNCED_PATHS_LIST = "SYNCED_PATHS";
5055
5071
  var PLUGIN_SKILL_DIRECTORIES_LIST = "PLUGIN_SKILL_DIRECTORIES";
5056
5072
  var PATH_SEPARATOR = "/";
5057
- function is_inside(path15, directory) {
5058
- return path15 === directory || path15.startsWith(`${directory}${PATH_SEPARATOR}`);
5073
+ function is_inside(path16, directory) {
5074
+ return path16 === directory || path16.startsWith(`${directory}${PATH_SEPARATOR}`);
5059
5075
  }
5060
- function matches_file(path15) {
5061
- return init_logic.get_ai_copy_files().includes(path15);
5076
+ function matches_file(path16) {
5077
+ return init_logic.get_ai_copy_files().includes(path16);
5062
5078
  }
5063
- function matches_mapping(path15) {
5064
- return init_logic.get_ai_copy_file_mappings().some((mapping) => mapping.src === path15 || mapping.dest === path15);
5079
+ function matches_mapping(path16) {
5080
+ return init_logic.get_ai_copy_file_mappings().some((mapping) => mapping.src === path16 || mapping.dest === path16);
5065
5081
  }
5066
- function matches_directory(path15) {
5067
- return init_logic.get_ai_copy_directories().some((directory) => is_inside(path15, directory));
5082
+ function matches_directory(path16) {
5083
+ return init_logic.get_ai_copy_directories().some((directory) => is_inside(path16, directory));
5068
5084
  }
5069
- function matches_plugin_skill(path15) {
5070
- return PLUGIN_SKILL_DIRECTORIES.some((directory) => is_inside(path15, directory));
5085
+ function matches_plugin_skill(path16) {
5086
+ return PLUGIN_SKILL_DIRECTORIES.some((directory) => is_inside(path16, directory));
5071
5087
  }
5072
- function matches_synced_path(path15) {
5073
- return synced_paths.get_synced_paths().includes(path15);
5088
+ function matches_synced_path(path16) {
5089
+ return synced_paths.get_synced_paths().includes(path16);
5074
5090
  }
5075
5091
  var MATCHERS = [
5076
5092
  { list: AI_COPY_FILES_LIST, matches: matches_file },
@@ -5079,18 +5095,18 @@ var MATCHERS = [
5079
5095
  { list: PLUGIN_SKILL_DIRECTORIES_LIST, matches: matches_plugin_skill },
5080
5096
  { list: SYNCED_PATHS_LIST, matches: matches_synced_path }
5081
5097
  ];
5082
- function find_list(path15) {
5083
- return MATCHERS.find((matcher) => matcher.matches(path15))?.list;
5098
+ function find_list(path16) {
5099
+ return MATCHERS.find((matcher) => matcher.matches(path16))?.list;
5084
5100
  }
5085
- function to_hit(path15) {
5086
- const list = find_list(path15);
5087
- return list === void 0 ? void 0 : { path: path15, list };
5101
+ function to_hit(path16) {
5102
+ const list = find_list(path16);
5103
+ return list === void 0 ? void 0 : { path: path16, list };
5088
5104
  }
5089
5105
  function find_managed_paths(paths) {
5090
- return paths.flatMap((path15) => to_hit(path15) ?? []);
5106
+ return paths.flatMap((path16) => to_hit(path16) ?? []);
5091
5107
  }
5092
5108
  function has_managed_path(paths) {
5093
- return paths.some((path15) => find_list(path15) !== void 0);
5109
+ return paths.some((path16) => find_list(path16) !== void 0);
5094
5110
  }
5095
5111
  function format_hit(hit) {
5096
5112
  return `${hit.path} (${hit.list})`;
@@ -5106,8 +5122,8 @@ var managed_config_scope = {
5106
5122
  };
5107
5123
 
5108
5124
  // scripts/init/session-language-environment.ts
5109
- import path8 from "node:path";
5110
- var CLAUDE_SETTINGS_PATH = path8.join(".claude", "settings.json");
5125
+ import path9 from "node:path";
5126
+ var CLAUDE_SETTINGS_PATH = path9.join(".claude", "settings.json");
5111
5127
  var KEY_LINE_PATTERN = new RegExp(
5112
5128
  String.raw`^\s*(?:export\s+)?${session_language.ENV_KEY}\s*=`,
5113
5129
  "mu"
@@ -5128,11 +5144,11 @@ var MARKER_TOKEN = "josh-managed-workflow:";
5128
5144
  var MARKER_PREFIX = `# ${MARKER_TOKEN}`;
5129
5145
 
5130
5146
  // scripts/init/claude-plugin-config.ts
5131
- import path9 from "node:path";
5147
+ import path10 from "node:path";
5132
5148
  var MARKETPLACE_NAME = "kit";
5133
5149
  var PLUGIN_ID2 = "kit@kit";
5134
5150
  var MARKETPLACE_PATH = "./node_modules/@joshuafolkken/kit";
5135
- var CLAUDE_SETTINGS_DESTINATION = path9.join(".claude", "settings.json");
5151
+ var CLAUDE_SETTINGS_DESTINATION = path10.join(".claude", "settings.json");
5136
5152
  var PLUGIN_SETTINGS = {
5137
5153
  extraKnownMarketplaces: {
5138
5154
  [MARKETPLACE_NAME]: { source: { source: "directory", path: MARKETPLACE_PATH } }
@@ -5194,7 +5210,7 @@ var PLAIN_KIT_COMMANDS = new Set(
5194
5210
  var PROJECT_ROOT_PREFIX2 = JSON.stringify(hook_launch.PROJECT_ROOT_PREFIX).slice(1, -1);
5195
5211
 
5196
5212
  // scripts/init/security-policy.ts
5197
- import path10 from "node:path";
5213
+ import path11 from "node:path";
5198
5214
  var SECURITY_MD = "SECURITY.md";
5199
5215
  var SECURITY_TEMPLATE = "templates/SECURITY.md";
5200
5216
  var REPOSITORY_PLACEHOLDER = "{{REPOSITORY}}";
@@ -5210,15 +5226,15 @@ function apply_repository(content, repository) {
5210
5226
  return content.replaceAll(REPOSITORY_PLACEHOLDER, () => repository);
5211
5227
  }
5212
5228
  function apply_repository_for_destination(destination_path, content) {
5213
- if (path10.basename(destination_path) !== SECURITY_MD) return content;
5214
- const repository = repository_at(path10.dirname(destination_path));
5229
+ if (path11.basename(destination_path) !== SECURITY_MD) return content;
5230
+ const repository = repository_at(path11.dirname(destination_path));
5215
5231
  if (repository === void 0) {
5216
5232
  throw new Error(`${SECURITY_MD} needs a GitHub origin to name the repository it reports to`);
5217
5233
  }
5218
5234
  return apply_repository(content, repository);
5219
5235
  }
5220
5236
  function does_report_to_kit(root) {
5221
- const existing = file_reader.read_if_readable(path10.join(root, SECURITY_MD)) ?? "";
5237
+ const existing = file_reader.read_if_readable(path11.join(root, SECURITY_MD)) ?? "";
5222
5238
  return new Set(existing.split(LINK_DELIMITER)).has(KIT_ADVISORY_URL);
5223
5239
  }
5224
5240
  function unresolved_warning(root) {
@@ -5338,8 +5354,8 @@ function requested_profile(args, usage = "josh init [--profile basic|full]") {
5338
5354
  throw new Error("Profile must be basic or full");
5339
5355
  }
5340
5356
  function read_manifest(root) {
5341
- const filename = path11.join(root, "package.json");
5342
- if (!existsSync5(filename)) return void 0;
5357
+ const filename = path12.join(root, "package.json");
5358
+ if (!existsSync6(filename)) return void 0;
5343
5359
  const parsed = JSON.parse(readFileSync5(filename, "utf8"));
5344
5360
  if (!json_value.is_record(parsed)) throw new Error("package.json must contain an object");
5345
5361
  return parsed;
@@ -5372,40 +5388,47 @@ function resolve_profile(root, requested) {
5372
5388
  if (profile !== void 0) return { profile, reason: "package.json josh.profile" };
5373
5389
  return inferred_profile(manifest);
5374
5390
  }
5391
+ function is_ignored_directory(name) {
5392
+ return IGNORED_DIRECTORIES.has(name);
5393
+ }
5375
5394
  function should_visit(entry) {
5376
- return entry.isDirectory() && !IGNORED_DIRECTORIES.has(entry.name);
5395
+ return entry.isDirectory() && !is_ignored_directory(entry.name);
5377
5396
  }
5378
5397
  function scan_directory(directory, pending) {
5379
5398
  const entries = readdirSync(directory, { withFileTypes: true });
5380
5399
  pending.push(
5381
- ...entries.filter((entry) => should_visit(entry)).map((entry) => path11.join(directory, entry.name))
5400
+ ...entries.filter((entry) => should_visit(entry)).map((entry) => path12.join(directory, entry.name))
5382
5401
  );
5383
- return entries.filter((entry) => entry.isFile()).map((entry) => path11.join(directory, entry.name));
5402
+ return entries.filter((entry) => entry.isFile()).map((entry) => path12.join(directory, entry.name));
5384
5403
  }
5385
5404
  function is_project_file(root, file) {
5386
- const relative_path = path11.relative(root, file).split(path11.sep).join(path11.posix.sep);
5405
+ const relative_path = path12.relative(root, file).split(path12.sep).join(path12.posix.sep);
5387
5406
  return !kit_written_paths.is_kit_written(relative_path);
5388
5407
  }
5389
- function file_extensions(root) {
5408
+ function list_files(root) {
5390
5409
  const pending = [root];
5391
5410
  const files = [];
5392
5411
  for (const directory of pending) {
5393
5412
  files.push(...scan_directory(directory, pending));
5394
5413
  }
5395
- return files.filter((file) => is_project_file(root, file)).map((file) => path11.extname(file));
5414
+ return files;
5415
+ }
5416
+ function file_extensions(root) {
5417
+ return list_files(root).filter((file) => is_project_file(root, file)).map((file) => path12.extname(file));
5396
5418
  }
5397
5419
  function scan_files(root) {
5398
5420
  const extensions = file_extensions(root);
5399
5421
  const has_web = extensions.some((extension) => WEB_EXTENSIONS.has(extension));
5422
+ const should_use_prettier = has_web && own_formatter.find_config(root) === void 0;
5400
5423
  const has_typescript = extensions.some((extension) => TYPESCRIPT_EXTENSIONS.has(extension));
5401
- return { has_web, has_typescript };
5424
+ return { should_use_prettier, has_typescript };
5402
5425
  }
5403
5426
  function has_github_remote(root) {
5404
5427
  const url = git_spawn_sync.origin_url(root);
5405
5428
  return url !== void 0 && repo_origin.parse_origin_url(url) !== void 0;
5406
5429
  }
5407
5430
  function has_git(root) {
5408
- return existsSync5(path11.join(root, ".git"));
5431
+ return existsSync6(path12.join(root, ".git"));
5409
5432
  }
5410
5433
  function has_workflow(root) {
5411
5434
  return workflow_mark.is_requested() || workflow_mark.is_recorded(read_manifest(root));
@@ -5427,6 +5450,8 @@ var project_profile = {
5427
5450
  resolve_profile,
5428
5451
  has_git,
5429
5452
  inspect_project,
5453
+ is_ignored_directory,
5454
+ list_files,
5430
5455
  requested_profile,
5431
5456
  with_legacy_profile_names
5432
5457
  };
@@ -5475,7 +5500,7 @@ var object_schema = z13.record(z13.string(), z13.unknown());
5475
5500
  function project_root(directory) {
5476
5501
  return ancestor_directories.nearest(
5477
5502
  directory,
5478
- (candidate) => existsSync6(path12.join(candidate, PACKAGE_JSON2))
5503
+ (candidate) => existsSync7(path13.join(candidate, PACKAGE_JSON2))
5479
5504
  ) ?? directory;
5480
5505
  }
5481
5506
  function is_kit_repository(directory) {
@@ -5488,7 +5513,7 @@ function has_files(directory, pattern) {
5488
5513
  return globSync2(pattern, { cwd: project_root(directory), exclude: is_ignored }).length > 0;
5489
5514
  }
5490
5515
  function has_config(directory, names) {
5491
- return names.some((name) => existsSync6(path12.join(project_root(directory), name)));
5516
+ return names.some((name) => existsSync7(path13.join(project_root(directory), name)));
5492
5517
  }
5493
5518
  function has_bin(directory, bin_name) {
5494
5519
  return find_local_bin_upwards(directory, bin_name) !== void 0;
@@ -5503,7 +5528,7 @@ function is_basic_manifest(manifest) {
5503
5528
  }
5504
5529
  function read_manifest2(directory) {
5505
5530
  try {
5506
- const manifest_path = path12.join(project_root(directory), PACKAGE_JSON2);
5531
+ const manifest_path = path13.join(project_root(directory), PACKAGE_JSON2);
5507
5532
  return json_value.parse_or_undefined(readFileSync6(manifest_path, "utf8"));
5508
5533
  } catch {
5509
5534
  return void 0;
@@ -5538,6 +5563,8 @@ function type_check_skip_reason(directory) {
5538
5563
  }
5539
5564
  function prettier_skip_reason(directory) {
5540
5565
  if (!is_basic(directory)) return void 0;
5566
+ const formatter = own_formatter.find_config(project_root(directory));
5567
+ if (formatter !== void 0) return `${formatter} configures the project's own formatter`;
5541
5568
  if (!has_files(directory, WEB_FILES)) return "no HTML, CSS or JavaScript files were found";
5542
5569
  return missing_tool_reason(directory, "prettier", "prettier");
5543
5570
  }
@@ -5590,40 +5617,40 @@ var BASIC_REQUIRED_SUFFIXES = [
5590
5617
  ".toml"
5591
5618
  ];
5592
5619
  function normalize(paths) {
5593
- return paths.map((path15) => path15.trim()).filter((path15) => path15 !== "");
5620
+ return paths.map((path16) => path16.trim()).filter((path16) => path16 !== "");
5594
5621
  }
5595
- function is_test_file(path15) {
5596
- return TEST_SUFFIXES.some((suffix) => path15.endsWith(suffix));
5622
+ function is_test_file(path16) {
5623
+ return TEST_SUFFIXES.some((suffix) => path16.endsWith(suffix));
5597
5624
  }
5598
- function is_basic_manual(path15, is_basic2) {
5599
- const lower = path15.toLowerCase();
5625
+ function is_basic_manual(path16, is_basic2) {
5626
+ const lower = path16.toLowerCase();
5600
5627
  return is_basic2 && BASIC_REQUIRED_SUFFIXES.every((suffix) => !lower.endsWith(suffix));
5601
5628
  }
5602
- function is_basic_visual(path15) {
5603
- const lower = path15.toLowerCase();
5629
+ function is_basic_visual(path16) {
5630
+ const lower = path16.toLowerCase();
5604
5631
  return BASIC_VISUAL_SUFFIXES.some((suffix) => lower.endsWith(suffix));
5605
5632
  }
5606
- function is_exempt(path15, is_basic2 = false) {
5607
- if (EXEMPT_PATHS.includes(path15) || is_basic_manual(path15, is_basic2)) return true;
5608
- return EXEMPT_SUFFIXES.some((suffix) => path15.endsWith(suffix)) || EXEMPT_PREFIXES.some((prefix) => path15.startsWith(prefix));
5633
+ function is_exempt(path16, is_basic2 = false) {
5634
+ if (EXEMPT_PATHS.includes(path16) || is_basic_manual(path16, is_basic2)) return true;
5635
+ return EXEMPT_SUFFIXES.some((suffix) => path16.endsWith(suffix)) || EXEMPT_PREFIXES.some((prefix) => path16.startsWith(prefix));
5609
5636
  }
5610
- function is_runtime(path15, is_basic2 = false) {
5611
- return !is_test_file(path15) && !is_exempt(path15, is_basic2);
5637
+ function is_runtime(path16, is_basic2 = false) {
5638
+ return !is_test_file(path16) && !is_exempt(path16, is_basic2);
5612
5639
  }
5613
5640
  function verdict_for2(paths, is_basic2 = false) {
5614
5641
  const changed = normalize(paths);
5615
- if (changed.some((path15) => is_test_file(path15))) return "satisfied";
5616
- if (changed.some((path15) => is_runtime(path15, is_basic2))) return "required";
5642
+ if (changed.some((path16) => is_test_file(path16))) return "satisfied";
5643
+ if (changed.some((path16) => is_runtime(path16, is_basic2))) return "required";
5617
5644
  return "exempt";
5618
5645
  }
5619
5646
  function runtime_files(paths, is_basic2 = false) {
5620
- return normalize(paths).filter((path15) => is_runtime(path15, is_basic2));
5647
+ return normalize(paths).filter((path16) => is_runtime(path16, is_basic2));
5621
5648
  }
5622
5649
  function exempt_files(paths, is_basic2 = false) {
5623
- return normalize(paths).filter((path15) => is_exempt(path15, is_basic2));
5650
+ return normalize(paths).filter((path16) => is_exempt(path16, is_basic2));
5624
5651
  }
5625
5652
  function manual_check_files(paths, is_basic2) {
5626
- return normalize(paths).filter((path15) => is_exempt(path15, is_basic2) && !is_exempt(path15));
5653
+ return normalize(paths).filter((path16) => is_exempt(path16, is_basic2) && !is_exempt(path16));
5627
5654
  }
5628
5655
  var test_declared_logic = {
5629
5656
  EXEMPT_PATHS,
@@ -5980,7 +6007,7 @@ var epic_busy = {
5980
6007
  // scripts/run/run-liveness.ts
5981
6008
  import { readFileSync as readFileSync7, realpathSync, statSync } from "node:fs";
5982
6009
  import { homedir, tmpdir } from "node:os";
5983
- import path13 from "node:path";
6010
+ import path14 from "node:path";
5984
6011
  import { setTimeout as sleep } from "node:timers/promises";
5985
6012
 
5986
6013
  // scripts/agent/agent-event.ts
@@ -6284,12 +6311,12 @@ var ALLOWED_ROOTS = [
6284
6311
  )
6285
6312
  ];
6286
6313
  function is_within(candidate, root) {
6287
- const relative = path13.relative(root, candidate);
6288
- return relative !== "" && !relative.startsWith("..") && !path13.isAbsolute(relative);
6314
+ const relative = path14.relative(root, candidate);
6315
+ return relative !== "" && !relative.startsWith("..") && !path14.isAbsolute(relative);
6289
6316
  }
6290
6317
  function to_safe_path(output_path) {
6291
- const normalized2 = path13.normalize(output_path);
6292
- if (!path13.isAbsolute(normalized2)) return void 0;
6318
+ const normalized2 = path14.normalize(output_path);
6319
+ if (!path14.isAbsolute(normalized2)) return void 0;
6293
6320
  return ALLOWED_ROOTS.some((root) => is_within(normalized2, root)) ? normalized2 : void 0;
6294
6321
  }
6295
6322
  function sample_output(output_path) {
@@ -6824,7 +6851,7 @@ var run_parent_cut_hook = {
6824
6851
  };
6825
6852
 
6826
6853
  // scripts/hooks/step-zero-notice.ts
6827
- import path14 from "node:path";
6854
+ import path15 from "node:path";
6828
6855
  var STAMP_PREFIX4 = "josh-step-zero-notice-";
6829
6856
  var EDIT_TOOLS3 = /* @__PURE__ */ new Set(["Edit", "Write"]);
6830
6857
  var PARENT_PREFIX = "..";
@@ -6839,9 +6866,9 @@ function edited_paths(tool_input) {
6839
6866
  );
6840
6867
  }
6841
6868
  function is_runtime_file(file_path, root) {
6842
- const relative = path14.relative(root, path14.resolve(root, file_path));
6843
- if (relative.startsWith(PARENT_PREFIX) || path14.isAbsolute(relative)) return false;
6844
- return !test_declared_logic.is_exempt(relative.split(path14.sep).join("/"));
6869
+ const relative = path15.relative(root, path15.resolve(root, file_path));
6870
+ if (relative.startsWith(PARENT_PREFIX) || path15.isAbsolute(relative)) return false;
6871
+ return !test_declared_logic.is_exempt(relative.split(path15.sep).join("/"));
6845
6872
  }
6846
6873
  function is_candidate2(raw_payload, root) {
6847
6874
  const payload = hook_decision.parse_hook_payload(raw_payload);
@@ -6,7 +6,7 @@ import {
6
6
  process_owner_schema,
7
7
  run_carry,
8
8
  time_instant
9
- } from "./chunk-3LE6VLSR.js";
9
+ } from "./chunk-3C4XRYG6.js";
10
10
  import {
11
11
  PLATFORM_TEMP_ROOT,
12
12
  PROBE_TIMEOUT_MS,
@@ -319,16 +319,16 @@ var ISSUE_COMMANDS = {
319
319
  description: "File an Issue with every filing step: lint, Origin, fold, WIP cap, duplicate scout, labels, then epic:bundle",
320
320
  category: "AI tools",
321
321
  reference: [
322
- "<title> --body-file <path> --depth <0|1|2> [--route <route>] [--label <name>] [--repo <owner/repo>] [--distinct <N,\u2026>] [--over-cap] [--no-auto-ok] [--requested] [--release]",
322
+ "<title> --body-file <path> --depth <0|1|2> [--route <route>] [--label <name>] [--repo <owner/repo>] [--distinct <N,\u2026>] [--over-cap] [--no-auto-ok] [--release]",
323
323
  "automation",
324
324
  ["network"]
325
325
  ]
326
326
  },
327
327
  "issue:release": {
328
328
  script: "scripts/issue/issue-release-cli.ts",
329
- description: "Link an Issue to the repository's open release Issue as its blocker, filing one when none is open",
329
+ description: "Link an Issue to the repository's open release Issue as its blocker (or, with --wait, as waiting on it), filing one when none is open",
330
330
  category: "AI tools",
331
- reference: ["<issue>", "automation", ["network"]]
331
+ reference: ["<issue> [--wait]", "automation", ["network"]]
332
332
  }
333
333
  };
334
334
 
@@ -613,6 +613,16 @@ var AI_COMMANDS = {
613
613
  category: "AI tools",
614
614
  reference: ["[--exclude <n>[,<n>...]] [--label <name>]", "automation", ["network"]]
615
615
  },
616
+ "auto-ok:judge": {
617
+ script: "scripts/auto-ok/auto-ok-judge-cli.ts",
618
+ description: "List the open issues backlogrun owes an auto-ok judgement, or record one (--apply / --decline)",
619
+ category: "AI tools",
620
+ reference: [
621
+ "[--apply <n> (--lane | --solo) | --decline <n> --reason <text>]",
622
+ "automation",
623
+ ["network"]
624
+ ]
625
+ },
616
626
  ...BACKLOG_COMMANDS,
617
627
  cost: {
618
628
  script: "scripts/cost-runtime/cost-cli.ts",
@@ -1930,7 +1940,7 @@ var PROJECT_COMMANDS = {
1930
1940
  description: "Set a project up for the GitHub Issue workflow, from git init to the setup PR",
1931
1941
  category: "Project",
1932
1942
  reference: [
1933
- `${PROFILE_ARGUMENTS} [--yes] [--github] [--public] [--init-command <command>] [--push-preflight-command <command>]`,
1943
+ `${PROFILE_ARGUMENTS} [--yes] [--github] [--public] [--dry-run] [--init-command <command>] [--push-preflight-command <command>]`,
1934
1944
  "developer",
1935
1945
  ["files", "git", "network", "processes"]
1936
1946
  ]
@@ -1963,7 +1973,7 @@ var PROJECT_COMMANDS = {
1963
1973
  description: "Initialize config in a new project",
1964
1974
  category: "Project",
1965
1975
  reference: [
1966
- `${PROFILE_ARGUMENTS} [--no-install]`,
1976
+ `${PROFILE_ARGUMENTS} [--no-install] [--dry-run]`,
1967
1977
  "developer",
1968
1978
  ["files", "network", "processes"]
1969
1979
  ]
@@ -2126,7 +2136,7 @@ var WORKFLOW_COMMANDS = {
2126
2136
  description: "Send Telegram notification",
2127
2137
  category: "Workflow",
2128
2138
  reference: [
2129
- "[--task-type <type>] [--body <text> | --body-file <path>] [--issue-url <url>] [--pr-url <url>] [--issue-title <text>] [--repo-name <name>]",
2139
+ "[--task-type <type>] [--body <text> | --body-file <path>] [--issue-url <url>] [--pr-url <url>] [--issue-title <text>] [--repo-name <name>] [--recommended <text>] [--alternative <text>]...",
2130
2140
  "automation",
2131
2141
  ["notifications"]
2132
2142
  ],
@@ -2,7 +2,7 @@ import {
2
2
  ENV_FILE_NAME,
3
3
  issue_number_shape,
4
4
  lane_paths
5
- } from "./chunk-3LE6VLSR.js";
5
+ } from "./chunk-3C4XRYG6.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-XER6SSIB.js";
8
+ } from "./chunk-LIAFCXL7.js";
9
9
  import {
10
10
  file_reader,
11
11
  json_value
12
- } from "./chunk-3LE6VLSR.js";
12
+ } from "./chunk-3C4XRYG6.js";
13
13
  import {
14
14
  HOOK_PROCESS_TIMEOUT_MS
15
15
  } from "./chunk-DGT54IH5.js";