@joshuafolkken/kit 1.972.0 → 1.983.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 (87) hide show
  1. package/.claude/skills/epic-commands/SKILL.md +6 -5
  2. package/.claude/skills/workflow-commands/SKILL.md +9 -9
  3. package/.claude/skills/workflow-commands/background-commands.md +1 -1
  4. package/.claude/skills/workflow-commands/fullrun-steps.md +8 -8
  5. package/.claude/skills/workflow-commands/fullrun.md +1 -0
  6. package/.claude/skills/workflow-commands/halfrun.md +16 -12
  7. package/.claude/skills/workflow-commands/issue-comments.md +1 -1
  8. package/.claude/skills/workflow-commands/issue-scout.md +21 -22
  9. package/.claude/skills/workflow-commands/kickoff.md +8 -9
  10. package/.claude/skills/workflow-commands/observation-filing.md +9 -10
  11. package/.claude/skills/workflow-commands/prerequisite.md +7 -6
  12. package/.claude/skills/workflow-commands/retrospective.md +5 -5
  13. package/.claude/skills/workflow-commands/rule-residency.md +2 -2
  14. package/.claude/skills/workflow-commands/split-assessment.md +4 -3
  15. package/.claude/skills/workflow-commands/target-repository.md +7 -6
  16. package/.claude/skills/workflow-commands/working-tree-hold.md +16 -1
  17. package/README.md +24 -20
  18. package/dist/hooks/batch-guard.js +4 -4
  19. package/dist/hooks/{chunk-ZPLXLJ7O.js → chunk-47SPMGOD.js} +16 -1
  20. package/dist/hooks/{chunk-BVMSPG3M.js → chunk-5JX6HXDX.js} +3 -3
  21. package/dist/hooks/{chunk-KQG4776P.js → chunk-APVOACVT.js} +1 -1
  22. package/dist/hooks/{chunk-2K52BRWV.js → chunk-ASUZGZFT.js} +2 -2
  23. package/dist/hooks/{chunk-CRGJTD6E.js → chunk-ERXMJJOV.js} +1 -1
  24. package/dist/hooks/{chunk-WWTMHHZU.js → chunk-IM3KM25Y.js} +61 -30
  25. package/dist/hooks/{chunk-BNWIOJFU.js → chunk-LBXQHXMC.js} +138 -358
  26. package/dist/hooks/{chunk-NXL3SBXY.js → chunk-P3UX7SFN.js} +2 -2
  27. package/dist/hooks/{chunk-F6OM6SIG.js → chunk-RFPHKU7C.js} +12 -12
  28. package/dist/hooks/{chunk-ZYYSBNR6.js → chunk-ZT65LR3U.js} +4 -4
  29. package/dist/hooks/codex-hook-adapter.js +10 -10
  30. package/dist/hooks/duplicate-read-guard.js +5 -5
  31. package/dist/hooks/format-edited.js +2 -2
  32. package/dist/hooks/investigation-guard.js +5 -5
  33. package/dist/hooks/pretool-guard.js +9 -9
  34. package/dist/hooks/stop-guard.js +4 -4
  35. package/dist/josh.js +16 -1
  36. package/package.json +2 -2
  37. package/prompts/collaboration-workflow/epic-bundle.md +8 -8
  38. package/prompts/collaboration-workflow/issue-template.md +5 -5
  39. package/prompts/collaboration-workflow/rule-delivery.md +43 -30
  40. package/prompts/collaboration-workflow/upstream-interrupt.md +1 -1
  41. package/prompts/collaboration-workflow/wip-cap.md +3 -3
  42. package/prompts/review.md +11 -9
  43. package/scripts/ci/pr-classification.ts +13 -12
  44. package/scripts/delegation/delegation-policy.ts +9 -9
  45. package/scripts/document/document-byte-budget.ts +1 -1
  46. package/scripts/git/issue-labels.ts +52 -5
  47. package/scripts/init/init-bootstrap.ts +92 -0
  48. package/scripts/init/init-install.ts +4 -1
  49. package/scripts/init/init-logic-workspace.ts +1 -1
  50. package/scripts/init/init.ts +23 -5
  51. package/scripts/init/start-plan.ts +1 -1
  52. package/scripts/init/start-steps.ts +5 -28
  53. package/scripts/issue/issue-file-cli.ts +188 -0
  54. package/scripts/issue/issue-file.ts +192 -0
  55. package/scripts/issue/issue-lint-cli.ts +1 -1
  56. package/scripts/issue/issue-scout-cli.ts +41 -97
  57. package/scripts/issue/issue-scout-closed.ts +102 -0
  58. package/scripts/josh/__snapshots__/josh-command-map.test.ts.snap +9 -1
  59. package/scripts/josh/josh-command-map.ts +1 -0
  60. package/scripts/josh/josh-commands-issue.ts +11 -0
  61. package/scripts/josh/josh-commands-project.ts +5 -1
  62. package/scripts/propagate/propagate-run.ts +1 -0
  63. package/scripts/propagate/propagate-select.ts +72 -0
  64. package/scripts/propagate/propagate-targets.ts +5 -3
  65. package/scripts/propagate/propagate.ts +86 -24
  66. package/scripts/repo/repository-labels.ts +91 -0
  67. package/scripts/rules/bash-triggers.ts +19 -6
  68. package/scripts/rules/delivered-rules.ts +28 -32
  69. package/scripts/rules/direct-filing.ts +38 -0
  70. package/scripts/rules/filing-cap.ts +11 -8
  71. package/scripts/rules/issue-fold.ts +4 -4
  72. package/scripts/rules/oracle-consulted.ts +4 -4
  73. package/scripts/rules/oracle-firing.ts +13 -16
  74. package/scripts/rules/rule-body-guard.ts +6 -9
  75. package/scripts/rules/stop-rules.ts +3 -2
  76. package/scripts/run/run-entry-cli.ts +34 -1
  77. package/scripts/run/run-halfrun-resume.ts +104 -0
  78. package/scripts/run/run-hold-cli.ts +27 -4
  79. package/scripts/run/run-hold.ts +11 -0
  80. package/scripts/security/security-audit.ts +12 -1
  81. package/scripts/sync/sync.ts +6 -0
  82. package/scripts/test/pilot-files.ts +0 -1
  83. package/scripts/version/fresh-metadata-cache.ts +36 -0
  84. package/scripts/version/latest-update.ts +2 -1
  85. package/scripts/rules/issue-bug-label.ts +0 -85
  86. package/scripts/rules/issue-filing-args.ts +0 -50
  87. package/scripts/rules/issue-scout.ts +0 -64
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  lane_guard_policy,
3
3
  time_batch_guard
4
- } from "./chunk-2K52BRWV.js";
4
+ } from "./chunk-ASUZGZFT.js";
5
5
  import {
6
6
  hook_decision
7
- } from "./chunk-KQG4776P.js";
7
+ } from "./chunk-APVOACVT.js";
8
8
 
9
9
  // scripts/hooks/batch-guard.ts
10
10
  import { text } from "node:stream/consumers";
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  time_batch_guard
3
- } from "./chunk-2K52BRWV.js";
3
+ } from "./chunk-ASUZGZFT.js";
4
4
  import {
5
5
  hook_decision
6
- } from "./chunk-KQG4776P.js";
6
+ } from "./chunk-APVOACVT.js";
7
7
  import {
8
8
  cost_blocks,
9
9
  cost_transcript,
10
10
  time_bundle_call,
11
11
  time_shell,
12
12
  time_spans
13
- } from "./chunk-ZPLXLJ7O.js";
13
+ } from "./chunk-47SPMGOD.js";
14
14
 
15
15
  // scripts/delegation/investigation-reads.ts
16
16
  import path from "node:path";
@@ -36,15 +36,15 @@ var DELEGATABLE_STEPS = [
36
36
  },
37
37
  {
38
38
  name: "followup-filing",
39
- // The late-run follow-up filing chain — issue:scout → file the Issue → epic:bundle → epic --add
40
- // — is a dependency chain `batch:guard` correctly keeps one call per step, and what makes it
41
- // expensive is the ~340k context it runs in at the tail of a run, not the step count
42
- // (joshuafolkken/kit#1892). A fresh unit runs the same chain at a small context, and the review
43
- // round cap already composed the finding text, so what the unit is handed is mechanical: run the
44
- // four commands and act on their deterministic answers. This is not `batch:guard`'s business —
45
- // the chain stays one call per step; delegation only moves it to a cheaper context.
46
- does: "run the late-run follow-up filing chain in an isolated unit \u2014 issue:scout, file the Issue, epic:bundle, epic --add \u2014 given the finding text the parent already composed, and return the new Issue number and the epic:bundle answer",
47
- verifier: "the parent reads the filed Issue from GitHub with `pnpm josh issue:state <new>`, not the unit's summary; a follow-up reported filed but not created is still absent, the way `epic-child`'s reported-done-but-not-merged child is still open. The finding text came from the parent and `issue:scout` / `epic:bundle` are deterministic, so the unit's work is the mechanical execution `issue:state` confirms"
39
+ // The late-run follow-up filing chain — `issue:file` (which scouts, lints, labels and runs
40
+ // epic:bundle itself, joshuafolkken/kit#2808) → epic --add — is a dependency chain `batch:guard`
41
+ // correctly keeps one call per step, and what makes it expensive is the ~340k context it runs in
42
+ // at the tail of a run, not the step count (joshuafolkken/kit#1892). A fresh unit runs the same
43
+ // chain at a small context, and the review round cap already composed the finding text, so what
44
+ // the unit is handed is mechanical: run the commands and act on their deterministic answers. This
45
+ // is not `batch:guard`'s business — delegation only moves the chain to a cheaper context.
46
+ does: "run the late-run follow-up filing chain in an isolated unit \u2014 issue:file (scout, lint, labels, epic:bundle), then epic --add \u2014 given the finding text the parent already composed, and return the new Issue number and the epic:bundle answer",
47
+ verifier: "the parent reads the filed Issue from GitHub with `pnpm josh issue:state <new>`, not the unit's summary; a follow-up reported filed but not created is still absent, the way `epic-child`'s reported-done-but-not-merged child is still open. The finding text came from the parent and `issue:file`'s steps are deterministic, so the unit's work is the mechanical execution `issue:state` confirms"
48
48
  },
49
49
  {
50
50
  name: "implementation-unit",
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  investigation_reads
3
- } from "./chunk-F6OM6SIG.js";
3
+ } from "./chunk-RFPHKU7C.js";
4
4
  import {
5
5
  lane_guard_policy
6
- } from "./chunk-2K52BRWV.js";
6
+ } from "./chunk-ASUZGZFT.js";
7
7
  import {
8
8
  hook_decision
9
- } from "./chunk-KQG4776P.js";
9
+ } from "./chunk-APVOACVT.js";
10
10
  import {
11
11
  json_value,
12
12
  time_spans
13
- } from "./chunk-ZPLXLJ7O.js";
13
+ } from "./chunk-47SPMGOD.js";
14
14
 
15
15
  // scripts/delegation/duplicate-read-guard.ts
16
16
  import { statSync } from "node:fs";
@@ -1,25 +1,25 @@
1
1
  #!/usr/bin/env tsx
2
2
  import {
3
3
  pretool_guard
4
- } from "./chunk-BNWIOJFU.js";
5
- import "./chunk-WWTMHHZU.js";
4
+ } from "./chunk-LBXQHXMC.js";
5
+ import "./chunk-IM3KM25Y.js";
6
6
  import {
7
7
  build_envelope,
8
8
  compose_context,
9
9
  format_edited_payload
10
- } from "./chunk-CRGJTD6E.js";
10
+ } from "./chunk-ERXMJJOV.js";
11
11
  import "./chunk-3V37IID6.js";
12
- import "./chunk-NXL3SBXY.js";
13
- import "./chunk-BVMSPG3M.js";
14
- import "./chunk-ZYYSBNR6.js";
15
- import "./chunk-F6OM6SIG.js";
16
- import "./chunk-2K52BRWV.js";
12
+ import "./chunk-P3UX7SFN.js";
13
+ import "./chunk-5JX6HXDX.js";
14
+ import "./chunk-ZT65LR3U.js";
15
+ import "./chunk-RFPHKU7C.js";
16
+ import "./chunk-ASUZGZFT.js";
17
17
  import {
18
18
  hook_decision
19
- } from "./chunk-KQG4776P.js";
19
+ } from "./chunk-APVOACVT.js";
20
20
  import {
21
21
  time_density_hook
22
- } from "./chunk-ZPLXLJ7O.js";
22
+ } from "./chunk-47SPMGOD.js";
23
23
  import "./chunk-WPALEIRX.js";
24
24
  import "./chunk-RKUAD3I6.js";
25
25
 
@@ -9,11 +9,11 @@ import {
9
9
  is_enabled,
10
10
  notice_refusal_path,
11
11
  refusal_path
12
- } from "./chunk-ZYYSBNR6.js";
13
- import "./chunk-F6OM6SIG.js";
14
- import "./chunk-2K52BRWV.js";
15
- import "./chunk-KQG4776P.js";
16
- import "./chunk-ZPLXLJ7O.js";
12
+ } from "./chunk-ZT65LR3U.js";
13
+ import "./chunk-RFPHKU7C.js";
14
+ import "./chunk-ASUZGZFT.js";
15
+ import "./chunk-APVOACVT.js";
16
+ import "./chunk-47SPMGOD.js";
17
17
  import "./chunk-WPALEIRX.js";
18
18
  import "./chunk-RKUAD3I6.js";
19
19
  export {
@@ -15,9 +15,9 @@ import {
15
15
  relative_to_root,
16
16
  resolve_invocations,
17
17
  select_invocation
18
- } from "./chunk-CRGJTD6E.js";
18
+ } from "./chunk-ERXMJJOV.js";
19
19
  import "./chunk-3V37IID6.js";
20
- import "./chunk-ZPLXLJ7O.js";
20
+ import "./chunk-47SPMGOD.js";
21
21
  import "./chunk-RKUAD3I6.js";
22
22
  export {
23
23
  ESLINT_DAEMON,
@@ -10,11 +10,11 @@ import {
10
10
  is_enabled,
11
11
  load_environment_file,
12
12
  refusal_path
13
- } from "./chunk-BVMSPG3M.js";
14
- import "./chunk-F6OM6SIG.js";
15
- import "./chunk-2K52BRWV.js";
16
- import "./chunk-KQG4776P.js";
17
- import "./chunk-ZPLXLJ7O.js";
13
+ } from "./chunk-5JX6HXDX.js";
14
+ import "./chunk-RFPHKU7C.js";
15
+ import "./chunk-ASUZGZFT.js";
16
+ import "./chunk-APVOACVT.js";
17
+ import "./chunk-47SPMGOD.js";
18
18
  import "./chunk-WPALEIRX.js";
19
19
  import "./chunk-RKUAD3I6.js";
20
20
  export {
@@ -3,16 +3,16 @@ import {
3
3
  pretool_guard,
4
4
  pretool_outcome,
5
5
  pretool_outcome_async
6
- } from "./chunk-BNWIOJFU.js";
7
- import "./chunk-WWTMHHZU.js";
6
+ } from "./chunk-LBXQHXMC.js";
7
+ import "./chunk-IM3KM25Y.js";
8
8
  import "./chunk-3V37IID6.js";
9
- import "./chunk-NXL3SBXY.js";
10
- import "./chunk-BVMSPG3M.js";
11
- import "./chunk-ZYYSBNR6.js";
12
- import "./chunk-F6OM6SIG.js";
13
- import "./chunk-2K52BRWV.js";
14
- import "./chunk-KQG4776P.js";
15
- import "./chunk-ZPLXLJ7O.js";
9
+ import "./chunk-P3UX7SFN.js";
10
+ import "./chunk-5JX6HXDX.js";
11
+ import "./chunk-ZT65LR3U.js";
12
+ import "./chunk-RFPHKU7C.js";
13
+ import "./chunk-ASUZGZFT.js";
14
+ import "./chunk-APVOACVT.js";
15
+ import "./chunk-47SPMGOD.js";
16
16
  import "./chunk-WPALEIRX.js";
17
17
  import "./chunk-RKUAD3I6.js";
18
18
  export {
@@ -19,20 +19,20 @@ import {
19
19
  run_hold,
20
20
  run_invocation,
21
21
  run_watcher_guard
22
- } from "./chunk-WWTMHHZU.js";
22
+ } from "./chunk-IM3KM25Y.js";
23
23
  import {
24
24
  session_language
25
25
  } from "./chunk-6V5OPIUU.js";
26
26
  import {
27
27
  hook_decision,
28
28
  lane_child_marker
29
- } from "./chunk-KQG4776P.js";
29
+ } from "./chunk-APVOACVT.js";
30
30
  import {
31
31
  PROJECT_ROOT,
32
32
  stamp_file,
33
33
  time_density_hook,
34
34
  time_hook_transcript
35
- } from "./chunk-ZPLXLJ7O.js";
35
+ } from "./chunk-47SPMGOD.js";
36
36
  import "./chunk-WPALEIRX.js";
37
37
  import "./chunk-RKUAD3I6.js";
38
38
 
@@ -1161,7 +1161,7 @@ function build_citation_reason(references) {
1161
1161
  const command = `pnpm josh issue:cite ${issue_citation.cite_arguments(references).join(" ")}`;
1162
1162
  return `\u26D4 issue citation: your reply names an Issue as a bare \`#N\` (${numbers}). Run \`${command}\` to print the paste-ready citation lines, then print the corrected citation lines alone \u2014 do not repeat your previous reply. ${ISSUE_CITATION_REASON}`;
1163
1163
  }
1164
- 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:scout "<title>"`, file it, run `pnpm josh epic:bundle <new>`, then end with the one-line citation of what was filed \u2014 do not repeat your previous reply. If it is not worth filing after all, say so in one line instead.';
1164
+ 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.';
1165
1165
  var HEADLESS_WAIT_MARKER = "\u26D4 headless parent:";
1166
1166
  var HEADLESS_REFUSAL_CAP = 3;
1167
1167
  var HEADLESS_WAIT_CALLS = ['"command":"pnpm josh lane:await', '"command":"pnpm josh run:progress'];
package/dist/josh.js CHANGED
@@ -447,6 +447,16 @@ var ISSUE_COMMANDS = {
447
447
  description: "Post one comment to an issue from a file, so no shell expands the body",
448
448
  category: "AI tools",
449
449
  reference: ["<issue> --body <text> | --body-file <path>", "automation", ["network"]]
450
+ },
451
+ "issue:file": {
452
+ script: "scripts/issue/issue-file-cli.ts",
453
+ description: "File an Issue with every filing step: lint, Origin, duplicate scout, labels, then epic:bundle",
454
+ category: "AI tools",
455
+ reference: [
456
+ "<title> --body-file <path> --depth <0|1|2> [--route <route>] [--label <name>] [--repo <owner/repo>] [--distinct <N,\u2026>]",
457
+ "automation",
458
+ ["network"]
459
+ ]
450
460
  }
451
461
  };
452
462
 
@@ -1225,7 +1235,11 @@ var PROJECT_COMMANDS = {
1225
1235
  script: "scripts/propagate/propagate.ts",
1226
1236
  description: "Carry the published release into every consumer repository next to this one",
1227
1237
  category: "Project",
1228
- reference: ["[--dry-run] [--skip-publish-wait]", "maintainer", ["files", "network"]]
1238
+ reference: [
1239
+ "[--dry-run] [--skip-publish-wait] [--target <repo>]",
1240
+ "maintainer",
1241
+ ["files", "network"]
1242
+ ]
1229
1243
  },
1230
1244
  adopt: {
1231
1245
  script: "scripts/adopt/adopt.ts",
@@ -1472,6 +1486,7 @@ var ALIASES = {
1472
1486
  ird: "issue:read",
1473
1487
  ist: "issue:state",
1474
1488
  isc: "issue:scout",
1489
+ ifl: "issue:file",
1475
1490
  isf: "issue:fold",
1476
1491
  isfe: "issue:fold-existing",
1477
1492
  dfr: "defect:rate",
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.972.0",
2
+ "version": "1.983.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": [
@@ -193,7 +193,7 @@
193
193
  "@stylistic/eslint-plugin": "^5.10.0",
194
194
  "@types/node": "^26.6.3",
195
195
  "@types/semver": "^7.8.0",
196
- "cspell": "^10.3.5",
196
+ "cspell": "^10.3.6",
197
197
  "esbuild": "^0.28.2",
198
198
  "eslint": "^10.11.0",
199
199
  "eslint-config-prettier": "^10.1.8",
@@ -12,18 +12,18 @@
12
12
 
13
13
  **Issue を新規に起票した直後**に、既存の open Issue を調べる。`kickoff` / `fullrun` / `halfrun` が起票したとき、および実装中に Tier A で起票したとき(`backlogrun` 実行中を含む)。
14
14
 
15
- `pnpm josh epic:bundle <N>`(エイリアス `eb`)が候補を探して推奨を表示する。**このコマンドは何も書き込まない** — 候補を出すのが機械、束ねるかを決めるのは AI である。
15
+ `pnpm josh epic:bundle <N>`(エイリアス `eb`)が候補を探して推奨を表示する。起票は `pnpm josh issue:file` で行い、このコマンドが最終段として `epic:bundle` を実行して答えを表示するので、別に呼ぶのは `⚠` で再実行を案内されたときだけである。**このコマンドは何も書き込まない** — 候補を出すのが機械、束ねるかを決めるのは AI である。
16
16
 
17
17
  ### 起票の「前」に答えるのは `issue:scout`
18
18
 
19
19
  `pnpm josh issue:scout "<title>"`(エイリアス `isc`)は、まだ存在しない Issue について同じ配属先の問いに答える(joshuafolkken/kit#1252)。**配属の判定は `epic:bundle` のものをそのまま呼んでおり、実装は 1 つしかない。** 加えて、`epic:bundle` が意図的に採らないシグナル — タイトルの語の重なりによる**重複候補** — を返す。既存 Issue の束ね直しに似た見出しが立つのは強シグナルだけで十分だからだが、「もう起票されていないか」は起票前にしか意味を持たない別の問いであり、しきい値を混ぜていない。
20
20
 
21
- **両方を実行する。順番が違うだけである。**
21
+ **両方を実行する。順番が違うだけである。** どちらも `pnpm josh issue:file` が 1 回の呼び出しの中で実行する。
22
22
 
23
- | いつ | コマンド | 何について答えるか |
24
- | -------------------------- | ----------------------- | -------------------------------------------------- |
25
- | `gh api … issues` の**前** | `issue:scout "<title>"` | まだ番号を持たない下書き。タイトルと要約だけがある |
26
- | 起票の**直後** | `epic:bundle <N>` | 実在する Issue。番号と、それに記録された関係がある |
23
+ | いつ | コマンド | 何について答えるか |
24
+ | -------------- | ----------------------- | -------------------------------------------------- |
25
+ | 起票の**前** | `issue:scout "<title>"` | まだ番号を持たない下書き。タイトルと本文がある |
26
+ | 起票の**直後** | `epic:bundle <N>` | 実在する Issue。番号と、それに記録された関係がある |
27
27
 
28
28
  手順上の位置づけと、重複候補が見つかったときに起票せず止まる規則は `.claude/skills/workflow-commands/SKILL.md` → §2e が単一ソースである。
29
29
 
@@ -41,8 +41,8 @@
41
41
 
42
42
  **これは「レビューを CI と並走させる」ではない。**(ここで言うレビューは 1 周目のことであり、2 周目については下の段落で別に扱う。) joshuafolkken/kit#1216 の (b) は不採用と決定済みであり、却下の理由は規則ではなく仕組みである — あちらは**コードを変える作業**を CI と重ねるため、修正を push するたびに CI がやり直しになり、重ねた分をそのまま払い戻す。起票はコードを 1 行も変えないので、走っている CI がそのまま使える。**1 周目のレビュー**はコミットの前のままで、「コミット前セルフレビュー」は書き換えていない。**2 周目だけは CI と並走する**(joshuafolkken/kit#1261)— 同じ仕組みを逆から読んだ結果であり、2 周目は fix delta しか読まず、通常はコードを 1 行も変えない。変えた場合は同一ブランチへの追加コミット 1 つと CI のやり直し 1 回を払う。単一ソースは `.claude/skills/workflow-commands/chain-rule.md` → "The pull request opens between the rounds, so CI runs beside round 2"。
43
43
 
44
- 1. 残指摘を後追い Issue として起票し、現在の Issue を参照する
45
- 2. **現在の Issue が閉じる前に** `pnpm josh epic:bundle <新規>` を実行する。候補探索は open Issue しか読まないため、親が閉じた後では恒久的に `none` になる(joshuafolkken/kit#947)
44
+ 1. 残指摘を後追い Issue として起票し、現在の Issue を参照する。起票は `pnpm josh issue:file "<title>" --body-file <本文ファイル> --depth <n> --route review-cap` で行う
45
+ 2. **現在の Issue が閉じる前に**起票する。`issue:file` が新規 Issue について `epic:bundle` を実行する。候補探索は open Issue しか読まないため、親が閉じた後では恒久的に `none` になる(joshuafolkken/kit#947)
46
46
  3. 答えに従う。**`epic:bundle` は推奨するだけで何も書き込まない**ので、「実行する」とは書き込みコマンドを自分で打つことである。**epic 本文の手編集は禁止** — タスクリストと `blocked-by` が食い違い、`epic:next` が `error` を返す
47
47
 
48
48
  | 答え | すること | Tier |
@@ -71,14 +71,14 @@ Issue には次の要素を必ず含める。
71
71
 
72
72
  - **起票前に不具合かどうかを必ず選ぶ。** `## 背景` の直下に、不具合なら `- 種別: 不具合`、非不具合なら `- 種別: 非不具合` を置く。両方の併記も省略も `pnpm josh issue:lint` が拒否する。故障を述べる本文でも単語から自動判定せず、起票者が判断する。振る舞い変更、機能改善、互換性の宣言はこの判断と併記できる
73
73
  - **不具合修正の Issue は `- 種別: 不具合` を宣言する。** この宣言がある Issue では、`pnpm josh git -y` が追加・変更したテストを修正前のツリー(merge-base)に当てて `pnpm josh test:red` で実行し、1 本も赤にならない(`green`)ときはコミットを拒否する。修正前でも緑の回帰テストは、報告された症状を再現していないためである(joshuafolkken/kit#2448)。回帰テストは、利用者が症状を見たのと同じ粒度で書く
74
- - **起票時の `bug` ラベルは本文の宣言から決める。** `pnpm josh issue:lint <本文ファイル>` の後、同じファイルを `gh api …/issues -F body=@<本文ファイル>` で送る。`labels:` に `bug` が含まれたら `-f 'labels[]=bug'` を同じ作成呼び出しに追加する。`depth`・`route` は併記する。`bugfix` は PR のリリース分類であり、Issue の `bug` の代わりにしない
75
- - **機能追加・機能改善は目的を本文で宣言する。** `## 背景` の直下に `- 目的: 機能追加` または `- 目的: 機能改善` を書く。`pnpm josh issue:lint <本文ファイル>` が `labels: enhancement` を返したら、同じ作成呼び出しに `-f 'labels[]=enhancement'` を付ける。不具合修正、文書のみ、依存更新、保守作業はタイトルの単語から推測して宣言しない。目的が曖昧なら起票文案の期待結果と受け入れ条件を具体化してから分類する
76
- - **互換性を壊す変更は影響を本文で宣言する。** 既存の利用者、API、設定の契約を変える場合は、`## 背景` の直下に `- 互換性: 破壊的変更` を書き、廃止対象と影響を説明する。移行措置や事前案内があっても破壊的変更なら宣言する。`pnpm josh issue:lint <本文ファイル>` が `labels: breaking-change` を返したら、同じ作成呼び出しに `-f 'labels[]=breaking-change'` を付ける。互換性を保つ変更には付けない。影響が曖昧なら起票文案で対象の利用者と契約を明確にしてから分類する
77
- - **`issue:lint` が返す分類ラベルをすべて起票時に指定する。** `bug`、`enhancement`、`breaking-change` は組み合わせて表示されることがある。`depth`・`route` など既存のラベルを残し、`labels: none` のときは分類ラベルを付けない。Issue が `enhancement` と `breaking-change` の両方を持つとき、PR のリリース分類は `breaking-change` 一つにする。Issue の目的の分類と PR のリリース分類を区別する
74
+ - **起票時の `bug` ラベルは本文の宣言から決める。** 起票は `pnpm josh issue:file "<title>" --body-file <本文ファイル> --depth <n>` で行い、このコマンドが `issue:lint` と同じ検査をしたうえで、`- 種別: 不具合` の宣言があれば `bug` ラベルを同じ作成リクエストに付ける。`depth`・`route` も同じ呼び出しで付く。`bugfix` は PR のリリース分類であり、Issue の `bug` の代わりにしない
75
+ - **機能追加・機能改善は目的を本文で宣言する。** `## 背景` の直下に `- 目的: 機能追加` または `- 目的: 機能改善` を書く。この宣言があれば `pnpm josh issue:file` が `enhancement` ラベルを同じ作成リクエストに付ける。不具合修正、文書のみ、依存更新、保守作業はタイトルの単語から推測して宣言しない。目的が曖昧なら起票文案の期待結果と受け入れ条件を具体化してから分類する
76
+ - **互換性を壊す変更は影響を本文で宣言する。** 既存の利用者、API、設定の契約を変える場合は、`## 背景` の直下に `- 互換性: 破壊的変更` を書き、廃止対象と影響を説明する。移行措置や事前案内があっても破壊的変更なら宣言する。この宣言があれば `pnpm josh issue:file` が `breaking-change` ラベルを同じ作成リクエストに付ける。互換性を保つ変更には付けない。影響が曖昧なら起票文案で対象の利用者と契約を明確にしてから分類する
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
79
  - **`## ベースライン`** は **「コマンド + 値」** で書く。``- `<測定コマンド>` → <現在の値>`` の形に限り、自然文だけの測定説明は受け付けない(再実行できないため)。マージ後に `pnpm josh measure:rerun` が同じコマンドをやり直し、**before / after の対**を印字する。値が動かなかったとき、反証された前提として `docs/maintainers/observations.md` に 1 行追記される(既存の append-only 台帳を使い、別の台帳は作らない)
80
80
  - **`## 再現`** は **「コマンド + 実際の出力」** で書く。コマンドを backtick、出力をフェンス(``` または ~~~)で囲む。自然文の「確認した」は再実行できないため受け付けない(`## ベースライン` と同じ理由)。読みだけの起票を起票時に弾くためである
81
- - **検査は `pnpm josh issue:lint <path>` が行う。** 対象判定・3 見出しの有無・発火点の配送可否・ベースラインが「コマンド + 値」か・再現が「コマンド + 実際の出力」かと、起票時に必要な分類ラベルを、起票前の本文ファイルからまとめて答える(未リントの起票は `pnpm josh rule:guard` が拒否する)
81
+ - **検査は `pnpm josh issue:lint <path>` が行う。** 対象判定・3 見出しの有無・発火点の配送可否・ベースラインが「コマンド + 値」か・再現が「コマンド + 実際の出力」かと、起票時に必要な分類ラベルを、起票前の本文ファイルからまとめて答える(`pnpm josh issue:file` は起票前に同じ検査を行い、問題があれば起票しない)
82
82
 
83
83
  ### 起票元へのバックリンク(`## Origin` / `## Upstream issues`)
84
84