@joshuafolkken/kit 1.978.0 → 1.998.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/backlogrun-child.md +1 -1
- package/.claude/skills/workflow-commands/backlogrun-steps.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/.github/workflows/sonar-qube.yml +12 -2
- package/CLAUDE.md +2 -2
- package/README.md +30 -21
- package/dist/CLAUDE.md +2 -2
- package/dist/hooks/batch-guard.js +4 -4
- package/dist/hooks/{chunk-ZYYSBNR6.js → chunk-4GDR2YTV.js} +4 -4
- package/dist/hooks/{chunk-2K52BRWV.js → chunk-56LGMJJV.js} +2 -2
- package/dist/hooks/{chunk-BNGGEY3Z.js → chunk-762BDXDU.js} +266 -327
- package/dist/hooks/{chunk-Q7LE77CO.js → chunk-7WAOP42A.js} +34 -30
- package/dist/hooks/{chunk-NXL3SBXY.js → chunk-A2H5I2VD.js} +2 -2
- package/dist/hooks/{chunk-CRGJTD6E.js → chunk-AWTFKKFW.js} +1 -1
- package/dist/hooks/{chunk-KQG4776P.js → chunk-GBJUERYK.js} +1 -1
- package/dist/hooks/{chunk-BVMSPG3M.js → chunk-KPZN42RT.js} +3 -3
- package/dist/hooks/{chunk-ZPLXLJ7O.js → chunk-PAXMLGSS.js} +42 -8
- package/dist/hooks/{chunk-F6OM6SIG.js → chunk-WMIR5SNX.js} +12 -12
- 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 +99 -27
- package/dist/josh.js +21 -6
- package/package.json +5 -1
- package/prettier/basic.d.ts +3 -0
- package/prettier/basic.js +10 -0
- package/prettier/index.js +2 -2
- package/prettier/static.js +3 -10
- 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/prompts/sonar-hotspot-handling.md +6 -0
- package/prompts/testing-guide.md +1 -1
- package/scripts/agent/agent-diagnostics.ts +1 -0
- package/scripts/agent/agent-role-profile.ts +1 -1
- package/scripts/behavior/behavior-rules.ts +8 -1
- package/scripts/build/build-claude-md.ts +13 -4
- package/scripts/delegation/delegation-policy.ts +9 -9
- package/scripts/document/document-byte-budget.ts +1 -1
- package/scripts/gate/gate-steps.ts +1 -1
- package/scripts/gate/project-checks.ts +12 -11
- package/scripts/gate/type-check-command.ts +1 -1
- package/scripts/git/git-branch.ts +14 -3
- package/scripts/git/git-issue.ts +13 -5
- package/scripts/git/git-pr.ts +16 -10
- package/scripts/git/git-preflight.ts +138 -0
- package/scripts/git/telegram-notify.ts +21 -0
- package/scripts/hooks/stop-guard.ts +2 -0
- package/scripts/init/basic-path-migration.ts +24 -0
- package/scripts/init/distributed-paths.ts +22 -0
- package/scripts/init/init-actions.ts +27 -19
- package/scripts/init/init-ai-copy.ts +86 -28
- package/scripts/init/{init-static.ts → init-basic.ts} +6 -6
- package/scripts/init/init-bootstrap.ts +4 -3
- package/scripts/init/init-install.ts +1 -1
- package/scripts/init/init-logic-templates.ts +1 -1
- package/scripts/init/init-logic.ts +1 -1
- package/scripts/init/init.ts +41 -19
- package/scripts/init/kit-setup-state.ts +30 -0
- package/scripts/init/kit-written-paths.ts +33 -0
- package/scripts/init/project-profile-cli.ts +15 -1
- package/scripts/init/project-profile.ts +41 -12
- package/scripts/init/session-language-environment.ts +83 -0
- package/scripts/init/start-exec.ts +28 -0
- package/scripts/init/start-plan.ts +35 -13
- package/scripts/init/start-prompt.ts +22 -8
- package/scripts/init/start-setup-pr.ts +138 -0
- package/scripts/init/start-steps.ts +30 -30
- package/scripts/init/start.ts +7 -3
- 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 +12 -4
- package/scripts/josh/josh-command-map.ts +1 -0
- package/scripts/josh/josh-commands-development.ts +3 -3
- package/scripts/josh/josh-commands-issue.ts +11 -0
- package/scripts/josh/josh-commands-project.ts +7 -3
- package/scripts/lint/cspell-cached.ts +3 -3
- package/scripts/lint/format.ts +1 -1
- package/scripts/lint/lint-parallel.ts +2 -2
- 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 +12 -8
- package/scripts/rules/issue-citation.ts +30 -1
- package/scripts/rules/issue-fold.ts +4 -4
- package/scripts/rules/last-prompt.ts +79 -0
- 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 +8 -5
- package/scripts/safe-chain/ci-installer-pin.ts +19 -12
- package/scripts/safe-chain/project-config.ts +1 -1
- package/scripts/sync/sync-ai-files.ts +204 -0
- package/scripts/sync/sync.ts +48 -184
- package/scripts/test/josh-harness-environment.ts +1 -1
- package/scripts/test/pilot-files.ts +0 -2
- package/scripts/test/test-declared-changed.ts +1 -1
- package/scripts/test/test-declared-logic.ts +55 -14
- package/scripts/test/test-declared.ts +23 -11
- package/scripts/test/test-unit-guard.ts +6 -6
- package/scripts/time-runtime/time-shell.ts +36 -2
- package/scripts/version/fresh-metadata-cache.ts +36 -0
- package/scripts/version/latest-update.ts +2 -1
- package/scripts-ai/git-workflow.ts +10 -0
- package/templates/CLAUDE.basic.md +8 -0
- package/templates/workflows/ci.yml +27 -0
- 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
- /package/{templates/CLAUDE.static.md → dist/CLAUDE.basic.md} +0 -0
- /package/templates/{cursorrules.static → cursorrules.basic} +0 -0
- /package/templates/{pnpm-workspace.static.yaml → pnpm-workspace.basic.yaml} +0 -0
- /package/templates/{prettierignore.static → prettierignore.basic} +0 -0
package/dist/hooks/stop-guard.js
CHANGED
|
@@ -19,20 +19,22 @@ import {
|
|
|
19
19
|
run_hold,
|
|
20
20
|
run_invocation,
|
|
21
21
|
run_watcher_guard
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-7WAOP42A.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-GBJUERYK.js";
|
|
30
30
|
import {
|
|
31
31
|
PROJECT_ROOT,
|
|
32
|
+
json_value,
|
|
32
33
|
stamp_file,
|
|
33
34
|
time_density_hook,
|
|
34
|
-
time_hook_transcript
|
|
35
|
-
|
|
35
|
+
time_hook_transcript,
|
|
36
|
+
time_reported_failure
|
|
37
|
+
} from "./chunk-PAXMLGSS.js";
|
|
36
38
|
import "./chunk-WPALEIRX.js";
|
|
37
39
|
import "./chunk-RKUAD3I6.js";
|
|
38
40
|
|
|
@@ -329,6 +331,17 @@ function bare_references(message2) {
|
|
|
329
331
|
for (const line of prose_lines(message2)) collect_line_references(line, found);
|
|
330
332
|
return [...new Set(found)];
|
|
331
333
|
}
|
|
334
|
+
function prompt_references(prompt) {
|
|
335
|
+
const found = /* @__PURE__ */ new Set();
|
|
336
|
+
for (const match of prompt.matchAll(ISSUE_NUMBER)) {
|
|
337
|
+
found.add(repo_prefix(prompt, match.index) + match[0]);
|
|
338
|
+
}
|
|
339
|
+
return found;
|
|
340
|
+
}
|
|
341
|
+
function unquoted_references(message2, prompt) {
|
|
342
|
+
const quoted = prompt_references(prompt);
|
|
343
|
+
return bare_references(message2).filter((reference) => !quoted.has(reference));
|
|
344
|
+
}
|
|
332
345
|
function has_bare_reference(message2) {
|
|
333
346
|
return bare_references(message2).length > 0;
|
|
334
347
|
}
|
|
@@ -366,7 +379,14 @@ function linkify(message2, slug) {
|
|
|
366
379
|
}
|
|
367
380
|
return out.join("\n");
|
|
368
381
|
}
|
|
369
|
-
var issue_citation = {
|
|
382
|
+
var issue_citation = {
|
|
383
|
+
bare_references,
|
|
384
|
+
cite_arguments,
|
|
385
|
+
has_bare_reference,
|
|
386
|
+
linkify,
|
|
387
|
+
prose_lines,
|
|
388
|
+
unquoted_references
|
|
389
|
+
};
|
|
370
390
|
|
|
371
391
|
// scripts/epic/epic-triage.ts
|
|
372
392
|
var TRIAGE_VERDICT = "triage";
|
|
@@ -684,6 +704,8 @@ var TASK_DEFINITIONS = {
|
|
|
684
704
|
stalled: { icon: "\u23F3", label: "Ready work is sitting undispatched" },
|
|
685
705
|
stranded: { icon: "\u{1F6A8}", label: "Run stranded \u2014 nobody is driving it" }
|
|
686
706
|
};
|
|
707
|
+
var NOTIFY_SWITCH_KEY = "JOSH_NOTIFY";
|
|
708
|
+
var NOTIFY_OFF_VALUE = "off";
|
|
687
709
|
var NOT_CONFIGURED_PREFIX = "Telegram is not configured";
|
|
688
710
|
var SEND_FAILED_PREFIX = "Telegram notification failed";
|
|
689
711
|
var REDACTED = "<redacted>";
|
|
@@ -720,6 +742,9 @@ function load_config() {
|
|
|
720
742
|
}
|
|
721
743
|
return { bot_token: result.data.telegram_bot_token, chat_id: result.data.telegram_chat_id };
|
|
722
744
|
}
|
|
745
|
+
function is_notify_disabled() {
|
|
746
|
+
return parse_environment_string(process.env[NOTIFY_SWITCH_KEY]).toLowerCase() === NOTIFY_OFF_VALUE;
|
|
747
|
+
}
|
|
723
748
|
function build_header(task_type, repo_name) {
|
|
724
749
|
const { icon, label: label2 } = TASK_DEFINITIONS[task_type];
|
|
725
750
|
if (repo_name === void 0 || repo_name.length === 0) return `${icon} ${label2}`;
|
|
@@ -767,6 +792,12 @@ function build_send_failure(error, config) {
|
|
|
767
792
|
return new Error(`${SEND_FAILED_PREFIX}: ${reason}`, { cause: new Error(reason) });
|
|
768
793
|
}
|
|
769
794
|
async function send(input) {
|
|
795
|
+
if (is_notify_disabled()) {
|
|
796
|
+
console.info(
|
|
797
|
+
`\u{1F515} Telegram notifications are disabled (${NOTIFY_SWITCH_KEY}=${NOTIFY_OFF_VALUE}).`
|
|
798
|
+
);
|
|
799
|
+
return;
|
|
800
|
+
}
|
|
770
801
|
const config = load_config();
|
|
771
802
|
const text2 = build_text(input);
|
|
772
803
|
try {
|
|
@@ -1038,8 +1069,48 @@ async function run_stall_check(ready = backlog_ready.DEFAULT_PORTS) {
|
|
|
1038
1069
|
}
|
|
1039
1070
|
var backlog_stalled_detect = { DEFAULT_PORTS: DEFAULT_PORTS2, detect_and_report, gather, report, run_stall_check };
|
|
1040
1071
|
|
|
1041
|
-
// scripts/rules/
|
|
1072
|
+
// scripts/rules/last-prompt.ts
|
|
1042
1073
|
import { z as z3 } from "zod";
|
|
1074
|
+
var WORKFLOW_KEYWORDS = /* @__PURE__ */ new Set([
|
|
1075
|
+
"kickoff",
|
|
1076
|
+
"fullrun",
|
|
1077
|
+
"halfrun",
|
|
1078
|
+
"backlogrun"
|
|
1079
|
+
]);
|
|
1080
|
+
var NO_PROMPT = "";
|
|
1081
|
+
var HUMAN_ORIGIN = "human";
|
|
1082
|
+
var KEYWORD_BEFORE_ARGUMENT = -2;
|
|
1083
|
+
var PROMPT_LINE_SCHEMA = z3.object({
|
|
1084
|
+
isMeta: z3.boolean().nullish(),
|
|
1085
|
+
origin: z3.object({ kind: z3.string().nullish() }).nullish(),
|
|
1086
|
+
message: z3.object({ content: z3.unknown() })
|
|
1087
|
+
});
|
|
1088
|
+
function is_person(line) {
|
|
1089
|
+
if (line.isMeta === true) return false;
|
|
1090
|
+
return line.origin === null || line.origin === void 0 || line.origin.kind === HUMAN_ORIGIN;
|
|
1091
|
+
}
|
|
1092
|
+
function person_text(line) {
|
|
1093
|
+
const parsed = PROMPT_LINE_SCHEMA.safeParse(json_value.parse_or_undefined(line));
|
|
1094
|
+
if (!parsed.success || !is_person(parsed.data)) return void 0;
|
|
1095
|
+
return time_reported_failure.result_text(parsed.data.message.content);
|
|
1096
|
+
}
|
|
1097
|
+
function is_invocation(prompt) {
|
|
1098
|
+
const words = prompt.trim().split(/\s+/u);
|
|
1099
|
+
return [words.at(0), words.at(KEYWORD_BEFORE_ARGUMENT)].some(
|
|
1100
|
+
(word) => WORKFLOW_KEYWORDS.has(word ?? NO_PROMPT)
|
|
1101
|
+
);
|
|
1102
|
+
}
|
|
1103
|
+
function prompt_line_text(line) {
|
|
1104
|
+
return filing_cap.is_prompt_line(line) ? person_text(line) : void 0;
|
|
1105
|
+
}
|
|
1106
|
+
function prompt_text(tail) {
|
|
1107
|
+
const text2 = tail.split("\n").map((line) => prompt_line_text(line)).findLast((one) => one !== void 0);
|
|
1108
|
+
return text2 === void 0 || is_invocation(text2) ? NO_PROMPT : text2;
|
|
1109
|
+
}
|
|
1110
|
+
var last_prompt = { prompt_text };
|
|
1111
|
+
|
|
1112
|
+
// scripts/rules/stop-rules.ts
|
|
1113
|
+
import { z as z4 } from "zod";
|
|
1043
1114
|
|
|
1044
1115
|
// scripts/rules/filing-offer.ts
|
|
1045
1116
|
var OFFER_PATTERNS = [
|
|
@@ -1147,10 +1218,10 @@ var reply_language = { MIN_PROSE_LETTERS, is_mismatch, script_of };
|
|
|
1147
1218
|
// scripts/rules/stop-rules.ts
|
|
1148
1219
|
var SWITCH_ENV_KEY = "JOSH_STOP_GUARD";
|
|
1149
1220
|
var BLOCK_DECISION = "block";
|
|
1150
|
-
var stop_payload_schema =
|
|
1151
|
-
transcript_path:
|
|
1152
|
-
stop_hook_active:
|
|
1153
|
-
last_assistant_message:
|
|
1221
|
+
var stop_payload_schema = z4.object({
|
|
1222
|
+
transcript_path: z4.string().min(1),
|
|
1223
|
+
stop_hook_active: z4.boolean().nullish(),
|
|
1224
|
+
last_assistant_message: z4.string().nullish()
|
|
1154
1225
|
});
|
|
1155
1226
|
var NO_OUTCOME = { reason: void 0 };
|
|
1156
1227
|
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.';
|
|
@@ -1161,7 +1232,7 @@ function build_citation_reason(references) {
|
|
|
1161
1232
|
const command = `pnpm josh issue:cite ${issue_citation.cite_arguments(references).join(" ")}`;
|
|
1162
1233
|
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
1234
|
}
|
|
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:
|
|
1235
|
+
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
1236
|
var HEADLESS_WAIT_MARKER = "\u26D4 headless parent:";
|
|
1166
1237
|
var HEADLESS_REFUSAL_CAP = 3;
|
|
1167
1238
|
var HEADLESS_WAIT_CALLS = ['"command":"pnpm josh lane:await', '"command":"pnpm josh run:progress'];
|
|
@@ -1199,14 +1270,14 @@ function needs_notify(context) {
|
|
|
1199
1270
|
function needs_release(context) {
|
|
1200
1271
|
return is_held_idle(context) && context.tree_clean;
|
|
1201
1272
|
}
|
|
1202
|
-
function citation_reason(
|
|
1203
|
-
const references = issue_citation.
|
|
1273
|
+
function citation_reason(context) {
|
|
1274
|
+
const references = issue_citation.unquoted_references(context.message, context.prompt);
|
|
1204
1275
|
if (references.length === 0) return void 0;
|
|
1205
1276
|
return build_citation_reason(references);
|
|
1206
1277
|
}
|
|
1207
1278
|
function reply_reason(context) {
|
|
1208
1279
|
if (needs_filing(context)) return FILING_OFFER_REASON;
|
|
1209
|
-
return citation_reason(context
|
|
1280
|
+
return citation_reason(context) ?? language_reason(context);
|
|
1210
1281
|
}
|
|
1211
1282
|
function is_headless_held(context) {
|
|
1212
1283
|
if (!context.headless_waiting) return false;
|
|
@@ -1302,7 +1373,7 @@ var run_stranded = {
|
|
|
1302
1373
|
};
|
|
1303
1374
|
|
|
1304
1375
|
// scripts/run/run-wake.ts
|
|
1305
|
-
import { z as
|
|
1376
|
+
import { z as z5 } from "zod";
|
|
1306
1377
|
var WAKE_PREFIX = "josh-run-wake-";
|
|
1307
1378
|
var WAKE_LOG_PREFIX = "josh-run-wake-log-";
|
|
1308
1379
|
var WAKE_LOG_SUFFIX = ".log";
|
|
@@ -1322,21 +1393,21 @@ var STOP_REASONS = {
|
|
|
1322
1393
|
expired: "expired",
|
|
1323
1394
|
unreadable: "unreadable"
|
|
1324
1395
|
};
|
|
1325
|
-
var run_wake_schema =
|
|
1326
|
-
invocation:
|
|
1327
|
-
started_at:
|
|
1328
|
-
pid:
|
|
1329
|
-
process_start:
|
|
1330
|
-
woke:
|
|
1331
|
-
woke_at:
|
|
1396
|
+
var run_wake_schema = z5.object({
|
|
1397
|
+
invocation: z5.string(),
|
|
1398
|
+
started_at: z5.string(),
|
|
1399
|
+
pid: z5.number(),
|
|
1400
|
+
process_start: z5.string().optional(),
|
|
1401
|
+
woke: z5.number(),
|
|
1402
|
+
woke_at: z5.string().optional(),
|
|
1332
1403
|
// **Every optional field of `RunWake` has to be listed here.** `z.object` strips what it does not
|
|
1333
1404
|
// declare, so a field added to the interface alone round-trips through disk as `undefined` — which
|
|
1334
1405
|
// reads as "no attempt has been made yet" and would restart the retry count on every pass.
|
|
1335
|
-
attempts:
|
|
1336
|
-
woke_pid:
|
|
1337
|
-
held_at:
|
|
1338
|
-
spawned:
|
|
1339
|
-
idle_since:
|
|
1406
|
+
attempts: z5.number().optional(),
|
|
1407
|
+
woke_pid: z5.number().optional(),
|
|
1408
|
+
held_at: z5.string().optional(),
|
|
1409
|
+
spawned: z5.array(z5.string()).optional(),
|
|
1410
|
+
idle_since: z5.string().optional(),
|
|
1340
1411
|
profile: agent_role_profile.PROFILE_SCHEMA.optional()
|
|
1341
1412
|
});
|
|
1342
1413
|
function is_overdue(marked_at, now, limit_ms = WAKE_GRACE_MS) {
|
|
@@ -1585,6 +1656,7 @@ async function build_context(transcript_path, payload_tail) {
|
|
|
1585
1656
|
tree_clean: !await run_hold.is_tree_dirty(),
|
|
1586
1657
|
notified: lane_park.mentions_confirmation_notify(tail),
|
|
1587
1658
|
message: payload_tail.message,
|
|
1659
|
+
prompt: last_prompt.prompt_text(tail),
|
|
1588
1660
|
stop_hook_active: payload_tail.stop_hook_active,
|
|
1589
1661
|
cut_pending: run_cut.carried_cut_sync() !== void 0,
|
|
1590
1662
|
filed: was_filed(tail),
|
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
|
|
|
@@ -859,7 +869,7 @@ var DEV_COMMANDS = {
|
|
|
859
869
|
},
|
|
860
870
|
lint: {
|
|
861
871
|
script: "scripts/lint/lint-parallel.ts",
|
|
862
|
-
description: "Check code with prettier and eslint (skips a tool a
|
|
872
|
+
description: "Check code with prettier and eslint (skips a tool a basic project lacks)",
|
|
863
873
|
category: "Development",
|
|
864
874
|
reference: ["", "developer", ["processes"]]
|
|
865
875
|
},
|
|
@@ -895,7 +905,7 @@ var DEV_COMMANDS = {
|
|
|
895
905
|
},
|
|
896
906
|
format: {
|
|
897
907
|
script: "scripts/lint/format.ts",
|
|
898
|
-
description: "Format code with prettier and eslint (skips a tool a
|
|
908
|
+
description: "Format code with prettier and eslint (skips a tool a basic project lacks)",
|
|
899
909
|
category: "Development",
|
|
900
910
|
reference: ["", "developer", ["files", "processes"]]
|
|
901
911
|
},
|
|
@@ -1008,7 +1018,7 @@ var DEV_COMMANDS = {
|
|
|
1008
1018
|
},
|
|
1009
1019
|
check: {
|
|
1010
1020
|
script: "scripts/gate/type-check-command.ts",
|
|
1011
|
-
description: "Type-check with tsc (skips a
|
|
1021
|
+
description: "Type-check with tsc (skips a basic project with no TypeScript to check)",
|
|
1012
1022
|
category: "Development",
|
|
1013
1023
|
reference: ["[arguments...]", "developer", ["processes"]]
|
|
1014
1024
|
},
|
|
@@ -1163,7 +1173,7 @@ var MAINTENANCE_COMMANDS = {
|
|
|
1163
1173
|
};
|
|
1164
1174
|
|
|
1165
1175
|
// scripts/josh/josh-commands-project.ts
|
|
1166
|
-
var PROFILE_ARGUMENTS = "[--profile
|
|
1176
|
+
var PROFILE_ARGUMENTS = "[--profile basic|full]";
|
|
1167
1177
|
var PROJECT_COMMANDS = {
|
|
1168
1178
|
profile: {
|
|
1169
1179
|
script: "scripts/init/project-profile-cli.ts",
|
|
@@ -1173,7 +1183,7 @@ var PROJECT_COMMANDS = {
|
|
|
1173
1183
|
},
|
|
1174
1184
|
start: {
|
|
1175
1185
|
script: "scripts/init/start.ts",
|
|
1176
|
-
description: "
|
|
1186
|
+
description: "Set a project up for the GitHub Issue workflow, from git init to the setup PR",
|
|
1177
1187
|
category: "Project",
|
|
1178
1188
|
reference: [
|
|
1179
1189
|
`${PROFILE_ARGUMENTS} [--yes] [--github] [--public]`,
|
|
@@ -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.998.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": [
|
|
@@ -97,6 +97,10 @@
|
|
|
97
97
|
"types": "./prettier/index.d.ts",
|
|
98
98
|
"default": "./prettier/index.js"
|
|
99
99
|
},
|
|
100
|
+
"./prettier/basic": {
|
|
101
|
+
"types": "./prettier/basic.d.ts",
|
|
102
|
+
"default": "./prettier/basic.js"
|
|
103
|
+
},
|
|
100
104
|
"./prettier/static": {
|
|
101
105
|
"types": "./prettier/static.d.ts",
|
|
102
106
|
"default": "./prettier/static.js"
|
package/prettier/index.js
CHANGED
package/prettier/static.js
CHANGED
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
trailingComma: 'all',
|
|
5
|
-
printWidth: 100,
|
|
6
|
-
semi: false,
|
|
7
|
-
arrowParens: 'always',
|
|
8
|
-
bracketSpacing: true,
|
|
9
|
-
endOfLine: 'lf',
|
|
10
|
-
}
|
|
1
|
+
// The basic profile's preset under the name it had before joshuafolkken/kit#2829. A project
|
|
2
|
+
// initialized earlier imports this path from its `prettier.config.mjs`, so it stays exported.
|
|
3
|
+
export { config } from './basic.js'
|
|
@@ -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
|
|