@joshuafolkken/kit 1.1379.0 → 1.1387.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/workflow-commands/backlogrun-progress.md +2 -3
- package/.claude/skills/workflow-commands/backlogrun-steps.md +2 -4
- package/.claude/skills/workflow-commands/retrospective.md +1 -2
- package/dist/hooks/batch-guard.js +6 -6
- package/dist/hooks/{chunk-RW4XMF47.js → chunk-2YSW3CXH.js} +133 -234
- package/dist/hooks/{chunk-4RWRP3FF.js → chunk-DCY2GWHC.js} +5 -5
- package/dist/hooks/{chunk-DHSKBAQ2.js → chunk-EAQEGME7.js} +1 -1
- package/dist/hooks/{chunk-E7LZL5AN.js → chunk-EBSHN25W.js} +3 -3
- package/dist/hooks/{chunk-HGA4EG5S.js → chunk-GJ7JPIHN.js} +15 -15
- package/dist/hooks/{chunk-TG2AB3W6.js → chunk-GNDJ7NJ7.js} +88 -501
- package/dist/hooks/{chunk-546X4PX3.js → chunk-IYVOLN6A.js} +3 -3
- package/dist/hooks/{chunk-NBEAGPS4.js → chunk-J3KSS7II.js} +1 -1
- package/dist/hooks/{chunk-7ZM464OW.js → chunk-LMWBRJIP.js} +3 -3
- package/dist/hooks/{chunk-TORRSNDJ.js → chunk-SL4GQ2XP.js} +3 -3
- package/dist/hooks/{chunk-PV3FWDSQ.js → chunk-STDSEPWU.js} +2 -2
- package/dist/hooks/{chunk-YSDAH73S.js → chunk-U32VSRNG.js} +420 -4
- package/dist/hooks/{chunk-QARPP36N.js → chunk-WNFJLBXI.js} +3 -3
- package/dist/hooks/codex-hook-adapter.js +13 -13
- package/dist/hooks/duplicate-read-guard.js +7 -7
- package/dist/hooks/format-edited.js +3 -3
- package/dist/hooks/inputs.json +213 -212
- package/dist/hooks/investigation-guard.js +7 -7
- package/dist/hooks/pretool-guard.js +12 -12
- package/dist/hooks/session-lang.js +65 -9
- package/dist/hooks/stop-guard.js +104 -32
- package/dist/josh.js +2 -2
- package/package.json +1 -1
- package/prompts/collaboration-workflow/upstream-interrupt.md +1 -1
- package/scripts/backlog/backlog-budget-cli.ts +2 -20
- package/scripts/backlog/backlog-budget.ts +72 -109
- package/scripts/backlog/backlog-drive-cli.ts +12 -7
- package/scripts/backlog/backlog-drive-launch.ts +2 -0
- package/scripts/backlog/backlog-drive-owner.ts +72 -5
- package/scripts/backlog/backlog-drive.ts +5 -2
- package/scripts/backlog/backlog-offer-cli.ts +1 -15
- package/scripts/backlog/backlogrun-launch.ts +56 -5
- package/scripts/document/document-byte-budget.ts +1 -1
- package/scripts/epic/epic-candidate-confirm.ts +1 -1
- package/scripts/epic/epic-cross-repo.ts +4 -4
- package/scripts/epic/epic-next.ts +1 -1
- package/scripts/hooks/stop-guard.ts +20 -9
- package/scripts/init/start-plan.ts +15 -4
- package/scripts/init/start-steps.ts +31 -3
- package/scripts/init/start.ts +20 -13
- package/scripts/josh/josh-commands-ai.ts +1 -1
- package/scripts/josh/josh-commands-project.ts +1 -1
- package/scripts/lane/lane-cli.ts +1 -3
- package/scripts/run/board/run-board-header.ts +137 -88
- package/scripts/run/board/run-board-labels.ts +18 -17
- package/scripts/run/board/run-board-machine.ts +21 -8
- package/scripts/run/board/run-board-read.ts +9 -2
- package/scripts/run/board/run-board-render.ts +1 -5
- package/scripts/run/board/run-board-setup.ts +73 -0
- package/scripts/run/board/run-board-span.ts +49 -8
- package/scripts/run/board/run-board-status.ts +10 -23
- package/scripts/run/board/run-board-tick.ts +11 -2
- package/scripts/run/carry/run-carry-added.ts +1 -1
- package/scripts/run/carry/run-carry-change.ts +1 -1
- package/scripts/run/carry/run-carry-cli.ts +36 -60
- package/scripts/run/carry/run-carry-ended.ts +10 -2
- package/scripts/run/carry/run-carry.ts +38 -68
- package/scripts/run/cut/run-cut.ts +4 -4
- package/scripts/run/event/run-event-render.ts +1 -1
- package/scripts/run/event/run-event-scope.ts +4 -8
- package/scripts/run/event/run-event-setup.ts +47 -0
- package/scripts/run/event/run-event-stream-emit.ts +0 -25
- package/scripts/run/event/run-event-stream.ts +41 -28
- package/scripts/run/merge/run-merge-collect.ts +1 -1
- package/scripts/run/merge/run-merge-steps.ts +1 -1
- package/scripts/run/progress/run-progress-read.ts +1 -1
- package/scripts/run/run-headless.ts +2 -2
- package/scripts/run/run-status-cli.ts +1 -5
- package/scripts/run/run-step.ts +2 -9
- package/scripts/run/run-stop-notify.ts +1 -1
- package/scripts/run/run-stranded-detect.ts +61 -15
- package/scripts/run/run-stranded.ts +25 -17
- package/scripts/run/wake/run-wake-cli.ts +58 -15
- package/scripts/run/wake/run-wake-describe.ts +5 -5
- package/scripts/run/wake/run-wake-driver.ts +13 -4
- package/scripts/run/wake/run-wake-handoff.ts +1 -1
- package/scripts/run/wake/run-wake-loop.ts +4 -21
- package/scripts/run/wake/run-wake-restart.ts +1 -1
- package/scripts/run/wake/run-wake.ts +6 -7
- package/scripts/backlog/backlog-idle.ts +0 -88
|
@@ -6,17 +6,23 @@ import {
|
|
|
6
6
|
agent_role_profile,
|
|
7
7
|
detached_launch,
|
|
8
8
|
git_common_directory,
|
|
9
|
+
issue_cite,
|
|
10
|
+
run_event_stream,
|
|
11
|
+
run_event_stream_emit,
|
|
9
12
|
run_headless
|
|
10
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-U32VSRNG.js";
|
|
14
|
+
import {
|
|
15
|
+
error_text
|
|
16
|
+
} from "./chunk-CDY4NFQG.js";
|
|
11
17
|
import {
|
|
12
18
|
josh_environment_file
|
|
13
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-J3KSS7II.js";
|
|
14
20
|
import {
|
|
15
21
|
agent_session_environment,
|
|
16
22
|
json_value,
|
|
17
23
|
process_identity,
|
|
18
24
|
run_carry
|
|
19
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-2YSW3CXH.js";
|
|
20
26
|
import {
|
|
21
27
|
stamp_file
|
|
22
28
|
} from "./chunk-NEC4AT4Z.js";
|
|
@@ -298,6 +304,32 @@ var agent_argv = {
|
|
|
298
304
|
with_resume_in
|
|
299
305
|
};
|
|
300
306
|
|
|
307
|
+
// scripts/run/event/run-event-setup.ts
|
|
308
|
+
var STAGE = {
|
|
309
|
+
// `josh backlogrun` started the parent session, which is reading its procedure.
|
|
310
|
+
STARTING: "starting session",
|
|
311
|
+
// `run:carry --begin` claimed the run, and the parent is planning it.
|
|
312
|
+
PLANNING: "planning",
|
|
313
|
+
// The supervisor took the run over from the parent and is asking for the first offer.
|
|
314
|
+
HANDING_OFF: "handing off"
|
|
315
|
+
};
|
|
316
|
+
var OPENING = "opening lane";
|
|
317
|
+
function opening_lane(issue) {
|
|
318
|
+
return `${OPENING} ${issue_cite.plain(issue)}`;
|
|
319
|
+
}
|
|
320
|
+
async function emit(text) {
|
|
321
|
+
await run_event_stream_emit.emit(run_event_stream.EVENT_KIND.SETUP, text);
|
|
322
|
+
}
|
|
323
|
+
function emit_in(repository, text, at) {
|
|
324
|
+
try {
|
|
325
|
+
const target = run_event_stream.target_of(repository);
|
|
326
|
+
run_event_stream.append(target, run_event_stream.EVENT_KIND.SETUP, text, at.toISOString());
|
|
327
|
+
} catch (error) {
|
|
328
|
+
error_text.trace_swallowed("run_event_setup.emit_in", error);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
var run_event_setup = { STAGE, emit, emit_in, opening_lane };
|
|
332
|
+
|
|
301
333
|
// scripts/backlog/backlogrun-launch.ts
|
|
302
334
|
import { z } from "zod";
|
|
303
335
|
var LAUNCH_PREFIX = "josh-backlogrun-launch-";
|
|
@@ -306,7 +338,11 @@ var LOG_SUFFIX = ".log";
|
|
|
306
338
|
var launch_schema = z.object({
|
|
307
339
|
pid: z.number(),
|
|
308
340
|
start: z.string().optional(),
|
|
309
|
-
session: z.string().optional()
|
|
341
|
+
session: z.string().optional(),
|
|
342
|
+
// What the parent was started to run and when, so `run:board` has a run to draw and a clock to count
|
|
343
|
+
// before the parent claims the carry record. Absent on a record an earlier version wrote.
|
|
344
|
+
invocation: z.string().optional(),
|
|
345
|
+
started_at: z.string().optional()
|
|
310
346
|
});
|
|
311
347
|
function launch_path(git_directory) {
|
|
312
348
|
return stamp_file.stamp_path(LAUNCH_PREFIX, git_directory);
|
|
@@ -348,9 +384,27 @@ function argv_of(invocation, provider, worktree, session) {
|
|
|
348
384
|
function note_to_stderr(note) {
|
|
349
385
|
console.error(`backlogrun: ${note}`);
|
|
350
386
|
}
|
|
351
|
-
function record_launch(git_directory,
|
|
352
|
-
const
|
|
353
|
-
|
|
387
|
+
function record_launch(git_directory, launch) {
|
|
388
|
+
const now = /* @__PURE__ */ new Date();
|
|
389
|
+
const identity = process_identity.read_start(launch.pid);
|
|
390
|
+
const record = { ...launch, start: identity, started_at: now.toISOString() };
|
|
391
|
+
stamp_file.replace_stamp(launch_path(git_directory), record);
|
|
392
|
+
run_event_setup.emit_in(git_directory, run_event_setup.STAGE.STARTING, now);
|
|
393
|
+
}
|
|
394
|
+
function live_launch(git_directory) {
|
|
395
|
+
const record = read_launch(launch_path(git_directory));
|
|
396
|
+
return is_launch_live(record) ? record : void 0;
|
|
397
|
+
}
|
|
398
|
+
function pending_launch(git_directory) {
|
|
399
|
+
const { invocation, started_at } = live_launch(git_directory) ?? {};
|
|
400
|
+
if (invocation === void 0 || started_at === void 0) return void 0;
|
|
401
|
+
return { invocation, started_at };
|
|
402
|
+
}
|
|
403
|
+
function started_for(git_directory, owner_pid) {
|
|
404
|
+
const record = live_launch(git_directory);
|
|
405
|
+
if (record?.started_at === void 0 || record.pid !== owner_pid) return void 0;
|
|
406
|
+
const started_ms = Date.parse(record.started_at);
|
|
407
|
+
return Number.isNaN(started_ms) ? void 0 : new Date(started_ms);
|
|
354
408
|
}
|
|
355
409
|
function spawn_parent(argv, provider, target) {
|
|
356
410
|
const environment = {
|
|
@@ -376,7 +430,7 @@ function start(invocation, provider, target) {
|
|
|
376
430
|
if (built.kind === "rejected") return { kind: "failed", note: built.note };
|
|
377
431
|
const result = spawn_parent(built, provider, target);
|
|
378
432
|
if (result.kind === "failed") return result;
|
|
379
|
-
record_launch(target.git_directory, result.pid, session);
|
|
433
|
+
record_launch(target.git_directory, { pid: result.pid, session, invocation });
|
|
380
434
|
const launched = { pid: result.pid, session, log_path: log_path(target.git_directory) };
|
|
381
435
|
return { kind: "launched", launched };
|
|
382
436
|
}
|
|
@@ -384,7 +438,9 @@ var backlogrun_launch = {
|
|
|
384
438
|
argv_of,
|
|
385
439
|
chosen_environment,
|
|
386
440
|
is_running,
|
|
387
|
-
|
|
441
|
+
pending_launch,
|
|
442
|
+
start,
|
|
443
|
+
started_for
|
|
388
444
|
};
|
|
389
445
|
|
|
390
446
|
// scripts/josh/session-language-cli.ts
|
package/dist/hooks/stop-guard.js
CHANGED
|
@@ -13,10 +13,8 @@ import {
|
|
|
13
13
|
lane_park,
|
|
14
14
|
repo_party,
|
|
15
15
|
run_cut,
|
|
16
|
-
run_event_stream,
|
|
17
|
-
run_event_stream_emit,
|
|
18
16
|
run_hold
|
|
19
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-GNDJ7NJ7.js";
|
|
20
18
|
import {
|
|
21
19
|
session_language
|
|
22
20
|
} from "./chunk-6V5OPIUU.js";
|
|
@@ -25,23 +23,25 @@ import {
|
|
|
25
23
|
agent_role_profile,
|
|
26
24
|
issue_cite,
|
|
27
25
|
lane_registry,
|
|
26
|
+
run_event_stream,
|
|
27
|
+
run_event_stream_emit,
|
|
28
28
|
run_headless
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-U32VSRNG.js";
|
|
30
30
|
import {
|
|
31
31
|
timed_fetch
|
|
32
32
|
} from "./chunk-FZ6FUSBM.js";
|
|
33
33
|
import "./chunk-CDY4NFQG.js";
|
|
34
34
|
import {
|
|
35
35
|
hook_decision
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-EBSHN25W.js";
|
|
37
37
|
import {
|
|
38
38
|
time_density_hook,
|
|
39
39
|
time_hook_transcript,
|
|
40
40
|
time_reported_failure
|
|
41
|
-
} from "./chunk-
|
|
41
|
+
} from "./chunk-SL4GQ2XP.js";
|
|
42
42
|
import {
|
|
43
43
|
lane_child_marker
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-J3KSS7II.js";
|
|
45
45
|
import {
|
|
46
46
|
backlog_budget,
|
|
47
47
|
issue_number_shape,
|
|
@@ -50,7 +50,7 @@ import {
|
|
|
50
50
|
process_owner_schema,
|
|
51
51
|
run_carry,
|
|
52
52
|
run_invocation
|
|
53
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-2YSW3CXH.js";
|
|
54
54
|
import {
|
|
55
55
|
PROJECT_ROOT,
|
|
56
56
|
stamp_file
|
|
@@ -964,8 +964,53 @@ var run_halfrun_resume = {
|
|
|
964
964
|
take_over
|
|
965
965
|
};
|
|
966
966
|
|
|
967
|
-
// scripts/run/
|
|
967
|
+
// scripts/run/carry/run-carry-ended.ts
|
|
968
|
+
import path from "node:path";
|
|
968
969
|
import { z as z4 } from "zod";
|
|
970
|
+
var ENDED_PREFIX = "josh-run-ended-";
|
|
971
|
+
var TRANSCRIPT_SUFFIX = ".jsonl";
|
|
972
|
+
var ended_run_schema = z4.object({
|
|
973
|
+
invocation: z4.string(),
|
|
974
|
+
started_at: z4.string(),
|
|
975
|
+
ended_at: z4.string(),
|
|
976
|
+
stopped: z4.string().optional(),
|
|
977
|
+
session: z4.string().optional()
|
|
978
|
+
});
|
|
979
|
+
function ended_path(git_directory) {
|
|
980
|
+
return stamp_file.stamp_path(ENDED_PREFIX, git_directory);
|
|
981
|
+
}
|
|
982
|
+
function session_of(transcript) {
|
|
983
|
+
return transcript === void 0 ? void 0 : path.basename(transcript, TRANSCRIPT_SUFFIX);
|
|
984
|
+
}
|
|
985
|
+
function stop_of(transcript, stopped) {
|
|
986
|
+
return stopped === void 0 ? {} : { stopped, session: session_of(transcript) };
|
|
987
|
+
}
|
|
988
|
+
function record_ended(target, read, now = /* @__PURE__ */ new Date(), stopped) {
|
|
989
|
+
if (read.kind !== "carried") return;
|
|
990
|
+
const { invocation, started_at, owner_transcript } = read.carry;
|
|
991
|
+
const ended_at = now.toISOString();
|
|
992
|
+
stamp_file.replace_stamp(target, {
|
|
993
|
+
invocation,
|
|
994
|
+
started_at,
|
|
995
|
+
ended_at,
|
|
996
|
+
...stop_of(owner_transcript, stopped)
|
|
997
|
+
});
|
|
998
|
+
}
|
|
999
|
+
function parse_ended(raw) {
|
|
1000
|
+
return json_value.parse_with(raw, ended_run_schema);
|
|
1001
|
+
}
|
|
1002
|
+
function read_ended(target) {
|
|
1003
|
+
const raw = stamp_file.read_stamp_text(target);
|
|
1004
|
+
return raw === void 0 ? void 0 : parse_ended(raw);
|
|
1005
|
+
}
|
|
1006
|
+
function has_ended(target, started_at) {
|
|
1007
|
+
const ended = read_ended(target);
|
|
1008
|
+
return ended !== void 0 && ended.started_at === started_at;
|
|
1009
|
+
}
|
|
1010
|
+
var run_carry_ended = { ended_path, has_ended, read_ended, record_ended };
|
|
1011
|
+
|
|
1012
|
+
// scripts/run/wake/run-wake.ts
|
|
1013
|
+
import { z as z5 } from "zod";
|
|
969
1014
|
var WAKE_PREFIX = "josh-run-wake-";
|
|
970
1015
|
var WAKE_LOG_PREFIX = "josh-run-wake-log-";
|
|
971
1016
|
var WAKE_LOG_SUFFIX = ".log";
|
|
@@ -981,19 +1026,18 @@ var PENDING_DECISION = { kind: "pending" };
|
|
|
981
1026
|
var FAILED_DECISION = { kind: "failed" };
|
|
982
1027
|
var STOP_REASONS = {
|
|
983
1028
|
none: "ended",
|
|
984
|
-
expired: "expired",
|
|
985
1029
|
unreadable: "unreadable"
|
|
986
1030
|
};
|
|
987
1031
|
var run_wake_schema = process_owner_schema.extend({
|
|
988
|
-
invocation:
|
|
989
|
-
started_at:
|
|
990
|
-
woke:
|
|
991
|
-
woke_at:
|
|
1032
|
+
invocation: z5.string(),
|
|
1033
|
+
started_at: z5.string(),
|
|
1034
|
+
woke: z5.number(),
|
|
1035
|
+
woke_at: z5.string().optional(),
|
|
992
1036
|
// Every optional `RunWake` field must be listed: `z.object` strips undeclared ones on the round trip.
|
|
993
|
-
attempts:
|
|
994
|
-
woke_pid:
|
|
995
|
-
spawned:
|
|
996
|
-
idle_since:
|
|
1037
|
+
attempts: z5.number().optional(),
|
|
1038
|
+
woke_pid: z5.number().optional(),
|
|
1039
|
+
spawned: z5.array(z5.string()).optional(),
|
|
1040
|
+
idle_since: z5.string().optional(),
|
|
997
1041
|
profile: agent_role_profile.PROFILE_SCHEMA.optional()
|
|
998
1042
|
});
|
|
999
1043
|
function is_overdue(marked_at, now, limit_ms = WAKE_GRACE_MS) {
|
|
@@ -1157,14 +1201,17 @@ function supervisor_liveness(wake, same_process = process_identity.is_same_proce
|
|
|
1157
1201
|
if (is_same === void 0) return UNKNOWN;
|
|
1158
1202
|
return is_same ? LIVE : GONE;
|
|
1159
1203
|
}
|
|
1204
|
+
function had_driver(carry) {
|
|
1205
|
+
return carry.is_handed_off === true || carry.owner_pid !== void 0;
|
|
1206
|
+
}
|
|
1160
1207
|
function is_stranded(input) {
|
|
1161
|
-
if (input.read.kind !== "carried" || input.
|
|
1208
|
+
if (input.read.kind !== "carried" || input.is_owner_live || !had_driver(input.read.carry)) {
|
|
1162
1209
|
return false;
|
|
1163
1210
|
}
|
|
1164
1211
|
return input.supervisor === GONE;
|
|
1165
1212
|
}
|
|
1166
1213
|
function describe2(carry) {
|
|
1167
|
-
return `Run stranded \u2014 ${run_carry.describe_carry(carry)}. The owner is gone, no
|
|
1214
|
+
return `Run stranded \u2014 ${run_carry.describe_carry(carry)}. The owner is gone, no successor holds the budget, and no supervisor is watching.`;
|
|
1168
1215
|
}
|
|
1169
1216
|
function verdict_of(is_run_stranded) {
|
|
1170
1217
|
return is_run_stranded ? STRANDED : OK2;
|
|
@@ -1184,10 +1231,12 @@ var run_stranded = {
|
|
|
1184
1231
|
|
|
1185
1232
|
// scripts/run/run-stranded-detect.ts
|
|
1186
1233
|
var STRAND_RECOVERY = `Restart supervision with \`${run_stranded.RECOVERY_COMMAND}\` \u2014 it wakes a fresh successor to claim the budget; the cutting session must not resume it itself.`;
|
|
1234
|
+
function targets_of(directory) {
|
|
1235
|
+
return { carry: run_carry.carry_path(directory), wake: run_wake.wake_path(directory) };
|
|
1236
|
+
}
|
|
1187
1237
|
async function real_resolve_targets() {
|
|
1188
1238
|
const directory = await run_carry.repository_directory();
|
|
1189
|
-
|
|
1190
|
-
return { carry: run_carry.carry_path(directory), wake: run_wake.wake_path(directory) };
|
|
1239
|
+
return directory === void 0 ? void 0 : targets_of(directory);
|
|
1191
1240
|
}
|
|
1192
1241
|
async function real_emit_stranded(text2) {
|
|
1193
1242
|
return await run_event_stream_emit.emit_once(run_event_stream.EVENT_KIND.STRANDED, text2);
|
|
@@ -1199,14 +1248,13 @@ var DEFAULT_PORTS3 = {
|
|
|
1199
1248
|
resolve_targets: real_resolve_targets,
|
|
1200
1249
|
read_carry: (target) => run_carry.read_carry(target),
|
|
1201
1250
|
is_owner_live: run_carry.is_owner_live,
|
|
1251
|
+
has_ended: run_carry_ended.has_ended,
|
|
1202
1252
|
read_wake: (target) => run_wake.read_wake(target),
|
|
1203
1253
|
supervisor_liveness: (wake) => run_stranded.supervisor_liveness(wake),
|
|
1204
1254
|
emit_stranded: real_emit_stranded,
|
|
1205
1255
|
notify_stranded: real_notify_stranded
|
|
1206
1256
|
};
|
|
1207
|
-
|
|
1208
|
-
const targets = await ports.resolve_targets();
|
|
1209
|
-
if (targets === void 0) return void 0;
|
|
1257
|
+
function input_at(ports, targets) {
|
|
1210
1258
|
const read = ports.read_carry(targets.carry);
|
|
1211
1259
|
if (read.kind !== "carried") return void 0;
|
|
1212
1260
|
return {
|
|
@@ -1215,6 +1263,10 @@ async function gather2(ports) {
|
|
|
1215
1263
|
supervisor: ports.supervisor_liveness(ports.read_wake(targets.wake))
|
|
1216
1264
|
};
|
|
1217
1265
|
}
|
|
1266
|
+
async function gather2(ports) {
|
|
1267
|
+
const targets = await ports.resolve_targets();
|
|
1268
|
+
return targets === void 0 ? void 0 : input_at(ports, targets);
|
|
1269
|
+
}
|
|
1218
1270
|
async function report2(ports, input) {
|
|
1219
1271
|
if (input.read.kind !== "carried") return;
|
|
1220
1272
|
const text2 = run_stranded.describe(input.read.carry);
|
|
@@ -1233,7 +1285,25 @@ async function run_stranded_check() {
|
|
|
1233
1285
|
} catch {
|
|
1234
1286
|
}
|
|
1235
1287
|
}
|
|
1236
|
-
|
|
1288
|
+
function is_stranded_at(directory, ports = DEFAULT_PORTS3) {
|
|
1289
|
+
const input = input_at(ports, targets_of(directory));
|
|
1290
|
+
return input !== void 0 && run_stranded.is_stranded(input);
|
|
1291
|
+
}
|
|
1292
|
+
function is_left_stranded(run, ports = DEFAULT_PORTS3) {
|
|
1293
|
+
const read = ports.read_carry(run.carry_target);
|
|
1294
|
+
if (read.kind !== "carried") return !ports.has_ended(run.ended_target, run.started_at);
|
|
1295
|
+
return run_stranded.is_stranded({
|
|
1296
|
+
read,
|
|
1297
|
+
is_owner_live: run_carry.is_held_by_another(read.carry, ports.is_owner_live),
|
|
1298
|
+
supervisor: run_stranded.GONE
|
|
1299
|
+
});
|
|
1300
|
+
}
|
|
1301
|
+
var run_stranded_detect = {
|
|
1302
|
+
detect_and_report: detect_and_report2,
|
|
1303
|
+
is_left_stranded,
|
|
1304
|
+
is_stranded_at,
|
|
1305
|
+
run_stranded_check
|
|
1306
|
+
};
|
|
1237
1307
|
|
|
1238
1308
|
// scripts/hooks/stop-guard.ts
|
|
1239
1309
|
async function hold_facts() {
|
|
@@ -1295,18 +1365,20 @@ async function outcome_of(raw_payload) {
|
|
|
1295
1365
|
return stop_rules.NO_OUTCOME;
|
|
1296
1366
|
}
|
|
1297
1367
|
}
|
|
1298
|
-
async function
|
|
1368
|
+
async function carried_owner_live() {
|
|
1299
1369
|
try {
|
|
1300
1370
|
const directory = await run_carry.repository_directory();
|
|
1301
|
-
if (directory === void 0) return
|
|
1302
|
-
|
|
1371
|
+
if (directory === void 0) return void 0;
|
|
1372
|
+
const read = run_carry.read_carry(run_carry.carry_path(directory));
|
|
1373
|
+
return read.kind === "carried" ? run_carry.is_owner_live(read.carry) : void 0;
|
|
1303
1374
|
} catch {
|
|
1304
|
-
return
|
|
1375
|
+
return void 0;
|
|
1305
1376
|
}
|
|
1306
1377
|
}
|
|
1307
1378
|
async function run_report_checks() {
|
|
1308
|
-
|
|
1309
|
-
|
|
1379
|
+
const is_owner_live = await carried_owner_live();
|
|
1380
|
+
if (is_owner_live === void 0) return;
|
|
1381
|
+
if (is_owner_live) await backlog_stalled_detect.run_stall_check(backlog_ready.DEFAULT_PORTS);
|
|
1310
1382
|
await run_stranded_detect.run_stranded_check();
|
|
1311
1383
|
}
|
|
1312
1384
|
async function write_stop_decision(raw_payload) {
|
package/dist/josh.js
CHANGED
|
@@ -1867,7 +1867,7 @@ var AI_COMMANDS = {
|
|
|
1867
1867
|
// `.env` rather than the ambient environment: the strand notification needs the Telegram
|
|
1868
1868
|
// credentials, the same reason `run:wake` carries these flags.
|
|
1869
1869
|
tsx_arguments: OPTIONAL_ENV_FILE_FLAGS,
|
|
1870
|
-
description: "Report whether the run is stranded \u2014
|
|
1870
|
+
description: "Report whether the run is stranded \u2014 owner gone, no successor holding the budget, and no supervisor watching",
|
|
1871
1871
|
category: "AI tools",
|
|
1872
1872
|
reference: ["", "automation", ["processes", "notifications"]]
|
|
1873
1873
|
},
|
|
@@ -2501,7 +2501,7 @@ var PROJECT_COMMANDS = {
|
|
|
2501
2501
|
description: "Set a project up for the GitHub Issue workflow, from git init to the setup PR",
|
|
2502
2502
|
category: "Project",
|
|
2503
2503
|
reference: [
|
|
2504
|
-
`${PROFILE_ARGUMENTS} [--yes] [--github] [--public] [--init-command <command>]`,
|
|
2504
|
+
`${PROFILE_ARGUMENTS} [--yes] [--github] [--public] [--init-command <command>] [--push-preflight-command <command>]`,
|
|
2505
2505
|
"developer",
|
|
2506
2506
|
["files", "git", "network", "processes"]
|
|
2507
2507
|
]
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.
|
|
2
|
+
"version": "1.1387.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": [
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
1. **起票する** — `pnpm josh issue:file "<title>" --body-file <path> --depth <n> --route interrupt --label priority:high`。上限は効かない(`wip-cap.md` →「割り込み起票 — 上限が効かない側」の条件 2)
|
|
19
19
|
2. **止まらずに直す** — 壊れた機構を迂回しない(回避策の禁止と、検証ゲートを緩めない規則はここでも変わらない)。`backlogrun` の中では、その割り込みを次の子にし、修正が着地してから塞がれていた子へ戻る。プールから選ぶランでは `priority:high` が先頭に並べ、epic の下では `wip-cap.md` の手順 3 で挿入する。名前を指定したランのドライバーは指定された Issue しか出さないので、`pnpm josh lane:launch <N>` で自分で dispatch する。バッチの外では `wip-cap.md` の手順 4 が変わらず効く — 起票まで済ませ、打つべき `fullrun #<N>` を報告して止まる
|
|
20
20
|
3. **再開できるなら自分で再開し、動くことを確かめる** — 修正のマージ後、再開の手段がある答えには人の打ち直しを求めない。手渡し済みの記録、所有者が死んだ記録、監督プロセスの停止(`warning` Telegram)には `pnpm josh run:wake --start`、`run:carry` の `standing` には `pnpm josh run:carry --resume "<invocation>" --owner "$PPID"` を自分で打つ。そのあと `pnpm josh run:wake --list` が監督プロセスを示し、そのログに次の子の dispatch が現れることを確かめて報告する
|
|
21
|
-
4. **人に打ち直しを求めるのは再開の手段が無いときだけ** — `
|
|
21
|
+
4. **人に打ち直しを求めるのは再開の手段が無いときだけ** — `mismatch`(別の起動の記録)、別の生きた所有者の `busy`。新しい承認を宣言するのは人だけ、という規則も変わらない
|
|
22
22
|
5. **`needs-decision` を付けない** — ランが自分で直せる不具合は人の判断を要さない(`.claude/skills/workflow-commands/backlogrun-park.md` → "Only a person's judgement carries `needs-decision`")
|
|
23
23
|
|
|
24
24
|
手順:
|
|
@@ -8,7 +8,6 @@ import {
|
|
|
8
8
|
type BudgetDecision,
|
|
9
9
|
type BudgetInput,
|
|
10
10
|
} from './backlog-budget'
|
|
11
|
-
import { backlog_idle } from './backlog-idle'
|
|
12
11
|
|
|
13
12
|
// The thin half of `josh backlog:budget` (joshuafolkken/kit#1632): read the loop's state off the
|
|
14
13
|
// command line, hand it to the pure decision, print the verdict on stdout and the reason on stderr
|
|
@@ -18,7 +17,6 @@ const ARGV_OFFSET = 2
|
|
|
18
17
|
const SUCCESS_EXIT_CODE = 0
|
|
19
18
|
const FAILURE_EXIT_CODE = 1
|
|
20
19
|
const JSON_KEY = 'budget'
|
|
21
|
-
const EXHAUSTED_ANSWER: BacklogAnswer = 'exhausted'
|
|
22
20
|
|
|
23
21
|
const USAGE = `Usage: josh backlog:budget --answer <${backlog_budget.ANSWERS.join('|')}> --started <ISO-8601> [--active <ISO-8601>, required unless the watch is off] [--merged <count>] [--running <count>] [--max <count>] [--idle <minutes>, 0 to turn the watch off] [--json]`
|
|
24
22
|
|
|
@@ -71,7 +69,7 @@ function to_count(raw: string | undefined): number | undefined {
|
|
|
71
69
|
|
|
72
70
|
// A flag that was given but could not be read makes the whole invocation unreadable. Falling back to
|
|
73
71
|
// the default instead would answer a question nobody asked — a mistyped `--idle 0` would read as the
|
|
74
|
-
// default
|
|
72
|
+
// default watch and hold a run open that was asked to finish at its first empty backlog.
|
|
75
73
|
function is_readable(raw: string | undefined, parsed: number | undefined): boolean {
|
|
76
74
|
return raw === undefined || parsed !== undefined
|
|
77
75
|
}
|
|
@@ -165,27 +163,11 @@ function build_input(values: ParsedValues, now_ms: number): BudgetInput | undefi
|
|
|
165
163
|
return input_of(values, { answer, now_ms, started_at_ms })
|
|
166
164
|
}
|
|
167
165
|
|
|
168
|
-
// The idle window, carried only on the watch an empty backlog opens — the one `idle_decision` reaches,
|
|
169
|
-
// not the draining watch a reached bound returns while children still run — so `backlog:offer` can
|
|
170
|
-
// record when that wait ends (joshuafolkken/kit#3430).
|
|
171
|
-
function idle_of(input: BudgetInput, verdict: string): string | undefined {
|
|
172
|
-
const is_idle_watch =
|
|
173
|
-
verdict === backlog_budget.WATCH_VERDICT &&
|
|
174
|
-
input.answer === EXHAUSTED_ANSWER &&
|
|
175
|
-
backlog_budget.is_finish(input)
|
|
176
|
-
const window = is_idle_watch ? backlog_idle.window_of(input) : undefined
|
|
177
|
-
|
|
178
|
-
return window === undefined ? undefined : backlog_idle.text_of(window)
|
|
179
|
-
}
|
|
180
|
-
|
|
181
166
|
function print_json(input: BudgetInput, decision: BudgetDecision): void {
|
|
182
167
|
const { verdict, reason } = decision
|
|
183
|
-
const idle = idle_of(input, verdict)
|
|
184
168
|
const is_finish = backlog_budget.is_finish(input)
|
|
185
169
|
|
|
186
|
-
console.info(
|
|
187
|
-
JSON.stringify({ [JSON_KEY]: verdict, reason, is_finish, ...(idle !== undefined && { idle }) }),
|
|
188
|
-
)
|
|
170
|
+
console.info(JSON.stringify({ [JSON_KEY]: verdict, reason, is_finish }))
|
|
189
171
|
}
|
|
190
172
|
|
|
191
173
|
function refuse(): number {
|