@joshuafolkken/kit 1.1128.0 → 1.1136.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/agents/investigator.md +17 -0
- package/.claude/settings.json +1 -0
- package/.claude/skills/workflow-commands/backlogrun-progress.md +2 -2
- package/.claude/skills/workflow-commands/delegation.md +5 -1
- package/SECURITY.md +1 -0
- package/dist/hooks/batch-guard.js +4 -4
- package/dist/hooks/{chunk-77J7IEQM.js → chunk-FO2I7UT7.js} +1 -1
- package/dist/hooks/{chunk-4JZDP5X5.js → chunk-GDU26K3J.js} +9 -1
- package/dist/hooks/{chunk-QVLT52OV.js → chunk-HANSKHES.js} +2 -2
- package/dist/hooks/{chunk-5SD2YM7Z.js → chunk-HBKZLITF.js} +4 -4
- package/dist/hooks/{chunk-AIOIOMPX.js → chunk-JKKTVDAG.js} +128 -61
- package/dist/hooks/{chunk-M7QKEKWO.js → chunk-KBXZLMRH.js} +9 -28
- package/dist/hooks/{chunk-XYUIQOW3.js → chunk-KOKOAV6D.js} +2 -2
- package/dist/hooks/{chunk-NXYMNPUQ.js → chunk-LJBLGHEH.js} +59 -19
- package/dist/hooks/{chunk-MKVGBQPA.js → chunk-NFZGFGOR.js} +1 -1
- package/dist/hooks/{chunk-7HVB7SZG.js → chunk-RFWWUI5F.js} +4 -4
- package/dist/hooks/codex-hook-adapter.js +10 -10
- package/dist/hooks/duplicate-read-guard.js +5 -5
- package/dist/hooks/format-edited.js +2 -2
- package/dist/hooks/inputs.json +199 -198
- package/dist/hooks/investigation-guard.js +5 -5
- package/dist/hooks/pretool-guard.js +9 -9
- package/dist/hooks/stop-guard.js +3 -3
- package/dist/josh.js +8 -1
- package/package.json +6 -4
- package/scripts/delegation/delegation-policy.ts +9 -1
- package/scripts/delegation/investigation-guard.ts +1 -1
- package/scripts/delegation/investigation-reads.ts +105 -19
- package/scripts/document/capped-print.ts +74 -0
- package/scripts/document/document-section-cli.ts +4 -3
- package/scripts/gate/scoped-green.ts +25 -14
- package/scripts/init/claude-kit-only-settings.ts +29 -0
- package/scripts/init/init-copy-content.ts +8 -2
- package/scripts/init/initial-commit.ts +24 -0
- package/scripts/init/start-exec.ts +16 -3
- package/scripts/init/start-steps.ts +8 -12
- package/scripts/issue/issue-read-cli.ts +1 -0
- package/scripts/issue/issue-report-failures.ts +6 -2
- package/scripts/issue/issue-state-cli.ts +1 -1
- package/scripts/josh/josh-commands-lane.ts +1 -1
- package/scripts/josh/josh-commands-project.ts +7 -0
- package/scripts/lane/lane-await.ts +46 -2
- package/scripts/lane/lane-cli.ts +11 -13
- package/scripts/release/github-release-environment.ts +1 -0
- package/scripts/release/github-release.ts +103 -17
- package/scripts/run/run-carry-cli.ts +3 -1
- package/scripts/run/run-carry-conversation.ts +94 -0
- package/scripts/run/run-carry-reclaim.ts +37 -0
- package/scripts/run/run-carry.ts +21 -5
- package/scripts/run/run-merge-steps.ts +4 -1
- package/scripts/test/test-related.ts +1 -6
- package/scripts/test/test-unit-guard.ts +21 -7
- package/scripts/time-runtime/time-spans.ts +4 -0
- package/templates/workflows/github-release.yml +13 -25
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: investigator
|
|
3
|
+
description: Read-only investigation unit for the pre-implementation reading — finds out how an Issue's subject currently works and returns the conclusion with its `file:line` citations, never the file text. Dispatch it when `pnpm josh investigation:guard` asks for a delegated unit, or when `pnpm josh delegate investigation` answers `delegate`.
|
|
4
|
+
tools: Read, Grep, Glob, Bash
|
|
5
|
+
effort: low
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
You are an investigation unit dispatched by a run that is about to implement an Issue. Your job is
|
|
9
|
+
to find out **how the subject currently works**, not what to change.
|
|
10
|
+
|
|
11
|
+
- Start from what the brief says the main line already concluded; do not re-read what it lists as read.
|
|
12
|
+
- Search and read freely — this context is yours, and keeping it out of the main line is why you exist.
|
|
13
|
+
- Never edit, stage or commit anything. A throwaway probe script may be written to the session
|
|
14
|
+
scratchpad, run, and deleted; return its output alone.
|
|
15
|
+
- Return the conclusion plus the `file:line` citations that support each claim. Never paste file
|
|
16
|
+
text beyond a short quoted line — the main line opens the cited lines to verify you.
|
|
17
|
+
- Report what the code does, never a root cause or a fix: deciding that stays in the main line.
|
package/.claude/settings.json
CHANGED
|
@@ -177,10 +177,10 @@ run in lanes".
|
|
|
177
177
|
that lane's `lane:open`.
|
|
178
178
|
|
|
179
179
|
**Start the unit without blocking on it — `pnpm josh lane:dispatch <N>` when the child runs in a
|
|
180
|
-
lane — and in the same turn start `pnpm josh lane:await <N
|
|
180
|
+
lane — and in the same turn start `pnpm josh lane:await <N...> --owner "$PPID"` in the background** (joshuafolkken/kit#2113).
|
|
181
181
|
`lane:await` watches local process presence and exits when any named child confirms-complete. **The
|
|
182
182
|
re-confirm delay and poll interval are the command's, not the agent's** — pass only the issue
|
|
183
|
-
numbers. Without that wake (Codex), hand off instead — "A parent without a completion callback".
|
|
183
|
+
numbers and `--owner` (why: `docs/josh-commands-automation.md` → `josh lane:await`). Without that wake (Codex), hand off instead — "A parent without a completion callback".
|
|
184
184
|
|
|
185
185
|
**A `lane:await` wake is a confirmed-gone process, so classify the ending at once — do not wait out
|
|
186
186
|
the silent-unit window** (joshuafolkken/kit#2277). On a `lane:await` wake go straight to `pnpm josh run:merge <N> --output <path>` — the composite reads the child's **exit
|
|
@@ -40,7 +40,11 @@ a temporary probe script and return its output.
|
|
|
40
40
|
**The threshold is 3 files, and it is a count, not a forecast.** When the next read reaches it,
|
|
41
41
|
delegate the unread investigation. Brief the unit on what was already read; do not re-read it there.
|
|
42
42
|
**A delegation resets the counter rather than spending it**; `pnpm josh investigation:guard` counts
|
|
43
|
-
unedited files and refuses the threshold
|
|
43
|
+
unedited files and search turns and refuses the threshold call. `pnpm josh delegate --list` prints
|
|
44
|
+
the threshold.
|
|
45
|
+
|
|
46
|
+
**Dispatch the unit as the `investigator` agent** (`kit:investigator` in a consumer) — the parent's
|
|
47
|
+
model at a lowered effort, read-only.
|
|
44
48
|
`docs/josh-commands-automation.md` → "`josh investigation:guard`" carries the command's counting details.
|
|
45
49
|
|
|
46
50
|
**The main line does not idle while the unit reads:** read files this run will edit, then verify the
|
package/SECURITY.md
CHANGED
|
@@ -36,6 +36,7 @@ The `files` field of `package.json` decides what the published `@joshuafolkken/k
|
|
|
36
36
|
|
|
37
37
|
- `CLAUDE.md`, `AGENTS.md`, `GEMINI.md`, `.cursorrules`, `prompts/` — the rules and procedures AI agents follow.
|
|
38
38
|
- `.claude/skills/`, `.claude/.claude-plugin/`, `.claude-plugin/` — the Claude Code skills, shipped as the `kit` plugin and its marketplace entry.
|
|
39
|
+
- `.claude/agents/` — the Claude Code subagent definitions (the `investigator`), shipped beside the skills. It is granted no `Edit` / `Write` tool, but it is granted `Bash`, so its read-only scope is an instruction in its prompt rather than a tool restriction — a dispatched unit can run any shell command the parent session's permissions allow.
|
|
39
40
|
- `.mcp.json` — the MCP server configuration for the Svelte documentation server. It contains only the public endpoint `https://mcp.svelte.dev/mcp`.
|
|
40
41
|
- `.coderabbit.yaml` — CodeRabbit review settings.
|
|
41
42
|
|
|
@@ -9,10 +9,10 @@ import {
|
|
|
9
9
|
load_environment_file,
|
|
10
10
|
notice_refusal_path,
|
|
11
11
|
refusal_path
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
15
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-KOKOAV6D.js";
|
|
13
|
+
import "./chunk-HANSKHES.js";
|
|
14
|
+
import "./chunk-NFZGFGOR.js";
|
|
15
|
+
import "./chunk-GDU26K3J.js";
|
|
16
16
|
import "./chunk-WPALEIRX.js";
|
|
17
17
|
import "./chunk-RKUAD3I6.js";
|
|
18
18
|
export {
|
|
@@ -358,7 +358,7 @@ var LANE_COMMANDS = {
|
|
|
358
358
|
...LANE_ARGUMENTS,
|
|
359
359
|
description: "Block until any of the named in-flight lane children completes; prints which one finished",
|
|
360
360
|
category: "AI tools",
|
|
361
|
-
reference: ["<issue> [<issue>...]", "automation", ["processes"]],
|
|
361
|
+
reference: ["<issue> [<issue>...] [--owner <pid>]", "automation", ["files", "processes"]],
|
|
362
362
|
default_script_arguments: ["await"]
|
|
363
363
|
},
|
|
364
364
|
"lane:launch": {
|
|
@@ -1059,6 +1059,13 @@ var PROJECT_COMMANDS = {
|
|
|
1059
1059
|
["files", "git", "network", "processes"]
|
|
1060
1060
|
]
|
|
1061
1061
|
},
|
|
1062
|
+
"dogfood:commit": {
|
|
1063
|
+
script: "scripts/dogfood/dogfood-commit-cli.ts",
|
|
1064
|
+
description: "Make the first commit of a dogfood run's own kit-test-* project",
|
|
1065
|
+
category: "Project",
|
|
1066
|
+
reference: ["<dir>", "automation", ["files", "git"]],
|
|
1067
|
+
is_kit_only: true
|
|
1068
|
+
},
|
|
1062
1069
|
init: {
|
|
1063
1070
|
script: "scripts/init/init.ts",
|
|
1064
1071
|
description: "Initialize config in a new project",
|
|
@@ -2573,6 +2580,7 @@ function to_spans(events, finished) {
|
|
|
2573
2580
|
is_bundleable: event.is_bundleable,
|
|
2574
2581
|
targets: event.targets,
|
|
2575
2582
|
is_writing: event.is_writing,
|
|
2583
|
+
may_write: event.may_write,
|
|
2576
2584
|
has_prior_reference: event.has_prior_reference,
|
|
2577
2585
|
writes: event.writes,
|
|
2578
2586
|
message_id: event.message_id,
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
lane_child_marker
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-NFZGFGOR.js";
|
|
4
4
|
import {
|
|
5
5
|
time_bundle_call,
|
|
6
6
|
time_format,
|
|
7
7
|
time_round_trips,
|
|
8
8
|
time_spans,
|
|
9
9
|
time_transcript_line
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-GDU26K3J.js";
|
|
11
11
|
|
|
12
12
|
// scripts/lane/lane-guard-policy.ts
|
|
13
13
|
var DEFAULT_MODE = "refuse";
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
investigation_reads
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-LJBLGHEH.js";
|
|
4
4
|
import {
|
|
5
5
|
lane_guard_policy
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-HANSKHES.js";
|
|
7
7
|
import {
|
|
8
8
|
hook_decision
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-NFZGFGOR.js";
|
|
10
10
|
import {
|
|
11
11
|
json_value,
|
|
12
12
|
time_spans
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-GDU26K3J.js";
|
|
14
14
|
|
|
15
15
|
// scripts/delegation/duplicate-read-guard.ts
|
|
16
16
|
import { statSync } from "node:fs";
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
lane_child_marker,
|
|
3
3
|
run_issue_number
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-NFZGFGOR.js";
|
|
5
5
|
import {
|
|
6
6
|
PLATFORM_TEMP_ROOT,
|
|
7
7
|
cost_blocks,
|
|
8
|
+
cost_transcript,
|
|
8
9
|
cost_usage,
|
|
9
10
|
file_reader,
|
|
10
11
|
json_value,
|
|
@@ -13,7 +14,7 @@ import {
|
|
|
13
14
|
time_density_hook,
|
|
14
15
|
time_shell,
|
|
15
16
|
time_transcript_line
|
|
16
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-GDU26K3J.js";
|
|
17
18
|
import {
|
|
18
19
|
ENV_FILE_NAME,
|
|
19
20
|
LANE_SEAT_KEY,
|
|
@@ -2199,6 +2200,67 @@ function apply_change(target, carry, change, now = /* @__PURE__ */ new Date()) {
|
|
|
2199
2200
|
}
|
|
2200
2201
|
var run_carry_change = { apply_change };
|
|
2201
2202
|
|
|
2203
|
+
// scripts/run/run-carry-conversation.ts
|
|
2204
|
+
import { existsSync, statSync } from "node:fs";
|
|
2205
|
+
import path2 from "node:path";
|
|
2206
|
+
|
|
2207
|
+
// scripts/cost-runtime/own-session.ts
|
|
2208
|
+
var NOT_FOUND = -1;
|
|
2209
|
+
function session_id_of(environment2) {
|
|
2210
|
+
const value = environment2[agent_session_environment.SESSION_ID_KEY];
|
|
2211
|
+
return value === void 0 || value === "" ? void 0 : value;
|
|
2212
|
+
}
|
|
2213
|
+
function select_own_session(files, environment2) {
|
|
2214
|
+
const session_id = session_id_of(environment2);
|
|
2215
|
+
if (session_id === void 0) {
|
|
2216
|
+
return { kind: "own", index: cost_transcript.latest_own_index(files) };
|
|
2217
|
+
}
|
|
2218
|
+
const index = files.findIndex((file) => file.session_id === session_id);
|
|
2219
|
+
return index === NOT_FOUND ? { kind: "absent", session_id } : { kind: "own", index };
|
|
2220
|
+
}
|
|
2221
|
+
var own_session = {
|
|
2222
|
+
session_id_of,
|
|
2223
|
+
select_own_session
|
|
2224
|
+
};
|
|
2225
|
+
|
|
2226
|
+
// scripts/run/run-carry-conversation.ts
|
|
2227
|
+
var CONVERSATION_QUIET_MS = 6e5;
|
|
2228
|
+
function own_transcript(environment2 = process.env, directories2 = cost_transcript.transcript_directories(process.cwd())) {
|
|
2229
|
+
const session_id = own_session.session_id_of(environment2);
|
|
2230
|
+
if (session_id === void 0) return void 0;
|
|
2231
|
+
const name = `${session_id}${cost_transcript.TRANSCRIPT_EXTENSION}`;
|
|
2232
|
+
return directories2.map((directory) => path2.join(directory, name)).find((file) => existsSync(file));
|
|
2233
|
+
}
|
|
2234
|
+
function modified_ms(transcript) {
|
|
2235
|
+
try {
|
|
2236
|
+
return statSync(transcript).mtimeMs;
|
|
2237
|
+
} catch {
|
|
2238
|
+
return void 0;
|
|
2239
|
+
}
|
|
2240
|
+
}
|
|
2241
|
+
function is_recent(modified, now) {
|
|
2242
|
+
return modified !== void 0 && now.getTime() - modified <= CONVERSATION_QUIET_MS;
|
|
2243
|
+
}
|
|
2244
|
+
function is_conversation_live(carry, now = /* @__PURE__ */ new Date(), read_modified = modified_ms) {
|
|
2245
|
+
if (carry.is_handed_off === true || carry.owner_transcript === void 0) return false;
|
|
2246
|
+
return is_recent(read_modified(carry.owner_transcript), now);
|
|
2247
|
+
}
|
|
2248
|
+
function is_same_conversation(carry, owner) {
|
|
2249
|
+
return owner.transcript !== void 0 && owner.transcript === carry.owner_transcript;
|
|
2250
|
+
}
|
|
2251
|
+
function reclaim_owner(carry, owner) {
|
|
2252
|
+
if (carry.is_handed_off === true || !is_same_conversation(carry, owner)) return carry;
|
|
2253
|
+
if (owner.pid === carry.owner_pid) return carry;
|
|
2254
|
+
return { ...carry, owner_pid: owner.pid, owner_start: owner.start };
|
|
2255
|
+
}
|
|
2256
|
+
var run_carry_conversation = {
|
|
2257
|
+
CONVERSATION_QUIET_MS,
|
|
2258
|
+
own_transcript,
|
|
2259
|
+
is_conversation_live,
|
|
2260
|
+
is_same_conversation,
|
|
2261
|
+
reclaim_owner
|
|
2262
|
+
};
|
|
2263
|
+
|
|
2202
2264
|
// scripts/backlog/backlog-budget-cli.ts
|
|
2203
2265
|
import { fileURLToPath } from "node:url";
|
|
2204
2266
|
|
|
@@ -2419,7 +2481,7 @@ var VALUE_OFFSET = 1;
|
|
|
2419
2481
|
var FLAG_PAIR_LENGTH = 2;
|
|
2420
2482
|
var ONLY_STEP = 1;
|
|
2421
2483
|
var EMPTY_LENGTH2 = 0;
|
|
2422
|
-
var
|
|
2484
|
+
var NOT_FOUND2 = -1;
|
|
2423
2485
|
function tokens_of(invocation) {
|
|
2424
2486
|
return invocation.split(TOKEN_SEPARATOR).filter((token) => token.length > EMPTY_LENGTH2);
|
|
2425
2487
|
}
|
|
@@ -2455,7 +2517,7 @@ function issue_of(token) {
|
|
|
2455
2517
|
}
|
|
2456
2518
|
function take_leading_prefixed(args) {
|
|
2457
2519
|
const stop = args.findIndex((token) => !token.startsWith(ISSUE_PREFIX));
|
|
2458
|
-
return args.slice(FIRST_TOKEN, stop ===
|
|
2520
|
+
return args.slice(FIRST_TOKEN, stop === NOT_FOUND2 ? args.length : stop);
|
|
2459
2521
|
}
|
|
2460
2522
|
function leading_issues(tokens) {
|
|
2461
2523
|
const issues = [];
|
|
@@ -2535,6 +2597,7 @@ var run_carry_schema = z6.object({
|
|
|
2535
2597
|
// which is the not-provably-live answer rather than a live one.
|
|
2536
2598
|
owner_pid: z6.number().optional(),
|
|
2537
2599
|
owner_start: z6.string().optional(),
|
|
2600
|
+
owner_transcript: z6.string().optional(),
|
|
2538
2601
|
is_handed_off: z6.boolean().optional(),
|
|
2539
2602
|
done: z6.array(z6.number()).optional(),
|
|
2540
2603
|
// Optional, so a record written before the retrospective existed still parses (joshuafolkken/kit#2328).
|
|
@@ -2569,8 +2632,8 @@ function classify3(raw, now) {
|
|
|
2569
2632
|
function read_carry(target, now = /* @__PURE__ */ new Date()) {
|
|
2570
2633
|
return classify3(stamp_file.read_stamp_text(target), now);
|
|
2571
2634
|
}
|
|
2572
|
-
function owner_of(pid, read3 = process_identity.read_start) {
|
|
2573
|
-
return { pid, start: read3(pid) };
|
|
2635
|
+
function owner_of(pid, read3 = process_identity.read_start, transcript = run_carry_conversation.own_transcript()) {
|
|
2636
|
+
return { pid, start: read3(pid), transcript };
|
|
2574
2637
|
}
|
|
2575
2638
|
function fresh_carry(invocation, owner, now) {
|
|
2576
2639
|
return {
|
|
@@ -2582,7 +2645,8 @@ function fresh_carry(invocation, owner, now) {
|
|
|
2582
2645
|
failures: NO_INCREMENT3,
|
|
2583
2646
|
outages: NO_INCREMENT3,
|
|
2584
2647
|
owner_pid: owner.pid,
|
|
2585
|
-
owner_start: owner.start
|
|
2648
|
+
owner_start: owner.start,
|
|
2649
|
+
owner_transcript: owner.transcript
|
|
2586
2650
|
};
|
|
2587
2651
|
}
|
|
2588
2652
|
function begin_carry(target, invocation, owner = NO_OWNER, now = /* @__PURE__ */ new Date()) {
|
|
@@ -2598,15 +2662,18 @@ function adopt_carry(target, carry, owner = NO_OWNER) {
|
|
|
2598
2662
|
...carry,
|
|
2599
2663
|
owner_pid: owner.pid,
|
|
2600
2664
|
owner_start: owner.start,
|
|
2665
|
+
owner_transcript: owner.transcript,
|
|
2601
2666
|
is_handed_off: false
|
|
2602
2667
|
};
|
|
2603
2668
|
stamp_file.remove_stamp(target);
|
|
2604
2669
|
return stamp_file.create_stamp(target, next) ? next : void 0;
|
|
2605
2670
|
}
|
|
2606
|
-
function is_owner_live(carry) {
|
|
2607
|
-
|
|
2671
|
+
function is_owner_live(carry, now = /* @__PURE__ */ new Date()) {
|
|
2672
|
+
if (process_identity.is_same_process(carry.owner_pid, carry.owner_start) !== false) return true;
|
|
2673
|
+
return run_carry_conversation.is_conversation_live(carry, now);
|
|
2608
2674
|
}
|
|
2609
2675
|
function is_owned_by(carry, owner) {
|
|
2676
|
+
if (run_carry_conversation.is_same_conversation(carry, owner)) return true;
|
|
2610
2677
|
return carry.owner_pid === owner.pid && carry.owner_start === owner.start;
|
|
2611
2678
|
}
|
|
2612
2679
|
function is_foreign_live_owner(carry, owner) {
|
|
@@ -2727,8 +2794,8 @@ import { spawn } from "node:child_process";
|
|
|
2727
2794
|
import { closeSync, constants, openSync, writeSync } from "node:fs";
|
|
2728
2795
|
|
|
2729
2796
|
// scripts/agent/agent-launch-environment.ts
|
|
2730
|
-
import { existsSync, lstatSync, mkdirSync, readlinkSync, symlinkSync, unlinkSync } from "node:fs";
|
|
2731
|
-
import
|
|
2797
|
+
import { existsSync as existsSync2, lstatSync, mkdirSync, readlinkSync, symlinkSync, unlinkSync } from "node:fs";
|
|
2798
|
+
import path4 from "node:path";
|
|
2732
2799
|
|
|
2733
2800
|
// scripts/gh/gh-cli-token.ts
|
|
2734
2801
|
import { execaSync as execaSync2 } from "execa";
|
|
@@ -2746,9 +2813,9 @@ var gh_cli_token = { get };
|
|
|
2746
2813
|
|
|
2747
2814
|
// scripts/agent/codex-home-source.ts
|
|
2748
2815
|
import os from "node:os";
|
|
2749
|
-
import
|
|
2816
|
+
import path3 from "node:path";
|
|
2750
2817
|
function default_home() {
|
|
2751
|
-
return
|
|
2818
|
+
return path3.join(os.homedir(), ".codex");
|
|
2752
2819
|
}
|
|
2753
2820
|
var codex_home_source = { default_home };
|
|
2754
2821
|
|
|
@@ -2765,18 +2832,18 @@ function remove_old_home_link(source, target) {
|
|
|
2765
2832
|
const current = lstatSync(target, { throwIfNoEntry: false });
|
|
2766
2833
|
if (current === void 0) return false;
|
|
2767
2834
|
if (!current.isSymbolicLink()) throw new Error(`Reviewer home file is not a link: ${target}`);
|
|
2768
|
-
if (
|
|
2835
|
+
if (existsSync2(source) && readlinkSync(target) === source) return true;
|
|
2769
2836
|
unlinkSync(target);
|
|
2770
2837
|
return false;
|
|
2771
2838
|
}
|
|
2772
2839
|
function link_home_file(source_home, target_home, name) {
|
|
2773
|
-
const source =
|
|
2774
|
-
const target =
|
|
2775
|
-
if (!remove_old_home_link(source, target) &&
|
|
2840
|
+
const source = path4.join(source_home, name);
|
|
2841
|
+
const target = path4.join(target_home, name);
|
|
2842
|
+
if (!remove_old_home_link(source, target) && existsSync2(source)) symlinkSync(source, target);
|
|
2776
2843
|
}
|
|
2777
2844
|
function reviewer_home(cwd, environment2) {
|
|
2778
2845
|
const source = environment2["CODEX_HOME"] ?? process.env["CODEX_HOME"] ?? codex_home_source.default_home();
|
|
2779
|
-
const target =
|
|
2846
|
+
const target = path4.resolve(cwd, ...REVIEWER_HOME);
|
|
2780
2847
|
mkdirSync(target, { recursive: true, mode: PRIVATE_DIRECTORY_MODE });
|
|
2781
2848
|
for (const name of HOME_FILES) link_home_file(source, target, name);
|
|
2782
2849
|
return target;
|
|
@@ -3604,8 +3671,8 @@ var lane_park = {
|
|
|
3604
3671
|
};
|
|
3605
3672
|
|
|
3606
3673
|
// scripts/discovery/repo-discovery.ts
|
|
3607
|
-
import { existsSync as
|
|
3608
|
-
import
|
|
3674
|
+
import { existsSync as existsSync3, readdirSync, readFileSync as readFileSync3, statSync as statSync2 } from "node:fs";
|
|
3675
|
+
import path5 from "node:path";
|
|
3609
3676
|
|
|
3610
3677
|
// scripts/discovery/repo-origin.ts
|
|
3611
3678
|
var GITHUB_HOST = "github.com";
|
|
@@ -3617,7 +3684,7 @@ var HOST_SEPARATOR = ":";
|
|
|
3617
3684
|
var OWNER_INDEX = 0;
|
|
3618
3685
|
var REPO_INDEX = 1;
|
|
3619
3686
|
var REPO_PATH_SEGMENTS = 2;
|
|
3620
|
-
var
|
|
3687
|
+
var NOT_FOUND3 = -1;
|
|
3621
3688
|
var SECTION_PREFIX = "[";
|
|
3622
3689
|
var ORIGIN_SECTION = /^\[remote\s+"origin"\]$/u;
|
|
3623
3690
|
var URL_KEY = "url";
|
|
@@ -3640,9 +3707,9 @@ function to_identity(repository_path) {
|
|
|
3640
3707
|
}
|
|
3641
3708
|
function parse_scp_like(url) {
|
|
3642
3709
|
const user_end = url.indexOf(USER_SEPARATOR);
|
|
3643
|
-
const authority = user_end ===
|
|
3710
|
+
const authority = user_end === NOT_FOUND3 ? url : url.slice(user_end + 1);
|
|
3644
3711
|
const host_end = authority.indexOf(HOST_SEPARATOR);
|
|
3645
|
-
if (host_end ===
|
|
3712
|
+
if (host_end === NOT_FOUND3) return void 0;
|
|
3646
3713
|
if (!is_github_ssh_host(authority.slice(0, host_end))) return void 0;
|
|
3647
3714
|
return to_identity(authority.slice(host_end + 1));
|
|
3648
3715
|
}
|
|
@@ -3664,14 +3731,14 @@ function is_section_header(line) {
|
|
|
3664
3731
|
}
|
|
3665
3732
|
function origin_section_lines(lines) {
|
|
3666
3733
|
const start = lines.findIndex((line) => ORIGIN_SECTION.test(line));
|
|
3667
|
-
if (start ===
|
|
3734
|
+
if (start === NOT_FOUND3) return [];
|
|
3668
3735
|
const rest = lines.slice(start + 1);
|
|
3669
3736
|
const end = rest.findIndex((line) => is_section_header(line));
|
|
3670
|
-
return end ===
|
|
3737
|
+
return end === NOT_FOUND3 ? rest : rest.slice(0, end);
|
|
3671
3738
|
}
|
|
3672
3739
|
function entry_value(line, key2) {
|
|
3673
3740
|
const separator = line.indexOf("=");
|
|
3674
|
-
if (separator ===
|
|
3741
|
+
if (separator === NOT_FOUND3) return void 0;
|
|
3675
3742
|
if (line.slice(0, separator).trim() !== key2) return void 0;
|
|
3676
3743
|
return line.slice(separator + 1).trim();
|
|
3677
3744
|
}
|
|
@@ -3738,10 +3805,10 @@ var GITDIR_PREFIX = "gitdir:";
|
|
|
3738
3805
|
var COMMON_DIRECTORY_FILE = "commondir";
|
|
3739
3806
|
var OVERRIDE_ENV_KEY = "JOSH_REPO_PATHS";
|
|
3740
3807
|
function resolve_common_directory(git_directory) {
|
|
3741
|
-
const pointer =
|
|
3742
|
-
if (!
|
|
3808
|
+
const pointer = path5.join(git_directory, COMMON_DIRECTORY_FILE);
|
|
3809
|
+
if (!existsSync3(pointer)) return git_directory;
|
|
3743
3810
|
try {
|
|
3744
|
-
return
|
|
3811
|
+
return path5.resolve(git_directory, readFileSync3(pointer, "utf8").trim());
|
|
3745
3812
|
} catch {
|
|
3746
3813
|
return git_directory;
|
|
3747
3814
|
}
|
|
@@ -3749,13 +3816,13 @@ function resolve_common_directory(git_directory) {
|
|
|
3749
3816
|
function follow_git_file(repository_path, git_file) {
|
|
3750
3817
|
const pointer = readFileSync3(git_file, "utf8").trim();
|
|
3751
3818
|
if (!pointer.startsWith(GITDIR_PREFIX)) return void 0;
|
|
3752
|
-
return
|
|
3819
|
+
return path5.resolve(repository_path, pointer.slice(GITDIR_PREFIX.length).trim());
|
|
3753
3820
|
}
|
|
3754
3821
|
function resolve_git_directory(repository_path) {
|
|
3755
|
-
const candidate =
|
|
3756
|
-
if (!
|
|
3822
|
+
const candidate = path5.join(repository_path, GIT_DIRECTORY);
|
|
3823
|
+
if (!existsSync3(candidate)) return void 0;
|
|
3757
3824
|
try {
|
|
3758
|
-
if (
|
|
3825
|
+
if (statSync2(candidate).isDirectory()) return candidate;
|
|
3759
3826
|
const linked = follow_git_file(repository_path, candidate);
|
|
3760
3827
|
return linked === void 0 ? void 0 : resolve_common_directory(linked);
|
|
3761
3828
|
} catch {
|
|
@@ -3767,7 +3834,7 @@ function read_origin_url(repository_path) {
|
|
|
3767
3834
|
if (git_directory === void 0) return void 0;
|
|
3768
3835
|
try {
|
|
3769
3836
|
return repo_origin.parse_origin_from_config(
|
|
3770
|
-
readFileSync3(
|
|
3837
|
+
readFileSync3(path5.join(git_directory, GIT_CONFIG), "utf8")
|
|
3771
3838
|
);
|
|
3772
3839
|
} catch {
|
|
3773
3840
|
return void 0;
|
|
@@ -3775,7 +3842,7 @@ function read_origin_url(repository_path) {
|
|
|
3775
3842
|
}
|
|
3776
3843
|
function sibling_directories(parent) {
|
|
3777
3844
|
try {
|
|
3778
|
-
return readdirSync(parent, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) =>
|
|
3845
|
+
return readdirSync(parent, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => path5.join(parent, entry.name)).toSorted((left, right) => left.localeCompare(right));
|
|
3779
3846
|
} catch {
|
|
3780
3847
|
return [];
|
|
3781
3848
|
}
|
|
@@ -3794,15 +3861,15 @@ function resolve_current_owner(repository_path) {
|
|
|
3794
3861
|
function main_worktree(repository_path) {
|
|
3795
3862
|
const git_directory = resolve_git_directory(repository_path);
|
|
3796
3863
|
if (git_directory === void 0) return repository_path;
|
|
3797
|
-
if (
|
|
3798
|
-
return
|
|
3864
|
+
if (path5.basename(git_directory) !== GIT_DIRECTORY) return repository_path;
|
|
3865
|
+
return path5.dirname(git_directory);
|
|
3799
3866
|
}
|
|
3800
3867
|
function discover_repositories(repository_path, environment2 = process.env) {
|
|
3801
3868
|
const main2 = main_worktree(repository_path);
|
|
3802
3869
|
const current_owner2 = resolve_current_owner(main2);
|
|
3803
3870
|
if (current_owner2 === void 0) return /* @__PURE__ */ new Map();
|
|
3804
3871
|
return repo_map_logic.build_repository_map(
|
|
3805
|
-
scan_siblings(
|
|
3872
|
+
scan_siblings(path5.dirname(main2)),
|
|
3806
3873
|
current_owner2,
|
|
3807
3874
|
environment2[OVERRIDE_ENV_KEY]
|
|
3808
3875
|
);
|
|
@@ -3912,8 +3979,8 @@ var lane_reap = {
|
|
|
3912
3979
|
};
|
|
3913
3980
|
|
|
3914
3981
|
// scripts/lane/lane-registry.ts
|
|
3915
|
-
import { existsSync as
|
|
3916
|
-
import
|
|
3982
|
+
import { existsSync as existsSync4 } from "node:fs";
|
|
3983
|
+
import path6 from "node:path";
|
|
3917
3984
|
|
|
3918
3985
|
// scripts/git/git-ls-remote.ts
|
|
3919
3986
|
var LS_REMOTE_COMMAND = "ls-remote";
|
|
@@ -4191,7 +4258,7 @@ function held_seat(content) {
|
|
|
4191
4258
|
return seat_from_content(content) ?? EMPTY_SEAT;
|
|
4192
4259
|
}
|
|
4193
4260
|
function read_environment(directory) {
|
|
4194
|
-
return file_reader.read_if_readable(
|
|
4261
|
+
return file_reader.read_if_readable(path6.join(directory, ENV_FILE_NAME));
|
|
4195
4262
|
}
|
|
4196
4263
|
function branch_issue(branch2) {
|
|
4197
4264
|
if (!branch2?.endsWith(lane_paths.LANE_BRANCH_SUFFIX)) return void 0;
|
|
@@ -4199,7 +4266,7 @@ function branch_issue(branch2) {
|
|
|
4199
4266
|
return ISSUE_PATTERN.test(issue) ? issue : void 0;
|
|
4200
4267
|
}
|
|
4201
4268
|
function is_gone(directory) {
|
|
4202
|
-
return !
|
|
4269
|
+
return !existsSync4(directory);
|
|
4203
4270
|
}
|
|
4204
4271
|
function build_lane(issue, branch2, directory, is_stranded) {
|
|
4205
4272
|
const content = is_stranded ? void 0 : read_environment(directory);
|
|
@@ -4596,20 +4663,20 @@ function parse_status_line(output) {
|
|
|
4596
4663
|
function status_of_failure(error) {
|
|
4597
4664
|
return has_stdout_field(error) ? parse_status_line(error.stdout) : void 0;
|
|
4598
4665
|
}
|
|
4599
|
-
async function exec_gh_api_status(
|
|
4666
|
+
async function exec_gh_api_status(path7, timeout_ms) {
|
|
4600
4667
|
const options = to_spawn_options(timeout_ms);
|
|
4601
4668
|
try {
|
|
4602
4669
|
await check_gh_installed();
|
|
4603
|
-
const { stdout } = await execa5("gh", ["api", "--include", "--silent",
|
|
4670
|
+
const { stdout } = await execa5("gh", ["api", "--include", "--silent", path7], options);
|
|
4604
4671
|
return parse_status_line(stdout);
|
|
4605
4672
|
} catch (error) {
|
|
4606
4673
|
return status_of_failure(error);
|
|
4607
4674
|
}
|
|
4608
4675
|
}
|
|
4609
|
-
function exec_gh_api_status_sync(
|
|
4676
|
+
function exec_gh_api_status_sync(path7, timeout_ms) {
|
|
4610
4677
|
const options = to_spawn_options(timeout_ms);
|
|
4611
4678
|
try {
|
|
4612
|
-
const { stdout } = execaSync3("gh", ["api", "--include", "--silent",
|
|
4679
|
+
const { stdout } = execaSync3("gh", ["api", "--include", "--silent", path7], options);
|
|
4613
4680
|
return parse_status_line(stdout);
|
|
4614
4681
|
} catch (error) {
|
|
4615
4682
|
return status_of_failure(error);
|
|
@@ -5001,9 +5068,9 @@ async function issue_get_labels_and_body(issue_number) {
|
|
|
5001
5068
|
return await issue_view_json(issue_number, "number,state,labels,body");
|
|
5002
5069
|
}
|
|
5003
5070
|
async function issue_list_comments(issue_number) {
|
|
5004
|
-
const
|
|
5071
|
+
const path7 = `${git_gh_api_path.issue_comments_api_path(issue_number)}${git_gh_api_path.FULL_PAGE_QUERY}`;
|
|
5005
5072
|
try {
|
|
5006
|
-
return await git_gh_exec.exec_gh_api({ path:
|
|
5073
|
+
return await git_gh_exec.exec_gh_api({ path: path7, should_paginate: true });
|
|
5007
5074
|
} catch {
|
|
5008
5075
|
return void 0;
|
|
5009
5076
|
}
|
|
@@ -5078,8 +5145,8 @@ function is_selected(rest, request) {
|
|
|
5078
5145
|
return !git_gh_issue_rest.is_pull_request(rest) && matches_body(rest, request.body_term);
|
|
5079
5146
|
}
|
|
5080
5147
|
async function fetch_page(request, page) {
|
|
5081
|
-
const
|
|
5082
|
-
const rows = git_gh_issue_rest.parse_rest_issues(await git_gh_exec.exec_gh_api({ path:
|
|
5148
|
+
const path7 = listing_path(request, page);
|
|
5149
|
+
const rows = git_gh_issue_rest.parse_rest_issues(await git_gh_exec.exec_gh_api({ path: path7 }));
|
|
5083
5150
|
return {
|
|
5084
5151
|
selected: rows.filter((row) => is_selected(row, request)),
|
|
5085
5152
|
is_full: rows.length >= PER_PAGE
|
|
@@ -5381,9 +5448,9 @@ function select_issue_classification(issue_json) {
|
|
|
5381
5448
|
return label2;
|
|
5382
5449
|
}
|
|
5383
5450
|
function fetch_current_labels(repository2, pull_number) {
|
|
5384
|
-
const
|
|
5451
|
+
const path7 = `repos/${repository2}/issues/${String(pull_number)}/labels`;
|
|
5385
5452
|
try {
|
|
5386
|
-
const names = git_gh_exec.exec_gh_api_sync({ path:
|
|
5453
|
+
const names = git_gh_exec.exec_gh_api_sync({ path: path7, jq_filter: ".[].name" });
|
|
5387
5454
|
return names.split("\n").filter((name) => name !== "");
|
|
5388
5455
|
} catch (error) {
|
|
5389
5456
|
const detail = error_text.message_of(error);
|
|
@@ -5626,9 +5693,9 @@ async function pr_view(branch_name) {
|
|
|
5626
5693
|
async function read_comments(branch_name, to_path, to_json) {
|
|
5627
5694
|
const pr_number = await resolve_pr_number(branch_name);
|
|
5628
5695
|
if (pr_number === void 0) return void 0;
|
|
5629
|
-
const
|
|
5696
|
+
const path7 = `${to_path(String(pr_number))}${COMMENTS_QUERY}`;
|
|
5630
5697
|
try {
|
|
5631
|
-
return to_json(await git_gh_exec.exec_gh_api({ path:
|
|
5698
|
+
return to_json(await git_gh_exec.exec_gh_api({ path: path7, should_paginate: true }));
|
|
5632
5699
|
} catch {
|
|
5633
5700
|
return void 0;
|
|
5634
5701
|
}
|
|
@@ -5774,16 +5841,16 @@ var git_gh_pr_rollup = {
|
|
|
5774
5841
|
|
|
5775
5842
|
// scripts/gh/git-gh-pr-snapshot.ts
|
|
5776
5843
|
var NO_HEAD_SHA_MESSAGE = "gh api answered a pull request with no head commit";
|
|
5777
|
-
async function read_object_pages(
|
|
5844
|
+
async function read_object_pages(path7) {
|
|
5778
5845
|
return await git_gh_exec.exec_gh_api({
|
|
5779
|
-
path: `${
|
|
5846
|
+
path: `${path7}${FULL_PAGE_QUERY}`,
|
|
5780
5847
|
should_paginate: true,
|
|
5781
5848
|
should_slurp: true
|
|
5782
5849
|
});
|
|
5783
5850
|
}
|
|
5784
|
-
async function read_array_pages(
|
|
5851
|
+
async function read_array_pages(path7) {
|
|
5785
5852
|
return await git_gh_exec.exec_gh_api({
|
|
5786
|
-
path: `${
|
|
5853
|
+
path: `${path7}${FULL_PAGE_QUERY}`,
|
|
5787
5854
|
should_paginate: true
|
|
5788
5855
|
});
|
|
5789
5856
|
}
|
|
@@ -5800,8 +5867,8 @@ async function read_status_check_rollup(commit_sha) {
|
|
|
5800
5867
|
return git_gh_pr_rollup.to_status_check_rollup({ check_runs_json, status_json });
|
|
5801
5868
|
}
|
|
5802
5869
|
async function pr_get_review_decision(pr_number) {
|
|
5803
|
-
const
|
|
5804
|
-
return git_gh_pr_review.to_review_decision(await read_array_pages(
|
|
5870
|
+
const path7 = git_gh_api_path.pull_reviews_api_path(String(pr_number));
|
|
5871
|
+
return git_gh_pr_review.to_review_decision(await read_array_pages(path7));
|
|
5805
5872
|
}
|
|
5806
5873
|
async function build_checks_fields(pull) {
|
|
5807
5874
|
return {
|
|
@@ -6364,9 +6431,9 @@ export {
|
|
|
6364
6431
|
filing_cap,
|
|
6365
6432
|
CONTEXT_CUT_THRESHOLD,
|
|
6366
6433
|
RECENT_REQUEST_WINDOW,
|
|
6367
|
-
agent_session_environment,
|
|
6368
6434
|
agent_role_profile,
|
|
6369
6435
|
cli_flags,
|
|
6436
|
+
own_session,
|
|
6370
6437
|
backlog_budget,
|
|
6371
6438
|
run_hold,
|
|
6372
6439
|
run_cut,
|