@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.
- package/.claude/settings.json +4 -4
- package/.claude/skills/epic-commands/SKILL.md +27 -239
- package/.claude/skills/epic-commands/epic-bundle.md +115 -0
- package/.claude/skills/epic-commands/execution-waves.md +126 -0
- package/.claude/skills/workflow-commands/SKILL.md +48 -194
- package/.claude/skills/workflow-commands/background-commands.md +1 -1
- package/.claude/skills/workflow-commands/backlogrun-child.md +12 -123
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +11 -60
- package/.claude/skills/workflow-commands/backlogrun-park.md +10 -8
- package/.claude/skills/workflow-commands/backlogrun-progress.md +17 -173
- package/.claude/skills/workflow-commands/backlogrun-recovery.md +155 -0
- package/.claude/skills/workflow-commands/backlogrun-steps.md +64 -144
- package/.claude/skills/workflow-commands/backlogrun.md +5 -4
- package/.claude/skills/workflow-commands/chain-rule.md +3 -2
- package/.claude/skills/workflow-commands/delegation.md +2 -2
- package/.claude/skills/workflow-commands/entry-sequence.md +62 -0
- package/.claude/skills/workflow-commands/followup.md +104 -181
- package/.claude/skills/workflow-commands/fullrun-steps.md +8 -9
- package/.claude/skills/workflow-commands/fullrun.md +16 -73
- package/.claude/skills/workflow-commands/halfrun.md +10 -36
- package/.claude/skills/workflow-commands/into-target.md +4 -4
- package/.claude/skills/workflow-commands/issue-comments.md +7 -8
- package/.claude/skills/workflow-commands/issue-scout.md +6 -6
- package/.claude/skills/workflow-commands/kickoff.md +6 -6
- package/.claude/skills/workflow-commands/needs-human-review.md +6 -6
- package/.claude/skills/workflow-commands/observation-filing.md +21 -172
- package/.claude/skills/workflow-commands/observation-ledger.md +150 -0
- package/.claude/skills/workflow-commands/pre-gate-cut.md +33 -93
- package/.claude/skills/workflow-commands/prerequisite.md +6 -6
- package/.claude/skills/workflow-commands/progress-watcher.md +90 -0
- package/.claude/skills/workflow-commands/prrun.md +5 -5
- package/.claude/skills/workflow-commands/retrospective.md +9 -9
- package/.claude/skills/workflow-commands/split-assessment.md +2 -2
- package/.claude/skills/workflow-commands/target-repository.md +2 -2
- package/.claude/skills/workflow-commands/working-tree-hold.md +7 -5
- package/.codex/hooks.json +4 -4
- package/AGENTS.md +1 -6
- package/CLAUDE.md +58 -120
- package/GEMINI.md +1 -6
- package/dist/CLAUDE.md +58 -120
- package/dist/hooks/batch-guard.js +4 -4
- package/dist/hooks/{chunk-NFZGFGOR.js → chunk-5KTCMCOT.js} +14 -1
- package/dist/hooks/{chunk-LJBLGHEH.js → chunk-A6P7PN7P.js} +4 -6
- package/dist/hooks/{chunk-FO2I7UT7.js → chunk-ANJ2WGFD.js} +1 -1
- package/dist/hooks/{chunk-GDU26K3J.js → chunk-DYAVAM6S.js} +563 -126
- package/dist/hooks/{chunk-RFWWUI5F.js → chunk-ENA7P5FB.js} +3 -3
- package/dist/hooks/{chunk-KBXZLMRH.js → chunk-GU5MATVE.js} +213 -65
- package/dist/hooks/chunk-GYNGP7HI.js +56 -0
- package/dist/hooks/{chunk-HBKZLITF.js → chunk-URJA6XY4.js} +4 -4
- package/dist/hooks/{chunk-KOKOAV6D.js → chunk-V2BTOZHT.js} +6 -4
- package/dist/hooks/{chunk-JKKTVDAG.js → chunk-ZDZ555YH.js} +100 -20
- package/dist/hooks/codex-hook-adapter.js +10 -10
- package/dist/hooks/duplicate-read-guard.js +5 -5
- package/dist/hooks/format-edited.js +2 -2
- package/dist/hooks/inputs.json +193 -192
- package/dist/hooks/investigation-guard.js +5 -5
- package/dist/hooks/pretool-guard.js +11 -10
- package/dist/hooks/stop-guard.js +5 -5
- package/dist/josh.js +25 -2
- package/dist/version/index.js +5 -1
- package/package.json +2 -1
- package/prompts/collaboration-workflow/file-edits.md +11 -10
- package/prompts/collaboration-workflow/gh-rest.md +2 -4
- package/prompts/collaboration-workflow/glossary.md +1 -1
- package/prompts/collaboration-workflow/issue-citation.md +5 -9
- package/prompts/collaboration-workflow/issue-template.md +40 -115
- package/prompts/collaboration-workflow/operating-rules.md +4 -5
- package/prompts/collaboration-workflow/output-bounds.md +12 -78
- package/prompts/collaboration-workflow/overview.md +7 -13
- package/prompts/collaboration-workflow/plan-comment.md +11 -39
- package/prompts/collaboration-workflow/principles.md +3 -4
- package/prompts/collaboration-workflow/report-format.md +28 -74
- package/prompts/collaboration-workflow/residency.md +12 -109
- package/prompts/collaboration-workflow/rule-delivery.md +98 -97
- package/prompts/collaboration-workflow/shell-body.md +3 -13
- package/prompts/collaboration-workflow/turn-batching.md +14 -88
- package/prompts/collaboration-workflow/upstream-interrupt.md +12 -14
- package/prompts/collaboration-workflow/wip-cap.md +6 -45
- package/prompts/collaboration-workflow.md +1 -13
- package/prompts/review-rubric.md +8 -71
- package/prompts/review.md +25 -55
- package/prompts/testing-guide.md +18 -67
- package/scripts/agent/agent-role-profile.ts +1 -1
- package/scripts/agent/codex-hooks.ts +3 -12
- package/scripts/backlog/backlog-budget.ts +1 -1
- package/scripts/backlog/backlog-drive-cli.ts +4 -3
- package/scripts/backlog/backlog-drive-offer-argv.ts +10 -1
- package/scripts/backlog/backlog-offer.ts +6 -6
- package/scripts/behavior/behavior-rules.ts +11 -4
- package/scripts/delegation/investigation-reads.ts +5 -5
- package/scripts/discovery/repo-discovery.ts +21 -7
- package/scripts/discovery/repo-origin.ts +26 -0
- package/scripts/discovery/repo-party.ts +42 -1
- package/scripts/document/backlogrun-parent-read-set.ts +14 -15
- package/scripts/document/document-byte-budget.ts +34 -20
- package/scripts/document/entry-read-budget.ts +21 -9
- package/scripts/document/lane-child-read-set.ts +12 -14
- package/scripts/document/read-set-cli.ts +4 -4
- package/scripts/document/read-set-point-of-use.ts +10 -2
- package/scripts/document/resident-budget.ts +47 -0
- package/scripts/epic/epic-shape.ts +10 -13
- package/scripts/epic/epic-solo.ts +1 -1
- package/scripts/exports/unused-members-cli.ts +7 -3
- package/scripts/gh/git-gh-api-path.ts +7 -0
- package/scripts/hooks/pretool-guard-cli.ts +2 -2
- package/scripts/hooks/pretool-guard.ts +45 -2
- package/scripts/hooks/run-hook.sh +41 -0
- package/scripts/init/hook-command-rewrite.ts +18 -35
- package/scripts/init/hook-launch.ts +21 -32
- package/scripts/issue/issue-auto-ok.ts +95 -0
- package/scripts/issue/issue-file-cli.ts +53 -7
- package/scripts/issue/issue-file.ts +28 -5
- package/scripts/issue/issue-labels.ts +12 -12
- package/scripts/issue/issue-rank.ts +1 -1
- package/scripts/issue/issue-read-cli.ts +3 -3
- package/scripts/issue/issue-read.ts +2 -2
- package/scripts/issue/issue-scout-cli.ts +2 -2
- package/scripts/issue/issue-state-cli.ts +1 -1
- package/scripts/issue/issue-state.ts +2 -2
- package/scripts/issue/issue-wip.ts +70 -0
- package/scripts/josh/hook-decision.ts +17 -0
- package/scripts/josh/josh-commands-development.ts +10 -0
- package/scripts/josh/josh-commands-issue.ts +2 -2
- package/scripts/lines/bytes-command.ts +29 -6
- package/scripts/observations/observation-ledger-line.ts +1 -1
- package/scripts/release/release-progress.ts +167 -0
- package/scripts/release/release-publish.ts +19 -8
- package/scripts/release/release-tag.ts +22 -8
- package/scripts/rules/decision-oracle-stage.ts +1 -1
- package/scripts/rules/decision-oracle.ts +6 -6
- package/scripts/rules/delivered-rules.ts +11 -11
- package/scripts/rules/direct-pr-create.ts +110 -0
- package/scripts/rules/file-body.ts +98 -42
- package/scripts/rules/filing-cap.ts +2 -2
- package/scripts/rules/filing-offer.ts +1 -1
- package/scripts/rules/gh-api.ts +18 -1
- package/scripts/rules/implementation-cut.ts +3 -1
- package/scripts/rules/lane-background.ts +67 -10
- package/scripts/rules/permission-guards.ts +10 -2
- package/scripts/rules/stop-rules.ts +4 -4
- package/scripts/rules/test-declared-commit.ts +1 -1
- package/scripts/rules/third-party-write.ts +56 -12
- package/scripts/run/run-cut-handoff.ts +21 -1
- package/scripts/run/run-entry-cli.ts +11 -3
- package/scripts/run/run-hold-cli.ts +16 -2
- package/scripts/run/run-label.ts +50 -0
- package/scripts/run/run-merge-steps.ts +8 -3
- package/scripts/run/run-merge.ts +1 -1
- package/scripts/run/run-prep-cli.ts +6 -2
- package/scripts/run/run-prep.ts +17 -0
- package/scripts/run/run-ship-preflight.ts +34 -3
- package/scripts/run/run-ship-review-steps.ts +1 -1
- package/scripts/run/run-ship-review.ts +26 -5
- package/scripts/run/run-step-cli.ts +20 -7
- package/scripts/run/run-wake-driver.ts +24 -1
- package/scripts/run/run-wake-session.ts +2 -1
- package/scripts/test/test-declared-logic.ts +1 -1
- package/scripts/time-runtime/time-batch-guard.ts +52 -16
- package/scripts/time-runtime/time-density-hook.ts +20 -2
- package/scripts/time-runtime/time-density.ts +4 -3
- package/scripts/time-runtime/time-markers.ts +15 -4
- package/scripts/version/npm-registry.ts +11 -1
- package/templates/workflows/ci.yml +9 -1
- package/.claude/skills/workflow-commands/followup-reference.md +0 -118
- package/dist/hooks/chunk-HANSKHES.js +0 -464
package/dist/version/index.js
CHANGED
|
@@ -1160,7 +1160,11 @@ function read_release_times(package_name) {
|
|
|
1160
1160
|
const parsed = times_schema.safeParse(read_packument(package_name, FULL_ACCEPT));
|
|
1161
1161
|
return parsed.success ? parsed.data.time : void 0;
|
|
1162
1162
|
}
|
|
1163
|
-
|
|
1163
|
+
function has_public_version(package_name, version) {
|
|
1164
|
+
const parsed = times_schema.safeParse(read_packument(package_name, FULL_ACCEPT));
|
|
1165
|
+
return parsed.success && parsed.data.time[version] !== void 0;
|
|
1166
|
+
}
|
|
1167
|
+
var npm_registry = { has_public_version, packument_url, read_latest, read_release_times };
|
|
1164
1168
|
|
|
1165
1169
|
// scripts/version/version-remote.ts
|
|
1166
1170
|
var TIMES_PAGE_SIZE = 100;
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.
|
|
2
|
+
"version": "1.1166.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": [
|
|
@@ -94,6 +94,7 @@
|
|
|
94
94
|
"!scripts/exports/namespace-members.ts",
|
|
95
95
|
"!scripts/exports/unused-members.ts",
|
|
96
96
|
"!scripts/document/generate-catalog.ts",
|
|
97
|
+
"!scripts/document/issue-citation-budget.ts",
|
|
97
98
|
"!scripts/document/retired-phrases.ts",
|
|
98
99
|
"!scripts/document/review-agent-type.ts",
|
|
99
100
|
"!scripts/document/single-source.ts",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
`CLAUDE.md` →「Never carry a file's new text inside a shell command.」の正典。
|
|
4
4
|
|
|
5
|
-
`pnpm josh rule:guard`(file-body の行)が、既存ファイルを書き戻すヒアドキュメント・書き込みを伴うインタプリタ heredoc / `node -e
|
|
5
|
+
`pnpm josh rule:guard`(file-body の行)が、既存ファイルを書き戻すヒアドキュメント・書き込みを伴うインタプリタ heredoc / `node -e`・書き込むスクリプトファイルを作るヒアドキュメント・in-place `perl -0pi -e` を、コマンドの何行目にあってもその呼び出しで拒否し、規則を述べる。**このファイルが担うのはガードに見えないもの**である — Bash を通らない Edit / Write の全文書き直し、ガードを素通りする `sed -i` の 4 条件、そしてコストである。
|
|
6
6
|
|
|
7
7
|
### 何を禁じているか
|
|
8
8
|
|
|
@@ -38,7 +38,7 @@ PY
|
|
|
38
38
|
|
|
39
39
|
- **新規ファイルの作成** — 既存本文が無いので、運ぶ重複がそもそも発生しない
|
|
40
40
|
- **ファイル全体の作り直し** — 構成の組み替えや生成物の再生成で、変更後の本文が元の本文とほとんど共有しない場合
|
|
41
|
-
- **部分編集のほうが大きくなる場合** — 変更箇所がファイル全域に散っていて、`old_string` / `new_string`
|
|
41
|
+
- **部分編集のほうが大きくなる場合** — 変更箇所がファイル全域に散っていて、`old_string` / `new_string` の合計が全文を超えるとき。このときも全文は **Write ツール**で書く — ヒアドキュメントやインタプリタで書き戻す形は、この例外でもガードに拒否される
|
|
42
42
|
|
|
43
43
|
**レビュー指摘の修正がこの規則の主戦場である。** 「この行の条件が逆」「この定数を切り出す」といった局所的な指摘ほど、部分編集は小さくなる。一方で全文書き直しのコストはファイルの大きさで決まり、指摘の小ささでは下がらない。**指摘が局所的であるほど、全文書き直しとの差は開く。**
|
|
44
44
|
|
|
@@ -55,14 +55,15 @@ PY
|
|
|
55
55
|
|
|
56
56
|
**4 条件のどれかが面倒に見えたら、そこが Edit を使う場所である。** `sed` はコストを下げるための例外であって、既定の編集手段ではない。
|
|
57
57
|
|
|
58
|
-
| 形
|
|
59
|
-
|
|
|
60
|
-
| Edit(数行の old / new)
|
|
61
|
-
| `sed -i` の短い置換
|
|
62
|
-
| `python3 - <<'PY'` で領域を書き戻す
|
|
63
|
-
| `cat > file <<'EOF'` で既存ファイルを書き直す
|
|
64
|
-
| `cat > new-file <<'EOF'` で新規ファイルを作る
|
|
65
|
-
|
|
|
58
|
+
| 形 | 可否 | 理由 |
|
|
59
|
+
| -------------------------------------------------- | ------------ | --------------------------------------------------------- |
|
|
60
|
+
| Edit(数行の old / new) | 可 | 差分だけが本文に載る |
|
|
61
|
+
| `sed -i` の短い置換 | 条件付きで可 | パターンと置換語しか載らない。上の 4 条件を満たすこと |
|
|
62
|
+
| `python3 - <<'PY'` で領域を書き戻す | 不可 | 置換後の本文が丸ごと載る |
|
|
63
|
+
| `cat > file <<'EOF'` で既存ファイルを書き直す | 不可 | 同上 |
|
|
64
|
+
| `cat > new-file <<'EOF'` で新規ファイルを作る | 可 | 既存本文を運んでいない。ただし長文なら Write のほうが安い |
|
|
65
|
+
| `cat > edit.py <<'EOF'` で書き込むスクリプトを作る | 不可 | 実行を 1 呼び出し後ろにずらしただけで、置換後の本文が載る |
|
|
66
|
+
| 読み取り・検索(`cat` / `sed -n` / `grep`) | 可 | 本文を運ばない |
|
|
66
67
|
|
|
67
68
|
### なぜコストが二重になるか
|
|
68
69
|
|
|
@@ -32,10 +32,8 @@ egress が `403` で拒否されるため、GraphQL を経由するサブコマ
|
|
|
32
32
|
- **引用の形**(そのままでよい)— 「`gh issue create` は使わない」のような禁止の引用や、「このサブコマンドは
|
|
33
33
|
GraphQL を経由する」のような CLI の対応状況の記録。書き換えると、何を禁じているのかが読めなくなる。
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
allowlist に 25 件を並べることになり、それは何も守らない(joshuafolkken/kit#1505)。そこでガードは
|
|
38
|
-
フェンスに留め、散文の側はこの規則と `scripts/gh/gh-document-guard.test.ts` のマーカーテストで押さえる。
|
|
35
|
+
**この区別は機械には引けない** — 文書ガードはフェンス付きコードブロックだけを走査するので、散文の側は
|
|
36
|
+
書き手がこの区別で守る(`docs/maintainers/gh-rest-rationale.md` → "Why the document guard scans fences only")。
|
|
39
37
|
|
|
40
38
|
**書き換えるときは `pnpm josh` のコマンドで置き換えられないかを先に見る。** 例えば Issue の状態を読むのは
|
|
41
39
|
`gh issue view` ではなく `pnpm josh issue:state <N>` で、これはラベルと `human_review` まで一度に返す。
|
|
@@ -14,4 +14,4 @@
|
|
|
14
14
|
- **interrupt** — WIP 上限を超えても起票できる、3 条件で決まる発見。別パッケージ起因の上流起票(割り込み Issue)とは別の区分。→ `prompts/collaboration-workflow/wip-cap.md` → "割り込み起票"、`prompts/collaboration-workflow/upstream-interrupt.md` → "別パッケージ起因の問題は割り込み Issue で対応する"
|
|
15
15
|
- **Tier** — 判断点の 3 区分。A は可逆で自分で決める、B は拮抗していて人に聞く、C は不可逆・共有状態で明示指示が要る。→ `CLAUDE.md` → "Decision autonomy"、`prompts/collaboration-workflow/operating-rules.md` → "意思決定の自律ポリシー"
|
|
16
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/
|
|
17
|
+
- **wave** — エピックの子をまとめて並行実行する組。仕組みではなく、依存宣言で表す形。→ `.claude/skills/epic-commands/execution-waves.md` → "Execution waves — parallel, then one alone, then the rest"
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## セッション向け出力で Issue はリンク+セッション言語の短い要約で参照する(joshuafolkken/kit#1758)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
番号だけの言及では、読み手は番号を内容に解決するために毎回 GitHub を開くことになる(`docs/maintainers/issue-citation-rationale.md` → "Why the rule exists")。発火点が `CLAUDE.md` に常駐している理由は `docs/maintainers/issue-citation-rationale.md` → "Why the trigger is resident in CLAUDE.md" にある。
|
|
6
6
|
|
|
7
7
|
**規則**: セッション向け出力で Issue を指すときは、次の 2 つを必ず添える。
|
|
8
8
|
|
|
@@ -13,11 +13,11 @@
|
|
|
13
13
|
|
|
14
14
|
- `[#<N>](https://github.com/<owner>/<repo>/issues/<N>) — <その Issue が何をするものかの短い要約>`
|
|
15
15
|
|
|
16
|
-
**この引用行は手で組み立てるものではなく、`pnpm josh issue:cite <N> [<N> ...]` が出す。** 番号を並べて渡すと、貼れる引用行を 1 呼び出しでまとめて出す(複数 Issue に 1 回、他リポジトリは `--repo <owner/repo>` あるいは `owner/repo#N`
|
|
16
|
+
**この引用行は手で組み立てるものではなく、`pnpm josh issue:cite <N> [<N> ...]` が出す。** 番号を並べて渡すと、貼れる引用行を 1 呼び出しでまとめて出す(複数 Issue に 1 回、他リポジトリは `--repo <owner/repo>` あるいは `owner/repo#N` 表記。`docs/maintainers/issue-citation-rationale.md` → "Why issue:cite prints the line")。要約はその Issue のタイトルをそのまま用いる。詳細は [docs/josh-commands.md](https://github.com/joshuafolkken/kit/blob/main/docs/josh-commands.md) の `josh issue:cite` を参照。
|
|
17
17
|
|
|
18
18
|
**要約タイトルは全訳ではなく要約でよい。** 何をするものか分かれば足りる。長い訳を作ることが目的ではない。`issue:cite` が出すタイトルを、必要ならセッション言語に言い換えて使う。
|
|
19
19
|
|
|
20
|
-
**対応前の言及も対象である。**
|
|
20
|
+
**対応前の言及も対象である。** 「これから走らせる」「待機中」「対象外」を並べる場面も含む。
|
|
21
21
|
|
|
22
22
|
### 適用範囲
|
|
23
23
|
|
|
@@ -27,12 +27,8 @@
|
|
|
27
27
|
|
|
28
28
|
### 英語固定の 3 つとは衝突しない
|
|
29
29
|
|
|
30
|
-
英語のままにするものは従来どおり 3
|
|
31
|
-
|
|
32
|
-
### なぜ CLAUDE.md に常駐させるか
|
|
33
|
-
|
|
34
|
-
規則の発火点は「セッション向け出力で Issue 番号を書こうとした瞬間」であり、これはワークフローのスキルを読んでいないターンでも起こる。したがって発火点(引き金)と形式は `CLAUDE.md` の Communication 節に常駐させ、本文(この節)を話題ファイルに置く。常駐側は短く保ち、詳細はここから読む。
|
|
30
|
+
英語のままにするものは従来どおり 3 つ(`overview.md` →「出力の言語(`JOSH_SESSION_LANG`)」)。番号に添えるセッション言語の要約は GitHub 上の**タイトル**ではなく、セッション内の散文の一部なので、タイトルの英語固定とは矛盾しない。
|
|
35
31
|
|
|
36
32
|
### 停止時の担保(joshuafolkken/kit#2247)
|
|
37
33
|
|
|
38
|
-
`Stop` フック `pnpm josh stop:guard` が返信の地の文に裸の `#N` を見つけると**停止をブロックし**、その番号と `pnpm josh issue:cite <N...>`
|
|
34
|
+
`Stop` フック `pnpm josh stop:guard` が返信の地の文に裸の `#N` を見つけると**停止をブロックし**、その番号と `pnpm josh issue:cite <N...>` の実行形を差し戻す。差し戻されたら、その実行形で引用し直す(仕組みは `docs/maintainers/issue-citation-rationale.md` → "How the Stop hook delivers it")。検出が外す範囲は [docs/josh-commands.md](https://github.com/joshuafolkken/kit/blob/main/docs/josh-commands.md) の `josh stop:guard` を参照。
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Issue には次の要素を必ず含める。
|
|
4
4
|
|
|
5
|
-
-
|
|
5
|
+
- タイトルは簡潔で明瞭な英語で記載する(「出力の言語(`JOSH_SESSION_LANG`)」の例外)。日本語のタイトルや改善できる英語のタイトルは、実装開始前に書き換え、`gh api -X PATCH repos/{owner}/{repo}/issues/<N> -f title="<title>"` で GitHub 側も合わせる
|
|
6
6
|
- 目的(何を改善したいか)
|
|
7
7
|
- 現象(現在の不具合や課題)
|
|
8
8
|
- 期待結果(完了時の状態)
|
|
@@ -32,17 +32,17 @@ Issue には次の要素を必ず含める。
|
|
|
32
32
|
|
|
33
33
|
## 発火点
|
|
34
34
|
|
|
35
|
-
<AI の振る舞いを変える Issue のみ。その規則が破れる瞬間に最初に呼ばれるツールコール名を 1 つだけ書く(例 `Bash` / `Edit` / `Read` / `Write` / `AskUserQuestion
|
|
35
|
+
<AI の振る舞いを変える Issue のみ。その規則が破れる瞬間に最初に呼ばれるツールコール名を 1 つだけ書く(例 `Bash` / `Edit` / `Read` / `Write` / `AskUserQuestion`)>
|
|
36
36
|
|
|
37
37
|
## ベースライン
|
|
38
38
|
|
|
39
|
-
<AI の振る舞いを変える Issue
|
|
39
|
+
<AI の振る舞いを変える Issue のみ。「コマンド + 値」で書く>
|
|
40
40
|
|
|
41
41
|
- `<測定コマンド>` → <現在の値>
|
|
42
42
|
|
|
43
43
|
## 再現
|
|
44
44
|
|
|
45
|
-
<AI の振る舞いを変える Issue
|
|
45
|
+
<AI の振る舞いを変える Issue のみ。「コマンド + 実際の出力」で書き、出力はフェンス(``` または ~~~)で囲む>
|
|
46
46
|
|
|
47
47
|
- `<再現コマンド>`
|
|
48
48
|
|
|
@@ -55,36 +55,26 @@ Issue には次の要素を必ず含める。
|
|
|
55
55
|
<別リポジトリのセッションから起票した場合のみ。起票元 Issue を `owner/repo#N` 形式で書く。自リポジトリ発の Issue では節ごと省略する>
|
|
56
56
|
````
|
|
57
57
|
|
|
58
|
-
###
|
|
58
|
+
### `## 背景` 直下の宣言と分類ラベル
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
起票は `pnpm josh issue:file "<title>" --body-file <本文ファイル> --depth <n>` で行う。本文の検査(`pnpm josh issue:lint <path>` と同じ)と、下表の宣言から決まる分類ラベルの付与は、このコマンドが 1 回の作成リクエストで行う。**宣言を選ぶのは起票者の判断であり、コマンドは単語から推測しない。**
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
| 宣言 | 付くラベル | 選ぶ基準 |
|
|
63
|
+
| ---------------------- | ----------------- | ------------------------------------------------------------------------------------------ |
|
|
64
|
+
| `- 種別: 不具合` | `bug` | 報告された症状を直す。`- 種別: 非不具合` とどちらか一方を必ず置く |
|
|
65
|
+
| `- 目的: 機能追加` | `enhancement` | 新しい機能。不具合修正・文書のみ・依存更新・保守作業には書かない |
|
|
66
|
+
| `- 目的: 機能改善` | `enhancement` | 既存機能の改善。目的が曖昧なら期待結果と受け入れ条件を具体化してから選ぶ |
|
|
67
|
+
| `- 互換性: 破壊的変更` | `breaking-change` | 既存の利用者・API・設定の契約を変える。移行措置があっても書き、廃止対象と影響を説明する |
|
|
68
|
+
| `- 種別: 振る舞い変更` | なし | AI の振る舞いを変える。`## 発火点` / `## ベースライン` / `## 再現` の 3 見出しが必須になる |
|
|
63
69
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
<なぜ必要か>
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
- **起票前に不具合かどうかを必ず選ぶ。** `## 背景` の直下に、不具合なら `- 種別: 不具合`、非不具合なら `- 種別: 非不具合` を置く。両方の併記も省略も `pnpm josh issue:lint` が拒否する。故障を述べる本文でも単語から自動判定せず、起票者が判断する。振る舞い変更、機能改善、互換性の宣言はこの判断と併記できる
|
|
73
|
-
- **不具合修正の Issue は `- 種別: 不具合` を宣言する。** この宣言がある Issue では、`pnpm josh git -y` が追加・変更したテストを修正前のツリー(merge-base)に当てて `pnpm josh test:red` で実行し、1 本も赤にならない(`green`)ときはコミットを拒否する。修正前でも緑の回帰テストは、報告された症状を再現していないためである(joshuafolkken/kit#2448)。回帰テストは、利用者が症状を見たのと同じ粒度で書く
|
|
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
|
-
- **`## 発火点`** には、その規則が破れる瞬間に最初に呼ばれるツールコール名を 1 つ書く。名前は `prompts/collaboration-workflow/rule-delivery.md` の配送表に載る、フックで配送可能なツール(`Bash` / `Edit` / `Read` / `Write` / `AskUserQuestion`)と突き合わせる。**表に無い名前**(そもそもツールコール名でない)と**不一致**(既知のツールだが配送できない)は区別して印字され、joshuafolkken/kit#2201 の「規則は正しいが名指ししたコールが実際に破れるコールの 1 つ後ろ」を起票時に検出する
|
|
79
|
-
- **`## ベースライン`** は **「コマンド + 値」** で書く。``- `<測定コマンド>` → <現在の値>`` の形に限り、自然文だけの測定説明は受け付けない(再実行できないため)。マージ後に `pnpm josh measure:rerun <N>` が同じコマンドをやり直し(本文は shell として実行されるため、作者が `OWNER` / `MEMBER` / `COLLABORATOR` の Issue に限る)、**before / after の対**を印字する。値が動かなかったとき、反証された前提として `docs/maintainers/observations/` の、その時点のブランチが指す Issue のファイルに 1 行追記される(既存の append-only 台帳を使い、別の台帳は作らない)
|
|
80
|
-
- **`## 再現`** は **「コマンド + 実際の出力」** で書く。コマンドを backtick、出力をフェンス(``` または ~~~)で囲む。自然文の「確認した」は再実行できないため受け付けない(`## ベースライン` と同じ理由)。読みだけの起票を起票時に弾くためである
|
|
81
|
-
- **検査は `pnpm josh issue:lint <path>` が行う。** 対象判定・3 見出しの有無・発火点の配送可否・ベースラインが「コマンド + 値」か・再現が「コマンド + 実際の出力」かと、起票時に必要な分類ラベルを、起票前の本文ファイルからまとめて答える(`pnpm josh issue:file` は起票前に同じ検査を行い、問題があれば起票しない)
|
|
70
|
+
- **`- 種別: 不具合` の Issue の回帰テストは、利用者が症状を見たのと同じ粒度で書く。** 修正前のツリーでも緑になるテストは `pnpm josh git -y` がコミットを拒否する(joshuafolkken/kit#2448)
|
|
71
|
+
- **`bugfix` は PR のリリース分類であり、Issue の `bug` の代わりにしない。** `enhancement` と `breaking-change` の両方を持つ Issue の PR は `breaking-change` 一つに分類する
|
|
72
|
+
- **`## 発火点`** の名前は `prompts/collaboration-workflow/rule-delivery.md` の配送表と突き合わされる
|
|
73
|
+
- **`## ベースライン`** の測定コマンドは、マージ後に `pnpm josh measure:rerun <N>` が再実行して before / after を印字する(作者が `OWNER` / `MEMBER` / `COLLABORATOR` の Issue に限る)
|
|
82
74
|
|
|
83
75
|
### 起票元へのバックリンク(`## Origin` / `## Upstream issues`)
|
|
84
76
|
|
|
85
|
-
**別リポジトリのセッションから起票した Issue
|
|
86
|
-
|
|
87
|
-
**双方向とも必須**(片方向では、上流の修正を待っている消費者側が「何を待っているのか」を辿れない):
|
|
77
|
+
**別リポジトリのセッションから起票した Issue には、起票元へのリンクを双方向で必ず書く。** 欠陥がどのプロジェクトでどう現れたかの証拠は起票元にしかない。
|
|
88
78
|
|
|
89
79
|
| 方向 | 置き場所 | 固定見出し | 内容 |
|
|
90
80
|
| --------------------- | ----------------------------- | ----------------------- | ---------------------------------------------------- |
|
|
@@ -92,106 +82,41 @@ Issue には次の要素を必ず含める。
|
|
|
92
82
|
| 起票元 Issue → 上流 | 起票元 Issue の本文かコメント | `## Upstream issues` | そこから起票した上流 Issue を全件列挙する |
|
|
93
83
|
| 起票元 Issue → 未起票 | 起票元 Issue の本文かコメント | `## Upstream candidate` | 第三者リポジトリへ報告する候補(**未起票**)と下書き |
|
|
94
84
|
|
|
95
|
-
-
|
|
96
|
-
- **リンクは必ずリポジトリ修飾する**(`owner/repo#N` または完全 URL
|
|
97
|
-
- **チェックボックス行(`- [ ] owner/repo#N
|
|
98
|
-
-
|
|
99
|
-
-
|
|
85
|
+
- **見出しは固定する**(grep で見つかるように)。起票元の本文が確定済みなら、同じ見出しでコメントに書く
|
|
86
|
+
- **リンクは必ずリポジトリ修飾する**(`owner/repo#N` または完全 URL)。裸の `#N` は上流側で別 Issue に解決される
|
|
87
|
+
- **チェックボックス行(`- [ ] owner/repo#N`)で書かない。** 散文か素の箇条書き(`- owner/repo#N`)にする — チェックボックス付きの他リポジトリ参照は epic の自動クローズを止める
|
|
88
|
+
- **未起票の候補は `## Upstream candidate` に置く。** third-party への報告はユーザーの明示指示まで起票しない(→「第三者リポジトリへの書き込みは Tier C(明示指示が必要)」)
|
|
89
|
+
- 割り込みで起票する手順は `upstream-interrupt.md`
|
|
100
90
|
|
|
101
91
|
### 複数 Issue に分割するときの epic Issue
|
|
102
92
|
|
|
103
|
-
|
|
93
|
+
**1 つの要望を 2 件以上の Issue に分割したら、件数や順序の有無にかかわらず常に epic を作る。** 分割の設計図を、最初にクローズされる子 Issue ではなく閉じない置き場に残すためである。作成は `pnpm josh epic`、点検は `pnpm josh epic:check <E>`、子の追加は `pnpm josh epic --add` で行い、本文を手で編集しない。epic 自体を実装ランに渡さない(`backlogrun #<E> --only` が子を回す)。コマンドと本文の記法は `epic-commands` スキル →「Creating an epic」。
|
|
104
94
|
|
|
105
|
-
|
|
95
|
+
**`josh` が使えない環境での手作業手順:**
|
|
106
96
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
-
|
|
110
|
-
- epic は最後の子 Issue がクローズされた時点で `pnpm josh followup` が自動クローズする。マージ後に `epic` ラベルの open な Issue を探し、タスクリストの子が全てクローズ済みなら子を列挙したコメント付きで閉じる。1 件でも open なら放置し、この処理の失敗は警告のみでランを止めない。最終 PR に `closes #<epic>` を書く方法は、バッチが途中で失敗したときにも発火して未完了を完了扱いにするため採用しない
|
|
111
|
-
- 自動クローズは `epic` ラベルとタスクリスト記法の両方に依存する。どちらかを欠くと epic は open のまま残るので、手動でクローズする
|
|
112
|
-
- タスクリストが**他リポジトリの子 Issue**(`owner/repo#N` や URL 形式)を含む場合、自動クローズは行われない。その子の状態は別リポジトリを指定しないと読めず、無視すると open のまま epic を閉じてしまうため。この場合も手動でクローズする
|
|
113
|
-
- **分割そのものが別リポジトリのセッション発である場合**(消費者リポジトリでの `kickoff new` が上流に子 Issue を起票したなど)、各子 Issue の本文に `## Origin` を、epic 本文にも同じ起票元へのリンクを書く(→「起票元へのバックリンク」)。epic 側は `Split rationale` の直後に散文か素の箇条書きで置く。**チェックボックス行で書くと直前の項目に該当して自動クローズが止まる**ため、この 1 点だけは形式を守る。起票元 Issue 側にも `## Upstream issues` として起票した子 Issue と epic を列挙する
|
|
114
|
-
- epic 本文の `Dependencies` に依存の連鎖(`#N -> #M`)が書かれているのに、手順 4 の依存関係が**一件も付いていない**場合、`pnpm josh followup` が子 Issue のマージごとに警告する。連鎖の形は検査しない(タスクリストの並び順を依存順と推測することになり誤検知を生むため)。判定の起点を本文の宣言に置くのは、epic の存在がもう順序ありを意味しないため — 順序不問のバッチにも epic を作る以上、依存関係ゼロ件は正常な状態でもありうる
|
|
97
|
+
1. 子 Issue をすべて起票し、番号を控える。
|
|
98
|
+
2. ラベルを用意する: `gh api repos/{owner}/{repo}/labels -f name=epic -f color=5319e7 -f description="Tracks a batch of child issues from one split" --silent 2>/dev/null || true`
|
|
99
|
+
3. epic を作り、`id` ではなく **number** を控える: `gh api repos/{owner}/{repo}/issues -f title="<epic-title>" -f 'labels[]=epic' -F body=@<body-file> --jq .number`。本文は次の形にする(順序がなければ `Dependencies` に `None — the children are independent; any execution order works.` と書く):
|
|
115
100
|
|
|
116
|
-
|
|
101
|
+
```md
|
|
102
|
+
## Split rationale
|
|
117
103
|
|
|
118
|
-
|
|
119
|
-
# 順序不問のバッチ
|
|
120
|
-
pnpm josh epic "<epic-title>" <N1> <N2> ...
|
|
104
|
+
<why this split>
|
|
121
105
|
|
|
122
|
-
|
|
123
|
-
pnpm josh epic "<epic-title>" <N1> <N2> ... --ordered
|
|
124
|
-
|
|
125
|
-
# 分割理由の散文を渡す(`-` で標準入力)
|
|
126
|
-
pnpm josh epic "<epic-title>" <N1> <N2> --rationale-file <path|->
|
|
127
|
-
|
|
128
|
-
# 別リポジトリのセッション発である場合のバックリンク
|
|
129
|
-
pnpm josh epic "<epic-title>" <N1> <N2> --origin <owner/repo#N>
|
|
130
|
-
```
|
|
106
|
+
## Dependencies
|
|
131
107
|
|
|
132
|
-
|
|
108
|
+
#101 -> #102
|
|
133
109
|
|
|
134
|
-
|
|
110
|
+
## Execution
|
|
135
111
|
|
|
136
|
-
|
|
112
|
+
backlogrun #<E> --only
|
|
137
113
|
|
|
138
|
-
|
|
139
|
-
2. `epic` ラベルを用意する(未作成なら `gh api repos/{owner}/{repo}/labels -f name=epic -f color=5319e7 -f description="Tracks a batch of child issues from one split" --silent 2>/dev/null || true`)
|
|
140
|
-
3. epic を作成し、番号 `<E>` を控える: `gh api repos/{owner}/{repo}/issues -f title="<epic-title>" -f 'labels[]=epic' -F body=@<body-file> --jq .number`(`--jq` を落とすと Issue の JSON 全体が出る。そこには `id` も含まれるが、**控えるのは `number` である** — `id` はデータベース id で、手順 4 が要求する値ではあっても epic の番号ではない)
|
|
141
|
-
4. 実行順序が**ある場合のみ**、子 Issue に依存関係を付与する(後述の理由により**作成後の独立ステップ**として行う):
|
|
114
|
+
## Progress
|
|
142
115
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
gh api repos/{owner}/{repo}/issues/<N3>/dependencies/blocked_by -F issue_id="$(gh api repos/{owner}/{repo}/issues/<N2> --jq .id)"
|
|
116
|
+
- [ ] #101 <title>
|
|
117
|
+
- [ ] #102 <title>
|
|
146
118
|
```
|
|
147
119
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
順序が不問なら手順 4 は行わない。epic の作成は無条件だが、依存関係の記録は順序が実在するときだけで、両者は独立している。
|
|
151
|
-
|
|
152
|
-
手順 2 の `|| true` はラベルが既に存在する場合(REST は 422 `already_exists` を返す)を無視するためのものである。**握り潰しの代償は `gh` の頃と変わっており、安全な方向に変わっている。** `gh issue create --label epic` はラベルを解決できずに失敗したため、異常は手順 3 で顕在化した。REST の `POST /issues` は `labels` に無いラベルを**その場で作る**(色と説明は既定値、joshuafolkken/kit#1026 が実測)ので、握り潰しが失うのは色と説明だけでラベル自体ではない。`epic:next` と自動クローズは名前だけを見るため、追跡は成立する。
|
|
153
|
-
|
|
154
|
-
手順 4 は REST の依存関係エンドポイントを直接叩くので `gh` のバージョンに依存しない。**失敗しても続行してよい**(付かないのは関係だけで、Issue とタスクリストは無傷)。関係付与は作成と分けて行う — 作成呼び出しに畳み込むと、関係の失敗が Issue の失敗になり、**Issue 自体が作られない**。分けておけば劣化は「Issue が消える」ではなく「関係が付かない」で済む。
|
|
155
|
-
|
|
156
|
-
epic 本文のテンプレート:
|
|
157
|
-
|
|
158
|
-
```md
|
|
159
|
-
## Split rationale
|
|
160
|
-
|
|
161
|
-
<なぜこの分割にしたか>
|
|
162
|
-
|
|
163
|
-
## Dependencies
|
|
164
|
-
|
|
165
|
-
#101 -> #102 -> #103
|
|
166
|
-
|
|
167
|
-
## Execution
|
|
168
|
-
|
|
169
|
-
backlogrun #<E> --only
|
|
170
|
-
|
|
171
|
-
## Progress
|
|
172
|
-
|
|
173
|
-
- [ ] #101 <title>
|
|
174
|
-
- [ ] #102 <title>
|
|
175
|
-
- [ ] #103 <title>
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
`Progress` は**必ずタスクリスト記法**(`- [ ] #N`)で書く。GitHub は参照先 Issue がクローズされた時点でこの記法のチェックボックスのみを自動で埋めるため、素のリンク(`#N` の直書き)では進捗が追跡されない。ただし全項目が埋まっても GitHub が epic 自体をクローズすることはない。
|
|
179
|
-
|
|
180
|
-
`Dependencies` は順序があるなら**必ず矢印記法**(`#101 -> #102`、`->` または `→`)で書く。`pnpm josh followup` の順序未記録チェックはこの記法を検出して初めて発火するため、`#102 depends on #101` のような散文で書くと、手順 4 を飛ばしても警告されない。順序が不問なら節ごと省略せず `None — the children are independent; any execution order works.` と明示する。空欄や節の削除では「順序がない」のか「書き忘れた」のかが読み手にもチェックにも区別できない。
|
|
181
|
-
|
|
182
|
-
**宣言の行は矢印の連鎖だけで構成する。** 理由の注記を同じ行の末尾に付けた `#101 -> #102 (#102 は #101 の API を使う)` は宣言として読まれず、`epic:check` が「機械可読な宣言が無い」と報告する。読み取り側が「連鎖しか書かれていない行」だけを宣言と見なすのは、節の外にある散文の推奨実行順(`推奨実行順: #869 -> #863 -> …`)を宣言と誤読しないためで、この判定は本文を読む 3 経路(`epic:check` の存在判定・`epic:next` のリンク読み取り・`josh epic --add` の書き換え)で共有されている(joshuafolkken/kit#858、joshuafolkken/kit#1155)。理由は連鎖の**次の行**か `Split rationale` に書く。**連鎖と `None — ...` 固定文を両方書いてはならない** — 順序があると同時に無いと宣言することになり、`epic:check` は矛盾として ✖ を返す。
|
|
183
|
-
|
|
184
|
-
#### ネイティブの依存関係と sub-issues
|
|
185
|
-
|
|
186
|
-
`gh` は Issue 間の関係をネイティブに扱える。下表のフラグと JSON フィールドは **2.97.0 の実バイナリで存在を確認済み**。導入バージョンを 2.94.0 とするのは `cli/cli` のリリースノート記載によるもので、2.94.0 自体での動作確認は行っていない。GitHub Enterprise Server では依存関係に 3.19 以降が必要(github.com では制約なし)。
|
|
187
|
-
|
|
188
|
-
**下表は `gh` CLI の対応状況の記録であり、本ドキュメントのどの手順もこれを経由しない。** `pnpm josh epic` も上記のフォールバック手順 4 も、REST の依存関係エンドポイントを `gh api` で直接叩くため、下表のフラグにも 2.94.0 要件にも依存しない(joshuafolkken/kit#1026)。**下表の形は `gh issue edit` / `gh issue view` であり、いずれも GraphQL を通るためクラウドセッションでは 403 になる**(joshuafolkken/kit#1022)。表を残すのは、sub-issues を採らなかった理由が CLI の対応状況とは無関係であることを示すためである。
|
|
189
|
-
|
|
190
|
-
| 種別 | 書き込み | 読み取り |
|
|
191
|
-
| -------- | -------------------------------------------------------------------------- | ------------------------------------------------------------ |
|
|
192
|
-
| 依存関係 | `gh issue edit <N> --add-blocked-by <M>` / `--add-blocking` / `--remove-*` | `gh issue view <N> --json blockedBy,blocking` |
|
|
193
|
-
| 親子関係 | `gh issue edit <N> --parent <M>` / `--add-sub-issue` | `gh issue view <N> --json parent,subIssues,subIssuesSummary` |
|
|
194
|
-
|
|
195
|
-
**依存関係は採用する**(上記の作成手順 4)。子 Issue 単体を見たときに何を待っているかが GitHub の UI と API の両方から分かるようになり、epic 本文の `Dependencies` 行が人間向けの散文でしかなかった問題が解消する。ただし依存関係は**表示するだけで着手を防がない**ため、順序を守る責任は引き続き依存関係の宣言(`--ordered`)と、それを読む `backlogrun` にある。epic 本文の `Dependencies` 行は、関係が付かなかった場合でも読める冗長な記録として残す。
|
|
120
|
+
4. 順序があるときだけ、別ステップで依存を足す(Issue 番号ではなく database id を渡す): `gh api repos/{owner}/{repo}/issues/<N2>/dependencies/blocked_by -F issue_id="$(gh api repos/{owner}/{repo}/issues/<N1> --jq .id)"`
|
|
196
121
|
|
|
197
|
-
|
|
122
|
+
各手順の理由と経緯は kit の `docs/maintainers/epic-commands-rationale.md` →「Creating an epic by hand」。
|
|
@@ -30,8 +30,7 @@ PR マージ・ブランチ削除・force push・共有ブランチへの push
|
|
|
30
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
|
-
-
|
|
34
|
-
- **同じ規則が禁じる force push とブランチ削除も deny に載っている**(joshuafolkken/kit#1062)。**deny は規則より狭いが、その差は配送ガードが埋めている** — `git -C` を前置した綴り、短縮フラグをまとめた綴り(`git push -uf`)、`:` をリテラルにできず glob が照合できない `git push origin :branch` は、いずれも `pnpm josh rule:guard` の `git-force` 行が argv を解析して拒否する(joshuafolkken/kit#2120)。**「マージ経路は deny が保証している」とは読まないこと**
|
|
33
|
+
- **deny と配送ガードは実装であって規則ではない。** `gh pr merge`・force push・ブランチ削除の直接実行は `.claude/settings.json` の `permissions.deny` と `pnpm josh rule:guard` が拒否する(一覧は各ファイルと [`rule-delivery.md`](./rule-delivery.md) →「配送されている規則」)が、それらが取りこぼす綴りを禁じているのは本節の規則のほうである。`fullrun` の auto-merge は `pnpm josh followup` の内部から gh を起動するため影響を受けない
|
|
35
34
|
- **共有状態に影響する操作(このセクションの対象=Tier C)は迷ったら確認する。** 確認のコストは低いが、意図しない操作の巻き戻しは高コスト
|
|
36
35
|
- ただしこの「迷ったら確認」は Tier C に限る。**可逆な実装・設計判断(Tier A)は別ルール**(下記「意思決定の自律ポリシー」)に従う
|
|
37
36
|
|
|
@@ -50,9 +49,9 @@ PR マージ・ブランチ削除・force push・共有ブランチへの push
|
|
|
50
49
|
- 上記以外で staging が必要だと考えたときは、**実行せずに先に確認する**
|
|
51
50
|
- **レーンの中で競合を解決したあとの「解決済み」の記録は、ケース 2 に含まれる(Tier A)。** レーンは run 専用の作業ツリーで、守るべき利用者の staging はない。利用者に `git add` の許可を求めず、`pnpm josh git -y` で記録する。手順は `.claude/skills/workflow-commands/chain-rule.md` →「origin/main is merged in before the gate」の 1 か所にだけ書く(joshuafolkken/kit#2445)
|
|
52
51
|
- 同じ理由で、`git reset` / `git checkout -- <path>` / `git restore <path>` など index や作業ツリーを破壊的に書き換える操作も、自分の判断で実行しない
|
|
53
|
-
- **`git stash` は例外的に、明文化されたフローの中でのみ自動実行してよい**: `fullrun new` / `halfrun new` の手順 5(作業ツリーに変更がある状態で `josh latest` を回す前の退避)、`backlogrun` のラン開始時の `josh latest`、「別パッケージ起因の問題は割り込み Issue で対応する」、および `backlogrun` が epic の子を始める前の preflight(`pnpm josh run:hold <N>` が `reclaim` と答えたときの回収 — joshuafolkken/kit#926, joshuafolkken/kit#1965)。**この 5 番目だけが復元を伴わない。前の 4 つはいずれも直後に `pnpm josh stash:pop "<メッセージ>"` で復元することが手順に含まれている**(stash はリポジトリ単位の 1 本のスタックを全 work tree が共有するため、位置指定や引数なしの `git stash pop` は別のレーンが最後に積んだ stash を取り込む — メッセージで対象を特定する。joshuafolkken/kit#2050)。 回収するのは異常終了したランの置き土産であって、いま実行中のランの作業ではないから、pop して戻す先がない。**代わりに stash を子の Issue にコメントで記録する** — 前提 Issue で中断するときの stash(`
|
|
54
|
-
-
|
|
55
|
-
-
|
|
52
|
+
- **`git stash` は例外的に、明文化されたフローの中でのみ自動実行してよい**: `fullrun new` / `halfrun new` の手順 5(作業ツリーに変更がある状態で `josh latest` を回す前の退避)、`backlogrun` のラン開始時の `josh latest`、「別パッケージ起因の問題は割り込み Issue で対応する」、および `backlogrun` が epic の子を始める前の preflight(`pnpm josh run:hold <N>` が `reclaim` と答えたときの回収 — joshuafolkken/kit#926, joshuafolkken/kit#1965)。**この 5 番目だけが復元を伴わない。前の 4 つはいずれも直後に `pnpm josh stash:pop "<メッセージ>"` で復元することが手順に含まれている**(stash はリポジトリ単位の 1 本のスタックを全 work tree が共有するため、位置指定や引数なしの `git stash pop` は別のレーンが最後に積んだ stash を取り込む — メッセージで対象を特定する。joshuafolkken/kit#2050)。 回収するのは異常終了したランの置き土産であって、いま実行中のランの作業ではないから、pop して戻す先がない。**代わりに stash を子の Issue にコメントで記録する** — 前提 Issue で中断するときの stash(`prerequisite.md`)と同じく、**その記録だけが後で pop させられる唯一の手がかり**であり、記録し忘れた stash は誰にも拾われない。これら以外の場面で退避したくなったときは、実行せずに先に確認する
|
|
53
|
+
- **staging・index の書き換え・`git commit` の直接実行は deny されており、deny には「そのターンでユーザーが明示指示した」という例外がない。** だから上記ケース 1 は AI 側では実行できず、ユーザー自身の端末で実行してもらう。ユーザーが明示的にコミットを指示した場合も、承認済みのコミットは `pnpm josh git` を通す(理由は `docs/maintainers/operating-rules-rationale.md` → "Why the index is the user's")
|
|
54
|
+
- **ツールが通したことを許可と読み替えてはならない。** deny と `pnpm josh rule:guard`(`worktree-mutation`・`index-mutation`・`destructive-command`・`protected-file` 行)は事故防止の実装で、規則より狭い。何をしてよいかを決めるのはこのルールである
|
|
56
55
|
|
|
57
56
|
### 意思決定の自律ポリシー(確認停止を減らす)
|
|
58
57
|
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
# コマンド出力が文脈へ持ち込む量の上限(joshuafolkken/kit#1173)
|
|
2
2
|
|
|
3
|
-
**上限は機構で決まり、実行側の判断には委ねられない。**
|
|
4
|
-
|
|
5
|
-
## 何をしているか
|
|
6
|
-
|
|
7
|
-
配布される `.claude/settings.json` の `env` ブロックが `BASH_MAX_OUTPUT_LENGTH` を宣言する。Claude Code は Bash ツールの出力がこの文字数を超えると真ん中を省略して渡すので、**1 回のコマンドが文脈へ持ち込む量に harness 側で上限が掛かる**。エージェントは何も判断しない。
|
|
3
|
+
**上限は機構で決まり、実行側の判断には委ねられない。** 配布される `.claude/settings.json` の `env` ブロックが `BASH_MAX_OUTPUT_LENGTH` を宣言し、Claude Code は Bash ツールの出力がこの文字数を超えると真ん中を省略して渡す。
|
|
8
4
|
|
|
9
5
|
```json
|
|
10
6
|
"env": {
|
|
@@ -12,96 +8,34 @@
|
|
|
12
8
|
}
|
|
13
9
|
```
|
|
14
10
|
|
|
15
|
-
**8,000
|
|
16
|
-
|
|
17
|
-
## なぜ既定の 30,000 では足りないか
|
|
18
|
-
|
|
19
|
-
直近 25 セッション・tool_result 2,333 件を実測した。**Bash の出力は tool_result トークンの 87.5%(1,848 件・1,241,642 トークン)**を占める。その 1,848 件のうち **30,000 文字を超えたものは 0 件**だった — 既定の上限はこのプロジェクトで一度も作動していない。存在するが届かない上限は、上限が無いのと同じである。
|
|
20
|
-
|
|
21
|
-
Bash 出力の長さの分布(文字数): p50 = 570 / p75 = 1,920 / p90 = 4,421 / p95 = 8,342 / p99 = 15,989 / 最大 = 28,908。
|
|
22
|
-
|
|
23
|
-
上限ごとに、真ん中を省略したときに削れる量:
|
|
24
|
-
|
|
25
|
-
| 上限(文字) | 該当する呼び出し | 削れる量(tool_result 全体に対して) |
|
|
26
|
-
| -------------- | ----------------- | ------------------------------------ |
|
|
27
|
-
| 4,000 | 218 件(11.8%) | 26.6% |
|
|
28
|
-
| 6,000 | 124 件(6.7%) | 18.2% |
|
|
29
|
-
| **8,000** | **95 件(5.1%)** | **12.7%** |
|
|
30
|
-
| 10,000 | 69 件(3.7%) | 8.7% |
|
|
31
|
-
| 15,000 | 22 件(1.2%) | 2.5% |
|
|
32
|
-
| 30,000(既定) | 0 件 | 0% |
|
|
33
|
-
|
|
34
|
-
**8,000 を採ったのは p95 だからである。** 20 回に 19 回はこれまでと何も変わらず、残る 1 回だけが範囲を指定して読み直す形になる。4,000 は削れる量こそ倍だが 8 回に 1 回が切り詰められ、読み直しの往復が上限で浮かせた分を食い返す。
|
|
35
|
-
|
|
36
|
-
## 却下した案と、その理由
|
|
37
|
-
|
|
38
|
-
- **非有界コマンドを PreToolUse guard が拒否する。** 実測が否定した。tool_result の上位には `cd`(5.4%)と `for`(4.4%)が入り、先頭語を見ても正体が分からない — 命令は `cd <dir> && …` や `for n in …; do …; done` の内側にある。さらに 2 位の `sed`(16.6%)は本 Issue が推奨する範囲指定の形そのもので、構文上は有界なのに 1 ブロック 8,000 トークンを運んでいる(`sed -n '30,400p'`)。**形で見分ける案は、実データ上で外れる。** 大きさで切る案にはこの弱点がない。
|
|
39
|
-
- **共通ラッパで切り詰める(`josh` のサブコマンド等)。** ラッパを通すかどうかが実行側の判断になり、本 Issue が問題視した構造がそのまま残る。上限を機構にするという要件を満たさない。
|
|
11
|
+
**8,000 文字**(harness の既定は 30,000、受け付ける最大は 150,000)。値の根拠となった分布と却下した案は `docs/maintainers/output-bounds-rationale.md` → "Why 8,000"。上限は **Bash ツールにだけ効き**、`Read` と `Agent` の結果には効かない。
|
|
40
12
|
|
|
41
13
|
## 切り詰められたときにどうするか
|
|
42
14
|
|
|
43
15
|
**情報を落とすのではなく、必要な範囲に合わせて読み直す。** 同じコマンドを再実行しても上限は同じなので、絞り込んで読む:
|
|
44
16
|
|
|
45
17
|
- ファイルなら範囲を指定する(`sed -n '120,180p' <file>`)か、`Read` ツールの `offset` / `limit` を使う
|
|
46
|
-
- 一覧なら件数を絞る(`--limit`、`| head -30`)
|
|
47
|
-
- JSON なら必要な項目だけ取り出す(`gh api … --jq '…'`)
|
|
18
|
+
- 一覧なら件数を絞る(`--limit`、`| head -30`)、JSON なら必要な項目だけ取り出す(`gh api … --jq '…'`)
|
|
48
19
|
- どうしても全量が要るときは、いったんファイルへ落として(`> <file>`)から範囲を読む
|
|
49
20
|
|
|
50
21
|
## 切り詰められた出力を、完全な出力として読まない
|
|
51
22
|
|
|
52
|
-
**検証ゲートと差分は、切り詰められた結果で判断しない。**
|
|
23
|
+
**検証ゲートと差分は、切り詰められた結果で判断しない。** 省略された箇所には harness がマーカーを残す — それは「短い出力」ではなく「一部しか読んでいない出力」である。
|
|
53
24
|
|
|
54
|
-
- **`pnpm josh gate
|
|
55
|
-
- **差分には判定行が無い。**
|
|
56
|
-
|
|
57
|
-
```bash
|
|
58
|
-
git diff main...HEAD > /tmp/diff.patch && wc -l /tmp/diff.patch
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
**切り詰めは黙って起きない** — 省略された箇所には harness がマーカーを残す。マーカーを見たら、それは「短い出力」ではなく「一部しか読んでいない出力」である。
|
|
25
|
+
- **`pnpm josh gate`** は合否の 1 行を末尾に出すので判定は失われない。失敗の内訳が切れたら、合否行の直前に出る **`full output: <path>` のファイルを読む**(joshuafolkken/kit#1227)
|
|
26
|
+
- **差分には判定行が無い。** 欠けた差分で「指摘なし」とするのはゲートを弱めたのと同じなので、**差分はファイルへ落としてから範囲で読む**(`git diff main...HEAD > /tmp/diff.patch && wc -l /tmp/diff.patch`)
|
|
62
27
|
|
|
63
28
|
## 検証コマンドをパイプに繋がない(joshuafolkken/kit#1556)
|
|
64
29
|
|
|
65
|
-
**パイプラインの終了コードは最後のコマンドのものである。** `pnpm josh gate 2>&1 | tail -40` は `tail` の終了コードで終わるので、**赤いゲートがシェルの上では成功として返る。**
|
|
66
|
-
|
|
67
|
-
joshuafolkken/kit#1546 の実行中に実際に起きた。2 回目のゲートが `✗ verification gate failed` を印字しながら、パイプラインは 0 を返していた。失敗は本物(Prettier の整形と、マーカーテスト 1 件)で、**実行した子が出力を読んでいたから気づいた**。終了コードだけを見ていれば、赤いツリーがそのままコミットされていた。
|
|
30
|
+
**パイプラインの終了コードは最後のコマンドのものである。** `pnpm josh gate 2>&1 | tail -40` は `tail` の終了コードで終わるので、**赤いゲートがシェルの上では成功として返る。** **これは `josh gate` の欠陥ではない。** POSIX どおりの挙動であり、直すべきは呼び出し方である。
|
|
68
31
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
- **既定はパイプなしで実行する。** josh の各チェックは合否の 1 行を末尾に出すので、この文書の上限で真ん中が省略されても判定は残る(前節)。切り詰める理由がそもそも無い
|
|
74
|
-
- **出力をどうしても絞るなら、ファイルへ落として範囲で読む**(`pnpm josh gate > /tmp/gate.log 2>&1; tail -40 /tmp/gate.log`)。リダイレクトは終了コードを奪わない
|
|
75
|
-
- **パイプが避けられないなら `set -o pipefail` を前置する。** パイプラインが検証側の終了コードを運ぶ
|
|
32
|
+
- **既定はパイプなしで実行する。** 判定行は末尾に出るので、上限で真ん中が省略されても残る
|
|
33
|
+
- 絞るなら、ファイルへ落として範囲で読む(`pnpm josh gate > /tmp/gate.log 2>&1; tail -40 /tmp/gate.log`)。リダイレクトは終了コードを奪わない
|
|
34
|
+
- パイプが避けられないなら `set -o pipefail` を前置する
|
|
76
35
|
- **どの形でも、印字された判定行を読む。終了コードだけを答えにしない**
|
|
77
36
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
`gate` / `check` / `lint*` / `cspell*` / `test*` / `eval` — 合否を返すものに限る。
|
|
81
|
-
|
|
82
|
-
**`git log | head` や `gh issue list | head` は対象外であり、意図的にそうしている。** 一覧を `| head` で絞るのは読み方として正しく、そこで拒否するフックは transcript の最頻形で発火することになる。**規則を広げると無視される方向に働き、無視される規則は無い規則より悪い**(`rule-delivery.md` →「誤ったターンで発火するフックは、フックが無いより悪い」)。
|
|
83
|
-
|
|
84
|
-
**フックは 2 つの形にも黙る。** `set -o pipefail` を前置したパイプラインは検証側の終了コードを運ぶので握りつぶしていない。引用符の中のコマンド列(`--body "cd x && pnpm josh gate | tail"` のような Issue 本文)はテキストであって呼び出しではない。**どちらも「規則に従った呼び出しを拒否しない」ためである** — 配送はラン 1 回きりなので、従った呼び出しで 1 回を使い切ると、後から本当に握りつぶしている呼び出しが素通りする。
|
|
85
|
-
|
|
86
|
-
`latest:scope` / `review:brief --level-only` / `review:brief` も対象外である。これらは**判定ではなく答えを印字する**コマンドで、`$(...)` で受けるのが正しい使い方である。コマンド置換そのものの無音の失敗は別の規則が扱う(`docs/josh-commands.md` →「`VAR=$(...) && cmd`」)。
|
|
87
|
-
|
|
88
|
-
### 引き金つき配送で強制する —— 却下した 2 案
|
|
89
|
-
|
|
90
|
-
- **手順書の実行例を書き換える。** 却下。**書き換える例が存在しない。** 文書・プロンプト・skill の全体を調べて、パイプ付きの検証例は `docs/josh-commands.md` の 1 件だけで、しかもそれはこの不具合の説明そのものだった。パイプは手本から写されているのではなく、**毎ターン新しく発明されている**
|
|
91
|
-
- **呼び出し規約として書く**(「ゲートをパイプに繋ぐな」「`set -o pipefail` を前置しろ」)。却下。**同じ案が既に却下されている** — `scripts/time-runtime/time-reported-failure.ts` が「規約は守られるか守られないかのどちらかであり、図が捉えるべきは『そうすべきだったこと』ではなく『実際にしたこと』である」としてこれを退け、代わりに検出器を置いた。散文が数値を動かさなかった計測は joshuafolkken/kit#1344 と joshuafolkken/kit#1460 にもある
|
|
92
|
-
|
|
93
|
-
採ったのは**引き金つき配送**である(`rule-delivery.md`)。`pnpm josh rule:guard` が、合否を意味する josh のチェックがパイプの手前に立った `Bash` 呼び出しを**その場で拒否する**。**拒否は読み飛ばせない。**
|
|
94
|
-
|
|
95
|
-
**検出器は残る。** `scripts/time-runtime/time-reported-failure.ts` はゲート自身の `✗ verification gate failed:` 行を `is_error` の上に読む。フックが届くのは Claude Code だけで、停止スイッチを立てたセッションにも他の harness にも届かない — 検出器はその外側を覆い、かつ**規則が守られたかどうかを事後に測れる唯一の経路**である。配送と検出は代替ではなく、前者が防ぎ後者が数える。
|
|
96
|
-
|
|
97
|
-
### 検査
|
|
98
|
-
|
|
99
|
-
`scripts/rules/piped-verification-rule.test.ts` が、配送文が仕組み・逃げ道・境界の 3 つを運ぶこと、この節が規則と却下した 2 案を単一ソースとして持つこと、そして `rule-delivery.md` の列挙表に行があることを固定する。発火・非発火そのものは `scripts/rules/delivered-rules.test.ts` が両方向から固定する。
|
|
100
|
-
|
|
101
|
-
## この上限が届かないもの
|
|
102
|
-
|
|
103
|
-
`BASH_MAX_OUTPUT_LENGTH` は **Bash ツールにだけ効く**。実測では `Read` ツールが tool_result の 10.6%(単一最大 18,991 トークン)、`Agent` が 2.3% を占めており、どちらもこの上限の対象外である。別の量として別途扱う。
|
|
37
|
+
**対象は結果が合否を意味するコマンドだけ** — `gate` / `check` / `lint*` / `cspell*` / `test*` / `eval`。**`git log | head` や `gh issue list | head` は対象外であり、意図的にそうしている。** `latest:scope` / `review:brief` も、判定ではなく答えを印字するので `$(...)` で受けてよい。`pnpm josh rule:guard` がパイプの手前に検証コマンドを置いた `Bash` をその場で拒否する(`rule-delivery.md`)。経緯・却下した案・検査は `docs/maintainers/output-bounds-rationale.md` → "Why the pipe rule is delivered by a trigger"。
|
|
104
38
|
|
|
105
39
|
## 検査
|
|
106
40
|
|
|
107
|
-
`scripts/lib/bash-output-cap.test.ts`
|
|
41
|
+
`scripts/lib/bash-output-cap.test.ts` が、配布設定の上限がこの文書の値と一致し、harness の既定より小さく最大を超えないことを固定する(`docs/maintainers/output-bounds-rationale.md` → "What the tests pin")。
|