@joshuafolkken/kit 1.1136.0 → 1.1166.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 (165) hide show
  1. package/.claude/settings.json +4 -4
  2. package/.claude/skills/epic-commands/SKILL.md +27 -239
  3. package/.claude/skills/epic-commands/epic-bundle.md +115 -0
  4. package/.claude/skills/epic-commands/execution-waves.md +126 -0
  5. package/.claude/skills/workflow-commands/SKILL.md +48 -194
  6. package/.claude/skills/workflow-commands/background-commands.md +1 -1
  7. package/.claude/skills/workflow-commands/backlogrun-child.md +12 -123
  8. package/.claude/skills/workflow-commands/backlogrun-lanes.md +11 -60
  9. package/.claude/skills/workflow-commands/backlogrun-park.md +10 -8
  10. package/.claude/skills/workflow-commands/backlogrun-progress.md +17 -173
  11. package/.claude/skills/workflow-commands/backlogrun-recovery.md +155 -0
  12. package/.claude/skills/workflow-commands/backlogrun-steps.md +64 -144
  13. package/.claude/skills/workflow-commands/backlogrun.md +5 -4
  14. package/.claude/skills/workflow-commands/chain-rule.md +3 -2
  15. package/.claude/skills/workflow-commands/delegation.md +2 -2
  16. package/.claude/skills/workflow-commands/entry-sequence.md +62 -0
  17. package/.claude/skills/workflow-commands/followup.md +104 -181
  18. package/.claude/skills/workflow-commands/fullrun-steps.md +8 -9
  19. package/.claude/skills/workflow-commands/fullrun.md +16 -73
  20. package/.claude/skills/workflow-commands/halfrun.md +10 -36
  21. package/.claude/skills/workflow-commands/into-target.md +4 -4
  22. package/.claude/skills/workflow-commands/issue-comments.md +7 -8
  23. package/.claude/skills/workflow-commands/issue-scout.md +6 -6
  24. package/.claude/skills/workflow-commands/kickoff.md +6 -6
  25. package/.claude/skills/workflow-commands/needs-human-review.md +6 -6
  26. package/.claude/skills/workflow-commands/observation-filing.md +21 -172
  27. package/.claude/skills/workflow-commands/observation-ledger.md +150 -0
  28. package/.claude/skills/workflow-commands/pre-gate-cut.md +33 -93
  29. package/.claude/skills/workflow-commands/prerequisite.md +6 -6
  30. package/.claude/skills/workflow-commands/progress-watcher.md +90 -0
  31. package/.claude/skills/workflow-commands/prrun.md +5 -5
  32. package/.claude/skills/workflow-commands/retrospective.md +9 -9
  33. package/.claude/skills/workflow-commands/split-assessment.md +2 -2
  34. package/.claude/skills/workflow-commands/target-repository.md +2 -2
  35. package/.claude/skills/workflow-commands/working-tree-hold.md +7 -5
  36. package/.codex/hooks.json +4 -4
  37. package/AGENTS.md +1 -6
  38. package/CLAUDE.md +58 -120
  39. package/GEMINI.md +1 -6
  40. package/dist/CLAUDE.md +58 -120
  41. package/dist/hooks/batch-guard.js +4 -4
  42. package/dist/hooks/{chunk-NFZGFGOR.js → chunk-5KTCMCOT.js} +14 -1
  43. package/dist/hooks/{chunk-LJBLGHEH.js → chunk-A6P7PN7P.js} +4 -6
  44. package/dist/hooks/{chunk-FO2I7UT7.js → chunk-ANJ2WGFD.js} +1 -1
  45. package/dist/hooks/{chunk-GDU26K3J.js → chunk-DYAVAM6S.js} +563 -126
  46. package/dist/hooks/{chunk-RFWWUI5F.js → chunk-ENA7P5FB.js} +3 -3
  47. package/dist/hooks/{chunk-KBXZLMRH.js → chunk-GU5MATVE.js} +213 -65
  48. package/dist/hooks/chunk-GYNGP7HI.js +56 -0
  49. package/dist/hooks/{chunk-HBKZLITF.js → chunk-URJA6XY4.js} +4 -4
  50. package/dist/hooks/{chunk-KOKOAV6D.js → chunk-V2BTOZHT.js} +6 -4
  51. package/dist/hooks/{chunk-JKKTVDAG.js → chunk-ZDZ555YH.js} +100 -20
  52. package/dist/hooks/codex-hook-adapter.js +10 -10
  53. package/dist/hooks/duplicate-read-guard.js +5 -5
  54. package/dist/hooks/format-edited.js +2 -2
  55. package/dist/hooks/inputs.json +193 -192
  56. package/dist/hooks/investigation-guard.js +5 -5
  57. package/dist/hooks/pretool-guard.js +11 -10
  58. package/dist/hooks/stop-guard.js +5 -5
  59. package/dist/josh.js +25 -2
  60. package/dist/version/index.js +5 -1
  61. package/package.json +2 -1
  62. package/prompts/collaboration-workflow/file-edits.md +11 -10
  63. package/prompts/collaboration-workflow/gh-rest.md +2 -4
  64. package/prompts/collaboration-workflow/glossary.md +1 -1
  65. package/prompts/collaboration-workflow/issue-citation.md +5 -9
  66. package/prompts/collaboration-workflow/issue-template.md +40 -115
  67. package/prompts/collaboration-workflow/operating-rules.md +4 -5
  68. package/prompts/collaboration-workflow/output-bounds.md +12 -78
  69. package/prompts/collaboration-workflow/overview.md +7 -13
  70. package/prompts/collaboration-workflow/plan-comment.md +11 -39
  71. package/prompts/collaboration-workflow/principles.md +3 -4
  72. package/prompts/collaboration-workflow/report-format.md +28 -74
  73. package/prompts/collaboration-workflow/residency.md +12 -109
  74. package/prompts/collaboration-workflow/rule-delivery.md +98 -97
  75. package/prompts/collaboration-workflow/shell-body.md +3 -13
  76. package/prompts/collaboration-workflow/turn-batching.md +14 -88
  77. package/prompts/collaboration-workflow/upstream-interrupt.md +12 -14
  78. package/prompts/collaboration-workflow/wip-cap.md +6 -45
  79. package/prompts/collaboration-workflow.md +1 -13
  80. package/prompts/review-rubric.md +8 -71
  81. package/prompts/review.md +25 -55
  82. package/prompts/testing-guide.md +18 -67
  83. package/scripts/agent/agent-role-profile.ts +1 -1
  84. package/scripts/agent/codex-hooks.ts +3 -12
  85. package/scripts/backlog/backlog-budget.ts +1 -1
  86. package/scripts/backlog/backlog-drive-cli.ts +4 -3
  87. package/scripts/backlog/backlog-drive-offer-argv.ts +10 -1
  88. package/scripts/backlog/backlog-offer.ts +6 -6
  89. package/scripts/behavior/behavior-rules.ts +11 -4
  90. package/scripts/delegation/investigation-reads.ts +5 -5
  91. package/scripts/discovery/repo-discovery.ts +21 -7
  92. package/scripts/discovery/repo-origin.ts +26 -0
  93. package/scripts/discovery/repo-party.ts +42 -1
  94. package/scripts/document/backlogrun-parent-read-set.ts +14 -15
  95. package/scripts/document/document-byte-budget.ts +34 -20
  96. package/scripts/document/entry-read-budget.ts +21 -9
  97. package/scripts/document/lane-child-read-set.ts +12 -14
  98. package/scripts/document/read-set-cli.ts +4 -4
  99. package/scripts/document/read-set-point-of-use.ts +10 -2
  100. package/scripts/document/resident-budget.ts +47 -0
  101. package/scripts/epic/epic-shape.ts +10 -13
  102. package/scripts/epic/epic-solo.ts +1 -1
  103. package/scripts/exports/unused-members-cli.ts +7 -3
  104. package/scripts/gh/git-gh-api-path.ts +7 -0
  105. package/scripts/hooks/pretool-guard-cli.ts +2 -2
  106. package/scripts/hooks/pretool-guard.ts +45 -2
  107. package/scripts/hooks/run-hook.sh +41 -0
  108. package/scripts/init/hook-command-rewrite.ts +18 -35
  109. package/scripts/init/hook-launch.ts +21 -32
  110. package/scripts/issue/issue-auto-ok.ts +95 -0
  111. package/scripts/issue/issue-file-cli.ts +53 -7
  112. package/scripts/issue/issue-file.ts +28 -5
  113. package/scripts/issue/issue-labels.ts +12 -12
  114. package/scripts/issue/issue-rank.ts +1 -1
  115. package/scripts/issue/issue-read-cli.ts +3 -3
  116. package/scripts/issue/issue-read.ts +2 -2
  117. package/scripts/issue/issue-scout-cli.ts +2 -2
  118. package/scripts/issue/issue-state-cli.ts +1 -1
  119. package/scripts/issue/issue-state.ts +2 -2
  120. package/scripts/issue/issue-wip.ts +70 -0
  121. package/scripts/josh/hook-decision.ts +17 -0
  122. package/scripts/josh/josh-commands-development.ts +10 -0
  123. package/scripts/josh/josh-commands-issue.ts +2 -2
  124. package/scripts/lines/bytes-command.ts +29 -6
  125. package/scripts/observations/observation-ledger-line.ts +1 -1
  126. package/scripts/release/release-progress.ts +167 -0
  127. package/scripts/release/release-publish.ts +19 -8
  128. package/scripts/release/release-tag.ts +22 -8
  129. package/scripts/rules/decision-oracle-stage.ts +1 -1
  130. package/scripts/rules/decision-oracle.ts +6 -6
  131. package/scripts/rules/delivered-rules.ts +11 -11
  132. package/scripts/rules/direct-pr-create.ts +110 -0
  133. package/scripts/rules/file-body.ts +98 -42
  134. package/scripts/rules/filing-cap.ts +2 -2
  135. package/scripts/rules/filing-offer.ts +1 -1
  136. package/scripts/rules/gh-api.ts +18 -1
  137. package/scripts/rules/implementation-cut.ts +3 -1
  138. package/scripts/rules/lane-background.ts +67 -10
  139. package/scripts/rules/permission-guards.ts +10 -2
  140. package/scripts/rules/stop-rules.ts +4 -4
  141. package/scripts/rules/test-declared-commit.ts +1 -1
  142. package/scripts/rules/third-party-write.ts +56 -12
  143. package/scripts/run/run-cut-handoff.ts +21 -1
  144. package/scripts/run/run-entry-cli.ts +11 -3
  145. package/scripts/run/run-hold-cli.ts +16 -2
  146. package/scripts/run/run-label.ts +50 -0
  147. package/scripts/run/run-merge-steps.ts +8 -3
  148. package/scripts/run/run-merge.ts +1 -1
  149. package/scripts/run/run-prep-cli.ts +6 -2
  150. package/scripts/run/run-prep.ts +17 -0
  151. package/scripts/run/run-ship-preflight.ts +34 -3
  152. package/scripts/run/run-ship-review-steps.ts +1 -1
  153. package/scripts/run/run-ship-review.ts +26 -5
  154. package/scripts/run/run-step-cli.ts +20 -7
  155. package/scripts/run/run-wake-driver.ts +24 -1
  156. package/scripts/run/run-wake-session.ts +2 -1
  157. package/scripts/test/test-declared-logic.ts +1 -1
  158. package/scripts/time-runtime/time-batch-guard.ts +52 -16
  159. package/scripts/time-runtime/time-density-hook.ts +20 -2
  160. package/scripts/time-runtime/time-density.ts +4 -3
  161. package/scripts/time-runtime/time-markers.ts +15 -4
  162. package/scripts/version/npm-registry.ts +11 -1
  163. package/templates/workflows/ci.yml +9 -1
  164. package/.claude/skills/workflow-commands/followup-reference.md +0 -118
  165. package/dist/hooks/chunk-HANSKHES.js +0 -464
@@ -1,6 +1,6 @@
1
1
  # 引き金つき配送 — 規則を「効く瞬間」に届ける(joshuafolkken/kit#1524)
2
2
 
3
- 規則の届け方は 2 つある。**常駐**(`CLAUDE.md` に書き、毎ターン読み込ませる)と、**引き金つき配送**(規則が効く瞬間にフックが本文を突きつける)である。この文書は後者の単一ソースであり、どの規則がどの引き金で配送されるかの列挙表でもある。
3
+ 規則の届け方は 2 つある。**常駐**(`CLAUDE.md` に書き、毎ターン読み込ませる)と、**引き金つき配送**(規則が効く瞬間にフックが本文を突きつける)である。この文書は後者の単一ソースであり、配送される規則の一覧でもある。配線・判定の細部と経緯は `docs/maintainers/rule-delivery-rationale.md` にあり、ランの途中で読む必要はない。
4
4
 
5
5
  ## なぜ配送が要るのか
6
6
 
@@ -8,111 +8,112 @@
8
8
 
9
9
  ## 判定基準 — 引き金を特定できるか
10
10
 
11
- どの規則を配送へ移すか — 引き金を 1 件のツール呼び出しとして名指しできるか、常駐側にトリガの 1 行を残す理由、移設が削除ではないこと — の単一ソースは [`residency.md`](./residency.md) →「第 1 問」であり、ここには写さない。この文書が持つのは、移した規則を届ける機構と列挙表である。移設は削除ではないので、joshuafolkken/kit#1477(読み込む命令文のコスト測定)の答えを待つ必要はない — あちらが門番なのは**削除**の判断である。
11
+ どの規則を配送へ移すか — 引き金を 1 件のツール呼び出しとして名指しできるか、常駐側にトリガの 1 行を残す理由、移設が削除ではないこと — の単一ソースは [`residency.md`](./residency.md) →「第 1 問」であり、ここには写さない。この文書が持つのは、移した規則の一覧である。
12
12
 
13
13
  ## 機構 — 1 本だけ、新規に作らない
14
14
 
15
- 配送はすべて `scripts/josh/hook-decision.ts` の `create_transcript_guard` の上に載る。バッチガード(joshuafolkken/kit#1390)と調査ガード(joshuafolkken/kit#1460)が既に共有している唯一の土台であり、ペイロードのスキーマ、`deny` の封筒、環境変数のスイッチ、`.env` の読み込み、ラン 1 回だけ発火させる記録の 5 つを持つ。**2 本目の配送経路を作るのは `CLAUDE.md` →「No clones」が禁じるクローン**であり、しかも 2 本が「配送したかどうか」で食い違いうる唯一の場所である。
16
-
17
- - **列挙表**: `scripts/rules/delivered-rules.ts`。1 規則 = 1 行(`id` / 引き金 / 配送文)。
18
- - **入口**: `scripts/hooks/pretool-guard-cli.ts`(ガードの合成は `scripts/hooks/pretool-guard.ts`)= `pnpm josh pretool:guard`。3 つの `PreToolUse` ガード(バッチング / 調査 / 規則)を 1 プロセスにまとめ、`.claude/settings.json` の `PreToolUse` に**単一エントリ**として `Bash|Edit|Read|Write` のマッチャで配線されている。拒否の優先順位はバッチングの理由が先、次に調査、最後に規則であり、各ガードは内部で従来どおり自分の環境変数スイッチを尊重する。
19
- - **停止スイッチ**: `JOSH_RULE_GUARD`(規則ガードのぶん。既定で有効。`off` / `0` / `false` / `no` で無効)。バッチング・調査の各ガードも同じく自前のスイッチを持つ。
20
-
21
- **規則ガードの列挙表に載るのは、効く瞬間がシェル呼び出しである規則に限られる。** Claude Code は 1 ターンのうち 1 件だけを拒否して残りを実行するため、拒否された `Edit` は兄弟の編集だけが適用された状態を残す(joshuafolkken/kit#1390)。単一の `pretool:guard` プロセスは `Bash|Edit|Read|Write` を受け取るが、規則ガードが拒否理由を返すのはシェル呼び出しに限られる。
22
-
23
- ### Stop フック — 2 つ目の入口、同じ土台(joshuafolkken/kit#2121)
24
-
25
- `pretool-guard` が `PreToolUse` の入口であるのと同じ意味で、`stop:guard`(`scripts/hooks/stop-guard.ts` = `pnpm josh stop:guard`)は **`Stop` イベントの入口**である。`.claude/settings.json` の `Stop` に matcher 空の**単一エントリ**として配線され、turn の終わりごとに走る。
26
-
27
- **土台は共有し、判定は再利用する。** スイッチ(`JOSH_STOP_GUARD`)と `.env` の読み込みは `hook-decision.ts` のものを、停止通知かどうかは `lane-park.ts` の正規表現を、押さえの有無は `run:hold` の記録読み取りを使う — **2 本目の判定機構は作らない**。起票の有無は `filing-cap.ts` の数え方を、第一者かどうかは `repo-party.ts` の比較を使う。違うのはイベントだけで、`Stop` のペイロードにはツール呼び出しが無く、4 行はいずれも `{"decision":"block","reason":…}` で返す。`Stop` イベントからモデルへ文字を届ける経路はこれ 1 本しかない(joshuafolkken/kit#2247)。
28
-
29
- **入口が 2 つでも土台は 1 つ。**「1 本だけ、新規に作らない」が禁じるのは共有部の 2 つ目の写しであって、イベントごとの入口ではない。`stop:guard` の 4 行は下の列挙表に載るが、引き金がシェル呼び出しではなく**ランの停止**なので、`delivered-rules.ts` の `DELIVERED_RULES`(`PreToolUse` 専用)ではなく `stop-rules.ts` に住む。どのエラーでも停止は通す(フェイルオープン)— 4 つのブロック行は自己解消し(通知を送る/押さえを解放する/起票する/引用を直して返信を出し直す)、`stop_hook_active` が無限ループの歯止めになる。
30
-
31
- `backlogrun` の通常の親ループと次の Issue の取得は監督プロセスが扱うため、次の Issue を取得させる Stop 判定は撤去した。名前を指定したエピックを判断用の headless セッションに渡す経路では、子レーンの待機がそのセッションに残るため、待機保護を維持する。停滞と取り残しの検出は Stop イベントが起きた時だけ実行し、停止判定とは独立して報告する。
15
+ 配送はすべて 1 つの土台に載り、入口はイベントごとに 2 つある。`PreToolUse` の入口が `pnpm josh pretool:guard`(バッチング / 調査 / 規則の 3 ガードを 1 プロセスで合成)、Stop フックの入口が `pnpm josh stop:guard` である。**2 本目の配送経路を作るのは `CLAUDE.md` →「No clones」が禁じるクローン**である。配線・停止スイッチ・拒否の優先順位: `docs/maintainers/rule-delivery-rationale.md` →「機構」。
32
16
 
33
17
  ## 配送されている規則
34
18
 
35
- | 規則 | 引き金 | 引き金が発火しないターンでは |
36
- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
37
- | **ターン内バッチング**(`turn-batching.md`) | `pnpm josh batch:guard` — 単発呼び出しのターンが 3 つ続いた次の `Bash` / `Edit` / `Read` | 往復あたりの呼び出し数が下限を上回っている = 規則は既に守られている |
38
- | **調査の委譲しきい値**(`SKILL.md` → §2b) | `pnpm josh investigation:guard` — 編集しないファイルの読み取りが 3 件目に達した `Read` / `Bash` | 読み取りがしきい値未満 = 委譲する対象がまだ無い |
39
- | **バックログ WIP 上限**(`wip-cap.md`) | `pnpm josh rule:guard` — Issue を起票する `Bash`(`pnpm josh issue:file`) | Issue が起票されていない = 上限に触れる行為が無い |
40
- | **直接起票の禁止**(`docs/josh-commands-automation.md` → `josh issue:file`、joshuafolkken/kit#2808) | `pnpm josh rule:guard` — `josh issue:file` を通さずに Issue を作成する `Bash`(`gh issue create`、または `…/issues` への `title` 付き POST)。拒否文は `pnpm josh issue:file` の書式を渡す。重複探し・本文の検査と分類ラベル・`## Origin` の確認・`epic:bundle` はこのコマンドが実行するので、それぞれを別の行で見張らない。**毎回発火する** | `pnpm josh issue:file` で起票している = 起票の全段がそろっている |
41
- | **1 ラン 10 件の起票上限**(`.claude/skills/workflow-commands/SKILL.md` → §2d、`observation-filing.md`) | `pnpm josh rule:guard` — Issue を起票する `Bash`(`pnpm josh issue:file`)。そのランで**拒否されていない**起票が既に 10 件あるとき、11 件目を拒否する。終了コードが 0 でない `issue:file` 呼び出しは起票に数えない。`is_issue_filing` を再利用し、新しい述語は作らない | 拒否されていない起票が 10 件未満 = 上限に触れていない。**繰り返す行為を止める行なので毎回発火する**(下の「例外」に従う) |
42
- | **Issue コメントの読み取り**(`SKILL.md` → §2g) | `pnpm josh rule:guard` — Issue 本文だけを読む `Bash`(`gh issue view <N>`、または `…/issues/<N>` で終わる GET) | Issue を読んでいない、または最初から `--comments` 付きで読んでいる |
43
- | **本文をシェルに載せない**(`shell-body.md`) | `pnpm josh rule:guard` — 二重引用符の本文値(`-f body="…"` / `-f "body=…"` / `--body "…"` / `--notify-message "…"`)にバッククォートか `$` を含む `Bash` | 本文がシェルに評価されない = 規則は既に守られている |
44
- | **@path をリテラル投稿する誤射**(`shell-body.md`、joshuafolkken/kit#2304) | `pnpm josh rule:guard` — 生フィールド(`-f` / `--raw-field`)で `body=@<path>` を渡した `Bash`。`@` で始まる値をそのまま送るため `@<path>` がコメントとして投稿される。**毎回発火する** | `-F` / `--field body=@`(ファイルを読む正しい綴り)・`@` を含まない本文・`pnpm josh issue:comment` = リテラルの `@path` が送出されない |
45
- | **検証コマンドのパイプ**(`output-bounds.md`) | `pnpm josh rule:guard` — 合否を意味する josh のチェック(`gate` / `check` / `lint*` / `cspell*` / `test*` / `eval` / `overrides` / `ranges`)がパイプの手前に立った `Bash` | 検証の終了コードが握りつぶされていない = 失敗が失敗として伝わる |
46
- | **早すぎる進捗報告**(`.claude/skills/workflow-commands/backlogrun-progress.md` → 「Progress while the run is quiet」) | `pnpm josh rule:guard` — 待つことだけが目的の `Bash`(全区間が `sleep`、または `sleep` に `echo` / `:` / `date` が並ぶだけ)。既に生きているタイマーがある回、またはその報告が間隔前に着地する回に拒否する | 待機タイマーを自前で張っていない = 時計は `run:progress` が 1 本だけ持っている |
47
- | **run 末尾の空転**(`background-commands.md`) | `pnpm josh rule:guard` — commit・push・PR 作成をまとめる段(`pnpm josh git -y` / 別名 `josh g`、`--yes` も同じ)を**前景**で出した `Bash`。`run_in_background` が付いていれば引き金に当たらない | 背景で発行している = 完了通知が run を再開させ、push とマージのあいだが空かない |
48
- | **gate 手前の cut**(`.claude/skills/workflow-commands/pre-gate-cut.md`) | `pnpm josh rule:guard` — レーンの作業ツリーに居て、目印 `JOSH_LANE_CHILD` がその Issue を指し、cut 記録がまだ無いまま `pnpm josh gate`(別名 `josh ga` も同じ)を走らせる `Bash` | レーン以外の checkout に居る、目印が無い(レーン内の人)、または既に cut 済み = 規則が守られている状態 |
49
- | **実装フェーズの cut**(`.claude/skills/workflow-commands/pre-gate-cut.md` → 「It is a guard, fired at the edit that crosses the threshold」、joshuafolkken/kit#2310) | `pnpm josh rule:guard` — 派遣されたレーンの子(目印 `JOSH_LANE_CHILD` がその Issue を指す)で cut 記録がまだ無く、直近文脈のコスト(`pnpm josh cost --cut` と同一の統計・同一のしきい値 `CONTEXT_CUT_THRESHOLD`、測定不能は `!== UNDER` で安全側に発火)が超過しているときに出した `Edit` / `Write`。編集の直前で拒否し `pnpm josh run:cut --impl <N> --handoff <path>` を返す。**しきい値を跨ぐたびに発火する**(`decide`、joshuafolkken/kit#2385)。直後の同じ編集の出し直しは通すので `busy` / `failed` でも空回りしない | レーンの子でない(レーン外・目印なし・レーン内の人)、非編集ツール、既に cut 済み、またはコストがしきい値未満 = 打ち切りが要らない状態 |
50
- | **レーンの子の保留**(`.claude/skills/workflow-commands/pre-gate-cut.md`) | `pnpm josh rule:guard` — 派遣されたレーンの子(目印 `JOSH_LANE_CHILD` がその Issue を指す)が、判断待ちの停止通知 `pnpm josh notify --task-type confirmation` を出した `Bash` | レーンの子でない(レーン外・目印なし・レーン内の人)、または停止通知でない = 保留を記録すべき停止が無い |
51
- | **レーンの子の対話質問**(`.claude/skills/workflow-commands/pre-gate-cut.md` → 「The interactive ask is refused one call earlier」) | `pnpm josh rule:guard` — 派遣されたレーンの子(目印 `JOSH_LANE_CHILD` がその Issue を指す)が `AskUserQuestion` を呼んだ呼び出し。停止通知の 1 つ手前で拒否し park 手順を返す。ハーネスは対話質問をターン終了で拒否するので、この 1 つ前が正しい引き金である。**毎回発火する** | レーンの子でない(レーン外・目印なし・レーン内の人)、または対話ツールでない = 握りつぶされる質問が無い |
52
- | **テストの宣言**(`CLAUDE.md` → Code Change Rules) | `pnpm josh rule:guard` — commit・push・PR 段(`pnpm josh git -y` / 別名 `josh g`)を出した瞬間に `pnpm josh test:declared` が作業ツリーを `required`(テストでも機械的免除パスでもない変更ファイルがある)と読む `Bash`。`run_tail` の commit 段照合を再利用し、新しい配送経路は作らない | 差分が `exempt`(`*.md` 等の非ランタイム)または `satisfied`(`*.test.ts` / `*.e2e.ts` を含む)= テストが要らない、または既に伴っている。免除は人が Step 0 で宣言するため 1 ラン 1 回だけ配送する |
53
- | **force push / ブランチ削除**(`operating-rules.md`、joshuafolkken/kit#2120) | `pnpm josh rule:guard` — `git push` / `git branch` を argv として解析し、force(`--force` / `-f` / 結合クラスタ `-uf`)・削除(`--delete` / `-d` / `-D` / コロン形 `:branch`)・`git -C` 前置を綴りによらず判定した `Bash`。**毎回発火する** | force / 削除でない通常の `git push` / `git branch` = 破壊的操作が無い |
54
- | **認可外の作業ツリー変更**(`operating-rules.md`、joshuafolkken/kit#2120) | `pnpm josh rule:guard` — `git checkout -- <path>` / `git restore <path>`(worktree)/ 認可外の `git stash`(bare・メッセージ無し push・位置指定 pop 等)を出した `Bash`。**毎回発火する** | メッセージ付き `git stash push -m` ・`git stash list` ・`pnpm josh git` ・`pnpm josh stash:pop` = 認可された退避 |
55
- | **ファイル本文をシェルに載せない**(`file-edits.md`、joshuafolkken/kit#2120) | `pnpm josh rule:guard` — 既存ファイルを対象としたヒアドキュメント書き込み・書き込みを伴う `node -e` / インタプリタ heredoc・in-place `perl -0pi -e` を出した `Bash`。既存判定は `stat` 1 回。**毎回発火する** | 新規ファイル作成・読み取り専用のヒアドキュメント・短い `sed -i` = 本文を丸ごと運んでいない |
56
- | **停止時の通知**(`CLAUDE.md` →「Mid-workflow stop notification」、joshuafolkken/kit#2121) | `pnpm josh stop:guard` — `Stop` フックで、作業ツリーを押さえたまま(`run:hold` 記録あり)その turn に `confirmation` 通知を出さずに止まろうとする。**停止をブロックする** | 押さえを持っていない、`confirmation` 通知が末尾にある、または pre-gate cut を取った回(レーンの子の自動継続)= 人待ちの停止ではない(`stop_hook_active` が無限ループの歯止め) |
57
- | **hold の解放**(`.claude/skills/workflow-commands/SKILL.md` → §2f、joshuafolkken/kit#2121) | `pnpm josh stop:guard` — `Stop` フックで、ツリーが綺麗(`git status --porcelain` が空)なのに `run:hold` 記録が残ったまま止まる。**停止をブロックする** | ツリーが汚れている(`halfrun` の commit 前停止・`needs-human-review` 停止)、または既に解放済み = 次のランが踏まない |
58
- | **Issue 引用の書式**(`prompts/collaboration-workflow/issue-citation.md`、joshuafolkken/kit#2121・joshuafolkken/kit#2247) | `pnpm josh stop:guard` — `Stop` フックで、`last_assistant_message` の地の文に裸の `#N` を含む。**停止をブロックする**(モデルに差し戻し、引用を直して返信を出し直させる) | リンク形式で引用している、コードフェンス/インラインコード/引用行の中、`PR` / `pull request` 直後の `#N`、または GitHub 向け成果物(`gh` 引数として渡る)、あるいは `stop_hook_active` が立っている = 差し戻す裸の番号が無い |
59
- | **起票の申し出**(`.claude/skills/workflow-commands/SKILL.md` → §2i、joshuafolkken/kit#2422) | `pnpm josh stop:guard` — `Stop` フックで、`last_assistant_message` の地の文が起票を申し出る(「起票してよければ」等)のに、transcript 末尾に起票(`filing_cap` の数え方)が無い。**停止をブロックする** | 起票済み、フェンス/引用行の中、第三者の `owner/repo` を名指す(`repo_party.classify`)、owner 不明、または `stop_hook_active` = 保留された Tier A 起票が無い |
60
- | **規則本文を散文に書き足す前の第 0 問・順序の問い**(`residency.md`、joshuafolkken/kit#2272・joshuafolkken/kit#2324) | `pnpm josh rule:guard` — `CLAUDE.md` / `prompts/**/*.md` / `.claude/skills/**/*.md` を対象とする `Edit` / `Write` で、リンク・URL を除いた正味の追記が閾値以上(規則本文の追記)。誤字・リンク張り替え・削除は当たらない。第 0 問(`oracle:list`)と順序の問い(`run:step`)を突きつける。前提を満たすまで毎回拒否する(下の「例外」)。**#2324 で stand-down** — `oracle:list` と `run:step` の両方を走らせた記録が末尾にあれば通す(リマインダではなく「問いに答えたか」で通す) | 規則ドキュメントを編集していない、追記が閾値未満、または両方の配置判定コマンドを実行済み = 散文の規則が増えていない、または配置の問いに答え済み |
61
- | **オラクル未参照の行為**(`decision-oracle.ts`、joshuafolkken/kit#2324) | `pnpm josh rule:guard` — 発火点を宣言したオラクルが支配する `Bash`(`pkg:scout` = `pnpm add`)を、そのオラクルの `pnpm josh <command>` 無しで出したとき拒否。拒否文は登録簿(判断・コマンド・回答語彙・単一ソース)から組み立て手書きしない。実行するまで毎回拒否し、実行済みで stand-down。発火点を名指しできないオラクルは理由を宣言し**可視化された未強制**として残る(`oracle:list` が発火点/理由を印字)。`release:scope` は理由側で、`pnpm josh followup` のマージ**後**に owe されるリリースを読むためマージを gate せず trail する(joshuafolkken/kit#2334) | 支配下の行為を出していない、またはそのオラクルを実行済み = 規則は既に守られている |
62
-
63
- **引き金はシェルのコマンド文字列しか見えない。** したがって node の中から REST で Issue を作る経路(`pnpm josh propagate` など)は上の正規表現に掛からない。同じ理由で、本文をファイルで渡す `gh api --input <file>` もタイトルが文字列に現れないため掛からない(`-f` / `-F` / `--field` / `--raw-field` の 4 綴りは覆う)。**これが、規則本文を配送に移したうえで常駐側にトリガ 1 行を残す理由の 1 つである** — 常駐の 1 行は経路によらず効き、配送はそれを効く瞬間に補強する。引き金つきの配送だけにすると、正規表現が知っている綴りだけが規則の適用範囲になる。
64
-
65
- **「引き金が発火しないターンでは何も起きない」ことは、欠落ではなく仕様である。** 上の各行はいずれも、発火しない状態が「規則が守られている状態」と一致している。この一致が取れない規則は、引き金を特定できていないということであり、常駐に残す。**誤ったターンで発火するフックは、フックが無いより悪い。**
66
-
67
- ### コメント投稿は引き金ではない
68
-
69
- WIP 上限の引き金は Issue の**作成**だけを見る。`…/issues/<N>/comments` はコメントであり、起票ではない — コメントは起票より桁違いに多く、そこで拒否するフックは「誤ったターンで発火するフック」そのものになる。`scripts/rules/delivered-rules.test.ts` がこの境界を両方向から固定している。
70
-
71
- ### Issue コメントの読み取り — 「読め」ではなく「目の前に置く」(joshuafolkken/kit#1319)
72
-
73
- **引き金は実装の開始ではなく、本文が届いた 1 件の呼び出しである。** 「実装を始める瞬間」は 1 件のツール呼び出しとして名指しできないが、「Issue の本文がランの目に入る瞬間」は名指しできる — `gh issue view <N>` か、`…/issues/<N>` で終わる GET。この行が判定基準を通るのはそこである。
74
-
75
- **拒否文は「コメントも読め」という要求ではなく、読み直しのコマンドそのものを渡す。** 散文の要求は joshuafolkken/kit#1344 が 3 ラン連続で「数値がまったく動かなかった」と実測した形式であり、この行がそれを避けるのは、本文だけの読み取りが**通らない**ことによる。ランの次の一手はコメント込みの読み取りになり、コメントは「読むべきもの」ではなく実際に手元にある。ただし `PreToolUse` の拒否が運べるのは文字列 1 本だけなので、**フックがコメント本文を注入するわけではない** — 1 往復ぶん遅れて、ランが自分で取りに行く。
76
-
77
- **この行は `batch:guard` と引き金が重なる唯一の行である。** `time_batch_guard.is_guarded_call` は `gh issue view` を候補として扱う(`gh issue create` は扱わない)。ただしこの行は前提を満たすまで毎回拒否するので(下の「例外」)、`is_first_delivery` の待避分岐を通らず、バッチングの拒否が出るターンでも拒否する。`delivered-rules.test.ts` がこれを固定している。
78
-
79
- **判定はコマンド 1 件ごとに、行頭に錨を打って行う。** シェル 1 行は複数のコマンドを運ぶため、`&&` / `||` / `;` / 改行で区切った各区間をそれぞれ判定する(`|` は区切りに使わない — `--jq` の中に現れる方がはるかに多い)。これがないと 2 つの誤りが同時に出る。引用符の中に `gh issue view` を含む書き込み(`gh issue comment <N> -b "…"`)が読み取りと誤認され、逆に `gh issue view <N> && grep -c x` のように無関係な `-c` を含む行が「コメント込み」と誤認されて配送が消える。
80
-
81
- **書き込みは読み取りではない。** `gh api` は `-f` / `-F` / `--field` / `--raw-field` / `--input` のいずれかが現れた時点で POST になり、`kickoff` はまさに `…/issues/<N>` へ PATCH してタイトルを正規化し空の本文を埋める。メソッドが明示的に `GET` でない、またはフィールド系のフラグを伴う呼び出しは対象外とする — さもないと 1 ラン 1 回の配送を書き込みに使い切り、同じランの本当の本文読み取りは無防備になる。
82
-
83
- **`-c` は「コメント込み」と見なさない。** `gh issue view <N> -c` は正しい読み取りだが、`-c` は `wc` / `grep` / `sort` のものである方が圧倒的に多く、これを行全体で許すとパイプで終わる複合行すべてで規則が黙る。誤って 1 往復ぶん止める側に倒し、`--comments` / `--json` の `comments` / `…/comments` エンドポイントの 3 綴りだけを「コメント込み」とする。最後の 1 つが要るのは、バッチングが本文とコメントを 1 行にまとめさせるからで、それを拒否すれば規則が求める形そのものを拒否することになる。
84
-
85
- **それでもシェル文字列しか見えない。** node の中から REST で本文を読む経路は最初から掛からない。だからこそ手順本体は `SKILL.md` → §2g に置かれており、フックはそれを補強するだけである。
19
+ 各項目は**規則**(単一ソース)・**発火点**・**発火しないとき**を持つ。フックが走らないエージェントはこれを自己適用のチェックリストにする(`principles.md`)。頻度を書いていない項目は 1 ラン 1 回だけ配送される — 「毎回発火する」「毎回拒否する」「たびに発火する」「停止をブロックする」(`stop:guard` は止まるたびに判定する)と書いた項目は、条件を満たすかぎり何度でも発火し、「再び発火する」と書いた項目は間隔をおいて再発火する。
20
+
21
+ - **ターン内バッチング**(`turn-batching.md`)
22
+ - 発火点: `pnpm josh batch:guard` — 単発呼び出しのターンが 3 つ続いた次の `Bash` / `Edit` / `Read`。単発が続くかぎり、さらに 3 ターンごとに**再び発火する**(joshuafolkken/kit#2164)
23
+ - 発火しないとき: 往復あたりの呼び出し数が下限を上回っている = 規則は既に守られている
24
+ - **調査の委譲しきい値**(`delegation.md`)
25
+ - 発火点: `pnpm josh investigation:guard` — 編集しないファイルの読み取りが 3 件目に達した `Read` / `Bash`。拒否の後も読み取りがもう一度しきい値まで積み上がれば**再び発火する**
26
+ - 発火しないとき: 読み取りがしきい値未満 = 委譲する対象がまだ無い
27
+ - **バックログ WIP 上限**(`wip-cap.md`)
28
+ - 発火点: `pnpm josh rule:guard` — Issue を起票する `Bash`(`pnpm josh issue:file`)
29
+ - 発火しないとき: Issue が起票されていない = 上限に触れる行為が無い
30
+ - **直接起票の禁止**(`docs/josh-commands-automation.md` → `josh issue:file`、joshuafolkken/kit#2808)
31
+ - 発火点: `pnpm josh rule:guard` — `josh issue:file` を通さずに Issue を作成する `Bash`(`gh issue create`、または `…/issues` への `title` 付き POST)。拒否文は `pnpm josh issue:file` の書式を渡す。**毎回発火する**
32
+ - 発火しないとき: `pnpm josh issue:file` で起票している = 重複探し・本文の検査・`epic:bundle` までの全段がそろっている
33
+ - **1 ラン 10 件の起票上限**(`.claude/skills/workflow-commands/prerequisite.md`、`observation-filing.md`)
34
+ - 発火点: `pnpm josh rule:guard` — 拒否されていない起票が既に 10 件あるランの 11 件目の `pnpm josh issue:file`。失敗した呼び出しは数えない。**毎回発火する**
35
+ - 発火しないとき: 拒否されていない起票が 10 件未満 = 上限に触れていない
36
+ - **Issue コメントの読み取り**(`issue-comments.md`)
37
+ - 発火点: `pnpm josh rule:guard` — Issue 本文だけを読む `Bash`(`gh issue view <N>`、または `…/issues/<N>` で終わる GET)。コメント込みで読み直すまで毎回拒否する
38
+ - 発火しないとき: Issue を読んでいない、または最初から `--comments` / `--json comments` / `…/comments` で読んでいる
39
+ - **本文をシェルに載せない**(`shell-body.md`)
40
+ - 発火点: `pnpm josh rule:guard` — 二重引用符の本文値(`-f body="…"` / `-f "body=…"` / `--body "…"` / `--notify-message "…"`)にバッククォートか `$` を含む `Bash`
41
+ - 発火しないとき: 本文がシェルに評価されない = 規則は既に守られている(経緯: `docs/maintainers/rule-delivery-rationale.md` →「本文のシェル評価を同じ機構の 1 行で覆った経緯」)
42
+ - **@path をリテラル投稿する誤射**(`shell-body.md`、joshuafolkken/kit#2304)
43
+ - 発火点: `pnpm josh rule:guard` — 生フィールド(`-f` / `--raw-field`)で `body=@<path>` を渡した `Bash`。**毎回発火する**
44
+ - 発火しないとき: `-F` / `--field body=@`・`@` を含まない本文・`pnpm josh issue:comment` = リテラルの `@path` が送出されない
45
+ - **検証コマンドのパイプ**(`output-bounds.md`)
46
+ - 発火点: `pnpm josh rule:guard` — 合否を意味する josh のチェック(`gate` / `check` / `lint*` / `cspell*` / `test*` / `eval` / `overrides` / `ranges`)がパイプの手前に立った `Bash`
47
+ - 発火しないとき: 検証の終了コードが握りつぶされていない = 失敗が失敗として伝わる
48
+ - **早すぎる進捗報告**(`.claude/skills/workflow-commands/progress-watcher.md` → 「Progress while the run is quiet」)
49
+ - 発火点: `pnpm josh rule:guard` — 待つことだけが目的の `Bash`(`sleep` だけ、または `echo` / `:` / `date` を並べただけ)を、タイマーが生きている回か報告が間隔前に着地する回に出したとき。**毎回発火する**
50
+ - 発火しないとき: 待機タイマーを自前で張っていない = 時計は `run:progress` が 1 本だけ持っている
51
+ - **run 末尾の空転**(`background-commands.md`)
52
+ - 発火点: `pnpm josh rule:guard` — `pnpm josh git -y`(別名 `josh g`、`--yes` も同じ)を**前景**で出した `Bash`。**毎回発火する**
53
+ - 発火しないとき: 背景で発行している = 完了通知が run を再開させ、push とマージのあいだが空かない
54
+ - **gate 手前の cut**(`.claude/skills/workflow-commands/pre-gate-cut.md`)
55
+ - 発火点: `pnpm josh rule:guard` — レーンの作業ツリーで、目印 `JOSH_LANE_CHILD` がその Issue を指し、cut 記録が無いまま `pnpm josh gate`(別名 `josh ga`)を走らせる `Bash`
56
+ - 発火しないとき: レーン以外の checkout に居る、目印が無い(レーン内の人)、または既に cut 済み = 規則が守られている状態
57
+ - **実装フェーズの cut**(`.claude/skills/workflow-commands/pre-gate-cut.md` → 「It is a guard, fired at the edit that crosses the threshold」、joshuafolkken/kit#2310)
58
+ - 発火点: `pnpm josh rule:guard` — 派遣されたレーンの子が cut 前に、直近文脈のコストが `pnpm josh cost --cut` のしきい値を超えた状態で出す `Edit` / `Write`。拒否文は `pnpm josh run:cut --impl <N> --handoff <path>` を渡す。しきい値を跨ぐたびに発火する
59
+ - 発火しないとき: レーンの子でない、非編集ツール、既に cut 済み、またはコストがしきい値未満 = 打ち切りが要らない状態
60
+ - **レーンの子の保留**(`.claude/skills/workflow-commands/pre-gate-cut.md`)
61
+ - 発火点: `pnpm josh rule:guard` — 派遣されたレーンの子が停止通知 `pnpm josh notify --task-type confirmation` を出した `Bash`
62
+ - 発火しないとき: レーンの子でない(レーン外・目印なし・レーン内の人)、または停止通知でない = 保留を記録すべき停止が無い
63
+ - **レーンの子の対話質問**(`.claude/skills/workflow-commands/pre-gate-cut.md` → 「The interactive ask is refused one call earlier」)
64
+ - 発火点: `pnpm josh rule:guard` — 派遣されたレーンの子の `AskUserQuestion`。park 手順を返す。**毎回発火する**
65
+ - 発火しないとき: レーンの子でない、または対話ツールでない = 握りつぶされる質問が無い
66
+ - **テストの宣言**(`CLAUDE.md` → Code Change Rules)
67
+ - 発火点: `pnpm josh rule:guard` — `pnpm josh git -y`(別名 `josh g`)を出した瞬間に `pnpm josh test:declared` が `required` と答える `Bash`
68
+ - 発火しないとき: `exempt`(非ランタイムのみ)または `satisfied`(テストを含む)= テストが要らない、または伴っている
69
+ - **force push / ブランチ削除**(`operating-rules.md`、joshuafolkken/kit#2120)
70
+ - 発火点: `pnpm josh rule:guard` — 綴りによらず force(`--force` / `-f` / `-uf` 等)・削除(`--delete` / `-d` / `-D` / `:branch`)と判定した `git push` / `git branch` の `Bash`。**毎回発火する**
71
+ - 発火しないとき: 通常の `git push` / `git branch` = 破壊的操作が無い
72
+ - **認可外の作業ツリー変更**(`operating-rules.md`、joshuafolkken/kit#2120)
73
+ - 発火点: `pnpm josh rule:guard` — `git checkout -- <path>` / `git restore <path>` / 強制 `git clean -f` / 認可外の `git stash`(bare・メッセージ無し push・位置指定 pop 等)の `Bash`。**毎回発火する**
74
+ - 発火しないとき: `git stash push -m` ・`git stash list` ・`pnpm josh git` ・`pnpm josh stash:pop` = 認可された退避
75
+ - **index の書き換え**(`operating-rules.md`、joshuafolkken/kit#2983)
76
+ - 発火点: `pnpm josh rule:guard` — 綴りによらず `git add` / `commit` / `reset` / `rm` / `mv` / `restore --staged` と判定した `Bash`。**毎回発火する**
77
+ - 発火しないとき: `pnpm josh git` = 承認済みのコミットフロー
78
+ - **破壊的コマンド**(`operating-rules.md`、joshuafolkken/kit#2983)
79
+ - 発火点: `pnpm josh rule:guard` — `rm -rf`(綴りによらず)・`gh repo delete` / `archive`・`gh pr close`・`gh api -X DELETE` の `Bash`。**毎回発火する**
80
+ - 発火しないとき: `gh issue close`・Issue ラベルの削除 = ワークフロー自身の手順
81
+ - **PR の直接作成**(`CLAUDE.md` → Git Rules、joshuafolkken/kit#3183)
82
+ - 発火点: `pnpm josh rule:guard` — `gh pr create`・`repos/<o>/<r>/pulls` への `gh api` 書き込みの `Bash`。`pnpm josh pr` を案内する。**毎回発火する**
83
+ - 発火しないとき: `pnpm josh pr`・PR の閲覧 = `closes #N` を生成する経路
84
+ - **保護ファイル**(`operating-rules.md`、joshuafolkken/kit#2983)
85
+ - 発火点: `pnpm josh rule:guard` — `.env` の `Read`、kit 以外のリポジトリでの `.claude/settings.json` の `Edit` / `Write`。**毎回発火する**
86
+ - 発火しないとき: kit 自身とユーザー単位の `~/.claude/settings.json` の編集
87
+ - **ファイル本文をシェルに載せない**(`file-edits.md`、joshuafolkken/kit#2120)
88
+ - 発火点: `pnpm josh rule:guard` — 既存ファイルへのヒアドキュメント書き込み・書き込みを伴う `node -e` / インタプリタ heredoc・`perl -0pi -e` の `Bash`。**毎回発火する**
89
+ - 発火しないとき: 新規ファイル作成・読み取り専用のヒアドキュメント・短い `sed -i` = 本文を丸ごと運んでいない
90
+ - **停止時の通知**(`CLAUDE.md` →「Mid-workflow stop notification」、joshuafolkken/kit#2121)
91
+ - 発火点: `pnpm josh stop:guard` — 作業ツリーを押さえたまま、その turn に `confirmation` 通知を出さずに止まる。**停止をブロックする**
92
+ - 発火しないとき: 押さえが無い、`confirmation` 通知が末尾にある、または pre-gate cut を取った回 = 人待ちの停止ではない
93
+ - **hold の解放**(`.claude/skills/workflow-commands/working-tree-hold.md`、joshuafolkken/kit#2121)
94
+ - 発火点: `pnpm josh stop:guard` — ツリーが綺麗なのに `run:hold` 記録が残ったまま止まる。**停止をブロックする**
95
+ - 発火しないとき: ツリーが汚れている(`halfrun` の commit 前停止・`needs-human-review` 停止)、または解放済み = 次のランが踏まない
96
+ - **Issue 引用の書式**(`prompts/collaboration-workflow/issue-citation.md`、joshuafolkken/kit#2121・joshuafolkken/kit#2247)
97
+ - 発火点: `pnpm josh stop:guard` — 最後の返信の地の文に裸の `#N` を含む。**停止をブロックする**。引用を直して返信を出し直させる
98
+ - 発火しないとき: リンク形式・コード/引用行の中・`PR` 直後の `#N`・GitHub 向け成果物 = 差し戻す裸の番号が無い
99
+ - **起票の申し出**(`.claude/skills/workflow-commands/observation-filing.md`、joshuafolkken/kit#2422)
100
+ - 発火点: `pnpm josh stop:guard` — 最後の返信の地の文が起票を申し出る(「起票してよければ」等)のに、起票していない。**停止をブロックする**
101
+ - 発火しないとき: 起票済み、フェンス/引用行の中、第三者の `owner/repo` を名指す、または owner 不明 = 保留された Tier A 起票が無い
102
+ - **規則本文を散文に書き足す前の第 0 問・順序の問い**(`residency.md`、joshuafolkken/kit#2272・joshuafolkken/kit#2324)
103
+ - 発火点: `pnpm josh rule:guard` — `CLAUDE.md` / `prompts/**/*.md` / `.claude/skills/**/*.md` への `Edit` / `Write` で、正味の追記が閾値以上のもの。`pnpm josh oracle:list` と `pnpm josh run:step` の両方を走らせるまで毎回拒否する
104
+ - 発火しないとき: 規則ドキュメントでない、追記が閾値未満(誤字・リンク張り替え・削除)、または両コマンドを実行済み = 配置の問いに答え済み
105
+ - **オラクル未参照の行為**(`decision-oracle.ts`、joshuafolkken/kit#2324)
106
+ - 発火点: `pnpm josh rule:guard` — 発火点を宣言したオラクルが支配する `Bash`(`pkg:scout` = `pnpm add`)を、そのオラクルの `pnpm josh <command>` 無しで出したとき。実行するまで毎回拒否する
107
+ - 発火しないとき: 支配下の行為を出していない、またはそのオラクルを実行済み = 規則は既に守られている
108
+
109
+ **引き金はシェルのコマンド文字列しか見えない**(node 内の REST や `gh api --input <file>` は掛からない)。だから常駐側にトリガ 1 行を残し、配送はそれを効く瞬間に補強する。
110
+
111
+ **「引き金が発火しないターンでは何も起きない」ことは仕様である。** 各項目の発火しない状態は「規則が守られている状態」と一致する。一致が取れない規則は引き金を特定できておらず、常駐に残す。**誤ったターンで発火するフックは、フックが無いより悪い。**
86
112
 
87
113
  ## 配送は 1 ラン 1 回
88
114
 
89
- 配送文は**ラン 1 回につき 1 度**しか出ない(記録は `hook-decision.ts` の stamp)。2 度目も拒否すれば、規則に従った直後の呼び出しを止めてラン自体を詰まらせる。したがって**配送文には「数えたうえで同じ呼び出しをもう一度出せ」と明記する**。これが無いと、拒否された側は次に何をすればよいか分からない。
90
-
91
- ### 例外 — 繰り返す行為を止める行は毎回発火する(joshuafolkken/kit#1570)
92
-
93
- **1 ラン 1 回が正しいのは、拒否がランの「知っていること」を変える行だけである。** コメントを読む、Issue を数える、本文をファイルに書く — いずれも一度届けば、そのランは以後それを知った状態で進む。**一方、止めたい対象そのものが繰り返される行為なら、1 回で終わる配送は「一度断られたあとは自由」を意味し、強制は親の自制に戻る。** その自制が破れたのが #1570 である。
94
-
95
- そこで **`decide` を自前で持つ行は 1 ラン 1 回の対象から外れ、条件を満たすかぎり毎回拒否する**。
96
-
97
- **`batch:guard` との待避分岐は、そういう行では守る対象が変わる。** 1 ラン 1 回の行では**記録**を守っていた — レースに負ければ、そのランに 1 度しかない配送を無駄打ちするからである。毎回発火する行はその形では消えない。一方で待機タイマーを張る呼び出しは定義上「単発の `Bash`」であり、まさにバッチングガードも候補として扱う形なので、**拒否まで待避させると、10 秒の窓とその中の再発行で規則がまるごと黙る**。したがって**拒否は無条件に行い、待避は「記録してよいか」として行へ渡す** — 他のフックが止めうる呼び出しでしてはならないのは、走らなかったタイマーを生きていると書き残すことだからである。配送文には「これは毎回発火する」と明記する(1 回きりだと読まれると、再発行すれば通ると誤解される)。
98
-
99
- ### 例外 — 前提を求める行は、前提が満たされるまで毎回拒否する(joshuafolkken/kit#2807)
100
-
101
- **`already_satisfied`(前提の行為がトランスクリプト末尾にあるか)を持つ行は、1 ラン 1 回の対象から外れる。** 前提が末尾に現れるまで、毎回拒否する。1 ラン 1 回のままだと、前提を飛ばしたランの再発行がそのまま通る。手順を読み飛ばしたランほどガードを素通りしてしまい、ガードの意味がない。対象は `issue-fold`・`issue-comments`・`rule-body`・`oracle-consulted:*` である。
102
-
103
- 従うランが詰まることはない。前提の行為を済ませれば、stand-down が先に答えて通すからである。記録を使い切る心配もないので、`batch:guard` との待避もしない。待避すると、10 秒の窓の中の再発行が前提を満たさないまま通ってしまう。配送文には「前提が末尾に現れるまで拒否する」と明記する。
104
-
105
- **前提の証拠を読めないときは、拒否を基本とする。** たとえば前提の行為を確かめるための記録が読めないときがこれに当たる。意図して通す例外は、理由をコードのコメントに残す。現在の例外は次のとおりである。
106
-
107
- - トランスクリプト自体を読めないとき(`hook-decision.ts`)
108
- - 初回の起票で、畳み込む相手がないとき(`issue-fold.ts`)
109
- - 進捗の記録がないとき(`early-heartbeat.ts`)
110
- - git の読み取りに失敗して、変更なしとして扱うとき(`delivered-rules.ts` の `test-declared` 行)
111
-
112
- ## 本文のシェル評価は同じ機構の 1 行で覆った(joshuafolkken/kit#1198)
113
-
114
- `delivered-rules.ts` の `shell-body` 行は、`-f body=` / `--body "` というフラグで引くのではなく、**二重引用符の本文値に `` ` `` か `$` が実際に含まれるとき**だけ発火する。`!`(履歴展開)は引き金に入れない。規則本文と引き金の死角は [`shell-body.md`](./shell-body.md) にある。経緯: `docs/maintainers/rule-delivery-rationale.md` →「本文のシェル評価を同じ機構の 1 行で覆った経緯」。
115
+ 配送文は**ラン 1 回につき 1 度**しか出ない — 2 度目も拒否すれば、規則に従った直後の呼び出しを止めてしまう。だから**配送文には「同じ呼び出しをもう一度出せ」と明記する**。例外は 2 つで、繰り返す行為を止める項目は毎回発火し(joshuafolkken/kit#1570)、前提の行為を求める項目は前提が末尾に現れるまで毎回拒否する(joshuafolkken/kit#2807)。これとは別に、バッチングと調査の 2 ガードは同じ呼び出しを二度拒否しないまま、違反が間隔分続けば再び発火する(joshuafolkken/kit#2164)— 1 回きりの注意ではない。先の 2 つの例外の配送文には「同じ呼び出しをもう一度出せ」ではなく、それぞれ「これは毎回発火する」「前提が末尾に現れるまで拒否する」と明記する — 1 回きりと読まれると、再発行すれば通ると誤解される。前提の証拠を読めないときは拒否を基本とする。経緯と意図した通過例外: `docs/maintainers/rule-delivery-rationale.md` →「配送は 1 ラン 1 回」。
115
116
 
116
117
  ## マーカーテスト
117
118
 
118
- 各テストファイルが何を固定するかの一覧: `docs/maintainers/rule-delivery-rationale.md` →「マーカーテスト」。列挙表の行を固定するスイートには `scripts/rules/turn-batching-rule.test.ts` / `scripts/rules/shell-body-rule.test.ts` / `scripts/rules/piped-verification-rule.test.ts` / `scripts/rules/pre-gate-cut.test.ts` / `scripts/rules/implementation-cut-rule.test.ts` / `scripts/rules/implementation-cut.test.ts` / `scripts/rules/lane-park.test.ts` / `scripts/rules/lane-interactive-ask.test.ts` / `scripts/rules/rule-body-guard.test.ts` がある。
119
+ 各項目を固定するスイートの一覧: `docs/maintainers/rule-delivery-rationale.md` →「マーカーテスト」。
@@ -56,11 +56,9 @@ pnpm josh notify --task-type confirmation --issue-url "<url>" --body-file <path>
56
56
 
57
57
  **`$'…'` も安全である。** ANSI-C クォートの中ではコマンド置換も変数展開も起きない。`CLAUDE.md` が Telegram の本文に `--body=$'…'` を指定しているのはそのためであり、この規則はそれを置き換えるものではない。ただし本文が長くなるほどファイルの方が扱いやすい。
58
58
 
59
- ### 引き金つき配送 — 書いただけでは守られないため
59
+ ### 引き金つき配送
60
60
 
61
- `pnpm josh rule:guard` が該当する `Bash` 呼び出しを拒否して本文を突きつける(`docs/maintainers/shell-body-rationale.md` →「引き金つき配送にした理由」)。列挙表の行は `scripts/rules/delivered-rules.ts` の `shell-body` であり、その行が読む引き金 — どの綴りが本文をインラインで運ぶか、シェルがその値に何をするか — は `scripts/rules/shell-body-trigger.ts` にある。
62
-
63
- **引き金はフラグではなく本文の中身である** — 二重引用符の本文値にバッククォートか `$` が実際に含まれるときだけ発火し、プレースホルダの作例(`-f body="<plan>"`)では無言である(`docs/maintainers/shell-body-rationale.md` →「引き金をフラグでなく本文で引く理由」)。
61
+ `pnpm josh rule:guard` が、二重引用符の本文値にバッククォートか `$` が実際に含まれる `Bash` 呼び出しを拒否して本文を突きつける。拒否されたら本文をファイルに移して出し直す。配線は `docs/maintainers/shell-body-rationale.md` →「引き金つき配送にした理由」、引き金の設計は `docs/maintainers/shell-body-rationale.md` →「引き金をフラグでなく本文で引く理由」、固定しているテストは `docs/maintainers/shell-body-rationale.md` →「マーカーテスト」にある。
64
62
 
65
63
  ### 引き金が見えないもの
66
64
 
@@ -69,12 +67,4 @@ pnpm josh notify --task-type confirmation --issue-url "<url>" --body-file <path>
69
67
  - **`-b`(GitHub CLI の `--body` の短縮形)は覆っていない** — 同じ綴りが `git checkout -b` のブランチ名でもあり、そこで拒否するのは誤ったターンでの発火になる
70
68
  - **`-f title="…"`** は覆っていない。タイトルは英語へ正規化された短い語であり、バッククォートを含む運用がない
71
69
 
72
- **この 4 つがあるため、常駐側の 1 行は消していない。** 配送は Claude Code にしか届かず(Codex / Gemini / Cursor はフックを走らせない)、正規表現が知っている綴りだけが規則の適用範囲になってはならない。
73
-
74
- ### マーカーテスト
75
-
76
- - `scripts/josh/cli-body.test.ts` — バッククォート・`$` を含む本文がファイル経由で無改変に通ること、`-` が標準入力を読むこと、通常ファイル以外の読める経路(`/dev/stdin`・プロセス置換)を開けること、インラインとファイルの同時指定を拒否すること
77
- - `scripts/rules/shell-body-trigger.test.ts` — 危険な綴りで発火し、プレースホルダ・`@file` 形式・エスケープ済み `\$` では無言であること。`body=` のどちら側に引用符があっても発火すること、`$( … )` で包んでもバッククォートは免除されないこと、`$( … )` の中の引用符で捕捉が切れないことを、いずれも発火・非発火の対で固定する
78
- - `scripts/rules/raw-field-body.test.ts` — `-f` / `--raw-field body=@` の綴りで発火し、`-F` / `--field body=@`・`@` を含まない本文・`labels[]=`・`pnpm josh issue:comment` では無言であること
79
- - `scripts/rules/delivered-rules.test.ts` — 上の引き金が列挙表の行に配線されており、非 `Bash` ツールでは無言であること
80
- - `scripts/rules/shell-body-rule.test.ts` — 常駐 1 行がこの文書を指しており、配送文が被害・安全な綴り・再発行の指示を運ぶこと。**この一覧そのものも固定する** — 一覧が「あるスイートが何を固定しているか」を書きながら、そのケースが存在しないという食い違いが実際に起きた(`-` の標準入力)
70
+ 引き金が見えない綴りでも規則は同じく拘束する。フックが走らないエージェントも同じである。
@@ -1,6 +1,6 @@
1
1
  # 独立した呼び出しは同じターンに載せる(joshuafolkken/kit#1304)
2
2
 
3
- `CLAUDE.md` →「Put every call that does not depend on another's result in the same turn」の正典。**常駐側にはトリガと判断基準の 1 行だけが残り、規則本文は `pnpm josh batch:guard` が効く瞬間に配送する**(joshuafolkken/kit#1524、下の「なぜ resident ではなく引き金つき配送に置くか」)。
3
+ `CLAUDE.md` →「Put every call that does not depend on another's result in the same turn」の正典。**常駐側にはトリガと判断基準の 1 行だけが残り、規則本文は `pnpm josh batch:guard` が効く瞬間に配送する**(joshuafolkken/kit#1524、`rule-delivery.md`、`docs/maintainers/turn-batching-rationale.md` → "Why it left residency (joshuafolkken/kit#1524)")。実測・却下した機構案・経緯は `docs/maintainers/turn-batching-rationale.md` にある。
4
4
 
5
5
  ## 何を求めているか
6
6
 
@@ -11,111 +11,37 @@
11
11
  - no → **その呼び出しは、依存していない他の呼び出しと同じターンに載せる**
12
12
  - yes → 結果を待つ。別のターンになるのが正しい
13
13
 
14
- 依存していない呼び出しを 1 つずつ別のターンに出す形が、この規則が禁じているものである。ファイルを 3 つ読むために 3 ターン使う、同じファイルの離れた 3 箇所を直すために 3 ターン使う、`git status` と `pnpm josh issue:state` と `pnpm josh latest:scope` を 3 ターンに分ける — いずれも後続の入力が前の結果を使っていない。
15
-
16
- ## なぜターン数が費用なのか
17
-
18
- **費用は仕事の量ではなく往復の回数にある。** joshuafolkken/kit#1295 の run(1,471 秒 / 153 ターン)で実測した:
19
-
20
- | 種別 | 回数 | ツール実行時間の合計 |
21
- | ---------------------------------------------------------------- | ---: | -------------------: |
22
- | `Edit` | 34 | 48 秒 |
23
- | 読み取り系の小さな `Bash`(`grep` 12 / `sed` 11 / `cat` 4 ほか) | 32 | 6 秒 |
24
-
25
- **ツール自体が動いていたのは合わせて約 54 秒**である。同じ 66 往復が消費した壁時計は 66 × 9〜13 秒 ≒ 600〜850 秒で、1 桁違う。1 ターンあたりの壁時計は 9〜13 秒の狭い帯に収まるので、**ターン数がそのまま run の下限を決めている。**
26
-
27
- ゲート短縮が run を縮めなかった経緯は `docs/maintainers/turn-batching-rationale.md` →「ゲートを削っても run が縮まなかった理由」。
14
+ ファイルを 3 つ読むために 3 ターン使う、同じファイルの離れた 3 箇所を直すために 3 ターン使う、`git status` と `pnpm josh issue:state` を別ターンに分ける — いずれも禁じられた形である。**費用は仕事の量ではなく往復の回数にある。** 1 ターンの壁時計はほぼ一定なので、ターン数が run の下限を決める(実測は `docs/maintainers/turn-batching-rationale.md` → "Why the number of turns is the cost")。
28
15
 
29
16
  ## 判断基準は「依存の有無」であって、呼び出しの種類ではない
30
17
 
31
- 読み取りだけの規則ではない。**`Edit` も同じ規則の対象である** — 同じファイルの離れた領域や、別々のファイルへの編集は、互いの結果を使っていないので同じターンに載る(実測の内訳は `docs/maintainers/turn-batching-rationale.md` →「`Edit` が最大の単一項目だった理由」)。
32
-
33
- 逆に、**依存があるなら分けるのが正しい。** 次はいずれも 1 つ前の結果を入力に使うので、同じターンに載せてはならない。
34
-
35
- - `grep` の結果を見てから、その行番号で `sed -n` を出す
36
- - `git switch` の成否を見てから `pnpm josh latest:scope` を出す
37
- - Edit の対象文字列を確かめるために先にファイルを読む(**Edit の前に読むことは省略できない**)
18
+ **`Edit` も同じ規則の対象である** — 別々のファイルや同じファイルの離れた領域への編集は、互いの結果を使っていないので同じターンに載る。逆に、**依存があるなら分けるのが正しい**: `grep` の結果の行番号で `sed -n` を出す、`git switch` の成否を見てから次を出す、Edit の前に対象を読む(**Edit の前に読むことは省略できない**)。
38
19
 
39
20
  ## 検証ゲートとレビューは往復を減らす対象ではない
40
21
 
41
- **ゲート・レビュー・差分の読み取りを、往復を減らす名目で弱めてはならない。** これは joshuafolkken/kit#1304 の受け入れ条件そのものである。具体的には:
22
+ **ゲート・レビュー・差分の読み取りを、往復を減らす名目で弱めてはならない。** `pnpm josh gate` の出力を絞って失敗の内訳を読まずに進む、`git diff main...HEAD` を一部だけ読んで「指摘なし」とする(`output-bounds.md`)、走らせるべきチェックを落とす — いずれも禁止。**往復を減らすのは「同じ仕事を少ないターンで出す」ことであって、「仕事を減らす」ことではない。**
42
23
 
43
- - `pnpm josh gate` の出力を絞り込んで読む、失敗の内訳を読まずに次へ進む — いずれも禁止
44
- - `git diff main...HEAD` を一部だけ読んでレビューを「指摘なし」と結論づける — 禁止(`output-bounds.md` →「切り詰められた出力を、完全な出力として読まない」と同じ理由)
45
- - 単発の再実行(`pnpm josh lint:related` / `pnpm josh test:related`)をまとめるために、走らせるべきチェックを落とす — 禁止
24
+ ## ガードが見えないところ — ここでは自分で規則を当てる
46
25
 
47
- **往復を減らすのは「同じ仕事を少ないターンで出す」ことであって、「仕事を減らす」ことではない。** 減らしてよいのはターンの数だけである。
26
+ ガードは閉じた履歴(結果が返ったターンの並び)から判定し、共有ターゲットを持つ呼び出しは依存とみなして止めない。機構は `docs/josh-commands-automation.md` →「`josh batch:guard`」、却下した案は `docs/maintainers/turn-batching-rationale.md` → "Rejected mechanisms"、範囲が広がった経緯は `docs/maintainers/turn-batching-rationale.md` → "How the guard's scope grew"。
48
27
 
49
- ## 機構で強制しない理由(却下した案)
50
-
51
- - **PreToolUse フックが「1 件の呼び出しだけを見て、それが独立かどうかを判定する」。** 採れない。**呼び出しの独立性は、1 件の呼び出しからは観測できない。** フックが見るのはこれから走る 1 件だけで、それが直前の結果に依存しているかどうかはフックの入力に無い。依存している正当な直列実行(`grep` → `sed -n`、Edit の前の読み取り)を止めてしまい、しかも止めた側は理由を説明できない。`output-bounds.md` が「形で見分ける案は実データ上で外れる」として PreToolUse guard を却下したのと同じ形である。
52
-
53
- **却下したのはこの判定のしかたであって、`PreToolUse` という機構そのものではない。** joshuafolkken/kit#1390 は**まさに `PreToolUse` フックとして** `pnpm josh batch:guard` を実装し、`.claude/settings.json` で配布している。判定に使うのは、いま出そうとしている 1 件ではなく**閉じた履歴** — 結果が返り終わったターンの並び — である。単発呼び出しのターンが 2 つ続いたことは 1 件からは見えないが、履歴からは見える。上に並べた懸念は、それぞれ設計で避けてある。依存は**共有ターゲット**で見るので `grep` → `sed -n` は止まらず、**書き込みも読み取りとまったく同じ基準で拒否され**(joshuafolkken/kit#1762)、**手元の呼び出しが直前の列と共有ターゲットを持つときは拒否を取り下げる**(書き込み同士を含む)。拒否は 1 つの単発連続につき **1 回だけ**である(窓を超える連続は `docs/maintainers/turn-batching-rationale.md` →「`batch:guard` の拒否窓」)。委譲された子やレビューエージェントは、親の記録を共有せず、それぞれに配送される(`docs/maintainers/turn-batching-rationale.md` →「フォークへの配送の実装(joshuafolkken/kit#1424)」)。機構の全体は `docs/josh-commands-automation.md` →「`josh batch:guard`」にある。範囲が `Bash|Edit|Read` に広がった経緯(joshuafolkken/kit#1509 を含む)は `docs/maintainers/turn-batching-rationale.md` →「書き込みが範囲に入った経緯(joshuafolkken/kit#1762)」、`docs/maintainers/turn-batching-rationale.md` →「読み取りが範囲に入った経緯(joshuafolkken/kit#1798)」、`docs/maintainers/turn-batching-rationale.md` →「事務コマンドが範囲に入った経緯(joshuafolkken/kit#1875)」。
54
-
55
- **ガードが見えないところ — ここでは自分で規則を当てる。**
56
-
57
- - **塞ぎきれないのは「いま中断しているターンの中身」であり、これは transcript から観測できないので設計上残る。** 同じファイルへの編集 3 件を 1 ターンにまとめた場合、先頭だけが拒否され残り 2 件が適用されることはある。**ただし壊れるのではなく失敗する** — 再発行された編集は書いたときの本文に一致するか、一致せずに報告されるかのどちらかである。
58
- - **ファイル全体を書き出す `Write` だけは拒否しない。** 再発行された `Write` は本文を照合しないので、そのターンの兄弟が適用した編集を無言で上書きしうる。根拠は `docs/maintainers/turn-batching-rationale.md` →「中断中のターンと `Write` の除外の根拠」。
59
- - **連続を切るのは「そもそもまとめられない呼び出し」、すなわち結果を次の呼び出しが必要とする委譲である。**
60
- - **`pnpm josh …` は読み取り専用サブコマンドの allow-list(`READ_JOSH_SUBCOMMANDS`)に載るものだけが bundleable である。** 書き込む・外部送信するサブコマンド(`run:progress --mark` はマーカーを書き、`notify` は送信し、`main:sync` / `epic` / `run:hold` は状態を書く)は allow-list に**入れない**。連鎖した行(`&&` / `|` / `>` など)は、先頭の `pnpm` が後続の変更を隠すため読みとしては信用せず、通常判定に落とす。
61
- - ツールを 1 つも呼ばないターンと、ガードが `off` のレーン子 — それぞれ下の「事後の計測」と「実装中の独立編集に効く合成コマンド」。
62
-
63
- - **複数編集を 1 呼び出しにまとめるツールを前提にする。** 前提にできない。この repository が対象とする harness には常に存在するとは限らず、存在しない側では規則が一度も発火しない。`pnpm josh` はどの harness にも存在するので、書き込みは合成コマンド `pnpm josh edit:files` で畳む(下節)。経緯は `docs/maintainers/turn-batching-rationale.md` →「複数編集ツールの前提を joshuafolkken/kit#2366 が反証した経緯」。
64
- - **ターンごとに件数の下限を課す。** 却下。依存が連続する区間では 1 件が正しい答えであり、下限は正しい振る舞いを罰する。上限も下限も持たないのが正しく、**代わりに事後の計測を置く**(次節)。
65
-
66
- harness 側の一般的な指示(「依存のない呼び出しは同じブロックで出す」)は**すでに存在していて、実測では発火していなかった** — 4 本の run で 1 往復あたり 1.13 / 1.04 / 1.03 / 1.00 呼び出し。帰結は `docs/maintainers/turn-batching-rationale.md` →「一般指示が発火しなかったことの帰結」。
28
+ - **いま中断しているターンの中身は見えない。** 同じターンの編集の先頭だけが拒否されることがあるが、壊れるのではなく失敗する — 再発行は本文に一致するか、一致せず報告される
29
+ - **ファイル全体を書き出す `Write` は拒否しない**(再発行が兄弟の編集を上書きしうるため)
30
+ - **`pnpm josh …` は読み取り専用の allow-list(`READ_JOSH_SUBCOMMANDS`)だけが bundleable** — 書き込む・送信するサブコマンドと、連鎖した行(`&&` / `|` / `>`)は通常判定に落ちる
31
+ - **ツールを呼ばないターンと、ガードが `off` のレーン子** — 下の計測と合成コマンドが受け持つ
67
32
 
68
33
  ## 事後の計測 — 実行タイミングレポートの `Round trips:`
69
34
 
70
- 強制の代わりに、**結果が毎回の計測に出る。**
71
-
72
- ```
73
- Round trips:
74
- tool calls 104 over 153 turn(s)
75
- round trips 104 1.00 calls per round trip
76
- ⚠ independent calls are going out one per turn (floor 1.50 calls per round trip)
77
- ```
78
-
79
- - **round trip は「1 ターンがまとめて出した呼び出しのかたまり」1 つ**であって、呼び出し 1 件ではない。まとめて出せば呼び出し数はそのままで往復だけが減る — つまりこの数字は、仕事を減らさずに費用だけ下げたかどうかを直接見せる
80
- - **しきい値は 1.50 呼び出し/往復。** 下回ると 1 行の指摘が出る。少しでもまとめている run は超えるので、これは程度を採点するのではなく**まとめていないこと**を検出する
81
- - **`tool-less turns` の行は、ツールを 1 つも呼ばなかったターン数**(`turn_count − round_trips`、joshuafolkken/kit#1875)。`batch:guard` は発話だけのターンを拒否できない — 呼ぶツールが無く `PreToolUse` が発火しないので、唯一の梃子がこの事後計測である。`Bundling:` はこれを構造上見られない(まとめる対象を持たないターンは列に入らない)。発話だけのターンは自分で減らす(実測は `docs/maintainers/turn-batching-rationale.md` →「`tool-less turns` の実測」)
82
- - 実装は `scripts/time-runtime/time-round-trips.ts`、詳細は `docs/josh-commands.md` の `time` コマンドの項
35
+ 強制の代わりに、結果が毎回の計測に出る。**round trip は 1 ターンがまとめて出した呼び出しのかたまり 1 つ**で、しきい値 1.50 呼び出し/往復を下回ると 1 行の指摘が出る。`tool-less turns` はツールを 1 つも呼ばなかったターン数で、`batch:guard` が拒否できない発話だけのターンは自分で減らす。実装は `scripts/time-runtime/time-round-trips.ts`、詳細は `docs/josh-commands.md` の `time` の項、読み方と実測は `docs/maintainers/turn-batching-rationale.md` → "Reading the round-trip measurement"。
83
36
 
84
37
  ## 実装中の独立編集に効く合成コマンド(joshuafolkken/kit#2202)
85
38
 
86
- **フックが届かない一区間が残っていた — レーン子の実装中の独立編集である。** レーン子(headless `claude -p`)ではガードが `off` なので(#2178)、別々のファイルへ `Read` → `Edit` を交互に出す並びは誰にも止められない。経緯は `docs/maintainers/turn-batching-rationale.md` →「合成コマンドに至った経緯(joshuafolkken/kit#2202)」。
87
-
88
- **しかし 1 手前に確定している — Step 0 が変更ごとに対象ファイルを列挙する。** `pnpm josh read:files` はその点で読み取りを畳む合成コマンドである。`report-format.md` が Step 0 の継ぎ目(`josh lines` の隣)でランをここへ導く**手順**である。
89
-
90
- **梃子の本体は読み取りと編集の脱交互化(de-interleave)。** 交互の並びで編集を分けているのは直前の読み取りへの依存で、読み取りを 1 回に畳めば続く別ファイルへの編集は互いにも直前の読み取りにも依存せず 1 ターンに載る。#2178 の並び — `Read A` / `Edit A` / `Read B` / `Edit B` … の **9 ターン** — が、`read:files A B C D` → `Edit A` + `Edit B` + `Edit C` + `Edit D` の **2 ターン**になる。
91
-
92
- 上限超過時は `read:files` が「Read ツールで 1 ターンにまとめて読め」と返しフォールバックでも読み取りは畳まれたまま。詳細は `docs/josh-commands-automation.md` →「`josh read:files`」。
93
-
94
- 書き込みは `pnpm josh edit:files` で畳む(joshuafolkken/kit#2366) — 編集を **プラン(`=====` のパスヘッダ+ git conflict マーカー対)** として受け取り 1 呼び出しで適用し、各編集は content-addressed なので `old` が 1 箇所に一致しなければ拒否して報告する。#2493 で `-`(標準入力)を受け、依存編集は `dependent` で拒否する。詳細は `docs/josh-commands-automation.md` →「`josh edit:files`」。
39
+ レーン子ではガードが `off` なので、`Read` → `Edit` の交互の並びは誰にも止められない。**Step 0 が対象ファイルを列挙した時点で、`pnpm josh read:files <path> …` で読み取りを 1 回に畳み、続く別ファイルへの編集を 1 ターンに載せる**(`report-format.md` が導く)。書き込みは `pnpm josh edit:files` で畳む(joshuafolkken/kit#2366) — プランを 1 呼び出しで適用し、`old` が 1 箇所に一致しなければ拒否する。形式は `docs/josh-commands-automation.md` →「`josh read:files`」と「`josh edit:files`」、経緯は `docs/maintainers/turn-batching-rationale.md` → "The composite commands"。
95
40
 
96
41
  ## ガード発火時にも合成コマンドを手渡す(joshuafolkken/kit#2311)
97
42
 
98
- ガードが**単発の読み取り連続**で発火したとき、通知はその読み取りを畳む `pnpm josh read:files <path> …` を貼り付け可能な形で手渡す — モデルが 1 ターンで確実に出せる単一の呼び出しである。経緯は `docs/maintainers/turn-batching-rationale.md` →「ガード通知に合成コマンドを載せた経緯(joshuafolkken/kit#2311)」。
99
-
100
- **読み取りに限り、2 件以上のときだけ。** 書き込みは `read:files` の対象外なので除外し、読み取り 1 件は既に単発なので畳むものがない。
101
-
102
- **書き込み側も同じ地点で手渡す(joshuafolkken/kit#2366)。** 単発 `Edit` の連続でガードが発火したとき、通知はその編集を名指し、それらのファイルにわたる `pnpm josh edit:files` の畳み込みを添える(`write_fold_directive`)。読み取りはパスだけで畳めるが編集は本文を伴うので、貼り付け可能なのはコマンドとファイル名までで、プラン本体はモデルが書く — それでも並列 `tool_use` ブロックではなく 1 ターンで出せる単一呼び出しに落ちる。`Edit` だけを数え、content-address できない `Write`(既に独自の通知を持つ)は除く。
103
-
104
- ## なぜ resident ではなく引き金つき配送に置くか(joshuafolkken/kit#1524)
105
-
106
- **この規則は常駐から外れている。** `pnpm josh batch:guard` が、単発呼び出しのターンが 3 つ続いた次の呼び出し(`Bash` / `Edit` / `Read`)を拒否し、そこで規則本文を突きつける — 規則が効く瞬間そのものである。配送の判定基準と機構は `rule-delivery.md` にある。
107
-
108
- 常駐から外した根拠は `docs/maintainers/turn-batching-rationale.md` →「常駐から外した根拠(joshuafolkken/kit#1524)」。
109
-
110
- **引き金が発火しないターンでは何も起きず、それが正しい。** 発火しないということは往復あたりの呼び出し数が下限(1.50)を上回っているということであり、規則が守られている状態と一致する。
111
-
112
- 配送文(`scripts/time-runtime/time-batch-guard.ts` の `REASON`、および `time-density.ts` の実行時 1 行)が運ぶのは次の 2 点である。常駐側に残していたのと同じ内容であり、削っていない。
113
-
114
- 1. 別の呼び出しの結果に依存しない呼び出しは、同じターンに載せる
115
- 2. 判断基準は「依存の有無」であって呼び出しの種類ではない(読み取りも編集も同じ)。かつ、往復を減らすことは仕事を減らすことではない
116
-
117
- 実測値・却下した機構案・計測の読み方はこのファイルと `docs/maintainers/turn-batching-rationale.md` にあり、配送文からは落としている。
43
+ 単発の読み取り(2 件以上)の連続でガードが発火すると、通知はそれを畳む `pnpm josh read:files` を貼り付け可能な形で渡す。単発 `Edit` の連続では、それらのファイルにわたる `pnpm josh edit:files` を添える(プラン本体はモデルが書く)。渡されたら、その 1 呼び出しで出し直す。
118
44
 
119
45
  ## マーカーテスト
120
46
 
121
- `scripts/rules/turn-batching-rule.test.ts` が固定する。内訳は `docs/maintainers/turn-batching-rationale.md` →「マーカーテストが固定するもの」。
47
+ `scripts/rules/turn-batching-rule.test.ts` が固定する。内訳は `docs/maintainers/turn-batching-rationale.md` → "What the marker test pins"。