@joshuafolkken/kit 1.1136.0 → 1.1178.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 +14 -63
- package/.claude/skills/workflow-commands/backlogrun-park.md +16 -15
- 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 +65 -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 +35 -95
- 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/.github/workflows/ci.yml +15 -2
- 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-32GQTL4F.js} +14 -1
- package/dist/hooks/{chunk-HBKZLITF.js → chunk-DO6NWWHU.js} +4 -4
- package/dist/hooks/{chunk-KBXZLMRH.js → chunk-G6KRCKEC.js} +216 -76
- package/dist/hooks/{chunk-JKKTVDAG.js → chunk-GDS5N2KB.js} +186 -309
- package/dist/hooks/chunk-I4XSL4TT.js +56 -0
- package/dist/hooks/{chunk-GDU26K3J.js → chunk-S6X6WYKR.js} +886 -174
- package/dist/hooks/{chunk-FO2I7UT7.js → chunk-UAGLLIGZ.js} +1 -1
- package/dist/hooks/{chunk-RFWWUI5F.js → chunk-VESKRQOF.js} +3 -3
- package/dist/hooks/{chunk-KOKOAV6D.js → chunk-VQLLNFNT.js} +6 -4
- package/dist/hooks/{chunk-LJBLGHEH.js → chunk-ZAL3NRGL.js} +4 -6
- 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 +178 -177
- package/dist/hooks/investigation-guard.js +5 -5
- package/dist/hooks/pretool-guard.js +11 -10
- package/dist/hooks/stop-guard.js +20 -6
- package/dist/josh.js +29 -3
- 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-next.ts +15 -4
- package/scripts/backlog/backlog-offer.ts +6 -6
- package/scripts/backlog/backlog-plan-cli.ts +6 -5
- package/scripts/backlog/backlog-rank.ts +18 -9
- package/scripts/backlog/backlog-restructure.ts +152 -0
- package/scripts/backlog/backlog-waves.ts +15 -17
- package/scripts/behavior/behavior-rules.ts +11 -4
- package/scripts/cost-runtime/context-cut-threshold.ts +1 -9
- package/scripts/cost-runtime/cost-verdict.ts +15 -28
- 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/followup/git-followup-stages.ts +9 -0
- package/scripts/followup/git-pr-followup.ts +1 -1
- package/scripts/gh/git-gh-api-path.ts +7 -0
- package/scripts/gh/git-gh-issue.ts +5 -3
- package/scripts/gh/git-gh-pr-read.ts +4 -0
- package/scripts/gh/git-pr-checks-eval.ts +8 -0
- package/scripts/gh/git-pr-checks.ts +11 -1
- package/scripts/git/constants.ts +10 -0
- package/scripts/git/main-merge.ts +57 -21
- package/scripts/git/schemas.ts +2 -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 +11 -1
- package/scripts/josh/josh-commands-issue.ts +2 -2
- package/scripts/lane/lane-launch-cli.ts +21 -3
- package/scripts/lines/bytes-command.ts +29 -6
- package/scripts/notify/telegram-notify.ts +26 -1
- 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/pre-gate-cut.ts +2 -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-carry.ts +11 -5
- package/scripts/run/run-cut-cli.ts +1 -1
- package/scripts/run/run-cut-handoff.ts +21 -1
- package/scripts/run/run-cut-report.ts +2 -2
- 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-cli.ts +27 -6
- package/scripts/run/run-ship-next.ts +13 -0
- package/scripts/run/run-ship-pre-detach.ts +66 -0
- package/scripts/run/run-ship-preflight.ts +34 -3
- package/scripts/run/run-ship-return.ts +7 -4
- package/scripts/run/run-ship-review-steps.ts +1 -1
- package/scripts/run/run-ship-review.ts +26 -5
- package/scripts/run/run-ship-stage.ts +13 -0
- package/scripts/run/run-ship-steps.ts +10 -2
- package/scripts/run/run-ship-sync.ts +114 -0
- package/scripts/run/run-ship.ts +6 -0
- package/scripts/run/run-step-cli.ts +20 -7
- package/scripts/run/run-wake-cli.ts +8 -1
- package/scripts/run/run-wake-driver.ts +62 -8
- package/scripts/run/run-wake-session.ts +2 -1
- package/scripts/test/test-declared-logic.ts +1 -1
- package/scripts/test/test-red-logic.ts +17 -2
- package/scripts/test/test-red.ts +8 -7
- 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/time-runtime/time-transcript-line.ts +27 -1
- 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
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
2
|
import {
|
|
3
|
+
pretool_guard,
|
|
3
4
|
pretool_outcome_async
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-G6KRCKEC.js";
|
|
6
|
+
import "./chunk-GDS5N2KB.js";
|
|
6
7
|
import "./chunk-3V37IID6.js";
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
9
|
-
import "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
8
|
+
import "./chunk-VQLLNFNT.js";
|
|
9
|
+
import "./chunk-VESKRQOF.js";
|
|
10
|
+
import "./chunk-DO6NWWHU.js";
|
|
11
|
+
import "./chunk-ZAL3NRGL.js";
|
|
12
|
+
import "./chunk-I4XSL4TT.js";
|
|
12
13
|
import {
|
|
13
14
|
hook_decision
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
15
|
+
} from "./chunk-32GQTL4F.js";
|
|
16
|
+
import "./chunk-S6X6WYKR.js";
|
|
16
17
|
import "./chunk-WPALEIRX.js";
|
|
17
18
|
import "./chunk-RKUAD3I6.js";
|
|
18
19
|
|
|
@@ -24,6 +25,6 @@ if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
|
24
25
|
else {
|
|
25
26
|
const raw_payload = await text(process.stdin);
|
|
26
27
|
hook_decision.load_environment_file();
|
|
27
|
-
|
|
28
|
+
pretool_guard.emit(raw_payload, await pretool_outcome_async(raw_payload));
|
|
28
29
|
}
|
|
29
30
|
}
|
package/dist/hooks/stop-guard.js
CHANGED
|
@@ -25,14 +25,14 @@ import {
|
|
|
25
25
|
run_headless,
|
|
26
26
|
run_hold,
|
|
27
27
|
run_invocation
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-GDS5N2KB.js";
|
|
29
29
|
import {
|
|
30
30
|
session_language
|
|
31
31
|
} from "./chunk-6V5OPIUU.js";
|
|
32
32
|
import {
|
|
33
33
|
hook_decision,
|
|
34
34
|
lane_child_marker
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-32GQTL4F.js";
|
|
36
36
|
import {
|
|
37
37
|
PROJECT_ROOT,
|
|
38
38
|
json_value,
|
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
time_density_hook,
|
|
41
41
|
time_hook_transcript,
|
|
42
42
|
time_reported_failure
|
|
43
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-S6X6WYKR.js";
|
|
44
44
|
import "./chunk-WPALEIRX.js";
|
|
45
45
|
import "./chunk-RKUAD3I6.js";
|
|
46
46
|
|
|
@@ -419,6 +419,9 @@ async function timed_fetch(url, init = {}, timeout_ms = FETCH_TIMEOUT_MS) {
|
|
|
419
419
|
// scripts/notify/telegram-notify.ts
|
|
420
420
|
import { z } from "zod";
|
|
421
421
|
var TELEGRAM_API_BASE = "https://api.telegram.org";
|
|
422
|
+
var TELEGRAM_TEXT_LIMIT = 4096;
|
|
423
|
+
var BODY_TRUNCATION_MARK = "\n...";
|
|
424
|
+
var TRAILING_HIGH_SURROGATE = /[\uD800-\uDBFF]$/u;
|
|
422
425
|
var telegram_environment_schema = z.object({
|
|
423
426
|
telegram_bot_token: z.string().min(1, { message: "TELEGRAM_BOT_TOKEN is required" }),
|
|
424
427
|
telegram_chat_id: z.string().min(1, { message: "TELEGRAM_CHAT_ID is required" })
|
|
@@ -502,9 +505,20 @@ function build_blocks(input) {
|
|
|
502
505
|
blocks.push(...build_url_parts(input));
|
|
503
506
|
return blocks;
|
|
504
507
|
}
|
|
505
|
-
function
|
|
508
|
+
function join_blocks(input) {
|
|
506
509
|
return build_blocks(input).join("\n\n");
|
|
507
510
|
}
|
|
511
|
+
function head_of(body, kept) {
|
|
512
|
+
const head = body.slice(0, kept);
|
|
513
|
+
return TRAILING_HIGH_SURROGATE.test(head) ? head.slice(0, -1) : head;
|
|
514
|
+
}
|
|
515
|
+
function build_text(input) {
|
|
516
|
+
const text2 = join_blocks(input);
|
|
517
|
+
const overflow = text2.length - TELEGRAM_TEXT_LIMIT;
|
|
518
|
+
if (overflow <= 0 || input.body === void 0) return text2;
|
|
519
|
+
const kept = Math.max(0, input.body.length - overflow - BODY_TRUNCATION_MARK.length);
|
|
520
|
+
return join_blocks({ ...input, body: `${head_of(input.body, kept)}${BODY_TRUNCATION_MARK}` });
|
|
521
|
+
}
|
|
508
522
|
async function post_message(config, text2) {
|
|
509
523
|
const url = `${TELEGRAM_API_BASE}/bot${config.bot_token}/sendMessage`;
|
|
510
524
|
const response = await timed_fetch(url, {
|
|
@@ -835,14 +849,14 @@ var stop_payload_schema = z3.object({
|
|
|
835
849
|
});
|
|
836
850
|
var NO_OUTCOME = { reason: void 0 };
|
|
837
851
|
var STOP_NOTIFY_REASON = '\u26D4 mid-workflow stop notification: this working tree is still held by a run and no `confirmation` Telegram was sent this turn, so a person is being left to wait off-screen without knowing the run paused. `CLAUDE.md` \u2192 "Mid-workflow stop notification" requires `pnpm josh notify --task-type confirmation --issue-url "<url>" --body=$\'<reason>\'` before any mid-workflow pause. Send it, then end with a one-line confirmation that it was sent \u2014 do not repeat your previous reply. This fires only while the hold is held and no notify is on the transcript, and `stop_hook_active` lets a second stop through so a run is never wedged.';
|
|
838
|
-
var HOLD_RELEASE_REASON = "\u26D4 working-tree hold not released: this working tree is clean but its `run:hold` record is still in place, so the next run here runs `git switch main && git pull` believing the tree is free while you hold it.
|
|
852
|
+
var HOLD_RELEASE_REASON = "\u26D4 working-tree hold not released: this working tree is clean but its `run:hold` record is still in place, so the next run here runs `git switch main && git pull` believing the tree is free while you hold it. The workflow-commands skill \u2192 `working-tree-hold.md`: a stop that leaves the tree clean releases the hold with `pnpm josh run:release <N>` (bare for a `new` entry). A `halfrun` pre-commit stop and a `needs-human-review` stop keep the hold because their tree is dirty, and a `prrun` stop keeps it by its stop mark \u2014 this row is silent there. Release it, then end with a one-line confirmation that it was released \u2014 do not repeat your previous reply.";
|
|
839
853
|
var ISSUE_CITATION_REASON = "Session-facing output cites an Issue as a number-link so the reader can click through and see which repository it is (`CLAUDE.md`, `prompts/collaboration-workflow/issue-citation.md`).";
|
|
840
854
|
function build_citation_reason(references) {
|
|
841
855
|
const numbers = references.join(", ");
|
|
842
856
|
const command = `pnpm josh issue:cite ${issue_citation.cite_arguments(references).join(" ")}`;
|
|
843
857
|
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}`;
|
|
844
858
|
}
|
|
845
|
-
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 (
|
|
859
|
+
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 (the workflow-commands skill \u2192 `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.';
|
|
846
860
|
var HEADLESS_WAIT_MARKER = "\u26D4 headless parent:";
|
|
847
861
|
var HEADLESS_REFUSAL_CAP = 3;
|
|
848
862
|
var HEADLESS_WAIT_CALLS = ['"command":"pnpm josh lane:await'];
|
package/dist/josh.js
CHANGED
|
@@ -26,6 +26,7 @@ import { execaSync } from "execa";
|
|
|
26
26
|
// scripts/git/constants.ts
|
|
27
27
|
import { platform } from "node:os";
|
|
28
28
|
var GIT_COMMAND_UNIX = "/usr/bin/git";
|
|
29
|
+
var GIT_BINARY_KEY = "JOSH_GIT_BINARY";
|
|
29
30
|
function get_git_command() {
|
|
30
31
|
if (platform() === "win32") {
|
|
31
32
|
return String.raw`"C:\Program Files\Git\cmd\git.exe"`;
|
|
@@ -33,6 +34,8 @@ function get_git_command() {
|
|
|
33
34
|
return GIT_COMMAND_UNIX;
|
|
34
35
|
}
|
|
35
36
|
function get_git_command_for_spawn() {
|
|
37
|
+
const binary = process.env[GIT_BINARY_KEY];
|
|
38
|
+
if (binary !== void 0 && binary !== "") return binary;
|
|
36
39
|
if (platform() === "win32") {
|
|
37
40
|
return String.raw`C:\Program Files\Git\cmd\git.exe`;
|
|
38
41
|
}
|
|
@@ -528,10 +531,10 @@ var ISSUE_COMMANDS = {
|
|
|
528
531
|
},
|
|
529
532
|
"issue:file": {
|
|
530
533
|
script: "scripts/issue/issue-file-cli.ts",
|
|
531
|
-
description: "File an Issue with every filing step: lint, Origin, duplicate scout, labels, then epic:bundle",
|
|
534
|
+
description: "File an Issue with every filing step: lint, Origin, WIP cap, duplicate scout, labels, then epic:bundle",
|
|
532
535
|
category: "AI tools",
|
|
533
536
|
reference: [
|
|
534
|
-
"<title> --body-file <path> --depth <0|1|2> [--route <route>] [--label <name>] [--repo <owner/repo>] [--distinct <N,\u2026>]",
|
|
537
|
+
"<title> --body-file <path> --depth <0|1|2> [--route <route>] [--label <name>] [--repo <owner/repo>] [--distinct <N,\u2026>] [--over-cap] [--no-auto-ok]",
|
|
535
538
|
"automation",
|
|
536
539
|
["network"]
|
|
537
540
|
]
|
|
@@ -1042,6 +1045,15 @@ var DEV_COMMANDS = {
|
|
|
1042
1045
|
// `UserPromptSubmit`, so it must stay eligible for in-process dispatch rather than pay a second
|
|
1043
1046
|
// tsx start each turn. It calls `process.loadEnvFile` itself through the shared loader.
|
|
1044
1047
|
},
|
|
1048
|
+
"codex:hook-adapter": {
|
|
1049
|
+
script: "scripts/hooks/codex-hook-adapter.ts",
|
|
1050
|
+
description: "Codex hook: run the pretool or posttool guard on a Codex payload (reads the tool call on stdin)",
|
|
1051
|
+
category: "Development",
|
|
1052
|
+
reference: ["<pretool|posttool>", "automation", ["none"]]
|
|
1053
|
+
// The live-source fallback `scripts/hooks/run-hook.sh` derives from the `codex-hook-adapter`
|
|
1054
|
+
// bundle name (joshuafolkken/kit#3184). **No `tsx_arguments`**, the same as `pretool:guard`
|
|
1055
|
+
// above: it runs before every guarded Codex call.
|
|
1056
|
+
},
|
|
1045
1057
|
"cspell:dot": {
|
|
1046
1058
|
script: "scripts/lint/cspell-cached.ts",
|
|
1047
1059
|
description: "Run spell check including dotfiles",
|
|
@@ -1080,7 +1092,7 @@ var DEV_COMMANDS = {
|
|
|
1080
1092
|
},
|
|
1081
1093
|
"test:red": {
|
|
1082
1094
|
script: "scripts/test/test-red.ts",
|
|
1083
|
-
description: "Run the changed unit tests against the pre-fix tree (merge-base worktree) and report red/green/no-test",
|
|
1095
|
+
description: "Run the changed unit tests against the pre-fix tree (merge-base worktree) and report red/green/no-test/test-only",
|
|
1084
1096
|
category: "Development",
|
|
1085
1097
|
reference: ["", "developer", ["git", "processes"]]
|
|
1086
1098
|
},
|
|
@@ -1688,6 +1700,7 @@ var REPO_PATH_SEGMENTS = 2;
|
|
|
1688
1700
|
var NOT_FOUND = -1;
|
|
1689
1701
|
var SECTION_PREFIX = "[";
|
|
1690
1702
|
var ORIGIN_SECTION = /^\[remote\s+"origin"\]$/u;
|
|
1703
|
+
var REMOTE_SECTION = /^\[remote\s+"[^"]+"\]$/u;
|
|
1691
1704
|
var URL_KEY = "url";
|
|
1692
1705
|
function is_github_hostname(host) {
|
|
1693
1706
|
return host.toLowerCase() === GITHUB_HOST;
|
|
@@ -1747,6 +1760,18 @@ function parse_origin_from_config(content) {
|
|
|
1747
1760
|
const lines = content.split("\n").map((line) => line.trim());
|
|
1748
1761
|
return origin_section_lines(lines).map((line) => entry_value(line, URL_KEY)).find((url) => url !== void 0);
|
|
1749
1762
|
}
|
|
1763
|
+
function section_groups(lines) {
|
|
1764
|
+
const groups = [];
|
|
1765
|
+
for (const line of lines) {
|
|
1766
|
+
if (is_section_header(line)) groups.push([line]);
|
|
1767
|
+
else groups.at(-1)?.push(line);
|
|
1768
|
+
}
|
|
1769
|
+
return groups;
|
|
1770
|
+
}
|
|
1771
|
+
function parse_remote_urls_from_config(content) {
|
|
1772
|
+
const lines = content.split("\n").map((line) => line.trim());
|
|
1773
|
+
return section_groups(lines).filter((group) => REMOTE_SECTION.test(group[0] ?? "")).flatMap((group) => group.map((line) => entry_value(line, URL_KEY))).filter((url) => url !== void 0);
|
|
1774
|
+
}
|
|
1750
1775
|
function format_identity(identity) {
|
|
1751
1776
|
return `${identity.owner}${PATH_SEPARATOR2}${identity.repo}`.toLowerCase();
|
|
1752
1777
|
}
|
|
@@ -1756,6 +1781,7 @@ var repo_origin = {
|
|
|
1756
1781
|
is_github_ssh_host,
|
|
1757
1782
|
parse_origin_from_config,
|
|
1758
1783
|
parse_origin_url,
|
|
1784
|
+
parse_remote_urls_from_config,
|
|
1759
1785
|
format_identity
|
|
1760
1786
|
};
|
|
1761
1787
|
|
package/dist/version/index.js
CHANGED
|
@@ -1160,7 +1160,11 @@ function read_release_times(package_name) {
|
|
|
1160
1160
|
const parsed = times_schema.safeParse(read_packument(package_name, FULL_ACCEPT));
|
|
1161
1161
|
return parsed.success ? parsed.data.time : void 0;
|
|
1162
1162
|
}
|
|
1163
|
-
|
|
1163
|
+
function has_public_version(package_name, version) {
|
|
1164
|
+
const parsed = times_schema.safeParse(read_packument(package_name, FULL_ACCEPT));
|
|
1165
|
+
return parsed.success && parsed.data.time[version] !== void 0;
|
|
1166
|
+
}
|
|
1167
|
+
var npm_registry = { has_public_version, packument_url, read_latest, read_release_times };
|
|
1164
1168
|
|
|
1165
1169
|
// scripts/version/version-remote.ts
|
|
1166
1170
|
var TIMES_PAGE_SIZE = 100;
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.
|
|
2
|
+
"version": "1.1178.0",
|
|
3
3
|
"name": "@joshuafolkken/kit",
|
|
4
4
|
"description": "Development toolkit for AI-assisted projects: formatting, AI assistant rules and a Git/GitHub Issue workflow for any repository, plus lint, type check, tests and hooks for Node projects",
|
|
5
5
|
"keywords": [
|
|
@@ -94,6 +94,7 @@
|
|
|
94
94
|
"!scripts/exports/namespace-members.ts",
|
|
95
95
|
"!scripts/exports/unused-members.ts",
|
|
96
96
|
"!scripts/document/generate-catalog.ts",
|
|
97
|
+
"!scripts/document/issue-citation-budget.ts",
|
|
97
98
|
"!scripts/document/retired-phrases.ts",
|
|
98
99
|
"!scripts/document/review-agent-type.ts",
|
|
99
100
|
"!scripts/document/single-source.ts",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
`CLAUDE.md` →「Never carry a file's new text inside a shell command.」の正典。
|
|
4
4
|
|
|
5
|
-
`pnpm josh rule:guard`(file-body の行)が、既存ファイルを書き戻すヒアドキュメント・書き込みを伴うインタプリタ heredoc / `node -e
|
|
5
|
+
`pnpm josh rule:guard`(file-body の行)が、既存ファイルを書き戻すヒアドキュメント・書き込みを伴うインタプリタ heredoc / `node -e`・書き込むスクリプトファイルを作るヒアドキュメント・in-place `perl -0pi -e` を、コマンドの何行目にあってもその呼び出しで拒否し、規則を述べる。**このファイルが担うのはガードに見えないもの**である — Bash を通らない Edit / Write の全文書き直し、ガードを素通りする `sed -i` の 4 条件、そしてコストである。
|
|
6
6
|
|
|
7
7
|
### 何を禁じているか
|
|
8
8
|
|
|
@@ -38,7 +38,7 @@ PY
|
|
|
38
38
|
|
|
39
39
|
- **新規ファイルの作成** — 既存本文が無いので、運ぶ重複がそもそも発生しない
|
|
40
40
|
- **ファイル全体の作り直し** — 構成の組み替えや生成物の再生成で、変更後の本文が元の本文とほとんど共有しない場合
|
|
41
|
-
- **部分編集のほうが大きくなる場合** — 変更箇所がファイル全域に散っていて、`old_string` / `new_string`
|
|
41
|
+
- **部分編集のほうが大きくなる場合** — 変更箇所がファイル全域に散っていて、`old_string` / `new_string` の合計が全文を超えるとき。このときも全文は **Write ツール**で書く — ヒアドキュメントやインタプリタで書き戻す形は、この例外でもガードに拒否される
|
|
42
42
|
|
|
43
43
|
**レビュー指摘の修正がこの規則の主戦場である。** 「この行の条件が逆」「この定数を切り出す」といった局所的な指摘ほど、部分編集は小さくなる。一方で全文書き直しのコストはファイルの大きさで決まり、指摘の小ささでは下がらない。**指摘が局所的であるほど、全文書き直しとの差は開く。**
|
|
44
44
|
|
|
@@ -55,14 +55,15 @@ PY
|
|
|
55
55
|
|
|
56
56
|
**4 条件のどれかが面倒に見えたら、そこが Edit を使う場所である。** `sed` はコストを下げるための例外であって、既定の編集手段ではない。
|
|
57
57
|
|
|
58
|
-
| 形
|
|
59
|
-
|
|
|
60
|
-
| Edit(数行の old / new)
|
|
61
|
-
| `sed -i` の短い置換
|
|
62
|
-
| `python3 - <<'PY'` で領域を書き戻す
|
|
63
|
-
| `cat > file <<'EOF'` で既存ファイルを書き直す
|
|
64
|
-
| `cat > new-file <<'EOF'` で新規ファイルを作る
|
|
65
|
-
|
|
|
58
|
+
| 形 | 可否 | 理由 |
|
|
59
|
+
| -------------------------------------------------- | ------------ | --------------------------------------------------------- |
|
|
60
|
+
| Edit(数行の old / new) | 可 | 差分だけが本文に載る |
|
|
61
|
+
| `sed -i` の短い置換 | 条件付きで可 | パターンと置換語しか載らない。上の 4 条件を満たすこと |
|
|
62
|
+
| `python3 - <<'PY'` で領域を書き戻す | 不可 | 置換後の本文が丸ごと載る |
|
|
63
|
+
| `cat > file <<'EOF'` で既存ファイルを書き直す | 不可 | 同上 |
|
|
64
|
+
| `cat > new-file <<'EOF'` で新規ファイルを作る | 可 | 既存本文を運んでいない。ただし長文なら Write のほうが安い |
|
|
65
|
+
| `cat > edit.py <<'EOF'` で書き込むスクリプトを作る | 不可 | 実行を 1 呼び出し後ろにずらしただけで、置換後の本文が載る |
|
|
66
|
+
| 読み取り・検索(`cat` / `sed -n` / `grep`) | 可 | 本文を運ばない |
|
|
66
67
|
|
|
67
68
|
### なぜコストが二重になるか
|
|
68
69
|
|
|
@@ -32,10 +32,8 @@ egress が `403` で拒否されるため、GraphQL を経由するサブコマ
|
|
|
32
32
|
- **引用の形**(そのままでよい)— 「`gh issue create` は使わない」のような禁止の引用や、「このサブコマンドは
|
|
33
33
|
GraphQL を経由する」のような CLI の対応状況の記録。書き換えると、何を禁じているのかが読めなくなる。
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
allowlist に 25 件を並べることになり、それは何も守らない(joshuafolkken/kit#1505)。そこでガードは
|
|
38
|
-
フェンスに留め、散文の側はこの規則と `scripts/gh/gh-document-guard.test.ts` のマーカーテストで押さえる。
|
|
35
|
+
**この区別は機械には引けない** — 文書ガードはフェンス付きコードブロックだけを走査するので、散文の側は
|
|
36
|
+
書き手がこの区別で守る(`docs/maintainers/gh-rest-rationale.md` → "Why the document guard scans fences only")。
|
|
39
37
|
|
|
40
38
|
**書き換えるときは `pnpm josh` のコマンドで置き換えられないかを先に見る。** 例えば Issue の状態を読むのは
|
|
41
39
|
`gh issue view` ではなく `pnpm josh issue:state <N>` で、これはラベルと `human_review` まで一度に返す。
|
|
@@ -14,4 +14,4 @@
|
|
|
14
14
|
- **interrupt** — WIP 上限を超えても起票できる、3 条件で決まる発見。別パッケージ起因の上流起票(割り込み Issue)とは別の区分。→ `prompts/collaboration-workflow/wip-cap.md` → "割り込み起票"、`prompts/collaboration-workflow/upstream-interrupt.md` → "別パッケージ起因の問題は割り込み Issue で対応する"
|
|
15
15
|
- **Tier** — 判断点の 3 区分。A は可逆で自分で決める、B は拮抗していて人に聞く、C は不可逆・共有状態で明示指示が要る。→ `CLAUDE.md` → "Decision autonomy"、`prompts/collaboration-workflow/operating-rules.md` → "意思決定の自律ポリシー"
|
|
16
16
|
- **carry** — `backlogrun` の 1 回の起動の予算と進捗を、セッション cut をまたいで引き継ぐ記録(`pnpm josh run:carry`)。→ `.claude/skills/workflow-commands/backlogrun-steps.md` → "The session cut is inside the invocation"
|
|
17
|
-
- **wave** — エピックの子をまとめて並行実行する組。仕組みではなく、依存宣言で表す形。→ `.claude/skills/epic-commands/
|
|
17
|
+
- **wave** — エピックの子をまとめて並行実行する組。仕組みではなく、依存宣言で表す形。→ `.claude/skills/epic-commands/execution-waves.md` → "Execution waves — parallel, then one alone, then the rest"
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## セッション向け出力で Issue はリンク+セッション言語の短い要約で参照する(joshuafolkken/kit#1758)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
番号だけの言及では、読み手は番号を内容に解決するために毎回 GitHub を開くことになる(`docs/maintainers/issue-citation-rationale.md` → "Why the rule exists")。発火点が `CLAUDE.md` に常駐している理由は `docs/maintainers/issue-citation-rationale.md` → "Why the trigger is resident in CLAUDE.md" にある。
|
|
6
6
|
|
|
7
7
|
**規則**: セッション向け出力で Issue を指すときは、次の 2 つを必ず添える。
|
|
8
8
|
|
|
@@ -13,11 +13,11 @@
|
|
|
13
13
|
|
|
14
14
|
- `[#<N>](https://github.com/<owner>/<repo>/issues/<N>) — <その Issue が何をするものかの短い要約>`
|
|
15
15
|
|
|
16
|
-
**この引用行は手で組み立てるものではなく、`pnpm josh issue:cite <N> [<N> ...]` が出す。** 番号を並べて渡すと、貼れる引用行を 1 呼び出しでまとめて出す(複数 Issue に 1 回、他リポジトリは `--repo <owner/repo>` あるいは `owner/repo#N`
|
|
16
|
+
**この引用行は手で組み立てるものではなく、`pnpm josh issue:cite <N> [<N> ...]` が出す。** 番号を並べて渡すと、貼れる引用行を 1 呼び出しでまとめて出す(複数 Issue に 1 回、他リポジトリは `--repo <owner/repo>` あるいは `owner/repo#N` 表記。`docs/maintainers/issue-citation-rationale.md` → "Why issue:cite prints the line")。要約はその Issue のタイトルをそのまま用いる。詳細は [docs/josh-commands.md](https://github.com/joshuafolkken/kit/blob/main/docs/josh-commands.md) の `josh issue:cite` を参照。
|
|
17
17
|
|
|
18
18
|
**要約タイトルは全訳ではなく要約でよい。** 何をするものか分かれば足りる。長い訳を作ることが目的ではない。`issue:cite` が出すタイトルを、必要ならセッション言語に言い換えて使う。
|
|
19
19
|
|
|
20
|
-
**対応前の言及も対象である。**
|
|
20
|
+
**対応前の言及も対象である。** 「これから走らせる」「待機中」「対象外」を並べる場面も含む。
|
|
21
21
|
|
|
22
22
|
### 適用範囲
|
|
23
23
|
|
|
@@ -27,12 +27,8 @@
|
|
|
27
27
|
|
|
28
28
|
### 英語固定の 3 つとは衝突しない
|
|
29
29
|
|
|
30
|
-
英語のままにするものは従来どおり 3
|
|
31
|
-
|
|
32
|
-
### なぜ CLAUDE.md に常駐させるか
|
|
33
|
-
|
|
34
|
-
規則の発火点は「セッション向け出力で Issue 番号を書こうとした瞬間」であり、これはワークフローのスキルを読んでいないターンでも起こる。したがって発火点(引き金)と形式は `CLAUDE.md` の Communication 節に常駐させ、本文(この節)を話題ファイルに置く。常駐側は短く保ち、詳細はここから読む。
|
|
30
|
+
英語のままにするものは従来どおり 3 つ(`overview.md` →「出力の言語(`JOSH_SESSION_LANG`)」)。番号に添えるセッション言語の要約は GitHub 上の**タイトル**ではなく、セッション内の散文の一部なので、タイトルの英語固定とは矛盾しない。
|
|
35
31
|
|
|
36
32
|
### 停止時の担保(joshuafolkken/kit#2247)
|
|
37
33
|
|
|
38
|
-
`Stop` フック `pnpm josh stop:guard` が返信の地の文に裸の `#N` を見つけると**停止をブロックし**、その番号と `pnpm josh issue:cite <N...>`
|
|
34
|
+
`Stop` フック `pnpm josh stop:guard` が返信の地の文に裸の `#N` を見つけると**停止をブロックし**、その番号と `pnpm josh issue:cite <N...>` の実行形を差し戻す。差し戻されたら、その実行形で引用し直す(仕組みは `docs/maintainers/issue-citation-rationale.md` → "How the Stop hook delivers it")。検出が外す範囲は [docs/josh-commands.md](https://github.com/joshuafolkken/kit/blob/main/docs/josh-commands.md) の `josh stop:guard` を参照。
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Issue には次の要素を必ず含める。
|
|
4
4
|
|
|
5
|
-
-
|
|
5
|
+
- タイトルは簡潔で明瞭な英語で記載する(「出力の言語(`JOSH_SESSION_LANG`)」の例外)。日本語のタイトルや改善できる英語のタイトルは、実装開始前に書き換え、`gh api -X PATCH repos/{owner}/{repo}/issues/<N> -f title="<title>"` で GitHub 側も合わせる
|
|
6
6
|
- 目的(何を改善したいか)
|
|
7
7
|
- 現象(現在の不具合や課題)
|
|
8
8
|
- 期待結果(完了時の状態)
|
|
@@ -32,17 +32,17 @@ Issue には次の要素を必ず含める。
|
|
|
32
32
|
|
|
33
33
|
## 発火点
|
|
34
34
|
|
|
35
|
-
<AI の振る舞いを変える Issue のみ。その規則が破れる瞬間に最初に呼ばれるツールコール名を 1 つだけ書く(例 `Bash` / `Edit` / `Read` / `Write` / `AskUserQuestion
|
|
35
|
+
<AI の振る舞いを変える Issue のみ。その規則が破れる瞬間に最初に呼ばれるツールコール名を 1 つだけ書く(例 `Bash` / `Edit` / `Read` / `Write` / `AskUserQuestion`)>
|
|
36
36
|
|
|
37
37
|
## ベースライン
|
|
38
38
|
|
|
39
|
-
<AI の振る舞いを変える Issue
|
|
39
|
+
<AI の振る舞いを変える Issue のみ。「コマンド + 値」で書く>
|
|
40
40
|
|
|
41
41
|
- `<測定コマンド>` → <現在の値>
|
|
42
42
|
|
|
43
43
|
## 再現
|
|
44
44
|
|
|
45
|
-
<AI の振る舞いを変える Issue
|
|
45
|
+
<AI の振る舞いを変える Issue のみ。「コマンド + 実際の出力」で書き、出力はフェンス(``` または ~~~)で囲む>
|
|
46
46
|
|
|
47
47
|
- `<再現コマンド>`
|
|
48
48
|
|
|
@@ -55,36 +55,26 @@ Issue には次の要素を必ず含める。
|
|
|
55
55
|
<別リポジトリのセッションから起票した場合のみ。起票元 Issue を `owner/repo#N` 形式で書く。自リポジトリ発の Issue では節ごと省略する>
|
|
56
56
|
````
|
|
57
57
|
|
|
58
|
-
###
|
|
58
|
+
### `## 背景` 直下の宣言と分類ラベル
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
起票は `pnpm josh issue:file "<title>" --body-file <本文ファイル> --depth <n>` で行う。本文の検査(`pnpm josh issue:lint <path>` と同じ)と、下表の宣言から決まる分類ラベルの付与は、このコマンドが 1 回の作成リクエストで行う。**宣言を選ぶのは起票者の判断であり、コマンドは単語から推測しない。**
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
| 宣言 | 付くラベル | 選ぶ基準 |
|
|
63
|
+
| ---------------------- | ----------------- | ------------------------------------------------------------------------------------------ |
|
|
64
|
+
| `- 種別: 不具合` | `bug` | 報告された症状を直す。`- 種別: 非不具合` とどちらか一方を必ず置く |
|
|
65
|
+
| `- 目的: 機能追加` | `enhancement` | 新しい機能。不具合修正・文書のみ・依存更新・保守作業には書かない |
|
|
66
|
+
| `- 目的: 機能改善` | `enhancement` | 既存機能の改善。目的が曖昧なら期待結果と受け入れ条件を具体化してから選ぶ |
|
|
67
|
+
| `- 互換性: 破壊的変更` | `breaking-change` | 既存の利用者・API・設定の契約を変える。移行措置があっても書き、廃止対象と影響を説明する |
|
|
68
|
+
| `- 種別: 振る舞い変更` | なし | AI の振る舞いを変える。`## 発火点` / `## ベースライン` / `## 再現` の 3 見出しが必須になる |
|
|
63
69
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
<なぜ必要か>
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
- **起票前に不具合かどうかを必ず選ぶ。** `## 背景` の直下に、不具合なら `- 種別: 不具合`、非不具合なら `- 種別: 非不具合` を置く。両方の併記も省略も `pnpm josh issue:lint` が拒否する。故障を述べる本文でも単語から自動判定せず、起票者が判断する。振る舞い変更、機能改善、互換性の宣言はこの判断と併記できる
|
|
73
|
-
- **不具合修正の Issue は `- 種別: 不具合` を宣言する。** この宣言がある Issue では、`pnpm josh git -y` が追加・変更したテストを修正前のツリー(merge-base)に当てて `pnpm josh test:red` で実行し、1 本も赤にならない(`green`)ときはコミットを拒否する。修正前でも緑の回帰テストは、報告された症状を再現していないためである(joshuafolkken/kit#2448)。回帰テストは、利用者が症状を見たのと同じ粒度で書く
|
|
74
|
-
- **起票時の `bug` ラベルは本文の宣言から決める。** 起票は `pnpm josh issue:file "<title>" --body-file <本文ファイル> --depth <n>` で行い、このコマンドが `issue:lint` と同じ検査をしたうえで、`- 種別: 不具合` の宣言があれば `bug` ラベルを同じ作成リクエストに付ける。`depth`・`route` も同じ呼び出しで付く。`bugfix` は PR のリリース分類であり、Issue の `bug` の代わりにしない
|
|
75
|
-
- **機能追加・機能改善は目的を本文で宣言する。** `## 背景` の直下に `- 目的: 機能追加` または `- 目的: 機能改善` を書く。この宣言があれば `pnpm josh issue:file` が `enhancement` ラベルを同じ作成リクエストに付ける。不具合修正、文書のみ、依存更新、保守作業はタイトルの単語から推測して宣言しない。目的が曖昧なら起票文案の期待結果と受け入れ条件を具体化してから分類する
|
|
76
|
-
- **互換性を壊す変更は影響を本文で宣言する。** 既存の利用者、API、設定の契約を変える場合は、`## 背景` の直下に `- 互換性: 破壊的変更` を書き、廃止対象と影響を説明する。移行措置や事前案内があっても破壊的変更なら宣言する。この宣言があれば `pnpm josh issue:file` が `breaking-change` ラベルを同じ作成リクエストに付ける。互換性を保つ変更には付けない。影響が曖昧なら起票文案で対象の利用者と契約を明確にしてから分類する
|
|
77
|
-
- **本文が宣言する分類ラベルは `pnpm josh issue:file` がすべて起票時に付ける。** `bug`、`enhancement`、`breaking-change` は組み合わせて付くことがある。`depth`・`route` などのラベルと併せて 1 回の作成リクエストで付け、宣言が無いとき(`issue:lint` の `labels: none`)は分類ラベルを付けない。Issue が `enhancement` と `breaking-change` の両方を持つとき、PR のリリース分類は `breaking-change` 一つにする。Issue の目的の分類と PR のリリース分類を区別する
|
|
78
|
-
- **`## 発火点`** には、その規則が破れる瞬間に最初に呼ばれるツールコール名を 1 つ書く。名前は `prompts/collaboration-workflow/rule-delivery.md` の配送表に載る、フックで配送可能なツール(`Bash` / `Edit` / `Read` / `Write` / `AskUserQuestion`)と突き合わせる。**表に無い名前**(そもそもツールコール名でない)と**不一致**(既知のツールだが配送できない)は区別して印字され、joshuafolkken/kit#2201 の「規則は正しいが名指ししたコールが実際に破れるコールの 1 つ後ろ」を起票時に検出する
|
|
79
|
-
- **`## ベースライン`** は **「コマンド + 値」** で書く。``- `<測定コマンド>` → <現在の値>`` の形に限り、自然文だけの測定説明は受け付けない(再実行できないため)。マージ後に `pnpm josh measure:rerun <N>` が同じコマンドをやり直し(本文は shell として実行されるため、作者が `OWNER` / `MEMBER` / `COLLABORATOR` の Issue に限る)、**before / after の対**を印字する。値が動かなかったとき、反証された前提として `docs/maintainers/observations/` の、その時点のブランチが指す Issue のファイルに 1 行追記される(既存の append-only 台帳を使い、別の台帳は作らない)
|
|
80
|
-
- **`## 再現`** は **「コマンド + 実際の出力」** で書く。コマンドを backtick、出力をフェンス(``` または ~~~)で囲む。自然文の「確認した」は再実行できないため受け付けない(`## ベースライン` と同じ理由)。読みだけの起票を起票時に弾くためである
|
|
81
|
-
- **検査は `pnpm josh issue:lint <path>` が行う。** 対象判定・3 見出しの有無・発火点の配送可否・ベースラインが「コマンド + 値」か・再現が「コマンド + 実際の出力」かと、起票時に必要な分類ラベルを、起票前の本文ファイルからまとめて答える(`pnpm josh issue:file` は起票前に同じ検査を行い、問題があれば起票しない)
|
|
70
|
+
- **`- 種別: 不具合` の Issue の回帰テストは、利用者が症状を見たのと同じ粒度で書く。** 修正前のツリーでも緑になるテストは `pnpm josh git -y` がコミットを拒否する(joshuafolkken/kit#2448)
|
|
71
|
+
- **`bugfix` は PR のリリース分類であり、Issue の `bug` の代わりにしない。** `enhancement` と `breaking-change` の両方を持つ Issue の PR は `breaking-change` 一つに分類する
|
|
72
|
+
- **`## 発火点`** の名前は `prompts/collaboration-workflow/rule-delivery.md` の配送表と突き合わされる
|
|
73
|
+
- **`## ベースライン`** の測定コマンドは、マージ後に `pnpm josh measure:rerun <N>` が再実行して before / after を印字する(作者が `OWNER` / `MEMBER` / `COLLABORATOR` の Issue に限る)
|
|
82
74
|
|
|
83
75
|
### 起票元へのバックリンク(`## Origin` / `## Upstream issues`)
|
|
84
76
|
|
|
85
|
-
**別リポジトリのセッションから起票した Issue
|
|
86
|
-
|
|
87
|
-
**双方向とも必須**(片方向では、上流の修正を待っている消費者側が「何を待っているのか」を辿れない):
|
|
77
|
+
**別リポジトリのセッションから起票した Issue には、起票元へのリンクを双方向で必ず書く。** 欠陥がどのプロジェクトでどう現れたかの証拠は起票元にしかない。
|
|
88
78
|
|
|
89
79
|
| 方向 | 置き場所 | 固定見出し | 内容 |
|
|
90
80
|
| --------------------- | ----------------------------- | ----------------------- | ---------------------------------------------------- |
|
|
@@ -92,106 +82,41 @@ Issue には次の要素を必ず含める。
|
|
|
92
82
|
| 起票元 Issue → 上流 | 起票元 Issue の本文かコメント | `## Upstream issues` | そこから起票した上流 Issue を全件列挙する |
|
|
93
83
|
| 起票元 Issue → 未起票 | 起票元 Issue の本文かコメント | `## Upstream candidate` | 第三者リポジトリへ報告する候補(**未起票**)と下書き |
|
|
94
84
|
|
|
95
|
-
-
|
|
96
|
-
- **リンクは必ずリポジトリ修飾する**(`owner/repo#N` または完全 URL
|
|
97
|
-
- **チェックボックス行(`- [ ] owner/repo#N
|
|
98
|
-
-
|
|
99
|
-
-
|
|
85
|
+
- **見出しは固定する**(grep で見つかるように)。起票元の本文が確定済みなら、同じ見出しでコメントに書く
|
|
86
|
+
- **リンクは必ずリポジトリ修飾する**(`owner/repo#N` または完全 URL)。裸の `#N` は上流側で別 Issue に解決される
|
|
87
|
+
- **チェックボックス行(`- [ ] owner/repo#N`)で書かない。** 散文か素の箇条書き(`- owner/repo#N`)にする — チェックボックス付きの他リポジトリ参照は epic の自動クローズを止める
|
|
88
|
+
- **未起票の候補は `## Upstream candidate` に置く。** third-party への報告はユーザーの明示指示まで起票しない(→「第三者リポジトリへの書き込みは Tier C(明示指示が必要)」)
|
|
89
|
+
- 割り込みで起票する手順は `upstream-interrupt.md`
|
|
100
90
|
|
|
101
91
|
### 複数 Issue に分割するときの epic Issue
|
|
102
92
|
|
|
103
|
-
|
|
93
|
+
**1 つの要望を 2 件以上の Issue に分割したら、件数や順序の有無にかかわらず常に epic を作る。** 分割の設計図を、最初にクローズされる子 Issue ではなく閉じない置き場に残すためである。作成は `pnpm josh epic`、点検は `pnpm josh epic:check <E>`、子の追加は `pnpm josh epic --add` で行い、本文を手で編集しない。epic 自体を実装ランに渡さない(`backlogrun #<E> --only` が子を回す)。コマンドと本文の記法は `epic-commands` スキル →「Creating an epic」。
|
|
104
94
|
|
|
105
|
-
|
|
95
|
+
**`josh` が使えない環境での手作業手順:**
|
|
106
96
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
-
|
|
110
|
-
- epic は最後の子 Issue がクローズされた時点で `pnpm josh followup` が自動クローズする。マージ後に `epic` ラベルの open な Issue を探し、タスクリストの子が全てクローズ済みなら子を列挙したコメント付きで閉じる。1 件でも open なら放置し、この処理の失敗は警告のみでランを止めない。最終 PR に `closes #<epic>` を書く方法は、バッチが途中で失敗したときにも発火して未完了を完了扱いにするため採用しない
|
|
111
|
-
- 自動クローズは `epic` ラベルとタスクリスト記法の両方に依存する。どちらかを欠くと epic は open のまま残るので、手動でクローズする
|
|
112
|
-
- タスクリストが**他リポジトリの子 Issue**(`owner/repo#N` や URL 形式)を含む場合、自動クローズは行われない。その子の状態は別リポジトリを指定しないと読めず、無視すると open のまま epic を閉じてしまうため。この場合も手動でクローズする
|
|
113
|
-
- **分割そのものが別リポジトリのセッション発である場合**(消費者リポジトリでの `kickoff new` が上流に子 Issue を起票したなど)、各子 Issue の本文に `## Origin` を、epic 本文にも同じ起票元へのリンクを書く(→「起票元へのバックリンク」)。epic 側は `Split rationale` の直後に散文か素の箇条書きで置く。**チェックボックス行で書くと直前の項目に該当して自動クローズが止まる**ため、この 1 点だけは形式を守る。起票元 Issue 側にも `## Upstream issues` として起票した子 Issue と epic を列挙する
|
|
114
|
-
- epic 本文の `Dependencies` に依存の連鎖(`#N -> #M`)が書かれているのに、手順 4 の依存関係が**一件も付いていない**場合、`pnpm josh followup` が子 Issue のマージごとに警告する。連鎖の形は検査しない(タスクリストの並び順を依存順と推測することになり誤検知を生むため)。判定の起点を本文の宣言に置くのは、epic の存在がもう順序ありを意味しないため — 順序不問のバッチにも epic を作る以上、依存関係ゼロ件は正常な状態でもありうる
|
|
97
|
+
1. 子 Issue をすべて起票し、番号を控える。
|
|
98
|
+
2. ラベルを用意する: `gh api repos/{owner}/{repo}/labels -f name=epic -f color=5319e7 -f description="Tracks a batch of child issues from one split" --silent 2>/dev/null || true`
|
|
99
|
+
3. epic を作り、`id` ではなく **number** を控える: `gh api repos/{owner}/{repo}/issues -f title="<epic-title>" -f 'labels[]=epic' -F body=@<body-file> --jq .number`。本文は次の形にする(順序がなければ `Dependencies` に `None — the children are independent; any execution order works.` と書く):
|
|
115
100
|
|
|
116
|
-
|
|
101
|
+
```md
|
|
102
|
+
## Split rationale
|
|
117
103
|
|
|
118
|
-
|
|
119
|
-
# 順序不問のバッチ
|
|
120
|
-
pnpm josh epic "<epic-title>" <N1> <N2> ...
|
|
104
|
+
<why this split>
|
|
121
105
|
|
|
122
|
-
|
|
123
|
-
pnpm josh epic "<epic-title>" <N1> <N2> ... --ordered
|
|
124
|
-
|
|
125
|
-
# 分割理由の散文を渡す(`-` で標準入力)
|
|
126
|
-
pnpm josh epic "<epic-title>" <N1> <N2> --rationale-file <path|->
|
|
127
|
-
|
|
128
|
-
# 別リポジトリのセッション発である場合のバックリンク
|
|
129
|
-
pnpm josh epic "<epic-title>" <N1> <N2> --origin <owner/repo#N>
|
|
130
|
-
```
|
|
106
|
+
## Dependencies
|
|
131
107
|
|
|
132
|
-
|
|
108
|
+
#101 -> #102
|
|
133
109
|
|
|
134
|
-
|
|
110
|
+
## Execution
|
|
135
111
|
|
|
136
|
-
|
|
112
|
+
backlogrun #<E> --only
|
|
137
113
|
|
|
138
|
-
|
|
139
|
-
2. `epic` ラベルを用意する(未作成なら `gh api repos/{owner}/{repo}/labels -f name=epic -f color=5319e7 -f description="Tracks a batch of child issues from one split" --silent 2>/dev/null || true`)
|
|
140
|
-
3. epic を作成し、番号 `<E>` を控える: `gh api repos/{owner}/{repo}/issues -f title="<epic-title>" -f 'labels[]=epic' -F body=@<body-file> --jq .number`(`--jq` を落とすと Issue の JSON 全体が出る。そこには `id` も含まれるが、**控えるのは `number` である** — `id` はデータベース id で、手順 4 が要求する値ではあっても epic の番号ではない)
|
|
141
|
-
4. 実行順序が**ある場合のみ**、子 Issue に依存関係を付与する(後述の理由により**作成後の独立ステップ**として行う):
|
|
114
|
+
## Progress
|
|
142
115
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
gh api repos/{owner}/{repo}/issues/<N3>/dependencies/blocked_by -F issue_id="$(gh api repos/{owner}/{repo}/issues/<N2> --jq .id)"
|
|
116
|
+
- [ ] #101 <title>
|
|
117
|
+
- [ ] #102 <title>
|
|
146
118
|
```
|
|
147
119
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
順序が不問なら手順 4 は行わない。epic の作成は無条件だが、依存関係の記録は順序が実在するときだけで、両者は独立している。
|
|
151
|
-
|
|
152
|
-
手順 2 の `|| true` はラベルが既に存在する場合(REST は 422 `already_exists` を返す)を無視するためのものである。**握り潰しの代償は `gh` の頃と変わっており、安全な方向に変わっている。** `gh issue create --label epic` はラベルを解決できずに失敗したため、異常は手順 3 で顕在化した。REST の `POST /issues` は `labels` に無いラベルを**その場で作る**(色と説明は既定値、joshuafolkken/kit#1026 が実測)ので、握り潰しが失うのは色と説明だけでラベル自体ではない。`epic:next` と自動クローズは名前だけを見るため、追跡は成立する。
|
|
153
|
-
|
|
154
|
-
手順 4 は REST の依存関係エンドポイントを直接叩くので `gh` のバージョンに依存しない。**失敗しても続行してよい**(付かないのは関係だけで、Issue とタスクリストは無傷)。関係付与は作成と分けて行う — 作成呼び出しに畳み込むと、関係の失敗が Issue の失敗になり、**Issue 自体が作られない**。分けておけば劣化は「Issue が消える」ではなく「関係が付かない」で済む。
|
|
155
|
-
|
|
156
|
-
epic 本文のテンプレート:
|
|
157
|
-
|
|
158
|
-
```md
|
|
159
|
-
## Split rationale
|
|
160
|
-
|
|
161
|
-
<なぜこの分割にしたか>
|
|
162
|
-
|
|
163
|
-
## Dependencies
|
|
164
|
-
|
|
165
|
-
#101 -> #102 -> #103
|
|
166
|
-
|
|
167
|
-
## Execution
|
|
168
|
-
|
|
169
|
-
backlogrun #<E> --only
|
|
170
|
-
|
|
171
|
-
## Progress
|
|
172
|
-
|
|
173
|
-
- [ ] #101 <title>
|
|
174
|
-
- [ ] #102 <title>
|
|
175
|
-
- [ ] #103 <title>
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
`Progress` は**必ずタスクリスト記法**(`- [ ] #N`)で書く。GitHub は参照先 Issue がクローズされた時点でこの記法のチェックボックスのみを自動で埋めるため、素のリンク(`#N` の直書き)では進捗が追跡されない。ただし全項目が埋まっても GitHub が epic 自体をクローズすることはない。
|
|
179
|
-
|
|
180
|
-
`Dependencies` は順序があるなら**必ず矢印記法**(`#101 -> #102`、`->` または `→`)で書く。`pnpm josh followup` の順序未記録チェックはこの記法を検出して初めて発火するため、`#102 depends on #101` のような散文で書くと、手順 4 を飛ばしても警告されない。順序が不問なら節ごと省略せず `None — the children are independent; any execution order works.` と明示する。空欄や節の削除では「順序がない」のか「書き忘れた」のかが読み手にもチェックにも区別できない。
|
|
181
|
-
|
|
182
|
-
**宣言の行は矢印の連鎖だけで構成する。** 理由の注記を同じ行の末尾に付けた `#101 -> #102 (#102 は #101 の API を使う)` は宣言として読まれず、`epic:check` が「機械可読な宣言が無い」と報告する。読み取り側が「連鎖しか書かれていない行」だけを宣言と見なすのは、節の外にある散文の推奨実行順(`推奨実行順: #869 -> #863 -> …`)を宣言と誤読しないためで、この判定は本文を読む 3 経路(`epic:check` の存在判定・`epic:next` のリンク読み取り・`josh epic --add` の書き換え)で共有されている(joshuafolkken/kit#858、joshuafolkken/kit#1155)。理由は連鎖の**次の行**か `Split rationale` に書く。**連鎖と `None — ...` 固定文を両方書いてはならない** — 順序があると同時に無いと宣言することになり、`epic:check` は矛盾として ✖ を返す。
|
|
183
|
-
|
|
184
|
-
#### ネイティブの依存関係と sub-issues
|
|
185
|
-
|
|
186
|
-
`gh` は Issue 間の関係をネイティブに扱える。下表のフラグと JSON フィールドは **2.97.0 の実バイナリで存在を確認済み**。導入バージョンを 2.94.0 とするのは `cli/cli` のリリースノート記載によるもので、2.94.0 自体での動作確認は行っていない。GitHub Enterprise Server では依存関係に 3.19 以降が必要(github.com では制約なし)。
|
|
187
|
-
|
|
188
|
-
**下表は `gh` CLI の対応状況の記録であり、本ドキュメントのどの手順もこれを経由しない。** `pnpm josh epic` も上記のフォールバック手順 4 も、REST の依存関係エンドポイントを `gh api` で直接叩くため、下表のフラグにも 2.94.0 要件にも依存しない(joshuafolkken/kit#1026)。**下表の形は `gh issue edit` / `gh issue view` であり、いずれも GraphQL を通るためクラウドセッションでは 403 になる**(joshuafolkken/kit#1022)。表を残すのは、sub-issues を採らなかった理由が CLI の対応状況とは無関係であることを示すためである。
|
|
189
|
-
|
|
190
|
-
| 種別 | 書き込み | 読み取り |
|
|
191
|
-
| -------- | -------------------------------------------------------------------------- | ------------------------------------------------------------ |
|
|
192
|
-
| 依存関係 | `gh issue edit <N> --add-blocked-by <M>` / `--add-blocking` / `--remove-*` | `gh issue view <N> --json blockedBy,blocking` |
|
|
193
|
-
| 親子関係 | `gh issue edit <N> --parent <M>` / `--add-sub-issue` | `gh issue view <N> --json parent,subIssues,subIssuesSummary` |
|
|
194
|
-
|
|
195
|
-
**依存関係は採用する**(上記の作成手順 4)。子 Issue 単体を見たときに何を待っているかが GitHub の UI と API の両方から分かるようになり、epic 本文の `Dependencies` 行が人間向けの散文でしかなかった問題が解消する。ただし依存関係は**表示するだけで着手を防がない**ため、順序を守る責任は引き続き依存関係の宣言(`--ordered`)と、それを読む `backlogrun` にある。epic 本文の `Dependencies` 行は、関係が付かなかった場合でも読める冗長な記録として残す。
|
|
120
|
+
4. 順序があるときだけ、別ステップで依存を足す(Issue 番号ではなく database id を渡す): `gh api repos/{owner}/{repo}/issues/<N2>/dependencies/blocked_by -F issue_id="$(gh api repos/{owner}/{repo}/issues/<N1> --jq .id)"`
|
|
196
121
|
|
|
197
|
-
|
|
122
|
+
各手順の理由と経緯は kit の `docs/maintainers/epic-commands-rationale.md` →「Creating an epic by hand」。
|