@joshuafolkken/kit 1.978.0 → 1.983.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/epic-commands/SKILL.md +6 -5
- package/.claude/skills/workflow-commands/SKILL.md +9 -9
- package/.claude/skills/workflow-commands/background-commands.md +1 -1
- package/.claude/skills/workflow-commands/fullrun-steps.md +8 -8
- package/.claude/skills/workflow-commands/halfrun.md +4 -5
- package/.claude/skills/workflow-commands/issue-comments.md +1 -1
- package/.claude/skills/workflow-commands/issue-scout.md +21 -22
- package/.claude/skills/workflow-commands/kickoff.md +8 -9
- package/.claude/skills/workflow-commands/observation-filing.md +9 -10
- package/.claude/skills/workflow-commands/prerequisite.md +7 -6
- package/.claude/skills/workflow-commands/retrospective.md +5 -5
- package/.claude/skills/workflow-commands/rule-residency.md +2 -2
- package/.claude/skills/workflow-commands/split-assessment.md +4 -3
- package/.claude/skills/workflow-commands/target-repository.md +7 -6
- package/dist/hooks/batch-guard.js +4 -4
- package/dist/hooks/{chunk-ZPLXLJ7O.js → chunk-47SPMGOD.js} +16 -1
- package/dist/hooks/{chunk-BVMSPG3M.js → chunk-5JX6HXDX.js} +3 -3
- package/dist/hooks/{chunk-KQG4776P.js → chunk-APVOACVT.js} +1 -1
- package/dist/hooks/{chunk-2K52BRWV.js → chunk-ASUZGZFT.js} +2 -2
- package/dist/hooks/{chunk-CRGJTD6E.js → chunk-ERXMJJOV.js} +1 -1
- package/dist/hooks/{chunk-Q7LE77CO.js → chunk-IM3KM25Y.js} +31 -29
- package/dist/hooks/{chunk-BNGGEY3Z.js → chunk-LBXQHXMC.js} +129 -342
- package/dist/hooks/{chunk-NXL3SBXY.js → chunk-P3UX7SFN.js} +2 -2
- package/dist/hooks/{chunk-F6OM6SIG.js → chunk-RFPHKU7C.js} +12 -12
- package/dist/hooks/{chunk-ZYYSBNR6.js → chunk-ZT65LR3U.js} +4 -4
- 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/investigation-guard.js +5 -5
- package/dist/hooks/pretool-guard.js +9 -9
- package/dist/hooks/stop-guard.js +4 -4
- package/dist/josh.js +16 -1
- package/package.json +1 -1
- package/prompts/collaboration-workflow/epic-bundle.md +8 -8
- package/prompts/collaboration-workflow/issue-template.md +5 -5
- package/prompts/collaboration-workflow/rule-delivery.md +43 -30
- package/prompts/collaboration-workflow/upstream-interrupt.md +1 -1
- package/prompts/collaboration-workflow/wip-cap.md +3 -3
- package/prompts/review.md +11 -9
- package/scripts/delegation/delegation-policy.ts +9 -9
- package/scripts/document/document-byte-budget.ts +1 -1
- package/scripts/issue/issue-file-cli.ts +188 -0
- package/scripts/issue/issue-file.ts +192 -0
- package/scripts/issue/issue-lint-cli.ts +1 -1
- package/scripts/issue/issue-scout-cli.ts +41 -97
- package/scripts/issue/issue-scout-closed.ts +102 -0
- package/scripts/josh/__snapshots__/josh-command-map.test.ts.snap +9 -1
- package/scripts/josh/josh-command-map.ts +1 -0
- package/scripts/josh/josh-commands-issue.ts +11 -0
- package/scripts/josh/josh-commands-project.ts +5 -1
- package/scripts/propagate/propagate-run.ts +1 -0
- package/scripts/propagate/propagate-select.ts +72 -0
- package/scripts/propagate/propagate-targets.ts +5 -3
- package/scripts/propagate/propagate.ts +86 -24
- package/scripts/rules/bash-triggers.ts +19 -6
- package/scripts/rules/delivered-rules.ts +28 -32
- package/scripts/rules/direct-filing.ts +38 -0
- package/scripts/rules/filing-cap.ts +11 -8
- package/scripts/rules/issue-fold.ts +4 -4
- package/scripts/rules/oracle-consulted.ts +4 -4
- package/scripts/rules/oracle-firing.ts +13 -16
- package/scripts/rules/rule-body-guard.ts +6 -9
- package/scripts/rules/stop-rules.ts +3 -2
- package/scripts/test/pilot-files.ts +0 -1
- package/scripts/version/fresh-metadata-cache.ts +36 -0
- package/scripts/version/latest-update.ts +2 -1
- package/scripts/rules/issue-bug-label.ts +0 -85
- package/scripts/rules/issue-filing-args.ts +0 -50
- package/scripts/rules/issue-scout.ts +0 -64
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
lane_guard_policy,
|
|
3
3
|
time_batch_guard
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-ASUZGZFT.js";
|
|
5
5
|
import {
|
|
6
6
|
hook_decision
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-APVOACVT.js";
|
|
8
8
|
|
|
9
9
|
// scripts/hooks/batch-guard.ts
|
|
10
10
|
import { text } from "node:stream/consumers";
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
time_batch_guard
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-ASUZGZFT.js";
|
|
4
4
|
import {
|
|
5
5
|
hook_decision
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-APVOACVT.js";
|
|
7
7
|
import {
|
|
8
8
|
cost_blocks,
|
|
9
9
|
cost_transcript,
|
|
10
10
|
time_bundle_call,
|
|
11
11
|
time_shell,
|
|
12
12
|
time_spans
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-47SPMGOD.js";
|
|
14
14
|
|
|
15
15
|
// scripts/delegation/investigation-reads.ts
|
|
16
16
|
import path from "node:path";
|
|
@@ -36,15 +36,15 @@ var DELEGATABLE_STEPS = [
|
|
|
36
36
|
},
|
|
37
37
|
{
|
|
38
38
|
name: "followup-filing",
|
|
39
|
-
// The late-run follow-up filing chain — issue:
|
|
40
|
-
// — is a dependency chain `batch:guard`
|
|
41
|
-
//
|
|
42
|
-
// (joshuafolkken/kit#1892). A fresh unit runs the same
|
|
43
|
-
// round cap already composed the finding text, so what
|
|
44
|
-
//
|
|
45
|
-
//
|
|
46
|
-
does: "run the late-run follow-up filing chain in an isolated unit \u2014 issue:scout,
|
|
47
|
-
verifier: "the parent reads the filed Issue from GitHub with `pnpm josh issue:state <new>`, not the unit's summary; a follow-up reported filed but not created is still absent, the way `epic-child`'s reported-done-but-not-merged child is still open. The finding text came from the parent and `issue:
|
|
39
|
+
// The late-run follow-up filing chain — `issue:file` (which scouts, lints, labels and runs
|
|
40
|
+
// epic:bundle itself, joshuafolkken/kit#2808) → epic --add — is a dependency chain `batch:guard`
|
|
41
|
+
// correctly keeps one call per step, and what makes it expensive is the ~340k context it runs in
|
|
42
|
+
// at the tail of a run, not the step count (joshuafolkken/kit#1892). A fresh unit runs the same
|
|
43
|
+
// chain at a small context, and the review round cap already composed the finding text, so what
|
|
44
|
+
// the unit is handed is mechanical: run the commands and act on their deterministic answers. This
|
|
45
|
+
// is not `batch:guard`'s business — delegation only moves the chain to a cheaper context.
|
|
46
|
+
does: "run the late-run follow-up filing chain in an isolated unit \u2014 issue:file (scout, lint, labels, epic:bundle), then epic --add \u2014 given the finding text the parent already composed, and return the new Issue number and the epic:bundle answer",
|
|
47
|
+
verifier: "the parent reads the filed Issue from GitHub with `pnpm josh issue:state <new>`, not the unit's summary; a follow-up reported filed but not created is still absent, the way `epic-child`'s reported-done-but-not-merged child is still open. The finding text came from the parent and `issue:file`'s steps are deterministic, so the unit's work is the mechanical execution `issue:state` confirms"
|
|
48
48
|
},
|
|
49
49
|
{
|
|
50
50
|
name: "implementation-unit",
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
investigation_reads
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-RFPHKU7C.js";
|
|
4
4
|
import {
|
|
5
5
|
lane_guard_policy
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-ASUZGZFT.js";
|
|
7
7
|
import {
|
|
8
8
|
hook_decision
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-APVOACVT.js";
|
|
10
10
|
import {
|
|
11
11
|
json_value,
|
|
12
12
|
time_spans
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-47SPMGOD.js";
|
|
14
14
|
|
|
15
15
|
// scripts/delegation/duplicate-read-guard.ts
|
|
16
16
|
import { statSync } from "node:fs";
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
2
|
import {
|
|
3
3
|
pretool_guard
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-LBXQHXMC.js";
|
|
5
|
+
import "./chunk-IM3KM25Y.js";
|
|
6
6
|
import {
|
|
7
7
|
build_envelope,
|
|
8
8
|
compose_context,
|
|
9
9
|
format_edited_payload
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-ERXMJJOV.js";
|
|
11
11
|
import "./chunk-3V37IID6.js";
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
15
|
-
import "./chunk-
|
|
16
|
-
import "./chunk-
|
|
12
|
+
import "./chunk-P3UX7SFN.js";
|
|
13
|
+
import "./chunk-5JX6HXDX.js";
|
|
14
|
+
import "./chunk-ZT65LR3U.js";
|
|
15
|
+
import "./chunk-RFPHKU7C.js";
|
|
16
|
+
import "./chunk-ASUZGZFT.js";
|
|
17
17
|
import {
|
|
18
18
|
hook_decision
|
|
19
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-APVOACVT.js";
|
|
20
20
|
import {
|
|
21
21
|
time_density_hook
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-47SPMGOD.js";
|
|
23
23
|
import "./chunk-WPALEIRX.js";
|
|
24
24
|
import "./chunk-RKUAD3I6.js";
|
|
25
25
|
|
|
@@ -9,11 +9,11 @@ import {
|
|
|
9
9
|
is_enabled,
|
|
10
10
|
notice_refusal_path,
|
|
11
11
|
refusal_path
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
15
|
-
import "./chunk-
|
|
16
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-ZT65LR3U.js";
|
|
13
|
+
import "./chunk-RFPHKU7C.js";
|
|
14
|
+
import "./chunk-ASUZGZFT.js";
|
|
15
|
+
import "./chunk-APVOACVT.js";
|
|
16
|
+
import "./chunk-47SPMGOD.js";
|
|
17
17
|
import "./chunk-WPALEIRX.js";
|
|
18
18
|
import "./chunk-RKUAD3I6.js";
|
|
19
19
|
export {
|
|
@@ -15,9 +15,9 @@ import {
|
|
|
15
15
|
relative_to_root,
|
|
16
16
|
resolve_invocations,
|
|
17
17
|
select_invocation
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-ERXMJJOV.js";
|
|
19
19
|
import "./chunk-3V37IID6.js";
|
|
20
|
-
import "./chunk-
|
|
20
|
+
import "./chunk-47SPMGOD.js";
|
|
21
21
|
import "./chunk-RKUAD3I6.js";
|
|
22
22
|
export {
|
|
23
23
|
ESLINT_DAEMON,
|
|
@@ -10,11 +10,11 @@ import {
|
|
|
10
10
|
is_enabled,
|
|
11
11
|
load_environment_file,
|
|
12
12
|
refusal_path
|
|
13
|
-
} from "./chunk-
|
|
14
|
-
import "./chunk-
|
|
15
|
-
import "./chunk-
|
|
16
|
-
import "./chunk-
|
|
17
|
-
import "./chunk-
|
|
13
|
+
} from "./chunk-5JX6HXDX.js";
|
|
14
|
+
import "./chunk-RFPHKU7C.js";
|
|
15
|
+
import "./chunk-ASUZGZFT.js";
|
|
16
|
+
import "./chunk-APVOACVT.js";
|
|
17
|
+
import "./chunk-47SPMGOD.js";
|
|
18
18
|
import "./chunk-WPALEIRX.js";
|
|
19
19
|
import "./chunk-RKUAD3I6.js";
|
|
20
20
|
export {
|
|
@@ -3,16 +3,16 @@ import {
|
|
|
3
3
|
pretool_guard,
|
|
4
4
|
pretool_outcome,
|
|
5
5
|
pretool_outcome_async
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-LBXQHXMC.js";
|
|
7
|
+
import "./chunk-IM3KM25Y.js";
|
|
8
8
|
import "./chunk-3V37IID6.js";
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
15
|
-
import "./chunk-
|
|
9
|
+
import "./chunk-P3UX7SFN.js";
|
|
10
|
+
import "./chunk-5JX6HXDX.js";
|
|
11
|
+
import "./chunk-ZT65LR3U.js";
|
|
12
|
+
import "./chunk-RFPHKU7C.js";
|
|
13
|
+
import "./chunk-ASUZGZFT.js";
|
|
14
|
+
import "./chunk-APVOACVT.js";
|
|
15
|
+
import "./chunk-47SPMGOD.js";
|
|
16
16
|
import "./chunk-WPALEIRX.js";
|
|
17
17
|
import "./chunk-RKUAD3I6.js";
|
|
18
18
|
export {
|
package/dist/hooks/stop-guard.js
CHANGED
|
@@ -19,20 +19,20 @@ import {
|
|
|
19
19
|
run_hold,
|
|
20
20
|
run_invocation,
|
|
21
21
|
run_watcher_guard
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-IM3KM25Y.js";
|
|
23
23
|
import {
|
|
24
24
|
session_language
|
|
25
25
|
} from "./chunk-6V5OPIUU.js";
|
|
26
26
|
import {
|
|
27
27
|
hook_decision,
|
|
28
28
|
lane_child_marker
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-APVOACVT.js";
|
|
30
30
|
import {
|
|
31
31
|
PROJECT_ROOT,
|
|
32
32
|
stamp_file,
|
|
33
33
|
time_density_hook,
|
|
34
34
|
time_hook_transcript
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-47SPMGOD.js";
|
|
36
36
|
import "./chunk-WPALEIRX.js";
|
|
37
37
|
import "./chunk-RKUAD3I6.js";
|
|
38
38
|
|
|
@@ -1161,7 +1161,7 @@ function build_citation_reason(references) {
|
|
|
1161
1161
|
const command = `pnpm josh issue:cite ${issue_citation.cite_arguments(references).join(" ")}`;
|
|
1162
1162
|
return `\u26D4 issue citation: your reply names an Issue as a bare \`#N\` (${numbers}). Run \`${command}\` to print the paste-ready citation lines, then print the corrected citation lines alone \u2014 do not repeat your previous reply. ${ISSUE_CITATION_REASON}`;
|
|
1163
1163
|
}
|
|
1164
|
-
var FILING_OFFER_REASON = '\u26D4 filing offer: your reply offers to file an Issue instead of filing it. Filing into a first-party repository is Tier A \u2014 the trigger is the judgement that it is worth filing, not the run\'s progress (`.claude/skills/workflow-commands/SKILL.md` \u2192 \xA72i, `observation-filing.md`). Run `pnpm josh issue:
|
|
1164
|
+
var FILING_OFFER_REASON = '\u26D4 filing offer: your reply offers to file an Issue instead of filing it. Filing into a first-party repository is Tier A \u2014 the trigger is the judgement that it is worth filing, not the run\'s progress (`.claude/skills/workflow-commands/SKILL.md` \u2192 \xA72i, `observation-filing.md`). Run `pnpm josh issue:file "<title>" --body-file <path> --depth <0|1|2>` \u2014 it scouts, lints, labels and runs `epic:bundle` itself \u2014 then end with the one-line citation of what was filed; do not repeat your previous reply. If it is not worth filing after all, say so in one line instead.';
|
|
1165
1165
|
var HEADLESS_WAIT_MARKER = "\u26D4 headless parent:";
|
|
1166
1166
|
var HEADLESS_REFUSAL_CAP = 3;
|
|
1167
1167
|
var HEADLESS_WAIT_CALLS = ['"command":"pnpm josh lane:await', '"command":"pnpm josh run:progress'];
|
package/dist/josh.js
CHANGED
|
@@ -447,6 +447,16 @@ var ISSUE_COMMANDS = {
|
|
|
447
447
|
description: "Post one comment to an issue from a file, so no shell expands the body",
|
|
448
448
|
category: "AI tools",
|
|
449
449
|
reference: ["<issue> --body <text> | --body-file <path>", "automation", ["network"]]
|
|
450
|
+
},
|
|
451
|
+
"issue:file": {
|
|
452
|
+
script: "scripts/issue/issue-file-cli.ts",
|
|
453
|
+
description: "File an Issue with every filing step: lint, Origin, duplicate scout, labels, then epic:bundle",
|
|
454
|
+
category: "AI tools",
|
|
455
|
+
reference: [
|
|
456
|
+
"<title> --body-file <path> --depth <0|1|2> [--route <route>] [--label <name>] [--repo <owner/repo>] [--distinct <N,\u2026>]",
|
|
457
|
+
"automation",
|
|
458
|
+
["network"]
|
|
459
|
+
]
|
|
450
460
|
}
|
|
451
461
|
};
|
|
452
462
|
|
|
@@ -1225,7 +1235,11 @@ var PROJECT_COMMANDS = {
|
|
|
1225
1235
|
script: "scripts/propagate/propagate.ts",
|
|
1226
1236
|
description: "Carry the published release into every consumer repository next to this one",
|
|
1227
1237
|
category: "Project",
|
|
1228
|
-
reference: [
|
|
1238
|
+
reference: [
|
|
1239
|
+
"[--dry-run] [--skip-publish-wait] [--target <repo>]",
|
|
1240
|
+
"maintainer",
|
|
1241
|
+
["files", "network"]
|
|
1242
|
+
]
|
|
1229
1243
|
},
|
|
1230
1244
|
adopt: {
|
|
1231
1245
|
script: "scripts/adopt/adopt.ts",
|
|
@@ -1472,6 +1486,7 @@ var ALIASES = {
|
|
|
1472
1486
|
ird: "issue:read",
|
|
1473
1487
|
ist: "issue:state",
|
|
1474
1488
|
isc: "issue:scout",
|
|
1489
|
+
ifl: "issue:file",
|
|
1475
1490
|
isf: "issue:fold",
|
|
1476
1491
|
isfe: "issue:fold-existing",
|
|
1477
1492
|
dfr: "defect:rate",
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.
|
|
2
|
+
"version": "1.983.0",
|
|
3
3
|
"name": "@joshuafolkken/kit",
|
|
4
4
|
"description": "Development toolkit for AI-assisted projects: formatting, AI assistant rules and a Git/GitHub Issue workflow for any repository, plus lint, type check, tests and hooks for Node projects",
|
|
5
5
|
"keywords": [
|
|
@@ -12,18 +12,18 @@
|
|
|
12
12
|
|
|
13
13
|
**Issue を新規に起票した直後**に、既存の open Issue を調べる。`kickoff` / `fullrun` / `halfrun` が起票したとき、および実装中に Tier A で起票したとき(`backlogrun` 実行中を含む)。
|
|
14
14
|
|
|
15
|
-
`pnpm josh epic:bundle <N>`(エイリアス `eb
|
|
15
|
+
`pnpm josh epic:bundle <N>`(エイリアス `eb`)が候補を探して推奨を表示する。起票は `pnpm josh issue:file` で行い、このコマンドが最終段として `epic:bundle` を実行して答えを表示するので、別に呼ぶのは `⚠` で再実行を案内されたときだけである。**このコマンドは何も書き込まない** — 候補を出すのが機械、束ねるかを決めるのは AI である。
|
|
16
16
|
|
|
17
17
|
### 起票の「前」に答えるのは `issue:scout`
|
|
18
18
|
|
|
19
19
|
`pnpm josh issue:scout "<title>"`(エイリアス `isc`)は、まだ存在しない Issue について同じ配属先の問いに答える(joshuafolkken/kit#1252)。**配属の判定は `epic:bundle` のものをそのまま呼んでおり、実装は 1 つしかない。** 加えて、`epic:bundle` が意図的に採らないシグナル — タイトルの語の重なりによる**重複候補** — を返す。既存 Issue の束ね直しに似た見出しが立つのは強シグナルだけで十分だからだが、「もう起票されていないか」は起票前にしか意味を持たない別の問いであり、しきい値を混ぜていない。
|
|
20
20
|
|
|
21
|
-
**両方を実行する。順番が違うだけである。**
|
|
21
|
+
**両方を実行する。順番が違うだけである。** どちらも `pnpm josh issue:file` が 1 回の呼び出しの中で実行する。
|
|
22
22
|
|
|
23
|
-
| いつ
|
|
24
|
-
|
|
|
25
|
-
|
|
|
26
|
-
| 起票の**直後**
|
|
23
|
+
| いつ | コマンド | 何について答えるか |
|
|
24
|
+
| -------------- | ----------------------- | -------------------------------------------------- |
|
|
25
|
+
| 起票の**前** | `issue:scout "<title>"` | まだ番号を持たない下書き。タイトルと本文がある |
|
|
26
|
+
| 起票の**直後** | `epic:bundle <N>` | 実在する Issue。番号と、それに記録された関係がある |
|
|
27
27
|
|
|
28
28
|
手順上の位置づけと、重複候補が見つかったときに起票せず止まる規則は `.claude/skills/workflow-commands/SKILL.md` → §2e が単一ソースである。
|
|
29
29
|
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
|
|
42
42
|
**これは「レビューを CI と並走させる」ではない。**(ここで言うレビューは 1 周目のことであり、2 周目については下の段落で別に扱う。) joshuafolkken/kit#1216 の (b) は不採用と決定済みであり、却下の理由は規則ではなく仕組みである — あちらは**コードを変える作業**を CI と重ねるため、修正を push するたびに CI がやり直しになり、重ねた分をそのまま払い戻す。起票はコードを 1 行も変えないので、走っている CI がそのまま使える。**1 周目のレビュー**はコミットの前のままで、「コミット前セルフレビュー」は書き換えていない。**2 周目だけは CI と並走する**(joshuafolkken/kit#1261)— 同じ仕組みを逆から読んだ結果であり、2 周目は fix delta しか読まず、通常はコードを 1 行も変えない。変えた場合は同一ブランチへの追加コミット 1 つと CI のやり直し 1 回を払う。単一ソースは `.claude/skills/workflow-commands/chain-rule.md` → "The pull request opens between the rounds, so CI runs beside round 2"。
|
|
43
43
|
|
|
44
|
-
1. 残指摘を後追い Issue として起票し、現在の Issue
|
|
45
|
-
2. **現在の Issue
|
|
44
|
+
1. 残指摘を後追い Issue として起票し、現在の Issue を参照する。起票は `pnpm josh issue:file "<title>" --body-file <本文ファイル> --depth <n> --route review-cap` で行う
|
|
45
|
+
2. **現在の Issue が閉じる前に**起票する。`issue:file` が新規 Issue について `epic:bundle` を実行する。候補探索は open Issue しか読まないため、親が閉じた後では恒久的に `none` になる(joshuafolkken/kit#947)
|
|
46
46
|
3. 答えに従う。**`epic:bundle` は推奨するだけで何も書き込まない**ので、「実行する」とは書き込みコマンドを自分で打つことである。**epic 本文の手編集は禁止** — タスクリストと `blocked-by` が食い違い、`epic:next` が `error` を返す
|
|
47
47
|
|
|
48
48
|
| 答え | すること | Tier |
|
|
@@ -71,14 +71,14 @@ Issue には次の要素を必ず含める。
|
|
|
71
71
|
|
|
72
72
|
- **起票前に不具合かどうかを必ず選ぶ。** `## 背景` の直下に、不具合なら `- 種別: 不具合`、非不具合なら `- 種別: 非不具合` を置く。両方の併記も省略も `pnpm josh issue:lint` が拒否する。故障を述べる本文でも単語から自動判定せず、起票者が判断する。振る舞い変更、機能改善、互換性の宣言はこの判断と併記できる
|
|
73
73
|
- **不具合修正の Issue は `- 種別: 不具合` を宣言する。** この宣言がある Issue では、`pnpm josh git -y` が追加・変更したテストを修正前のツリー(merge-base)に当てて `pnpm josh test:red` で実行し、1 本も赤にならない(`green`)ときはコミットを拒否する。修正前でも緑の回帰テストは、報告された症状を再現していないためである(joshuafolkken/kit#2448)。回帰テストは、利用者が症状を見たのと同じ粒度で書く
|
|
74
|
-
- **起票時の `bug` ラベルは本文の宣言から決める。** `pnpm josh issue:
|
|
75
|
-
- **機能追加・機能改善は目的を本文で宣言する。** `## 背景` の直下に `- 目的: 機能追加` または `- 目的: 機能改善`
|
|
76
|
-
- **互換性を壊す変更は影響を本文で宣言する。** 既存の利用者、API、設定の契約を変える場合は、`## 背景` の直下に `- 互換性: 破壊的変更`
|
|
77
|
-
-
|
|
74
|
+
- **起票時の `bug` ラベルは本文の宣言から決める。** 起票は `pnpm josh issue:file "<title>" --body-file <本文ファイル> --depth <n>` で行い、このコマンドが `issue:lint` と同じ検査をしたうえで、`- 種別: 不具合` の宣言があれば `bug` ラベルを同じ作成リクエストに付ける。`depth`・`route` も同じ呼び出しで付く。`bugfix` は PR のリリース分類であり、Issue の `bug` の代わりにしない
|
|
75
|
+
- **機能追加・機能改善は目的を本文で宣言する。** `## 背景` の直下に `- 目的: 機能追加` または `- 目的: 機能改善` を書く。この宣言があれば `pnpm josh issue:file` が `enhancement` ラベルを同じ作成リクエストに付ける。不具合修正、文書のみ、依存更新、保守作業はタイトルの単語から推測して宣言しない。目的が曖昧なら起票文案の期待結果と受け入れ条件を具体化してから分類する
|
|
76
|
+
- **互換性を壊す変更は影響を本文で宣言する。** 既存の利用者、API、設定の契約を変える場合は、`## 背景` の直下に `- 互換性: 破壊的変更` を書き、廃止対象と影響を説明する。移行措置や事前案内があっても破壊的変更なら宣言する。この宣言があれば `pnpm josh issue:file` が `breaking-change` ラベルを同じ作成リクエストに付ける。互換性を保つ変更には付けない。影響が曖昧なら起票文案で対象の利用者と契約を明確にしてから分類する
|
|
77
|
+
- **本文が宣言する分類ラベルは `pnpm josh issue:file` がすべて起票時に付ける。** `bug`、`enhancement`、`breaking-change` は組み合わせて付くことがある。`depth`・`route` などのラベルと併せて 1 回の作成リクエストで付け、宣言が無いとき(`issue:lint` の `labels: none`)は分類ラベルを付けない。Issue が `enhancement` と `breaking-change` の両方を持つとき、PR のリリース分類は `breaking-change` 一つにする。Issue の目的の分類と PR のリリース分類を区別する
|
|
78
78
|
- **`## 発火点`** には、その規則が破れる瞬間に最初に呼ばれるツールコール名を 1 つ書く。名前は `prompts/collaboration-workflow/rule-delivery.md` の配送表に載る、フックで配送可能なツール(`Bash` / `Edit` / `Read` / `Write` / `AskUserQuestion`)と突き合わせる。**表に無い名前**(そもそもツールコール名でない)と**不一致**(既知のツールだが配送できない)は区別して印字され、joshuafolkken/kit#2201 の「規則は正しいが名指ししたコールが実際に破れるコールの 1 つ後ろ」を起票時に検出する
|
|
79
79
|
- **`## ベースライン`** は **「コマンド + 値」** で書く。``- `<測定コマンド>` → <現在の値>`` の形に限り、自然文だけの測定説明は受け付けない(再実行できないため)。マージ後に `pnpm josh measure:rerun` が同じコマンドをやり直し、**before / after の対**を印字する。値が動かなかったとき、反証された前提として `docs/maintainers/observations.md` に 1 行追記される(既存の append-only 台帳を使い、別の台帳は作らない)
|
|
80
80
|
- **`## 再現`** は **「コマンド + 実際の出力」** で書く。コマンドを backtick、出力をフェンス(``` または ~~~)で囲む。自然文の「確認した」は再実行できないため受け付けない(`## ベースライン` と同じ理由)。読みだけの起票を起票時に弾くためである
|
|
81
|
-
- **検査は `pnpm josh issue:lint <path>` が行う。** 対象判定・3 見出しの有無・発火点の配送可否・ベースラインが「コマンド + 値」か・再現が「コマンド +
|
|
81
|
+
- **検査は `pnpm josh issue:lint <path>` が行う。** 対象判定・3 見出しの有無・発火点の配送可否・ベースラインが「コマンド + 値」か・再現が「コマンド + 実際の出力」かと、起票時に必要な分類ラベルを、起票前の本文ファイルからまとめて答える(`pnpm josh issue:file` は起票前に同じ検査を行い、問題があれば起票しない)
|
|
82
82
|
|
|
83
83
|
### 起票元へのバックリンク(`## Origin` / `## Upstream issues`)
|
|
84
84
|
|
|
@@ -53,33 +53,33 @@
|
|
|
53
53
|
|
|
54
54
|
## 配送されている規則
|
|
55
55
|
|
|
56
|
-
| 規則 | 引き金
|
|
57
|
-
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
58
|
-
| **ターン内バッチング**(`turn-batching.md`) | `pnpm josh batch:guard` — 単発呼び出しのターンが 3 つ続いた次の `Bash` / `Edit` / `Read`
|
|
59
|
-
| **調査の委譲しきい値**(`SKILL.md` → §2b) | `pnpm josh investigation:guard` — 編集しないファイルの読み取りが 3 件目に達した `Read` / `Bash`
|
|
60
|
-
| **バックログ WIP 上限**(`wip-cap.md`) | `pnpm josh rule:guard` — Issue
|
|
61
|
-
|
|
|
62
|
-
| **1 ラン 10 件の起票上限**(`.claude/skills/workflow-commands/SKILL.md` → §2d、`observation-filing.md`) | `pnpm josh rule:guard` — Issue
|
|
63
|
-
| **Issue コメントの読み取り**(`SKILL.md` → §2g) | `pnpm josh rule:guard` — Issue 本文だけを読む `Bash`(`gh issue view <N>`、または `…/issues/<N>` で終わる GET)
|
|
64
|
-
| **本文をシェルに載せない**(`shell-body.md`) | `pnpm josh rule:guard` — 二重引用符の本文値(`-f body="…"` / `-f "body=…"` / `--body "…"` / `--notify-message "…"`)にバッククォートか `$` を含む `Bash`
|
|
65
|
-
| **@path をリテラル投稿する誤射**(`shell-body.md`、joshuafolkken/kit#2304) | `pnpm josh rule:guard` — 生フィールド(`-f` / `--raw-field`)で `body=@<path>` を渡した `Bash`。`@` で始まる値をそのまま送るため `@<path>` がコメントとして投稿される。**毎回発火する**
|
|
66
|
-
| **検証コマンドのパイプ**(`output-bounds.md`) | `pnpm josh rule:guard` — 合否を意味する josh のチェック(`gate` / `check` / `lint*` / `cspell*` / `test*` / `eval` / `overrides` / `ranges`)がパイプの手前に立った `Bash`
|
|
67
|
-
| **早すぎる進捗報告**(`.claude/skills/workflow-commands/backlogrun-progress.md` → 「Progress while the run is quiet」) | `pnpm josh rule:guard` — 待つことだけが目的の `Bash`(全区間が `sleep`、または `sleep` に `echo` / `:` / `date` が並ぶだけ)。既に生きているタイマーがある回、またはその報告が間隔前に着地する回に拒否する
|
|
68
|
-
| **run 末尾の空転**(`background-commands.md`) | `pnpm josh rule:guard` — commit・push・PR 作成をまとめる段(`pnpm josh git -y` / 別名 `josh g`、`--yes` も同じ)を**前景**で出した `Bash`。`run_in_background` が付いていれば引き金に当たらない
|
|
69
|
-
| **gate 手前の cut**(`.claude/skills/workflow-commands/pre-gate-cut.md`) | `pnpm josh rule:guard` — レーンの作業ツリーに居て、目印 `JOSH_LANE_CHILD` がその Issue を指し、cut 記録がまだ無いまま `pnpm josh gate`(別名 `josh ga` も同じ)を走らせる `Bash`
|
|
70
|
-
| **実装フェーズの cut**(`.claude/skills/workflow-commands/pre-gate-cut.md` → 「It is a guard, fired at the edit that crosses the threshold」、joshuafolkken/kit#2310) | `pnpm josh rule:guard` — 派遣されたレーンの子(目印 `JOSH_LANE_CHILD` がその Issue を指す)で cut 記録がまだ無く、直近文脈のコスト(`pnpm josh cost --cut` と同一の統計・同一のしきい値 `CONTEXT_CUT_THRESHOLD`、測定不能は `!== UNDER` で安全側に発火)が超過しているときに出した `Edit` / `Write`。編集の直前で拒否し `pnpm josh run:cut --impl <N> --handoff <path>` を返す。**しきい値を跨ぐたびに発火する**(`decide`、joshuafolkken/kit#2385)。直後の同じ編集の出し直しは通すので `busy` / `failed` でも空回りしない
|
|
71
|
-
| **レーンの子の保留**(`.claude/skills/workflow-commands/pre-gate-cut.md`) | `pnpm josh rule:guard` — 派遣されたレーンの子(目印 `JOSH_LANE_CHILD` がその Issue を指す)が、判断待ちの停止通知 `pnpm josh notify --task-type confirmation` を出した `Bash`
|
|
72
|
-
| **レーンの子の対話質問**(`.claude/skills/workflow-commands/pre-gate-cut.md` → 「The interactive ask is refused one call earlier」) | `pnpm josh rule:guard` — 派遣されたレーンの子(目印 `JOSH_LANE_CHILD` がその Issue を指す)が `AskUserQuestion` を呼んだ呼び出し。停止通知の 1 つ手前で拒否し park 手順を返す。ハーネスは対話質問をターン終了で拒否するので、この 1 つ前が正しい引き金である。**毎回発火する**
|
|
73
|
-
| **テストの宣言**(`CLAUDE.md` → Code Change Rules) | `pnpm josh rule:guard` — commit・push・PR 段(`pnpm josh git -y` / 別名 `josh g`)を出した瞬間に `pnpm josh test:declared` が作業ツリーを `required`(テストでも機械的免除パスでもない変更ファイルがある)と読む `Bash`。`run_tail` の commit 段照合を再利用し、新しい配送経路は作らない
|
|
74
|
-
| **force push / ブランチ削除**(`operating-rules.md`、joshuafolkken/kit#2120) | `pnpm josh rule:guard` — `git push` / `git branch` を argv として解析し、force(`--force` / `-f` / 結合クラスタ `-uf`)・削除(`--delete` / `-d` / `-D` / コロン形 `:branch`)・`git -C` 前置を綴りによらず判定した `Bash`。**毎回発火する**
|
|
75
|
-
| **認可外の作業ツリー変更**(`operating-rules.md`、joshuafolkken/kit#2120) | `pnpm josh rule:guard` — `git checkout -- <path>` / `git restore <path>`(worktree)/ 認可外の `git stash`(bare・メッセージ無し push・位置指定 pop 等)を出した `Bash`。**毎回発火する**
|
|
76
|
-
| **ファイル本文をシェルに載せない**(`file-edits.md`、joshuafolkken/kit#2120) | `pnpm josh rule:guard` — 既存ファイルを対象としたヒアドキュメント書き込み・書き込みを伴う `node -e` / インタプリタ heredoc・in-place `perl -0pi -e` を出した `Bash`。既存判定は `stat` 1 回。**毎回発火する**
|
|
77
|
-
| **停止時の通知**(`CLAUDE.md` →「Mid-workflow stop notification」、joshuafolkken/kit#2121) | `pnpm josh stop:guard` — `Stop` フックで、作業ツリーを押さえたまま(`run:hold` 記録あり)その turn に `confirmation` 通知を出さずに止まろうとする。**停止をブロックする**
|
|
78
|
-
| **hold の解放**(`.claude/skills/workflow-commands/SKILL.md` → §2f、joshuafolkken/kit#2121) | `pnpm josh stop:guard` — `Stop` フックで、ツリーが綺麗(`git status --porcelain` が空)なのに `run:hold` 記録が残ったまま止まる。**停止をブロックする**
|
|
79
|
-
| **Issue 引用の書式**(`prompts/collaboration-workflow/issue-citation.md`、joshuafolkken/kit#2121・joshuafolkken/kit#2247) | `pnpm josh stop:guard` — `Stop` フックで、`last_assistant_message` の地の文に裸の `#N` を含む。**停止をブロックする**(モデルに差し戻し、引用を直して返信を出し直させる)
|
|
80
|
-
| **起票の申し出**(`.claude/skills/workflow-commands/SKILL.md` → §2i、joshuafolkken/kit#2422) | `pnpm josh stop:guard` — `Stop` フックで、`last_assistant_message` の地の文が起票を申し出る(「起票してよければ」等)のに、transcript 末尾に起票(`filing_cap` の数え方)が無い。**停止をブロックする**
|
|
81
|
-
| **規則本文を散文に書き足す前の第 0 問・順序の問い**(`residency.md`、joshuafolkken/kit#2272・joshuafolkken/kit#2324) | `pnpm josh rule:guard` — `CLAUDE.md` / `prompts/**/*.md` / `.claude/skills/**/*.md` を対象とする `Edit` / `Write` で、リンク・URL を除いた正味の追記が閾値以上(規則本文の追記)。誤字・リンク張り替え・削除は当たらない。第 0 問(`oracle:list`)と順序の問い(`run:step
|
|
82
|
-
| **オラクル未参照の行為**(`decision-oracle.ts`、joshuafolkken/kit#2324) | `pnpm josh rule:guard` — 発火点を宣言したオラクルが支配する `Bash`(`pkg:scout` = `pnpm add
|
|
56
|
+
| 規則 | 引き金 | 引き金が発火しないターンでは |
|
|
57
|
+
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
58
|
+
| **ターン内バッチング**(`turn-batching.md`) | `pnpm josh batch:guard` — 単発呼び出しのターンが 3 つ続いた次の `Bash` / `Edit` / `Read` | 往復あたりの呼び出し数が下限を上回っている = 規則は既に守られている |
|
|
59
|
+
| **調査の委譲しきい値**(`SKILL.md` → §2b) | `pnpm josh investigation:guard` — 編集しないファイルの読み取りが 3 件目に達した `Read` / `Bash` | 読み取りがしきい値未満 = 委譲する対象がまだ無い |
|
|
60
|
+
| **バックログ WIP 上限**(`wip-cap.md`) | `pnpm josh rule:guard` — Issue を起票する `Bash`(`pnpm josh issue:file`) | Issue が起票されていない = 上限に触れる行為が無い |
|
|
61
|
+
| **直接起票の禁止**(`docs/josh-commands.md` → `josh issue:file`、joshuafolkken/kit#2808) | `pnpm josh rule:guard` — `josh issue:file` を通さずに Issue を作成する `Bash`(`gh issue create`、または `…/issues` への `title` 付き POST)。拒否文は `pnpm josh issue:file` の書式を渡す。重複探し・本文の検査と分類ラベル・`## Origin` の確認・`epic:bundle` はこのコマンドが実行するので、それぞれを別の行で見張らない。**毎回発火する** | `pnpm josh issue:file` で起票している = 起票の全段がそろっている |
|
|
62
|
+
| **1 ラン 10 件の起票上限**(`.claude/skills/workflow-commands/SKILL.md` → §2d、`observation-filing.md`) | `pnpm josh rule:guard` — Issue を起票する `Bash`(`pnpm josh issue:file`)。そのランで**拒否されていない**起票が既に 10 件あるとき、11 件目を拒否する。終了コードが 0 でない `issue:file` 呼び出しは起票に数えない。`is_issue_filing` を再利用し、新しい述語は作らない | 拒否されていない起票が 10 件未満 = 上限に触れていない。**繰り返す行為を止める行なので毎回発火する**(下の「例外」に従う) |
|
|
63
|
+
| **Issue コメントの読み取り**(`SKILL.md` → §2g) | `pnpm josh rule:guard` — Issue 本文だけを読む `Bash`(`gh issue view <N>`、または `…/issues/<N>` で終わる GET) | Issue を読んでいない、または最初から `--comments` 付きで読んでいる |
|
|
64
|
+
| **本文をシェルに載せない**(`shell-body.md`) | `pnpm josh rule:guard` — 二重引用符の本文値(`-f body="…"` / `-f "body=…"` / `--body "…"` / `--notify-message "…"`)にバッククォートか `$` を含む `Bash` | 本文がシェルに評価されない = 規則は既に守られている |
|
|
65
|
+
| **@path をリテラル投稿する誤射**(`shell-body.md`、joshuafolkken/kit#2304) | `pnpm josh rule:guard` — 生フィールド(`-f` / `--raw-field`)で `body=@<path>` を渡した `Bash`。`@` で始まる値をそのまま送るため `@<path>` がコメントとして投稿される。**毎回発火する** | `-F` / `--field body=@`(ファイルを読む正しい綴り)・`@` を含まない本文・`pnpm josh issue:comment` = リテラルの `@path` が送出されない |
|
|
66
|
+
| **検証コマンドのパイプ**(`output-bounds.md`) | `pnpm josh rule:guard` — 合否を意味する josh のチェック(`gate` / `check` / `lint*` / `cspell*` / `test*` / `eval` / `overrides` / `ranges`)がパイプの手前に立った `Bash` | 検証の終了コードが握りつぶされていない = 失敗が失敗として伝わる |
|
|
67
|
+
| **早すぎる進捗報告**(`.claude/skills/workflow-commands/backlogrun-progress.md` → 「Progress while the run is quiet」) | `pnpm josh rule:guard` — 待つことだけが目的の `Bash`(全区間が `sleep`、または `sleep` に `echo` / `:` / `date` が並ぶだけ)。既に生きているタイマーがある回、またはその報告が間隔前に着地する回に拒否する | 待機タイマーを自前で張っていない = 時計は `run:progress` が 1 本だけ持っている |
|
|
68
|
+
| **run 末尾の空転**(`background-commands.md`) | `pnpm josh rule:guard` — commit・push・PR 作成をまとめる段(`pnpm josh git -y` / 別名 `josh g`、`--yes` も同じ)を**前景**で出した `Bash`。`run_in_background` が付いていれば引き金に当たらない | 背景で発行している = 完了通知が run を再開させ、push とマージのあいだが空かない |
|
|
69
|
+
| **gate 手前の cut**(`.claude/skills/workflow-commands/pre-gate-cut.md`) | `pnpm josh rule:guard` — レーンの作業ツリーに居て、目印 `JOSH_LANE_CHILD` がその Issue を指し、cut 記録がまだ無いまま `pnpm josh gate`(別名 `josh ga` も同じ)を走らせる `Bash` | レーン以外の checkout に居る、目印が無い(レーン内の人)、または既に cut 済み = 規則が守られている状態 |
|
|
70
|
+
| **実装フェーズの cut**(`.claude/skills/workflow-commands/pre-gate-cut.md` → 「It is a guard, fired at the edit that crosses the threshold」、joshuafolkken/kit#2310) | `pnpm josh rule:guard` — 派遣されたレーンの子(目印 `JOSH_LANE_CHILD` がその Issue を指す)で cut 記録がまだ無く、直近文脈のコスト(`pnpm josh cost --cut` と同一の統計・同一のしきい値 `CONTEXT_CUT_THRESHOLD`、測定不能は `!== UNDER` で安全側に発火)が超過しているときに出した `Edit` / `Write`。編集の直前で拒否し `pnpm josh run:cut --impl <N> --handoff <path>` を返す。**しきい値を跨ぐたびに発火する**(`decide`、joshuafolkken/kit#2385)。直後の同じ編集の出し直しは通すので `busy` / `failed` でも空回りしない | レーンの子でない(レーン外・目印なし・レーン内の人)、非編集ツール、既に cut 済み、またはコストがしきい値未満 = 打ち切りが要らない状態 |
|
|
71
|
+
| **レーンの子の保留**(`.claude/skills/workflow-commands/pre-gate-cut.md`) | `pnpm josh rule:guard` — 派遣されたレーンの子(目印 `JOSH_LANE_CHILD` がその Issue を指す)が、判断待ちの停止通知 `pnpm josh notify --task-type confirmation` を出した `Bash` | レーンの子でない(レーン外・目印なし・レーン内の人)、または停止通知でない = 保留を記録すべき停止が無い |
|
|
72
|
+
| **レーンの子の対話質問**(`.claude/skills/workflow-commands/pre-gate-cut.md` → 「The interactive ask is refused one call earlier」) | `pnpm josh rule:guard` — 派遣されたレーンの子(目印 `JOSH_LANE_CHILD` がその Issue を指す)が `AskUserQuestion` を呼んだ呼び出し。停止通知の 1 つ手前で拒否し park 手順を返す。ハーネスは対話質問をターン終了で拒否するので、この 1 つ前が正しい引き金である。**毎回発火する** | レーンの子でない(レーン外・目印なし・レーン内の人)、または対話ツールでない = 握りつぶされる質問が無い |
|
|
73
|
+
| **テストの宣言**(`CLAUDE.md` → Code Change Rules) | `pnpm josh rule:guard` — commit・push・PR 段(`pnpm josh git -y` / 別名 `josh g`)を出した瞬間に `pnpm josh test:declared` が作業ツリーを `required`(テストでも機械的免除パスでもない変更ファイルがある)と読む `Bash`。`run_tail` の commit 段照合を再利用し、新しい配送経路は作らない | 差分が `exempt`(`*.md` 等の非ランタイム)または `satisfied`(`*.test.ts` / `*.e2e.ts` を含む)= テストが要らない、または既に伴っている。免除は人が Step 0 で宣言するため 1 ラン 1 回だけ配送する |
|
|
74
|
+
| **force push / ブランチ削除**(`operating-rules.md`、joshuafolkken/kit#2120) | `pnpm josh rule:guard` — `git push` / `git branch` を argv として解析し、force(`--force` / `-f` / 結合クラスタ `-uf`)・削除(`--delete` / `-d` / `-D` / コロン形 `:branch`)・`git -C` 前置を綴りによらず判定した `Bash`。**毎回発火する** | force / 削除でない通常の `git push` / `git branch` = 破壊的操作が無い |
|
|
75
|
+
| **認可外の作業ツリー変更**(`operating-rules.md`、joshuafolkken/kit#2120) | `pnpm josh rule:guard` — `git checkout -- <path>` / `git restore <path>`(worktree)/ 認可外の `git stash`(bare・メッセージ無し push・位置指定 pop 等)を出した `Bash`。**毎回発火する** | メッセージ付き `git stash push -m` ・`git stash list` ・`pnpm josh git` ・`pnpm josh stash:pop` = 認可された退避 |
|
|
76
|
+
| **ファイル本文をシェルに載せない**(`file-edits.md`、joshuafolkken/kit#2120) | `pnpm josh rule:guard` — 既存ファイルを対象としたヒアドキュメント書き込み・書き込みを伴う `node -e` / インタプリタ heredoc・in-place `perl -0pi -e` を出した `Bash`。既存判定は `stat` 1 回。**毎回発火する** | 新規ファイル作成・読み取り専用のヒアドキュメント・短い `sed -i` = 本文を丸ごと運んでいない |
|
|
77
|
+
| **停止時の通知**(`CLAUDE.md` →「Mid-workflow stop notification」、joshuafolkken/kit#2121) | `pnpm josh stop:guard` — `Stop` フックで、作業ツリーを押さえたまま(`run:hold` 記録あり)その turn に `confirmation` 通知を出さずに止まろうとする。**停止をブロックする** | 押さえを持っていない、`confirmation` 通知が末尾にある、または pre-gate cut を取った回(レーンの子の自動継続)= 人待ちの停止ではない(`stop_hook_active` が無限ループの歯止め) |
|
|
78
|
+
| **hold の解放**(`.claude/skills/workflow-commands/SKILL.md` → §2f、joshuafolkken/kit#2121) | `pnpm josh stop:guard` — `Stop` フックで、ツリーが綺麗(`git status --porcelain` が空)なのに `run:hold` 記録が残ったまま止まる。**停止をブロックする** | ツリーが汚れている(`halfrun` の commit 前停止・`needs-human-review` 停止)、または既に解放済み = 次のランが踏まない |
|
|
79
|
+
| **Issue 引用の書式**(`prompts/collaboration-workflow/issue-citation.md`、joshuafolkken/kit#2121・joshuafolkken/kit#2247) | `pnpm josh stop:guard` — `Stop` フックで、`last_assistant_message` の地の文に裸の `#N` を含む。**停止をブロックする**(モデルに差し戻し、引用を直して返信を出し直させる) | リンク形式で引用している、コードフェンス/インラインコード/引用行の中、`PR` / `pull request` 直後の `#N`、または GitHub 向け成果物(`gh` 引数として渡る)、あるいは `stop_hook_active` が立っている = 差し戻す裸の番号が無い |
|
|
80
|
+
| **起票の申し出**(`.claude/skills/workflow-commands/SKILL.md` → §2i、joshuafolkken/kit#2422) | `pnpm josh stop:guard` — `Stop` フックで、`last_assistant_message` の地の文が起票を申し出る(「起票してよければ」等)のに、transcript 末尾に起票(`filing_cap` の数え方)が無い。**停止をブロックする** | 起票済み、フェンス/引用行の中、第三者の `owner/repo` を名指す(`repo_party.classify`)、owner 不明、または `stop_hook_active` = 保留された Tier A 起票が無い |
|
|
81
|
+
| **規則本文を散文に書き足す前の第 0 問・順序の問い**(`residency.md`、joshuafolkken/kit#2272・joshuafolkken/kit#2324) | `pnpm josh rule:guard` — `CLAUDE.md` / `prompts/**/*.md` / `.claude/skills/**/*.md` を対象とする `Edit` / `Write` で、リンク・URL を除いた正味の追記が閾値以上(規則本文の追記)。誤字・リンク張り替え・削除は当たらない。第 0 問(`oracle:list`)と順序の問い(`run:step`)を突きつける。前提を満たすまで毎回拒否する(下の「例外」)。**#2324 で stand-down** — `oracle:list` と `run:step` の両方を走らせた記録が末尾にあれば通す(リマインダではなく「問いに答えたか」で通す) | 規則ドキュメントを編集していない、追記が閾値未満、または両方の配置判定コマンドを実行済み = 散文の規則が増えていない、または配置の問いに答え済み |
|
|
82
|
+
| **オラクル未参照の行為**(`decision-oracle.ts`、joshuafolkken/kit#2324) | `pnpm josh rule:guard` — 発火点を宣言したオラクルが支配する `Bash`(`pkg:scout` = `pnpm add`)を、そのオラクルの `pnpm josh <command>` 無しで出したとき拒否。拒否文は登録簿(判断・コマンド・回答語彙・単一ソース)から組み立て手書きしない。実行するまで毎回拒否し、実行済みで stand-down。発火点を名指しできないオラクルは理由を宣言し**可視化された未強制**として残る(`oracle:list` が発火点/理由を印字)。`release:scope` は理由側で、`pnpm josh followup` のマージ**後**に owe されるリリースを読むためマージを gate せず trail する(joshuafolkken/kit#2334) | 支配下の行為を出していない、またはそのオラクルを実行済み = 規則は既に守られている |
|
|
83
83
|
|
|
84
84
|
**引き金はシェルのコマンド文字列しか見えない。** したがって node の中から REST で Issue を作る経路(`pnpm josh propagate` など)は上の正規表現に掛からない。同じ理由で、本文をファイルで渡す `gh api --input <file>` もタイトルが文字列に現れないため掛からない(`-f` / `-F` / `--field` / `--raw-field` の 4 綴りは覆う)。**これが、規則本文を配送に移したうえで常駐側にトリガ 1 行を残す理由の 1 つである** — 常駐の 1 行は経路によらず効き、配送はそれを効く瞬間に補強する。引き金つきの配送だけにすると、正規表現が知っている綴りだけが規則の適用範囲になる。
|
|
85
85
|
|
|
@@ -95,7 +95,7 @@ WIP 上限の引き金は Issue の**作成**だけを見る。`…/issues/<N>/c
|
|
|
95
95
|
|
|
96
96
|
**拒否文は「コメントも読め」という要求ではなく、読み直しのコマンドそのものを渡す。** 散文の要求は joshuafolkken/kit#1344 が 3 ラン連続で「数値がまったく動かなかった」と実測した形式であり、この行がそれを避けるのは、本文だけの読み取りが**通らない**ことによる。ランの次の一手はコメント込みの読み取りになり、コメントは「読むべきもの」ではなく実際に手元にある。ただし `PreToolUse` の拒否が運べるのは文字列 1 本だけなので、**フックがコメント本文を注入するわけではない** — 1 往復ぶん遅れて、ランが自分で取りに行く。
|
|
97
97
|
|
|
98
|
-
**この行は `batch:guard` と引き金が重なる唯一の行である。** `time_batch_guard.is_guarded_call` は `gh issue view` を候補として扱う(`gh issue create`
|
|
98
|
+
**この行は `batch:guard` と引き金が重なる唯一の行である。** `time_batch_guard.is_guarded_call` は `gh issue view` を候補として扱う(`gh issue create` は扱わない)。ただしこの行は前提を満たすまで毎回拒否するので(下の「例外」)、`is_first_delivery` の待避分岐を通らず、バッチングの拒否が出るターンでも拒否する。`delivered-rules.test.ts` がこれを固定している。
|
|
99
99
|
|
|
100
100
|
**判定はコマンド 1 件ごとに、行頭に錨を打って行う。** シェル 1 行は複数のコマンドを運ぶため、`&&` / `||` / `;` / 改行で区切った各区間をそれぞれ判定する(`|` は区切りに使わない — `--jq` の中に現れる方がはるかに多い)。これがないと 2 つの誤りが同時に出る。引用符の中に `gh issue view` を含む書き込み(`gh issue comment <N> -b "…"`)が読み取りと誤認され、逆に `gh issue view <N> && grep -c x` のように無関係な `-c` を含む行が「コメント込み」と誤認されて配送が消える。
|
|
101
101
|
|
|
@@ -117,6 +117,19 @@ WIP 上限の引き金は Issue の**作成**だけを見る。`…/issues/<N>/c
|
|
|
117
117
|
|
|
118
118
|
**`batch:guard` との待避分岐は、そういう行では守る対象が変わる。** 1 ラン 1 回の行では**記録**を守っていた — レースに負ければ、そのランに 1 度しかない配送を無駄打ちするからである。毎回発火する行はその形では消えない。一方で待機タイマーを張る呼び出しは定義上「単発の `Bash`」であり、まさにバッチングガードも候補として扱う形なので、**拒否まで待避させると、10 秒の窓とその中の再発行で規則がまるごと黙る**。したがって**拒否は無条件に行い、待避は「記録してよいか」として行へ渡す** — 他のフックが止めうる呼び出しでしてはならないのは、走らなかったタイマーを生きていると書き残すことだからである。配送文には「これは毎回発火する」と明記する(1 回きりだと読まれると、再発行すれば通ると誤解される)。
|
|
119
119
|
|
|
120
|
+
### 例外 — 前提を求める行は、前提が満たされるまで毎回拒否する(joshuafolkken/kit#2807)
|
|
121
|
+
|
|
122
|
+
**`already_satisfied`(前提の行為がトランスクリプト末尾にあるか)を持つ行は、1 ラン 1 回の対象から外れる。** 前提が末尾に現れるまで、毎回拒否する。1 ラン 1 回のままだと、前提を飛ばしたランの再発行がそのまま通る。手順を読み飛ばしたランほどガードを素通りしてしまい、ガードの意味がない。対象は `issue-fold`・`issue-comments`・`rule-body`・`oracle-consulted:*` である。
|
|
123
|
+
|
|
124
|
+
従うランが詰まることはない。前提の行為を済ませれば、stand-down が先に答えて通すからである。記録を使い切る心配もないので、`batch:guard` との待避もしない。待避すると、10 秒の窓の中の再発行が前提を満たさないまま通ってしまう。配送文には「前提が末尾に現れるまで拒否する」と明記する。
|
|
125
|
+
|
|
126
|
+
**前提の証拠を読めないときは、拒否を基本とする。** たとえば前提の行為を確かめるための記録が読めないときがこれに当たる。意図して通す例外は、理由をコードのコメントに残す。現在の例外は次のとおりである。
|
|
127
|
+
|
|
128
|
+
- トランスクリプト自体を読めないとき(`hook-decision.ts`)
|
|
129
|
+
- 初回の起票で、畳み込む相手がないとき(`issue-fold.ts`)
|
|
130
|
+
- 進捗の記録がないとき(`early-heartbeat.ts`)
|
|
131
|
+
- git の読み取りに失敗して、変更なしとして扱うとき(`delivered-rules.ts` の `test-declared` 行)
|
|
132
|
+
|
|
120
133
|
## 本文のシェル評価は同じ機構の 1 行で覆った(joshuafolkken/kit#1198)
|
|
121
134
|
|
|
122
135
|
コメント本文をシェルに載せるとバッククォートがコマンドとして実行される問題は、**この機構の追加 1 行で覆った**。起票時の見込みどおり新しい機構は要らず、`delivered-rules.ts` の `shell-body` 行と、その発火・非発火を固定するテストで足りている(実装先として書いていた joshuafolkken/kit#1542 は #1198 の重複として閉じられたため、実装は #1198 側で行った)。
|
|
@@ -136,11 +149,11 @@ WIP 上限の引き金は Issue の**作成**だけを見る。`…/issues/<N>/c
|
|
|
136
149
|
- `scripts/rules/piped-verification-rule.test.ts` — 検証コマンドのパイプが `output-bounds.md` に単一ソースとして存在し、配送文が仕組み・逃げ道・境界の 3 つを運び、読み取り専用の一覧を巻き込んでいないこと
|
|
137
150
|
- `scripts/rules/pre-gate-cut-rule.test.ts` — gate 手前の cut の手順が `.claude/skills/workflow-commands/pre-gate-cut.md` に単一ソースとして存在し、この文書と `docs/josh-commands.md` の双方が引き金を書いていること。発火・非発火(レーンかつ目印ありかつ未 cut でのみ拒否し、目印の無い人・レーン外・cut 済みでは無言)は `scripts/rules/pre-gate-cut.test.ts` が固定する
|
|
138
151
|
- `scripts/rules/implementation-cut-rule.test.ts` — 実装フェーズの cut の手順が `.claude/skills/workflow-commands/pre-gate-cut.md` →「It is a guard, fired at the edit that crosses the threshold」に単一ソースとして存在し、配送文がその節・命令・再武装の契約(再開で記録を消して両ガードを再武装させること、joshuafolkken/kit#2310)を運ぶこと。発火・非発火(レーンの子かつ目印ありかつ未 cut かつしきい値超過の `Edit` / `Write` でのみ拒否し、レーン外・目印なし・非編集・cut 済み・しきい値未満では無言)は `scripts/rules/implementation-cut.test.ts` が固定する
|
|
139
|
-
- `scripts/rules/
|
|
152
|
+
- `scripts/rules/delivered-rules-filing.test.ts` — 直接起票(`gh issue create`、`…/issues` への `title` 付き POST)が毎回拒否されて `pnpm josh issue:file` を案内され、`issue:file` の呼び出し自体は拒否されないこと。起票上限と畳み込みの行が `issue:file` の呼び出しで発火し、失敗した `issue:file` 呼び出しを起票に数えないことも同じスイートが固定する
|
|
140
153
|
- `scripts/rules/filing-cap.test.ts` — 起票回数の計数(拒否された起票を数に入れないこと)を固定する。発火・非発火(10 件目まで無言・11 件目で拒否・毎回発火する)は `scripts/rules/delivered-rules.test.ts` が固定する
|
|
141
154
|
- `scripts/rules/lane-park-rule.test.ts` — レーンの子の保留の手順が `.claude/skills/workflow-commands/pre-gate-cut.md` に単一ソースとして存在し、配送文がその節を指すこと。発火・非発火(レーンの子かつ停止通知でのみ拒否し、レーン外・目印なし・停止通知でないときは無言)は `scripts/rules/lane-park.test.ts` が固定する
|
|
142
155
|
- `scripts/rules/lane-interactive-ask-rule.test.ts` — レーンの子の対話質問の手順が `.claude/skills/workflow-commands/pre-gate-cut.md` → 「The interactive ask is refused one call earlier」に単一ソースとして存在し、配送文がその節を指すこと(joshuafolkken/kit#2201)。発火・非発火(レーンの子の `AskUserQuestion` でのみ拒否し、レーン外・目印なし・対話ツールでないときは無言)と毎回発火は `scripts/rules/lane-interactive-ask.test.ts` が、終了記録からの質問・選択肢の取り出しは `scripts/agent/interactive-ask.test.ts` が固定する
|
|
143
156
|
- `scripts/rules/lane-switch-main.test.ts` — レーンの子の `git switch main`(joshuafolkken/kit#2313)を、失敗する前に拒否する述語(`switch_target` / `is_switch_away_from_lane`)と配送文の文言を固定する。手順の単一ソースは `.claude/skills/workflow-commands/backlogrun-lanes.md` / `backlogrun-child.md`。発火・非発火(レーンの子が自分のレーンブランチ以外へ切り替えるときのみ拒否し、自ブランチ・作成/デタッチ・レーン外・主チェックアウトでは無言)と毎回発火、「1 コマンドを 1 行だけが主張する」ことは同スイートが固定する
|
|
144
157
|
- `scripts/rules/git-argv.test.ts` / `scripts/rules/git-force.test.ts` / `scripts/rules/worktree-guard.test.ts` / `scripts/rules/file-body.test.ts` — Bash 文字列の 3 群(joshuafolkken/kit#2120)の述語と配送文の文言を固定する。実際の配送経路での発火・無言と「1 コマンドを 1 行だけが主張する」ことは `scripts/rules/delivered-rules-bash.test.ts` が固定する
|
|
145
|
-
- `scripts/rules/rule-body-guard.test.ts` — 規則本文を散文に書き足す `Edit` / `Write`(joshuafolkken/kit#2272)の述語・配送文・列挙表掲載を固定する。発火(規則ドキュメントへの追記)と無言(誤字・リンク張り替え・削除・非規則ファイル・非 Edit/Write
|
|
158
|
+
- `scripts/rules/rule-body-guard.test.ts` — 規則本文を散文に書き足す `Edit` / `Write`(joshuafolkken/kit#2272)の述語・配送文・列挙表掲載を固定する。発火(規則ドキュメントへの追記)と無言(誤字・リンク張り替え・削除・非規則ファイル・非 Edit/Write)、および実際の配送経路での「2 つのコマンドを実行するまで毎回拒否」はこの 1 スイートが固定する。配送文が第 0 問(`oracle:list`)と順序の問い(`run:step`)を運び、単一ソースが `residency.md` であることも同じスイートが押さえる
|
|
146
159
|
- `scripts/rules/stop-rules-rule.test.ts` — 停止時 4 規則の単一ソース(`CLAUDE.md` の停止通知・`SKILL.md` → §2f・`SKILL.md` → §2i・`issue-citation.md`)と `rule-delivery.md` の列挙表掲載を固定する。発火・無言(押さえ×未通知でブロック/綺麗×押さえでブロック/汚れ・通知済みで無言/`stop_hook_active` で無言/起票の申し出×未起票でブロック・起票済み/第三者リポジトリ/owner 不明で無言/裸 `#N` でブロック・リンク形式やコードフェンス/インラインコード/引用行/PR 参照の中で無言)は `scripts/rules/stop-rules.test.ts`・`scripts/rules/filing-offer.test.ts`・`scripts/rules/issue-citation.test.ts` が、`Stop` フックの配線は `scripts/claude/claude-settings-hooks.test.ts` が固定する
|