@joshuafolkken/kit 1.1387.0 → 1.1435.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/skills/epic-commands/SKILL.md +1 -1
- package/.claude/skills/epic-commands/epic-bundle.md +5 -0
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +5 -3
- package/.claude/skills/workflow-commands/backlogrun-steps.md +4 -3
- package/.claude/skills/workflow-commands/backlogrun.md +1 -0
- package/.claude/skills/workflow-commands/chain-rule.md +4 -2
- package/.claude/skills/workflow-commands/issue-comments.md +6 -0
- package/.claude/skills/workflow-commands/observation-ledger.md +3 -2
- package/.claude/skills/workflow-commands/pre-gate-cut.md +5 -3
- package/README.md +25 -0
- package/dist/hooks/audit-provision.js +2 -2
- package/dist/hooks/batch-guard.js +7 -7
- package/dist/hooks/{chunk-IYVOLN6A.js → chunk-2G5F2YCD.js} +3 -3
- package/dist/hooks/{chunk-2YSW3CXH.js → chunk-3LE6VLSR.js} +17 -6
- package/dist/hooks/{chunk-J3KSS7II.js → chunk-4BHUPFKF.js} +1 -1
- package/dist/hooks/{chunk-EAQEGME7.js → chunk-5SJSSCJG.js} +1 -1
- package/dist/hooks/{chunk-FZ6FUSBM.js → chunk-723HKZO5.js} +1 -1
- package/dist/hooks/{chunk-LMWBRJIP.js → chunk-7KMN5QB5.js} +3 -3
- package/dist/hooks/{chunk-NEC4AT4Z.js → chunk-DGT54IH5.js} +4 -0
- package/dist/hooks/{chunk-STDSEPWU.js → chunk-EMB55BDF.js} +4 -4
- package/dist/hooks/{chunk-JBBMAPC4.js → chunk-IX6TTTI6.js} +4 -0
- package/dist/hooks/{chunk-GJ7JPIHN.js → chunk-JXQBK323.js} +2674 -187
- package/dist/hooks/{chunk-DCY2GWHC.js → chunk-MSYSUSY6.js} +5 -5
- package/dist/hooks/{chunk-EBSHN25W.js → chunk-MU4LJFIV.js} +4 -4
- package/dist/hooks/{chunk-WNFJLBXI.js → chunk-QL6QTPWN.js} +3 -3
- package/dist/hooks/{chunk-SL4GQ2XP.js → chunk-XER6SSIB.js} +91 -18
- package/dist/hooks/{chunk-U32VSRNG.js → chunk-YW452ZAX.js} +89 -34
- package/dist/hooks/{chunk-GNDJ7NJ7.js → chunk-YZXYOAZ3.js} +202 -55
- package/dist/hooks/codex-hook-adapter.js +15 -15
- package/dist/hooks/duplicate-read-guard.js +8 -8
- package/dist/hooks/format-edited.js +5 -5
- package/dist/hooks/inputs.json +288 -229
- package/dist/hooks/investigation-guard.js +8 -8
- package/dist/hooks/pretool-guard.js +14 -14
- package/dist/hooks/session-lang.js +69 -16
- package/dist/hooks/stop-guard.js +13 -38
- package/dist/josh.js +62 -9
- package/package.json +4 -3
- package/prompts/review.md +22 -0
- package/scripts/agent/claude-agent-argv.ts +13 -1
- package/scripts/auth/auth-setup-cli.ts +101 -0
- package/scripts/auth/claude-token-output.ts +78 -0
- package/scripts/auth/claude-token.ts +68 -0
- package/scripts/backlog/backlog-drive-epic.ts +24 -8
- package/scripts/backlog/backlog-drive-launch.ts +3 -0
- package/scripts/backlog/backlog-drive-named-offer.ts +7 -2
- package/scripts/backlog/backlog-drive-named.ts +4 -2
- package/scripts/backlog/backlog-drive-unread.ts +56 -0
- package/scripts/backlog/backlog-drive.ts +16 -8
- package/scripts/backlog/backlog-overlap.ts +22 -5
- package/scripts/backlog/backlog-ready.ts +1 -3
- package/scripts/backlog/backlogrun-args.ts +13 -2
- package/scripts/backlog/backlogrun-cli.ts +91 -19
- package/scripts/backlog/backlogrun-launch.ts +24 -0
- package/scripts/backlog/backlogrun-replace.ts +166 -0
- package/scripts/backlog/backlogrun-stop.ts +178 -0
- package/scripts/behavior/behavior-cli.ts +6 -1
- package/scripts/doctor/doctor-io.ts +60 -9
- package/scripts/doctor/doctor.ts +20 -1
- package/scripts/document/document-byte-budget.ts +3 -3
- package/scripts/epic/epic-bundle-cli.ts +8 -8
- package/scripts/epic/epic-bundle-referenced.ts +2 -5
- package/scripts/epic/epic-bundle.ts +39 -4
- package/scripts/exports/unused-members-cli.ts +2 -1
- package/scripts/followup/followup-checks-event.ts +82 -0
- package/scripts/followup/git-followup-finish.ts +16 -2
- package/scripts/followup/git-followup-workflow.ts +5 -2
- package/scripts/followup/git-pr-followup-checks.ts +18 -4
- package/scripts/followup/git-pr-followup-wrapup.ts +5 -0
- package/scripts/followup/git-pr-followup.ts +4 -1
- package/scripts/fresh-machine/fresh-machine-cli.ts +204 -0
- package/scripts/fresh-machine/fresh-machine-docker.ts +65 -0
- package/scripts/fresh-machine/fresh-machine-image.ts +62 -0
- package/scripts/fresh-machine/fresh-machine-log.ts +61 -0
- package/scripts/fresh-machine/fresh-machine-patterns.ts +130 -0
- package/scripts/fresh-machine/fresh-machine-run.ts +215 -0
- package/scripts/fresh-machine/fresh-machine-script.ts +45 -0
- package/scripts/fresh-machine/fresh-machine-spec.ts +57 -0
- package/scripts/fresh-machine/specs/kit-test-backlogrun-python.json +34 -0
- package/scripts/fresh-machine/specs/kit-test-backlogrun.json +31 -0
- package/scripts/gate/gate-report.ts +70 -15
- package/scripts/gate/project-checks.ts +13 -2
- package/scripts/gate/scoped-green.ts +2 -1
- package/scripts/gate/verification-gate.ts +4 -3
- package/scripts/gh/gh-author-association.ts +14 -0
- package/scripts/gh/git-gh-conditional.ts +66 -0
- package/scripts/gh/git-gh-exec.ts +1 -1
- package/scripts/gh/git-gh-issue-read.ts +6 -3
- package/scripts/gh/git-gh-issue-write.ts +5 -1
- package/scripts/gh/git-gh-issue.ts +4 -1
- package/scripts/gh/git-pr-checks-eval.ts +13 -0
- package/scripts/gh/git-pr-checks-parse.ts +8 -1
- package/scripts/gh/git-pr-checks-watch.ts +11 -4
- package/scripts/gh/git-pr-checks.ts +36 -2
- package/scripts/git/git-command.ts +16 -4
- package/scripts/git/git-schemas.ts +1 -0
- package/scripts/git/git-spawn-sync.ts +1 -1
- package/scripts/hooks/pretool-guard.ts +3 -1
- package/scripts/init/hook-command-rewrite.ts +31 -0
- package/scripts/init/init-actions.ts +4 -1
- package/scripts/init/init-ai-copy.ts +33 -10
- package/scripts/init/init-basic.ts +8 -3
- package/scripts/init/init-logic-toolchain.ts +76 -0
- package/scripts/init/init-logic.ts +2 -0
- package/scripts/init/init.ts +5 -23
- package/scripts/init/project-profile.ts +36 -7
- package/scripts/init/start-exec.ts +27 -1
- package/scripts/init/start-plan.ts +15 -0
- package/scripts/init/start-steps.ts +46 -0
- package/scripts/init/start.ts +1 -0
- package/scripts/init/workflow-mark.ts +35 -0
- package/scripts/issue/issue-ack-cli.ts +84 -0
- package/scripts/issue/issue-labels.ts +40 -8
- package/scripts/issue/issue-state-cli.ts +14 -4
- package/scripts/issue/issue-watch-diff.ts +152 -0
- package/scripts/issue/issue-watch-gate.ts +81 -0
- package/scripts/issue/issue-watch-hook.ts +54 -0
- package/scripts/issue/issue-watch.ts +240 -0
- package/scripts/issue/measure-rerun-cli.ts +3 -4
- package/scripts/josh/josh-command-map.ts +4 -0
- package/scripts/josh/josh-commands-backlog.ts +2 -2
- package/scripts/josh/josh-commands-development.ts +1 -1
- package/scripts/josh/josh-commands-issue.ts +7 -0
- package/scripts/josh/josh-commands-lane.ts +11 -2
- package/scripts/josh/josh-commands-project.ts +24 -0
- package/scripts/josh/josh-verdict.ts +33 -4
- package/scripts/lane/claude-lane-broker.ts +142 -0
- package/scripts/lane/lane-await.ts +6 -2
- package/scripts/lane/lane-cache.ts +37 -7
- package/scripts/lane/lane-capacity.ts +8 -6
- package/scripts/lane/lane-child-invocation.ts +1 -0
- package/scripts/lane/lane-cli.ts +15 -1
- package/scripts/lane/lane-close.ts +15 -6
- package/scripts/lane/lane-dispatch.ts +36 -10
- package/scripts/lane/lane-environment.ts +1 -1
- package/scripts/lane/lane-launch-cli.ts +13 -4
- package/scripts/lane/lane-ledger.ts +21 -3
- package/scripts/lane/lane-measure-cli.ts +10 -2
- package/scripts/lane/lane-open.ts +9 -1
- package/scripts/lane/lane-preserve.ts +49 -0
- package/scripts/lane/lane-reap.ts +20 -5
- package/scripts/lane/lane-registry.ts +6 -0
- package/scripts/lane/lane-restart-cli.ts +51 -0
- package/scripts/lane/lane-restart.ts +175 -0
- package/scripts/lane/{openai-review-broker.ts → lane-session-broker.ts} +106 -28
- package/scripts/lane/lane-spent.ts +195 -0
- package/scripts/lane/lane-stage-stats.ts +27 -3
- package/scripts/lane/lane-stop-stats.ts +96 -0
- package/scripts/lane/openai-lane-supervisor.ts +2 -2
- package/scripts/lane/process-tools.ts +31 -0
- package/scripts/lib/buffered-process.ts +36 -2
- package/scripts/lib/pnpm-reach.ts +27 -0
- package/scripts/lib/status-icons.ts +5 -1
- package/scripts/lint/lint-parallel.ts +19 -2
- package/scripts/observations/observation-ledger-home.ts +1 -0
- package/scripts/review/review-attest-cli.ts +21 -6
- package/scripts/review/review-brief-cli.ts +2 -2
- package/scripts/review/review-comment-round.ts +114 -0
- package/scripts/review/review-record-cli.ts +39 -17
- package/scripts/rules/implementation-cut.ts +3 -3
- package/scripts/rules/pre-gate-cut.ts +1 -1
- package/scripts/run/board/run-board-checks.ts +42 -0
- package/scripts/run/board/run-board-cli.ts +2 -0
- package/scripts/run/board/run-board-every.ts +3 -1
- package/scripts/run/board/run-board-fit.ts +16 -5
- package/scripts/run/board/run-board-fresh.ts +64 -0
- package/scripts/run/board/run-board-header.ts +129 -53
- package/scripts/run/board/run-board-labels.ts +47 -4
- package/scripts/run/board/run-board-lane-event.ts +66 -0
- package/scripts/run/board/run-board-layout.ts +57 -9
- package/scripts/run/board/run-board-now.ts +234 -0
- package/scripts/run/board/run-board-operation-read.ts +75 -0
- package/scripts/run/board/run-board-operation.ts +150 -0
- package/scripts/run/board/run-board-phase.ts +26 -1
- package/scripts/run/board/run-board-plan.ts +4 -6
- package/scripts/run/board/run-board-read.ts +49 -3
- package/scripts/run/board/run-board-reason.ts +124 -0
- package/scripts/run/board/run-board-render-checks.ts +55 -0
- package/scripts/run/board/run-board-render-legend.ts +12 -3
- package/scripts/run/board/run-board-render-slot.ts +2 -2
- package/scripts/run/board/run-board-render-tail.ts +128 -0
- package/scripts/run/board/run-board-render-thanks.ts +50 -0
- package/scripts/run/board/run-board-render-title.ts +58 -0
- package/scripts/run/board/run-board-render.ts +96 -80
- package/scripts/run/board/run-board-row-yield.ts +32 -0
- package/scripts/run/board/run-board-setup.ts +61 -13
- package/scripts/run/board/run-board-state.ts +10 -0
- package/scripts/run/board/run-board-status.ts +66 -7
- package/scripts/run/board/run-board-thanks-csv.ts +71 -0
- package/scripts/run/board/run-board-thanks-read.ts +112 -0
- package/scripts/run/board/run-board-thanks.ts +53 -0
- package/scripts/run/board/run-board-tick.ts +50 -21
- package/scripts/run/board/run-board-usual.ts +44 -0
- package/scripts/run/carry/run-carry-args.ts +9 -1
- package/scripts/run/carry/run-carry-cli.ts +2 -45
- package/scripts/run/carry/run-carry-end.ts +73 -0
- package/scripts/run/carry/run-carry.ts +8 -1
- package/scripts/run/entry/run-entry-cli.ts +5 -0
- package/scripts/run/event/run-event-checks.ts +54 -0
- package/scripts/run/event/run-event-render.ts +2 -0
- package/scripts/run/event/run-event-scope.ts +1 -0
- package/scripts/run/event/run-event-setup.ts +55 -11
- package/scripts/run/event/run-event-stream.ts +27 -11
- package/scripts/run/merge/run-merge-cli.ts +7 -4
- package/scripts/run/merge/run-merge-ship.ts +61 -0
- package/scripts/run/merge/run-merge-steps.ts +7 -14
- package/scripts/run/merge/run-merge-token.ts +16 -2
- package/scripts/run/run-headless.ts +1 -0
- package/scripts/run/run-step.ts +2 -0
- package/scripts/run/ship/run-ship-cli.ts +22 -2
- package/scripts/run/ship/run-ship-return.ts +31 -13
- package/scripts/run/ship/run-ship-review-steps.ts +17 -4
- package/scripts/run/ship/run-ship-stage.ts +1 -0
- package/scripts/run/wake/run-wake-await.ts +130 -0
- package/scripts/run/wake/run-wake-cli.ts +60 -71
- package/scripts/run/wake/run-wake-describe.ts +34 -2
- package/scripts/run/wake/run-wake-driver.ts +11 -4
- package/scripts/run/wake/run-wake-session.ts +20 -3
- package/scripts/run/wake/run-wake-stop.ts +37 -0
- package/scripts/run/wake/run-wake-supervise.ts +44 -0
- package/scripts/sync/claude-settings-merge.ts +144 -0
- package/scripts/sync/sync-ai-files.ts +28 -3
- package/scripts/sync/sync.ts +15 -0
- package/scripts/test/project-test-script.ts +73 -0
- package/scripts/test/skip-marker.ts +14 -1
- package/scripts/test/test-related.ts +3 -2
- package/scripts/test/test-unit-guard.ts +78 -14
- package/scripts/time-runtime/time-reported-failure.ts +11 -3
- package/scripts/uninstall/distributed-files.ts +92 -0
- package/scripts/uninstall/uninstall-plan.ts +119 -0
- package/scripts/uninstall/uninstall-report.ts +61 -0
- package/scripts/uninstall/uninstall.ts +206 -0
- package/templates/AGENTS.basic.md +4 -0
- package/templates/GEMINI.basic.md +6 -0
- package/dist/hooks/chunk-6V5OPIUU.js +0 -13
- package/scripts/run/board/run-board-track.ts +0 -22
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
2
|
import {
|
|
3
3
|
pretool_guard
|
|
4
|
-
} from "./chunk-
|
|
5
|
-
import "./chunk-
|
|
6
|
-
import "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
4
|
+
} from "./chunk-JXQBK323.js";
|
|
5
|
+
import "./chunk-MSYSUSY6.js";
|
|
6
|
+
import "./chunk-YZXYOAZ3.js";
|
|
7
|
+
import "./chunk-IX6TTTI6.js";
|
|
8
|
+
import "./chunk-YW452ZAX.js";
|
|
9
9
|
import "./chunk-CDY4NFQG.js";
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
12
|
-
import "./chunk-
|
|
13
|
-
import "./chunk-
|
|
10
|
+
import "./chunk-7KMN5QB5.js";
|
|
11
|
+
import "./chunk-2G5F2YCD.js";
|
|
12
|
+
import "./chunk-QL6QTPWN.js";
|
|
13
|
+
import "./chunk-5SJSSCJG.js";
|
|
14
14
|
import {
|
|
15
15
|
hook_decision
|
|
16
|
-
} from "./chunk-
|
|
17
|
-
import "./chunk-
|
|
18
|
-
import "./chunk-
|
|
19
|
-
import "./chunk-
|
|
20
|
-
import "./chunk-
|
|
16
|
+
} from "./chunk-MU4LJFIV.js";
|
|
17
|
+
import "./chunk-XER6SSIB.js";
|
|
18
|
+
import "./chunk-4BHUPFKF.js";
|
|
19
|
+
import "./chunk-3LE6VLSR.js";
|
|
20
|
+
import "./chunk-DGT54IH5.js";
|
|
21
21
|
|
|
22
22
|
// scripts/hooks/pretool-guard-cli.ts
|
|
23
23
|
import { text } from "node:stream/consumers";
|
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
|
-
import {
|
|
3
|
-
session_language
|
|
4
|
-
} from "./chunk-6V5OPIUU.js";
|
|
5
2
|
import {
|
|
6
3
|
agent_role_profile,
|
|
7
4
|
detached_launch,
|
|
@@ -9,23 +6,24 @@ import {
|
|
|
9
6
|
issue_cite,
|
|
10
7
|
run_event_stream,
|
|
11
8
|
run_event_stream_emit,
|
|
12
|
-
run_headless
|
|
13
|
-
|
|
9
|
+
run_headless,
|
|
10
|
+
session_language
|
|
11
|
+
} from "./chunk-YW452ZAX.js";
|
|
14
12
|
import {
|
|
15
13
|
error_text
|
|
16
14
|
} from "./chunk-CDY4NFQG.js";
|
|
17
15
|
import {
|
|
18
16
|
josh_environment_file
|
|
19
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-4BHUPFKF.js";
|
|
20
18
|
import {
|
|
21
19
|
agent_session_environment,
|
|
22
20
|
json_value,
|
|
23
21
|
process_identity,
|
|
24
22
|
run_carry
|
|
25
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-3LE6VLSR.js";
|
|
26
24
|
import {
|
|
27
25
|
stamp_file
|
|
28
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-DGT54IH5.js";
|
|
29
27
|
|
|
30
28
|
// scripts/josh/session-language-cli.ts
|
|
31
29
|
import { fileURLToPath } from "node:url";
|
|
@@ -104,7 +102,14 @@ var agent_diagnostics = { check };
|
|
|
104
102
|
import { existsSync } from "node:fs";
|
|
105
103
|
import path from "node:path";
|
|
106
104
|
var AGENT_COMMAND = "claude";
|
|
107
|
-
var
|
|
105
|
+
var PERMISSION_FLAGS = ["--permission-mode", "bypassPermissions"];
|
|
106
|
+
var AGENT_FLAGS = [
|
|
107
|
+
"-p",
|
|
108
|
+
"--verbose",
|
|
109
|
+
"--output-format",
|
|
110
|
+
"stream-json",
|
|
111
|
+
...PERMISSION_FLAGS
|
|
112
|
+
];
|
|
108
113
|
var MODEL_FLAG = "--model";
|
|
109
114
|
var EFFORT_FLAG = "--effort";
|
|
110
115
|
var RESUME_FLAG = "--resume";
|
|
@@ -311,24 +316,57 @@ var STAGE = {
|
|
|
311
316
|
// `run:carry --begin` claimed the run, and the parent is planning it.
|
|
312
317
|
PLANNING: "planning",
|
|
313
318
|
// The supervisor took the run over from the parent and is asking for the first offer.
|
|
314
|
-
HANDING_OFF: "handing off"
|
|
319
|
+
HANDING_OFF: "handing off",
|
|
320
|
+
// The driver answered something only a session can act on — an untriaged child, an epic left to a
|
|
321
|
+
// person — and the supervisor is waking one. The next hand-off replaces it.
|
|
322
|
+
JUDGING: "waiting on judgment",
|
|
323
|
+
// The supervisor started that session, which is now acting on the driver's answer. It is detached, so
|
|
324
|
+
// its end is the supervisor's next hand-off, which replaces this.
|
|
325
|
+
SESSION: "judgment session running",
|
|
326
|
+
// The driver's launch of a lane returned without a child: no lane was free to open, or a step after
|
|
327
|
+
// the open failed. It names no issue, so the lane's own stage ends here whatever the driver does next.
|
|
328
|
+
NO_CHILD: "no child launched"
|
|
315
329
|
};
|
|
316
330
|
var OPENING = "opening lane";
|
|
331
|
+
var INSTALLING = "installing dependencies";
|
|
332
|
+
var DISPATCHING = "dispatching";
|
|
333
|
+
var LANE_STAGE = { OPENING, INSTALLING, DISPATCHING };
|
|
317
334
|
function opening_lane(issue) {
|
|
318
335
|
return `${OPENING} ${issue_cite.plain(issue)}`;
|
|
319
336
|
}
|
|
337
|
+
function installing(issue) {
|
|
338
|
+
return `${INSTALLING} ${issue_cite.plain(issue)}`;
|
|
339
|
+
}
|
|
340
|
+
function dispatching(issue) {
|
|
341
|
+
return `${DISPATCHING} ${issue_cite.plain(issue)}`;
|
|
342
|
+
}
|
|
320
343
|
async function emit(text) {
|
|
321
344
|
await run_event_stream_emit.emit(run_event_stream.EVENT_KIND.SETUP, text);
|
|
322
345
|
}
|
|
323
|
-
function
|
|
346
|
+
function append_stage(resolve_target, text, at) {
|
|
324
347
|
try {
|
|
325
|
-
const
|
|
326
|
-
run_event_stream.append(
|
|
348
|
+
const { SETUP } = run_event_stream.EVENT_KIND;
|
|
349
|
+
run_event_stream.append(resolve_target(), SETUP, text, at.toISOString());
|
|
327
350
|
} catch (error) {
|
|
328
|
-
error_text.trace_swallowed("run_event_setup.
|
|
351
|
+
error_text.trace_swallowed("run_event_setup.append_stage", error);
|
|
329
352
|
}
|
|
330
353
|
}
|
|
331
|
-
|
|
354
|
+
function emit_in(repository, text, at) {
|
|
355
|
+
append_stage(() => run_event_stream.target_of(repository), text, at);
|
|
356
|
+
}
|
|
357
|
+
function emit_to(target, text, at) {
|
|
358
|
+
append_stage(() => target, text, at);
|
|
359
|
+
}
|
|
360
|
+
var run_event_setup = {
|
|
361
|
+
LANE_STAGE,
|
|
362
|
+
STAGE,
|
|
363
|
+
dispatching,
|
|
364
|
+
emit,
|
|
365
|
+
emit_in,
|
|
366
|
+
emit_to,
|
|
367
|
+
installing,
|
|
368
|
+
opening_lane
|
|
369
|
+
};
|
|
332
370
|
|
|
333
371
|
// scripts/backlog/backlogrun-launch.ts
|
|
334
372
|
import { z } from "zod";
|
|
@@ -406,6 +444,20 @@ function started_for(git_directory, owner_pid) {
|
|
|
406
444
|
const started_ms = Date.parse(record.started_at);
|
|
407
445
|
return Number.isNaN(started_ms) ? void 0 : new Date(started_ms);
|
|
408
446
|
}
|
|
447
|
+
function signal_parent(pid) {
|
|
448
|
+
try {
|
|
449
|
+
process.kill(pid, "SIGTERM");
|
|
450
|
+
} catch {
|
|
451
|
+
note_to_stderr(`process ${String(pid)} could not be signalled; its launch record is removed.`);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
function stop_parent(git_directory) {
|
|
455
|
+
const record = live_launch(git_directory);
|
|
456
|
+
stamp_file.remove_stamp(launch_path(git_directory));
|
|
457
|
+
if (record === void 0) return void 0;
|
|
458
|
+
signal_parent(record.pid);
|
|
459
|
+
return record.pid;
|
|
460
|
+
}
|
|
409
461
|
function spawn_parent(argv, provider, target) {
|
|
410
462
|
const environment = {
|
|
411
463
|
...run_headless.environment(),
|
|
@@ -440,7 +492,8 @@ var backlogrun_launch = {
|
|
|
440
492
|
is_running,
|
|
441
493
|
pending_launch,
|
|
442
494
|
start,
|
|
443
|
-
started_for
|
|
495
|
+
started_for,
|
|
496
|
+
stop_parent
|
|
444
497
|
};
|
|
445
498
|
|
|
446
499
|
// scripts/josh/session-language-cli.ts
|
package/dist/hooks/stop-guard.js
CHANGED
|
@@ -3,9 +3,8 @@ import {
|
|
|
3
3
|
RUN_LANE_LABEL,
|
|
4
4
|
RUN_SOLO_LABEL,
|
|
5
5
|
filing_cap,
|
|
6
|
-
|
|
6
|
+
gh_spawn,
|
|
7
7
|
git_gh_command,
|
|
8
|
-
git_gh_exec,
|
|
9
8
|
has_label_name,
|
|
10
9
|
issue_citation,
|
|
11
10
|
lane_background,
|
|
@@ -14,10 +13,7 @@ import {
|
|
|
14
13
|
repo_party,
|
|
15
14
|
run_cut,
|
|
16
15
|
run_hold
|
|
17
|
-
} from "./chunk-
|
|
18
|
-
import {
|
|
19
|
-
session_language
|
|
20
|
-
} from "./chunk-6V5OPIUU.js";
|
|
16
|
+
} from "./chunk-YZXYOAZ3.js";
|
|
21
17
|
import {
|
|
22
18
|
agent_headless,
|
|
23
19
|
agent_role_profile,
|
|
@@ -25,23 +21,24 @@ import {
|
|
|
25
21
|
lane_registry,
|
|
26
22
|
run_event_stream,
|
|
27
23
|
run_event_stream_emit,
|
|
28
|
-
run_headless
|
|
29
|
-
|
|
24
|
+
run_headless,
|
|
25
|
+
session_language
|
|
26
|
+
} from "./chunk-YW452ZAX.js";
|
|
30
27
|
import {
|
|
31
28
|
timed_fetch
|
|
32
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-723HKZO5.js";
|
|
33
30
|
import "./chunk-CDY4NFQG.js";
|
|
34
31
|
import {
|
|
35
32
|
hook_decision
|
|
36
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-MU4LJFIV.js";
|
|
37
34
|
import {
|
|
38
35
|
time_density_hook,
|
|
39
36
|
time_hook_transcript,
|
|
40
37
|
time_reported_failure
|
|
41
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-XER6SSIB.js";
|
|
42
39
|
import {
|
|
43
40
|
lane_child_marker
|
|
44
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-4BHUPFKF.js";
|
|
45
42
|
import {
|
|
46
43
|
backlog_budget,
|
|
47
44
|
issue_number_shape,
|
|
@@ -50,11 +47,10 @@ import {
|
|
|
50
47
|
process_owner_schema,
|
|
51
48
|
run_carry,
|
|
52
49
|
run_invocation
|
|
53
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-3LE6VLSR.js";
|
|
54
51
|
import {
|
|
55
|
-
PROJECT_ROOT,
|
|
56
52
|
stamp_file
|
|
57
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-DGT54IH5.js";
|
|
58
54
|
|
|
59
55
|
// scripts/hooks/stop-guard.ts
|
|
60
56
|
import { text } from "node:stream/consumers";
|
|
@@ -136,7 +132,7 @@ var lane_seed_policy = {
|
|
|
136
132
|
};
|
|
137
133
|
|
|
138
134
|
// scripts/lane/lane-capacity.ts
|
|
139
|
-
var DEFAULT_LANE_LIMIT =
|
|
135
|
+
var DEFAULT_LANE_LIMIT = 4;
|
|
140
136
|
var LANE_LIMIT_KEY = "JOSH_LANE_LIMIT";
|
|
141
137
|
var POSITIVE_INTEGER = /^[1-9]\d*$/u;
|
|
142
138
|
var NO_LANES = 0;
|
|
@@ -245,8 +241,7 @@ var backlog_stalled = {
|
|
|
245
241
|
var NO_FREE = 0;
|
|
246
242
|
var NONE2 = 0;
|
|
247
243
|
async function live_lane_count() {
|
|
248
|
-
|
|
249
|
-
return lanes.filter((lane) => !lane.is_stranded).length;
|
|
244
|
+
return lane_registry.live_count(await lane_registry.list_lanes());
|
|
250
245
|
}
|
|
251
246
|
async function free_under(limit) {
|
|
252
247
|
return lane_capacity.free_lanes(limit, await live_lane_count());
|
|
@@ -320,26 +315,6 @@ var backlog_ready = {
|
|
|
320
315
|
ready_line
|
|
321
316
|
};
|
|
322
317
|
|
|
323
|
-
// scripts/gh/gh-spawn.ts
|
|
324
|
-
var NO_BUDGET = 0;
|
|
325
|
-
function fetch_repo_name(timeout_ms) {
|
|
326
|
-
const stdout = git_gh_exec.read_gh_api_sync({
|
|
327
|
-
path: git_gh_api_path.repo_api_path(),
|
|
328
|
-
jq_filter: ".full_name",
|
|
329
|
-
cwd: PROJECT_ROOT,
|
|
330
|
-
timeout_ms: timeout_ms ?? NO_BUDGET
|
|
331
|
-
});
|
|
332
|
-
const name = stdout?.trim();
|
|
333
|
-
return name === "" ? void 0 : name;
|
|
334
|
-
}
|
|
335
|
-
function get_repo_name_with_owner() {
|
|
336
|
-
return fetch_repo_name(void 0);
|
|
337
|
-
}
|
|
338
|
-
function get_repo_name_with_owner_within(timeout_ms) {
|
|
339
|
-
return fetch_repo_name(timeout_ms);
|
|
340
|
-
}
|
|
341
|
-
var gh_spawn = { get_repo_name_with_owner, get_repo_name_with_owner_within };
|
|
342
|
-
|
|
343
318
|
// scripts/notify/telegram-notify.ts
|
|
344
319
|
import { z } from "zod";
|
|
345
320
|
var TELEGRAM_API_BASE = "https://api.telegram.org";
|
package/dist/josh.js
CHANGED
|
@@ -1275,10 +1275,10 @@ var BACKLOG_COMMANDS = {
|
|
|
1275
1275
|
// Started from a terminal: the `backlogrun` keyword's launcher, and the board.
|
|
1276
1276
|
backlogrun: {
|
|
1277
1277
|
script: "scripts/backlog/backlogrun-cli.ts",
|
|
1278
|
-
description: "Start a backlogrun in the background and show its board; with one already running, only show the board",
|
|
1278
|
+
description: "Start a backlogrun in the background and show its board; with one already running, only show the board, or replace it when it is idle and the invocation differs; --stop stops it",
|
|
1279
1279
|
category: "AI tools",
|
|
1280
1280
|
reference: [
|
|
1281
|
-
"[
|
|
1281
|
+
"[<n>...] [--only] [--max <n>] [--idle <minutes>] [--agent claude|codex] | --stop",
|
|
1282
1282
|
"developer",
|
|
1283
1283
|
["files", "network", "processes"]
|
|
1284
1284
|
]
|
|
@@ -1388,6 +1388,12 @@ var GUARD_COMMANDS = {
|
|
|
1388
1388
|
// scripts/josh/josh-commands-issue.ts
|
|
1389
1389
|
var ISSUES_WITH_REPO = "<issue...> [--repo <owner/repo>]";
|
|
1390
1390
|
var ISSUE_COMMANDS = {
|
|
1391
|
+
"issue:ack": {
|
|
1392
|
+
script: "scripts/issue/issue-ack-cli.ts",
|
|
1393
|
+
description: "Record that the run read a person's update to its issue, printing the update it acknowledges",
|
|
1394
|
+
category: "AI tools",
|
|
1395
|
+
reference: ["<issue>", "automation", ["network"]]
|
|
1396
|
+
},
|
|
1391
1397
|
"issue:read": {
|
|
1392
1398
|
script: "scripts/issue/issue-read-cli.ts",
|
|
1393
1399
|
description: "Print each issue's title, body and every comment on it, in one call",
|
|
@@ -1486,7 +1492,7 @@ var LANE_COMMANDS = {
|
|
|
1486
1492
|
},
|
|
1487
1493
|
"lane:prune": {
|
|
1488
1494
|
...LANE_ARGUMENTS,
|
|
1489
|
-
description: "Close every lane an interruption left without its work tree, then sweep unregistered leftovers under the lanes root",
|
|
1495
|
+
description: "Close every lane an interruption left without its work tree and every spent lane, then sweep unregistered leftovers under the lanes root",
|
|
1490
1496
|
category: "AI tools",
|
|
1491
1497
|
reference: ["", "automation", ["files", "git"]],
|
|
1492
1498
|
default_script_arguments: ["prune"]
|
|
@@ -1518,6 +1524,14 @@ var LANE_COMMANDS = {
|
|
|
1518
1524
|
category: "AI tools",
|
|
1519
1525
|
reference: ["<issue> [--stash <message>]", "automation", ["files", "git", "processes"]]
|
|
1520
1526
|
},
|
|
1527
|
+
// `.env` is read for `JOSH_LANE_ROOT`, as every lane command reads it, so the lane is found.
|
|
1528
|
+
"lane:restart": {
|
|
1529
|
+
script: "scripts/lane/lane-restart-cli.ts",
|
|
1530
|
+
tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
|
|
1531
|
+
description: "Stop a running lane child, stash its uncommitted work and re-dispatch its issue in a fresh session \u2014 not counted as an outage or a failure",
|
|
1532
|
+
category: "AI tools",
|
|
1533
|
+
reference: ["<issue>", "developer", ["files", "git", "processes", "network"]]
|
|
1534
|
+
},
|
|
1521
1535
|
// A live run's lane limit: `.env` is read so the bare form reports the
|
|
1522
1536
|
// `JOSH_LANE_LIMIT` a person set there when no override stands.
|
|
1523
1537
|
"lane:limit": {
|
|
@@ -1538,7 +1552,7 @@ var LANE_COMMANDS = {
|
|
|
1538
1552
|
},
|
|
1539
1553
|
"lane:stats": {
|
|
1540
1554
|
...MEASURE_ARGUMENTS,
|
|
1541
|
-
description: "Print one table row of lane throughput, gate duration and machine load over a period,
|
|
1555
|
+
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, and the wait after each ship stop reason under those",
|
|
1542
1556
|
category: "AI tools",
|
|
1543
1557
|
reference: ["--period <days> [--limit <lane-limit>]", "maintainer", ["none"]],
|
|
1544
1558
|
default_script_arguments: ["stats"]
|
|
@@ -1905,17 +1919,27 @@ import { availableParallelism as availableParallelism4 } from "node:os";
|
|
|
1905
1919
|
// scripts/lib/status-icons.ts
|
|
1906
1920
|
var FAIL_ICON = "\u2717";
|
|
1907
1921
|
var PASS_ICON = "\u2714";
|
|
1908
|
-
var
|
|
1922
|
+
var WARN_ICON = "\u26A0";
|
|
1923
|
+
var status_icons = { FAIL_ICON, PASS_ICON, WARN_ICON };
|
|
1909
1924
|
|
|
1910
1925
|
// scripts/josh/josh-verdict.ts
|
|
1911
|
-
var { FAIL_ICON: FAIL_ICON2, PASS_ICON: PASS_ICON2 } = status_icons;
|
|
1926
|
+
var { FAIL_ICON: FAIL_ICON2, PASS_ICON: PASS_ICON2, WARN_ICON: WARN_ICON2 } = status_icons;
|
|
1912
1927
|
var GATE_SUBJECT = "verification gate";
|
|
1913
1928
|
var GATE_PASSED_PREFIX = `${PASS_ICON2} ${GATE_SUBJECT} passed`;
|
|
1914
1929
|
var GATE_FAILED_PREFIX = `${FAIL_ICON2} ${GATE_SUBJECT} failed`;
|
|
1930
|
+
var GATE_UNVERIFIED_PREFIX = `${WARN_ICON2} ${GATE_SUBJECT} not verified`;
|
|
1915
1931
|
var PASSED_VERDICT = "passed";
|
|
1916
1932
|
var FAILED_VERDICT = "failed";
|
|
1917
|
-
|
|
1918
|
-
|
|
1933
|
+
var UNVERIFIED_VERDICT = "unverified";
|
|
1934
|
+
function format_counts(counts) {
|
|
1935
|
+
if (counts.skipped === 0) return `${String(counts.ran)} checks`;
|
|
1936
|
+
return `${String(counts.ran)} ran, ${String(counts.skipped)} skipped`;
|
|
1937
|
+
}
|
|
1938
|
+
function format_gate_passed(counts, total) {
|
|
1939
|
+
return `${GATE_PASSED_PREFIX} (${format_counts(counts)}) in ${total}.`;
|
|
1940
|
+
}
|
|
1941
|
+
function format_gate_unverified(skipped, total) {
|
|
1942
|
+
return `${GATE_UNVERIFIED_PREFIX} (0 ran, ${String(skipped)} skipped) in ${total}.`;
|
|
1919
1943
|
}
|
|
1920
1944
|
function format_gate_failed(failed_labels, total) {
|
|
1921
1945
|
return `${GATE_FAILED_PREFIX}: ${failed_labels} (${total})`;
|
|
@@ -1930,13 +1954,16 @@ function read_verdict(line) {
|
|
|
1930
1954
|
const trimmed = line.trimStart();
|
|
1931
1955
|
if (trimmed.startsWith(GATE_FAILED_PREFIX)) return FAILED_VERDICT;
|
|
1932
1956
|
if (trimmed.startsWith(GATE_PASSED_PREFIX)) return PASSED_VERDICT;
|
|
1957
|
+
if (trimmed.startsWith(GATE_UNVERIFIED_PREFIX)) return UNVERIFIED_VERDICT;
|
|
1933
1958
|
return void 0;
|
|
1934
1959
|
}
|
|
1935
1960
|
var josh_verdict = {
|
|
1936
1961
|
PASSED_VERDICT,
|
|
1937
1962
|
FAILED_VERDICT,
|
|
1963
|
+
UNVERIFIED_VERDICT,
|
|
1938
1964
|
format_gate_passed,
|
|
1939
1965
|
format_gate_failed,
|
|
1966
|
+
format_gate_unverified,
|
|
1940
1967
|
GATE_OPENING_MARK,
|
|
1941
1968
|
GATE_OPENING_PREFIX,
|
|
1942
1969
|
is_gate_opening,
|
|
@@ -2269,7 +2296,7 @@ var DEV_COMMANDS = {
|
|
|
2269
2296
|
},
|
|
2270
2297
|
"test:unit": {
|
|
2271
2298
|
script: "scripts/test/test-unit-guard.ts",
|
|
2272
|
-
description: "Run unit tests with Vitest (
|
|
2299
|
+
description: "Run unit tests with Vitest (without Vitest: a basic project runs its own test script, others skip; fails when Vitest has no tests)",
|
|
2273
2300
|
category: "Development",
|
|
2274
2301
|
reference: [FILTER_ARGUMENTS, "developer", ["processes"]],
|
|
2275
2302
|
core_weight: gate_plan.direct_unit_weight,
|
|
@@ -2513,6 +2540,22 @@ var PROJECT_COMMANDS = {
|
|
|
2513
2540
|
reference: ["<dir>", "automation", ["files", "git"]],
|
|
2514
2541
|
is_kit_only: true
|
|
2515
2542
|
},
|
|
2543
|
+
"fresh:run": {
|
|
2544
|
+
script: "scripts/fresh-machine/fresh-machine-cli.ts",
|
|
2545
|
+
description: "Run an install scenario in a Docker container of a machine with nothing installed, and keep the log",
|
|
2546
|
+
category: "Project",
|
|
2547
|
+
reference: [
|
|
2548
|
+
"<pattern> | --spec <file.json> [--package-version <version>] [--log-dir <dir>] [--rebuild] | --list",
|
|
2549
|
+
"maintainer",
|
|
2550
|
+
["files", "network", "processes"]
|
|
2551
|
+
]
|
|
2552
|
+
},
|
|
2553
|
+
"auth:setup": {
|
|
2554
|
+
script: "scripts/auth/auth-setup-cli.ts",
|
|
2555
|
+
description: "Save the long-lived Claude Code token `claude setup-token` prints in the macOS keychain, for josh fresh:run",
|
|
2556
|
+
category: "Project",
|
|
2557
|
+
reference: ["[--check]", "maintainer", ["network", "processes"]]
|
|
2558
|
+
},
|
|
2516
2559
|
init: {
|
|
2517
2560
|
script: "scripts/init/init.ts",
|
|
2518
2561
|
description: "Initialize config in a new project",
|
|
@@ -2529,6 +2572,12 @@ var PROJECT_COMMANDS = {
|
|
|
2529
2572
|
category: "Project",
|
|
2530
2573
|
reference: ["", "developer", ["files"]]
|
|
2531
2574
|
},
|
|
2575
|
+
uninstall: {
|
|
2576
|
+
script: "scripts/uninstall/uninstall.ts",
|
|
2577
|
+
description: "Remove what kit added to a project and list what is left to review by hand",
|
|
2578
|
+
category: "Project",
|
|
2579
|
+
reference: [`${PROFILE_ARGUMENTS} [--yes]`, "developer", ["files", "processes"]]
|
|
2580
|
+
},
|
|
2532
2581
|
"registry:migrate": {
|
|
2533
2582
|
script: "scripts/registry-migration/migrate.ts",
|
|
2534
2583
|
description: "Migrate a project from GitHub Packages to public npm",
|
|
@@ -2791,6 +2840,7 @@ var ALIASES = {
|
|
|
2791
2840
|
pf: "profile",
|
|
2792
2841
|
st: "start",
|
|
2793
2842
|
sy: "sync",
|
|
2843
|
+
un: "uninstall",
|
|
2794
2844
|
rmi: "registry:migrate",
|
|
2795
2845
|
g: "git",
|
|
2796
2846
|
gp: "pr",
|
|
@@ -2816,9 +2866,12 @@ var ALIASES = {
|
|
|
2816
2866
|
rvf: "review:findings",
|
|
2817
2867
|
ruv: "rule:value",
|
|
2818
2868
|
ev: "eval",
|
|
2869
|
+
fr: "fresh:run",
|
|
2870
|
+
as: "auth:setup",
|
|
2819
2871
|
lsm: "lane:sample",
|
|
2820
2872
|
lst: "lane:stats",
|
|
2821
2873
|
lli: "lane:limit",
|
|
2874
|
+
lrs: "lane:restart",
|
|
2822
2875
|
blr: "backlogrun"
|
|
2823
2876
|
};
|
|
2824
2877
|
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.
|
|
2
|
+
"version": "1.1435.0",
|
|
3
3
|
"name": "@joshuafolkken/kit",
|
|
4
4
|
"description": "Development toolkit for AI-assisted projects: formatting, AI assistant rules and a Git/GitHub Issue workflow for any repository, plus lint, type check, tests and hooks for Node projects",
|
|
5
5
|
"keywords": [
|
|
@@ -276,6 +276,7 @@
|
|
|
276
276
|
},
|
|
277
277
|
"dependencies": {
|
|
278
278
|
"cli-spinners": "^3.4.0",
|
|
279
|
+
"csv-parse": "^7.0.3",
|
|
279
280
|
"execa": "^10.1.0",
|
|
280
281
|
"js-yaml": "^5.4.3",
|
|
281
282
|
"jsonc-parser": "^3.3.1",
|
|
@@ -284,12 +285,12 @@
|
|
|
284
285
|
"string-width": "^8.3.0",
|
|
285
286
|
"terminal-link": "^5.0.0",
|
|
286
287
|
"tsx": "^4.23.15",
|
|
287
|
-
"zod": "^4.6.
|
|
288
|
+
"zod": "^4.6.6"
|
|
288
289
|
},
|
|
289
290
|
"devEngines": {
|
|
290
291
|
"packageManager": {
|
|
291
292
|
"name": "pnpm",
|
|
292
|
-
"version": "12.12.
|
|
293
|
+
"version": "12.12.1+sha512.b7f98934c0b1f29a65f5da52f2d7f994e7faad573ffdddea1497fb4dcb5aec051590ee7c7d95a38172b4bfae103a5b83edf2ee866e11731c2cafa96063610ac5",
|
|
293
294
|
"onFail": "download"
|
|
294
295
|
}
|
|
295
296
|
},
|
package/prompts/review.md
CHANGED
|
@@ -27,6 +27,28 @@ is a verification pass over the fixes, not the first review again
|
|
|
27
27
|
|
|
28
28
|
---
|
|
29
29
|
|
|
30
|
+
## Before round 1 — the implementer's self-check
|
|
31
|
+
|
|
32
|
+
**Answer these five over your own diff before the scoped pair that precedes round 1.** A round-1
|
|
33
|
+
High/Medium makes round 2 due, and most of them are of a kind the implementer clears more cheaply
|
|
34
|
+
than a reviewer finds: in a sample of 135 round-1 High/Medium findings, about two in three fell under one of these questions. Fix what an answer turns up; the review, its
|
|
35
|
+
severity tests and the round cap are unchanged.
|
|
36
|
+
|
|
37
|
+
1. **Tests pin the change** — for each condition, branch or call you added or changed, name the test
|
|
38
|
+
that turns red when it is deleted or inverted, and check its fixture actually reaches that branch
|
|
39
|
+
(no assert on a string the code never draws, no comparison against a literal copy).
|
|
40
|
+
2. **Prose matches the code** — grep the docs, prompts and comments for the old wording of every
|
|
41
|
+
behavior, constant, command and heading you changed, moved or removed, `"the table above"` and
|
|
42
|
+
rewritten sentences included.
|
|
43
|
+
3. **Failure is not a negative answer** — every timeout, non-zero exit or `gh` failure on a path you
|
|
44
|
+
touched returns something a caller can tell apart from `false`, `undefined` or "nothing found".
|
|
45
|
+
4. **Every caller moved with it** — grep every reference to a function, list or command you changed,
|
|
46
|
+
and update each sibling path (the other CLI, the registry, the consumer side) in the same change.
|
|
47
|
+
5. **The Issue is met on HEAD** — the premises you relied on hold on the current tree, and each
|
|
48
|
+
acceptance criterion is checked off one by one against the diff.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
30
52
|
## Review level (decided by `pnpm josh review:brief --level-only`, never by judgement)
|
|
31
53
|
|
|
32
54
|
**Run `pnpm josh review:brief --level-only` and use what it prints** — `low` or `medium`, from the
|
|
@@ -8,7 +8,19 @@ import {
|
|
|
8
8
|
} from './agent-role-profile'
|
|
9
9
|
|
|
10
10
|
const AGENT_COMMAND = 'claude'
|
|
11
|
-
|
|
11
|
+
// **The permission mode is passed, not left to the checkout's `.claude/settings.json`.** Claude Code
|
|
12
|
+
// ignores a project's `defaultMode: bypassPermissions` (since v2.1.257) and its `permissions.allow` in
|
|
13
|
+
// a workspace whose trust dialog was never accepted — every fresh clone and every new lane worktree — so
|
|
14
|
+
// a headless child stopped on approvals nobody could give. The flag sets the mode that file declares;
|
|
15
|
+
// its `deny` list stays in effect (#3796).
|
|
16
|
+
const PERMISSION_FLAGS: ReadonlyArray<string> = ['--permission-mode', 'bypassPermissions']
|
|
17
|
+
const AGENT_FLAGS: ReadonlyArray<string> = [
|
|
18
|
+
'-p',
|
|
19
|
+
'--verbose',
|
|
20
|
+
'--output-format',
|
|
21
|
+
'stream-json',
|
|
22
|
+
...PERMISSION_FLAGS,
|
|
23
|
+
]
|
|
12
24
|
const MODEL_FLAG = '--model'
|
|
13
25
|
const EFFORT_FLAG = '--effort'
|
|
14
26
|
// Resumes a stored session by id. An `outage` re-dispatch passes the
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
import { fileURLToPath } from 'node:url'
|
|
3
|
+
import { parseArgs } from 'node:util'
|
|
4
|
+
import { execa } from 'execa'
|
|
5
|
+
import { claude_token } from './claude-token'
|
|
6
|
+
import { claude_token_output } from './claude-token-output'
|
|
7
|
+
|
|
8
|
+
// `josh auth:setup` — run `claude setup-token` and keep the token it prints in the macOS keychain,
|
|
9
|
+
// where `josh fresh:run` reads it. The token reaches neither the screen nor a file: it is replaced in
|
|
10
|
+
// the command's output. `--check` answers whether one is saved.
|
|
11
|
+
|
|
12
|
+
const ARGV_OFFSET = 2
|
|
13
|
+
const FAILURE_EXIT_CODE = 1
|
|
14
|
+
const CLAUDE = 'claude'
|
|
15
|
+
const SAVED = `saved: ${claude_token.VARIABLE} (macOS keychain)`
|
|
16
|
+
const NO_TOKEN = 'claude setup-token printed no token, so nothing was saved.'
|
|
17
|
+
const NO_KEYCHAIN = `This machine has no macOS keychain, so nothing was run. Run \`claude setup-token\` yourself and export ${claude_token.VARIABLE} — josh fresh:run reads it when the keychain has none.`
|
|
18
|
+
const NOT_SAVED = 'The keychain did not keep the token. Run `pnpm josh auth:setup` again.'
|
|
19
|
+
|
|
20
|
+
interface Printed {
|
|
21
|
+
decoder: TextDecoder
|
|
22
|
+
text: string
|
|
23
|
+
shown: number
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function refuse(message: string): number {
|
|
27
|
+
console.error(message)
|
|
28
|
+
|
|
29
|
+
return FAILURE_EXIT_CODE
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function check(): number {
|
|
33
|
+
const date = claude_token.saved_date()
|
|
34
|
+
|
|
35
|
+
if (date === undefined) {
|
|
36
|
+
return refuse(`missing: no ${claude_token.VARIABLE} saved. ${claude_token.SETUP_HINT}`)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
console.info(`ok: ${claude_token.VARIABLE} saved on ${date} (macOS keychain)`)
|
|
40
|
+
|
|
41
|
+
return 0
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function store(token: string | undefined): number {
|
|
45
|
+
if (token === undefined) return refuse(NO_TOKEN)
|
|
46
|
+
|
|
47
|
+
if (!claude_token.save(token)) return refuse(NOT_SAVED)
|
|
48
|
+
|
|
49
|
+
console.info(SAVED)
|
|
50
|
+
|
|
51
|
+
return 0
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// The sign-in URL and any prompt are shown as they arrive; from the token on, the output is held
|
|
55
|
+
// back and shown once claude ends, with the token replaced.
|
|
56
|
+
function show_live(printed: Printed, chunk: Uint8Array): void {
|
|
57
|
+
printed.text += printed.decoder.decode(chunk, { stream: true })
|
|
58
|
+
const live = claude_token_output.live_length(printed.text)
|
|
59
|
+
|
|
60
|
+
process.stdout.write(printed.text.slice(printed.shown, live))
|
|
61
|
+
printed.shown = live
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// The browser sign-in needs the terminal's stdin, so only stdout passes through josh.
|
|
65
|
+
async function setup(): Promise<number> {
|
|
66
|
+
if (!claude_token.has_keychain()) return refuse(NO_KEYCHAIN)
|
|
67
|
+
|
|
68
|
+
const printed: Printed = { decoder: new TextDecoder(), text: '', shown: 0 }
|
|
69
|
+
const child = execa(CLAUDE, ['setup-token'], {
|
|
70
|
+
stdin: 'inherit',
|
|
71
|
+
stderr: 'inherit',
|
|
72
|
+
reject: false,
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
child.stdout.on('data', (chunk: Uint8Array) => {
|
|
76
|
+
show_live(printed, chunk)
|
|
77
|
+
})
|
|
78
|
+
const result = await child
|
|
79
|
+
const held = printed.text.slice(printed.shown) + printed.decoder.decode()
|
|
80
|
+
const { token, shown } = claude_token_output.capture(held)
|
|
81
|
+
|
|
82
|
+
process.stdout.write(shown)
|
|
83
|
+
|
|
84
|
+
if (result.failed) return refuse(`claude setup-token failed: ${result.shortMessage ?? CLAUDE}`)
|
|
85
|
+
|
|
86
|
+
return store(token)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async function run(argv: ReadonlyArray<string>): Promise<number> {
|
|
90
|
+
const { values } = parseArgs({ args: [...argv], options: { check: { type: 'boolean' } } })
|
|
91
|
+
|
|
92
|
+
return values.check === true ? check() : await setup()
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const auth_setup_cli = { run }
|
|
96
|
+
|
|
97
|
+
if (process.argv[1] === fileURLToPath(import.meta.url)) {
|
|
98
|
+
process.exitCode = await run(process.argv.slice(ARGV_OFFSET))
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export { auth_setup_cli }
|