@joshuafolkken/kit 1.1471.0 → 1.1514.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 +6 -6
- package/.claude/skills/epic-commands/SKILL.md +2 -14
- package/.claude/skills/epic-commands/epic-bundle.md +9 -5
- package/.claude/skills/epic-commands/execution-waves.md +1 -2
- package/.claude/skills/verify-ui/SKILL.md +1 -2
- package/.claude/skills/workflow-commands/SKILL.md +7 -9
- package/.claude/skills/workflow-commands/background-commands.md +3 -7
- package/.claude/skills/workflow-commands/backlogrun-child.md +3 -10
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +6 -15
- package/.claude/skills/workflow-commands/backlogrun-park.md +2 -8
- package/.claude/skills/workflow-commands/backlogrun-progress.md +10 -19
- package/.claude/skills/workflow-commands/backlogrun-recovery.md +8 -8
- package/.claude/skills/workflow-commands/backlogrun-steps.md +2 -10
- package/.claude/skills/workflow-commands/backlogrun.md +31 -50
- package/.claude/skills/workflow-commands/chain-rule.md +7 -6
- package/.claude/skills/workflow-commands/delegation.md +12 -8
- package/.claude/skills/workflow-commands/entry-sequence.md +1 -3
- package/.claude/skills/workflow-commands/followup.md +3 -6
- package/.claude/skills/workflow-commands/fullrun-steps.md +3 -5
- package/.claude/skills/workflow-commands/fullrun.md +4 -6
- package/.claude/skills/workflow-commands/halfrun.md +3 -7
- package/.claude/skills/workflow-commands/into-target.md +1 -2
- package/.claude/skills/workflow-commands/issue-comments.md +3 -3
- package/.claude/skills/workflow-commands/issue-scout.md +3 -2
- package/.claude/skills/workflow-commands/latest-gate.md +2 -6
- package/.claude/skills/workflow-commands/needs-human-review.md +2 -5
- package/.claude/skills/workflow-commands/observation-filing.md +0 -14
- package/.claude/skills/workflow-commands/observation-ledger.md +4 -9
- package/.claude/skills/workflow-commands/pre-gate-cut.md +11 -16
- package/.claude/skills/workflow-commands/prerequisite.md +1 -2
- package/.claude/skills/workflow-commands/progress-watcher.md +2 -7
- package/.claude/skills/workflow-commands/prrun.md +3 -5
- package/.claude/skills/workflow-commands/retrospective.md +4 -4
- package/.claude/skills/workflow-commands/split-assessment.md +1 -3
- package/.claude/skills/workflow-commands/target-repository.md +1 -2
- package/.claude/skills/workflow-commands/working-tree-hold.md +2 -4
- package/.codex/hooks.json +6 -6
- package/.github/actions/setup-node/action.yml +1 -1
- package/.github/workflows/ci.yml +1 -1
- package/.github/workflows/publish.yml +2 -2
- package/CLAUDE.md +1 -1
- package/cspell/index.yaml +7 -0
- package/dist/CLAUDE.md +1 -1
- package/dist/commands/document-section-cli.js +67 -34
- package/dist/hooks/batch-guard.js +6 -6
- package/dist/hooks/chunk-4KKD2UTK.js +66 -0
- package/dist/hooks/{chunk-J47HU5H5.js → chunk-6TS2JD6D.js} +3 -3
- package/dist/hooks/chunk-7DSBJVFH.js +50 -0
- package/dist/hooks/{chunk-YHBZAJSV.js → chunk-A65Y4YOR.js} +3 -3
- package/dist/hooks/{chunk-E7OIKX5Z.js → chunk-APUO6U4J.js} +85 -7
- package/dist/hooks/{chunk-IX6TTTI6.js → chunk-EFXE6C37.js} +8 -22
- package/dist/hooks/chunk-GP4IEC4O.js +20 -0
- package/dist/hooks/{chunk-SHGPANFB.js → chunk-JP45SOCJ.js} +3 -3
- package/dist/hooks/{chunk-K4EOONYM.js → chunk-LAOV7NLM.js} +1 -1
- package/dist/hooks/chunk-M4HGZV7U.js +83 -0
- package/dist/hooks/{chunk-KC5AK2GF.js → chunk-O6GDRNJB.js} +3 -3
- package/dist/hooks/{chunk-YYPI7SJZ.js → chunk-PF2NZL2A.js} +5 -5
- package/dist/hooks/{chunk-H5HVWYXK.js → chunk-PTICX4OL.js} +3 -4
- package/dist/hooks/{chunk-IIGFYXKC.js → chunk-RT27QRJW.js} +581 -1438
- package/dist/hooks/{chunk-43ZHT22P.js → chunk-SYOTDYCI.js} +1127 -1089
- package/dist/hooks/{chunk-AS74OU3D.js → chunk-TNUMY6NL.js} +1507 -1336
- package/dist/hooks/chunk-UPUZF3AN.js +279 -0
- package/dist/hooks/{chunk-EUMACUK2.js → chunk-WK6SMBIC.js} +1948 -806
- package/dist/hooks/codex-hook-adapter.js +17 -14
- package/dist/hooks/duplicate-read-guard.js +7 -7
- package/dist/hooks/format-edited.js +5 -4
- package/dist/hooks/inputs.json +317 -264
- package/dist/hooks/investigation-guard.js +8 -11
- package/dist/hooks/pretool-guard.js +16 -13
- package/dist/hooks/session-lang.js +370 -25
- package/dist/hooks/stop-guard.js +2576 -176
- package/dist/josh.js +2124 -277
- package/lefthook/base.yml +5 -3
- package/package.json +12 -10
- package/prompts/collaboration-workflow/file-edits.md +1 -3
- package/prompts/collaboration-workflow/gh-rest.md +1 -2
- package/prompts/collaboration-workflow/issue-citation.md +2 -4
- package/prompts/collaboration-workflow/issue-template.md +10 -2
- package/prompts/collaboration-workflow/lane-instructions.md +35 -0
- package/prompts/collaboration-workflow/operating-rules.md +2 -6
- package/prompts/collaboration-workflow/output-bounds.md +3 -3
- package/prompts/collaboration-workflow/overview.md +1 -1
- package/prompts/collaboration-workflow/principles.md +14 -8
- package/prompts/collaboration-workflow/report-format.md +9 -0
- package/prompts/collaboration-workflow/residency.md +12 -8
- package/prompts/collaboration-workflow/rule-delivery.md +3 -11
- package/prompts/collaboration-workflow/shell-body.md +6 -6
- package/prompts/collaboration-workflow/turn-batching.md +5 -5
- package/prompts/collaboration-workflow/upstream-interrupt.md +2 -2
- package/prompts/collaboration-workflow/wip-cap.md +6 -6
- package/prompts/collaboration-workflow.md +1 -0
- package/prompts/review.md +4 -5
- package/prompts/testing-guide.md +2 -2
- package/scripts/agent/agent-argv.ts +20 -4
- package/scripts/agent/agent-role-profile.ts +101 -45
- package/scripts/agent/agent-safe-text.ts +60 -0
- package/scripts/agent/claude-agent-argv.ts +14 -0
- package/scripts/agent/codex-agent-argv.ts +2 -0
- package/scripts/agent/lane-instructions.ts +144 -0
- package/scripts/backlog/backlog-budget.ts +4 -4
- package/scripts/backlog/backlog-drive-named.ts +1 -1
- package/scripts/backlog/backlog-drive-restore.ts +9 -1
- package/scripts/backlog/backlog-occupied.ts +56 -0
- package/scripts/backlog/backlog-ready.ts +47 -10
- package/scripts/delegation/duplicate-read-guard.ts +2 -2
- package/scripts/delegation/investigation-guard.ts +15 -65
- package/scripts/delegation/investigation-reads.ts +0 -1
- package/scripts/document/document-byte-budget.ts +6 -5
- package/scripts/document/document-section-cli.ts +17 -5
- package/scripts/document/entry-read-budget.ts +2 -2
- package/scripts/document/read-set-cli.ts +4 -1
- package/scripts/epic/epic-audit-orphans.ts +5 -8
- package/scripts/epic/epic-audit.ts +52 -1
- package/scripts/epic/epic-bundle-evidence.ts +49 -26
- package/scripts/epic/epic-bundle-referenced.ts +14 -3
- package/scripts/epic/epic-bundle.ts +17 -9
- package/scripts/followup/git-followup-workflow.ts +19 -1
- package/scripts/gate/check-inputs.ts +129 -0
- package/scripts/gate/check-reuse.ts +162 -0
- package/scripts/gate/core-budget.ts +93 -44
- package/scripts/gate/core-wait.ts +130 -0
- package/scripts/gate/free-cores.ts +49 -0
- package/scripts/gate/gate-ledger.ts +17 -3
- package/scripts/gate/gate-plan.ts +23 -1
- package/scripts/gate/gate-report.ts +15 -2
- package/scripts/gate/gate-run-steps.ts +150 -0
- package/scripts/gate/held-mark.ts +55 -0
- package/scripts/gate/machine-capacity.ts +70 -11
- package/scripts/gate/pre-commit-type-check.ts +14 -1
- package/scripts/gate/verification-gate.ts +58 -125
- package/scripts/gh/git-gh-issue-rest.ts +1 -0
- package/scripts/gh/git-gh-issue-write.ts +24 -2
- package/scripts/gh/git-pr.ts +13 -1
- package/scripts/git/main-merge-regenerate.ts +78 -0
- package/scripts/git/main-merge.ts +14 -5
- package/scripts/hooks/batch-guard.ts +5 -8
- package/scripts/hooks/pre-commit-lint.ts +91 -0
- package/scripts/hooks/pre-push-unit.ts +1 -1
- package/scripts/hooks/pretool-guard.ts +27 -52
- package/scripts/hooks/reserved-run.ts +1 -0
- package/scripts/hooks/run-hook.sh +10 -12
- package/scripts/hooks/stop-actions.ts +204 -0
- package/scripts/hooks/stop-guard.ts +62 -21
- package/scripts/init/hook-launch.ts +12 -7
- package/scripts/issue/expected-effect-lint.ts +59 -0
- package/scripts/issue/issue-cite-cli.ts +35 -15
- package/scripts/issue/issue-classification.ts +1 -1
- package/scripts/issue/issue-lint-cli.ts +5 -3
- package/scripts/issue/issue-scout-cli.ts +19 -14
- package/scripts/issue/markdown-section.ts +19 -5
- package/scripts/josh/command-usage.ts +110 -0
- package/scripts/josh/josh-command-map.ts +2 -0
- package/scripts/josh/josh-command-types.ts +55 -9
- package/scripts/josh/josh-commands-ai.ts +13 -0
- package/scripts/josh/josh-commands-development.ts +1 -1
- package/scripts/josh/josh-commands-hooks.ts +6 -0
- package/scripts/josh/josh-commands-lane.ts +10 -1
- package/scripts/josh/josh-commands-workflow.ts +5 -0
- package/scripts/josh/josh-logic.ts +6 -15
- package/scripts/josh/josh-usage-automation.ts +121 -0
- package/scripts/josh/josh-usage-backlog.ts +180 -0
- package/scripts/josh/josh-usage-developer.ts +230 -0
- package/scripts/josh/josh-usage-hooks.ts +38 -0
- package/scripts/josh/josh-usage-issue.ts +205 -0
- package/scripts/josh/josh-usage-review.ts +101 -0
- package/scripts/josh/josh-usage-run.ts +252 -0
- package/scripts/josh/josh-usage-session.ts +238 -0
- package/scripts/josh/josh-usage-workflow.ts +212 -0
- package/scripts/josh/josh.ts +14 -5
- package/scripts/josh/package-directory.ts +20 -0
- package/scripts/lane/lane-capacity.ts +8 -2
- package/scripts/lane/lane-check-stats.ts +56 -0
- package/scripts/lane/lane-child-invocation.ts +35 -4
- package/scripts/lane/lane-dispatch.ts +3 -3
- package/scripts/lane/lane-guard-policy.ts +2 -2
- package/scripts/lane/lane-handoff.ts +8 -1
- package/scripts/lane/lane-install.ts +12 -4
- package/scripts/lane/lane-ledger.ts +43 -1
- package/scripts/lane/lane-limit-cli.ts +8 -9
- package/scripts/lane/lane-measure-cli.ts +2 -0
- package/scripts/lane/lane-preserve.ts +29 -1
- package/scripts/lane/lane-registry.ts +9 -7
- package/scripts/lane/lane-restart.ts +5 -26
- package/scripts/lane/lane-session-action.ts +146 -0
- package/scripts/lane/lane-session-broker.ts +57 -138
- package/scripts/lane/lane-withdraw-cli.ts +71 -0
- package/scripts/lane/lane-withdraw.ts +182 -0
- package/scripts/lint/format.ts +4 -4
- package/scripts/lint/lint-parallel.ts +10 -3
- package/scripts/lint/lint-related-scope.ts +4 -1
- package/scripts/notify/telegram-test.ts +10 -5
- package/scripts/report/report-format-reference.ts +2 -0
- package/scripts/review/acceptance-map-check.ts +61 -0
- package/scripts/review/acceptance-map.ts +205 -0
- package/scripts/review/review-brief-cli.ts +1 -1
- package/scripts/rules/agent-model.ts +59 -0
- package/scripts/rules/delivered-rules.ts +11 -2
- package/scripts/rules/filing-cap.ts +1 -0
- package/scripts/rules/firing-point.ts +6 -5
- package/scripts/rules/guard-remedy.ts +117 -0
- package/scripts/rules/issue-comments.ts +67 -6
- package/scripts/rules/last-prompt.ts +50 -5
- package/scripts/rules/oracle-list-cli.ts +7 -0
- package/scripts/rules/piped-verification.ts +3 -1
- package/scripts/rules/rule-list.ts +4 -1
- package/scripts/rules/rule-registry-rows.ts +10 -0
- package/scripts/rules/rule-registry.ts +7 -4
- package/scripts/rules/rule-rewrite.ts +114 -0
- package/scripts/rules/rule-value.ts +7 -1
- package/scripts/rules/shell-segments.ts +15 -0
- package/scripts/rules/stop-decision.ts +77 -0
- package/scripts/rules/stop-rules.ts +147 -47
- package/scripts/rules/tail-commands.ts +15 -1
- package/scripts/run/board/run-board-cli.ts +2 -0
- package/scripts/run/board/run-board-closed.ts +8 -2
- package/scripts/run/board/run-board-github.ts +9 -1
- package/scripts/run/board/run-board-header.ts +4 -1
- package/scripts/run/board/run-board-labels.ts +2 -0
- package/scripts/run/board/run-board-layout.ts +1 -1
- package/scripts/run/board/run-board-read.ts +16 -0
- package/scripts/run/board/run-board-reason.ts +10 -1
- package/scripts/run/board/run-board-render-legend.ts +1 -0
- package/scripts/run/board/run-board-render-slot.ts +1 -1
- package/scripts/run/board/run-board-render-waits.ts +41 -0
- package/scripts/run/board/run-board-render.ts +6 -1
- package/scripts/run/board/run-board-row-yield.ts +1 -0
- package/scripts/run/board/run-board-state.ts +5 -0
- package/scripts/run/board/run-board-status.ts +72 -21
- package/scripts/run/board/run-board-tick.ts +5 -1
- package/scripts/run/cut/run-cut-cli.ts +3 -2
- package/scripts/run/cut/run-cut-report.ts +16 -0
- package/scripts/run/detached-launch.ts +23 -4
- package/scripts/run/entry/run-entry-cli.ts +8 -1
- package/scripts/run/event/run-event-render.ts +1 -0
- package/scripts/run/event/run-event-scope.ts +19 -1
- package/scripts/run/event/run-event-stream-emit.ts +13 -6
- package/scripts/run/event/run-event-stream.ts +4 -0
- package/scripts/run/hold/run-hold-session.ts +46 -0
- package/scripts/run/hold/run-hold.ts +7 -1
- package/scripts/run/launch-priority.ts +32 -0
- package/scripts/run/merge/run-merge-cli.ts +16 -65
- package/scripts/run/merge/run-merge-signals.ts +99 -0
- package/scripts/run/merge/run-merge-steps.ts +11 -1
- package/scripts/run/merge/run-merge.ts +21 -9
- package/scripts/run/run-liveness.ts +1 -1
- package/scripts/run/run-poll-hook.ts +157 -0
- package/scripts/run/run-step-cli.ts +22 -15
- package/scripts/run/run-step-section.ts +85 -0
- package/scripts/run/ship/run-ship-cli.ts +5 -12
- package/scripts/run/ship/run-ship-detach.ts +9 -0
- package/scripts/run/ship/run-ship-next.ts +10 -2
- package/scripts/run/ship/run-ship-overlap.ts +195 -0
- package/scripts/run/ship/run-ship-pre-detach.ts +33 -15
- package/scripts/run/ship/run-ship-preflight.ts +28 -2
- package/scripts/run/ship/run-ship-return.ts +31 -7
- package/scripts/run/ship/run-ship-review-steps.ts +12 -10
- package/scripts/run/ship/run-ship-steps.ts +1 -1
- package/scripts/run/ship/run-ship-stop-context.ts +206 -0
- package/scripts/run/ship/run-ship-sync.ts +14 -6
- package/scripts/test/test-e2e-guard.ts +30 -5
- package/scripts/test/test-unit-guard.ts +16 -1
- package/scripts/test/unit-worker-share.ts +26 -4
- package/scripts/time-runtime/time-shell.ts +29 -4
- package/scripts/time-runtime/time-spans.ts +1 -0
- package/scripts/time-runtime/time-tool-call.ts +7 -0
- package/templates/gitignore +6 -2
- package/dist/hooks/chunk-K4LMBQC2.js +0 -68
package/dist/josh.js
CHANGED
|
@@ -131,20 +131,20 @@ var ABSENT_CODE = "ENOENT";
|
|
|
131
131
|
function is_absent(error) {
|
|
132
132
|
return error instanceof Error && "code" in error && error.code === ABSENT_CODE;
|
|
133
133
|
}
|
|
134
|
-
function read_optional(
|
|
134
|
+
function read_optional(path16) {
|
|
135
135
|
try {
|
|
136
|
-
return readFileSync(
|
|
136
|
+
return readFileSync(path16, "utf8");
|
|
137
137
|
} catch (error) {
|
|
138
138
|
if (is_absent(error)) return void 0;
|
|
139
139
|
throw error;
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
|
-
function read_file_or_empty(
|
|
143
|
-
return read_optional(
|
|
142
|
+
function read_file_or_empty(path16) {
|
|
143
|
+
return read_optional(path16) ?? "";
|
|
144
144
|
}
|
|
145
|
-
function read_if_readable(
|
|
145
|
+
function read_if_readable(path16) {
|
|
146
146
|
try {
|
|
147
|
-
return readFileSync(
|
|
147
|
+
return readFileSync(path16, "utf8");
|
|
148
148
|
} catch {
|
|
149
149
|
return void 0;
|
|
150
150
|
}
|
|
@@ -267,93 +267,6 @@ var doctor_consumer = {
|
|
|
267
267
|
secretlint_line
|
|
268
268
|
};
|
|
269
269
|
|
|
270
|
-
// scripts/josh/josh-logic.ts
|
|
271
|
-
import { existsSync as existsSync4, readFileSync as readFileSync5 } from "node:fs";
|
|
272
|
-
import path11 from "node:path";
|
|
273
|
-
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
274
|
-
|
|
275
|
-
// scripts/build/local-bin.ts
|
|
276
|
-
import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
|
|
277
|
-
import { createRequire } from "node:module";
|
|
278
|
-
import path3 from "node:path";
|
|
279
|
-
|
|
280
|
-
// scripts/lib/ancestor-directories.ts
|
|
281
|
-
import path2 from "node:path";
|
|
282
|
-
var MAX_DEPTH = 64;
|
|
283
|
-
function list(start_directory) {
|
|
284
|
-
const directories = [];
|
|
285
|
-
let current = path2.resolve(start_directory);
|
|
286
|
-
while (directories.length < MAX_DEPTH && !directories.includes(current)) {
|
|
287
|
-
directories.push(current);
|
|
288
|
-
current = path2.dirname(current);
|
|
289
|
-
}
|
|
290
|
-
return directories;
|
|
291
|
-
}
|
|
292
|
-
function nearest(start_directory, is_match) {
|
|
293
|
-
return list(start_directory).find((directory) => is_match(directory));
|
|
294
|
-
}
|
|
295
|
-
var ancestor_directories = { list, nearest };
|
|
296
|
-
|
|
297
|
-
// scripts/lib/schemas.ts
|
|
298
|
-
import { z as z2 } from "zod";
|
|
299
|
-
var overrides_snapshot_schema = z2.record(z2.string(), z2.string());
|
|
300
|
-
var package_version_schema = z2.object({ version: z2.string() });
|
|
301
|
-
var package_named_version_schema = z2.looseObject({ name: z2.string(), version: z2.string() });
|
|
302
|
-
var package_with_version_schema = z2.looseObject({ version: z2.string() });
|
|
303
|
-
var ls_global_dependency_schema = z2.looseObject({ version: z2.string() });
|
|
304
|
-
var ls_global_dependencies_schema = z2.record(z2.string(), ls_global_dependency_schema).optional();
|
|
305
|
-
var pnpm_ls_global_schema = z2.array(
|
|
306
|
-
z2.looseObject({
|
|
307
|
-
dependencies: ls_global_dependencies_schema
|
|
308
|
-
})
|
|
309
|
-
);
|
|
310
|
-
var vscode_settings_schema = z2.record(z2.string(), z2.unknown());
|
|
311
|
-
var with_scripts_schema = z2.looseObject({
|
|
312
|
-
scripts: z2.record(z2.string(), z2.string()).optional()
|
|
313
|
-
});
|
|
314
|
-
var with_development_deps_schema = z2.looseObject({
|
|
315
|
-
devDependencies: z2.record(z2.string(), z2.string()).optional()
|
|
316
|
-
});
|
|
317
|
-
var with_package_manager_schema = z2.looseObject({
|
|
318
|
-
packageManager: z2.string().optional()
|
|
319
|
-
});
|
|
320
|
-
var with_development_engine_schema = z2.looseObject({
|
|
321
|
-
devEngines: z2.record(z2.string(), z2.unknown()).optional()
|
|
322
|
-
});
|
|
323
|
-
var bin_entry_schema = z2.union([z2.string(), z2.record(z2.string(), z2.string())]).optional();
|
|
324
|
-
var package_bin_schema = z2.looseObject({ bin: bin_entry_schema });
|
|
325
|
-
var json_object_schema = z2.record(z2.string(), z2.unknown());
|
|
326
|
-
var string_array_schema = z2.array(z2.string());
|
|
327
|
-
var string_record_schema = z2.record(z2.string(), z2.string());
|
|
328
|
-
|
|
329
|
-
// scripts/build/local-bin.ts
|
|
330
|
-
var NODE_MODULES2 = "node_modules";
|
|
331
|
-
var BIN_DIR = ".bin";
|
|
332
|
-
var WINDOWS_PLATFORM = "win32";
|
|
333
|
-
var WINDOWS_SHIM_SUFFIX = ".cmd";
|
|
334
|
-
var PACKAGE_JSON = "package.json";
|
|
335
|
-
function resolve_local_bin(project_root, bin_name) {
|
|
336
|
-
const shim = process.platform === WINDOWS_PLATFORM ? `${bin_name}${WINDOWS_SHIM_SUFFIX}` : bin_name;
|
|
337
|
-
return path3.join(project_root, NODE_MODULES2, BIN_DIR, shim);
|
|
338
|
-
}
|
|
339
|
-
function read_bin_entry(manifest_path, package_name, bin_name) {
|
|
340
|
-
const { bin } = package_bin_schema.parse(JSON.parse(readFileSync2(manifest_path, "utf8")));
|
|
341
|
-
if (typeof bin === "string") return bin_name === path3.basename(package_name) ? bin : void 0;
|
|
342
|
-
return bin?.[bin_name];
|
|
343
|
-
}
|
|
344
|
-
function resolve_package_bin(base_directory, package_name, bin_name) {
|
|
345
|
-
try {
|
|
346
|
-
const resolve_from = createRequire(path3.join(base_directory, PACKAGE_JSON));
|
|
347
|
-
const manifest_path = resolve_from.resolve(`${package_name}/${PACKAGE_JSON}`);
|
|
348
|
-
const bin_entry = read_bin_entry(manifest_path, package_name, bin_name);
|
|
349
|
-
if (bin_entry === void 0) return void 0;
|
|
350
|
-
const cli_entry = path3.join(path3.dirname(manifest_path), bin_entry);
|
|
351
|
-
return existsSync2(cli_entry) ? cli_entry : void 0;
|
|
352
|
-
} catch {
|
|
353
|
-
return void 0;
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
|
|
357
270
|
// scripts/gate/core-budget.ts
|
|
358
271
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
359
272
|
import { readdirSync as readdirSync2 } from "node:fs";
|
|
@@ -364,7 +277,7 @@ import path8 from "node:path";
|
|
|
364
277
|
import { accessSync, constants } from "node:fs";
|
|
365
278
|
import { tmpdir } from "node:os";
|
|
366
279
|
var POSIX_TEMP_ROOT = "/tmp";
|
|
367
|
-
var
|
|
280
|
+
var WINDOWS_PLATFORM = "win32";
|
|
368
281
|
function is_writable_directory(directory) {
|
|
369
282
|
try {
|
|
370
283
|
accessSync(directory, constants.W_OK);
|
|
@@ -374,7 +287,7 @@ function is_writable_directory(directory) {
|
|
|
374
287
|
}
|
|
375
288
|
}
|
|
376
289
|
function resolve_temporary_root(platform2, can_write = is_writable_directory) {
|
|
377
|
-
if (platform2 ===
|
|
290
|
+
if (platform2 === WINDOWS_PLATFORM) return tmpdir();
|
|
378
291
|
return can_write(POSIX_TEMP_ROOT) ? POSIX_TEMP_ROOT : tmpdir();
|
|
379
292
|
}
|
|
380
293
|
var TEMP_ROOT_KEY = "JOSH_TEMP_ROOT";
|
|
@@ -386,9 +299,9 @@ var PLATFORM_TEMP_ROOT = temporary_root(process.env[TEMP_ROOT_KEY], process.plat
|
|
|
386
299
|
// scripts/josh/process-identity.ts
|
|
387
300
|
import { execFileSync, spawnSync } from "node:child_process";
|
|
388
301
|
import { randomUUID } from "node:crypto";
|
|
389
|
-
import { readFileSync as
|
|
302
|
+
import { readFileSync as readFileSync2, rmSync } from "node:fs";
|
|
390
303
|
import { createServer } from "node:net";
|
|
391
|
-
import
|
|
304
|
+
import path2 from "node:path";
|
|
392
305
|
var PS_COMMAND = "/bin/ps";
|
|
393
306
|
var FORMAT_FLAG = "-o";
|
|
394
307
|
var START_TIME_FORMAT = "lstart=";
|
|
@@ -403,7 +316,7 @@ var BEACON_SUFFIX = ".sock";
|
|
|
403
316
|
var BEACON_PREFIX = `josh-process-identity-${String(process.getuid?.() ?? "")}-`;
|
|
404
317
|
var BEACON_ID_LENGTH = 36;
|
|
405
318
|
var BEACON_ID_PATTERN = /^[\da-f-]+$/u;
|
|
406
|
-
var
|
|
319
|
+
var WINDOWS_PLATFORM2 = "win32";
|
|
407
320
|
var BEACON_LIVE_STATUS = 0;
|
|
408
321
|
var BEACON_UNKNOWN_STATUS = 1;
|
|
409
322
|
var BEACON_GONE_STATUS = 2;
|
|
@@ -426,7 +339,7 @@ function is_present_pid(pid) {
|
|
|
426
339
|
}
|
|
427
340
|
function read_proc_start(pid) {
|
|
428
341
|
try {
|
|
429
|
-
const stat =
|
|
342
|
+
const stat = readFileSync2(`/proc/${String(pid)}/stat`, "utf8");
|
|
430
343
|
const fields = stat.slice(stat.lastIndexOf(")") + 1).trim().split(/\s+/u);
|
|
431
344
|
const start = fields[PROC_START_FIELD_INDEX];
|
|
432
345
|
return start === void 0 ? void 0 : `proc:${start}`;
|
|
@@ -491,7 +404,7 @@ function try_bind_beacon(bind, target) {
|
|
|
491
404
|
}
|
|
492
405
|
}
|
|
493
406
|
function open_beacon(bind = bind_beacon) {
|
|
494
|
-
const target =
|
|
407
|
+
const target = path2.join(PLATFORM_TEMP_ROOT, `${BEACON_PREFIX}${randomUUID()}${BEACON_SUFFIX}`);
|
|
495
408
|
const token = `${BEACON_SCHEME}${target}`;
|
|
496
409
|
const server = try_bind_beacon(bind, target);
|
|
497
410
|
if (server === void 0) return void 0;
|
|
@@ -502,7 +415,7 @@ function open_beacon(bind = bind_beacon) {
|
|
|
502
415
|
}
|
|
503
416
|
function resolve_own_start(probes = START_PROBES, platform2 = process.platform) {
|
|
504
417
|
const start = read_start(process.pid, probes);
|
|
505
|
-
if (start !== void 0 || platform2 ===
|
|
418
|
+
if (start !== void 0 || platform2 === WINDOWS_PLATFORM2) return start;
|
|
506
419
|
return open_beacon();
|
|
507
420
|
}
|
|
508
421
|
function is_valid_beacon_name(name) {
|
|
@@ -513,8 +426,8 @@ function is_valid_beacon_name(name) {
|
|
|
513
426
|
function beacon_target(token) {
|
|
514
427
|
if (!token.startsWith(BEACON_SCHEME)) return void 0;
|
|
515
428
|
const target = token.slice(BEACON_SCHEME.length);
|
|
516
|
-
if (
|
|
517
|
-
return is_valid_beacon_name(
|
|
429
|
+
if (path2.dirname(target) !== PLATFORM_TEMP_ROOT) return void 0;
|
|
430
|
+
return is_valid_beacon_name(path2.basename(target)) ? target : void 0;
|
|
518
431
|
}
|
|
519
432
|
function run_socket_probe(target) {
|
|
520
433
|
return spawnSync(process.execPath, ["-e", SOCKET_PROBE_SOURCE, target], {
|
|
@@ -573,18 +486,18 @@ var process_identity = {
|
|
|
573
486
|
};
|
|
574
487
|
|
|
575
488
|
// scripts/josh/process-owner.ts
|
|
576
|
-
import { z as
|
|
577
|
-
var process_owner_schema =
|
|
489
|
+
import { z as z2 } from "zod";
|
|
490
|
+
var process_owner_schema = z2.object({ pid: z2.number(), process_start: z2.string().optional() });
|
|
578
491
|
|
|
579
492
|
// scripts/josh/stamp-file.ts
|
|
580
493
|
import { createHash, randomUUID as randomUUID2 } from "node:crypto";
|
|
581
|
-
import { lstatSync, readFileSync as
|
|
582
|
-
import
|
|
494
|
+
import { lstatSync, readFileSync as readFileSync3, renameSync, rmSync as rmSync2, writeFileSync } from "node:fs";
|
|
495
|
+
import path4 from "node:path";
|
|
583
496
|
|
|
584
497
|
// scripts/init/init-paths.ts
|
|
585
|
-
import
|
|
498
|
+
import path3 from "node:path";
|
|
586
499
|
import { fileURLToPath } from "node:url";
|
|
587
|
-
var PACKAGE_DIR =
|
|
500
|
+
var PACKAGE_DIR = path3.join(path3.dirname(fileURLToPath(import.meta.url)), "..", "..");
|
|
588
501
|
var PROJECT_ROOT = process.cwd();
|
|
589
502
|
|
|
590
503
|
// scripts/josh/stamp-file.ts
|
|
@@ -604,7 +517,7 @@ function account_key() {
|
|
|
604
517
|
}
|
|
605
518
|
function stamp_path(prefix, root = PACKAGE_DIR, suffix = STAMP_SUFFIX) {
|
|
606
519
|
const key = digest(`${account_key()}${ACCOUNT_KEY_SEPARATOR}${root}`).slice(0, STAMP_KEY_LENGTH);
|
|
607
|
-
return
|
|
520
|
+
return path4.join(PLATFORM_TEMP_ROOT, `${prefix}${key}${suffix}`);
|
|
608
521
|
}
|
|
609
522
|
function write_exclusively(target, content) {
|
|
610
523
|
rmSync2(target, { force: true });
|
|
@@ -664,7 +577,7 @@ function remove_stamp(target) {
|
|
|
664
577
|
function read_stamp_text(source) {
|
|
665
578
|
try {
|
|
666
579
|
if (!is_own_regular_file(source)) return void 0;
|
|
667
|
-
return
|
|
580
|
+
return readFileSync3(source, "utf8");
|
|
668
581
|
} catch {
|
|
669
582
|
return void 0;
|
|
670
583
|
}
|
|
@@ -685,7 +598,7 @@ var stamp_file = {
|
|
|
685
598
|
// scripts/test/unit-worker-share.ts
|
|
686
599
|
import { readdirSync } from "node:fs";
|
|
687
600
|
import { availableParallelism } from "node:os";
|
|
688
|
-
import
|
|
601
|
+
import path5 from "node:path";
|
|
689
602
|
var RUN_PREFIX = "josh-unit-running-";
|
|
690
603
|
var WORKER_FLAG = "--maxWorkers";
|
|
691
604
|
var WORKER_FLAGS = [WORKER_FLAG, "--max-workers"];
|
|
@@ -724,7 +637,7 @@ function is_marker_live(source) {
|
|
|
724
637
|
return false;
|
|
725
638
|
}
|
|
726
639
|
function live_run_count(directory = PLATFORM_TEMP_ROOT) {
|
|
727
|
-
return marker_files(directory).filter((name) => is_marker_live(
|
|
640
|
+
return marker_files(directory).filter((name) => is_marker_live(path5.join(directory, name))).length;
|
|
728
641
|
}
|
|
729
642
|
var NESTED_KEY = "JOSH_UNIT_RUN_MARKED";
|
|
730
643
|
var NESTED_VALUE = "1";
|
|
@@ -735,17 +648,23 @@ function resolve_unit_workers(available_cores, runs) {
|
|
|
735
648
|
if (runs <= SOLO_RUNS) return void 0;
|
|
736
649
|
return Math.max(MIN_WORKERS, Math.floor(available_cores / runs));
|
|
737
650
|
}
|
|
738
|
-
function
|
|
651
|
+
function cap_to_free(workers, free_cores, available_cores) {
|
|
652
|
+
if (free_cores === void 0 || free_cores >= (workers ?? available_cores)) return workers;
|
|
653
|
+
return Math.max(MIN_WORKERS, Math.floor(free_cores));
|
|
654
|
+
}
|
|
655
|
+
function current_share(available_cores = availableParallelism(), live_runs = live_run_count(), free_cores) {
|
|
739
656
|
const own_run = is_nested_run() ? 0 : SOLO_RUNS;
|
|
740
|
-
|
|
657
|
+
const share = resolve_unit_workers(available_cores, live_runs + own_run);
|
|
658
|
+
return cap_to_free(share, free_cores, available_cores);
|
|
741
659
|
}
|
|
742
660
|
function is_worker_flag(argument) {
|
|
743
661
|
return WORKER_FLAGS.some((flag) => argument === flag || argument.startsWith(`${flag}=`));
|
|
744
662
|
}
|
|
663
|
+
function has_worker_flag(vitest_arguments) {
|
|
664
|
+
return vitest_arguments.some((argument) => is_worker_flag(argument));
|
|
665
|
+
}
|
|
745
666
|
function worker_arguments(vitest_arguments, share) {
|
|
746
|
-
if (share === void 0 || vitest_arguments
|
|
747
|
-
return [];
|
|
748
|
-
}
|
|
667
|
+
if (share === void 0 || has_worker_flag(vitest_arguments)) return [];
|
|
749
668
|
return [`${WORKER_FLAG}=${String(share)}`];
|
|
750
669
|
}
|
|
751
670
|
function mark_run_started(target) {
|
|
@@ -772,7 +691,9 @@ var unit_worker_share = {
|
|
|
772
691
|
NESTED_VALUE,
|
|
773
692
|
RUN_PREFIX,
|
|
774
693
|
SOLO_RUNS,
|
|
694
|
+
cap_to_free,
|
|
775
695
|
current_share,
|
|
696
|
+
has_worker_flag,
|
|
776
697
|
is_nested_run,
|
|
777
698
|
live_run_count,
|
|
778
699
|
marker_path,
|
|
@@ -783,7 +704,7 @@ var unit_worker_share = {
|
|
|
783
704
|
};
|
|
784
705
|
|
|
785
706
|
// scripts/gate/core-budget.ts
|
|
786
|
-
import { z as
|
|
707
|
+
import { z as z3 } from "zod";
|
|
787
708
|
|
|
788
709
|
// scripts/gate/core-admission.ts
|
|
789
710
|
var MS_PER_SECOND = 1e3;
|
|
@@ -856,6 +777,151 @@ var core_admission = {
|
|
|
856
777
|
sum_load
|
|
857
778
|
};
|
|
858
779
|
|
|
780
|
+
// scripts/gate/core-wait.ts
|
|
781
|
+
import path7 from "node:path";
|
|
782
|
+
|
|
783
|
+
// scripts/lane/lane-paths.ts
|
|
784
|
+
import path6 from "node:path";
|
|
785
|
+
|
|
786
|
+
// scripts/issue/issue-number-shape.ts
|
|
787
|
+
var ISSUE_NUMBER_PATTERN = /^[1-9]\d*$/u;
|
|
788
|
+
var BAD_ISSUE_MESSAGE = "Not an issue number: ";
|
|
789
|
+
function is_issue_number(value) {
|
|
790
|
+
return ISSUE_NUMBER_PATTERN.test(value);
|
|
791
|
+
}
|
|
792
|
+
function require_issue_number(issue) {
|
|
793
|
+
if (!is_issue_number(issue)) throw new Error(`${BAD_ISSUE_MESSAGE}${issue}`);
|
|
794
|
+
}
|
|
795
|
+
var issue_number_shape = { ISSUE_NUMBER_PATTERN, is_issue_number, require_issue_number };
|
|
796
|
+
|
|
797
|
+
// scripts/lane/lane-paths.ts
|
|
798
|
+
var LANE_ROOT_KEY = "JOSH_LANE_ROOT";
|
|
799
|
+
var LANE_DIRECTORY_SUFFIX = "-lanes";
|
|
800
|
+
var LANE_BRANCH_SUFFIX = "-lane";
|
|
801
|
+
function default_lane_root(repository_root) {
|
|
802
|
+
const name = path6.basename(repository_root);
|
|
803
|
+
return path6.join(path6.dirname(repository_root), `.${name}${LANE_DIRECTORY_SUFFIX}`);
|
|
804
|
+
}
|
|
805
|
+
function lane_root(repository_root, environment = process.env) {
|
|
806
|
+
const configured = environment[LANE_ROOT_KEY]?.trim() ?? "";
|
|
807
|
+
return configured.length === 0 ? default_lane_root(repository_root) : path6.resolve(configured);
|
|
808
|
+
}
|
|
809
|
+
function lane_directory(root, issue) {
|
|
810
|
+
return path6.join(root, issue);
|
|
811
|
+
}
|
|
812
|
+
var DEFAULT_LANE_ROOT_PATTERN = new RegExp(String.raw`^\..+${LANE_DIRECTORY_SUFFIX}$`, "u");
|
|
813
|
+
function is_lane_root(directory, environment) {
|
|
814
|
+
const configured = environment[LANE_ROOT_KEY]?.trim() ?? "";
|
|
815
|
+
if (configured.length > 0) return path6.resolve(configured) === directory;
|
|
816
|
+
return DEFAULT_LANE_ROOT_PATTERN.test(path6.basename(directory));
|
|
817
|
+
}
|
|
818
|
+
function lane_issue_of(directory, environment = process.env) {
|
|
819
|
+
const resolved = path6.resolve(directory);
|
|
820
|
+
const issue = path6.basename(resolved);
|
|
821
|
+
if (!issue_number_shape.ISSUE_NUMBER_PATTERN.test(issue)) return void 0;
|
|
822
|
+
return is_lane_root(path6.dirname(resolved), environment) ? issue : void 0;
|
|
823
|
+
}
|
|
824
|
+
function lane_branch(issue) {
|
|
825
|
+
return `${issue}${LANE_BRANCH_SUFFIX}`;
|
|
826
|
+
}
|
|
827
|
+
var SEAT_LOCK_DIR = ".seat-locks";
|
|
828
|
+
function is_lane_entry(name) {
|
|
829
|
+
return issue_number_shape.ISSUE_NUMBER_PATTERN.test(name) || DEFAULT_LANE_ROOT_PATTERN.test(name);
|
|
830
|
+
}
|
|
831
|
+
var lane_paths = {
|
|
832
|
+
LANE_BRANCH_SUFFIX,
|
|
833
|
+
LANE_ROOT_KEY,
|
|
834
|
+
SEAT_LOCK_DIR,
|
|
835
|
+
default_lane_root,
|
|
836
|
+
is_lane_entry,
|
|
837
|
+
lane_branch,
|
|
838
|
+
lane_directory,
|
|
839
|
+
lane_issue_of,
|
|
840
|
+
lane_root
|
|
841
|
+
};
|
|
842
|
+
|
|
843
|
+
// scripts/gate/core-wait.ts
|
|
844
|
+
var WAIT_REASONS = ["cores", "memory", "pressure"];
|
|
845
|
+
var REASON_TEXT = {
|
|
846
|
+
cores: "not enough free cores",
|
|
847
|
+
memory: "not enough free memory",
|
|
848
|
+
pressure: "memory under pressure"
|
|
849
|
+
};
|
|
850
|
+
function wait_reason(key, reservations, budget) {
|
|
851
|
+
const cores_only = { cores: budget.cores, memory_mb: Infinity };
|
|
852
|
+
if (!core_admission.is_admitted(key, reservations, cores_only)) return "cores";
|
|
853
|
+
return budget.memory_pressured === true ? "pressure" : "memory";
|
|
854
|
+
}
|
|
855
|
+
function wait_line(command, reason) {
|
|
856
|
+
return `\u23F3 ${command ?? "a step"} waits for the core budget \u2014 ${REASON_TEXT[reason]}`;
|
|
857
|
+
}
|
|
858
|
+
function lanes_root_of(checkout) {
|
|
859
|
+
if (lane_paths.lane_issue_of(checkout) === void 0) return lane_paths.lane_root(checkout);
|
|
860
|
+
return path7.dirname(path7.resolve(checkout));
|
|
861
|
+
}
|
|
862
|
+
function where_of(checkout) {
|
|
863
|
+
return { checkout, lane: lane_paths.lane_issue_of(checkout), lanes_root: lanes_root_of(checkout) };
|
|
864
|
+
}
|
|
865
|
+
function place_of(marker, home_root) {
|
|
866
|
+
const { checkout, lane, lanes_root } = marker;
|
|
867
|
+
if (checkout === void 0 || lanes_root === void 0 || lanes_root === home_root) {
|
|
868
|
+
return { lane, elsewhere: void 0 };
|
|
869
|
+
}
|
|
870
|
+
const name = lane === void 0 ? path7.basename(checkout) : `${path7.basename(lanes_root)}/${lane}`;
|
|
871
|
+
return { lane: void 0, elsewhere: name };
|
|
872
|
+
}
|
|
873
|
+
function wait_of(marker, now, home_root) {
|
|
874
|
+
const { command, wait_reason: reason } = marker;
|
|
875
|
+
if (reason === void 0 || marker.admitted_at !== void 0) return [];
|
|
876
|
+
return [{ command, ...place_of(marker, home_root), waited_ms: now - marker.claimed_at, reason }];
|
|
877
|
+
}
|
|
878
|
+
function waits_of(entries, now, home) {
|
|
879
|
+
const home_root = lanes_root_of(home);
|
|
880
|
+
return entries.flatMap((entry) => wait_of(entry.reservation, now, home_root)).toSorted((left, right) => right.waited_ms - left.waited_ms);
|
|
881
|
+
}
|
|
882
|
+
var core_wait = {
|
|
883
|
+
REASON_TEXT,
|
|
884
|
+
WAIT_REASONS,
|
|
885
|
+
wait_line,
|
|
886
|
+
wait_reason,
|
|
887
|
+
waits_of,
|
|
888
|
+
where_of
|
|
889
|
+
};
|
|
890
|
+
|
|
891
|
+
// scripts/gate/held-mark.ts
|
|
892
|
+
var HELD_KEY = "JOSH_CORE_RESERVED";
|
|
893
|
+
var HELD_VALUE = "1";
|
|
894
|
+
var HELD_RESERVATION_KEY = "JOSH_CORE_RESERVATION";
|
|
895
|
+
function is_held() {
|
|
896
|
+
return process.env[HELD_KEY] === HELD_VALUE;
|
|
897
|
+
}
|
|
898
|
+
function held_reservation() {
|
|
899
|
+
const key = process.env[HELD_RESERVATION_KEY] ?? "";
|
|
900
|
+
return key === "" ? void 0 : key;
|
|
901
|
+
}
|
|
902
|
+
function set_held_mark(value, reservation) {
|
|
903
|
+
process.env[HELD_KEY] = value;
|
|
904
|
+
process.env[HELD_RESERVATION_KEY] = reservation;
|
|
905
|
+
}
|
|
906
|
+
async function with_held_mark(run2, reservation = "") {
|
|
907
|
+
const previous = process.env[HELD_KEY] ?? "";
|
|
908
|
+
const previous_reservation = process.env[HELD_RESERVATION_KEY] ?? "";
|
|
909
|
+
set_held_mark(HELD_VALUE, reservation);
|
|
910
|
+
try {
|
|
911
|
+
return await run2();
|
|
912
|
+
} finally {
|
|
913
|
+
set_held_mark(previous, previous_reservation);
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
var held_mark = {
|
|
917
|
+
HELD_KEY,
|
|
918
|
+
HELD_RESERVATION_KEY,
|
|
919
|
+
HELD_VALUE,
|
|
920
|
+
held_reservation,
|
|
921
|
+
is_held,
|
|
922
|
+
with_held_mark
|
|
923
|
+
};
|
|
924
|
+
|
|
859
925
|
// scripts/gate/machine-capacity.ts
|
|
860
926
|
import { readFile } from "node:fs/promises";
|
|
861
927
|
import { availableParallelism as availableParallelism2, cpus, totalmem } from "node:os";
|
|
@@ -874,9 +940,20 @@ var PAGE_SIZE_ARGUMENTS = ["PAGESIZE"];
|
|
|
874
940
|
var LEVEL_NAME = "kern.memorystatus_level";
|
|
875
941
|
var SWAP_IN_NAME = "vm.compressor.swapper.swapins_total";
|
|
876
942
|
var SWAP_OUT_NAME = "vm.compressor.swapper.swapouts_total";
|
|
943
|
+
var COMPRESSED_NAME = "vm.compressor_input_bytes";
|
|
877
944
|
var PAGE_SIZE_NAME = "hw.pagesize";
|
|
878
945
|
var PRESSURE_NAME = "kern.memorystatus_vm_pressure_level";
|
|
879
|
-
var
|
|
946
|
+
var PRESSURE_WARNING = 2;
|
|
947
|
+
var SWAP_PRESSURE_MB = 16;
|
|
948
|
+
var COMPRESSION_PRESSURE_MB = 64;
|
|
949
|
+
var SYSCTL_ARGUMENTS = [
|
|
950
|
+
LEVEL_NAME,
|
|
951
|
+
SWAP_IN_NAME,
|
|
952
|
+
SWAP_OUT_NAME,
|
|
953
|
+
COMPRESSED_NAME,
|
|
954
|
+
PAGE_SIZE_NAME,
|
|
955
|
+
PRESSURE_NAME
|
|
956
|
+
];
|
|
880
957
|
var SYSCTL_LINE = /^(?<name>[\w.]+): (?<value>\d+)$/gmu;
|
|
881
958
|
function cpu_times() {
|
|
882
959
|
let busy = 0;
|
|
@@ -905,9 +982,9 @@ function sysctl_values(output) {
|
|
|
905
982
|
function swapped_pages(pages_in, pages_out) {
|
|
906
983
|
return pages_in === void 0 || pages_out === void 0 ? void 0 : pages_in + pages_out;
|
|
907
984
|
}
|
|
908
|
-
function
|
|
909
|
-
if (
|
|
910
|
-
return
|
|
985
|
+
function mb_of(units, unit_bytes) {
|
|
986
|
+
if (units === void 0 || unit_bytes === void 0) return void 0;
|
|
987
|
+
return units * unit_bytes / BYTES_PER_MB;
|
|
911
988
|
}
|
|
912
989
|
function swapped_between(from, to) {
|
|
913
990
|
if (from === void 0 || to === void 0) return void 0;
|
|
@@ -918,11 +995,12 @@ function parse_darwin_memory(output, total_bytes) {
|
|
|
918
995
|
const level = values.get(LEVEL_NAME);
|
|
919
996
|
return {
|
|
920
997
|
available_mb: level === void 0 ? void 0 : level / PERCENT * (total_bytes / BYTES_PER_MB),
|
|
921
|
-
swapped_mb:
|
|
998
|
+
swapped_mb: mb_of(
|
|
922
999
|
swapped_pages(values.get(SWAP_IN_NAME), values.get(SWAP_OUT_NAME)),
|
|
923
1000
|
values.get(PAGE_SIZE_NAME)
|
|
924
1001
|
),
|
|
925
|
-
pressure_level: values.get(PRESSURE_NAME)
|
|
1002
|
+
pressure_level: values.get(PRESSURE_NAME),
|
|
1003
|
+
compressed_mb: mb_of(values.get(COMPRESSED_NAME), 1)
|
|
926
1004
|
};
|
|
927
1005
|
}
|
|
928
1006
|
function parse_linux_available(meminfo) {
|
|
@@ -935,7 +1013,7 @@ function pages_of(pattern, vmstat) {
|
|
|
935
1013
|
}
|
|
936
1014
|
function parse_linux_swapped(vmstat, page_bytes) {
|
|
937
1015
|
const pages = swapped_pages(pages_of(LINUX_SWAP_IN, vmstat), pages_of(LINUX_SWAP_OUT, vmstat));
|
|
938
|
-
return
|
|
1016
|
+
return mb_of(pages, page_bytes);
|
|
939
1017
|
}
|
|
940
1018
|
async function settled(read2) {
|
|
941
1019
|
try {
|
|
@@ -985,11 +1063,26 @@ async function default_sleep(ms) {
|
|
|
985
1063
|
setTimeout(resolve, ms);
|
|
986
1064
|
});
|
|
987
1065
|
}
|
|
1066
|
+
function moved_over(from, to, limit) {
|
|
1067
|
+
return (swapped_between(from, to) ?? 0) > limit;
|
|
1068
|
+
}
|
|
1069
|
+
function is_pressured(before, after) {
|
|
1070
|
+
return (after.pressure_level ?? 0) >= PRESSURE_WARNING || moved_over(before.swapped_mb, after.swapped_mb, SWAP_PRESSURE_MB) || moved_over(before.compressed_mb, after.compressed_mb, COMPRESSION_PRESSURE_MB);
|
|
1071
|
+
}
|
|
1072
|
+
function pressured_available(before, after) {
|
|
1073
|
+
if (after.available_mb === void 0) return void 0;
|
|
1074
|
+
return is_pressured(before, after) ? 0 : after.available_mb;
|
|
1075
|
+
}
|
|
988
1076
|
async function read_machine(sleep = default_sleep) {
|
|
989
1077
|
const before = cpu_times();
|
|
990
|
-
const [
|
|
1078
|
+
const [memory_before] = await Promise.all([read_memory(), sleep(SAMPLE_WINDOW_MS)]);
|
|
1079
|
+
const memory_after = await read_memory();
|
|
991
1080
|
const busy_cores = is_unquoted() ? busy_cores_between(before, cpu_times(), cpus().length) : void 0;
|
|
992
|
-
return {
|
|
1081
|
+
return {
|
|
1082
|
+
busy_cores,
|
|
1083
|
+
available_mb: pressured_available(memory_before, memory_after),
|
|
1084
|
+
memory_pressured: is_pressured(memory_before, memory_after)
|
|
1085
|
+
};
|
|
993
1086
|
}
|
|
994
1087
|
async function read_sample() {
|
|
995
1088
|
return { cpu: cpu_times(), memory: await read_memory(), total_mb: totalmem() / BYTES_PER_MB };
|
|
@@ -1001,21 +1094,25 @@ function external_cores(busy_cores, ledger_cores) {
|
|
|
1001
1094
|
function machine_budget(cores, reading, ledger) {
|
|
1002
1095
|
return {
|
|
1003
1096
|
cores: cores - external_cores(reading.busy_cores, ledger.cores),
|
|
1004
|
-
memory_mb: reading.available_mb === void 0 ? Infinity : reading.available_mb + ledger.memory_mb
|
|
1097
|
+
memory_mb: reading.available_mb === void 0 ? Infinity : reading.available_mb + ledger.memory_mb,
|
|
1098
|
+
memory_pressured: reading.memory_pressured
|
|
1005
1099
|
};
|
|
1006
1100
|
}
|
|
1007
1101
|
var machine_capacity = {
|
|
1008
1102
|
BASELINE_CORES,
|
|
1009
1103
|
busy_cores_between,
|
|
1010
1104
|
busy_share_between,
|
|
1105
|
+
COMPRESSION_PRESSURE_MB,
|
|
1011
1106
|
external_cores,
|
|
1012
1107
|
machine_budget,
|
|
1013
1108
|
parse_darwin_memory,
|
|
1014
1109
|
parse_linux_available,
|
|
1015
1110
|
parse_linux_swapped,
|
|
1111
|
+
pressured_available,
|
|
1016
1112
|
read_machine,
|
|
1017
1113
|
read_memory,
|
|
1018
1114
|
read_sample,
|
|
1115
|
+
SWAP_PRESSURE_MB,
|
|
1019
1116
|
swapped_between
|
|
1020
1117
|
};
|
|
1021
1118
|
|
|
@@ -1029,22 +1126,32 @@ var CORE_WEIGHTS = {
|
|
|
1029
1126
|
lint: 2,
|
|
1030
1127
|
type_check: 1,
|
|
1031
1128
|
spell_check: 1,
|
|
1032
|
-
eslint_scan: 1
|
|
1129
|
+
eslint_scan: 1,
|
|
1130
|
+
format: 1,
|
|
1131
|
+
retrospective: 1,
|
|
1132
|
+
install: 1,
|
|
1133
|
+
e2e: 2
|
|
1033
1134
|
};
|
|
1034
1135
|
var MEMORY_MB = {
|
|
1035
1136
|
lint: 2400,
|
|
1036
1137
|
type_check: 1300,
|
|
1037
1138
|
spell_check: 350,
|
|
1038
1139
|
eslint_scan: 2400,
|
|
1039
|
-
unit_worker: 350
|
|
1140
|
+
unit_worker: 350,
|
|
1141
|
+
format: 300,
|
|
1142
|
+
retrospective: 900,
|
|
1143
|
+
install: 100
|
|
1040
1144
|
};
|
|
1041
|
-
var HELD_KEY = "JOSH_CORE_RESERVED";
|
|
1042
|
-
var HELD_VALUE = "1";
|
|
1043
1145
|
var reservation_schema = process_owner_schema.extend({
|
|
1044
|
-
weight:
|
|
1045
|
-
claimed_at:
|
|
1046
|
-
memory_mb:
|
|
1047
|
-
admitted_at:
|
|
1146
|
+
weight: z3.number(),
|
|
1147
|
+
claimed_at: z3.number(),
|
|
1148
|
+
memory_mb: z3.number().optional(),
|
|
1149
|
+
admitted_at: z3.number().optional(),
|
|
1150
|
+
command: z3.string().optional(),
|
|
1151
|
+
checkout: z3.string().optional(),
|
|
1152
|
+
lane: z3.string().optional(),
|
|
1153
|
+
lanes_root: z3.string().optional(),
|
|
1154
|
+
wait_reason: z3.enum(core_wait.WAIT_REASONS).optional()
|
|
1048
1155
|
});
|
|
1049
1156
|
function marker_name(key) {
|
|
1050
1157
|
return `${RESERVED_PREFIX}${key}${RESERVED_SUFFIX}`;
|
|
@@ -1096,6 +1203,10 @@ async function default_sleep2(ms) {
|
|
|
1096
1203
|
function write_reservation(target, fields) {
|
|
1097
1204
|
stamp_file.replace_stamp(target, { ...process_identity.own_fields(), ...fields });
|
|
1098
1205
|
}
|
|
1206
|
+
function report_wait(line) {
|
|
1207
|
+
process.stderr.write(`${line}
|
|
1208
|
+
`);
|
|
1209
|
+
}
|
|
1099
1210
|
function resolve_timing(options) {
|
|
1100
1211
|
return {
|
|
1101
1212
|
now: options.now ?? Date.now,
|
|
@@ -1122,6 +1233,13 @@ function overflow_of(context, reservations, budget) {
|
|
|
1122
1233
|
budget
|
|
1123
1234
|
};
|
|
1124
1235
|
}
|
|
1236
|
+
function mark_waiting(context, reason) {
|
|
1237
|
+
const previous = context.fields.wait_reason;
|
|
1238
|
+
if (previous === reason) return;
|
|
1239
|
+
context.fields = { ...context.fields, wait_reason: reason };
|
|
1240
|
+
write_reservation(context.target, context.fields);
|
|
1241
|
+
if (previous === void 0) context.report(core_wait.wait_line(context.fields.command, reason));
|
|
1242
|
+
}
|
|
1125
1243
|
async function poll_admission(context) {
|
|
1126
1244
|
const reservations = live_reservations(context.directory);
|
|
1127
1245
|
const budget = await current_budget(context, reservations);
|
|
@@ -1129,6 +1247,7 @@ async function poll_admission(context) {
|
|
|
1129
1247
|
if (context.now() >= context.deadline) {
|
|
1130
1248
|
return admit(context, overflow_of(context, reservations, budget));
|
|
1131
1249
|
}
|
|
1250
|
+
mark_waiting(context, core_wait.wait_reason(context.key, reservations, budget));
|
|
1132
1251
|
return void 0;
|
|
1133
1252
|
}
|
|
1134
1253
|
async function await_admission(context) {
|
|
@@ -1139,13 +1258,23 @@ async function await_admission(context) {
|
|
|
1139
1258
|
}
|
|
1140
1259
|
return admission;
|
|
1141
1260
|
}
|
|
1261
|
+
function resolve_ports(options) {
|
|
1262
|
+
return {
|
|
1263
|
+
read_machine: options.read_machine ?? machine_capacity.read_machine,
|
|
1264
|
+
report: options.report ?? report_wait
|
|
1265
|
+
};
|
|
1266
|
+
}
|
|
1267
|
+
function claim_fields(weight, claimed_at, options) {
|
|
1268
|
+
const { memory_mb, command } = options;
|
|
1269
|
+
return { weight, claimed_at, memory_mb, command, ...core_wait.where_of(process.cwd()) };
|
|
1270
|
+
}
|
|
1142
1271
|
async function reserve(weight, options = {}) {
|
|
1143
1272
|
const timing = resolve_timing(options);
|
|
1144
1273
|
const directory = options.directory ?? PLATFORM_TEMP_ROOT;
|
|
1145
1274
|
const claimed_at = timing.now();
|
|
1146
1275
|
const name = marker_name(randomUUID3());
|
|
1147
1276
|
const target = path8.join(directory, name);
|
|
1148
|
-
const fields =
|
|
1277
|
+
const fields = claim_fields(weight, claimed_at, options);
|
|
1149
1278
|
write_reservation(target, fields);
|
|
1150
1279
|
const admission = await await_admission({
|
|
1151
1280
|
...timing,
|
|
@@ -1155,92 +1284,134 @@ async function reserve(weight, options = {}) {
|
|
|
1155
1284
|
budget: normalize_budget(options.budget ?? availableParallelism3()),
|
|
1156
1285
|
deadline: claimed_at + timing.wait_cap_ms,
|
|
1157
1286
|
fields,
|
|
1158
|
-
|
|
1287
|
+
...resolve_ports(options)
|
|
1159
1288
|
});
|
|
1160
1289
|
return { target, admission };
|
|
1161
1290
|
}
|
|
1291
|
+
function budget_waits(directory = PLATFORM_TEMP_ROOT, now = Date.now(), home = process.cwd()) {
|
|
1292
|
+
return core_wait.waits_of(live_reservations(directory), now, home);
|
|
1293
|
+
}
|
|
1162
1294
|
function release(handle) {
|
|
1163
1295
|
sweep_marker2(handle.target);
|
|
1164
1296
|
}
|
|
1165
1297
|
async function with_core_reservation(weight, run2, options = {}) {
|
|
1166
1298
|
const handle = await reserve(weight, options);
|
|
1167
1299
|
try {
|
|
1168
|
-
return await run2(handle.admission);
|
|
1300
|
+
return await run2(handle.admission, path8.basename(handle.target));
|
|
1169
1301
|
} finally {
|
|
1170
1302
|
release(handle);
|
|
1171
1303
|
}
|
|
1172
1304
|
}
|
|
1173
|
-
function is_held() {
|
|
1174
|
-
return process.env[HELD_KEY] === HELD_VALUE;
|
|
1175
|
-
}
|
|
1176
|
-
function set_held_mark(value) {
|
|
1177
|
-
process.env[HELD_KEY] = value;
|
|
1178
|
-
}
|
|
1179
|
-
async function with_held_mark(run2) {
|
|
1180
|
-
const previous = process.env[HELD_KEY] ?? "";
|
|
1181
|
-
set_held_mark(HELD_VALUE);
|
|
1182
|
-
try {
|
|
1183
|
-
return await run2();
|
|
1184
|
-
} finally {
|
|
1185
|
-
set_held_mark(previous);
|
|
1186
|
-
}
|
|
1187
|
-
}
|
|
1188
1305
|
async function with_command_reservation(weight, run2, options = {}) {
|
|
1189
|
-
if (is_held() || unit_worker_share.is_nested_run()) return await run2();
|
|
1190
|
-
return await with_core_reservation(
|
|
1306
|
+
if (held_mark.is_held() || unit_worker_share.is_nested_run()) return await run2();
|
|
1307
|
+
return await with_core_reservation(
|
|
1308
|
+
weight,
|
|
1309
|
+
async (_admission, key) => await held_mark.with_held_mark(run2, key),
|
|
1310
|
+
options
|
|
1311
|
+
);
|
|
1191
1312
|
}
|
|
1192
1313
|
var core_budget = {
|
|
1193
1314
|
CORE_WEIGHTS,
|
|
1194
|
-
HELD_KEY,
|
|
1195
|
-
HELD_VALUE,
|
|
1315
|
+
HELD_KEY: held_mark.HELD_KEY,
|
|
1316
|
+
HELD_VALUE: held_mark.HELD_VALUE,
|
|
1196
1317
|
MEMORY_MB,
|
|
1197
1318
|
RESERVED_PREFIX,
|
|
1198
1319
|
admitted_keys: core_admission.admitted_keys,
|
|
1199
1320
|
admitted_load: core_admission.admitted_load,
|
|
1321
|
+
budget_waits,
|
|
1200
1322
|
describe_overflow: core_admission.describe_overflow,
|
|
1201
|
-
is_held,
|
|
1323
|
+
is_held: held_mark.is_held,
|
|
1202
1324
|
live_reservations,
|
|
1203
1325
|
release,
|
|
1204
1326
|
reserve,
|
|
1205
1327
|
with_command_reservation,
|
|
1206
1328
|
with_core_reservation,
|
|
1207
|
-
with_held_mark
|
|
1329
|
+
with_held_mark: held_mark.with_held_mark
|
|
1208
1330
|
};
|
|
1209
1331
|
|
|
1210
|
-
//
|
|
1211
|
-
import {
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
var
|
|
1215
|
-
|
|
1216
|
-
|
|
1332
|
+
// ports/index.js
|
|
1333
|
+
import { existsSync as existsSync2 } from "node:fs";
|
|
1334
|
+
import path9 from "node:path";
|
|
1335
|
+
var PORT_SEED_KEY = "PORT_SEED";
|
|
1336
|
+
var LANE_SEAT_KEY = "JOSH_LANE_SEAT";
|
|
1337
|
+
var ENV_FILE_NAME = ".env";
|
|
1338
|
+
var PACKAGE_FILE_NAME = "package.json";
|
|
1339
|
+
var PROJECT_ENVIRONMENT_KEYS = /* @__PURE__ */ new Set([PORT_SEED_KEY, LANE_SEAT_KEY, "PLAYWRIGHT_REUSE_SERVER"]);
|
|
1340
|
+
var DEV_PORT_BASE = 5173;
|
|
1341
|
+
var PREVIEW_PORT_BASE = 4173;
|
|
1342
|
+
var MIN_SEED = 0;
|
|
1343
|
+
var SEED_LANE_MULTIPLIER = 10;
|
|
1344
|
+
var MAX_LANE = 9;
|
|
1345
|
+
var MAX_SEED = 99;
|
|
1346
|
+
var INTEGER_PATTERN = /^\d+$/u;
|
|
1347
|
+
function fail_invalid(key, raw, max) {
|
|
1348
|
+
throw new Error(
|
|
1349
|
+
`${key} must be an integer between ${MIN_SEED} and ${max}, got ${JSON.stringify(raw)}. Unset it to use the default ports (dev ${DEV_PORT_BASE}, preview ${PREVIEW_PORT_BASE}).`
|
|
1350
|
+
);
|
|
1217
1351
|
}
|
|
1218
|
-
function
|
|
1219
|
-
const
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1352
|
+
function read_trimmed(environment, key) {
|
|
1353
|
+
const raw = environment[key];
|
|
1354
|
+
return raw === void 0 ? "" : raw.trim();
|
|
1355
|
+
}
|
|
1356
|
+
function resolve_bounded(environment, key, max) {
|
|
1357
|
+
const trimmed = read_trimmed(environment, key);
|
|
1358
|
+
if (trimmed.length === 0) return MIN_SEED;
|
|
1359
|
+
if (!INTEGER_PATTERN.test(trimmed)) fail_invalid(key, trimmed, max);
|
|
1360
|
+
const value = Number(trimmed);
|
|
1361
|
+
if (value > max) fail_invalid(key, trimmed, max);
|
|
1362
|
+
return value;
|
|
1363
|
+
}
|
|
1364
|
+
function resolve_seed(environment = process.env) {
|
|
1365
|
+
return resolve_bounded(environment, PORT_SEED_KEY, MAX_SEED);
|
|
1366
|
+
}
|
|
1367
|
+
function resolve_lane(environment = process.env) {
|
|
1368
|
+
return resolve_bounded(environment, LANE_SEAT_KEY, MAX_LANE);
|
|
1369
|
+
}
|
|
1370
|
+
function resolve_offset(environment = process.env) {
|
|
1371
|
+
return resolve_seed(environment) * SEED_LANE_MULTIPLIER + resolve_lane(environment);
|
|
1372
|
+
}
|
|
1373
|
+
function offset_from(base, environment) {
|
|
1374
|
+
return base + resolve_offset(environment);
|
|
1375
|
+
}
|
|
1376
|
+
function resolve_development_port(environment = process.env) {
|
|
1377
|
+
return offset_from(DEV_PORT_BASE, environment);
|
|
1378
|
+
}
|
|
1379
|
+
function resolve_preview_port(environment = process.env) {
|
|
1380
|
+
return offset_from(PREVIEW_PORT_BASE, environment);
|
|
1381
|
+
}
|
|
1382
|
+
function resolve_project_directory(directory) {
|
|
1383
|
+
const start = path9.resolve(directory);
|
|
1384
|
+
let current = start;
|
|
1385
|
+
while (!existsSync2(path9.join(current, PACKAGE_FILE_NAME))) {
|
|
1386
|
+
const parent = path9.dirname(current);
|
|
1387
|
+
if (parent === current) return start;
|
|
1388
|
+
current = parent;
|
|
1226
1389
|
}
|
|
1227
1390
|
return current;
|
|
1228
1391
|
}
|
|
1229
|
-
function
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1392
|
+
function discard_loaded_keys(snapshot) {
|
|
1393
|
+
for (const key of Object.keys(process.env)) {
|
|
1394
|
+
if (!PROJECT_ENVIRONMENT_KEYS.has(key) && !Object.hasOwn(snapshot, key)) {
|
|
1395
|
+
Reflect.deleteProperty(process.env, key);
|
|
1396
|
+
}
|
|
1233
1397
|
}
|
|
1234
|
-
return at(previous, target.length);
|
|
1235
1398
|
}
|
|
1236
|
-
function
|
|
1237
|
-
const
|
|
1238
|
-
return
|
|
1239
|
-
}
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1399
|
+
function load_environment_file(directory = process.cwd()) {
|
|
1400
|
+
const file = path9.join(resolve_project_directory(directory), ENV_FILE_NAME);
|
|
1401
|
+
if (!existsSync2(file)) return false;
|
|
1402
|
+
const snapshot = { ...process.env };
|
|
1403
|
+
process.loadEnvFile(file);
|
|
1404
|
+
discard_loaded_keys(snapshot);
|
|
1405
|
+
return true;
|
|
1406
|
+
}
|
|
1407
|
+
var ports = {
|
|
1408
|
+
load_environment_file,
|
|
1409
|
+
resolve_project_directory,
|
|
1410
|
+
resolve_seed,
|
|
1411
|
+
resolve_lane,
|
|
1412
|
+
resolve_development_port,
|
|
1413
|
+
resolve_preview_port
|
|
1414
|
+
};
|
|
1244
1415
|
|
|
1245
1416
|
// scripts/josh/josh-command-types.ts
|
|
1246
1417
|
var OPTIONAL_ENV_FILE_FLAGS = [`--env-file-if-exists=${ENV_FILE_NAME}`];
|
|
@@ -1250,6 +1421,10 @@ var TS_BUILD_INFO_FILE = ".tsbuildinfo";
|
|
|
1250
1421
|
var CSPELL_CACHE_FILE = ".cspellcache";
|
|
1251
1422
|
var ESLINT_EDIT_CACHE_FILE = ".eslintcache.edit";
|
|
1252
1423
|
var ESLINT_RELATED_CACHE_FILE = ".eslintcache.related";
|
|
1424
|
+
var PRETTIER_CACHE_FILE = ".prettiercache";
|
|
1425
|
+
var PRETTIER_RELATED_CACHE_FILE = ".prettiercache.related";
|
|
1426
|
+
var CSPELL_COMMIT_CACHE_FILE = ".cspellcache.commit";
|
|
1427
|
+
var ESLINT_COMMIT_CACHE_FILE = ".eslintcache.commit";
|
|
1253
1428
|
var ROOTED_JSON_PORTABILITY = "rooted-json";
|
|
1254
1429
|
var ESLINT_CACHE_SPEC = {
|
|
1255
1430
|
cache_file: ESLINT_CACHE_FILE,
|
|
@@ -1272,7 +1447,11 @@ var GATE_CACHE_FILES = GATE_CACHE_SPECS.map((spec) => spec.cache_file);
|
|
|
1272
1447
|
var IGNORED_CACHE_FILES = [
|
|
1273
1448
|
...GATE_CACHE_FILES,
|
|
1274
1449
|
ESLINT_EDIT_CACHE_FILE,
|
|
1275
|
-
ESLINT_RELATED_CACHE_FILE
|
|
1450
|
+
ESLINT_RELATED_CACHE_FILE,
|
|
1451
|
+
PRETTIER_CACHE_FILE,
|
|
1452
|
+
PRETTIER_RELATED_CACHE_FILE,
|
|
1453
|
+
CSPELL_COMMIT_CACHE_FILE,
|
|
1454
|
+
ESLINT_COMMIT_CACHE_FILE
|
|
1276
1455
|
];
|
|
1277
1456
|
var CONTENT_CACHE_FLAGS = ["--cache", "--cache-strategy", "content"];
|
|
1278
1457
|
var CACHE_LOCATION_FLAG = "--cache-location";
|
|
@@ -1283,6 +1462,10 @@ var ESLINT_CACHE_FLAGS = content_cache_flags(ESLINT_CACHE_FILE);
|
|
|
1283
1462
|
var ESLINT_EDIT_CACHE_FLAGS = content_cache_flags(ESLINT_EDIT_CACHE_FILE);
|
|
1284
1463
|
var ESLINT_RELATED_CACHE_FLAGS = content_cache_flags(ESLINT_RELATED_CACHE_FILE);
|
|
1285
1464
|
var CSPELL_CACHE_FLAGS = content_cache_flags(CSPELL_CACHE_FILE);
|
|
1465
|
+
var PRETTIER_CACHE_FLAGS = content_cache_flags(PRETTIER_CACHE_FILE);
|
|
1466
|
+
var PRETTIER_RELATED_CACHE_FLAGS = content_cache_flags(PRETTIER_RELATED_CACHE_FILE);
|
|
1467
|
+
var CSPELL_COMMIT_CACHE_FLAGS = content_cache_flags(CSPELL_COMMIT_CACHE_FILE);
|
|
1468
|
+
var ESLINT_COMMIT_CACHE_FLAGS = content_cache_flags(ESLINT_COMMIT_CACHE_FILE);
|
|
1286
1469
|
|
|
1287
1470
|
// scripts/josh/josh-commands-backlog.ts
|
|
1288
1471
|
var BACKLOG_COMMANDS = {
|
|
@@ -1546,6 +1729,14 @@ var LANE_COMMANDS = {
|
|
|
1546
1729
|
category: "AI tools",
|
|
1547
1730
|
reference: ["<issue>", "developer", ["files", "git", "processes", "network"]]
|
|
1548
1731
|
},
|
|
1732
|
+
// `.env` is read for `JOSH_LANE_ROOT`, as every lane command reads it, so the lane is found.
|
|
1733
|
+
"lane:withdraw": {
|
|
1734
|
+
script: "scripts/lane/lane-withdraw-cli.ts",
|
|
1735
|
+
tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
|
|
1736
|
+
description: "Stop a running lane child, stash its uncommitted work, close its issue as not planned and close the lane \u2014 booked withdrawn, not as an outage or a failure",
|
|
1737
|
+
category: "AI tools",
|
|
1738
|
+
reference: ["<issue> --reason <text>", "developer", ["files", "git", "processes", "network"]]
|
|
1739
|
+
},
|
|
1549
1740
|
// A live run's lane limit: `.env` is read so the bare form reports the
|
|
1550
1741
|
// `JOSH_LANE_LIMIT` a person set there when no override stands.
|
|
1551
1742
|
"lane:limit": {
|
|
@@ -1566,7 +1757,7 @@ var LANE_COMMANDS = {
|
|
|
1566
1757
|
},
|
|
1567
1758
|
"lane:stats": {
|
|
1568
1759
|
...MEASURE_ARGUMENTS,
|
|
1569
|
-
description: "Print one table row of lane throughput, gate duration and machine load over a period, the per-stage durations of a lane under it,
|
|
1760
|
+
description: "Print one table row of lane throughput, gate duration and machine load over a period, the per-stage durations of a lane under it, the wait after each ship stop reason under those, and the duration and reuse count of each gate check last",
|
|
1570
1761
|
category: "AI tools",
|
|
1571
1762
|
reference: ["--period <days> [--limit <lane-limit>]", "maintainer", ["none"]],
|
|
1572
1763
|
default_script_arguments: ["stats"]
|
|
@@ -1772,6 +1963,15 @@ var AI_COMMANDS = {
|
|
|
1772
1963
|
category: "AI tools",
|
|
1773
1964
|
reference: ["(--cut | --over <tokens-per-request>) [--path <dir>]", "automation", ["none"]]
|
|
1774
1965
|
},
|
|
1966
|
+
"cost:audit": {
|
|
1967
|
+
script: "scripts/cost-audit/cost-audit-cli.ts",
|
|
1968
|
+
description: "Report AI cost over a period by session kind, tool category and guard, with cost per merge and regressions against the period before",
|
|
1969
|
+
category: "AI tools",
|
|
1970
|
+
reference: ["[--period <days>]", "maintainer", ["none"]],
|
|
1971
|
+
// Kit-only: it reads kit's own transcript store, like `josh retrospective`, which carries its
|
|
1972
|
+
// summary line.
|
|
1973
|
+
is_kit_only: true
|
|
1974
|
+
},
|
|
1775
1975
|
...DOCUMENT_COMMANDS,
|
|
1776
1976
|
time: {
|
|
1777
1977
|
script: "scripts/time/time-cli.ts",
|
|
@@ -1799,6 +1999,8 @@ var AI_COMMANDS = {
|
|
|
1799
1999
|
description: "Aggregate a finished run's cost, review findings, observation ledger and events into one digest",
|
|
1800
2000
|
category: "AI tools",
|
|
1801
2001
|
reference: ["", "maintainer", ["none"]],
|
|
2002
|
+
core_weight: core_budget.CORE_WEIGHTS.retrospective,
|
|
2003
|
+
memory_mb: core_budget.MEMORY_MB.retrospective,
|
|
1802
2004
|
// Kit-only: it reads kit's own development run — the transcript store, the review ledger and the
|
|
1803
2005
|
// run event stream — so it means nothing in a consumer project and is dropped from a consumer's
|
|
1804
2006
|
// help, through the same declaration `josh time` uses for the same reason.
|
|
@@ -2000,6 +2202,7 @@ var TYPE_CHECK_LABEL = "check";
|
|
|
2000
2202
|
var UNIT_LABEL = "test:unit";
|
|
2001
2203
|
var BEHAVIOR_LABEL = "behavior";
|
|
2002
2204
|
var METRICS_LABEL = "metrics";
|
|
2205
|
+
var EXPORTS_LABEL = "exports";
|
|
2003
2206
|
var WARNING_CHECKER_LABELS = [LINT_LABEL, TYPE_CHECK_LABEL];
|
|
2004
2207
|
var STATIC_CHECKS = [
|
|
2005
2208
|
{
|
|
@@ -2025,7 +2228,7 @@ var STATIC_CHECKS = [
|
|
|
2025
2228
|
// program and walks it for about 5s, and it is over well before lint and the type check. A
|
|
2026
2229
|
// reservation would only take a place from the four-core CI runner's fan-out and a worker from the
|
|
2027
2230
|
// unit suite for the whole gate.
|
|
2028
|
-
{ label:
|
|
2231
|
+
{ label: EXPORTS_LABEL, target: "exports:unused", reserved_cores: 0 },
|
|
2029
2232
|
// **The metrics ratchet is kit's own**: it holds kit's repository-wide
|
|
2030
2233
|
// totals to the merge-base's. It is one in-process eslint pass with only `max-lines` enabled, over
|
|
2031
2234
|
// in a few seconds, so it reserves no core for the reason the unused-member check above does not.
|
|
@@ -2114,6 +2317,15 @@ function resolve_gate_plan(available_cores = availableParallelism4(), concurrent
|
|
|
2114
2317
|
unit_worker_cap: unit_cap_for(checks, available_cores, concurrent_runs)
|
|
2115
2318
|
};
|
|
2116
2319
|
}
|
|
2320
|
+
function bound_by_free(plan, available_cores, free_cores) {
|
|
2321
|
+
if (!has_unit_check(plan.checks)) return plan;
|
|
2322
|
+
const unit_worker_cap = unit_worker_share.cap_to_free(
|
|
2323
|
+
plan.unit_worker_cap,
|
|
2324
|
+
free_cores,
|
|
2325
|
+
available_cores
|
|
2326
|
+
);
|
|
2327
|
+
return { ...plan, unit_worker_cap };
|
|
2328
|
+
}
|
|
2117
2329
|
function format_machine(available_cores, concurrent_runs) {
|
|
2118
2330
|
const cores = `${String(available_cores)} cores`;
|
|
2119
2331
|
if (concurrent_runs <= unit_worker_share.SOLO_RUNS) return cores;
|
|
@@ -2132,6 +2344,7 @@ function format_gate_plan(plan, available_cores = availableParallelism4(), concu
|
|
|
2132
2344
|
return `${josh_verdict.GATE_OPENING_PREFIX}${width}, ${cap} (${machine})`;
|
|
2133
2345
|
}
|
|
2134
2346
|
var gate_plan = {
|
|
2347
|
+
EXPORTS_LABEL,
|
|
2135
2348
|
GATE_CHECKS,
|
|
2136
2349
|
LINT_LABEL,
|
|
2137
2350
|
MEASURED_CORES,
|
|
@@ -2141,6 +2354,7 @@ var gate_plan = {
|
|
|
2141
2354
|
TYPE_CHECK_LABEL,
|
|
2142
2355
|
UNIT_LABEL,
|
|
2143
2356
|
WARNING_CHECKER_LABELS,
|
|
2357
|
+
bound_by_free,
|
|
2144
2358
|
check_memory,
|
|
2145
2359
|
check_weight,
|
|
2146
2360
|
direct_unit_memory,
|
|
@@ -2273,7 +2487,7 @@ var DEV_COMMANDS = {
|
|
|
2273
2487
|
},
|
|
2274
2488
|
"stop:guard": {
|
|
2275
2489
|
script: "scripts/hooks/stop-guard.ts",
|
|
2276
|
-
description: "Claude Code Stop hook:
|
|
2490
|
+
description: "Claude Code Stop hook: send the hold notify, release the hold and print the issue citations itself; block on the rules that need the model (reads the Stop payload on stdin)",
|
|
2277
2491
|
category: "Development",
|
|
2278
2492
|
reference: ["", "automation", ["none"]]
|
|
2279
2493
|
// **No `tsx_arguments`, deliberately**, the same as `pretool:guard` above: this runs at every
|
|
@@ -2407,6 +2621,12 @@ var HOOKS_COMMANDS = {
|
|
|
2407
2621
|
category: "Git hooks",
|
|
2408
2622
|
reference: ["[paths...]", "automation", ["none"]]
|
|
2409
2623
|
},
|
|
2624
|
+
"pre-commit-lint": {
|
|
2625
|
+
script: "scripts/hooks/pre-commit-lint.ts",
|
|
2626
|
+
description: "Git hook: run cspell, prettier or eslint over staged files from a content cache",
|
|
2627
|
+
category: "Git hooks",
|
|
2628
|
+
reference: ["<cspell|prettier|eslint> [paths...]", "automation", ["files"]]
|
|
2629
|
+
},
|
|
2410
2630
|
"pre-push-unit": {
|
|
2411
2631
|
script: "scripts/hooks/pre-push-unit.ts",
|
|
2412
2632
|
description: "Git hook: run unit tests, reusing a green gate recorded on the pushed tree",
|
|
@@ -2812,6 +3032,11 @@ var WORKFLOW_COMMANDS = {
|
|
|
2812
3032
|
// A script rather than an `sh -c` chain, because the strategy has to be named rather than left to
|
|
2813
3033
|
// the caller's git configuration: a bare `git pull` aborts with `Need to specify how to reconcile
|
|
2814
3034
|
// divergent branches` on exactly the diverged branch the command exists for.
|
|
3035
|
+
//
|
|
3036
|
+
// **It declares no core weight, by measurement** (joshuafolkken/kit#3944): its own work is git, and
|
|
3037
|
+
// the catalog it may regenerate took 0.6s of CPU. The heavy processes seen beside it are commit
|
|
3038
|
+
// hooks — its regenerated catalog's commit runs them — which reserve themselves, and a weight here
|
|
3039
|
+
// would set the held mark they inherit, folding the parallel hook tools into this one place.
|
|
2815
3040
|
"main:merge": {
|
|
2816
3041
|
script: "scripts/git/main-merge.ts",
|
|
2817
3042
|
description: "Merge origin default branch into the current branch",
|
|
@@ -2887,6 +3112,7 @@ var ALIASES = {
|
|
|
2887
3112
|
tm: "time",
|
|
2888
3113
|
tmd: "time:density",
|
|
2889
3114
|
rtr: "retrospective",
|
|
3115
|
+
ca: "cost:audit",
|
|
2890
3116
|
rvf: "review:findings",
|
|
2891
3117
|
ruv: "rule:value",
|
|
2892
3118
|
ev: "eval",
|
|
@@ -2896,73 +3122,1685 @@ var ALIASES = {
|
|
|
2896
3122
|
lst: "lane:stats",
|
|
2897
3123
|
lli: "lane:limit",
|
|
2898
3124
|
lrs: "lane:restart",
|
|
3125
|
+
lwd: "lane:withdraw",
|
|
2899
3126
|
blr: "backlogrun"
|
|
2900
3127
|
};
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
var SHELL_COMMAND_FLAG = "-c";
|
|
2905
|
-
var PATH_SEPARATOR = "/";
|
|
2906
|
-
var USAGE_ERROR_EXIT_CODE = 1;
|
|
2907
|
-
function is_shell_interpreter(executable) {
|
|
2908
|
-
return SHELL_INTERPRETERS.has(executable.split(PATH_SEPARATOR).at(-1) ?? executable);
|
|
2909
|
-
}
|
|
2910
|
-
function is_composite_shell(shell) {
|
|
2911
|
-
const [executable, flag] = shell ?? [];
|
|
2912
|
-
if (executable === void 0) return false;
|
|
2913
|
-
return is_shell_interpreter(executable) && flag === SHELL_COMMAND_FLAG;
|
|
2914
|
-
}
|
|
2915
|
-
function format_targets(targets) {
|
|
2916
|
-
return targets.map((target) => `josh ${target}`).join(" or ");
|
|
2917
|
-
}
|
|
2918
|
-
function format_rejection(cmd, targets) {
|
|
2919
|
-
const hint = targets.length > 0 ? `pass them to ${format_targets(targets)} instead` : "it runs a fixed sequence and forwards nothing";
|
|
2920
|
-
return `josh ${cmd} takes no extra arguments \u2014 ${hint}`;
|
|
2921
|
-
}
|
|
2922
|
-
function reject_extra_arguments(cmd, entry, extra) {
|
|
2923
|
-
if (extra.length === 0 || !is_composite_shell(entry.shell)) return void 0;
|
|
2924
|
-
return format_rejection(cmd, entry.argument_targets ?? []);
|
|
3128
|
+
function canonical_command(name) {
|
|
3129
|
+
if (!Object.hasOwn(ALIASES, name)) return name;
|
|
3130
|
+
return ALIASES[name] ?? name;
|
|
2925
3131
|
}
|
|
2926
|
-
var composite_arguments = { format_rejection, is_composite_shell, reject_extra_arguments };
|
|
2927
3132
|
|
|
2928
|
-
// scripts/josh/josh-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
var
|
|
2933
|
-
var
|
|
2934
|
-
var
|
|
2935
|
-
var
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
}
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
2965
|
-
|
|
3133
|
+
// scripts/josh/josh-usage-automation.ts
|
|
3134
|
+
var STAGED = "--staged";
|
|
3135
|
+
var JSON_FLAG = "--json";
|
|
3136
|
+
var BRANCH_DIFF = "the branch diff";
|
|
3137
|
+
var STAGED_DIFF = "the staged diff instead";
|
|
3138
|
+
var PR_NUMBER = "42";
|
|
3139
|
+
var DRY_RUN = "--dry-run";
|
|
3140
|
+
var SKIP_PUBLISH_WAIT = "--skip-publish-wait";
|
|
3141
|
+
var AUTOMATION_USAGE = {
|
|
3142
|
+
"refactor:scan": { examples: [{ arguments: "" }] },
|
|
3143
|
+
"time:density": {
|
|
3144
|
+
examples: [{ arguments: "" }, { arguments: "--lanes 5", note: "the five most recent lanes" }],
|
|
3145
|
+
flags: [
|
|
3146
|
+
{
|
|
3147
|
+
names: ["--lanes <n>"],
|
|
3148
|
+
description: "average over a different count of recent qualifying lanes (default 10)."
|
|
3149
|
+
},
|
|
3150
|
+
{
|
|
3151
|
+
names: ["--path <dir>"],
|
|
3152
|
+
description: "read another project's lane transcripts, as `josh time` does. Run it from the main checkout \u2014 a lane reads only its own transcript."
|
|
3153
|
+
}
|
|
3154
|
+
]
|
|
3155
|
+
},
|
|
3156
|
+
"e2e:retry-check": { examples: [{ arguments: "" }] },
|
|
3157
|
+
"sync:scope": {
|
|
3158
|
+
examples: [
|
|
3159
|
+
{ arguments: "", note: BRANCH_DIFF },
|
|
3160
|
+
{ arguments: STAGED, note: STAGED_DIFF },
|
|
3161
|
+
{ arguments: JSON_FLAG, note: '{"scope":"managed","reason":"..."}' }
|
|
3162
|
+
],
|
|
3163
|
+
flags: [
|
|
3164
|
+
{ names: [STAGED], description: "inspect the staged diff instead of the branch diff." },
|
|
3165
|
+
{ names: [JSON_FLAG], description: 'emit `{"scope","reason"}` as JSON.' }
|
|
3166
|
+
]
|
|
3167
|
+
},
|
|
3168
|
+
"dogfood:commit": { examples: [{ arguments: "~/Development/kit-test-html-start" }] },
|
|
3169
|
+
"fresh:run": {
|
|
3170
|
+
examples: [
|
|
3171
|
+
{ arguments: "--list", note: "kit's six patterns" },
|
|
3172
|
+
{ arguments: "kit-test-html-init", note: "one pattern, the packed checkout" },
|
|
3173
|
+
{
|
|
3174
|
+
arguments: "kit-test-html-start",
|
|
3175
|
+
note: "a GitHub pattern, the latest published version"
|
|
3176
|
+
},
|
|
3177
|
+
{ arguments: "--spec fresh/html-init.json", note: "a scenario another toolkit wrote" }
|
|
3178
|
+
],
|
|
3179
|
+
flags: [
|
|
3180
|
+
{ names: ["--list"], description: "print the pattern names and run nothing." },
|
|
3181
|
+
{
|
|
3182
|
+
names: ["--spec <file.json>"],
|
|
3183
|
+
description: "run the scenario in this file instead of a named pattern; the path is relative to the project root."
|
|
3184
|
+
},
|
|
3185
|
+
{
|
|
3186
|
+
names: ["--package-version <version>"],
|
|
3187
|
+
description: "the published version a `package_source: published` scenario installs. Default: the registry's latest version of the package the command is run from."
|
|
3188
|
+
},
|
|
3189
|
+
{
|
|
3190
|
+
names: ["--log-dir <dir>"],
|
|
3191
|
+
description: "where the log is written. Default: `.claude/tmp/fresh-machine`."
|
|
3192
|
+
},
|
|
3193
|
+
{ names: ["--rebuild"], description: "build the machine image without the layer cache." }
|
|
3194
|
+
]
|
|
3195
|
+
},
|
|
3196
|
+
"auth:setup": {
|
|
3197
|
+
examples: [
|
|
3198
|
+
{ arguments: "", note: "sign in and save the token" },
|
|
3199
|
+
{ arguments: "--check", note: "ok: \u2026 saved on <date>, or missing: \u2026 and exit 1" }
|
|
3200
|
+
]
|
|
3201
|
+
},
|
|
3202
|
+
"sonar:hotspots": { examples: [{ arguments: PR_NUMBER }] },
|
|
3203
|
+
"sonar:new-code": { examples: [{ arguments: PR_NUMBER }] },
|
|
3204
|
+
"ui:routes": {
|
|
3205
|
+
examples: [
|
|
3206
|
+
{ arguments: "", note: BRANCH_DIFF },
|
|
3207
|
+
{ arguments: STAGED, note: STAGED_DIFF }
|
|
3208
|
+
]
|
|
3209
|
+
},
|
|
3210
|
+
propagate: {
|
|
3211
|
+
examples: [
|
|
3212
|
+
{ arguments: "" },
|
|
3213
|
+
{ arguments: DRY_RUN, note: "report targets and steps, write nothing" },
|
|
3214
|
+
{ arguments: SKIP_PUBLISH_WAIT, note: "release already known to be published" },
|
|
3215
|
+
{ arguments: "--target app-kit", note: "carry the release into one consumer only" }
|
|
3216
|
+
],
|
|
3217
|
+
flags: [
|
|
3218
|
+
{
|
|
3219
|
+
names: [DRY_RUN],
|
|
3220
|
+
description: "report targets and steps without writing; skips the publish wait, opens no issues."
|
|
3221
|
+
},
|
|
3222
|
+
{
|
|
3223
|
+
names: [SKIP_PUBLISH_WAIT],
|
|
3224
|
+
description: "skip the registry poll for an already-published release."
|
|
3225
|
+
},
|
|
3226
|
+
{
|
|
3227
|
+
names: ["--target <repo>"],
|
|
3228
|
+
description: "process only that consumer (`app-kit` or `joshuafolkken/app-kit`); the rest are reported `skipped` and left untouched. An unknown, ambiguous or non-dependent name fails before the publish wait, writing nothing."
|
|
3229
|
+
}
|
|
3230
|
+
]
|
|
3231
|
+
},
|
|
3232
|
+
"repo:party": {
|
|
3233
|
+
examples: [
|
|
3234
|
+
{ arguments: "joshuafolkken/kit", note: "\u2192 first-party (in the kit session)" },
|
|
3235
|
+
{ arguments: "sveltejs/kit", note: "\u2192 third-party" },
|
|
3236
|
+
{ arguments: "", note: "no argument: the session's own repository" }
|
|
3237
|
+
]
|
|
3238
|
+
}
|
|
3239
|
+
};
|
|
3240
|
+
|
|
3241
|
+
// scripts/josh/josh-usage-backlog.ts
|
|
3242
|
+
var EXCLUDE = "--exclude <N>";
|
|
3243
|
+
var BUDGET = '--answer candidates --started "$started" --active "$active"';
|
|
3244
|
+
var REPO = "--repo <owner/repo>";
|
|
3245
|
+
var JUST_MERGED = "skip the issue just merged";
|
|
3246
|
+
var EXCLUDE_1630 = "--exclude 1630";
|
|
3247
|
+
var BACKLOG_USAGE = {
|
|
3248
|
+
epic: {
|
|
3249
|
+
examples: [
|
|
3250
|
+
{ arguments: '"Epic: split the parser work" 101 102 103' },
|
|
3251
|
+
{ arguments: '"Epic: staged rollout" 101 102 --ordered' },
|
|
3252
|
+
{ arguments: '"Epic: ..." 101 102 --rationale-file rationale.md' },
|
|
3253
|
+
{ arguments: "--promote 858 101 102 103", note: "turn an existing issue into an epic" },
|
|
3254
|
+
{ arguments: "--add 893 894", note: "track #894, declaring no order for it" },
|
|
3255
|
+
{ arguments: "--add 893 894 --before 891", note: "#894 must finish before #891" },
|
|
3256
|
+
{ arguments: "--add 893 894 --after 890", note: "#894 starts once #890 is done" },
|
|
3257
|
+
{ arguments: "--add 893 894 --decision-file why.md", note: "\u2026and record why, in one call" },
|
|
3258
|
+
{
|
|
3259
|
+
arguments: "--reconcile 2184",
|
|
3260
|
+
note: "rewrite the body to match the recorded blocked-by, and record any order the body declared"
|
|
3261
|
+
}
|
|
3262
|
+
],
|
|
3263
|
+
flags: [
|
|
3264
|
+
{
|
|
3265
|
+
names: ["--ordered"],
|
|
3266
|
+
description: "argument order is the dependency order; writes the arrow chain, records the matching `blocked-by` relations, and adds a `### Declared order` entry under `## Decisions`."
|
|
3267
|
+
},
|
|
3268
|
+
{
|
|
3269
|
+
names: ["--rationale-file <path|->"],
|
|
3270
|
+
description: "split rationale prose (`-` reads stdin)."
|
|
3271
|
+
},
|
|
3272
|
+
{
|
|
3273
|
+
names: ["--origin <owner/repo#N>"],
|
|
3274
|
+
description: "backlink when the split originated in another repository."
|
|
3275
|
+
},
|
|
3276
|
+
{
|
|
3277
|
+
names: ["--before <M>"],
|
|
3278
|
+
description: "with `--add`: insert before `#M`, re-pointing what `#M` was waiting on so the chain is never broken."
|
|
3279
|
+
},
|
|
3280
|
+
{
|
|
3281
|
+
names: ["--after <M>"],
|
|
3282
|
+
description: "with `--add`: start after `#M`; branches when `#M` already has a successor, extends when it is a tail."
|
|
3283
|
+
},
|
|
3284
|
+
{
|
|
3285
|
+
names: ["--order-before <M>", "--order-after <M>"],
|
|
3286
|
+
description: "with `--add`: move the task-list row only; write no `blocked-by` relation."
|
|
3287
|
+
},
|
|
3288
|
+
{
|
|
3289
|
+
names: ["--decision-file <path|->"],
|
|
3290
|
+
description: "with `--add`: record why the child was placed."
|
|
3291
|
+
},
|
|
3292
|
+
{
|
|
3293
|
+
names: ["--remove <E> <M> <N> [<N2> \u2026]"],
|
|
3294
|
+
description: "delete a declared order from the body and the relations; each consecutive pair is one link."
|
|
3295
|
+
}
|
|
3296
|
+
]
|
|
3297
|
+
},
|
|
3298
|
+
"epic:next": {
|
|
3299
|
+
examples: [
|
|
3300
|
+
{ arguments: "858" },
|
|
3301
|
+
{ arguments: "858 --repo joshuafolkken/kit", note: "just the next child for one repository" },
|
|
3302
|
+
{ arguments: "858 --repo joshuafolkken/kit --lanes", note: "one child per free lane there" }
|
|
3303
|
+
],
|
|
3304
|
+
flags: [
|
|
3305
|
+
{
|
|
3306
|
+
names: [REPO],
|
|
3307
|
+
description: "answer for one repository; stdout carries one token (an issue number, or `wait`/`stop`/`complete`), everything else on stderr."
|
|
3308
|
+
},
|
|
3309
|
+
{
|
|
3310
|
+
names: ["--lanes"],
|
|
3311
|
+
description: "print one issue number per free lane (requires `--repo`); `JOSH_LANE_LIMIT` sets the ceiling, default 4. Prints `triage` instead while any candidate carries neither `run:solo` nor `run:lane` (the triage gate in `josh backlog:next`)."
|
|
3312
|
+
}
|
|
3313
|
+
]
|
|
3314
|
+
},
|
|
3315
|
+
"epic:bundle": { examples: [{ arguments: "874" }] },
|
|
3316
|
+
"epic:audit": { examples: [{ arguments: "858" }] },
|
|
3317
|
+
"epic:check": { examples: [{ arguments: "700" }] },
|
|
3318
|
+
"auto-ok:next": {
|
|
3319
|
+
examples: [{ arguments: "" }, { arguments: "--exclude 906", note: JUST_MERGED }],
|
|
3320
|
+
flags: [
|
|
3321
|
+
{
|
|
3322
|
+
names: [EXCLUDE],
|
|
3323
|
+
description: "drop issues from the answer; comma-separated, repeatable."
|
|
3324
|
+
}
|
|
3325
|
+
]
|
|
3326
|
+
},
|
|
3327
|
+
"auto-ok:judge": {
|
|
3328
|
+
examples: [
|
|
3329
|
+
{ arguments: "", note: "the issues that still owe a judgement" },
|
|
3330
|
+
{ arguments: "--apply 912 --lane", note: "opt it in, with its run label" },
|
|
3331
|
+
{ arguments: '--decline 913 --reason "<why>"', note: "record why it stays out" }
|
|
3332
|
+
],
|
|
3333
|
+
flags: [
|
|
3334
|
+
{
|
|
3335
|
+
names: ["--apply <N> --lane|--solo"],
|
|
3336
|
+
description: "checks the exclusions again against the labels as they stand, applies the run label and then `auto-ok`, and notes it on the progress board."
|
|
3337
|
+
},
|
|
3338
|
+
{ names: ["--decline <N> --reason <text>"], description: "applies nothing." }
|
|
3339
|
+
]
|
|
3340
|
+
},
|
|
3341
|
+
"backlog:next": {
|
|
3342
|
+
examples: [{ arguments: "" }, { arguments: EXCLUDE_1630, note: JUST_MERGED }],
|
|
3343
|
+
flags: [
|
|
3344
|
+
{
|
|
3345
|
+
names: [EXCLUDE],
|
|
3346
|
+
description: "drop issues from every bucket; comma-separated, repeatable."
|
|
3347
|
+
}
|
|
3348
|
+
]
|
|
3349
|
+
},
|
|
3350
|
+
"backlog:plan": {
|
|
3351
|
+
examples: [
|
|
3352
|
+
{ arguments: "" },
|
|
3353
|
+
{ arguments: EXCLUDE_1630, note: "after #1630 merged" },
|
|
3354
|
+
{ arguments: "--waves", note: "the run order, wave by wave" }
|
|
3355
|
+
],
|
|
3356
|
+
flags: [
|
|
3357
|
+
{ names: [EXCLUDE], description: "same exclusion as `backlog:next`." },
|
|
3358
|
+
{
|
|
3359
|
+
names: ["--waves"],
|
|
3360
|
+
description: "print the order the run takes, wave by wave, assuming each wave merges before the next. Read-only."
|
|
3361
|
+
}
|
|
3362
|
+
]
|
|
3363
|
+
},
|
|
3364
|
+
"backlog:stalled": { examples: [{ arguments: "" }] },
|
|
3365
|
+
"backlog:budget": {
|
|
3366
|
+
examples: [
|
|
3367
|
+
{ arguments: BUDGET },
|
|
3368
|
+
{ arguments: '--answer exhausted --started "$started" --active "$active" --idle 60' },
|
|
3369
|
+
{ arguments: `${BUDGET} --merged 3 --running 2 --max 5` }
|
|
3370
|
+
],
|
|
3371
|
+
flags: [
|
|
3372
|
+
{
|
|
3373
|
+
names: ["--answer <candidates|exhausted|blocked|parked|unreadable|untriaged>"],
|
|
3374
|
+
description: "`backlog:next`'s answer, mapped."
|
|
3375
|
+
},
|
|
3376
|
+
{
|
|
3377
|
+
names: ["--started", "--active"],
|
|
3378
|
+
description: "when the invocation began / when it last had work (required unless the watch is off)."
|
|
3379
|
+
},
|
|
3380
|
+
{
|
|
3381
|
+
names: ["--idle <minutes>"],
|
|
3382
|
+
description: "once nothing can proceed, keep polling this long, counted from `--active` (default 480, 8 hours; `--idle 0` turns the watch off)."
|
|
3383
|
+
},
|
|
3384
|
+
{
|
|
3385
|
+
names: ["--max <count>"],
|
|
3386
|
+
description: "issues one invocation may take (default unlimited); `--merged` and `--running` count against it."
|
|
3387
|
+
},
|
|
3388
|
+
{
|
|
3389
|
+
names: ["--json"],
|
|
3390
|
+
description: 'collapse verdict and reason into `{"budget": "<verdict>", "reason": "\u2026"}`.'
|
|
3391
|
+
}
|
|
3392
|
+
]
|
|
3393
|
+
},
|
|
3394
|
+
"backlog:offer": {
|
|
3395
|
+
examples: [{ arguments: '--started "$started" --active "$active" --running 2 --retries 1' }]
|
|
3396
|
+
},
|
|
3397
|
+
"backlog:drive": {
|
|
3398
|
+
examples: [{ arguments: '--owner "$PPID" [--max <n>] [--idle <minutes>] [--only]' }]
|
|
3399
|
+
}
|
|
3400
|
+
};
|
|
3401
|
+
|
|
3402
|
+
// scripts/josh/josh-usage-developer.ts
|
|
3403
|
+
var UNSEEDED = {};
|
|
3404
|
+
var NARROWED = { arguments: "scripts/thing.ts", note: "narrow by the given files instead" };
|
|
3405
|
+
var DEVELOPER_USAGE = {
|
|
3406
|
+
gate: {
|
|
3407
|
+
examples: [
|
|
3408
|
+
{ arguments: "" },
|
|
3409
|
+
{ arguments: "--verbose", note: "every check's output, passing ones included" },
|
|
3410
|
+
{ arguments: "--force", note: "re-run even on a tree already recorded green" },
|
|
3411
|
+
{ arguments: "--no-unit", note: "the static checks only (CI only)" }
|
|
3412
|
+
]
|
|
3413
|
+
},
|
|
3414
|
+
lint: { examples: [{ arguments: "" }] },
|
|
3415
|
+
"lint:related": { examples: [{ arguments: "" }, NARROWED] },
|
|
3416
|
+
lines: {
|
|
3417
|
+
examples: [{ arguments: "scripts/hooks/format-edited-file.ts scripts/josh/josh-logic.ts" }]
|
|
3418
|
+
},
|
|
3419
|
+
bytes: {
|
|
3420
|
+
examples: [
|
|
3421
|
+
{ arguments: "docs/josh-commands.md", note: "one document" },
|
|
3422
|
+
{ arguments: "", note: "scan: every budgeted document near its ceiling" }
|
|
3423
|
+
]
|
|
3424
|
+
},
|
|
3425
|
+
metrics: {
|
|
3426
|
+
examples: [
|
|
3427
|
+
{ arguments: "", note: "print the totals and check them against the merge-base's" },
|
|
3428
|
+
{ arguments: '--accept --reason "<why>"', note: "record this branch's growth and why" }
|
|
3429
|
+
]
|
|
3430
|
+
},
|
|
3431
|
+
format: { examples: [{ arguments: "" }] },
|
|
3432
|
+
"cspell:dot": { examples: [{ arguments: "", note: "includes dotfiles" }] },
|
|
3433
|
+
behavior: { examples: [{ arguments: "" }] },
|
|
3434
|
+
"exports:unused": { examples: [{ arguments: "" }] },
|
|
3435
|
+
"test:unit": { examples: [{ arguments: "" }] },
|
|
3436
|
+
"test:related": {
|
|
3437
|
+
examples: [
|
|
3438
|
+
{ arguments: "" },
|
|
3439
|
+
NARROWED,
|
|
3440
|
+
{ arguments: "--silent", note: "flags are forwarded to vitest" }
|
|
3441
|
+
]
|
|
3442
|
+
},
|
|
3443
|
+
"test:declared": {
|
|
3444
|
+
examples: [
|
|
3445
|
+
{ arguments: "" },
|
|
3446
|
+
{ arguments: "--match", note: "check Step 0 declarations on stdin" },
|
|
3447
|
+
{ arguments: "--help", note: "print usage, including the --match stdin form" }
|
|
3448
|
+
]
|
|
3449
|
+
},
|
|
3450
|
+
"test:e2e": { examples: [{ arguments: "" }] },
|
|
3451
|
+
test: { examples: [{ arguments: "" }] },
|
|
3452
|
+
check: { examples: [{ arguments: "" }] },
|
|
3453
|
+
port: {
|
|
3454
|
+
examples: [
|
|
3455
|
+
{
|
|
3456
|
+
arguments: "dev",
|
|
3457
|
+
note: `${String(ports.resolve_development_port(UNSEEDED))} with no seed set`
|
|
3458
|
+
},
|
|
3459
|
+
{
|
|
3460
|
+
arguments: "preview",
|
|
3461
|
+
note: `${String(ports.resolve_preview_port(UNSEEDED))} with no seed set`
|
|
3462
|
+
}
|
|
3463
|
+
]
|
|
3464
|
+
},
|
|
3465
|
+
profile: { examples: [{ arguments: "" }] },
|
|
3466
|
+
init: {
|
|
3467
|
+
examples: [
|
|
3468
|
+
{
|
|
3469
|
+
arguments: "",
|
|
3470
|
+
note: "create/merge config files, install and format (--no-install skips both, --dry-run only prints the plan)"
|
|
3471
|
+
}
|
|
3472
|
+
]
|
|
3473
|
+
},
|
|
3474
|
+
"registry:migrate": { examples: [{ arguments: "" }] },
|
|
3475
|
+
sync: { examples: [{ arguments: "", note: "overwrite managed files" }] },
|
|
3476
|
+
uninstall: {
|
|
3477
|
+
examples: [
|
|
3478
|
+
{ arguments: "", note: "show the plan, then ask" },
|
|
3479
|
+
{ arguments: "--yes", note: "remove without asking" }
|
|
3480
|
+
]
|
|
3481
|
+
},
|
|
3482
|
+
adopt: {
|
|
3483
|
+
examples: [
|
|
3484
|
+
{ arguments: "" },
|
|
3485
|
+
{ arguments: "--dry-run", note: "report the steps without touching anything" }
|
|
3486
|
+
],
|
|
3487
|
+
flags: [{ names: ["--dry-run"], description: "report the plan without writing." }]
|
|
3488
|
+
},
|
|
3489
|
+
git: {
|
|
3490
|
+
examples: [
|
|
3491
|
+
{ arguments: "", note: "interactive" },
|
|
3492
|
+
{ arguments: "-y", note: "unattended (no TTY required)" },
|
|
3493
|
+
{ arguments: '-y "title"', note: "set commit message prefix" },
|
|
3494
|
+
{ arguments: '-y "<title> #<N>"', note: "follow-up commit on the same branch" },
|
|
3495
|
+
{
|
|
3496
|
+
arguments: "-y --skip-commit --skip-push",
|
|
3497
|
+
note: "open the PR without committing/pushing"
|
|
3498
|
+
}
|
|
3499
|
+
],
|
|
3500
|
+
flags: [
|
|
3501
|
+
{
|
|
3502
|
+
names: ["-y", "--yes"],
|
|
3503
|
+
description: "run non-interactively; works without a TTY (agent or CI shell)."
|
|
3504
|
+
},
|
|
3505
|
+
{
|
|
3506
|
+
names: ["--skip-commit", "--skip-push"],
|
|
3507
|
+
description: "recover/open a PR without a new commit or push."
|
|
3508
|
+
}
|
|
3509
|
+
]
|
|
3510
|
+
},
|
|
3511
|
+
pr: { examples: [{ arguments: "", note: "open the PR for the current <N>-<slug> branch" }] },
|
|
3512
|
+
"review:findings": { examples: [{ arguments: "" }] },
|
|
3513
|
+
"main:sync": { examples: [{ arguments: "" }] },
|
|
3514
|
+
"main:merge": { examples: [{ arguments: "" }] },
|
|
3515
|
+
version: {
|
|
3516
|
+
examples: [
|
|
3517
|
+
{ arguments: "" },
|
|
3518
|
+
{
|
|
3519
|
+
arguments: "--upgrade",
|
|
3520
|
+
note: "upgrade global + project to latest, then re-run fix-gh-packages"
|
|
3521
|
+
}
|
|
3522
|
+
],
|
|
3523
|
+
flags: [
|
|
3524
|
+
{
|
|
3525
|
+
names: ["--upgrade"],
|
|
3526
|
+
description: "upgrade both the global install (`pnpm add -g`) and the project devDependency (`pnpm add -D` + `fix-gh-packages`); already-current or not-installed targets are skipped."
|
|
3527
|
+
}
|
|
3528
|
+
]
|
|
3529
|
+
},
|
|
3530
|
+
ranges: { examples: [{ arguments: "" }] },
|
|
3531
|
+
doctor: {
|
|
3532
|
+
examples: [
|
|
3533
|
+
{ arguments: "", note: "diagnose only" },
|
|
3534
|
+
{ arguments: "--fix", note: "reclaim the global josh by removing a stale kit shim" },
|
|
3535
|
+
{ arguments: "--ports", note: "also print the per-repository port-seed table" }
|
|
3536
|
+
],
|
|
3537
|
+
flags: [
|
|
3538
|
+
{
|
|
3539
|
+
names: ["--fix"],
|
|
3540
|
+
description: "remove a shadowing binary **only if it is a kit shim** (its body references `@joshuafolkken/kit` or the removed `install-bin` script); any other binary is left and reported for manual review. Also the one-shot recovery for an old project that re-created the global shim."
|
|
3541
|
+
},
|
|
3542
|
+
{ names: ["--ports"], description: "additionally print the port-seed table (see below)." }
|
|
3543
|
+
]
|
|
3544
|
+
},
|
|
3545
|
+
audit: { examples: [{ arguments: "" }] },
|
|
3546
|
+
overrides: {
|
|
3547
|
+
examples: [
|
|
3548
|
+
{ arguments: "", note: "verify overrides unchanged" },
|
|
3549
|
+
{ arguments: "--save", note: "snapshot current merged overrides" }
|
|
3550
|
+
],
|
|
3551
|
+
flags: [
|
|
3552
|
+
{
|
|
3553
|
+
names: ["--save"],
|
|
3554
|
+
description: "write the current merged overrides to `.overrides-snapshot.json` (gitignored); later runs compare against it and exit non-zero on any add, removal, or change."
|
|
3555
|
+
}
|
|
3556
|
+
]
|
|
3557
|
+
},
|
|
3558
|
+
backlogrun: {
|
|
3559
|
+
examples: [
|
|
3560
|
+
{ arguments: "", note: "start in Claude, then show the board" },
|
|
3561
|
+
{ arguments: "3437 --only", note: "the arguments go to backlogrun as typed" },
|
|
3562
|
+
{ arguments: "--agent codex", note: "start in Codex" },
|
|
3563
|
+
{ arguments: "--stop", note: "stop the run in this repository" }
|
|
3564
|
+
]
|
|
3565
|
+
},
|
|
3566
|
+
"lane:limit": {
|
|
3567
|
+
examples: [
|
|
3568
|
+
{ arguments: "8", note: "raise or lower the live run's limit to 8" },
|
|
3569
|
+
{ arguments: "", note: "print the limit, the lanes in use and the free lanes" },
|
|
3570
|
+
{ arguments: "--reset", note: "clear the override; JOSH_LANE_LIMIT applies again" }
|
|
3571
|
+
]
|
|
3572
|
+
},
|
|
3573
|
+
"lane:withdraw": {
|
|
3574
|
+
examples: [{ arguments: '3769 --reason "folded into a broader issue"' }]
|
|
3575
|
+
},
|
|
3576
|
+
"test:red": { examples: [{ arguments: "", note: "red, green, no-test or test-only" }] },
|
|
3577
|
+
start: {
|
|
3578
|
+
examples: [
|
|
3579
|
+
{ arguments: "", note: "asks for the profile and the repository" },
|
|
3580
|
+
{
|
|
3581
|
+
arguments: "--yes --github --profile basic",
|
|
3582
|
+
note: "unattended, including the GitHub repository"
|
|
3583
|
+
}
|
|
3584
|
+
],
|
|
3585
|
+
flags: [
|
|
3586
|
+
{ names: ["--profile basic|full"], description: "the profile, without asking." },
|
|
3587
|
+
{ names: ["--yes"], description: "take the defaults \u2014 not consent to write to GitHub." },
|
|
3588
|
+
{ names: ["--github"], description: "create the GitHub repository and push `main`." },
|
|
3589
|
+
{ names: ["--public"], description: "create the repository public instead of private." },
|
|
3590
|
+
{
|
|
3591
|
+
names: ['--init-command "<command>"'],
|
|
3592
|
+
description: "run this setup command in place of `josh init`."
|
|
3593
|
+
},
|
|
3594
|
+
{
|
|
3595
|
+
names: ['--push-preflight-command "<command>"'],
|
|
3596
|
+
description: "a check run before the first step when the plan pushes; a failure stops the run before it writes anything."
|
|
3597
|
+
},
|
|
3598
|
+
{ names: ["--dry-run"], description: "print the plan and change nothing." }
|
|
3599
|
+
]
|
|
3600
|
+
},
|
|
3601
|
+
latest: { examples: [{ arguments: "", note: "full update (update + audit + pnpm)" }] },
|
|
3602
|
+
"latest:corepack": { examples: [{ arguments: "", note: "update pnpm only" }] },
|
|
3603
|
+
"latest:update": { examples: [{ arguments: "", note: "update dependencies only" }] },
|
|
3604
|
+
"lane:restart": {
|
|
3605
|
+
examples: [{ arguments: "3769", note: "prints the fresh child's pid" }]
|
|
3606
|
+
},
|
|
3607
|
+
"rule:value": {
|
|
3608
|
+
examples: [
|
|
3609
|
+
{ arguments: "" },
|
|
3610
|
+
{
|
|
3611
|
+
arguments: "--refresh",
|
|
3612
|
+
note: "write the reading to the loop-head cache instead of stdout"
|
|
3613
|
+
}
|
|
3614
|
+
]
|
|
3615
|
+
}
|
|
3616
|
+
};
|
|
3617
|
+
|
|
3618
|
+
// scripts/josh/josh-usage-hooks.ts
|
|
3619
|
+
var PRE_TOOL_USE = "run by the PreToolUse hook, the pending tool call as JSON on stdin";
|
|
3620
|
+
var IN_PRETOOL_GUARD = "run inside pretool:guard, not wired on its own";
|
|
3621
|
+
var HOOK_USAGE = {
|
|
3622
|
+
"format:edited": {
|
|
3623
|
+
examples: [
|
|
3624
|
+
{ arguments: "", note: "run by the PostToolUse hook, the tool call as JSON on stdin" }
|
|
3625
|
+
]
|
|
3626
|
+
},
|
|
3627
|
+
"batch:guard": { examples: [{ arguments: "", note: IN_PRETOOL_GUARD }] },
|
|
3628
|
+
"investigation:guard": { examples: [{ arguments: "", note: PRE_TOOL_USE }] },
|
|
3629
|
+
"duplicate-read:guard": { examples: [{ arguments: "", note: IN_PRETOOL_GUARD }] },
|
|
3630
|
+
"rule:guard": { examples: [{ arguments: "", note: PRE_TOOL_USE }] },
|
|
3631
|
+
"rule:list": { examples: [{ arguments: "", note: "print every trigger-delivered rule" }] },
|
|
3632
|
+
"pretool:guard": { examples: [{ arguments: "", note: PRE_TOOL_USE }] },
|
|
3633
|
+
"codex:hook-adapter": {
|
|
3634
|
+
examples: [
|
|
3635
|
+
{ arguments: "pretool", note: "a Codex PreToolUse payload on stdin" },
|
|
3636
|
+
{ arguments: "posttool", note: "a Codex PostToolUse payload on stdin" }
|
|
3637
|
+
]
|
|
3638
|
+
},
|
|
3639
|
+
"stop:guard": {
|
|
3640
|
+
examples: [{ arguments: "", note: "run by the Stop hook, the stop payload as JSON on stdin" }]
|
|
3641
|
+
},
|
|
3642
|
+
"session:lang": {
|
|
3643
|
+
examples: [{ arguments: "", note: "run by the UserPromptSubmit hook; `ja` prints nothing" }]
|
|
3644
|
+
}
|
|
3645
|
+
};
|
|
3646
|
+
|
|
3647
|
+
// scripts/josh/josh-usage-issue.ts
|
|
3648
|
+
var REPO2 = "--repo <owner/repo>";
|
|
3649
|
+
var BODY_FILE = "--body-file <path>";
|
|
3650
|
+
var CONCURRENT = "several numbers, read concurrently";
|
|
3651
|
+
var REPO_FLAG = {
|
|
3652
|
+
names: [REPO2],
|
|
3653
|
+
description: "read a child in another repository; applies to every number."
|
|
3654
|
+
};
|
|
3655
|
+
var JSON_FLAG2 = { names: ["--json"], description: "print the verdict and reason as JSON." };
|
|
3656
|
+
var ISSUE_USAGE = {
|
|
3657
|
+
"issue:read": {
|
|
3658
|
+
examples: [{ arguments: "1715" }, { arguments: "1715 1567 1605", note: CONCURRENT }]
|
|
3659
|
+
},
|
|
3660
|
+
"issue:ack": { examples: [{ arguments: "3773" }] },
|
|
3661
|
+
"issue:state": {
|
|
3662
|
+
examples: [
|
|
3663
|
+
{ arguments: "42", note: "single-number shape" },
|
|
3664
|
+
{ arguments: "42 43 44", note: "each block headed by `issue:`" },
|
|
3665
|
+
{ arguments: "42 43 --repo joshuafolkken/app-kit", note: "a child in another repo" }
|
|
3666
|
+
],
|
|
3667
|
+
flags: [REPO_FLAG]
|
|
3668
|
+
},
|
|
3669
|
+
"issue:release": {
|
|
3670
|
+
examples: [
|
|
3671
|
+
{ arguments: "3360" },
|
|
3672
|
+
{ arguments: "3716 --wait", note: "blocked by the release issue instead" }
|
|
3673
|
+
],
|
|
3674
|
+
flags: [
|
|
3675
|
+
{
|
|
3676
|
+
names: ["--wait"],
|
|
3677
|
+
description: "the issue is blocked by the release issue instead, so `backlog:next` offers it again once the release ships (`.claude/skills/workflow-commands/prerequisite.md`)."
|
|
3678
|
+
}
|
|
3679
|
+
]
|
|
3680
|
+
},
|
|
3681
|
+
"issue:scout": {
|
|
3682
|
+
examples: [
|
|
3683
|
+
{ arguments: '"Stop the gate re-running after every edit"' },
|
|
3684
|
+
{ arguments: '"<title>" --body "parent: #1246"' },
|
|
3685
|
+
{ arguments: '"<title>" --body-file draft.md' }
|
|
3686
|
+
],
|
|
3687
|
+
flags: [
|
|
3688
|
+
{
|
|
3689
|
+
names: ['--body "<text>"'],
|
|
3690
|
+
description: "supply references (`#N`) in a `parent: #N` line or an acceptance-criteria section so the epic half has a number to work from; without one there (a background mention does not count) it prints `Epic: not asked`."
|
|
3691
|
+
},
|
|
3692
|
+
{
|
|
3693
|
+
names: [BODY_FILE],
|
|
3694
|
+
description: 'pass the whole draft, including its purpose, requirements and acceptance criteria. A file that cannot be read ends the command rather than being treated as "no candidates".'
|
|
3695
|
+
}
|
|
3696
|
+
]
|
|
3697
|
+
},
|
|
3698
|
+
"issue:file": {
|
|
3699
|
+
examples: [
|
|
3700
|
+
{ arguments: '"<title>" --body-file body.md --depth 1' },
|
|
3701
|
+
{
|
|
3702
|
+
arguments: '"<title>" --body-file body.md --depth 0 --route tier-a --repo joshuafolkken/kit'
|
|
3703
|
+
},
|
|
3704
|
+
{ arguments: '"<title>" --body-file body.md --depth 1 --distinct 2801,2795' }
|
|
3705
|
+
],
|
|
3706
|
+
flags: [
|
|
3707
|
+
{ names: [BODY_FILE], description: "the body. Required." },
|
|
3708
|
+
{
|
|
3709
|
+
names: ["--depth <0|1|2>"],
|
|
3710
|
+
description: 'the depth label. Required. The criteria are `.claude/skills/workflow-commands/observation-filing.md` \u2192 "The depth test".'
|
|
3711
|
+
},
|
|
3712
|
+
{
|
|
3713
|
+
names: ["--route <tier-a|split|interrupt|review-cap>"],
|
|
3714
|
+
description: "the `route:` label naming the filing route. Omit it for a filing with no route."
|
|
3715
|
+
},
|
|
3716
|
+
{
|
|
3717
|
+
names: ["--label <name>"],
|
|
3718
|
+
description: "an extra label (for example `epic`). Repeatable."
|
|
3719
|
+
},
|
|
3720
|
+
{
|
|
3721
|
+
names: [REPO2],
|
|
3722
|
+
description: "the target repository. Defaults to this repository."
|
|
3723
|
+
},
|
|
3724
|
+
{
|
|
3725
|
+
names: ["--distinct <N,\u2026>"],
|
|
3726
|
+
description: "duplicate candidates you read and judged distinct."
|
|
3727
|
+
},
|
|
3728
|
+
{
|
|
3729
|
+
names: ["--over-cap"],
|
|
3730
|
+
description: "the run is blocked by this filing; the cap lets it through."
|
|
3731
|
+
},
|
|
3732
|
+
{
|
|
3733
|
+
names: ["--no-auto-ok"],
|
|
3734
|
+
description: "needs a person's judgement (Tier B / C); no `auto-ok`."
|
|
3735
|
+
},
|
|
3736
|
+
{
|
|
3737
|
+
names: ["--release"],
|
|
3738
|
+
description: "a consumer can use the change only once it is published. The filed issue becomes a blocker of the target's release issue (step 10)."
|
|
3739
|
+
}
|
|
3740
|
+
]
|
|
3741
|
+
},
|
|
3742
|
+
"issue:fold-existing": { examples: [{ arguments: "assessment.json --json" }] },
|
|
3743
|
+
"issue:fold": {
|
|
3744
|
+
examples: [
|
|
3745
|
+
{
|
|
3746
|
+
arguments: '"First finding" "Second finding"',
|
|
3747
|
+
note: "fold | separate | no-fold-needed | undetermined"
|
|
3748
|
+
},
|
|
3749
|
+
{ arguments: '"a" "b" --not-separable', note: "the pair is really one deliverable \u2192 fold" },
|
|
3750
|
+
{ arguments: '"a" "b" --json', note: "the verdict and reason, machine-readable" }
|
|
3751
|
+
],
|
|
3752
|
+
flags: [
|
|
3753
|
+
{
|
|
3754
|
+
names: ["--not-separable"],
|
|
3755
|
+
description: "declare the judgement half: the findings are one deliverable, so they fold whatever their size."
|
|
3756
|
+
},
|
|
3757
|
+
JSON_FLAG2
|
|
3758
|
+
]
|
|
3759
|
+
},
|
|
3760
|
+
"issue:cite": {
|
|
3761
|
+
examples: [
|
|
3762
|
+
{ arguments: "2220" },
|
|
3763
|
+
{ arguments: "2220 1758 1252", note: CONCURRENT },
|
|
3764
|
+
{ arguments: "45 --repo joshuafolkken/app-kit", note: "bare numbers in another repository" },
|
|
3765
|
+
{ arguments: "joshuafolkken/app-kit#45 2220", note: "per-token owner/repo#N notation" }
|
|
3766
|
+
],
|
|
3767
|
+
flags: [
|
|
3768
|
+
{
|
|
3769
|
+
names: [REPO2],
|
|
3770
|
+
description: "the repository for every bare number; a token written `owner/repo#N` overrides it for itself."
|
|
3771
|
+
}
|
|
3772
|
+
]
|
|
3773
|
+
},
|
|
3774
|
+
"issue:comment": {
|
|
3775
|
+
examples: [
|
|
3776
|
+
{
|
|
3777
|
+
arguments: "2304 --body-file .claude/tmp/park.md",
|
|
3778
|
+
note: "the body from a file \u2014 no shell evaluates it"
|
|
3779
|
+
},
|
|
3780
|
+
{
|
|
3781
|
+
arguments: '2304 --body "a short note"',
|
|
3782
|
+
note: "inline, for a body with no backticks or $"
|
|
3783
|
+
}
|
|
3784
|
+
],
|
|
3785
|
+
flags: [
|
|
3786
|
+
{
|
|
3787
|
+
names: ["--body <text>"],
|
|
3788
|
+
description: "the comment body, inline. Trimmed, with `\\n` expanded to a newline."
|
|
3789
|
+
},
|
|
3790
|
+
{
|
|
3791
|
+
names: [BODY_FILE],
|
|
3792
|
+
description: "read the body from a file, or from stdin with `-`. The safe form the rule steers every caller toward."
|
|
3793
|
+
}
|
|
3794
|
+
]
|
|
3795
|
+
},
|
|
3796
|
+
"pkg:scout": {
|
|
3797
|
+
examples: [{ arguments: '"date formatting" --size 5' }],
|
|
3798
|
+
flags: [
|
|
3799
|
+
{ names: ["--size <n>"], description: "how many candidates to fetch and rank (default 10)." }
|
|
3800
|
+
]
|
|
3801
|
+
},
|
|
3802
|
+
"issue:lint": { examples: [{ arguments: ".claude/tmp/issue-body.md" }] },
|
|
3803
|
+
"defect:rate": {
|
|
3804
|
+
examples: [{ arguments: "", note: "the last 14 days" }, { arguments: "--days 30" }],
|
|
3805
|
+
flags: [
|
|
3806
|
+
{
|
|
3807
|
+
names: ["--days <n>"],
|
|
3808
|
+
description: "the window in whole days (default 14, at most 3650). Anything else prints the usage and exits 1."
|
|
3809
|
+
}
|
|
3810
|
+
]
|
|
3811
|
+
},
|
|
3812
|
+
"issue:backlinks": { examples: [{ arguments: "2123" }] },
|
|
3813
|
+
"report:lint": { examples: [{ arguments: "< summary.md" }] },
|
|
3814
|
+
"stash:pop": {
|
|
3815
|
+
examples: [
|
|
3816
|
+
{ arguments: '"backlogrun: parked #2028"' },
|
|
3817
|
+
{
|
|
3818
|
+
arguments: '"backlogrun: josh latest before lanes" --dir "$dir"',
|
|
3819
|
+
note: "into a lane's work tree"
|
|
3820
|
+
}
|
|
3821
|
+
],
|
|
3822
|
+
flags: [
|
|
3823
|
+
{
|
|
3824
|
+
names: ["--dir <path>"],
|
|
3825
|
+
description: "applies the pop in that work tree (`git -C <path>`); without it the pop lands in the current checkout. The stack is shared, so it reads the same either way."
|
|
3826
|
+
}
|
|
3827
|
+
]
|
|
3828
|
+
}
|
|
3829
|
+
};
|
|
3830
|
+
|
|
3831
|
+
// scripts/josh/josh-usage-review.ts
|
|
3832
|
+
var MACHINE_READABLE = "the verdict and the reason, machine-readable";
|
|
3833
|
+
var LEVEL_ONLY = "--level-only";
|
|
3834
|
+
var JSON_FLAG3 = "--json";
|
|
3835
|
+
var CHECK = "--check";
|
|
3836
|
+
var ROUND_1_CLOSED = "--round-1-closed";
|
|
3837
|
+
var REVIEW_USAGE = {
|
|
3838
|
+
"review:brief": {
|
|
3839
|
+
examples: [
|
|
3840
|
+
{ arguments: "", note: "round 1" },
|
|
3841
|
+
{ arguments: "--round 2", note: "verification pass, scoped to the fix delta" },
|
|
3842
|
+
{ arguments: LEVEL_ONLY, note: "the level alone (pre-commit review)" },
|
|
3843
|
+
{ arguments: "--level-only --json", note: "level and reason, machine-readable" }
|
|
3844
|
+
],
|
|
3845
|
+
flags: [
|
|
3846
|
+
{
|
|
3847
|
+
names: ["--round 2"],
|
|
3848
|
+
description: "target is round 1's fixes and nothing else (widened back to the whole change when the record's change base no longer matches)."
|
|
3849
|
+
},
|
|
3850
|
+
{
|
|
3851
|
+
names: [LEVEL_ONLY],
|
|
3852
|
+
description: "print the level alone (level to stdout, reason to stderr); bypasses the scoped-green refusal."
|
|
3853
|
+
},
|
|
3854
|
+
{
|
|
3855
|
+
names: ["--staged", "--json"],
|
|
3856
|
+
description: "the staged diff; machine-readable level and reason."
|
|
3857
|
+
}
|
|
3858
|
+
]
|
|
3859
|
+
},
|
|
3860
|
+
"review:round2": {
|
|
3861
|
+
examples: [
|
|
3862
|
+
{ arguments: "", note: "\u2192 required" },
|
|
3863
|
+
{ arguments: ROUND_1_CLOSED, note: "\u2192 required | skip" },
|
|
3864
|
+
{ arguments: JSON_FLAG3, note: MACHINE_READABLE }
|
|
3865
|
+
],
|
|
3866
|
+
flags: [
|
|
3867
|
+
{
|
|
3868
|
+
names: [ROUND_1_CLOSED],
|
|
3869
|
+
description: "the caller states every round-1 High/Medium finding closed and none was filed or deferred; its absence answers `required`."
|
|
3870
|
+
},
|
|
3871
|
+
{ names: [JSON_FLAG3], description: "machine-readable verdict and reason." }
|
|
3872
|
+
]
|
|
3873
|
+
},
|
|
3874
|
+
disposition: { examples: [{ arguments: "<path...>", note: "\u2192 runtime | non-runtime" }] },
|
|
3875
|
+
"review:attest": {
|
|
3876
|
+
examples: [
|
|
3877
|
+
{ arguments: "<nonce>", note: "run by the review, from the checkout it read" },
|
|
3878
|
+
{ arguments: CHECK, note: "run by the run, before it acts on the review" }
|
|
3879
|
+
],
|
|
3880
|
+
flags: [
|
|
3881
|
+
{ names: ["<nonce>"], description: "attest the checkout the review read." },
|
|
3882
|
+
{
|
|
3883
|
+
names: [CHECK],
|
|
3884
|
+
description: "verify before acting; `josh followup` asks again before merging."
|
|
3885
|
+
}
|
|
3886
|
+
]
|
|
3887
|
+
},
|
|
3888
|
+
delegate: {
|
|
3889
|
+
examples: [
|
|
3890
|
+
{ arguments: "gate-fix", note: "\u2192 delegate" },
|
|
3891
|
+
{ arguments: "review", note: "\u2192 keep" },
|
|
3892
|
+
{ arguments: "--list", note: "the enumeration, and what was rejected and why" }
|
|
3893
|
+
]
|
|
3894
|
+
},
|
|
3895
|
+
fanout: {
|
|
3896
|
+
examples: [
|
|
3897
|
+
{ arguments: "scripts/a.ts,scripts/a.test.ts scripts/b.ts", note: "\u2192 parallel" },
|
|
3898
|
+
{
|
|
3899
|
+
arguments: "scripts/a.ts,shared.ts scripts/b.ts,shared.ts",
|
|
3900
|
+
note: "\u2192 serial (units share shared.ts)"
|
|
3901
|
+
},
|
|
3902
|
+
{ arguments: "scripts/a.ts", note: "\u2192 serial (fewer than two units)" }
|
|
3903
|
+
]
|
|
3904
|
+
},
|
|
3905
|
+
"split:assess": {
|
|
3906
|
+
examples: [
|
|
3907
|
+
{ arguments: "", note: "\u2192 single" },
|
|
3908
|
+
{ arguments: JSON_FLAG3, note: MACHINE_READABLE }
|
|
3909
|
+
]
|
|
3910
|
+
},
|
|
3911
|
+
"oracle:list": { examples: [{ arguments: "" }] },
|
|
3912
|
+
"clone:scan": { examples: [{ arguments: "" }] },
|
|
3913
|
+
cases: {
|
|
3914
|
+
examples: [
|
|
3915
|
+
{ arguments: "scripts/a.ts scripts/b.ts", note: "the boundaries these paths cross" }
|
|
3916
|
+
]
|
|
3917
|
+
}
|
|
3918
|
+
};
|
|
3919
|
+
|
|
3920
|
+
// scripts/josh/josh-usage-run.ts
|
|
3921
|
+
var ISSUE = { arguments: "<N>" };
|
|
3922
|
+
var OUTPUT = "--output <path>";
|
|
3923
|
+
var OWNER = "--owner <pid>";
|
|
3924
|
+
var REPO_FLAG2 = { names: ["--repo <owner/name>"], description: "a child in another repository." };
|
|
3925
|
+
var RUN_USAGE = {
|
|
3926
|
+
"run:hold": {
|
|
3927
|
+
examples: [
|
|
3928
|
+
{ arguments: "1091", note: "claim for issue 1091" },
|
|
3929
|
+
{ arguments: "1091 --fullrun", note: "claim as `fullrun #1091` (what `run:entry` runs)" }
|
|
3930
|
+
],
|
|
3931
|
+
flags: [
|
|
3932
|
+
{ names: ["--fullrun"], description: "marks the record as `fullrun #N`'s." },
|
|
3933
|
+
{
|
|
3934
|
+
names: ["--halfrun-stop"],
|
|
3935
|
+
description: "marks a `halfrun` stop for `run:entry` to adopt."
|
|
3936
|
+
},
|
|
3937
|
+
{
|
|
3938
|
+
names: ["--prrun-stop"],
|
|
3939
|
+
description: "marks a `prrun` stop with the commit its pull request is on."
|
|
3940
|
+
}
|
|
3941
|
+
]
|
|
3942
|
+
},
|
|
3943
|
+
"run:release": {
|
|
3944
|
+
examples: [
|
|
3945
|
+
{ arguments: "1091", note: "release this run's own record" },
|
|
3946
|
+
{ arguments: "--force", note: "clear a record left by a run that has ended" }
|
|
3947
|
+
],
|
|
3948
|
+
flags: [
|
|
3949
|
+
{
|
|
3950
|
+
names: ["--force"],
|
|
3951
|
+
description: "removes a record this run did not write, clearing another run's stale claim."
|
|
3952
|
+
}
|
|
3953
|
+
]
|
|
3954
|
+
},
|
|
3955
|
+
"run:tidy": { examples: [{ arguments: "" }] },
|
|
3956
|
+
"run:carry": {
|
|
3957
|
+
examples: [
|
|
3958
|
+
{ arguments: '--begin "backlogrun --max 5" --owner "$PPID"' },
|
|
3959
|
+
{ arguments: "--json", note: "read the record back in a resumed session" },
|
|
3960
|
+
{ arguments: '--cut --owner "$PPID"', note: "hand the record off before a cut" },
|
|
3961
|
+
{
|
|
3962
|
+
arguments: '--retrospective --summary "0 filed; dropped #2240 already merged" --owner "$PPID"',
|
|
3963
|
+
note: "close the end-of-run retrospective"
|
|
3964
|
+
},
|
|
3965
|
+
{
|
|
3966
|
+
arguments: '--resume "backlogrun --max 5" --owner "$PPID"',
|
|
3967
|
+
note: "adopt a record no cut handed off"
|
|
3968
|
+
},
|
|
3969
|
+
{
|
|
3970
|
+
arguments: '--end --stopped "epic #2126: everything is blocked behind parked #2118"',
|
|
3971
|
+
note: "end + push"
|
|
3972
|
+
}
|
|
3973
|
+
],
|
|
3974
|
+
flags: [
|
|
3975
|
+
{
|
|
3976
|
+
names: [OWNER],
|
|
3977
|
+
description: "the long-lived process spending the budget (`$PPID` under a loop); required by counts and `--begin` / `--resume`. A live PID stays `busy` if probes fail."
|
|
3978
|
+
},
|
|
3979
|
+
{ names: ["--done <issue>"], description: "shrinks a named-issue run's `remaining` list." },
|
|
3980
|
+
{
|
|
3981
|
+
names: ["--merged <issue>"],
|
|
3982
|
+
description: "names the merged issue and counts it once against `merged_issues`, so a merge `run:merge` already recorded is not counted twice."
|
|
3983
|
+
},
|
|
3984
|
+
{ names: ["--filed", "--cut"], description: "increments, never totals." },
|
|
3985
|
+
{
|
|
3986
|
+
names: ["--retrospective"],
|
|
3987
|
+
description: "marks the end-of-run retrospective run, once per invocation, and requires `--summary <text>` \u2014 the same close writes that result as one `retrospective` event on the run's event stream (best-effort), so a run that filed zero improvements reads apart from one whose retrospective never ran. Either flag without the other is refused."
|
|
3988
|
+
},
|
|
3989
|
+
{
|
|
3990
|
+
names: ["--stopped <reason>"],
|
|
3991
|
+
description: "rides on `--end`: the run stopped rather than finished, so one \u23F8\uFE0F confirmation is pushed with the reason."
|
|
3992
|
+
},
|
|
3993
|
+
{
|
|
3994
|
+
names: ["--end"],
|
|
3995
|
+
description: "over a live record flushes pending ledger lines once (a failed flush goes to stderr and the record is still cleared); first collects each lane the run launched whose issue merged, exactly as `run:merge` would; keeps the run it removes as the last ended run \u2014 its invocation, start and end, one record overwritten by the next `--end` \u2014 so `run:board` can still draw a finished run."
|
|
3996
|
+
}
|
|
3997
|
+
]
|
|
3998
|
+
},
|
|
3999
|
+
"run:add": {
|
|
4000
|
+
examples: [
|
|
4001
|
+
{ arguments: "101 102", note: "ahead of the rest of the queue (`#N` works too)" },
|
|
4002
|
+
{ arguments: "101 --no-priority", note: "at the end of the queue" }
|
|
4003
|
+
]
|
|
4004
|
+
},
|
|
4005
|
+
"run:wake": {
|
|
4006
|
+
examples: [
|
|
4007
|
+
{ arguments: "--start", note: "launch the detached supervisor" },
|
|
4008
|
+
{ arguments: "--list", note: "supervisor state, cut/wake counts, latest progress line" },
|
|
4009
|
+
{ arguments: "--stop", note: "stop the supervisor alone" },
|
|
4010
|
+
{ arguments: "--loop --interval 30", note: "run the loop body in the foreground" }
|
|
4011
|
+
]
|
|
4012
|
+
},
|
|
4013
|
+
"run:cut": {
|
|
4014
|
+
examples: [
|
|
4015
|
+
{ arguments: "1839", note: "take the cut and hand it to a fresh process" },
|
|
4016
|
+
{
|
|
4017
|
+
arguments: "--impl 1839 --handoff .claude/tmp/handoff-1839.json",
|
|
4018
|
+
note: "cut mid-implementation, carrying the instruction"
|
|
4019
|
+
},
|
|
4020
|
+
{ arguments: "--resume 1839", note: "a fresh process's entry check" },
|
|
4021
|
+
{ arguments: "--end", note: "clear the record" }
|
|
4022
|
+
]
|
|
4023
|
+
},
|
|
4024
|
+
"run:liveness": {
|
|
4025
|
+
examples: [
|
|
4026
|
+
{ arguments: "1169 --output <path>" },
|
|
4027
|
+
{ arguments: "1169 --output <path> --window 45 --gap 2 --repo joshuafolkken/app-kit" }
|
|
4028
|
+
],
|
|
4029
|
+
flags: [
|
|
4030
|
+
{
|
|
4031
|
+
names: [OUTPUT],
|
|
4032
|
+
description: "absolute, under the home or temp directory; a symlink is followed and size compared as well as mtime."
|
|
4033
|
+
},
|
|
4034
|
+
{
|
|
4035
|
+
names: ["--process alive | none"],
|
|
4036
|
+
description: "overrides the process trace, which the command otherwise reads itself: the child's own command line (`fullrun #<N>`) or its detached ship supervisor."
|
|
4037
|
+
},
|
|
4038
|
+
{
|
|
4039
|
+
names: ["--window <min>"],
|
|
4040
|
+
description: "silent window the file must be frozen for (default 30)."
|
|
4041
|
+
},
|
|
4042
|
+
{ names: ["--gap <sec>"], description: "spacing between samples (default 5)." },
|
|
4043
|
+
REPO_FLAG2
|
|
4044
|
+
]
|
|
4045
|
+
},
|
|
4046
|
+
"run:ending": {
|
|
4047
|
+
examples: [
|
|
4048
|
+
{ arguments: "2118 --output <path>" },
|
|
4049
|
+
{ arguments: "2118 --output <path> --repo joshuafolkken/app-kit" }
|
|
4050
|
+
],
|
|
4051
|
+
flags: [
|
|
4052
|
+
{
|
|
4053
|
+
names: [OUTPUT],
|
|
4054
|
+
description: "the child's transcript, absolute and under the home or temp directory (validated the same way `run:liveness --output` is)."
|
|
4055
|
+
},
|
|
4056
|
+
REPO_FLAG2
|
|
4057
|
+
]
|
|
4058
|
+
},
|
|
4059
|
+
"run:prep": { examples: [ISSUE] },
|
|
4060
|
+
"run:entry": {
|
|
4061
|
+
examples: [
|
|
4062
|
+
{ arguments: "<N>", note: "a `fullrun`" },
|
|
4063
|
+
{ arguments: "<N> --to halfrun", note: "a run that goes as far as `halfrun`" }
|
|
4064
|
+
]
|
|
4065
|
+
},
|
|
4066
|
+
"run:status": {
|
|
4067
|
+
examples: [ISSUE, { arguments: "<N> --repo <owner/repo>", note: "a cross-repo child" }]
|
|
4068
|
+
},
|
|
4069
|
+
"run:next": { examples: [ISSUE] },
|
|
4070
|
+
"run:step": {
|
|
4071
|
+
examples: [
|
|
4072
|
+
{ arguments: "<N>", note: "the run's next action for issue <N>" },
|
|
4073
|
+
{ arguments: "", note: "the `backlogrun` parent's next action" }
|
|
4074
|
+
]
|
|
4075
|
+
},
|
|
4076
|
+
"run:merge": {
|
|
4077
|
+
examples: [
|
|
4078
|
+
{
|
|
4079
|
+
arguments: '<N> --epic <E> --repo <owner/repo> --owner "$PPID" --output <path>',
|
|
4080
|
+
note: "prints the next child number, or a verdict"
|
|
4081
|
+
},
|
|
4082
|
+
{ arguments: '<N> --owner "$PPID"', note: "backlog offer (no epic)" }
|
|
4083
|
+
],
|
|
4084
|
+
flags: [
|
|
4085
|
+
{
|
|
4086
|
+
names: ["--epic <E>", "--repo <owner/repo>"],
|
|
4087
|
+
description: "offer the epic's next children; omit both for the opted-in backlog."
|
|
4088
|
+
},
|
|
4089
|
+
{
|
|
4090
|
+
names: [OWNER],
|
|
4091
|
+
description: "the parent's process, so the carry count respects the ownership guard."
|
|
4092
|
+
},
|
|
4093
|
+
{
|
|
4094
|
+
names: [OUTPUT],
|
|
4095
|
+
description: "the transcript the outage split reads; absent, it is off."
|
|
4096
|
+
}
|
|
4097
|
+
]
|
|
4098
|
+
},
|
|
4099
|
+
"run:review": {
|
|
4100
|
+
examples: [
|
|
4101
|
+
{
|
|
4102
|
+
arguments: "",
|
|
4103
|
+
note: "detach the gate, print the brief; then launch the /code-review subagent"
|
|
4104
|
+
},
|
|
4105
|
+
{ arguments: "--join", note: "after the review returns: join the gate, check its verdict" }
|
|
4106
|
+
]
|
|
4107
|
+
},
|
|
4108
|
+
"run:tail": {
|
|
4109
|
+
examples: [
|
|
4110
|
+
{ arguments: "<N>", note: "the closed issue" },
|
|
4111
|
+
{ arguments: "<N> <follow-up-N>", note: "and a follow-up filed this run" }
|
|
4112
|
+
]
|
|
4113
|
+
},
|
|
4114
|
+
ship: {
|
|
4115
|
+
examples: [
|
|
4116
|
+
{ arguments: '"<title> #<N>" --body-file <evidence.md>' },
|
|
4117
|
+
{ arguments: '"<title> #<N>" --review', note: "both review rounds inside the ship" },
|
|
4118
|
+
{ arguments: '--detach "<title> #<N>"', note: "hand the ship to a supervisor" },
|
|
4119
|
+
{ arguments: "--log <N>", note: "a detached ship's log" }
|
|
4120
|
+
],
|
|
4121
|
+
flags: [
|
|
4122
|
+
{
|
|
4123
|
+
names: ["--body-file <path>"],
|
|
4124
|
+
description: "the PR body carrying the live-execution evidence `followup` gates on; forwarded to `git -y` alone."
|
|
4125
|
+
},
|
|
4126
|
+
{ names: ["--notify-message <text>"], description: "forwarded to `followup` alone." },
|
|
4127
|
+
{
|
|
4128
|
+
names: ["--review"],
|
|
4129
|
+
description: "runs review round 1 beside the gate, and round 2 after the commit when `review:round2` requires it; a High or an unfixed Medium stops the ship."
|
|
4130
|
+
},
|
|
4131
|
+
{
|
|
4132
|
+
names: ["--detach"],
|
|
4133
|
+
description: "hands the ship to a supervisor (implied in a lane child); a stop emits `ship-stop` (`--log <N>`). The preflight, type check, unused exports, cspell and guard tests run before the hand-off; a stop returns to the same session."
|
|
4134
|
+
}
|
|
4135
|
+
]
|
|
4136
|
+
},
|
|
4137
|
+
"run:report": {
|
|
4138
|
+
examples: [{ arguments: "", note: "print the report; the same text josh notify sends" }]
|
|
4139
|
+
},
|
|
4140
|
+
"run:event": {
|
|
4141
|
+
examples: [
|
|
4142
|
+
{ arguments: "--append <kind> <text>", note: "append one event; prints its position" },
|
|
4143
|
+
{ arguments: "--from <position>", note: "every event after <position>, in order (JSON)" },
|
|
4144
|
+
{ arguments: "--follow <position>", note: "new events, waiting for one; position on stderr" },
|
|
4145
|
+
{ arguments: "--watch [<position>]", note: "every new event, rendered, until interrupted" },
|
|
4146
|
+
{ arguments: "--last", note: "the newest event alone" }
|
|
4147
|
+
]
|
|
4148
|
+
}
|
|
4149
|
+
};
|
|
4150
|
+
|
|
4151
|
+
// scripts/josh/josh-usage-session.ts
|
|
4152
|
+
var BARE = { arguments: "" };
|
|
4153
|
+
var PATH_DIR = "--path <dir>";
|
|
4154
|
+
var SESSION_USAGE = {
|
|
4155
|
+
"run:progress": {
|
|
4156
|
+
examples: [
|
|
4157
|
+
{ arguments: "--output <path>" },
|
|
4158
|
+
{ arguments: "--once", note: "five labelled lines now, whatever the clock says" },
|
|
4159
|
+
{ arguments: "--interval 20 --repo joshuafolkken/app-kit --hours 4" }
|
|
4160
|
+
],
|
|
4161
|
+
flags: [
|
|
4162
|
+
{
|
|
4163
|
+
names: ["--mark"],
|
|
4164
|
+
description: "record that a real report happened without printing a line (keeps the last line for `run:wake --list`)."
|
|
4165
|
+
},
|
|
4166
|
+
{
|
|
4167
|
+
names: ["--path"],
|
|
4168
|
+
description: 'print the ambient heartbeat log\'s path and exit. Every heartbeat line is mirrored there, so `tail -F "$(pnpm josh run:progress --path)"` follows the run across a `backlogrun` session cut. Reads no run state, so it answers in a lane child too.'
|
|
4169
|
+
},
|
|
4170
|
+
{
|
|
4171
|
+
names: ["--interval <min>"],
|
|
4172
|
+
description: "silence interval (default 20; also `JOSH_PROGRESS_INTERVAL_MINUTES`, then `josh.progress_interval_minutes`)."
|
|
4173
|
+
},
|
|
4174
|
+
{
|
|
4175
|
+
names: ["--wait"],
|
|
4176
|
+
description: "start once in the background: each report goes to the event stream and ambient log, never stdout; exits only on an arrival, `josh followup` ending the run, or `--hours`."
|
|
4177
|
+
},
|
|
4178
|
+
{
|
|
4179
|
+
names: ["--hours <n>"],
|
|
4180
|
+
description: "how long the watcher lives (default 8 with `--wait`, 1 otherwise)."
|
|
4181
|
+
},
|
|
4182
|
+
{ names: ["--repo <owner/name>"], description: "scopes the read." }
|
|
4183
|
+
]
|
|
4184
|
+
},
|
|
4185
|
+
"run:board": {
|
|
4186
|
+
examples: [
|
|
4187
|
+
{ arguments: "", note: "redraw until interrupted" },
|
|
4188
|
+
{ arguments: "--once", note: "one frame, then exit" },
|
|
4189
|
+
{ arguments: "--chat", note: "one frame for a chat, recorded as a progress report" },
|
|
4190
|
+
{
|
|
4191
|
+
arguments: "--every 5",
|
|
4192
|
+
note: "the --chat frame as a \u{1F4CA} Progress Telegram every 5 minutes, until the run ends"
|
|
4193
|
+
}
|
|
4194
|
+
],
|
|
4195
|
+
flags: [
|
|
4196
|
+
{
|
|
4197
|
+
names: ["--chat"],
|
|
4198
|
+
description: "answers a `backlogrun` progress question: the frame `--once` draws, with only `\u{1F9E0}` on the machine line and no escapes; it records the report as `run:progress --mark` does."
|
|
4199
|
+
},
|
|
4200
|
+
{
|
|
4201
|
+
names: ["--every <minutes>"],
|
|
4202
|
+
description: "sends the `--chat` frame as a `\u{1F4CA} Progress` Telegram now and every `<minutes>` until the run ends \u2014 only when a person asks for it."
|
|
4203
|
+
}
|
|
4204
|
+
]
|
|
4205
|
+
},
|
|
4206
|
+
"run:watcher:guard": { examples: [BARE] },
|
|
4207
|
+
"run:stranded": { examples: [BARE] },
|
|
4208
|
+
"lane:open": { examples: [{ arguments: "1490", note: "prints the lane directory on stdout" }] },
|
|
4209
|
+
"lane:close": {
|
|
4210
|
+
examples: [{ arguments: "1490" }, { arguments: "--all" }],
|
|
4211
|
+
flags: [{ names: ["--all"], description: "closes every lane." }]
|
|
4212
|
+
},
|
|
4213
|
+
"lane:list": { examples: [BARE] },
|
|
4214
|
+
"lane:prune": { examples: [BARE] },
|
|
4215
|
+
"lane:output": {
|
|
4216
|
+
examples: [
|
|
4217
|
+
{ arguments: "1713 /abs/path/to/agent-7.jsonl", note: "record it; prints the path back" },
|
|
4218
|
+
{ arguments: "1713", note: "read it; prints the path, or `none`" }
|
|
4219
|
+
]
|
|
4220
|
+
},
|
|
4221
|
+
"lane:dispatch": {
|
|
4222
|
+
examples: [
|
|
4223
|
+
{
|
|
4224
|
+
arguments: "1749",
|
|
4225
|
+
note: "prints the child's pid; a refusal is an empty capture and exit 1"
|
|
4226
|
+
}
|
|
4227
|
+
],
|
|
4228
|
+
flags: [
|
|
4229
|
+
{
|
|
4230
|
+
names: ["JOSH_{SCHEDULER,WORKER,REVIEWER}_MODEL"],
|
|
4231
|
+
description: "Claude Code role overrides; Anthropic defaults are respectively `claude-opus-5-5`, `claude-opus-5-5`, and `claude-opus-5-5`. Codex keeps its provider-specific model."
|
|
4232
|
+
},
|
|
4233
|
+
{
|
|
4234
|
+
names: ["JOSH_{SCHEDULER,WORKER,REVIEWER}_EFFORT"],
|
|
4235
|
+
description: "role effort overrides for either provider; defaults are `medium`, `medium`, and `high`."
|
|
4236
|
+
},
|
|
4237
|
+
{
|
|
4238
|
+
names: ["JOSH_REVIEWER_VERIFICATION_{MODEL,EFFORT}"],
|
|
4239
|
+
description: "review round 2 and later (the verification pass); Anthropic defaults are `claude-sonnet-5-5` / `high`, falling back to `JOSH_REVIEWER_*`."
|
|
4240
|
+
}
|
|
4241
|
+
]
|
|
4242
|
+
},
|
|
4243
|
+
"lane:await": {
|
|
4244
|
+
examples: [
|
|
4245
|
+
{ arguments: "1749 1750", note: "block until either lane completes" },
|
|
4246
|
+
{
|
|
4247
|
+
arguments: '1749 1750 --owner "$PPID"',
|
|
4248
|
+
note: "reclaim the carry record for a resumed conversation first"
|
|
4249
|
+
}
|
|
4250
|
+
]
|
|
4251
|
+
},
|
|
4252
|
+
"lane:launch": {
|
|
4253
|
+
examples: [
|
|
4254
|
+
{ arguments: "1749", note: "every lane after the first" },
|
|
4255
|
+
{
|
|
4256
|
+
arguments: '1749 --stash "backlogrun: josh latest before lanes"',
|
|
4257
|
+
note: "the first lane only"
|
|
4258
|
+
}
|
|
4259
|
+
]
|
|
4260
|
+
},
|
|
4261
|
+
"lane:sample": { examples: [{ arguments: "", note: "one machine-load reading" }] },
|
|
4262
|
+
"lane:stats": {
|
|
4263
|
+
examples: [{ arguments: "--period 7", note: "a 7-day period's stage medians and maxima" }]
|
|
4264
|
+
},
|
|
4265
|
+
cost: {
|
|
4266
|
+
examples: [
|
|
4267
|
+
{
|
|
4268
|
+
arguments: "--cut",
|
|
4269
|
+
note: "compare billed input per request with the shared 135,000 context-cut threshold"
|
|
4270
|
+
},
|
|
4271
|
+
{ arguments: "--over <tokens>", note: "compare with an explicit limit" },
|
|
4272
|
+
{ arguments: `--cut ${PATH_DIR}`, note: "Anthropic project or current OpenAI worktree" }
|
|
4273
|
+
],
|
|
4274
|
+
flags: [
|
|
4275
|
+
{
|
|
4276
|
+
names: [PATH_DIR],
|
|
4277
|
+
description: "selects another Anthropic project; OpenAI accepts only linked checkouts of the current project."
|
|
4278
|
+
}
|
|
4279
|
+
]
|
|
4280
|
+
},
|
|
4281
|
+
"doc:section": {
|
|
4282
|
+
examples: [
|
|
4283
|
+
{ arguments: '<file.md> "<heading>"' },
|
|
4284
|
+
{ arguments: 'backlogrun.md "The hand-off"' }
|
|
4285
|
+
]
|
|
4286
|
+
},
|
|
4287
|
+
"read:set": {
|
|
4288
|
+
examples: [
|
|
4289
|
+
{ arguments: "", note: "every entry point" },
|
|
4290
|
+
{ arguments: "backlogrun", note: "one of them" },
|
|
4291
|
+
{ arguments: "backlogrun --json" }
|
|
4292
|
+
]
|
|
4293
|
+
},
|
|
4294
|
+
"doc:read": {
|
|
4295
|
+
examples: [
|
|
4296
|
+
{ arguments: "CLAUDE.md", note: "under the cap: prints the document" },
|
|
4297
|
+
{ arguments: "backlogrun.md", note: "over the cap: prints a directive, no content" }
|
|
4298
|
+
]
|
|
4299
|
+
},
|
|
4300
|
+
"read:files": {
|
|
4301
|
+
examples: [
|
|
4302
|
+
{ arguments: "a.ts b.ts c.ts", note: "under the cap: prints each file under its own header" },
|
|
4303
|
+
{
|
|
4304
|
+
arguments: "a.ts big.ts",
|
|
4305
|
+
note: "over the cap: prints a directive to Read them in one turn, no content"
|
|
4306
|
+
}
|
|
4307
|
+
]
|
|
4308
|
+
},
|
|
4309
|
+
"edit:files": {
|
|
4310
|
+
examples: [
|
|
4311
|
+
{
|
|
4312
|
+
arguments: "plan.txt",
|
|
4313
|
+
note: "applies every block in the plan, one line per edit reporting the outcome"
|
|
4314
|
+
},
|
|
4315
|
+
{ arguments: "- <<'EDITS'", note: "plan from stdin, then EDITS" }
|
|
4316
|
+
]
|
|
4317
|
+
},
|
|
4318
|
+
time: {
|
|
4319
|
+
examples: [
|
|
4320
|
+
{ arguments: "", note: "the last run tree, wall clock and cost by role" },
|
|
4321
|
+
{ arguments: "--run", note: "the same run-tree scope, named explicitly" },
|
|
4322
|
+
{ arguments: "--json", note: "the same figures, machine-readable" },
|
|
4323
|
+
{ arguments: PATH_DIR, note: "read another project's transcripts from this checkout" }
|
|
4324
|
+
],
|
|
4325
|
+
flags: [
|
|
4326
|
+
{
|
|
4327
|
+
names: ["--run"],
|
|
4328
|
+
description: '(default) the whole run tree, wall clock led beside dollars. It is the only scope; any other flag is a usage error (exit 1). History: `docs/maintainers/josh-commands-run-rationale.md` \u2192 "`josh cost` and `josh time` lost their report scopes".'
|
|
4329
|
+
},
|
|
4330
|
+
{
|
|
4331
|
+
names: [PATH_DIR],
|
|
4332
|
+
description: "aim the read at another project (absolute path); keeps the `cwd` behavior when absent."
|
|
4333
|
+
},
|
|
4334
|
+
{ names: ["--json"], description: "the run tree, machine-readable." }
|
|
4335
|
+
]
|
|
4336
|
+
},
|
|
4337
|
+
"cost:audit": {
|
|
4338
|
+
examples: [
|
|
4339
|
+
{ arguments: "", note: "the last 7 days against the 7 before" },
|
|
4340
|
+
{ arguments: "--period 30", note: "the last 30 days against the 30 before" }
|
|
4341
|
+
],
|
|
4342
|
+
flags: [
|
|
4343
|
+
{
|
|
4344
|
+
names: ["--period <days>"],
|
|
4345
|
+
description: "the length of each period, a positive whole number of days (default 7)."
|
|
4346
|
+
}
|
|
4347
|
+
]
|
|
4348
|
+
},
|
|
4349
|
+
retrospective: {
|
|
4350
|
+
examples: [{ arguments: "", note: "the digest for the run this checkout carries" }]
|
|
4351
|
+
},
|
|
4352
|
+
eval: {
|
|
4353
|
+
examples: [
|
|
4354
|
+
{ arguments: "", note: "every scenario" },
|
|
4355
|
+
{ arguments: "consult-not-execute", note: "one scenario by name" }
|
|
4356
|
+
],
|
|
4357
|
+
flags: [
|
|
4358
|
+
{ names: ["JOSH_EVAL_MODEL"], description: "the model to run against (default `sonnet`)." },
|
|
4359
|
+
{
|
|
4360
|
+
names: ["JOSH_EVAL_CONCURRENCY"],
|
|
4361
|
+
description: "how many sessions run at once (default `5`); a non-positive-integer value is refused."
|
|
4362
|
+
}
|
|
4363
|
+
]
|
|
4364
|
+
}
|
|
4365
|
+
};
|
|
4366
|
+
|
|
4367
|
+
// scripts/josh/josh-usage-workflow.ts
|
|
4368
|
+
var PR_TITLE = '"PR title #N"';
|
|
4369
|
+
var ISSUE_URL = '--issue-url "https://..."';
|
|
4370
|
+
var REVIEW_ISSUE = "--issue 2325";
|
|
4371
|
+
var CHECK2 = "--check";
|
|
4372
|
+
var JSON_FLAG4 = "--json";
|
|
4373
|
+
var BODY_FILE_NOTE = "(`-` reads stdin); use this whenever the body carries a backtick or `$`. Passing both forms is refused.";
|
|
4374
|
+
var WORKFLOW_USAGE = {
|
|
4375
|
+
followup: {
|
|
4376
|
+
examples: [
|
|
4377
|
+
{ arguments: PR_TITLE, note: "merges (default)" },
|
|
4378
|
+
{ arguments: String.raw`${PR_TITLE} --notify-message "Implemented X:\n- change 1"` },
|
|
4379
|
+
{ arguments: `${PR_TITLE} --notify-message-file completion.md` },
|
|
4380
|
+
{ arguments: `${PR_TITLE} --ai-review-ignore-reason "false positive"` },
|
|
4381
|
+
{ arguments: `${PR_TITLE} --no-merge`, note: "do the work, leave the PR open" }
|
|
4382
|
+
],
|
|
4383
|
+
flags: [
|
|
4384
|
+
{
|
|
4385
|
+
names: ["--no-merge"],
|
|
4386
|
+
description: "do the follow-up work but do not merge; leaves the PR open (the only flag that stops the merge). `--merge` is a deprecated no-op. A PR already merged by hand skips the CI wait, the AI-review scan and the merge and runs only the post-merge tail; a completion report already on the Issue is not posted again."
|
|
4387
|
+
},
|
|
4388
|
+
{
|
|
4389
|
+
names: ["--notify-message"],
|
|
4390
|
+
description: "inline completion body; `\\n` expands to newlines."
|
|
4391
|
+
},
|
|
4392
|
+
{
|
|
4393
|
+
names: ["--notify-message-file"],
|
|
4394
|
+
description: `read the completion body from a file ${BODY_FILE_NOTE}`
|
|
4395
|
+
},
|
|
4396
|
+
{
|
|
4397
|
+
names: ["--ai-review-ignore-reason"],
|
|
4398
|
+
description: "reason to dismiss an AI-review finding."
|
|
4399
|
+
}
|
|
4400
|
+
]
|
|
4401
|
+
},
|
|
4402
|
+
notify: {
|
|
4403
|
+
examples: [
|
|
4404
|
+
{ arguments: String.raw`--task-type planning ${ISSUE_URL} --body="- bullet 1\n- bullet 2"` },
|
|
4405
|
+
{
|
|
4406
|
+
arguments: `--task-type confirmation ${ISSUE_URL} --body-file r.md --recommended "Go" --alternative "Wait"`
|
|
4407
|
+
}
|
|
4408
|
+
],
|
|
4409
|
+
flags: [
|
|
4410
|
+
{
|
|
4411
|
+
names: ["--task-type"],
|
|
4412
|
+
description: "one of `planning` \u{1F4CB}, `completion` \u2705, `failure` \u274C, `warning` \u26A0\uFE0F, `kickoff_retry` \u{1F504}, `confirmation` \u23F8\uFE0F. Do not send `completion` or `warning` by hand \u2014 `josh followup` sends them."
|
|
4413
|
+
},
|
|
4414
|
+
{
|
|
4415
|
+
names: ["--body", "--body=$'\u2026'"],
|
|
4416
|
+
description: "inline body; use `--body=$'\u2026'` when it starts with `-`."
|
|
4417
|
+
},
|
|
4418
|
+
{ names: ["--body-file"], description: `read the body from a file ${BODY_FILE_NOTE}` },
|
|
4419
|
+
{
|
|
4420
|
+
names: ["--repo-name", "--issue-url", "--pr-url"],
|
|
4421
|
+
description: "header repository, resolved in that order, then the working directory. The issue title is read from `--issue-url`."
|
|
4422
|
+
},
|
|
4423
|
+
{
|
|
4424
|
+
names: ["--recommended", "--alternative"],
|
|
4425
|
+
description: "the choices appended under `JOSH_SESSION_LANG` headings; `--recommended` is required for `confirmation`, `--alternative` is repeatable."
|
|
4426
|
+
}
|
|
4427
|
+
]
|
|
4428
|
+
},
|
|
4429
|
+
"observations:flush": { examples: [{ arguments: "" }] },
|
|
4430
|
+
"measure:rerun": { examples: [{ arguments: "2212" }] },
|
|
4431
|
+
"review:record": {
|
|
4432
|
+
examples: [
|
|
4433
|
+
{ arguments: `${REVIEW_ISSUE} bug-risks:medium:src/foo.ts:42 tests:low:a.test.ts` },
|
|
4434
|
+
{ arguments: REVIEW_ISSUE, note: "a zero-finding round \u2014 records one `none` line" },
|
|
4435
|
+
{
|
|
4436
|
+
arguments: `${REVIEW_ISSUE} --comment`,
|
|
4437
|
+
note: "a round that passed after the PR opened \u2014 an Issue comment, no append"
|
|
4438
|
+
},
|
|
4439
|
+
{ arguments: `${CHECK2} ${REVIEW_ISSUE}`, note: "the merge gate: was it recorded?" }
|
|
4440
|
+
]
|
|
4441
|
+
},
|
|
4442
|
+
bump: { examples: [{ arguments: "major" }, { arguments: "minor" }, { arguments: "patch" }] },
|
|
4443
|
+
release: {
|
|
4444
|
+
examples: [
|
|
4445
|
+
{ arguments: "" },
|
|
4446
|
+
{ arguments: "--dry-run", note: "count and report, write nothing" }
|
|
4447
|
+
],
|
|
4448
|
+
flags: [
|
|
4449
|
+
{
|
|
4450
|
+
names: ["--dry-run"],
|
|
4451
|
+
description: "count and report only; writes nothing, fetches nothing, and creates no work tree."
|
|
4452
|
+
},
|
|
4453
|
+
{
|
|
4454
|
+
names: ["--help", "-h"],
|
|
4455
|
+
description: "print the usage line and exit 0 without fetching or releasing. Any other argument is refused with the usage line and a non-zero exit, before anything is fetched."
|
|
4456
|
+
}
|
|
4457
|
+
]
|
|
4458
|
+
},
|
|
4459
|
+
"release:scope": {
|
|
4460
|
+
examples: [
|
|
4461
|
+
{ arguments: "", note: "\u2192 required | skip | unknown" },
|
|
4462
|
+
{ arguments: "--json", note: '{"scope":"\u2026","reason":"\u2026"} on one line' }
|
|
4463
|
+
]
|
|
4464
|
+
},
|
|
4465
|
+
"ruleset:check": {
|
|
4466
|
+
examples: [
|
|
4467
|
+
{ arguments: "", note: "report only" },
|
|
4468
|
+
{ arguments: "--apply", note: "add the missing checks to the existing rule" }
|
|
4469
|
+
],
|
|
4470
|
+
flags: [
|
|
4471
|
+
{
|
|
4472
|
+
names: ["--apply"],
|
|
4473
|
+
description: "append the missing checks to the ruleset's required-checks rule (or to the branch protection's contexts). It never creates a ruleset: with none, create one under Settings \u2192 Rules \u2192 Rulesets, then rerun. Writing a repository setting needs admin access, so only this flag writes \u2014 `josh sync` and `josh doctor` never do."
|
|
4474
|
+
}
|
|
4475
|
+
]
|
|
4476
|
+
},
|
|
4477
|
+
"audit:provision": {
|
|
4478
|
+
examples: [
|
|
4479
|
+
{ arguments: "", note: "no-op if a scanner is already present" },
|
|
4480
|
+
{ arguments: "--force", note: "ignore backoff, allow a longer download" }
|
|
4481
|
+
],
|
|
4482
|
+
flags: [
|
|
4483
|
+
{
|
|
4484
|
+
names: ["--force"],
|
|
4485
|
+
description: "ignore the 6-hour failure backoff and allow a longer download window; the command to run after fixing a network problem."
|
|
4486
|
+
}
|
|
4487
|
+
]
|
|
4488
|
+
},
|
|
4489
|
+
"reconcile-templates": {
|
|
4490
|
+
examples: [
|
|
4491
|
+
{ arguments: "", note: "regenerate copy templates + record tripwire hashes" },
|
|
4492
|
+
{ arguments: CHECK2, note: "verify templates are in sync; non-zero on drift" }
|
|
4493
|
+
],
|
|
4494
|
+
flags: [
|
|
4495
|
+
{
|
|
4496
|
+
names: [CHECK2],
|
|
4497
|
+
description: "verify only; exits non-zero on drift. A pre-commit hook runs this when a tracked source or copy template is staged."
|
|
4498
|
+
}
|
|
4499
|
+
]
|
|
4500
|
+
},
|
|
4501
|
+
"pre-push-unit": { examples: [{ arguments: "" }] },
|
|
4502
|
+
"reserved-run": {
|
|
4503
|
+
examples: [
|
|
4504
|
+
{ arguments: "2 -- pnpm install", note: "hold 2 cores while installing" },
|
|
4505
|
+
{ arguments: "1 -- pnpm josh audit", note: "hold 1 core while scanning" }
|
|
4506
|
+
]
|
|
4507
|
+
},
|
|
4508
|
+
"pre-commit-type-check": { examples: [{ arguments: "" }] },
|
|
4509
|
+
"pr:classification": {
|
|
4510
|
+
examples: [{ arguments: "", note: "run by CI on a pull request; fails without one label" }]
|
|
4511
|
+
},
|
|
4512
|
+
"observation:record": {
|
|
4513
|
+
examples: [
|
|
4514
|
+
{ arguments: "flaky-e2e d1 'tests/e2e/login.test.ts' 'times out on CI only'" },
|
|
4515
|
+
{
|
|
4516
|
+
arguments: "flaky-e2e d1 'src/app.ts' 'fails there too' --checkout ~/Development/app",
|
|
4517
|
+
note: "another repository's ledger"
|
|
4518
|
+
}
|
|
4519
|
+
],
|
|
4520
|
+
flags: [
|
|
4521
|
+
{
|
|
4522
|
+
names: ["--checkout <path>"],
|
|
4523
|
+
description: "count and append in that repository's `.josh/observations/` instead."
|
|
4524
|
+
}
|
|
4525
|
+
]
|
|
4526
|
+
},
|
|
4527
|
+
"release:github": {
|
|
4528
|
+
examples: [
|
|
4529
|
+
{ arguments: "", note: "run by CI with GH_TOKEN, RELEASE_TAG and GITHUB_REPOSITORY set" }
|
|
4530
|
+
]
|
|
4531
|
+
},
|
|
4532
|
+
"latest:scope": {
|
|
4533
|
+
examples: [
|
|
4534
|
+
{ arguments: "", note: "required or skip, the reason on stderr" },
|
|
4535
|
+
{ arguments: "--record", note: "note a finished josh latest run" },
|
|
4536
|
+
{ arguments: JSON_FLAG4, note: "the verdict and the reason as JSON" }
|
|
4537
|
+
],
|
|
4538
|
+
flags: [
|
|
4539
|
+
{ names: ["--record"], description: "write the completion record `josh latest` ends with." },
|
|
4540
|
+
{ names: [JSON_FLAG4], description: "emit the verdict and its reason as JSON." }
|
|
4541
|
+
]
|
|
4542
|
+
},
|
|
4543
|
+
"latest:guard": { examples: [{ arguments: "", note: "refuses inside a lane" }] },
|
|
4544
|
+
"prevent-main-commit": { examples: [{ arguments: "", note: "run by the pre-commit hook" }] },
|
|
4545
|
+
"check-commit-message": {
|
|
4546
|
+
examples: [{ arguments: ".git/COMMIT_EDITMSG", note: "run by the commit-msg hook" }]
|
|
4547
|
+
},
|
|
4548
|
+
"secretlint-scan": {
|
|
4549
|
+
examples: [{ arguments: "src/app.ts .env.example", note: "the staged paths" }]
|
|
4550
|
+
},
|
|
4551
|
+
"pre-commit-lint": {
|
|
4552
|
+
examples: [
|
|
4553
|
+
{ arguments: "cspell src/app.ts" },
|
|
4554
|
+
{ arguments: "prettier src/app.ts" },
|
|
4555
|
+
{ arguments: "eslint src/app.ts" }
|
|
4556
|
+
]
|
|
4557
|
+
}
|
|
4558
|
+
};
|
|
4559
|
+
|
|
4560
|
+
// scripts/josh/command-usage.ts
|
|
4561
|
+
var USAGE_PAGE_TABLES = {
|
|
4562
|
+
"docs/josh-commands.md": [DEVELOPER_USAGE],
|
|
4563
|
+
"docs/josh-commands-run.md": [RUN_USAGE, SESSION_USAGE],
|
|
4564
|
+
"docs/josh-commands-backlog.md": [ISSUE_USAGE, BACKLOG_USAGE, REVIEW_USAGE],
|
|
4565
|
+
"docs/josh-commands-automation.md": [AUTOMATION_USAGE, WORKFLOW_USAGE, HOOK_USAGE]
|
|
4566
|
+
};
|
|
4567
|
+
var COMMAND_USAGE = Object.fromEntries(
|
|
4568
|
+
Object.values(USAGE_PAGE_TABLES).flat().flatMap((table) => Object.entries(table))
|
|
4569
|
+
);
|
|
4570
|
+
var NOTE_GAP = 3;
|
|
4571
|
+
function usage_for(name) {
|
|
4572
|
+
return Object.hasOwn(COMMAND_USAGE, name) ? COMMAND_USAGE[name] : void 0;
|
|
4573
|
+
}
|
|
4574
|
+
function example_line(name, example) {
|
|
4575
|
+
const command = example.arguments ? `pnpm josh ${name} ${example.arguments}` : `pnpm josh ${name}`;
|
|
4576
|
+
return { command, note: example.note };
|
|
4577
|
+
}
|
|
4578
|
+
function format_examples(name, usage) {
|
|
4579
|
+
const lines = usage.examples.map((example) => example_line(name, example));
|
|
4580
|
+
const width = Math.max(...lines.map((line) => line.command.length)) + NOTE_GAP;
|
|
4581
|
+
const rendered = lines.map(
|
|
4582
|
+
(line) => line.note === void 0 ? line.command : `${line.command.padEnd(width)}# ${line.note}`
|
|
4583
|
+
);
|
|
4584
|
+
return ["```bash", ...rendered, "```"].join("\n");
|
|
4585
|
+
}
|
|
4586
|
+
function code_span(text) {
|
|
4587
|
+
return `\`${text}\``;
|
|
4588
|
+
}
|
|
4589
|
+
function format_flags(flags) {
|
|
4590
|
+
const items = flags.map(
|
|
4591
|
+
(flag) => `- ${flag.names.map((spelling) => code_span(spelling)).join(" / ")} \u2014 ${flag.description}`
|
|
4592
|
+
);
|
|
4593
|
+
return ["**Options:**", "", ...items].join("\n");
|
|
4594
|
+
}
|
|
4595
|
+
function format_usage(name) {
|
|
4596
|
+
const usage = usage_for(name);
|
|
4597
|
+
if (usage === void 0) return void 0;
|
|
4598
|
+
const flags = usage.flags === void 0 ? [] : [format_flags(usage.flags)];
|
|
4599
|
+
return [format_examples(name, usage), ...flags].join("\n\n");
|
|
4600
|
+
}
|
|
4601
|
+
function format_command_help(input) {
|
|
4602
|
+
const name = canonical_command(input);
|
|
4603
|
+
const entry = Object.hasOwn(COMMAND_MAP, name) ? COMMAND_MAP[name] : void 0;
|
|
4604
|
+
if (entry === void 0) return void 0;
|
|
4605
|
+
const [synopsis] = entry.reference;
|
|
4606
|
+
const head = synopsis ? `josh ${name} ${synopsis}` : `josh ${name}`;
|
|
4607
|
+
const usage = format_usage(name);
|
|
4608
|
+
return [head, "", entry.description, ...usage === void 0 ? [] : ["", usage]].join("\n");
|
|
4609
|
+
}
|
|
4610
|
+
function page_commands(page) {
|
|
4611
|
+
const tables = Object.hasOwn(USAGE_PAGE_TABLES, page) ? USAGE_PAGE_TABLES[page] : void 0;
|
|
4612
|
+
return (tables ?? []).flatMap((table) => Object.keys(table));
|
|
4613
|
+
}
|
|
4614
|
+
var command_usage = {
|
|
4615
|
+
USAGE_PAGES: Object.keys(USAGE_PAGE_TABLES),
|
|
4616
|
+
format_command_help,
|
|
4617
|
+
format_usage,
|
|
4618
|
+
page_commands
|
|
4619
|
+
};
|
|
4620
|
+
|
|
4621
|
+
// scripts/josh/josh-logic.ts
|
|
4622
|
+
import { existsSync as existsSync6, readFileSync as readFileSync5 } from "node:fs";
|
|
4623
|
+
import path15 from "node:path";
|
|
4624
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
4625
|
+
|
|
4626
|
+
// scripts/build/local-bin.ts
|
|
4627
|
+
import { existsSync as existsSync3, readFileSync as readFileSync4 } from "node:fs";
|
|
4628
|
+
import { createRequire } from "node:module";
|
|
4629
|
+
import path11 from "node:path";
|
|
4630
|
+
|
|
4631
|
+
// scripts/lib/ancestor-directories.ts
|
|
4632
|
+
import path10 from "node:path";
|
|
4633
|
+
var MAX_DEPTH = 64;
|
|
4634
|
+
function list(start_directory) {
|
|
4635
|
+
const directories = [];
|
|
4636
|
+
let current = path10.resolve(start_directory);
|
|
4637
|
+
while (directories.length < MAX_DEPTH && !directories.includes(current)) {
|
|
4638
|
+
directories.push(current);
|
|
4639
|
+
current = path10.dirname(current);
|
|
4640
|
+
}
|
|
4641
|
+
return directories;
|
|
4642
|
+
}
|
|
4643
|
+
function nearest(start_directory, is_match) {
|
|
4644
|
+
return list(start_directory).find((directory) => is_match(directory));
|
|
4645
|
+
}
|
|
4646
|
+
var ancestor_directories = { list, nearest };
|
|
4647
|
+
|
|
4648
|
+
// scripts/lib/schemas.ts
|
|
4649
|
+
import { z as z4 } from "zod";
|
|
4650
|
+
var overrides_snapshot_schema = z4.record(z4.string(), z4.string());
|
|
4651
|
+
var package_version_schema = z4.object({ version: z4.string() });
|
|
4652
|
+
var package_named_version_schema = z4.looseObject({ name: z4.string(), version: z4.string() });
|
|
4653
|
+
var package_with_version_schema = z4.looseObject({ version: z4.string() });
|
|
4654
|
+
var ls_global_dependency_schema = z4.looseObject({ version: z4.string() });
|
|
4655
|
+
var ls_global_dependencies_schema = z4.record(z4.string(), ls_global_dependency_schema).optional();
|
|
4656
|
+
var pnpm_ls_global_schema = z4.array(
|
|
4657
|
+
z4.looseObject({
|
|
4658
|
+
dependencies: ls_global_dependencies_schema
|
|
4659
|
+
})
|
|
4660
|
+
);
|
|
4661
|
+
var vscode_settings_schema = z4.record(z4.string(), z4.unknown());
|
|
4662
|
+
var with_scripts_schema = z4.looseObject({
|
|
4663
|
+
scripts: z4.record(z4.string(), z4.string()).optional()
|
|
4664
|
+
});
|
|
4665
|
+
var with_development_deps_schema = z4.looseObject({
|
|
4666
|
+
devDependencies: z4.record(z4.string(), z4.string()).optional()
|
|
4667
|
+
});
|
|
4668
|
+
var with_package_manager_schema = z4.looseObject({
|
|
4669
|
+
packageManager: z4.string().optional()
|
|
4670
|
+
});
|
|
4671
|
+
var with_development_engine_schema = z4.looseObject({
|
|
4672
|
+
devEngines: z4.record(z4.string(), z4.unknown()).optional()
|
|
4673
|
+
});
|
|
4674
|
+
var bin_entry_schema = z4.union([z4.string(), z4.record(z4.string(), z4.string())]).optional();
|
|
4675
|
+
var package_bin_schema = z4.looseObject({ bin: bin_entry_schema });
|
|
4676
|
+
var json_object_schema = z4.record(z4.string(), z4.unknown());
|
|
4677
|
+
var string_array_schema = z4.array(z4.string());
|
|
4678
|
+
var string_record_schema = z4.record(z4.string(), z4.string());
|
|
4679
|
+
|
|
4680
|
+
// scripts/build/local-bin.ts
|
|
4681
|
+
var NODE_MODULES2 = "node_modules";
|
|
4682
|
+
var BIN_DIR = ".bin";
|
|
4683
|
+
var WINDOWS_PLATFORM3 = "win32";
|
|
4684
|
+
var WINDOWS_SHIM_SUFFIX = ".cmd";
|
|
4685
|
+
var PACKAGE_JSON = "package.json";
|
|
4686
|
+
function resolve_local_bin(project_root, bin_name) {
|
|
4687
|
+
const shim = process.platform === WINDOWS_PLATFORM3 ? `${bin_name}${WINDOWS_SHIM_SUFFIX}` : bin_name;
|
|
4688
|
+
return path11.join(project_root, NODE_MODULES2, BIN_DIR, shim);
|
|
4689
|
+
}
|
|
4690
|
+
function read_bin_entry(manifest_path, package_name, bin_name) {
|
|
4691
|
+
const { bin } = package_bin_schema.parse(JSON.parse(readFileSync4(manifest_path, "utf8")));
|
|
4692
|
+
if (typeof bin === "string") return bin_name === path11.basename(package_name) ? bin : void 0;
|
|
4693
|
+
return bin?.[bin_name];
|
|
4694
|
+
}
|
|
4695
|
+
function resolve_package_bin(base_directory, package_name, bin_name) {
|
|
4696
|
+
try {
|
|
4697
|
+
const resolve_from = createRequire(path11.join(base_directory, PACKAGE_JSON));
|
|
4698
|
+
const manifest_path = resolve_from.resolve(`${package_name}/${PACKAGE_JSON}`);
|
|
4699
|
+
const bin_entry = read_bin_entry(manifest_path, package_name, bin_name);
|
|
4700
|
+
if (bin_entry === void 0) return void 0;
|
|
4701
|
+
const cli_entry = path11.join(path11.dirname(manifest_path), bin_entry);
|
|
4702
|
+
return existsSync3(cli_entry) ? cli_entry : void 0;
|
|
4703
|
+
} catch {
|
|
4704
|
+
return void 0;
|
|
4705
|
+
}
|
|
4706
|
+
}
|
|
4707
|
+
|
|
4708
|
+
// scripts/josh/josh-logic.ts
|
|
4709
|
+
import { execaSync as execaSync2 } from "execa";
|
|
4710
|
+
|
|
4711
|
+
// scripts/josh/command-suggest.ts
|
|
4712
|
+
var MAX_SUGGESTION_DISTANCE = 3;
|
|
4713
|
+
function at(values, index) {
|
|
4714
|
+
return values[index] ?? 0;
|
|
4715
|
+
}
|
|
4716
|
+
function fill_distance_row(source, target, row, previous) {
|
|
4717
|
+
const current = [row];
|
|
4718
|
+
for (let col = 1; col <= target.length; col++) {
|
|
4719
|
+
const cost = source[row - 1] === target[col - 1] ? 0 : 1;
|
|
4720
|
+
const deletion = at(previous, col) + 1;
|
|
4721
|
+
const insertion = at(current, col - 1) + 1;
|
|
4722
|
+
const substitution = at(previous, col - 1) + cost;
|
|
4723
|
+
current.push(Math.min(deletion, insertion, substitution));
|
|
4724
|
+
}
|
|
4725
|
+
return current;
|
|
4726
|
+
}
|
|
4727
|
+
function edit_distance(source, target) {
|
|
4728
|
+
let previous = Array.from({ length: target.length + 1 }, (_unused, index) => index);
|
|
4729
|
+
for (let row = 1; row <= source.length; row++) {
|
|
4730
|
+
previous = fill_distance_row(source, target, row, previous);
|
|
4731
|
+
}
|
|
4732
|
+
return at(previous, target.length);
|
|
4733
|
+
}
|
|
4734
|
+
function closest_command(input, commands) {
|
|
4735
|
+
const within = commands.map((command) => ({ command, distance: edit_distance(input, command) })).filter((scored) => scored.distance <= MAX_SUGGESTION_DISTANCE).toSorted((left, right) => left.distance - right.distance);
|
|
4736
|
+
return within[0]?.command;
|
|
4737
|
+
}
|
|
4738
|
+
var command_suggest = { closest_command, edit_distance };
|
|
4739
|
+
|
|
4740
|
+
// scripts/josh/josh-composite-arguments.ts
|
|
4741
|
+
var SHELL_INTERPRETERS = /* @__PURE__ */ new Set(["sh", "bash", "zsh", "dash"]);
|
|
4742
|
+
var SHELL_COMMAND_FLAG = "-c";
|
|
4743
|
+
var PATH_SEPARATOR = "/";
|
|
4744
|
+
var USAGE_ERROR_EXIT_CODE = 1;
|
|
4745
|
+
function is_shell_interpreter(executable) {
|
|
4746
|
+
return SHELL_INTERPRETERS.has(executable.split(PATH_SEPARATOR).at(-1) ?? executable);
|
|
4747
|
+
}
|
|
4748
|
+
function is_composite_shell(shell) {
|
|
4749
|
+
const [executable, flag] = shell ?? [];
|
|
4750
|
+
if (executable === void 0) return false;
|
|
4751
|
+
return is_shell_interpreter(executable) && flag === SHELL_COMMAND_FLAG;
|
|
4752
|
+
}
|
|
4753
|
+
function format_targets(targets) {
|
|
4754
|
+
return targets.map((target) => `josh ${target}`).join(" or ");
|
|
4755
|
+
}
|
|
4756
|
+
function format_rejection(cmd, targets) {
|
|
4757
|
+
const hint = targets.length > 0 ? `pass them to ${format_targets(targets)} instead` : "it runs a fixed sequence and forwards nothing";
|
|
4758
|
+
return `josh ${cmd} takes no extra arguments \u2014 ${hint}`;
|
|
4759
|
+
}
|
|
4760
|
+
function reject_extra_arguments(cmd, entry, extra) {
|
|
4761
|
+
if (extra.length === 0 || !is_composite_shell(entry.shell)) return void 0;
|
|
4762
|
+
return format_rejection(cmd, entry.argument_targets ?? []);
|
|
4763
|
+
}
|
|
4764
|
+
var composite_arguments = { format_rejection, is_composite_shell, reject_extra_arguments };
|
|
4765
|
+
|
|
4766
|
+
// scripts/josh/josh-in-process.ts
|
|
4767
|
+
import { realpathSync } from "node:fs";
|
|
4768
|
+
import path12 from "node:path";
|
|
4769
|
+
import { pathToFileURL } from "node:url";
|
|
4770
|
+
var TYPESCRIPT_EXTENSION = ".ts";
|
|
4771
|
+
var JAVASCRIPT_EXTENSION = ".js";
|
|
4772
|
+
var BUNDLED_COMMAND_DIRECTORY = path12.join("dist", "commands");
|
|
4773
|
+
var FAILURE_EXIT_CODE = 1;
|
|
4774
|
+
function is_typescript_dispatcher(dispatcher_url) {
|
|
4775
|
+
return dispatcher_url.endsWith(TYPESCRIPT_EXTENSION);
|
|
4776
|
+
}
|
|
4777
|
+
function bundled_script_path(package_directory, script) {
|
|
4778
|
+
const name = `${path12.basename(script, TYPESCRIPT_EXTENSION)}${JAVASCRIPT_EXTENSION}`;
|
|
4779
|
+
return path12.join(package_directory, BUNDLED_COMMAND_DIRECTORY, name);
|
|
4780
|
+
}
|
|
4781
|
+
function in_process_target(entry, package_directory, dispatcher_url) {
|
|
4782
|
+
if (entry.script === void 0 || entry.tsx_arguments !== void 0) return void 0;
|
|
4783
|
+
if (is_typescript_dispatcher(dispatcher_url)) return path12.join(package_directory, entry.script);
|
|
4784
|
+
return entry.is_bundled === true ? bundled_script_path(package_directory, entry.script) : void 0;
|
|
4785
|
+
}
|
|
4786
|
+
function read_exit_code() {
|
|
4787
|
+
const code = process.exitCode;
|
|
4788
|
+
return typeof code === "number" ? code : 0;
|
|
4789
|
+
}
|
|
4790
|
+
function resolve_real_path(script_path) {
|
|
4791
|
+
try {
|
|
4792
|
+
return realpathSync(script_path);
|
|
4793
|
+
} catch {
|
|
4794
|
+
return script_path;
|
|
4795
|
+
}
|
|
4796
|
+
}
|
|
4797
|
+
async function run_in_process(script_path, script_arguments) {
|
|
4798
|
+
const resolved_path = resolve_real_path(script_path);
|
|
4799
|
+
process.argv = [process.execPath, resolved_path, ...script_arguments];
|
|
4800
|
+
try {
|
|
4801
|
+
await import(pathToFileURL(resolved_path).href);
|
|
4802
|
+
} catch (error) {
|
|
4803
|
+
console.error(error);
|
|
2966
4804
|
return FAILURE_EXIT_CODE;
|
|
2967
4805
|
}
|
|
2968
4806
|
return read_exit_code();
|
|
@@ -2985,9 +4823,20 @@ var kit_only = {
|
|
|
2985
4823
|
notice: kit_only_notice
|
|
2986
4824
|
};
|
|
2987
4825
|
|
|
4826
|
+
// scripts/josh/package-directory.ts
|
|
4827
|
+
import { existsSync as existsSync4 } from "node:fs";
|
|
4828
|
+
import path13 from "node:path";
|
|
4829
|
+
var PACKAGE_JSON2 = "package.json";
|
|
4830
|
+
function find_package_directory(start_directory) {
|
|
4831
|
+
return ancestor_directories.nearest(
|
|
4832
|
+
start_directory,
|
|
4833
|
+
(directory) => existsSync4(path13.join(directory, PACKAGE_JSON2))
|
|
4834
|
+
) ?? start_directory;
|
|
4835
|
+
}
|
|
4836
|
+
|
|
2988
4837
|
// scripts/josh/run-github-prerequisite.ts
|
|
2989
|
-
import { existsSync as
|
|
2990
|
-
import
|
|
4838
|
+
import { existsSync as existsSync5 } from "node:fs";
|
|
4839
|
+
import path14 from "node:path";
|
|
2991
4840
|
|
|
2992
4841
|
// scripts/discovery/repo-origin.ts
|
|
2993
4842
|
var GITHUB_HOST = "github.com";
|
|
@@ -3096,7 +4945,7 @@ var GITHUB_RUN_COMMANDS = /* @__PURE__ */ new Set([
|
|
|
3096
4945
|
]);
|
|
3097
4946
|
function explanation(root, command) {
|
|
3098
4947
|
if (!GITHUB_RUN_COMMANDS.has(command)) return void 0;
|
|
3099
|
-
if (!
|
|
4948
|
+
if (!existsSync5(path14.join(root, ".git"))) {
|
|
3100
4949
|
return `${command} requires Git and a GitHub origin. Run git init and add a GitHub origin first.`;
|
|
3101
4950
|
}
|
|
3102
4951
|
const url = git_spawn_sync.origin_url(root);
|
|
@@ -3110,21 +4959,15 @@ var COLUMN_WIDTH = 26;
|
|
|
3110
4959
|
var ALIAS_PAD_WIDTH = 2;
|
|
3111
4960
|
var TSX_BIN = "tsx";
|
|
3112
4961
|
var TSX_PACKAGE = "tsx";
|
|
3113
|
-
var
|
|
4962
|
+
var PACKAGE_JSON3 = "package.json";
|
|
3114
4963
|
var UNKNOWN_COMMAND_EXIT_CODE = -1;
|
|
3115
|
-
|
|
3116
|
-
return ancestor_directories.nearest(
|
|
3117
|
-
start_directory,
|
|
3118
|
-
(directory) => existsSync4(path11.join(directory, PACKAGE_JSON2))
|
|
3119
|
-
) ?? start_directory;
|
|
3120
|
-
}
|
|
3121
|
-
var PACKAGE_DIR2 = find_package_directory(path11.dirname(fileURLToPath2(import.meta.url)));
|
|
4964
|
+
var PACKAGE_DIR2 = find_package_directory(path15.dirname(fileURLToPath2(import.meta.url)));
|
|
3122
4965
|
function resolve_tsx_executable() {
|
|
3123
4966
|
const candidates = [
|
|
3124
4967
|
resolve_local_bin(PACKAGE_DIR2, TSX_BIN),
|
|
3125
4968
|
resolve_local_bin(process.cwd(), TSX_BIN)
|
|
3126
4969
|
];
|
|
3127
|
-
return candidates.find(
|
|
4970
|
+
return candidates.find(existsSync6) ?? TSX_BIN;
|
|
3128
4971
|
}
|
|
3129
4972
|
function resolve_tsx_cli_entry() {
|
|
3130
4973
|
for (const base_directory of [PACKAGE_DIR2, process.cwd()]) {
|
|
@@ -3141,7 +4984,7 @@ function resolve_tsx_runner() {
|
|
|
3141
4984
|
return { executable: resolve_tsx_executable(), leading_arguments: [] };
|
|
3142
4985
|
}
|
|
3143
4986
|
function read_package_version() {
|
|
3144
|
-
const raw = readFileSync5(
|
|
4987
|
+
const raw = readFileSync5(path15.join(PACKAGE_DIR2, PACKAGE_JSON3), "utf8");
|
|
3145
4988
|
return package_version_schema.parse(JSON.parse(raw)).version;
|
|
3146
4989
|
}
|
|
3147
4990
|
var HEADER = `josh v${read_package_version()} \u2014 Joshua Folkken's dev toolkit`;
|
|
@@ -3228,7 +5071,7 @@ async function run_script_entry(entry, subcommand_arguments) {
|
|
|
3228
5071
|
const script_arguments = [...entry.default_script_arguments ?? [], ...subcommand_arguments];
|
|
3229
5072
|
const target = josh_in_process.in_process_target(entry, PACKAGE_DIR2, import.meta.url);
|
|
3230
5073
|
if (target !== void 0) return await josh_in_process.run_in_process(target, script_arguments);
|
|
3231
|
-
return spawn_script_entry(entry,
|
|
5074
|
+
return spawn_script_entry(entry, path15.join(PACKAGE_DIR2, entry.script ?? ""), script_arguments);
|
|
3232
5075
|
}
|
|
3233
5076
|
function github_prerequisite_exit(resolved, is_consumer) {
|
|
3234
5077
|
if (!is_consumer) return void 0;
|
|
@@ -3260,13 +5103,13 @@ async function run_entry(entry, subcommand_arguments) {
|
|
|
3260
5103
|
function declared(value) {
|
|
3261
5104
|
return typeof value === "function" ? value() : value;
|
|
3262
5105
|
}
|
|
3263
|
-
async function dispatch_entry(entry, subcommand_arguments) {
|
|
5106
|
+
async function dispatch_entry(command, entry, subcommand_arguments) {
|
|
3264
5107
|
const weight = declared(entry.core_weight);
|
|
3265
5108
|
if (weight === void 0) return await run_entry(entry, subcommand_arguments);
|
|
3266
5109
|
return await core_budget.with_command_reservation(
|
|
3267
5110
|
weight,
|
|
3268
5111
|
async () => await run_entry(entry, subcommand_arguments),
|
|
3269
|
-
{ memory_mb: declared(entry.memory_mb) }
|
|
5112
|
+
{ memory_mb: declared(entry.memory_mb), command }
|
|
3270
5113
|
);
|
|
3271
5114
|
}
|
|
3272
5115
|
async function run_command(cmd, subcommand_arguments, is_consumer = false) {
|
|
@@ -3275,7 +5118,7 @@ async function run_command(cmd, subcommand_arguments, is_consumer = false) {
|
|
|
3275
5118
|
if (!entry) return UNKNOWN_COMMAND_EXIT_CODE;
|
|
3276
5119
|
const early_exit = pre_dispatch_exit(resolved, entry, subcommand_arguments, is_consumer);
|
|
3277
5120
|
if (early_exit !== void 0) return early_exit;
|
|
3278
|
-
return await dispatch_entry(entry, subcommand_arguments);
|
|
5121
|
+
return await dispatch_entry(resolved, entry, subcommand_arguments);
|
|
3279
5122
|
}
|
|
3280
5123
|
var josh_logic = {
|
|
3281
5124
|
format_help,
|
|
@@ -3289,13 +5132,17 @@ var josh_logic = {
|
|
|
3289
5132
|
var ARGV_OFFSET = 2;
|
|
3290
5133
|
var HELP_COMMANDS = /* @__PURE__ */ new Set(["help", "--help", "-h"]);
|
|
3291
5134
|
var ALL_FLAG = "--all";
|
|
3292
|
-
function print_help(is_all, is_consumer) {
|
|
3293
|
-
console.info(josh_logic.format_help(is_all, is_consumer));
|
|
3294
|
-
}
|
|
3295
5135
|
function handle_unknown(cmd) {
|
|
3296
5136
|
console.error(josh_logic.format_unknown_command(cmd));
|
|
3297
5137
|
process.exit(1);
|
|
3298
5138
|
}
|
|
5139
|
+
function print_help(is_all, is_consumer, topic) {
|
|
5140
|
+
if (topic === void 0 || topic.startsWith("-")) {
|
|
5141
|
+
console.info(josh_logic.format_help(is_all, is_consumer));
|
|
5142
|
+
return;
|
|
5143
|
+
}
|
|
5144
|
+
console.info(command_usage.format_command_help(topic) ?? handle_unknown(topic));
|
|
5145
|
+
}
|
|
3299
5146
|
function record_exit_code(exit_code) {
|
|
3300
5147
|
if (exit_code !== 0) process.exitCode = exit_code;
|
|
3301
5148
|
}
|
|
@@ -3304,7 +5151,7 @@ async function main() {
|
|
|
3304
5151
|
const is_all = process.argv.includes(ALL_FLAG);
|
|
3305
5152
|
const is_consumer = doctor_consumer.is_kit_consumer(find_package_directory(process.cwd()));
|
|
3306
5153
|
if (!cmd || cmd === ALL_FLAG || HELP_COMMANDS.has(cmd)) {
|
|
3307
|
-
print_help(is_all, is_consumer);
|
|
5154
|
+
print_help(is_all, is_consumer, process.argv[ARGV_OFFSET + 1]);
|
|
3308
5155
|
return;
|
|
3309
5156
|
}
|
|
3310
5157
|
const subcommand_arguments = process.argv.slice(ARGV_OFFSET + 1);
|