@joshuafolkken/kit 1.1094.0 → 1.1128.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 (149) hide show
  1. package/.claude/skills/workflow-commands/SKILL.md +1 -1
  2. package/.claude/skills/workflow-commands/background-commands.md +36 -85
  3. package/.claude/skills/workflow-commands/backlogrun-progress.md +29 -32
  4. package/.claude/skills/workflow-commands/backlogrun-steps.md +2 -2
  5. package/.claude/skills/workflow-commands/fullrun.md +5 -4
  6. package/.claude/skills/workflow-commands/halfrun.md +5 -4
  7. package/.claude/skills/workflow-commands/latest-gate.md +7 -15
  8. package/.claude/skills/workflow-commands/pre-gate-cut.md +4 -8
  9. package/.claude/skills/workflow-commands/split-assessment.md +4 -18
  10. package/.github/actions/setup-node/action.yml +33 -0
  11. package/.github/actions/setup-pnpm/action.yml +4 -4
  12. package/.github/workflows/auto-tag.yml +2 -3
  13. package/.github/workflows/ci.yml +7 -8
  14. package/.github/workflows/dependabot-auto-merge.yml +1 -0
  15. package/.github/workflows/pr-classification.yml +1 -3
  16. package/.github/workflows/production.yml +1 -0
  17. package/.github/workflows/publish.yml +10 -9
  18. package/.github/workflows/sonar-qube.yml +17 -13
  19. package/.pnpmfile.mjs +29 -0
  20. package/AGENTS.md +4 -11
  21. package/CLAUDE.md +24 -17
  22. package/GEMINI.md +4 -13
  23. package/README.md +8 -3
  24. package/SECURITY.md +1 -0
  25. package/cspell/index.yaml +4 -0
  26. package/dist/CLAUDE.basic.md +6 -6
  27. package/dist/CLAUDE.md +24 -17
  28. package/dist/CLAUDE.static.md +6 -6
  29. package/dist/config-merge/index.js +33 -9
  30. package/dist/hooks/batch-guard.js +4 -4
  31. package/dist/hooks/{chunk-NKOG3XAV.js → chunk-4JZDP5X5.js} +2 -2
  32. package/dist/hooks/{chunk-3C4YCCEF.js → chunk-5SD2YM7Z.js} +4 -4
  33. package/dist/hooks/{chunk-OIZUHPJI.js → chunk-77J7IEQM.js} +1 -1
  34. package/dist/hooks/{chunk-KHWHKJOM.js → chunk-7HVB7SZG.js} +3 -3
  35. package/dist/hooks/{chunk-UD24EAIL.js → chunk-AIOIOMPX.js} +1875 -104
  36. package/dist/hooks/{chunk-M2XDCUKD.js → chunk-M7QKEKWO.js} +88 -1783
  37. package/dist/hooks/{chunk-E54KGFEQ.js → chunk-MKVGBQPA.js} +1 -1
  38. package/dist/hooks/{chunk-7ZPFAVR7.js → chunk-NXYMNPUQ.js} +3 -3
  39. package/dist/hooks/{chunk-O4LL4HTI.js → chunk-QVLT52OV.js} +2 -2
  40. package/dist/hooks/{chunk-IL27YTPH.js → chunk-XYUIQOW3.js} +2 -2
  41. package/dist/hooks/codex-hook-adapter.js +12 -47
  42. package/dist/hooks/duplicate-read-guard.js +5 -5
  43. package/dist/hooks/format-edited.js +2 -2
  44. package/dist/hooks/inputs.json +180 -179
  45. package/dist/hooks/investigation-guard.js +5 -5
  46. package/dist/hooks/pretool-guard.js +9 -9
  47. package/dist/hooks/stop-guard.js +17 -12
  48. package/dist/josh.js +79 -30
  49. package/dist/version/index.js +36 -20
  50. package/eslint/rules/unicorn.js +3 -2
  51. package/package.json +18 -2
  52. package/pnpm-workspace.yaml +5 -7
  53. package/prompts/collaboration-workflow/glossary.md +17 -0
  54. package/prompts/collaboration-workflow/issue-template.md +1 -1
  55. package/prompts/collaboration-workflow/operating-rules.md +1 -1
  56. package/prompts/collaboration-workflow/principles.md +9 -0
  57. package/prompts/collaboration-workflow.md +1 -0
  58. package/scripts/backlog/backlog-arrival.ts +30 -10
  59. package/scripts/backlog/backlog-budget-cli.ts +15 -16
  60. package/scripts/backlog/backlog-offer-cli.ts +6 -14
  61. package/scripts/backlog/backlog-plan.ts +29 -18
  62. package/scripts/backlog/backlog-ready.ts +20 -7
  63. package/scripts/config-merge/parse-jsonc.ts +33 -3
  64. package/scripts/config-merge/patch-json-key.ts +13 -6
  65. package/scripts/cost-runtime/cost-cli.ts +3 -7
  66. package/scripts/doctor/doctor-consumer.ts +3 -5
  67. package/scripts/doctor/doctor-io.ts +9 -13
  68. package/scripts/document/backlogrun-parent-read-set.ts +12 -1
  69. package/scripts/document/document-byte-budget.ts +1 -0
  70. package/scripts/document/entry-read-budget.ts +13 -7
  71. package/scripts/document/entry-read-set.ts +32 -8
  72. package/scripts/document/lane-child-read-set.ts +7 -0
  73. package/scripts/document/read-set-point-of-use.ts +8 -3
  74. package/scripts/document/read-set-trim.ts +3 -1
  75. package/scripts/epic/epic-audit.ts +3 -18
  76. package/scripts/gh/git-gh-issue-list.ts +12 -11
  77. package/scripts/gh/git-gh-issue-write.ts +4 -1
  78. package/scripts/gh/git-gh-pr-auto-merge.ts +4 -1
  79. package/scripts/git/git-command.ts +6 -1
  80. package/scripts/git/git-spawn-sync.ts +65 -0
  81. package/scripts/git/git-spawn.ts +5 -4
  82. package/scripts/git/stash/stash-pop-args.ts +1 -6
  83. package/scripts/init/init-file-action.ts +54 -0
  84. package/scripts/init/init-logic-migrate.ts +35 -17
  85. package/scripts/init/init-logic-secretlint.ts +1 -1
  86. package/scripts/init/init-logic.ts +6 -22
  87. package/scripts/init/init.ts +11 -68
  88. package/scripts/init/kit-written-paths.ts +2 -0
  89. package/scripts/init/project-profile.ts +3 -6
  90. package/scripts/init/start-steps.ts +2 -1
  91. package/scripts/issue/defect-rate-cli.ts +61 -20
  92. package/scripts/issue/issue-backlinks.ts +7 -14
  93. package/scripts/issue/issue-cite.ts +12 -6
  94. package/scripts/issue/issue-file.ts +5 -12
  95. package/scripts/issue/markdown-section.ts +21 -6
  96. package/scripts/issue/measure-rerun-cli.ts +73 -14
  97. package/scripts/josh/josh-commands-project.ts +1 -1
  98. package/scripts/josh/josh-commands-workflow.ts +1 -1
  99. package/scripts/josh/run-github-prerequisite.ts +3 -6
  100. package/scripts/lane/lane-await.ts +43 -13
  101. package/scripts/lane/lane-close.ts +4 -1
  102. package/scripts/lane/lane-launch-cli.ts +10 -16
  103. package/scripts/lane/openai-review-broker.ts +4 -1
  104. package/scripts/lib/cli-flags.ts +31 -2
  105. package/scripts/lib/error-message.ts +12 -1
  106. package/scripts/lines/line-targets.ts +0 -11
  107. package/scripts/lines/lines-command.ts +5 -3
  108. package/scripts/propagate/propagate-git.ts +3 -8
  109. package/scripts/refactor/refactor-scan.ts +2 -1
  110. package/scripts/registry-migration/migrate-logic.ts +28 -19
  111. package/scripts/registry-migration/migrate.ts +6 -5
  112. package/scripts/release/github-release-cli.ts +14 -3
  113. package/scripts/release/release-publish.ts +36 -2
  114. package/scripts/release/release-worktree.ts +97 -2
  115. package/scripts/review/review-checkout.ts +3 -2
  116. package/scripts/review/review-record-cli.ts +9 -16
  117. package/scripts/rules/early-heartbeat.ts +4 -3
  118. package/scripts/rules/lane-park.ts +9 -0
  119. package/scripts/rules/stop-rules.ts +7 -4
  120. package/scripts/run/run-carry-args.ts +8 -12
  121. package/scripts/run/run-cut-args.ts +1 -6
  122. package/scripts/run/run-ending-cli.ts +1 -5
  123. package/scripts/run/run-entry-cli.ts +40 -9
  124. package/scripts/run/run-entry-stop.ts +104 -0
  125. package/scripts/run/run-event-stream-emit.ts +7 -2
  126. package/scripts/run/run-hold.ts +4 -1
  127. package/scripts/run/run-liveness-cli.ts +1 -5
  128. package/scripts/run/run-merge-cli.ts +2 -10
  129. package/scripts/run/run-parent-cut-hook.ts +4 -1
  130. package/scripts/run/run-prep-cli.ts +4 -1
  131. package/scripts/run/run-progress-args.ts +20 -4
  132. package/scripts/run/run-progress-cli.ts +31 -29
  133. package/scripts/run/run-progress-clock.ts +4 -1
  134. package/scripts/run/run-ship-cli.ts +8 -16
  135. package/scripts/run/run-ship-probe.ts +4 -1
  136. package/scripts/run/run-status-cli.ts +2 -15
  137. package/scripts/run/run-tidy-lanes.ts +4 -1
  138. package/scripts/run/run-wake-cli.ts +2 -10
  139. package/scripts/run/run-watcher-guard.ts +9 -5
  140. package/scripts/safe-chain/pack-hook.ts +92 -0
  141. package/scripts/sync/sync-ai-files.ts +4 -0
  142. package/scripts/test/test-declared-changed.ts +13 -16
  143. package/scripts/test/test-declared.ts +3 -7
  144. package/scripts/version/version-commands.ts +11 -1
  145. package/templates/CLAUDE.basic.md +6 -6
  146. package/templates/workflows/ci.yml +16 -82
  147. package/templates/workflows/dependabot-auto-merge.yml +1 -0
  148. package/templates/workflows/github-release.yml +1 -3
  149. package/tsconfig.sonar.json +4 -22
@@ -1,18 +1,18 @@
1
1
  #!/usr/bin/env tsx
2
2
  import {
3
3
  pretool_outcome_async
4
- } from "./chunk-M2XDCUKD.js";
5
- import "./chunk-UD24EAIL.js";
4
+ } from "./chunk-M7QKEKWO.js";
5
+ import "./chunk-AIOIOMPX.js";
6
6
  import "./chunk-3V37IID6.js";
7
- import "./chunk-IL27YTPH.js";
8
- import "./chunk-KHWHKJOM.js";
9
- import "./chunk-3C4YCCEF.js";
10
- import "./chunk-7ZPFAVR7.js";
11
- import "./chunk-O4LL4HTI.js";
7
+ import "./chunk-XYUIQOW3.js";
8
+ import "./chunk-7HVB7SZG.js";
9
+ import "./chunk-5SD2YM7Z.js";
10
+ import "./chunk-NXYMNPUQ.js";
11
+ import "./chunk-QVLT52OV.js";
12
12
  import {
13
13
  hook_decision
14
- } from "./chunk-E54KGFEQ.js";
15
- import "./chunk-NKOG3XAV.js";
14
+ } from "./chunk-MKVGBQPA.js";
15
+ import "./chunk-4JZDP5X5.js";
16
16
  import "./chunk-WPALEIRX.js";
17
17
  import "./chunk-RKUAD3I6.js";
18
18
 
@@ -7,6 +7,7 @@ import {
7
7
  backlog_budget,
8
8
  filing_cap,
9
9
  git_gh_api_path,
10
+ git_gh_command,
10
11
  git_gh_exec,
11
12
  has_label_name,
12
13
  issue_cite,
@@ -24,14 +25,14 @@ import {
24
25
  run_headless,
25
26
  run_hold,
26
27
  run_invocation
27
- } from "./chunk-UD24EAIL.js";
28
+ } from "./chunk-AIOIOMPX.js";
28
29
  import {
29
30
  session_language
30
31
  } from "./chunk-6V5OPIUU.js";
31
32
  import {
32
33
  hook_decision,
33
34
  lane_child_marker
34
- } from "./chunk-E54KGFEQ.js";
35
+ } from "./chunk-MKVGBQPA.js";
35
36
  import {
36
37
  PROJECT_ROOT,
37
38
  json_value,
@@ -39,7 +40,7 @@ import {
39
40
  time_density_hook,
40
41
  time_hook_transcript,
41
42
  time_reported_failure
42
- } from "./chunk-NKOG3XAV.js";
43
+ } from "./chunk-4JZDP5X5.js";
43
44
  import "./chunk-WPALEIRX.js";
44
45
  import "./chunk-RKUAD3I6.js";
45
46
 
@@ -349,19 +350,23 @@ async function read_ready(ports = DEFAULT_PORTS) {
349
350
  if (free_lanes2 <= NO_FREE) return { issues: [], free_lanes: free_lanes2 };
350
351
  return { issues: await ports.ready_issues(), free_lanes: free_lanes2 };
351
352
  }
352
- function ready_line(reading) {
353
+ function ready_line(reading, slug) {
353
354
  if (reading.issues.length === NONE2 || reading.free_lanes <= NO_FREE) return void 0;
354
- const issues = reading.issues.map((issue) => `#${issue}`).join(" ");
355
+ const cite = issue_cite.citer(slug, /* @__PURE__ */ new Map());
356
+ const issues = reading.issues.map((issue) => cite(issue)).join(" ");
355
357
  return `ready ${issues} \xB7 free lanes ${String(reading.free_lanes)}`;
356
358
  }
357
- async function parent_ready_line(ports, is_parent) {
359
+ async function parent_ready_line(ports, is_parent, read_repo) {
358
360
  if (!await is_parent()) return void 0;
359
- return ready_line(await read_ready(ports));
361
+ const reading = await read_ready(ports);
362
+ return reading.issues.length === NONE2 ? void 0 : ready_line(reading, await read_repo());
360
363
  }
361
- async function print_ready_line(ports = DEFAULT_PORTS, is_parent = run_headless.is_backlog_parent) {
364
+ function print_line(line) {
365
+ if (line !== void 0) console.info(line);
366
+ }
367
+ async function print_ready_line(ports = DEFAULT_PORTS, is_parent = run_headless.is_backlog_parent, read_repo = git_gh_command.repo_get_name_with_owner) {
362
368
  try {
363
- const line = await parent_ready_line(ports, is_parent);
364
- if (line !== void 0) console.info(line);
369
+ print_line(await parent_ready_line(ports, is_parent, read_repo));
365
370
  } catch {
366
371
  }
367
372
  }
@@ -840,8 +845,8 @@ function build_citation_reason(references) {
840
845
  var FILING_OFFER_REASON = '\u26D4 filing offer: your reply offers to file an Issue instead of filing it. Filing into a first-party repository is Tier A \u2014 the trigger is the judgement that it is worth filing, not the run\'s progress (`.claude/skills/workflow-commands/SKILL.md` \u2192 \xA72i, `observation-filing.md`). Run `pnpm josh issue:file "<title>" --body-file <path> --depth <0|1|2>` \u2014 it scouts, lints, labels and runs `epic:bundle` itself \u2014 then end with the one-line citation of what was filed; do not repeat your previous reply. If it is not worth filing after all, say so in one line instead.';
841
846
  var HEADLESS_WAIT_MARKER = "\u26D4 headless parent:";
842
847
  var HEADLESS_REFUSAL_CAP = 3;
843
- var HEADLESS_WAIT_CALLS = ['"command":"pnpm josh lane:await', '"command":"pnpm josh run:progress'];
844
- var HEADLESS_WAIT_BODY = ' this is a `claude -p` `backlogrun` parent (`JOSH_RUN_HEADLESS`) with lanes still in flight, and ending this turn ends the process \u2014 its background waits are killed with it and the lanes are left without a parent. Wait in the foreground instead: run `pnpm josh lane:await <N...>` for the in-flight lanes (and `pnpm josh run:progress --wait` for the heartbeat) as foreground commands within the tool timeout, act on what they report, and continue the loop. End the turn only after `pnpm josh run:carry --cut` or `--end` (`backlogrun-progress.md` \u2192 "The parent keeps no clock of its own").';
848
+ var HEADLESS_WAIT_CALLS = ['"command":"pnpm josh lane:await'];
849
+ var HEADLESS_WAIT_BODY = ' this is a `claude -p` `backlogrun` parent (`JOSH_RUN_HEADLESS`) with lanes still in flight, and ending this turn ends the process \u2014 its background waits are killed with it and the lanes are left without a parent. Wait in the foreground instead: run `pnpm josh lane:await <N...>` for the in-flight lanes as a foreground command within the tool timeout (with `pnpm josh run:progress --wait` in the background for the heartbeat, which streams its reports itself and lives while this turn does), act on what it reports, and continue the loop. End the turn only after `pnpm josh run:carry --cut` or `--end` (`backlogrun-progress.md` \u2192 "The parent keeps no clock of its own").';
845
850
  var HEADLESS_WAIT_REASON = `${HEADLESS_WAIT_MARKER}${HEADLESS_WAIT_BODY}`;
846
851
  var INDEX_COMMAND_PATTERN = /git (?:add|stage|rm --cached|restore --staged|restore -S)\b/u;
847
852
  var PERMISSION_PATTERN = /許可|承認|permission|approve|approval|authorization/iu;
package/dist/josh.js CHANGED
@@ -4,6 +4,74 @@
4
4
  import { existsSync } from "node:fs";
5
5
  import path from "node:path";
6
6
 
7
+ // scripts/lib/spawn-exit.ts
8
+ var SPAWN_ERROR_EXIT_CODE = 2;
9
+ var SIGNAL_KILL_EXIT_CODE = 1;
10
+ function resolve_spawn_exit(executable, result) {
11
+ if (result.exitCode !== void 0) return result.exitCode;
12
+ if (result.isTerminated === true) return SIGNAL_KILL_EXIT_CODE;
13
+ console.error(`Failed to execute ${executable}: ${result.shortMessage ?? "spawn failed"}`);
14
+ return SPAWN_ERROR_EXIT_CODE;
15
+ }
16
+ function read_spawn_stdout(result) {
17
+ return result.stdout ?? "";
18
+ }
19
+ function read_spawn_stderr(result) {
20
+ return result.stderr ?? "";
21
+ }
22
+
23
+ // scripts/git/git-spawn-sync.ts
24
+ import { execaSync } from "execa";
25
+
26
+ // scripts/git/constants.ts
27
+ import { platform } from "node:os";
28
+ var GIT_COMMAND_UNIX = "/usr/bin/git";
29
+ function get_git_command() {
30
+ if (platform() === "win32") {
31
+ return String.raw`"C:\Program Files\Git\cmd\git.exe"`;
32
+ }
33
+ return GIT_COMMAND_UNIX;
34
+ }
35
+ function get_git_command_for_spawn() {
36
+ if (platform() === "win32") {
37
+ return String.raw`C:\Program Files\Git\cmd\git.exe`;
38
+ }
39
+ return GIT_COMMAND_UNIX;
40
+ }
41
+ var git_utilities = {
42
+ get_git_command,
43
+ get_git_command_for_spawn
44
+ };
45
+
46
+ // scripts/git/git-spawn-sync.ts
47
+ var GIT_TIMEOUT_MS = 1e4;
48
+ var SUCCESS_EXIT_CODE = 0;
49
+ var C_LOCALE = { LC_ALL: "C", LANGUAGE: "C" };
50
+ function run(args, options = {}) {
51
+ const result = execaSync(git_utilities.get_git_command_for_spawn(), args, {
52
+ ...options,
53
+ extendEnv: true,
54
+ reject: false,
55
+ timeout: options.timeout ?? GIT_TIMEOUT_MS
56
+ });
57
+ return {
58
+ exit_code: result.exitCode,
59
+ stdout: read_spawn_stdout(result),
60
+ stderr: read_spawn_stderr(result)
61
+ };
62
+ }
63
+ function read(args, options = {}) {
64
+ const result = run(args, options);
65
+ return result.exit_code === SUCCESS_EXIT_CODE ? result.stdout.trim() : void 0;
66
+ }
67
+ function origin_url(cwd) {
68
+ return read(["config", "--get", "remote.origin.url"], { cwd });
69
+ }
70
+ function toplevel(timeout = GIT_TIMEOUT_MS) {
71
+ return run(["rev-parse", "--show-toplevel"], { env: C_LOCALE, timeout });
72
+ }
73
+ var git_spawn_sync = { GIT_TIMEOUT_MS, C_LOCALE, run, read, origin_url, toplevel };
74
+
7
75
  // scripts/lib/json-value.ts
8
76
  function parse_or_undefined(text) {
9
77
  try {
@@ -43,24 +111,10 @@ function read_if_readable(path5) {
43
111
  }
44
112
  var file_reader = { read_optional, read_file_or_empty, read_if_readable };
45
113
 
46
- // scripts/lib/spawn-exit.ts
47
- var SPAWN_ERROR_EXIT_CODE = 2;
48
- var SIGNAL_KILL_EXIT_CODE = 1;
49
- function resolve_spawn_exit(executable, result) {
50
- if (result.exitCode !== void 0) return result.exitCode;
51
- if (result.isTerminated === true) return SIGNAL_KILL_EXIT_CODE;
52
- console.error(`Failed to execute ${executable}: ${result.shortMessage ?? "spawn failed"}`);
53
- return SPAWN_ERROR_EXIT_CODE;
54
- }
55
- function read_spawn_stdout(result) {
56
- return result.stdout ?? "";
57
- }
58
-
59
114
  // scripts/version/kit-descriptor.ts
60
115
  var KIT_PACKAGE_NAME = "@joshuafolkken/kit";
61
116
 
62
117
  // scripts/doctor/doctor-consumer.ts
63
- import { execaSync } from "execa";
64
118
  import { z } from "zod";
65
119
  var NODE_MODULES = "node_modules";
66
120
  var SETTINGS_PATH = path.join(".claude", "settings.json");
@@ -68,7 +122,7 @@ var CLAUDE_MD = "CLAUDE.md";
68
122
  var PLUGIN_ID = "kit@kit";
69
123
  var CLAUDE_MD_POINTER = `@${NODE_MODULES}/${KIT_PACKAGE_NAME}/dist/${CLAUDE_MD}`;
70
124
  var SECRETLINT_BIN = path.join(NODE_MODULES, ".bin", "secretlint");
71
- var GIT_TIMEOUT_MS = 2e3;
125
+ var GIT_TIMEOUT_MS2 = 2e3;
72
126
  var manifest_schema = z.object({
73
127
  name: z.string().optional(),
74
128
  dependencies: z.record(z.string(), z.string()).optional(),
@@ -102,11 +156,9 @@ function is_plugin_declared(root) {
102
156
  return parsed.success && parsed.data.enabledPlugins?.[PLUGIN_ID] === true;
103
157
  }
104
158
  function configured_hooks_path(root) {
105
- const result = execaSync("git", ["-C", root, "config", "--get", "core.hooksPath"], {
106
- reject: false,
107
- timeout: GIT_TIMEOUT_MS
159
+ const value = git_spawn_sync.read(["-C", root, "config", "--get", "core.hooksPath"], {
160
+ timeout: GIT_TIMEOUT_MS2
108
161
  });
109
- const value = read_spawn_stdout(result).trim();
110
162
  return value === "" ? void 0 : value;
111
163
  }
112
164
  function claude_md_state(root) {
@@ -166,6 +218,7 @@ function report_consumer_setup(root) {
166
218
  var doctor_consumer = {
167
219
  claude_md_line,
168
220
  claude_md_state,
221
+ configured_hooks_path,
169
222
  hooks_path_line,
170
223
  is_kit_consumer,
171
224
  is_plugin_declared,
@@ -246,7 +299,7 @@ function resolve_package_bin(base_directory, package_name, bin_name) {
246
299
  }
247
300
 
248
301
  // scripts/josh/josh-logic.ts
249
- import { execaSync as execaSync3 } from "execa";
302
+ import { execaSync as execaSync2 } from "execa";
250
303
 
251
304
  // scripts/josh/command-suggest.ts
252
305
  var MAX_SUGGESTION_DISTANCE = 3;
@@ -1255,7 +1308,7 @@ var PROJECT_COMMANDS = {
1255
1308
  },
1256
1309
  "registry:migrate": {
1257
1310
  script: "scripts/registry-migration/migrate.ts",
1258
- description: "Migrate a kit-only project from GitHub Packages to public npm",
1311
+ description: "Migrate a project from GitHub Packages to public npm",
1259
1312
  category: "Project",
1260
1313
  reference: ["", "developer", ["files", "network", "processes"]]
1261
1314
  },
@@ -1441,7 +1494,7 @@ var WORKFLOW_COMMANDS = {
1441
1494
  script: "scripts/issue/measure-rerun-cli.ts",
1442
1495
  description: "Re-run a merged issue\u2019s baseline command and print the before/after pair",
1443
1496
  category: "Workflow",
1444
- reference: ["<path>", "automation", ["processes", "files"]]
1497
+ reference: ["<issue-number>", "automation", ["network", "processes", "files"]]
1445
1498
  },
1446
1499
  // A script rather than an `sh -c` chain, because it has a precondition to enforce: run inside a
1447
1500
  // linked work tree it would hijack the default branch from every other one (joshuafolkken/kit#1535).
@@ -1700,7 +1753,6 @@ var repo_origin = {
1700
1753
  };
1701
1754
 
1702
1755
  // scripts/josh/run-github-prerequisite.ts
1703
- import { execaSync as execaSync2 } from "execa";
1704
1756
  var GITHUB_RUN_COMMANDS = /* @__PURE__ */ new Set([
1705
1757
  "run:entry",
1706
1758
  "run:prep",
@@ -1714,11 +1766,8 @@ function explanation(root, command) {
1714
1766
  if (!existsSync3(path3.join(root, ".git"))) {
1715
1767
  return `${command} requires Git and a GitHub origin. Run git init and add a GitHub origin first.`;
1716
1768
  }
1717
- const result = execaSync2("git", ["config", "--get", "remote.origin.url"], {
1718
- cwd: root,
1719
- reject: false
1720
- });
1721
- if (result.exitCode === 0 && repo_origin.parse_origin_url(result.stdout)) return void 0;
1769
+ const url = git_spawn_sync.origin_url(root);
1770
+ if (url !== void 0 && repo_origin.parse_origin_url(url)) return void 0;
1722
1771
  return `${command} requires a GitHub origin. Add an origin pointing to GitHub first.`;
1723
1772
  }
1724
1773
  var run_github_prerequisite = { explanation };
@@ -1821,7 +1870,7 @@ function should_use_shell(executable) {
1821
1870
  return process.platform === "win32" && executable !== process.execPath;
1822
1871
  }
1823
1872
  function spawn_script(tsx_executable, script_arguments) {
1824
- const result = execaSync3(tsx_executable, script_arguments, {
1873
+ const result = execaSync2(tsx_executable, script_arguments, {
1825
1874
  stdio: "inherit",
1826
1875
  shell: should_use_shell(tsx_executable),
1827
1876
  reject: false
@@ -1830,7 +1879,7 @@ function spawn_script(tsx_executable, script_arguments) {
1830
1879
  }
1831
1880
  function run_shell_command(shell, extra) {
1832
1881
  const [executable = "", ...rest_arguments] = shell;
1833
- const result = execaSync3(executable, [...rest_arguments, ...extra], {
1882
+ const result = execaSync2(executable, [...rest_arguments, ...extra], {
1834
1883
  stdio: "inherit",
1835
1884
  reject: false
1836
1885
  });
@@ -565,7 +565,13 @@ var agent_session_environment = {
565
565
  function message_of(error) {
566
566
  return error instanceof Error ? error.message : String(error);
567
567
  }
568
- var error_text = { message_of };
568
+ var DEBUG_ENV_KEY = "JOSH_DEBUG";
569
+ function trace_swallowed(where, error) {
570
+ if ((process.env[DEBUG_ENV_KEY] ?? "").trim() === "") return;
571
+ process.stderr.write(`josh debug: ${where}: ${message_of(error)}
572
+ `);
573
+ }
574
+ var error_text = { message_of, trace_swallowed };
569
575
 
570
576
  // scripts/gh/git-gh-exec.ts
571
577
  import { execa as execa2, execaSync } from "execa";
@@ -1009,18 +1015,23 @@ function is_package_entry(line) {
1009
1015
  function is_github_tarball_line(line) {
1010
1016
  return line.trimStart().startsWith("tarball: https://npm.pkg.github.com/");
1011
1017
  }
1012
- function clean_kit_line(line, version, integrities) {
1013
- if (!version) return line;
1018
+ function package_id(key) {
1019
+ const name = fix_gh_packages_logic.package_path_from_key(key);
1020
+ return `${name}@${fix_gh_packages_logic.package_version_from_key(key)}`;
1021
+ }
1022
+ function clean_scoped_line(line, id, integrities) {
1023
+ if (!id) return line;
1014
1024
  if (is_github_tarball_line(line)) return void 0;
1015
1025
  const cleaned = remove_flow_tarball(line);
1016
- const pair = integrities.get(version);
1026
+ const pair = integrities.get(id);
1017
1027
  if (pair === void 0) return cleaned;
1018
1028
  return cleaned.split(`integrity: ${pair[0]}`).join(`integrity: ${pair[1]}`);
1019
1029
  }
1020
- function next_kit_version(line, version) {
1021
- if (!is_package_entry(line)) return version;
1022
- const prefix = " '@joshuafolkken/kit@";
1023
- return line.startsWith(prefix) ? line.slice(prefix.length).split("'", 1)[0] ?? "" : "";
1030
+ function next_scoped_id(line, id) {
1031
+ if (!is_package_entry(line)) return id;
1032
+ const prefix = ` '${SCOPE}/`;
1033
+ if (!line.startsWith(prefix)) return "";
1034
+ return package_id(line.slice(" '".length).split("'", 1)[0] ?? "");
1024
1035
  }
1025
1036
  function integrity_pair(old_integrity, npm_integrity) {
1026
1037
  if (old_integrity === void 0 || npm_integrity === void 0) return void 0;
@@ -1029,24 +1040,24 @@ function integrity_pair(old_integrity, npm_integrity) {
1029
1040
  function lock_integrities(lockfile, npm_integrities) {
1030
1041
  const packages = fix_gh_packages_logic.parse_lockfile_packages(lockfile);
1031
1042
  const pairs = /* @__PURE__ */ new Map();
1032
- const kit_entries = Object.entries(packages).filter(([key]) => key.startsWith(`${SCOPE}/kit@`));
1033
- for (const [key, entry] of kit_entries) {
1034
- const version = fix_gh_packages_logic.package_version_from_key(key);
1035
- const pair = integrity_pair(entry.resolution?.integrity, npm_integrities.get(version));
1036
- if (pair !== void 0) pairs.set(version, pair);
1043
+ const scoped_entries = Object.entries(packages).filter(([key]) => key.startsWith(`${SCOPE}/`));
1044
+ for (const [key, entry] of scoped_entries) {
1045
+ const id = package_id(key);
1046
+ const pair = integrity_pair(entry.resolution?.integrity, npm_integrities.get(id));
1047
+ if (pair !== void 0) pairs.set(id, pair);
1037
1048
  }
1038
1049
  return pairs;
1039
1050
  }
1040
1051
  function push_if_defined(lines, cleaned) {
1041
1052
  if (cleaned !== void 0) lines.push(cleaned);
1042
1053
  }
1043
- function rewrite_kit_lockfile(lockfile, npm_integrities) {
1044
- let kit_version = "";
1054
+ function rewrite_scoped_lockfile(lockfile, npm_integrities) {
1055
+ let id = "";
1045
1056
  const lines = [];
1046
1057
  const integrities = lock_integrities(lockfile, npm_integrities);
1047
1058
  for (const line of lockfile.split("\n")) {
1048
- kit_version = next_kit_version(line, kit_version);
1049
- const cleaned = clean_kit_line(line, kit_version, integrities);
1059
+ id = next_scoped_id(line, id);
1060
+ const cleaned = clean_scoped_line(line, id, integrities);
1050
1061
  push_if_defined(lines, cleaned);
1051
1062
  }
1052
1063
  return lines.join("\n");
@@ -1076,7 +1087,7 @@ function previous_registry(project_npmrc, user_npmrc) {
1076
1087
  }
1077
1088
  function plan(project_npmrc, user_npmrc, lockfile) {
1078
1089
  const packages = scoped_packages(lockfile);
1079
- const blocked = packages.filter((name) => name !== `${SCOPE}/kit`);
1090
+ const blocked = [];
1080
1091
  if (has_duplicate_mapping(project_npmrc, user_npmrc)) blocked.push("duplicate registry mappings");
1081
1092
  const unsupported = unsupported_registry(project_npmrc);
1082
1093
  if (unsupported !== void 0) blocked.push(unsupported);
@@ -1088,7 +1099,7 @@ var migrate_logic = {
1088
1099
  plan,
1089
1100
  github_tarballs,
1090
1101
  is_github_tarball,
1091
- rewrite_kit_lockfile,
1102
+ rewrite_scoped_lockfile,
1092
1103
  scoped_versions
1093
1104
  };
1094
1105
 
@@ -1276,6 +1287,7 @@ var version_targets = {
1276
1287
  var FAILURE_EXIT_CODE = 1;
1277
1288
  var ALREADY_UP_TO_DATE = "Already up to date";
1278
1289
  var NO_QUARANTINE_MINUTES2 = 0;
1290
+ var UPGRADE_TIMEOUT_MS = 6e5;
1279
1291
  function read_release_hold(package_config, latest, versions) {
1280
1292
  if (versions.every((version) => version === void 0 || version === latest)) return void 0;
1281
1293
  const minimum_age_minutes = release_age.read_nearest_minimum_release_age(process.cwd());
@@ -1360,7 +1372,11 @@ function run_check(config) {
1360
1372
  );
1361
1373
  }
1362
1374
  function run_upgrade_command(command) {
1363
- const result = execaSync4("sh", ["-c", command], { stdio: "inherit", reject: false });
1375
+ const result = execaSync4("sh", ["-c", command], {
1376
+ stdio: "inherit",
1377
+ reject: false,
1378
+ timeout: UPGRADE_TIMEOUT_MS
1379
+ });
1364
1380
  return result.exitCode ?? FAILURE_EXIT_CODE;
1365
1381
  }
1366
1382
  function run_all_upgrade_commands(commands) {
@@ -80,8 +80,9 @@ export const unicorn_rules = {
80
80
  'unicorn/custom-error-definition': 'error',
81
81
  // throw new Error()の形式を強制
82
82
  'unicorn/throw-new-error': 'error',
83
- // 空の配列をチェック
84
- 'unicorn/no-empty-file': 'error',
83
+ // 空ファイルを禁止する。コメントだけのファイルは許可する: `sv create` の足場 `src/lib/index.ts` は
84
+ // コメント 1 行だけで、手を加えていないプロジェクトで lint が落ちてしまうため(#3069)
85
+ 'unicorn/no-empty-file': ['error', { allowComments: true }],
85
86
  // 静的なみずからのみのクラスを禁止
86
87
  'unicorn/no-static-only-class': 'error',
87
88
  // this別名を禁止(arrow functionを使うべき)
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.1094.0",
2
+ "version": "1.1128.0",
3
3
  "name": "@joshuafolkken/kit",
4
4
  "description": "Development toolkit for AI-assisted projects: formatting, AI assistant rules and a Git/GitHub Issue workflow for any repository, plus lint, type check, tests and hooks for Node projects",
5
5
  "keywords": [
@@ -59,6 +59,7 @@
59
59
  ".ncurc.json",
60
60
  ".prettierignore",
61
61
  "pnpm-workspace.yaml",
62
+ ".pnpmfile.mjs",
62
63
  "tsconfig.sonar.json",
63
64
  "playwright.config.ts",
64
65
  "!**/*.test.ts",
@@ -161,6 +162,7 @@
161
162
  "peerDependencies": {
162
163
  "@eslint/compat": "^2.1.1",
163
164
  "@eslint/js": "^10.0.1",
165
+ "@ianvs/prettier-plugin-sort-imports": "^4.7.1",
164
166
  "@playwright/test": ">=1.0.0",
165
167
  "@stylistic/eslint-plugin": "^5.10.0",
166
168
  "eslint": "^10.0.0",
@@ -171,6 +173,9 @@
171
173
  "eslint-plugin-sonarjs": "^4.2.1",
172
174
  "eslint-plugin-unicorn": "^76.0.0",
173
175
  "globals": "^17.12.0",
176
+ "prettier": "^3.9.9",
177
+ "prettier-plugin-svelte": "^4.1.1",
178
+ "prettier-plugin-tailwindcss": "^0.8.1",
174
179
  "typescript": "^6.0.3",
175
180
  "typescript-eslint": "^8.70.1"
176
181
  },
@@ -184,6 +189,9 @@
184
189
  "@eslint/js": {
185
190
  "optional": true
186
191
  },
192
+ "@ianvs/prettier-plugin-sort-imports": {
193
+ "optional": true
194
+ },
187
195
  "@stylistic/eslint-plugin": {
188
196
  "optional": true
189
197
  },
@@ -211,6 +219,15 @@
211
219
  "globals": {
212
220
  "optional": true
213
221
  },
222
+ "prettier": {
223
+ "optional": true
224
+ },
225
+ "prettier-plugin-svelte": {
226
+ "optional": true
227
+ },
228
+ "prettier-plugin-tailwindcss": {
229
+ "optional": true
230
+ },
214
231
  "typescript": {
215
232
  "optional": true
216
233
  },
@@ -256,7 +273,6 @@
256
273
  "jsonc-parser": "^3.3.1",
257
274
  "ora": "^9.4.1",
258
275
  "semver": "^7.8.5",
259
- "strip-json-comments": "^5.0.3",
260
276
  "tsx": "^4.23.15",
261
277
  "zod": "^4.6.5"
262
278
  },
@@ -28,11 +28,9 @@ minimumReleaseAgeExclude:
28
28
 
29
29
  overrides:
30
30
  svelte: ^5.55.7
31
- devalue: ^5.8.1
32
- # Indirect deps a within-range re-resolution could not lift past their parents' pins, floored at the
33
- # smallest release clearing each OSV advisory (joshuafolkken/kit#2200; user-approved 2026-09-21 to
34
- # override indirect packages). Carets so `josh latest`'s re-resolution keeps them current within the
35
- # major without reintroducing the advisory.
31
+ # An indirect dep a within-range re-resolution could not lift past its parents' pins, floored at the
32
+ # smallest release clearing its OSV advisory (joshuafolkken/kit#2200; user-approved 2026-09-21 to
33
+ # override indirect packages). A caret so `josh latest`'s re-resolution keeps it current within the
34
+ # major without reintroducing the advisory. The devalue, postcss and nanoid floors were removed once
35
+ # their parents' ranges exceeded them (joshuafolkken/kit#3091).
36
36
  vite: ^8.0.16 # OSV — vite 8.0.8 → 8.0.16
37
- postcss: ^8.5.23 # OSV — postcss 8.5.16 → 8.5.23
38
- nanoid: ^3.3.18 # OSV — nanoid 3.3.15 → 3.3.18
@@ -0,0 +1,17 @@
1
+ # ワークフロー用語集
2
+
3
+ **これは定義集であり、規則を定める場所ではない。** 各語は 1〜2 行の定義と、その語の本文がある単一ソースへのポインタだけを持つ。手順・条件・数値は指し先が持ち、ここでは言い換えない — 言い換えた行は指し先より先に古くなる(joshuafolkken/kit#3080)。
4
+
5
+ `scripts/document/workflow-glossary.test.ts` が、下の主要語が定義されていることと、各ポインタが実在する節に解決することを検査する。
6
+
7
+ - **lane** — `backlogrun` が子 Issue を並行実行するための、専用ブランチ・`.env`・ポートを持つ git worktree。実装・ゲート・レビューは並行し、マージは直列。→ `.claude/skills/workflow-commands/backlogrun-lanes.md` → "Lanes — running more than one child at a time"
8
+ - **cut** — 実行中のプロセスを意図して終わらせ、新しいプロセスが同じ作業を引き継ぐ境界。レーン子のゲート前の cut と、`backlogrun` のセッション cut がある。→ `.claude/skills/workflow-commands/pre-gate-cut.md` → "The pre-gate cut"、`.claude/skills/workflow-commands/backlogrun-progress.md` → "The hand-off"
9
+ - **hold** — 1 つの作業ツリーを 1 つのランが占有しているという記録。`pnpm josh run:hold` が取り、`pnpm josh run:release` が外す。→ `.claude/skills/workflow-commands/working-tree-hold.md` → "The working-tree hold"
10
+ - **park** — `backlogrun` が自分で決められない子を `needs-decision` で止め、バッチ全体は止めずに次の子へ進むこと。→ `.claude/skills/workflow-commands/backlogrun-park.md` → "park and continue"
11
+ - **point of use** — 文書を入口ではなく、その文書に従うべき操作と同じターンで、その操作の直前に読むこと。→ `.claude/skills/workflow-commands/SKILL.md` → "Four documents are read at the point of use, not at the entry"
12
+ - **entry read** — コマンド起動時に読む文書の集合。`pnpm josh read:set` がその集合と費用を答える。→ `.claude/skills/workflow-commands/SKILL.md` → "Which file to read"
13
+ - **oracle** — 機械的に読める入力だけから規則の答えを計算するコマンド。一覧は `pnpm josh oracle:list`。→ `prompts/collaboration-workflow/residency.md` → "第 0 問"
14
+ - **interrupt** — WIP 上限を超えても起票できる、3 条件で決まる発見。別パッケージ起因の上流起票(割り込み Issue)とは別の区分。→ `prompts/collaboration-workflow/wip-cap.md` → "割り込み起票"、`prompts/collaboration-workflow/upstream-interrupt.md` → "別パッケージ起因の問題は割り込み Issue で対応する"
15
+ - **Tier** — 判断点の 3 区分。A は可逆で自分で決める、B は拮抗していて人に聞く、C は不可逆・共有状態で明示指示が要る。→ `CLAUDE.md` → "Decision autonomy"、`prompts/collaboration-workflow/operating-rules.md` → "意思決定の自律ポリシー"
16
+ - **carry** — `backlogrun` の 1 回の起動の予算と進捗を、セッション cut をまたいで引き継ぐ記録(`pnpm josh run:carry`)。→ `.claude/skills/workflow-commands/backlogrun-steps.md` → "The session cut is inside the invocation"
17
+ - **wave** — エピックの子をまとめて並行実行する組。仕組みではなく、依存宣言で表す形。→ `.claude/skills/epic-commands/SKILL.md` → "Execution waves"
@@ -76,7 +76,7 @@ Issue には次の要素を必ず含める。
76
76
  - **互換性を壊す変更は影響を本文で宣言する。** 既存の利用者、API、設定の契約を変える場合は、`## 背景` の直下に `- 互換性: 破壊的変更` を書き、廃止対象と影響を説明する。移行措置や事前案内があっても破壊的変更なら宣言する。この宣言があれば `pnpm josh issue:file` が `breaking-change` ラベルを同じ作成リクエストに付ける。互換性を保つ変更には付けない。影響が曖昧なら起票文案で対象の利用者と契約を明確にしてから分類する
77
77
  - **本文が宣言する分類ラベルは `pnpm josh issue:file` がすべて起票時に付ける。** `bug`、`enhancement`、`breaking-change` は組み合わせて付くことがある。`depth`・`route` などのラベルと併せて 1 回の作成リクエストで付け、宣言が無いとき(`issue:lint` の `labels: none`)は分類ラベルを付けない。Issue が `enhancement` と `breaking-change` の両方を持つとき、PR のリリース分類は `breaking-change` 一つにする。Issue の目的の分類と PR のリリース分類を区別する
78
78
  - **`## 発火点`** には、その規則が破れる瞬間に最初に呼ばれるツールコール名を 1 つ書く。名前は `prompts/collaboration-workflow/rule-delivery.md` の配送表に載る、フックで配送可能なツール(`Bash` / `Edit` / `Read` / `Write` / `AskUserQuestion`)と突き合わせる。**表に無い名前**(そもそもツールコール名でない)と**不一致**(既知のツールだが配送できない)は区別して印字され、joshuafolkken/kit#2201 の「規則は正しいが名指ししたコールが実際に破れるコールの 1 つ後ろ」を起票時に検出する
79
- - **`## ベースライン`** は **「コマンド + 値」** で書く。``- `<測定コマンド>` → <現在の値>`` の形に限り、自然文だけの測定説明は受け付けない(再実行できないため)。マージ後に `pnpm josh measure:rerun` が同じコマンドをやり直し、**before / after の対**を印字する。値が動かなかったとき、反証された前提として `docs/maintainers/observations/` の、その時点のブランチが指す Issue のファイルに 1 行追記される(既存の append-only 台帳を使い、別の台帳は作らない)
79
+ - **`## ベースライン`** は **「コマンド + 値」** で書く。``- `<測定コマンド>` → <現在の値>`` の形に限り、自然文だけの測定説明は受け付けない(再実行できないため)。マージ後に `pnpm josh measure:rerun <N>` が同じコマンドをやり直し(本文は shell として実行されるため、作者が `OWNER` / `MEMBER` / `COLLABORATOR` の Issue に限る)、**before / after の対**を印字する。値が動かなかったとき、反証された前提として `docs/maintainers/observations/` の、その時点のブランチが指す Issue のファイルに 1 行追記される(既存の append-only 台帳を使い、別の台帳は作らない)
80
80
  - **`## 再現`** は **「コマンド + 実際の出力」** で書く。コマンドを backtick、出力をフェンス(``` または ~~~)で囲む。自然文の「確認した」は再実行できないため受け付けない(`## ベースライン` と同じ理由)。読みだけの起票を起票時に弾くためである
81
81
  - **検査は `pnpm josh issue:lint <path>` が行う。** 対象判定・3 見出しの有無・発火点の配送可否・ベースラインが「コマンド + 値」か・再現が「コマンド + 実際の出力」かと、起票時に必要な分類ラベルを、起票前の本文ファイルからまとめて答える(`pnpm josh issue:file` は起票前に同じ検査を行い、問題があれば起票しない)
82
82
 
@@ -27,7 +27,7 @@
27
27
 
28
28
  PR マージ・ブランチ削除・force push・共有ブランチへの push・外部通知の追加送信・リポジトリ設定の変更など、**共有状態に影響する操作はその場でユーザーに明示指示されたものだけ実行する**。
29
29
 
30
- - `fullrun` の auto-merge は `fullrun` の指示自体に含まれるため許可される(本文は [`followup.md`](../../.claude/skills/workflow-commands/followup.md))。それ以外の状況で勝手にマージしてはならない
30
+ - `fullrun` と `backlogrun` の auto-merge は、それぞれの指示自体に含まれるため許可される(本文は [`followup.md`](../../.claude/skills/workflow-commands/followup.md)、`backlogrun` の子への継承は [`backlogrun-child.md`](../../.claude/skills/workflow-commands/backlogrun-child.md))。`prrun` はマージを認可しない。それ以外の状況で勝手にマージしてはならない
31
31
  - `kickoff` / `pnpm josh followup` 単独実行は文書化されたスコープで終了する。PR が OPEN のまま完了したら状態を報告して停止する
32
32
  - 「チェックが全部 green だから次のステップに進む」は承認ではない
33
33
  - **`gh pr merge` の直接実行は kit 配布の `.claude/settings.json` の `permissions.deny` で機械的に遮断されている。** パターンの一覧はそのファイルが一次情報であり、ここでは書き写さない。 `fullrun` の auto-merge は `pnpm josh followup` が node スクリプト内部から gh を起動するため影響を受けない — Bash マッチャに見えるのは `pnpm josh …` だけである。**ただし deny は実装であって規則ではない** — パターンが取りこぼす綴りを禁じているのは本節の規則のほうである
@@ -72,3 +72,12 @@
72
72
  - **導線文書に規則を書き戻さない。** そこに書かれた規則は、次の改訂で更新し忘れる 4 つ目の置き場になる
73
73
  - `scripts/document/ai-document-pointers.test.ts` が機械的に守る。導線文書に規則本体が再出現した場合、導線の一文が消えた場合、`CLAUDE.md` が単一ソースであることの記述が消えた場合に落ちる
74
74
  - 経緯は `docs/maintainers/principles-rationale.md` → "Why AGENTS and GEMINI are pointers"、`@CLAUDE.md` 行と他ツールでの未検証は `docs/maintainers/principles-rationale.md` → "The include line, and what has not been verified"
75
+
76
+ ### Claude Code 以外のエージェントでの読み替え
77
+
78
+ `CLAUDE.md` は Claude Code 向けに書かれており、その機能を名指しする。Codex・Gemini CLI など別のエージェントは次のように読み替える。導線文書が持つのはツール固有の 1 行だけで、共通の読み替えはこの節にしか無い(joshuafolkken/kit#3079)。
79
+
80
+ - **フック**: フックが走らない、または出力が見えないツールでは、フックが届ける規則を自分で適用する。その一覧は手書きせず、[`rule-delivery.md`](./rule-delivery.md) →「配送されている規則」の表を正とする — 表の各行が、そのツールでは自分で守る規則である。表の外でフックが担う 3 つも同じく自分で行う — 最初の実行時コード編集の前に Step 0 の作業サマリを提示する、編集ごとの整形フックに頼らず編集後に `pnpm josh lint:related` と `pnpm josh cspell:dot` を走らせる、`JOSH_SESSION_LANG` は注入を待たずに `.env` から解決する。フックの全体は `.claude/settings.json` の `hooks` が正である
81
+ - **Skill・`/verify-ui`・`/code-review`**: `CLAUDE.md` が skill のロードやサブエージェントでの実行を指示する箇所では、その skill の `SKILL.md` を読み、自分のセッションで従う
82
+ - **`.claude/settings.json` の deny list** は効かない。それが裏付ける規則 — 指示なしのコミット・マージ・ステージングその他の共有状態変更をしない — はそのまま拘束する
83
+ - **`AskUserQuestion`** は、ユーザーに平文で尋ねることを指す
@@ -29,6 +29,7 @@
29
29
  | 引き金つき配送 — 規則を効く瞬間に届ける | [`rule-delivery.md`](./collaboration-workflow/rule-delivery.md) |
30
30
  | コマンド出力が文脈へ持ち込む量の上限 | [`output-bounds.md`](./collaboration-workflow/output-bounds.md) |
31
31
  | 運用ルール | [`operating-rules.md`](./collaboration-workflow/operating-rules.md) |
32
+ | 用語集 — lane・cut・hold・park などの定義と単一ソース | [`glossary.md`](./collaboration-workflow/glossary.md) |
32
33
 
33
34
  **どの 1 本を開けばよいかを決めるのに必要なのは、この索引だけである。** バイト数はここに書かない — 手で保守した数字は本文より先に古くなり、古い数字は無いより悪い。実サイズは `ls -l prompts/collaboration-workflow/` が答える。
34
35