@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
|
@@ -4,37 +4,35 @@
|
|
|
4
4
|
|
|
5
5
|
### 無条件ルール: 起票は確認なし、停止は必ず
|
|
6
6
|
|
|
7
|
-
**この手順に「これは今の作業をブロックするか?」という判定は一切存在しない。**
|
|
7
|
+
**この手順に「これは今の作業をブロックするか?」という判定は一切存在しない。** 上流の欠陥は、ブロックするものもしないものも、**発見した時点で**同じ手順を通る。例外はない。判定を置かない理由は `docs/maintainers/upstream-interrupt-rationale.md` → "Why there is no blocking test" にある。
|
|
8
8
|
|
|
9
|
-
-
|
|
10
|
-
- **起票は Tier A
|
|
9
|
+
- **トリガーは「発見」であって「ブロックし始めたとき」ではない**
|
|
10
|
+
- **起票は Tier A(確認なし)**。起票してよいか、どのリポジトリへ起票するか、いずれもユーザー確認を取らない。対象は first-party に限る(→「第三者リポジトリへの書き込みは Tier C(明示指示が必要)」)
|
|
11
11
|
- **停止は無条件**。Issue が存在する状態にしてから停止する。上流の修正を待つか先送りするかは、Issue を目の前にしたユーザーが決める
|
|
12
|
-
-
|
|
13
|
-
- **`backlogrun` の中では、停止の範囲がセッション全体ではなくその子 Issue に限定される**。起票は変わらず無条件(first-party なら Tier A)で、回避策の禁止も変わらない。変わるのは停止の及ぶ範囲だけであり、該当の子に `needs-decision` を付けて park し、依存していない他の子へ進む(→「backlogrun — 子 Issue の無人実行」)。回避策を書かせないという本来の目的は、起票と回避策禁止が保たれることで維持される
|
|
12
|
+
- **`backlogrun` の中では、停止の範囲がセッション全体ではなくその子 Issue に限定される**。起票と回避策の禁止は変わらない。該当の子に `needs-decision` を付けて park し、依存していない他の子へ進む(→ `.claude/skills/workflow-commands/backlogrun-park.md` → "park and continue")
|
|
14
13
|
|
|
15
14
|
手順:
|
|
16
15
|
|
|
17
16
|
1. **現在の作業を退避する**: `git stash push -u -m "upstream-interrupt: paused #<N>"`(WIP コミットでも可)。退避したことを忘れないよう、この時点で stash を作る。メッセージ付きで積むのは、復元をメッセージで特定するため(下記ステップ 5)
|
|
18
17
|
2. **進行中の Issue に状況を明記する**: `pnpm josh issue:comment <N> --body-file <path>` で、(a) 作業を stash したこと、(b) 中断理由(どの別パッケージの・どんな問題で中断したか)、(c) 対象パッケージに作成した新 Issue へのリンクを `## Upstream issues` 見出しの下に `owner/repo#N` 形式で、を記載する。これにより「なぜこの Issue が一時停止しているか」と「何を待っているのか」が後から監査できる(→「起票元へのバックリンク」)
|
|
19
|
-
3. **対象パッケージのリポジトリに新しい Issue を作成する(確認なし)**: `pnpm josh issue:file "<root-cause title>" --body-file <body-file> --depth <n> --route tier-a --repo <owner>/<repo>`(`route:tier-a` は実装中の Tier A 起票を経路として集計するためのラベル — joshuafolkken/kit#1083
|
|
18
|
+
3. **対象パッケージのリポジトリに新しい Issue を作成する(確認なし)**: `pnpm josh issue:file "<root-cause title>" --body-file <body-file> --depth <n> --route tier-a --repo <owner>/<repo>`(`route:tier-a` は実装中の Tier A 起票を経路として集計するためのラベル — joshuafolkken/kit#1083)。本文の検査、本文が宣言する分類ラベルの付与、`## Origin` 節の確認、起票先での重複探し、`epic:bundle` はこのコマンドが実行する(`docs/josh-commands-automation.md` → `josh issue:file`)。分類の単一ソースは `prompts/collaboration-workflow/issue-template.md`。根本原因・再現・期待結果を Step 1 のテンプレに沿って記載し、**本文に `## Origin` 節を置いて起票元 Issue を `owner/repo#N` 形式で書く**(→「起票元へのバックリンク」)。ここで「起票してよいか」を尋ねて停止してはならない
|
|
20
19
|
4. **`confirmation` Telegram を送って停止する**: 上流 Issue の URL と、何が止まっているかを本文に書く(→ `CLAUDE.md` → "Mid-workflow stop notification (`confirmation`)")。無人実行でも画面外でユーザーが気付ける。停止は Issue が既に存在する状態で行うので、ユーザーは「待つ / 先送りする」を Issue を見ながら 1 語で答えられる
|
|
21
20
|
5. **元の作業を再開する**: 上流の修正がマージされた、または**ユーザーが先送りを明示判断した**後に `pnpm josh stash:pop "upstream-interrupt: paused #<N>"`(位置指定や引数なしの `git stash pop` は使わない — stash は全 work tree が共有する 1 本のスタックで、別のレーンの stash を取り込む恐れがある)して、退避していた元タスクを続行する。上流 Issue を割り込みで実装するかどうかもユーザーの判断(上流パッケージの実装・PR・マージはそれぞれのワークフロー規則に従う)
|
|
22
21
|
|
|
23
22
|
### 第三者リポジトリへの書き込みは Tier C(明示指示が必要)
|
|
24
23
|
|
|
25
|
-
上の「起票は確認なし」は **first-party
|
|
24
|
+
上の「起票は確認なし」は **first-party**(`pnpm josh repo:party` が `first-party` と答えるリポジトリ)だけに成り立つ。**自分たちが所有しないリポジトリへの書き込みは、これとは別物**として扱う。
|
|
26
25
|
|
|
27
|
-
- **判定は機械的に行い、判断に委ねない**: `pnpm josh repo:party [<owner/repo>]` が `first-party` / `third-party` / `unknown` の 1 語で答える(対象リポジトリの owner がセッションのリポジトリの owner と一致すれば **first-party**、owner を読めなければ **unknown** で third-party 扱いはしない)。**それ以外は全て third-party** で、fork も、単に contribute しているだけの org リポジトリも third-party
|
|
28
|
-
- **first-party は従来どおり**: Tier A
|
|
29
|
-
- **third-party は書き込みの種別を問わず Tier C**: Issue・コメント・PR・Discussion・レビューのいずれも、**その turn
|
|
26
|
+
- **判定は機械的に行い、判断に委ねない**: `pnpm josh repo:party [<owner/repo>]` が `first-party` / `third-party` / `unknown` の 1 語で答える(対象リポジトリの owner がセッションのリポジトリの owner と一致すれば **first-party**、owner を読めなければ **unknown** で third-party 扱いはしない)。**それ以外は全て third-party** で、fork も、単に contribute しているだけの org リポジトリも third-party に入る
|
|
27
|
+
- **first-party は従来どおり**: Tier A。確認なしで起票し、双方向バックリンクを書き、停止する
|
|
28
|
+
- **third-party は書き込みの種別を問わず Tier C**: Issue・コメント・PR・Discussion・レビューのいずれも、**その turn におけるユーザーの明示指示**なしに行ってはならない。公開は外向きかつ実質不可逆である(`docs/maintainers/upstream-interrupt-rationale.md` → "Why third-party writes are Tier C")
|
|
30
29
|
- **third-party だと判明したときの手順**: (1) **自分たちの側の Issue** に証拠込みで所見を記録する。見出しは `## Upstream candidate` を使い、`## Upstream issues` は使わない(後者は「起票済み」を主張する見出しであるため)。(2) 報告本文の下書きをその Issue 内に用意し、ユーザーが 1 メッセージで承認できる状態にする。(3) 対象プロジェクト名と報告しようとしている内容を書いた `confirmation` Telegram を送って**停止する**
|
|
31
30
|
- **third-party 報告の証拠バー**(下書きを提示する前に満たす):
|
|
32
31
|
- **自プロジェクトの外で成立する最小再現**(対象の依存だけを入れた素の scaffold)。用意できない場合は「プロジェクト組み込みの再現しかない」ことを下書きに明記する
|
|
33
32
|
- **本文の全主張が検証済み**であること。推測を事実として書かない
|
|
34
33
|
- 同じ欠陥を扱う**既存 Issue の検索**
|
|
35
34
|
- **取り下げも外向きの行為**: 既に起票した third-party Issue のクローズ・編集・コメントも、同じく明示指示を要する
|
|
36
|
-
-
|
|
37
|
-
- このルールは横断ドキュメント(CLAUDE.md「Third-party repositories are Tier C」)のカノニカル参照
|
|
35
|
+
- **正しい診断は公開の許可ではない**。所見の正しさは、この節のどの要求も免除しない(事例: `docs/maintainers/upstream-interrupt-rationale.md` → "Why a correct diagnosis is not authorization")
|
|
38
36
|
|
|
39
37
|
### 検証ゲートを緩めることも「回避策」である
|
|
40
38
|
|
|
@@ -47,5 +45,5 @@
|
|
|
47
45
|
注意:
|
|
48
46
|
|
|
49
47
|
- **即席回避と根本対応は「迷って選ぶもの」ではない**。上流起因と分かった時点で選択肢は根本対応だけであり、「今回は軽いから即席で」という判断はこの手順に存在しない
|
|
50
|
-
-
|
|
51
|
-
- このルールは横断ドキュメント(CLAUDE.md「Cross-package problems → file the upstream Issue, then
|
|
48
|
+
- 上流パッケージの **マージ等の共有状態操作** は、起票と違って Tier A ではない。通常どおりそれぞれのワークフローの明示起動を要する
|
|
49
|
+
- このルールは横断ドキュメント(CLAUDE.md「Cross-package problems → file the upstream Issue, then stop」)のカノニカル参照
|
|
@@ -10,18 +10,11 @@
|
|
|
10
10
|
|
|
11
11
|
**オープン Issue が上限を超えている状態で新しく起票するときは、先に 1 件閉じる。**
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
**件数は `pnpm josh issue:file` が起票の前に数える**(joshuafolkken/kit#3181)。手で数えることも、見積もりや記憶で済ませることもない。数え方・印字・保留の詳細は `docs/josh-commands-automation.md` → "`josh issue:file`" にある。
|
|
14
14
|
|
|
15
|
-
```bash
|
|
16
|
-
gh api "repos/{owner}/{repo}/issues?state=open&per_page=100" --paginate \
|
|
17
|
-
--jq '.[] | select(.pull_request == null) | .number' | wc -l
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
- **数えるのは「起票しようとしているリポジトリ」のオープン Issue 全件**である。`{owner}/{repo}` はカレントリポジトリに展開されるので、**別リポジトリへ起票するときはそのリポジトリのパスを直接書く**(例: `repos/joshuafolkken/app-kit/issues?...`)。自リポジトリの件数で他リポジトリへの起票を判断するのは、別のバックログを見ているのと同じである。
|
|
21
|
-
- epic も子も含める。epic を除外すると、epic を作ることで上限を回避できてしまう。
|
|
22
15
|
- **上限は 30。** これを超える 1 件を作る前に 1 件閉じる。エージェントが読む文書(`CLAUDE.md`・`prompts/`・配布 skill)がこの数字を書くのはこの行だけで、一次情報は `scripts/rules/delivered-rules.ts` の `WIP_CAP` である(一致はテストが固定する)。
|
|
23
|
-
-
|
|
24
|
-
-
|
|
16
|
+
- コマンドは起票先(`--repo` を付ければそのリポジトリ)のオープン Issue を epic も含めて数え、`wip:` 行に件数・上限・判定を印字する。上限を超えて免除が宣言されていなければ**何も送らずに保留し、免除の問いを印字する**。
|
|
17
|
+
- **免除を宣言するのはこのファイルの判断である** — `--route interrupt`(下の 3 条件)、`--route split` / `--route tier-a`(実行が詰まる起票)はルートそのものが宣言になる。ルートの無い実行が詰まる起票(利用者が `new` と打った入口など)は `--over-cap` を付けて出し直す。裁量起票(`--route review-cap` を含む)に `--over-cap` を付けてはならない。
|
|
25
18
|
|
|
26
19
|
## なぜ上限が要るのか
|
|
27
20
|
|
|
@@ -45,7 +38,7 @@ gh api "repos/{owner}/{repo}/issues?state=open&per_page=100" --paginate \
|
|
|
45
38
|
|
|
46
39
|
### 実行が詰まる起票 — 上限が効かない側
|
|
47
40
|
|
|
48
|
-
前提 Issue(`
|
|
41
|
+
前提 Issue(`prerequisite.md`)、別パッケージ起因の割り込み Issue、ユーザーが `new` と打った入口、`issue:scout` が重複無しと答えた新規作業、**そして分割判定が作る子 Issue と epic**。**これらは起票しないと実行が進まない。**
|
|
49
42
|
|
|
50
43
|
- **上限を理由に止めない。** 理由は `docs/maintainers/wip-cap-rationale.md` →「実行が詰まる起票を止めない理由」。
|
|
51
44
|
- **分割の子がここに入る理由**: 分割を検出した `fullrun` / `halfrun` は「子と epic を起票して **STOP**」と定められている(`fullrun.md` / `halfrun.md`)。**分割するかどうかを決めるのは分割判定の側**で、既定はもう「分割しない」に上がっている — 上限が二重に効く必要はない。
|
|
@@ -78,41 +71,9 @@ gh api "repos/{owner}/{repo}/issues?state=open&per_page=100" --paginate \
|
|
|
78
71
|
```
|
|
79
72
|
|
|
80
73
|
2. **超過している事実と、当たった条件の番号を本文に 1 行書く**(例:「オープン 37 件で起票。3 条件のうち 2(文書化された手順が完了できない)に該当」)。**どちらか一方では足りない** — 件数だけでは判定が再現できず、条件だけでは上限の可視化が効かない。
|
|
81
|
-
3. **次に実行されるものとして挿入する。** epic の下にあるなら `pnpm josh epic --add <E> <N>` で、**位置を指定せずに**追加する(`<E>` が epic、`<N>` が起票した割り込み)。**`--before` / `--after` を使ってはならない。** それらは `blocked-by`
|
|
74
|
+
3. **次に実行されるものとして挿入する。** epic の下にあるなら `pnpm josh epic --add <E> <N>` で、**位置を指定せずに**追加する(`<E>` が epic、`<N>` が起票した割り込み)。**`--before` / `--after` を使ってはならない。** それらは `blocked-by` を書き込み、「発見したランをブロックしていない欠陥」という割り込みの定義と矛盾する**偽の依存関係**になる。**順序は実行側が持つ** — 先に提示させたいときは、行だけを動かす `--order-before <M>` を使う。仕組みと経緯は `docs/maintainers/wip-cap-rationale.md` →「位置を指定しない追加の経緯」。**epic の下に無いなら挿入先そのものが無い**ので、この手順は飛ばして 4 だけを行う。
|
|
82
75
|
4. **着手は、既にある承認の内側でのみ、指示を待たずに行う。** `backlogrun` の中なら、打たれたキーワードがバッチを承認しているので、割り込みは次の子として着手してよい。**バッチの外では `CLAUDE.md` →「Explicit invocation required」が変わらず効く** — 起票と挿入まで済ませたうえで、利用者に打つべきコマンド(`fullrun #<N>`)を報告して止まる。**割り込みは上限の例外であって、明示起動規則の例外ではない。**
|
|
83
76
|
|
|
84
77
|
**起票と、実行されるようにするところまでが 1 つのまとまりである。** epic の下にある割り込みを起票だけして追加しなければ、`epic:next` はそれを候補にすら出さない — Issue は残るが実行されないという、コメントに埋もれるのと大差ない状態になる。**epic の外にある割り込みでは、まとまりの後半は 4 の報告そのもの**であり、打つべきコマンドを利用者に渡すまでが 1 回の行為である。上の「ひとまとまりで判定する」がここにも効く。
|
|
85
78
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
**kit 自身の検証が今の `main` で無関係な PR の判定まで誤らせている欠陥を直す Issue は単独で実行し、バッチを再開するのはそれが `main` へマージされてからとする。** 「着地」はマージであって、PR を開いた時点でもレビューが収束した時点でもない。
|
|
89
|
-
|
|
90
|
-
**該当するかは判断ではなく、次の 3 条件で決まる。**
|
|
91
|
-
|
|
92
|
-
1. **欠陥である**(`- 種別: 不具合`)。改善・リファクタ・削除・機能追加は当たらない。
|
|
93
|
-
2. **kit 自身の検証の欠陥である。** 検証とは次の 4 つを指し、配布先リポジトリ向けの CI・テンプレートの不具合は当たらない。
|
|
94
|
-
- **検証ゲート**(lint / 型チェック / スペルチェック / 単体テスト)
|
|
95
|
-
- **コードレビュー**
|
|
96
|
-
- **push 時のフック**
|
|
97
|
-
- **マージ時のチェック**
|
|
98
|
-
3. **今の `main` で、その Issue と無関係な PR の判定まで誤らせている**(嘘の緑 / 嘘の赤)。効率の問題や、特定の条件でしか起きないものは当たらない。
|
|
99
|
-
|
|
100
|
-
**3 条件すべてに当たれば単独実行、1 つでも外れれば `run:lane`。** 単独実行なら `run:solo` を付け、強制はそれを読む `backlog:next` と `epic:next --lanes` が行う(joshuafolkken/kit#2776)。外れれば(改善、機能追加、文書修正、配布先 CI の修正など)`run:lane` を付け、並列バッチの一員として走らせてよい。どちらもなければ `triage` が返り何も始まらない(joshuafolkken/kit#2779)ので、run が起票する Issue(割り込み・分割・前提)は起票時にどちらかを付ける。**「重大だと感じるか」は判定条件ではない**(起票側の 3 条件と同じ理由)。
|
|
101
|
-
|
|
102
|
-
**他レーンを止める根拠は 1 つ — 壊れた検証の上でバッチを回すと、全員の結果が信用できないこと。** 割り込み自身の検証が欠陥の影響下にあることはその Issue 自身の扱い(修正後の検証で確かめる)であって、他レーンを止める根拠にはしない。根拠と、判定を条件にした由来・狭めた経緯は `docs/maintainers/wip-cap-rationale.md` →「単独実行の理由と由来」。
|
|
103
|
-
|
|
104
|
-
## 上限そのものを変えるとき
|
|
105
|
-
|
|
106
|
-
**上限の数字は Tier C ではない** — 引き上げも引き下げも、測定を添えて提案してよい。ただし**変更は必ず `WIP_CAP` と「規則」節の 1 行を同じコミットで動かす**。片方だけ動かすと一致を固定するテストが落ちる。
|
|
107
|
-
|
|
108
|
-
**引き上げる条件は「窮屈だから」ではない。** オープン件数が 7 日移動平均で減り続けていて、なお上限が起票を止めているとき — つまり装置が目的を果たし終えたときだけである。
|
|
109
|
-
|
|
110
|
-
## 3 つは一緒に動く
|
|
111
|
-
|
|
112
|
-
上限は単独では効かない。**製造側を止めないまま上限だけ入れると、製造は続いたまま実行だけが止まる。** 経緯は `docs/maintainers/wip-cap-rationale.md` →「3 つを 1 コミットで着地させた経緯」。
|
|
113
|
-
|
|
114
|
-
| 製造元 | 変更 | 単一ソース |
|
|
115
|
-
| ------------------------- | ---------------------------------------------- | ----------------------------------------------------------------------- |
|
|
116
|
-
| 分割判定 | 既定を「分割しない」に。目安は単一ソースにある | `.claude/skills/workflow-commands/split-assessment.md` → "The question" |
|
|
117
|
-
| レビュー round 2 の残指摘 | 既定を branch 3(PR に 1 行残して落とす)に | `prompts/review.md` → "Three-way disposition after the cap" |
|
|
118
|
-
| オープン件数 | WIP 上限 | このファイル |
|
|
79
|
+
**割り込みをバッチの中で単独で走らせるか、並列のレーンで走らせるか**は `.claude/skills/workflow-commands/backlogrun-lanes.md` → "Lanes — running more than one child at a time" が単一ソースである(理由は `docs/maintainers/wip-cap-rationale.md` →「単独実行の理由と由来」)。上限の数字の変え方は `docs/maintainers/wip-cap-rationale.md` →「上限そのものを変えるとき」、上限が分割判定・レビュー上限と一緒に動く理由は `docs/maintainers/wip-cap-rationale.md` →「3 つは一緒に動く」と `docs/maintainers/wip-cap-rationale.md` →「3 つを 1 コミットで着地させた経緯」にある。
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
**これは人間が読むための索引であり、規則を定める場所ではない。** 常駐の引き金は `CLAUDE.md` に、実行中の操作手順は `.claude/skills/workflow-commands/` に、各話題の規則は下の表のファイルにあり、それぞれが自分の規則の一次情報である。この索引はそれらを言い直さない。
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
**必要な 1 本だけを開くこと。この索引を入口に、下の表から選ぶ。** 他の文書からこれらの話題を指すときは、索引を経由せず**本文があるファイルを直接指す**([`residency.md`](./collaboration-workflow/residency.md))。
|
|
12
12
|
|
|
13
13
|
| 話題 | ファイル |
|
|
14
14
|
| ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
|
|
@@ -30,15 +30,3 @@
|
|
|
30
30
|
| コマンド出力が文脈へ持ち込む量の上限 | [`output-bounds.md`](./collaboration-workflow/output-bounds.md) |
|
|
31
31
|
| 運用ルール | [`operating-rules.md`](./collaboration-workflow/operating-rules.md) |
|
|
32
32
|
| 用語集 — lane・cut・hold・park などの定義と単一ソース | [`glossary.md`](./collaboration-workflow/glossary.md) |
|
|
33
|
-
|
|
34
|
-
**どの 1 本を開けばよいかを決めるのに必要なのは、この索引だけである。** バイト数はここに書かない — 手で保守した数字は本文より先に古くなり、古い数字は無いより悪い。実サイズは `ls -l prompts/collaboration-workflow/` が答える。
|
|
35
|
-
|
|
36
|
-
## 参照の書き方
|
|
37
|
-
|
|
38
|
-
`CLAUDE.md` と `.claude/skills/` からこれらの話題を指すときは、**本文があるファイルを直接指す**(話題ファイル、skill へ単一ソース化済みならその skill。[`residency.md`](./collaboration-workflow/residency.md))。索引や指し先を経由させる形(`prompts/collaboration-workflow.md` → 「節名」)は、読み手に 2 回読みを強いるうえ、節名が変わると黙って行き止まりになる。
|
|
39
|
-
|
|
40
|
-
```md
|
|
41
|
-
See `prompts/collaboration-workflow/upstream-interrupt.md`.
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
`scripts/claude/collaboration-prompt-split.test.ts` が、文書と skill が指すファイルの実在と、この索引が全ファイルを列挙していることを検査する。
|
package/prompts/review-rubric.md
CHANGED
|
@@ -50,10 +50,8 @@ for every finding that passes test 1, and to say so when the attempt failed**: "
|
|
|
50
50
|
is a skipped step.
|
|
51
51
|
|
|
52
52
|
**A distributed artifact is on that list deliberately.** `CLAUDE.md`, `prompts/**`, `.claude/**` and
|
|
53
|
-
`docs/**` are reviewed at the same level as runtime code
|
|
54
|
-
|
|
55
|
-
wrong file, in artifacts distributed to every consumer — that no test covered, because prose is what
|
|
56
|
-
they were. A severity rule that ranked documentation below runtime code would contradict that.
|
|
53
|
+
`docs/**` are reviewed at the same level as runtime code — a dangling pointer or a citation naming the
|
|
54
|
+
wrong file reaches every consumer, and no test covers prose.
|
|
57
55
|
|
|
58
56
|
**`high` and `low`.** A `high` is fixed before committing and blocks the merge regardless of round
|
|
59
57
|
count; a `low` that does not reach the user may be skipped with a one-line reason. This section
|
|
@@ -214,73 +212,12 @@ allowed.
|
|
|
214
212
|
|
|
215
213
|
### 4. Project conventions (`CLAUDE.md`)
|
|
216
214
|
|
|
217
|
-
**
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
enforces it, never assumed:
|
|
224
|
-
|
|
225
|
-
- **Naming** — `@typescript-eslint/naming-convention` (`eslint/rules/naming-convention.js`).
|
|
226
|
-
- **`export default`** — `import/no-default-export` is `error` project-wide (`eslint/rules/import.js`),
|
|
227
|
-
switched off only for `*.d.ts` in `eslint/base.js`.
|
|
228
|
-
- **Individually named exports of function declarations, and of consts that are not `UPPER_CASE`** —
|
|
229
|
-
`no-restricted-syntax` in `eslint/rules/code-quality.js`. **Its selector exempts
|
|
230
|
-
`ArrowFunctionExpression`**, so `export const helper = (s: string): string => s` passes it; that
|
|
231
|
-
gap is a reader's job, below.
|
|
232
|
-
- **File names** — kebab-case through `unicorn/filename-case`.
|
|
233
|
-
- **The `*.spec.*` suffix, and a top-level `tests/` directory** — `eslint/rules/test-filename.js`,
|
|
234
|
-
wired into `eslint/base.js` itself, so it holds in kit and in every project built on that base
|
|
235
|
-
config. **Both bans cover every JS/TS extension** (`.ts` `.tsx` `.mts` `.cts` `.js` `.jsx` `.mjs`
|
|
236
|
-
`.cjs`) and neither covers `.svelte`. **A trailing block switching `no-restricted-syntax` off is
|
|
237
|
-
what can still take it away** — so read a diff that adds one as a gate defect, per the last
|
|
238
|
-
paragraph of this category.
|
|
239
|
-
- **Magic numbers** — `@typescript-eslint/no-magic-numbers`; **`any`, unused vars, floating promises
|
|
240
|
-
and explicit param and return types** — `eslint/rules/typescript.js` and `eslint/rules/promise.js`.
|
|
241
|
-
- **Identical functions and repeated string literals** — `eslint/rules/sonarjs.js`.
|
|
242
|
-
- **Every quality limit below.**
|
|
243
|
-
|
|
244
|
-
- **Quality limits**: a reference, enforced by `eslint/rules/code-quality.js` and
|
|
245
|
-
`eslint/rules/sonarjs.js` rather than re-checked here — function complexity ≤5, nesting ≤2,
|
|
246
|
-
function ≤25 lines, file ≤300 lines, params ≤4, statements per function ≤10,
|
|
247
|
-
cognitive complexity ≤4 — **the line counts are code lines, not physical lines**: `max-lines` and
|
|
248
|
-
`max-lines-per-function` run with `skipBlankLines` and `skipComments`, so read what
|
|
249
|
-
`pnpm josh lint` reports rather than `wc -l`, and test files (`*.test.ts` / `*.e2e.ts`) allow
|
|
250
|
-
35 code lines per function instead of 25 — **`*.spec.ts` is not on that list**, because the same
|
|
251
|
-
config bans the name outright.
|
|
252
|
-
|
|
253
|
-
**What only a reader can see — check these:**
|
|
254
|
-
|
|
255
|
-
- **`function` syntax rather than an arrow const** — **no rule enforces this**: there is no
|
|
256
|
-
`func-style` and no arrow selector anywhere in `eslint/`, and the named-export selector above
|
|
257
|
-
explicitly exempts `ArrowFunctionExpression`. So `const do_thing = (n: number): number => n + 1` and
|
|
258
|
-
`export const helper = (s: string): string => s` both lint clean, and this review is the only thing
|
|
259
|
-
between either and the default branch. The route-file exemption in `CLAUDE.md` covers the named
|
|
260
|
-
route handlers and nothing else.
|
|
261
|
-
- **The early-return one-liner** — `curly` is configured `['error', 'multi-line']`, which requires
|
|
262
|
-
braces on a multi-line body and never requires the one-liner form. A short `if (x) { return y }`
|
|
263
|
-
passes lint, so "single `return` under 100 chars → one-liner `if (x) return y`" is a reader's check.
|
|
264
|
-
- **Duplication that is not identical** — `sonarjs/no-identical-functions` sees only functions that
|
|
265
|
-
match. Two implementations of one idea in different shapes are invisible to it, and they are exactly
|
|
266
|
-
what "No clones — single-source" is about, package boundaries included.
|
|
267
|
-
- **A name that satisfies the convention and says the wrong thing** — `naming-convention` checks the
|
|
268
|
-
shape, never the meaning. An `is_` prefix on a function that returns a parsed value passes lint and
|
|
269
|
-
misleads every caller.
|
|
270
|
-
- **Grouping and layout** — a namespace object that collects unrelated functions, or a file whose
|
|
271
|
-
contents no longer match what its name says. Structure is not something lint judges.
|
|
272
|
-
- **Svelte semantics** — `$state` reassignment, `Props` as an interface name, restricted DOM
|
|
273
|
-
manipulation, and `PascalCase.svelte` / `PascalCase.svelte.ts` file names where the project's lint
|
|
274
|
-
does not cover them.
|
|
275
|
-
- **Test placement beyond the two banned patterns** — the ban above decides the `*.spec.*` suffix and
|
|
276
|
-
the top-level `tests/` directory, and nothing else. **A `tests/Foo.svelte` is outside both**, so it
|
|
277
|
-
is a reader's check. Colocation itself is what it cannot see: a test that avoids both and still sits
|
|
278
|
-
in a directory away from the code it exercises lints clean, and so does an `*.e2e.ts` placed outside
|
|
279
|
-
`src/routes/**`.
|
|
280
|
-
|
|
281
|
-
**A gate finding that got through is still a finding.** If lint could have caught something and did
|
|
282
|
-
not — a disabled rule, an ignored path, an `// eslint-disable` the change added — say so. That is a
|
|
283
|
-
defect in the gate, and no other step is looking at it.
|
|
215
|
+
**Do not re-check what lint enforces — the gate has already run; lint does not catch `function`
|
|
216
|
+
syntax over an arrow const (outside named route handlers), the early-return one-liner, duplication
|
|
217
|
+
that is not identical, a name whose shape passes but whose meaning misleads, grouping and file layout,
|
|
218
|
+
Svelte semantics, or test placement beyond the `*.spec.*` / top-level `tests/` bans, so check those.**
|
|
219
|
+
A lint gap the change opens — a disabled rule, an ignored path, an added `eslint-disable`, a block
|
|
220
|
+
switching `no-restricted-syntax` off — is itself a finding.
|
|
284
221
|
|
|
285
222
|
### 5. i18n
|
|
286
223
|
|
package/prompts/review.md
CHANGED
|
@@ -15,17 +15,10 @@ points to them rather than restating them:
|
|
|
15
15
|
|
|
16
16
|
## When to run
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
/ `halfrun` / `backlogrun`, driven by the brief `pnpm josh review:brief` prints. Round 1 runs before the
|
|
23
|
-
commit — scope: `git diff main`. Round 2 runs after it, beside the CI the commit started
|
|
24
|
-
(`.claude/skills/workflow-commands/chain-rule.md` → "The pull request opens between the rounds, so CI
|
|
25
|
-
runs beside round 2").
|
|
26
|
-
|
|
27
|
-
The workflow review uses the `reviewer` role profile printed by `pnpm josh review:brief`. Pass its
|
|
28
|
-
model and effort explicitly to the review subagent; do not substitute the review level for effort.
|
|
18
|
+
When a review runs is `CLAUDE.md` → "Pre-commit Self-Review"; inside a workflow, round 1 runs before
|
|
19
|
+
the commit and round 2 beside CI (`.claude/skills/workflow-commands/chain-rule.md`). Pass the
|
|
20
|
+
`reviewer` profile's model and effort that `pnpm josh review:brief` prints to the review subagent;
|
|
21
|
+
do not substitute the review level for effort.
|
|
29
22
|
|
|
30
23
|
Re-run after applying fixes until **no high or medium findings remain — or until the round cap below is
|
|
31
24
|
reached, the first review included — whichever comes first.** The cap below is not optional. The second round
|
|
@@ -46,10 +39,8 @@ pnpm josh review:brief --level-only # the branch diff
|
|
|
46
39
|
pnpm josh review:brief --level-only --staged # the staged diff
|
|
47
40
|
```
|
|
48
41
|
|
|
49
|
-
**The level is decided from the changed paths and nothing else
|
|
50
|
-
|
|
51
|
-
likely to be shipped. A rule an agent applies from memory is a rule an agent can talk itself out of;
|
|
52
|
-
one it has to run answers the same way every time.
|
|
42
|
+
**The level is decided from the changed paths and nothing else** — never "this one is small"
|
|
43
|
+
(`docs/maintainers/review-history.md`).
|
|
53
44
|
|
|
54
45
|
| Every changed path is… | Level | Rounds |
|
|
55
46
|
| ---------------------------------------------------------------------------------------- | -------- | ----------------------- |
|
|
@@ -64,13 +55,8 @@ would hand a reduced level to a caller that failed to read the diff.
|
|
|
64
55
|
in `package.json`'s `files` and are written into every consumer project by `josh init` / `josh sync`,
|
|
65
56
|
so a defect in one reaches a consumer and is reviewed at `medium` like any other shipped file.
|
|
66
57
|
|
|
67
|
-
**Documentation is not inert either
|
|
68
|
-
|
|
69
|
-
them from _testing_ — which asks whether an automated test could have caught the defect — while this
|
|
70
|
-
asks whether a human reading the diff is the only thing that can. Measured on joshuafolkken/kit#963 and
|
|
71
|
-
#965, both documentation-only by that classification: a `medium` review found ten real defects in each
|
|
72
|
-
— pointers into sections that had been removed, and citations naming the wrong file, in artifacts
|
|
73
|
-
distributed to every consumer — that nothing else would have caught.
|
|
58
|
+
**Documentation is not inert either.** `CLAUDE.md`, `prompts/**`, `.claude/**` and `docs/**` are all
|
|
59
|
+
reviewed at `medium`, though exempt from _testing_: a reader is the only detector a prose defect has.
|
|
74
60
|
|
|
75
61
|
**A confirmed High blocks regardless of round count**, and the round cap below does not change that.
|
|
76
62
|
|
|
@@ -78,26 +64,19 @@ distributed to every consumer — that nothing else would have caught.
|
|
|
78
64
|
|
|
79
65
|
## Review round cap (2 rounds)
|
|
80
66
|
|
|
81
|
-
The severity rule in the rubric is not a stopping condition on its own
|
|
82
|
-
|
|
83
|
-
new code the fixes produce, which is unbounded.
|
|
67
|
+
The severity rule in the rubric is not a stopping condition on its own: every fix creates new surface a
|
|
68
|
+
further round would find something in.
|
|
84
69
|
|
|
85
70
|
**Two rounds is the ceiling, not the schedule.** Whether the second one is due at all is
|
|
86
71
|
`pnpm josh review:round2`'s answer — "When round 2 is skipped entirely, and when it is not" below is
|
|
87
|
-
the single source of that condition
|
|
88
|
-
|
|
89
|
-
This is measured, not theorized. On joshuafolkken/kit#854 four rounds produced 18 findings; on #855
|
|
90
|
-
two rounds produced 19. Almost none of them was a repeat: each round found new things, and many of
|
|
91
|
-
those were about code the **previous round's fix** had just written. Two rounds of that is diligence; a
|
|
92
|
-
third is the review chasing its own tail.
|
|
72
|
+
the single source of that condition.
|
|
93
73
|
|
|
94
74
|
### A merge-conflict resolution review is not one of the two
|
|
95
75
|
|
|
96
76
|
**When `pnpm josh followup` reports `PR checks failed (merge conflict)`, the child resolves the conflict
|
|
97
|
-
in its own lane and reviews the resolution — and that round does not count against the cap
|
|
98
|
-
(joshuafolkken/kit#1623). The cap bounds re-reading _the change under review_; a resolution review reads
|
|
77
|
+
in its own lane and reviews the resolution — and that round does not count against the cap**. The cap bounds re-reading _the change under review_; a resolution review reads
|
|
99
78
|
a different subject — not the change, but what merging a moved `main` into it did.
|
|
100
|
-
`.claude/skills/workflow-commands/backlogrun-
|
|
79
|
+
`.claude/skills/workflow-commands/backlogrun-recovery.md` → "Conflicts are not predicted" is the single source of
|
|
101
80
|
the procedure and of the four conditions under which the run steps back instead of resolving.
|
|
102
81
|
`pnpm josh review:attest --check` must answer `ok` before the merge is re-issued, and a confirmed High
|
|
103
82
|
parks the child rather than buying it a further round.
|
|
@@ -105,7 +84,7 @@ parks the child rather than buying it a further round.
|
|
|
105
84
|
### When round 2 is skipped entirely, and when it is not
|
|
106
85
|
|
|
107
86
|
**Two rounds is the ceiling; whether the second round runs at all is a command's answer, not a reading
|
|
108
|
-
of a list
|
|
87
|
+
of a list**:
|
|
109
88
|
|
|
110
89
|
```bash
|
|
111
90
|
pnpm josh review:round2 --round-1-closed # → required | skip ; the reason on stderr
|
|
@@ -116,8 +95,7 @@ round-1 High/Medium finding actually closed — by a fix in this working tree, o
|
|
|
116
95
|
positive — and none was filed or deferred. **Without the flag the answer is `required`**, which is also
|
|
117
96
|
what the command answers to every uncertainty it meets, a missing round-1 snapshot included.
|
|
118
97
|
|
|
119
|
-
**`skip` has exactly two arms, and both are states in which round 1's fix code needs no review
|
|
120
|
-
(joshuafolkken/kit#1222 — the round exists because round 1's fix code is otherwise unreviewed):
|
|
98
|
+
**`skip` has exactly two arms, and both are states in which round 1's fix code needs no review**:
|
|
121
99
|
|
|
122
100
|
| Arm | What it is |
|
|
123
101
|
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
|
@@ -126,9 +104,7 @@ what the command answers to every uncertainty it meets, a missing round-1 snapsh
|
|
|
126
104
|
|
|
127
105
|
**Neither arm weakens the standard.** A round-1 High/Medium that did not close is not a closed finding,
|
|
128
106
|
so the flag is not passable; the cap is still two rounds; and a confirmed High still blocks the merge.
|
|
129
|
-
|
|
130
|
-
is not adopted**: a documentation-only diff is exactly where the review is the only detector (the #963 /
|
|
131
|
-
#965 measurement above), so a prompt fix answers `required`.
|
|
107
|
+
A documentation-only fix delta is not inert, so a prompt fix answers `required`.
|
|
132
108
|
|
|
133
109
|
**A skipped round is recorded on the Issue**, so the condition stays auditable and can be withdrawn if
|
|
134
110
|
a defect is later traced to a skipped delta:
|
|
@@ -142,7 +118,7 @@ a defect is later traced to a skipped delta:
|
|
|
142
118
|
### Three-way disposition after the cap
|
|
143
119
|
|
|
144
120
|
**After the second round, place every remaining non-High finding in exactly one of three exits, decided
|
|
145
|
-
from what the finding is rather than from the filer's discretion
|
|
121
|
+
from what the finding is rather than from the filer's discretion**. **The
|
|
146
122
|
default exit is branch 3, and branch 2 has to be earned**. Read them in order — branch 1 where the fix is
|
|
147
123
|
trivial and local, branch 2 only where the finding clears the bar it names, branch 3 for everything
|
|
148
124
|
left, which is most of them. "It might matter later" is branch 3.
|
|
@@ -167,12 +143,6 @@ left, which is most of them. "It might matter later" is branch 3.
|
|
|
167
143
|
suspicion included. **The note is not optional**: one line naming the finding and why it was dropped
|
|
168
144
|
is what keeps a dropped finding auditable rather than invisible.
|
|
169
145
|
|
|
170
|
-
**What it costs, and why that is the right trade.** A dropped finding that later turns out to matter is
|
|
171
|
-
re-found by the next review of that code, at the price of one round it would have paid anyway. A filed
|
|
172
|
-
finding that never mattered is carried forever — placed in an epic, offered by `epic:next`, read by
|
|
173
|
-
everyone who scans the backlog. The two errors are not symmetric, and the old default was on the
|
|
174
|
-
expensive side of them.
|
|
175
|
-
|
|
176
146
|
**Findings that reduce to one root judgement are filed as one Issue, not several** — a single follow-up
|
|
177
147
|
Issue with a section per symptom (`## 現象 1` / `## 現象 2`).
|
|
178
148
|
|
|
@@ -187,7 +157,7 @@ Only branch 2 files an Issue. What follows applies to that branch.
|
|
|
187
157
|
the commit.** Where the run opens a pull request — `fullrun`, `backlogrun` — they go after
|
|
188
158
|
`pnpm josh git -y` and before `pnpm josh followup`; where it does not — `halfrun`, or a standalone
|
|
189
159
|
pre-commit self-review — they run as soon as the disposition is decided. **The chain may run in a
|
|
190
|
-
delegated unit** — `pnpm josh delegate followup-filing
|
|
160
|
+
delegated unit** — `pnpm josh delegate followup-filing`.
|
|
191
161
|
- **When the round files a second follow-up, run `pnpm josh issue:fold` first.** Several findings from
|
|
192
162
|
one review fold into one Issue by default — the filing-time counterpart to the split assessment,
|
|
193
163
|
reading the same two questions (`.claude/skills/workflow-commands/split-assessment.md` → "The same
|
|
@@ -204,13 +174,13 @@ Only branch 2 files an Issue. What follows applies to that branch.
|
|
|
204
174
|
write command yourself — never a hand edit of the epic body, which leaves the task list and the
|
|
205
175
|
`blocked-by` relations disagreeing and `epic:next` returning `error`.
|
|
206
176
|
|
|
207
|
-
| Answer | Do
|
|
208
|
-
| ------------------------------------------------------------------------------------------------- |
|
|
209
|
-
| `add_to_epic` | `pnpm josh epic --add <E> <new>` — add `--before <M>` / `--after <M>` when the relation carries an order
|
|
210
|
-
| `create_epic` | `pnpm josh epic "<title>" <new> <other> [--ordered]`
|
|
211
|
-
| `ask` — candidates spread across two or more epics | **Choose the epic you recommend, run its write command, and record the decision** — what was taken, what was rejected, why — on both the new Issue and that epic's `## Decisions`. This does not stop a run and does not park a child
|
|
212
|
-
| `none` | Nothing
|
|
213
|
-
| **The command could not answer** — non-zero exit, or **any** ⚠ warning above `Nothing to bundle.` | Stop and report, naming what it said. **A `none` printed after such a warning is not "nothing to bundle"** — the search was incomplete
|
|
177
|
+
| Answer | Do | Tier |
|
|
178
|
+
| ------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- |
|
|
179
|
+
| `add_to_epic` | `pnpm josh epic --add <E> <new>` — add `--before <M>` / `--after <M>` when the relation carries an order | **A — no confirmation** |
|
|
180
|
+
| `create_epic` | `pnpm josh epic "<title>" <new> <other> [--ordered]` | **A — no confirmation** |
|
|
181
|
+
| `ask` — candidates spread across two or more epics | **Choose the epic you recommend, run its write command, and record the decision** — what was taken, what was rejected, why — on both the new Issue and that epic's `## Decisions`. This does not stop a run and does not park a child; stop only where the two epics are genuinely too close to separate | **A — no confirmation** |
|
|
182
|
+
| `none` | Nothing | — |
|
|
183
|
+
| **The command could not answer** — non-zero exit, or **any** ⚠ warning above `Nothing to bundle.` | Stop and report, naming what it said. **A `none` printed after such a warning is not "nothing to bundle"** — the search was incomplete | — |
|
|
214
184
|
|
|
215
185
|
- **A confirmed High is never deferred.** A real defect does not ship because a round counter ran out,
|
|
216
186
|
so a standing High blocks the merge — never fixed-in-place, filed, or dropped as one of the three
|
package/prompts/testing-guide.md
CHANGED
|
@@ -22,7 +22,8 @@ Req N: ...
|
|
|
22
22
|
### Rules
|
|
23
23
|
|
|
24
24
|
- **Every user-facing behavior change** (UI interaction, keyboard shortcut, visible state change) must have a corresponding E2E test.
|
|
25
|
-
- **Every logic/utility change** (pure functions, filters, transforms) must have a unit test.
|
|
25
|
+
- **Every logic/utility change** (pure functions, filters, transforms) must have a unit test. A bug fix takes a regression test; a refactor takes tests pinning the existing behavior BEFORE the change (`prompts/refactoring.md`).
|
|
26
|
+
- **Non-runtime updates (pre-approved manual-only exception):** a change touching no executable runtime code path — docs, non-executable config, editor/IDE files, cosmetic asset swaps with no selector/path change — may be verified by hand; declare it in Step 0 with the reason. The mechanically exempt (`*.md`, `.editorconfig`, `.idea/**`, `.vscode/**`, `prompts/**`) need no declaration. A runtime change whose test is infeasible needs the reason and user approval.
|
|
26
27
|
- **basic で kit がテストできない言語だけの変更:** `package.json` に `josh.profile: basic`(改名前の `static` も同じ)が記録され、変更が HTML/CSS や Lua などのソースだけなら自動テストは不要。HTML/CSS はブラウザーで対象ページを開き、想定する画面幅でレイアウト・リンク・HTML 内の操作を確認する。そのほかのソースは変更した処理を実際に動かす。どちらも結果を記録する。同じ変更に JavaScript または TypeScript のファイルが含まれれば自動テストを行う。
|
|
27
28
|
- If a test is genuinely infeasible (e.g., native OS date-picker popup cannot be driven by Playwright), write a comment in the test file explaining why and test the closest observable behavior instead (e.g., that the editor remains open after the `change` event fires).
|
|
28
29
|
- Do **not** report a requirement as done if its test is missing.
|
|
@@ -59,7 +60,7 @@ There is exactly **one** convention for every test file — never choose between
|
|
|
59
60
|
- **The `.svelte.` infix is required for component/browser tests and must be preserved.** `*.svelte.test.ts` routes the file to the **browser/component** vitest project (`include: src/**/*.svelte.{test,spec}.{js,ts}`); plain `*.test.ts` routes to the **node/unit** project (`include: src/**/*.{test,spec}.{js,ts}`). Renaming `Foo.svelte.test.ts` → `Foo.test.ts` silently moves it to the wrong project — do not drop the `.svelte.` infix.
|
|
60
61
|
- **Colocate every test next to the code it exercises.** A top-level `tests/` directory is **not used** — place `foo.test.ts` beside `foo.ts`, and E2E specs under the relevant `src/routes/**` path. The top-level `tests/` ban is **lint-enforced** by the same rule (`eslint/rules/test-filename.js`). Note: `playwright.config.ts` discovers E2E via `testMatch: '**/*.e2e.{ts,js}'`, so an `*.e2e.ts` placed outside `src/routes/**` would still run — that specific `src/routes/**` placement is enforced by **convention/review, not config**, and must be upheld manually.
|
|
61
62
|
|
|
62
|
-
> **Enforcement:** the `*.spec.ts` ban and the top-level `tests/` ban are enforced by the test-filename rule (`eslint/rules/test-filename.js`), wired into the shared `eslint/base.js`, so they fail loudly in `josh lint` for kit itself, for every consumer of that base config, and for every AI tool
|
|
63
|
+
> **Enforcement:** the `*.spec.ts` ban and the top-level `tests/` ban are enforced by the test-filename rule (`eslint/rules/test-filename.js`), wired into the shared `eslint/base.js`, so they fail loudly in `josh lint` for kit itself, for every consumer of that base config, and for every AI tool (`docs/maintainers/testing-guide-history.md`).
|
|
63
64
|
|
|
64
65
|
---
|
|
65
66
|
|
|
@@ -177,19 +178,8 @@ test('returns expected values in sequence', () => {
|
|
|
177
178
|
|
|
178
179
|
## 6. Closing the E2E gate without a human run
|
|
179
180
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
replacement is **not** a relaxation — nothing that a red local run stopped is allowed through.
|
|
183
|
-
|
|
184
|
-
### Why it existed, and why it no longer does
|
|
185
|
-
|
|
186
|
-
The reason was never that a human reads E2E output better. It was that `followup` waited 180
|
|
187
|
-
seconds for CI, which no suite containing E2E can finish in — so the command exited red beside a CI
|
|
188
|
-
that was still running, and the only reliable E2E signal left was a person's terminal. That budget
|
|
189
|
-
is now derived from the distributed `templates/workflows/ci.yml` rather than picked as a round
|
|
190
|
-
number: 1920 seconds, the longest run its `needs` graph permits plus runner-queue headroom, with a
|
|
191
|
-
unit test that fails if a declared job budget outgrows it (joshuafolkken/kit#851). CI can now be
|
|
192
|
-
waited on, so it can be relied on.
|
|
181
|
+
No human E2E run closes the gate, and nothing a red local run stopped is let through
|
|
182
|
+
(`docs/maintainers/testing-guide-history.md`).
|
|
193
183
|
|
|
194
184
|
### Which result closes the gate
|
|
195
185
|
|
|
@@ -219,60 +209,21 @@ a **defined** outcome, not an accident: a project with no E2E suite has nothing
|
|
|
219
209
|
read, and the run says so out loud. **A skip you did not see printed is not one** — it is an unread
|
|
220
210
|
result, and it falls under the previous paragraph.
|
|
221
211
|
|
|
222
|
-
**CI decides the same question
|
|
212
|
+
**CI decides the same question by the same rule.** The `e2e-detect` job in
|
|
223
213
|
`templates/workflows/ci.yml` enables the `e2e` job when any `*.e2e.{ts,js}` exists outside
|
|
224
|
-
`node_modules` — the guard's own glob
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
"no E2E" in CI while `josh test:e2e` ran it locally: the job's `if:` went false, GitHub recorded it
|
|
229
|
-
as `skipped`, the rollup parser counted the skip as passing exactly as it does for every other
|
|
230
|
-
conditional job, and the first row of the table above closed the gate on a suite nobody ran.
|
|
231
|
-
**Where the specs live was a precondition on the CI signal; it is now a property of the workflow.**
|
|
232
|
-
The agreement is executed rather than described — `scripts/ci/ci-yml-e2e-detect.test.ts` runs the
|
|
233
|
-
workflow's own script against each layout and compares its verdict to the guard's, and asserts over
|
|
234
|
-
the whole matrix that no layout containing specs can yield `enabled=false`. § 1's placement
|
|
235
|
-
convention still stands on its own merits (`eslint/rules/test-filename.js` bans a top-level
|
|
236
|
-
`tests/` directory outright), but the CI signal no longer depends on following it.
|
|
237
|
-
|
|
238
|
-
**One difference from the guard remains, and it is deliberate and one-sided.** The guard also skips
|
|
239
|
-
when `@playwright/test` is not installed, which is what keeps that optional peer optional for the
|
|
240
|
-
pre-push hook; CI enables the job on the spec alone, so a spec that cannot run ends red rather than
|
|
241
|
-
silently green. Enabling more than the guard costs a failed job, enabling less costs a merge — so
|
|
242
|
-
the difference may widen in that direction and never narrow.
|
|
214
|
+
`node_modules` — the guard's own glob — whatever the config's filename;
|
|
215
|
+
`scripts/ci/ci-yml-e2e-detect.test.ts` pins the agreement. CI enables the job on the spec alone, even
|
|
216
|
+
where the guard skips for a missing `@playwright/test`, so a spec that cannot run ends red rather than
|
|
217
|
+
silently green.
|
|
243
218
|
|
|
244
219
|
### The gate is not weakened
|
|
245
220
|
|
|
246
|
-
Two properties carry the verification the human step used to carry, and both are asserted by tests
|
|
247
|
-
rather than left to prose:
|
|
248
|
-
|
|
249
221
|
- **A non-passing check keeps the merge closed.** `evaluate_pr_state` returns `success` only when
|
|
250
|
-
GitHub reports the pull request `CLEAN` **and** every required check passes
|
|
251
|
-
|
|
252
|
-
the
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
**`E2E` stays off the required-check list, and that is a decision rather than an oversight**
|
|
259
|
-
(joshuafolkken/kit#991). A required check is satisfied by a _skipped_ job — the rollup parser maps
|
|
260
|
-
`SKIPPED` to `pass` — so requiring `E2E` would have passed on exactly the skipped job described
|
|
261
|
-
above, which is the failure it looks like it would have caught. It adds nothing to the failure path
|
|
262
|
-
either: a red E2E already ends the wait on the poll that sees it. What it would add is a cost —
|
|
263
|
-
a repository whose CI reports no `E2E` context at all resolves the required entry to `missing`,
|
|
264
|
-
which is never `pass`, so the evaluation stays `pending` until the 32-minute wait times out with
|
|
265
|
-
nothing actually wrong. What guarantees the job runs is the detection rule above, not the required
|
|
266
|
-
list. A project that wants it required opts in through `JOSH_REQUIRED_CHECKS`, which
|
|
267
|
-
`scripts/gh/git-pr-checks-eval.test.ts` covers; the decision itself — `E2E` off the default list,
|
|
268
|
-
and a repository reporting no `E2E` check still mergeable — is pinned in
|
|
269
|
-
`scripts/gh/git-pr-checks-e2e-gate.test.ts`.
|
|
270
|
-
|
|
271
|
-
**A red E2E is reported as soon as it goes red, and by name.** `E2E` is not on the required list, so
|
|
272
|
-
until joshuafolkken/kit#990 nothing ended the wait when it failed: the rollup read as pending,
|
|
273
|
-
`followup` ran out its 32-minute budget, and the run ended in `Timed out while waiting for PR checks
|
|
274
|
-
to complete.` — a message naming neither the job nor the cause. Any failing check now ends the wait
|
|
275
|
-
on the poll that sees it, and the error names it (`PR checks failed (failed checks: E2E).`).
|
|
276
|
-
The poll loop keeps CodeRabbit exempt under the temporary kit#753 policy. **This is a change to how fast the gate
|
|
277
|
-
reports, never to what it lets through** — no failing check gained a path to `success`, which
|
|
278
|
-
`scripts/gh/git-pr-checks-e2e-gate.test.ts` continues to assert.
|
|
222
|
+
GitHub reports the pull request `CLEAN` **and** every required check passes; the only exception is a
|
|
223
|
+
non-passing set made entirely of CodeRabbit checks (the temporary kit#753 policy). A failing check
|
|
224
|
+
ends the wait on the poll that sees it, by name (`PR checks failed (failed checks: E2E).`).
|
|
225
|
+
- **Filtering, narrowing or reinterpreting E2E output to get past it is a workaround** —
|
|
226
|
+
`CLAUDE.md` → "Cross-package problems"; reporting the filtered result honestly does not make it
|
|
227
|
+
compliant.
|
|
228
|
+
- **`E2E` stays off the default required-check list**; a project opts in through
|
|
229
|
+
`JOSH_REQUIRED_CHECKS`. `scripts/gh/git-pr-checks-e2e-gate.test.ts` pins both properties.
|
|
@@ -74,7 +74,7 @@ const PROVIDER_PROFILES = { anthropic: DEFAULT_PROFILES, openai: OPENAI_PROFILES
|
|
|
74
74
|
|
|
75
75
|
// **Effort as a function of the run phase, not the role alone** (joshuafolkken/kit#2382). For the first
|
|
76
76
|
// merge only the mechanical ship/bookkeeping region is lowered: the pre-gate resume drives the gate,
|
|
77
|
-
// commit, PR and merge, applying fixes the gate has already named — work
|
|
77
|
+
// commit, PR and merge, applying fixes the gate has already named — work delegation.md calls the opposite
|
|
78
78
|
// of judgement. The design-judgment implementation phases keep the role default, as does any role/phase
|
|
79
79
|
// with no entry, and the review's own judgement is the reviewer role's (`high`), untouched by lowering
|
|
80
80
|
// the worker here. The investigation phase — highest output density — is left for a later merge, once
|