@joshuafolkken/kit 1.953.0 → 1.972.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/background-commands.md +3 -0
- package/.claude/skills/workflow-commands/backlogrun-child.md +75 -120
- package/.claude/skills/workflow-commands/backlogrun-lanes.md +78 -115
- package/.claude/skills/workflow-commands/backlogrun-progress.md +82 -146
- package/.claude/skills/workflow-commands/backlogrun-steps.md +173 -229
- package/.claude/skills/workflow-commands/backlogrun.md +3 -1
- package/.claude/skills/workflow-commands/followup.md +3 -0
- package/.claude/skills/workflow-commands/fullrun.md +3 -4
- package/.claude/skills/workflow-commands/observation-filing.md +31 -25
- package/.claude/skills/workflow-commands/pre-gate-cut.md +96 -161
- package/.github/workflows/pr-classification.yml +12 -1
- package/CLAUDE.md +3 -3
- package/README.md +5 -3
- package/dist/CLAUDE.md +3 -3
- package/dist/hooks/batch-guard.js +4 -4
- package/dist/hooks/{chunk-OM5VDM6F.js → chunk-2K52BRWV.js} +2 -2
- package/dist/hooks/{chunk-Z5TVZ4AP.js → chunk-BNWIOJFU.js} +29 -16
- package/dist/hooks/{chunk-NKVLBB65.js → chunk-BVMSPG3M.js} +3 -3
- package/dist/hooks/{chunk-IA7WC4NS.js → chunk-CRGJTD6E.js} +1 -1
- package/dist/hooks/{chunk-M4U4YNRE.js → chunk-F6OM6SIG.js} +3 -3
- package/dist/hooks/{chunk-O3PEDF3M.js → chunk-KQG4776P.js} +1 -1
- package/dist/hooks/{chunk-V7RH56HU.js → chunk-NXL3SBXY.js} +2 -2
- package/dist/hooks/{chunk-452OKRQX.js → chunk-WWTMHHZU.js} +120 -18
- package/dist/hooks/{chunk-EYFJ74MJ.js → chunk-ZPLXLJ7O.js} +21 -7
- package/dist/hooks/{chunk-IBFC25IX.js → chunk-ZYYSBNR6.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/investigation-guard.js +5 -5
- package/dist/hooks/pretool-guard.js +9 -9
- package/dist/hooks/stop-guard.js +206 -176
- package/dist/josh.js +14 -6
- package/package.json +3 -3
- package/prompts/collaboration-workflow/wip-cap.md +1 -1
- package/scripts/backlog/backlog-arrival.ts +11 -1
- package/scripts/backlog/backlog-budget.ts +25 -8
- package/scripts/backlog/backlog-drive-cli.ts +5 -1
- package/scripts/backlog/backlog-drive-retrospective.ts +20 -0
- package/scripts/backlog/backlog-drive.ts +7 -3
- package/scripts/backlog/backlog-next.ts +45 -2
- package/scripts/backlog/backlog-offer.ts +1 -0
- package/scripts/backlog/backlog-plan-cli.ts +66 -27
- package/scripts/backlog/backlog-plan.ts +30 -2
- package/scripts/backlog/backlog-stalled.ts +9 -0
- package/scripts/backlog/backlog-waves.ts +169 -0
- package/scripts/document/document-byte-budget.ts +1 -1
- package/scripts/document/entry-read-budget.ts +7 -5
- package/scripts/epic/epic-lane-offer.ts +69 -4
- package/scripts/epic/epic-next.ts +2 -2
- package/scripts/epic/epic-solo.ts +147 -0
- package/scripts/epic/epic-triage.ts +47 -0
- package/scripts/gate/hook-gate-reuse.ts +7 -8
- package/scripts/git/git-closes-keyword.ts +15 -0
- package/scripts/git/git-followup-flush.ts +5 -6
- package/scripts/git/git-followup-issue-close.ts +75 -0
- package/scripts/git/git-pr-followup-wrapup.ts +36 -6
- package/scripts/git/git-pr-followup.ts +9 -16
- package/scripts/git/git-staging.ts +33 -20
- package/scripts/git/issue-labels.ts +42 -0
- package/scripts/hooks/stop-guard.ts +1 -0
- package/scripts/init/init-install.ts +64 -0
- package/scripts/init/init.ts +38 -11
- package/scripts/init/project-profile.ts +9 -5
- package/scripts/init/start-plan.ts +145 -0
- package/scripts/init/start-prompt.ts +55 -0
- package/scripts/init/start-steps.ts +167 -0
- package/scripts/init/start.ts +92 -16
- package/scripts/issue/issue-closing-pr.ts +93 -0
- package/scripts/josh/__snapshots__/josh-command-map.test.ts.snap +4 -2
- package/scripts/josh/josh-commands-project.ts +11 -3
- package/scripts/josh/josh-commands-workflow.ts +3 -3
- package/scripts/observations/observation-ledger-prepare.ts +31 -0
- package/scripts/observations/observation-ledger.ts +5 -5
- package/scripts/observations/observations-flush.ts +11 -30
- package/scripts/rules/implementation-cut.ts +49 -16
- package/scripts/rules/lane-background.ts +25 -5
- package/scripts/rules/stop-rules.ts +16 -4
- package/scripts/run/run-carry-cli.ts +21 -0
- package/scripts/run/run-cut-cli.ts +92 -110
- package/scripts/run/run-cut-report.ts +167 -0
- package/scripts/run/run-cut.ts +23 -7
- package/scripts/run/run-entry-cli.ts +36 -2
- package/scripts/run/run-headless.ts +1 -0
- package/scripts/run/run-hold-cli.ts +36 -15
- package/scripts/run/run-hold.ts +15 -4
- package/scripts/run/run-merge-cli.ts +28 -14
- package/scripts/run/run-merge-steps.ts +38 -2
- package/scripts/run/run-merge.ts +41 -3
- package/scripts/run/run-prep-cli.ts +8 -2
- package/scripts/run/run-prep-locate.ts +165 -0
- package/scripts/run/run-prep.ts +12 -1
- package/scripts/run/run-retrospective.ts +34 -0
- package/scripts/run/run-step-cli.ts +19 -5
- package/scripts/run/run-step.ts +31 -19
- package/scripts/run/run-tail-cli.ts +4 -2
- package/scripts/run/run-wake-work.ts +4 -0
- package/scripts/safe-chain/ci-installer-pin.ts +8 -4
- package/scripts/time-runtime/time-background.ts +11 -0
- package/scripts/time-runtime/time-transcript-line.ts +4 -0
- package/templates/pnpm-workspace.static.yaml +2 -0
package/README.md
CHANGED
|
@@ -19,13 +19,15 @@ kit adds no linter or test runner for languages other than JavaScript and TypeSc
|
|
|
19
19
|
In your project directory:
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
pnpm add -D --allow-build=esbuild @joshuafolkken/kit
|
|
22
|
+
pnpm add -D --allow-build=esbuild --allow-build=unrs-resolver @joshuafolkken/kit
|
|
23
23
|
pnpm exec josh init
|
|
24
|
-
pnpm install
|
|
25
|
-
pnpm josh format
|
|
26
24
|
pnpm josh gate
|
|
27
25
|
```
|
|
28
26
|
|
|
27
|
+
`josh init` finishes by running `pnpm install` and `josh format` itself; pass `--no-install` to skip both, for example on CI or offline.
|
|
28
|
+
|
|
29
|
+
`josh init` is the entry without GitHub. To start a new project on the GitHub Issue workflow (`kickoff`), run `pnpm exec josh start` instead of `josh init` — it also creates the Git repository, the GitHub repository and the labels ([init.md → `josh init` or `josh start`](./docs/init.md#josh-init-or-josh-start)).
|
|
30
|
+
|
|
29
31
|
It needs [Node.js](https://nodejs.org/) 22.19.0 or later with [pnpm](https://pnpm.io/), even for a `static` project; [getting-started.md](./docs/getting-started.md) installs both. The global `josh` command ([cli.md](./docs/cli.md)) and the [gh CLI](https://cli.github.com/) for `josh version` and the GitHub Issue workflow are optional.
|
|
30
32
|
|
|
31
33
|
## Documentation
|
package/dist/CLAUDE.md
CHANGED
|
@@ -89,7 +89,7 @@ Read from a `.env` file at the project root by the AI scripts, `josh port` and `
|
|
|
89
89
|
|
|
90
90
|
### Dependency overrides (`pnpm-workspace.yaml` / `package.json`)
|
|
91
91
|
|
|
92
|
-
- **Effective overrides live in `pnpm-workspace.yaml`.** pnpm 11 and 12 ignore `pnpm.overrides` in `package.json
|
|
92
|
+
- **Effective overrides live in `pnpm-workspace.yaml`.** pnpm 11 and 12 ignore `pnpm.overrides` in `package.json`. Check both files for existing declarations, but never count the ignored package field as an effective override. **An absent or empty `pnpm.overrides` is not evidence that the project has no overrides.**
|
|
93
93
|
- **NEVER** remove or modify entries in **either** location without explicit user approval.
|
|
94
94
|
- **NEVER** modify the `devEngines` field in `package.json` without explicit user confirmation. It pins the development toolchain (e.g. pnpm version); silently changing it can break CI or other contributors' environments.
|
|
95
95
|
- **The check is a command you run, not a conclusion you reach.** After `pnpm update`, `josh latest`, or any dependency-update command, **load the `dependency-update` skill** and follow its procedure before reporting anything about the pins.
|
|
@@ -144,7 +144,7 @@ Before every `git commit` (follow-up commits included), self-review against `nod
|
|
|
144
144
|
|
|
145
145
|
## Doc Sync Rules
|
|
146
146
|
|
|
147
|
-
**`CLAUDE.md` is the single source for every agent rule.** `AGENTS.md` and `GEMINI.md` carry no rules — a rule addition, spec change or wording fix is written **once**, here (joshuafolkken/kit#963).
|
|
147
|
+
**`CLAUDE.md` is the single source for every agent rule.** `AGENTS.md` and `GEMINI.md` carry no rules — a rule addition, spec change or wording fix is written **once**, here (joshuafolkken/kit#963).
|
|
148
148
|
|
|
149
149
|
**docs/ must stay in sync with the package.** When `josh bump` changes the version, review `https://github.com/joshuafolkken/kit/tree/main/docs/` and update any section describing changed behavior (new/renamed commands, `josh init` / `josh sync` behavior, new config files) before committing.
|
|
150
150
|
|
|
@@ -166,7 +166,7 @@ Before every `git commit` (follow-up commits included), self-review against `nod
|
|
|
166
166
|
|
|
167
167
|
`kickoff`, `fullrun`, `halfrun` and `backlogrun` are the Issue-driven shorthand commands. **Their procedures are not resident** — they live in the `workflow-commands` skill. **What stays here is decided by one question: must the rule fire on a turn where no skill was loaded?** Explicit invocation, the mid-workflow stop notification, the `overrides` / `devEngines` prohibitions, the UI-verification gate and the three `epic:*` rules below all do; everything a run reaches only after reading the skill is routed to, never restated (`SKILL.md` → "What stays resident, and what is read from here").
|
|
168
168
|
|
|
169
|
-
**Read the skill before running any part of a command — including the first `gh` call.**
|
|
169
|
+
**Read the skill before running any part of a command — including the first `gh` call.**
|
|
170
170
|
|
|
171
171
|
| Typed keyword | What it does | Read first |
|
|
172
172
|
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- |
|
|
@@ -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-NXL3SBXY.js";
|
|
13
|
+
import "./chunk-2K52BRWV.js";
|
|
14
|
+
import "./chunk-KQG4776P.js";
|
|
15
|
+
import "./chunk-ZPLXLJ7O.js";
|
|
16
16
|
import "./chunk-WPALEIRX.js";
|
|
17
17
|
import "./chunk-RKUAD3I6.js";
|
|
18
18
|
export {
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
lane_child_marker
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-KQG4776P.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-ZPLXLJ7O.js";
|
|
11
11
|
|
|
12
12
|
// scripts/lane/lane-guard-policy.ts
|
|
13
13
|
var DEFAULT_MODE = "refuse";
|
|
@@ -35,31 +35,31 @@ import {
|
|
|
35
35
|
run_watcher_guard,
|
|
36
36
|
shell_segments,
|
|
37
37
|
tail_commands
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-WWTMHHZU.js";
|
|
39
39
|
import {
|
|
40
40
|
find_local_bin_upwards
|
|
41
41
|
} from "./chunk-3V37IID6.js";
|
|
42
42
|
import {
|
|
43
43
|
batch_outcome
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-NXL3SBXY.js";
|
|
45
45
|
import {
|
|
46
46
|
investigation_refusal
|
|
47
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-BVMSPG3M.js";
|
|
48
48
|
import {
|
|
49
49
|
duplicate_read_outcome
|
|
50
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-ZYYSBNR6.js";
|
|
51
51
|
import {
|
|
52
52
|
investigation_reads
|
|
53
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-F6OM6SIG.js";
|
|
54
54
|
import {
|
|
55
55
|
lane_guard_policy,
|
|
56
56
|
time_batch_guard
|
|
57
|
-
} from "./chunk-
|
|
57
|
+
} from "./chunk-2K52BRWV.js";
|
|
58
58
|
import {
|
|
59
59
|
hook_decision,
|
|
60
60
|
lane_child_marker,
|
|
61
61
|
run_issue_number
|
|
62
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-KQG4776P.js";
|
|
63
63
|
import {
|
|
64
64
|
PLATFORM_TEMP_ROOT,
|
|
65
65
|
cost_attribute,
|
|
@@ -71,7 +71,7 @@ import {
|
|
|
71
71
|
stamp_file,
|
|
72
72
|
time_density_hook,
|
|
73
73
|
time_shell
|
|
74
|
-
} from "./chunk-
|
|
74
|
+
} from "./chunk-ZPLXLJ7O.js";
|
|
75
75
|
|
|
76
76
|
// scripts/hooks/pretool-guard.ts
|
|
77
77
|
import { text } from "node:stream/consumers";
|
|
@@ -1016,24 +1016,37 @@ function current_state() {
|
|
|
1016
1016
|
directory: process.cwd(),
|
|
1017
1017
|
source: process.env,
|
|
1018
1018
|
carried: run_cut.carried_cut_sync,
|
|
1019
|
+
held_issue: run_cut.held_issue_sync,
|
|
1019
1020
|
// **Read through the short reuse window** (joshuafolkken/kit#2385). The row now fires per
|
|
1020
1021
|
// threshold crossing rather than once per run, so this predicate is a candidate on every edit;
|
|
1021
1022
|
// the window collapses one turn's burst of edits to a single whole-transcript price.
|
|
1022
1023
|
verdict: () => implementation_cut_verdict.reused_verdict(() => cost_cli.session_verdict())
|
|
1023
1024
|
};
|
|
1024
1025
|
}
|
|
1025
|
-
function
|
|
1026
|
+
function lane_child_issue(state) {
|
|
1026
1027
|
if (!lane_child_marker.is_child_of(state.directory, state.source)) return void 0;
|
|
1027
|
-
|
|
1028
|
+
return lane_paths.lane_issue_of(state.directory, { ...state.source });
|
|
1029
|
+
}
|
|
1030
|
+
function held_run_issue(state) {
|
|
1031
|
+
if (lane_paths.lane_issue_of(state.directory, { ...state.source }) !== void 0) return void 0;
|
|
1032
|
+
return state.held_issue();
|
|
1033
|
+
}
|
|
1034
|
+
function uncut_run_issue(state) {
|
|
1035
|
+
const issue = lane_child_issue(state) ?? held_run_issue(state);
|
|
1028
1036
|
if (issue === void 0) return void 0;
|
|
1029
1037
|
return state.carried()?.issue === issue ? void 0 : issue;
|
|
1030
1038
|
}
|
|
1039
|
+
function warrants_the_cut(state) {
|
|
1040
|
+
const verdict = state.verdict();
|
|
1041
|
+
if (lane_child_issue(state) === void 0) return verdict === cost_verdict.OVER_VERDICT;
|
|
1042
|
+
return verdict !== cost_verdict.UNDER_VERDICT;
|
|
1043
|
+
}
|
|
1031
1044
|
function is_over_threshold_edit(call, state = current_state()) {
|
|
1032
|
-
if (!is_edit_tool(call.name) ||
|
|
1033
|
-
return state
|
|
1045
|
+
if (!is_edit_tool(call.name) || uncut_run_issue(state) === void 0) return false;
|
|
1046
|
+
return warrants_the_cut(state);
|
|
1034
1047
|
}
|
|
1035
1048
|
var THRESHOLD_TEXT = `${cost_format.format_tokens(CONTEXT_CUT_THRESHOLD)}-token`;
|
|
1036
|
-
var IMPLEMENTATION_CUT_REASON = `\u26D4 implementation-phase cut: this checkout is a lane dispatched for this issue and its recent-context cost has crossed the shared ${THRESHOLD_TEXT} threshold mid-implementation, so the thinking accumulated so far is now re-read on every later request. Take the cut before this edit. First write a handoff file with the Write tool \u2014 the user\u2019s instruction verbatim, what you have completed, what remains, and what you deliberately did not touch \u2014 and pass it as \`--handoff <path>\`, so the fresh process resumes on the original instruction rather than the working tree alone (joshuafolkken/kit#2354); a resume that finds no instruction is refused \`incomplete\` rather than continuing blind. \`pnpm josh run:cut --impl <N> --handoff <path>\` ends this process and relaunches a fresh one that resumes back into implementation (\`resume-impl\`), dropping the accumulated context rather than carrying it \u2014 joshuafolkken/kit#1933 built the boundary and joshuafolkken/kit#2310 measured it firing 0 times because the verdict was only ever read at session entry, where the context has not yet grown. The verdict is \`pnpm josh cost --cut\`'s exactly \u2014 the same per-request billed-input statistic against the same threshold, never a second measurement. Issue \`pnpm josh run:cut --impl <N> --handoff <path>\` now and read the verdict: on \`cut\`, **end the turn immediately** \u2014 the fresh process owns the run and continues implementing, so it must not be waited for; on \`not-a-lane\`, \`unready\`, \`busy\`, \`failed\` or \`unknown\`, this process carries the run on and the edit is simply the next call. Never relaunch a second process after \`busy\`. This fired because the dispatch mark names this lane; a person working here carries no mark and sees no refusal, so there is no human-or-child judgement left to make. The procedure is \`.claude/skills/workflow-commands/pre-gate-cut.md\`. Reissue this edit once the cut has answered \u2014 an edit reissued right after this refusal passes, so \`busy\` / \`failed\` cannot wedge the run edit after edit; this fires again on the next threshold crossing rather than once per run.`;
|
|
1049
|
+
var IMPLEMENTATION_CUT_REASON = `\u26D4 implementation-phase cut: this checkout is a lane dispatched for this issue, or a run holds it for this issue (joshuafolkken/kit#2760), and its recent-context cost has crossed the shared ${THRESHOLD_TEXT} threshold mid-implementation, so the thinking accumulated so far is now re-read on every later request. Take the cut before this edit. First write a handoff file with the Write tool \u2014 the user\u2019s instruction verbatim, what you have completed, what remains, and what you deliberately did not touch \u2014 and pass it as \`--handoff <path>\`, so the fresh process resumes on the original instruction rather than the working tree alone (joshuafolkken/kit#2354); a resume that finds no instruction is refused \`incomplete\` rather than continuing blind. \`pnpm josh run:cut --impl <N> --handoff <path>\` ends this process and relaunches a fresh one that resumes back into implementation (\`resume-impl\`), dropping the accumulated context rather than carrying it \u2014 joshuafolkken/kit#1933 built the boundary and joshuafolkken/kit#2310 measured it firing 0 times because the verdict was only ever read at session entry, where the context has not yet grown. The verdict is \`pnpm josh cost --cut\`'s exactly \u2014 the same per-request billed-input statistic against the same threshold, never a second measurement. Issue \`pnpm josh run:cut --impl <N> --handoff <path>\` now and read the verdict: on \`cut\`, **end the turn immediately** \u2014 in a lane the fresh process owns the run and continues implementing, so it must not be waited for; outside a lane nothing is relaunched, so first send the \`confirmation\` Telegram naming the resume command \`fullrun #<N>\` and keep the hold; on \`not-a-lane\`, \`unready\`, \`busy\`, \`failed\` or \`unknown\`, this process carries the run on and the edit is simply the next call. Never relaunch a second process after \`busy\`. This fired because the dispatch mark names this lane or the run hold names this issue; a person working here carries no mark and holds no run, so sees no refusal, so there is no human-or-child judgement left to make. The procedure is \`.claude/skills/workflow-commands/pre-gate-cut.md\`. Reissue this edit once the cut has answered \u2014 an edit reissued right after this refusal passes, so \`busy\` / \`failed\` cannot wedge the run edit after edit; this fires again on the next threshold crossing rather than once per run.`;
|
|
1037
1050
|
var REISSUE_WINDOW_MS = 9e4;
|
|
1038
1051
|
function is_reissued_refusal(now_ms, delivered_at_ms) {
|
|
1039
1052
|
return now_ms - delivered_at_ms < REISSUE_WINDOW_MS;
|
|
@@ -1057,7 +1070,7 @@ var implementation_cut = {
|
|
|
1057
1070
|
is_over_threshold_edit,
|
|
1058
1071
|
is_reissued_refusal,
|
|
1059
1072
|
takes_the_impl_cut,
|
|
1060
|
-
|
|
1073
|
+
uncut_run_issue
|
|
1061
1074
|
};
|
|
1062
1075
|
|
|
1063
1076
|
// scripts/rules/issue-bug-label.ts
|
|
@@ -1951,12 +1964,12 @@ function uncut_lane_issue(state) {
|
|
|
1951
1964
|
if (state.marked_issue !== issue) return void 0;
|
|
1952
1965
|
return state.carried()?.issue === issue ? void 0 : issue;
|
|
1953
1966
|
}
|
|
1954
|
-
function
|
|
1967
|
+
function warrants_the_cut2(verdict) {
|
|
1955
1968
|
return verdict !== cost_verdict.UNDER_VERDICT;
|
|
1956
1969
|
}
|
|
1957
1970
|
function is_uncut_gate(command, state = current_state2()) {
|
|
1958
1971
|
if (!runs_the_gate(command) || uncut_lane_issue(state) === void 0) return false;
|
|
1959
|
-
return
|
|
1972
|
+
return warrants_the_cut2(state.context_verdict());
|
|
1960
1973
|
}
|
|
1961
1974
|
var PRE_GATE_CUT_REASON = "\u26D4 pre-gate cut: this checkout is a lane dispatched for this issue and the gate is the boundary to cut at, so take the cut before running it. `pnpm josh run:cut <N>` ends this process and relaunches a fresh one that resumes from the gate, dropping the thinking built up while implementing rather than carrying it on every later request \u2014 joshuafolkken/kit#1839 measured 176K of 204K output riding across that boundary, and joshuafolkken/kit#1864 measured the step itself firing 0 times in 6 lane children while it was carried as prose. Issue `pnpm josh run:cut <N>` now, and read the verdict: on `cut`, **end the turn immediately** \u2014 the fresh process owns the run from there and must not be waited for; on `not-a-lane`, `unready`, `busy`, `failed` or `unknown`, this process carries the run on and the gate is simply the next call. Never relaunch a second process after `busy`. This fired because the dispatch mark names this lane; a person working here carries no mark and sees no refusal, so there is no human-or-child judgement left to make. The procedure is `.claude/skills/workflow-commands/pre-gate-cut.md`. Reissue the gate once the cut has answered \u2014 this fires once per run, so it cannot repeat on the call in hand.";
|
|
1962
1975
|
function reaches_the_pre_gate_boundary(call, _turn, run2) {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
investigation_reads
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-F6OM6SIG.js";
|
|
4
4
|
import {
|
|
5
5
|
lane_guard_policy
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-2K52BRWV.js";
|
|
7
7
|
import {
|
|
8
8
|
hook_decision
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-KQG4776P.js";
|
|
10
10
|
|
|
11
11
|
// scripts/delegation/investigation-guard.ts
|
|
12
12
|
import { text } from "node:stream/consumers";
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
time_batch_guard
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-2K52BRWV.js";
|
|
4
4
|
import {
|
|
5
5
|
hook_decision
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-KQG4776P.js";
|
|
7
7
|
import {
|
|
8
8
|
cost_blocks,
|
|
9
9
|
cost_transcript,
|
|
10
10
|
time_bundle_call,
|
|
11
11
|
time_shell,
|
|
12
12
|
time_spans
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-ZPLXLJ7O.js";
|
|
14
14
|
|
|
15
15
|
// scripts/delegation/investigation-reads.ts
|
|
16
16
|
import path from "node:path";
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
lane_guard_policy,
|
|
3
3
|
time_batch_guard
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-2K52BRWV.js";
|
|
5
5
|
import {
|
|
6
6
|
hook_decision
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-KQG4776P.js";
|
|
8
8
|
|
|
9
9
|
// scripts/hooks/batch-guard.ts
|
|
10
10
|
import { text } from "node:stream/consumers";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
lane_child_marker,
|
|
3
3
|
run_issue_number
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-KQG4776P.js";
|
|
5
5
|
import {
|
|
6
6
|
PLATFORM_TEMP_ROOT,
|
|
7
7
|
cost_blocks,
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
time_density_hook,
|
|
13
13
|
time_shell,
|
|
14
14
|
time_transcript_line
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-ZPLXLJ7O.js";
|
|
16
16
|
import {
|
|
17
17
|
ENV_FILE_NAME,
|
|
18
18
|
LANE_SEAT_KEY,
|
|
@@ -546,7 +546,8 @@ async function is_linked_worktree() {
|
|
|
546
546
|
var run_hold_schema = z.object({
|
|
547
547
|
issue: z.string(),
|
|
548
548
|
taken_at: z.string(),
|
|
549
|
-
pid: z.number()
|
|
549
|
+
pid: z.number(),
|
|
550
|
+
is_fullrun: z.boolean().optional()
|
|
550
551
|
});
|
|
551
552
|
function parse_hold(raw) {
|
|
552
553
|
try {
|
|
@@ -570,16 +571,16 @@ function classify(raw, now) {
|
|
|
570
571
|
function read_hold(target, now = /* @__PURE__ */ new Date()) {
|
|
571
572
|
return classify(stamp_file.read_stamp_text(target), now);
|
|
572
573
|
}
|
|
573
|
-
function build_hold(issue, now) {
|
|
574
|
-
return { issue, taken_at: now.toISOString(), pid: process.pid };
|
|
574
|
+
function build_hold(issue, now, is_fullrun) {
|
|
575
|
+
return { issue, taken_at: now.toISOString(), pid: process.pid, is_fullrun };
|
|
575
576
|
}
|
|
576
577
|
function write_hold(target, issue, now = /* @__PURE__ */ new Date()) {
|
|
577
578
|
const hold = build_hold(issue, now);
|
|
578
579
|
stamp_file.write_stamp(target, hold);
|
|
579
580
|
return hold;
|
|
580
581
|
}
|
|
581
|
-
function create_hold(target, issue, now = /* @__PURE__ */ new Date()) {
|
|
582
|
-
return stamp_file.create_stamp(target, build_hold(issue, now));
|
|
582
|
+
function create_hold(target, issue, now = /* @__PURE__ */ new Date(), is_fullrun) {
|
|
583
|
+
return stamp_file.create_stamp(target, build_hold(issue, now, is_fullrun));
|
|
583
584
|
}
|
|
584
585
|
async function is_tree_dirty() {
|
|
585
586
|
try {
|
|
@@ -943,11 +944,13 @@ var IDLE_POLL_MINUTES = 5;
|
|
|
943
944
|
var RUN_VERDICT = "run";
|
|
944
945
|
var WATCH_VERDICT = "watch";
|
|
945
946
|
var STOP_VERDICT = "stop";
|
|
946
|
-
var
|
|
947
|
+
var TRIAGE_VERDICT = "triage";
|
|
948
|
+
var ANSWERS = ["blocked", "candidates", "exhausted", "parked", "unreadable", "untriaged"];
|
|
947
949
|
var WHOLE_RUN_REASON = `The whole-run bound of ${String(WHOLE_RUN_BUDGET_HOURS)} hours has passed. An unattended run that has not finished overnight needs a person, not more waiting.`;
|
|
948
950
|
var PARKED_REASON = "Nothing opted in can proceed without a person. Report the parked issues and finish.";
|
|
949
951
|
var UNREADABLE_REASON = "The backlog listing could not be read, so nothing was offered. Report what the command printed and finish \u2014 it is not an empty backlog.";
|
|
950
952
|
var BLOCKED_REASON = "Everything opted in is blocked or already running, so waiting can still change the answer. Poll again at the polling interval.";
|
|
953
|
+
var TRIAGE_REASON = "An opted-in candidate carries neither `run:solo` nor `run:lane`, so nothing starts until it is judged. Read each issue named above, record its order and one of the two labels with a comment, then ask again.";
|
|
951
954
|
var NO_IDLE_WATCH_REASON = "The backlog is empty and the idle watch was turned off with `--idle 0`, so the run finishes here.";
|
|
952
955
|
function to_minutes(duration_ms) {
|
|
953
956
|
return String(Math.ceil(duration_ms / MS_PER_MINUTE));
|
|
@@ -1013,14 +1016,20 @@ function idle_decision(input) {
|
|
|
1013
1016
|
function is_finish(input) {
|
|
1014
1017
|
return stop_reason(input) === void 0 && max_decision(input) === void 0;
|
|
1015
1018
|
}
|
|
1019
|
+
var FIXED_DECISIONS = {
|
|
1020
|
+
blocked: { verdict: WATCH_VERDICT, reason: BLOCKED_REASON },
|
|
1021
|
+
untriaged: { verdict: TRIAGE_VERDICT, reason: TRIAGE_REASON }
|
|
1022
|
+
};
|
|
1023
|
+
function answer_decision(input) {
|
|
1024
|
+
if (input.answer === "candidates") return { verdict: RUN_VERDICT, reason: run_reason(input) };
|
|
1025
|
+
return FIXED_DECISIONS[input.answer] ?? idle_decision(input);
|
|
1026
|
+
}
|
|
1016
1027
|
function decide2(input) {
|
|
1017
1028
|
const reason = stop_reason(input);
|
|
1018
1029
|
if (reason !== void 0) return stopping(input, reason);
|
|
1019
1030
|
const capped = max_decision(input);
|
|
1020
1031
|
if (capped !== void 0) return capped;
|
|
1021
|
-
|
|
1022
|
-
if (input.answer === "blocked") return { verdict: WATCH_VERDICT, reason: BLOCKED_REASON };
|
|
1023
|
-
return idle_decision(input);
|
|
1032
|
+
return answer_decision(input);
|
|
1024
1033
|
}
|
|
1025
1034
|
var backlog_budget = {
|
|
1026
1035
|
ANSWERS,
|
|
@@ -1034,6 +1043,8 @@ var backlog_budget = {
|
|
|
1034
1043
|
PARKED_REASON,
|
|
1035
1044
|
RUN_VERDICT,
|
|
1036
1045
|
STOP_VERDICT,
|
|
1046
|
+
TRIAGE_REASON,
|
|
1047
|
+
TRIAGE_VERDICT,
|
|
1037
1048
|
UNREADABLE_REASON,
|
|
1038
1049
|
WATCH_VERDICT,
|
|
1039
1050
|
WHOLE_RUN_BUDGET_HOURS,
|
|
@@ -1448,16 +1459,22 @@ function adopt_cut(target, cut) {
|
|
|
1448
1459
|
function end_cut(target) {
|
|
1449
1460
|
stamp_file.remove_stamp(target);
|
|
1450
1461
|
}
|
|
1451
|
-
function
|
|
1452
|
-
if (directory === void 0) return
|
|
1462
|
+
function hold_of(directory) {
|
|
1463
|
+
if (directory === void 0) return void 0;
|
|
1453
1464
|
const read2 = run_hold.read_hold(run_hold.hold_path(directory));
|
|
1454
|
-
return read2.kind === "held" || read2.kind === "stale";
|
|
1465
|
+
return read2.kind === "held" || read2.kind === "stale" ? read2.hold : void 0;
|
|
1466
|
+
}
|
|
1467
|
+
function fullrun_issue(hold) {
|
|
1468
|
+
return hold?.is_fullrun === true ? hold.issue : void 0;
|
|
1469
|
+
}
|
|
1470
|
+
function held_issue_sync() {
|
|
1471
|
+
return fullrun_issue(hold_of(worktree_git_directory_sync()));
|
|
1455
1472
|
}
|
|
1456
1473
|
async function current_state() {
|
|
1457
1474
|
const branch2 = await git_command.branch();
|
|
1458
1475
|
const is_dirty = await run_hold.is_tree_dirty();
|
|
1459
|
-
const
|
|
1460
|
-
return { branch: branch2, is_dirty, is_held:
|
|
1476
|
+
const hold = hold_of(await worktree_directory2());
|
|
1477
|
+
return { branch: branch2, is_dirty, is_held: hold !== void 0, held_issue: fullrun_issue(hold) };
|
|
1461
1478
|
}
|
|
1462
1479
|
function describe_cut(cut) {
|
|
1463
1480
|
return `${cut.invocation} cut at ${cut.cut_at} on ${cut.branch} (${cut.phase})`;
|
|
@@ -1499,8 +1516,10 @@ var run_cut = {
|
|
|
1499
1516
|
describe_cut,
|
|
1500
1517
|
end_cut,
|
|
1501
1518
|
fresh_cut,
|
|
1519
|
+
fullrun_issue,
|
|
1502
1520
|
handed_off_message,
|
|
1503
1521
|
has_required_handoff,
|
|
1522
|
+
held_issue_sync,
|
|
1504
1523
|
incomplete_message,
|
|
1505
1524
|
invocation_for,
|
|
1506
1525
|
is_expired,
|
|
@@ -1602,12 +1621,19 @@ function is_candidate(call) {
|
|
|
1602
1621
|
function is_background_long_run(call, is_lane_child = () => lane_child_marker.is_child_of(process.cwd())) {
|
|
1603
1622
|
return is_candidate(call) && is_lane_child();
|
|
1604
1623
|
}
|
|
1605
|
-
function
|
|
1624
|
+
function unfinished_ids(tail, launched_ids) {
|
|
1606
1625
|
const lines = tail.split("\n").map((line) => time_transcript_line.parse_line(line));
|
|
1607
1626
|
const finished = new Set(lines.map((line) => line?.finished_background ?? ""));
|
|
1608
|
-
const
|
|
1627
|
+
const blocks = lines.flatMap((line) => line?.blocks ?? []);
|
|
1628
|
+
const launched = blocks.flatMap((block) => launched_ids(block));
|
|
1609
1629
|
return launched.filter((id) => id !== "" && !finished.has(id));
|
|
1610
1630
|
}
|
|
1631
|
+
function pending_background_ids(tail) {
|
|
1632
|
+
return unfinished_ids(tail, (block) => [block.background_id, block.agent_id]);
|
|
1633
|
+
}
|
|
1634
|
+
function pending_agent_ids(tail) {
|
|
1635
|
+
return unfinished_ids(tail, (block) => [block.agent_id]);
|
|
1636
|
+
}
|
|
1611
1637
|
var LANE_BACKGROUND_REASON = '\u26D4 lane background: this session is a dispatched lane child (`JOSH_LANE_CHILD`), a headless `claude -p` process whose background Bash tasks are killed when the turn ends \u2014 so a backgrounded `josh gate` / `josh git` / `josh followup` never re-invokes you; it dies at `exit code 143` (joshuafolkken/kit#2704, measured on the #2606 child: implementation, review and live verification done, the run parked instead of merged). Hand the gate-to-merge region to the detached supervisor instead: `pnpm josh ship --detach --review "<title> #<N>"` (add `--cite <N>`), then end the turn on `launched` / `busy` \u2014 `.claude/skills/workflow-commands/chain-rule.md` step 0 is the single source. A single check you must read before continuing runs in the foreground within the tool timeout; the commit-push step does not \u2014 in a child it too belongs to the detached ship, in either spelling. This rule fires on every occurrence, not once per run.';
|
|
1612
1638
|
var LANE_BACKGROUND_STOP_REASON = "\u26D4 lane background stop: this is a dispatched lane child (`JOSH_LANE_CHILD`) and a background task it launched has not finished \u2014 ending this headless turn kills it, and nothing re-invokes you afterwards (joshuafolkken/kit#2704). Do not send a notification and do not stop: wait for the task in the foreground and act on its result, or re-issue the work through `pnpm josh ship --detach`, whose supervisor outlives the turn (`.claude/skills/workflow-commands/chain-rule.md` step 0). Do not repeat your previous reply.";
|
|
1613
1639
|
var ROW2 = {
|
|
@@ -1621,17 +1647,91 @@ var lane_background = {
|
|
|
1621
1647
|
LANE_BACKGROUND_STOP_REASON,
|
|
1622
1648
|
ROW: ROW2,
|
|
1623
1649
|
is_background_long_run,
|
|
1650
|
+
pending_agent_ids,
|
|
1624
1651
|
pending_background_ids
|
|
1625
1652
|
};
|
|
1626
1653
|
|
|
1627
1654
|
// scripts/git/issue-labels.ts
|
|
1655
|
+
var EPIC_LABEL = "epic";
|
|
1628
1656
|
var BUG_LABEL = "bug";
|
|
1629
1657
|
var ENHANCEMENT_LABEL = "enhancement";
|
|
1630
1658
|
var BREAKING_CHANGE_LABEL = "breaking-change";
|
|
1631
1659
|
var IN_PROGRESS_LABEL = "in-progress";
|
|
1632
1660
|
var NEEDS_DECISION_LABEL = "needs-decision";
|
|
1661
|
+
var RUN_SOLO_LABEL = "run:solo";
|
|
1662
|
+
var RUN_LANE_LABEL = "run:lane";
|
|
1633
1663
|
var NEEDS_HUMAN_REVIEW_LABEL = "needs-human-review";
|
|
1634
1664
|
var ALREADY_DONE_LABEL = "already-done";
|
|
1665
|
+
var INTERRUPT_ROUTE_LABEL = "route:interrupt";
|
|
1666
|
+
var REVIEW_CAP_ROUTE_LABEL = "route:review-cap";
|
|
1667
|
+
var SPLIT_ROUTE_LABEL = "route:split";
|
|
1668
|
+
var TIER_A_ROUTE_LABEL = "route:tier-a";
|
|
1669
|
+
var FILING_ROUTE_LABELS = [
|
|
1670
|
+
{
|
|
1671
|
+
name: INTERRUPT_ROUTE_LABEL,
|
|
1672
|
+
// Not `5319e7`, which is the `epic` label's purple: in a listing an interrupt would render as
|
|
1673
|
+
// an epic, and the two are read at a glance rather than by name.
|
|
1674
|
+
color: "1d76db",
|
|
1675
|
+
// Keyed to the tests rather than to severity. "A serious defect" is the self-assessment
|
|
1676
|
+
// `wip-cap.md` bans as a criterion, and this string is what a person reads in `gh label list`.
|
|
1677
|
+
description: "Filed past the WIP cap \u2014 meets one of the three interrupt tests (wip-cap.md)"
|
|
1678
|
+
},
|
|
1679
|
+
{
|
|
1680
|
+
name: REVIEW_CAP_ROUTE_LABEL,
|
|
1681
|
+
color: "eab308",
|
|
1682
|
+
description: "Filed by the review round cap's carry-forward (prompts/review.md \u2192 Review round cap)"
|
|
1683
|
+
},
|
|
1684
|
+
{
|
|
1685
|
+
name: SPLIT_ROUTE_LABEL,
|
|
1686
|
+
color: "0e8a16",
|
|
1687
|
+
description: "A child issue created by a split (split-assessment.md)"
|
|
1688
|
+
},
|
|
1689
|
+
{
|
|
1690
|
+
name: TIER_A_ROUTE_LABEL,
|
|
1691
|
+
color: "d93f0b",
|
|
1692
|
+
description: "Filed Tier A during implementation \u2014 an upstream defect or a prerequisite"
|
|
1693
|
+
}
|
|
1694
|
+
];
|
|
1695
|
+
var DEPTH_0_LABEL = "depth:0";
|
|
1696
|
+
var DEPTH_1_LABEL = "depth:1";
|
|
1697
|
+
var DEPTH_2_LABEL = "depth:2";
|
|
1698
|
+
var DEPTH_LABELS = [
|
|
1699
|
+
{
|
|
1700
|
+
name: DEPTH_0_LABEL,
|
|
1701
|
+
color: "0e8a16",
|
|
1702
|
+
description: "Depth 0 \u2014 what a consumer of this package touches (SKILL.md \xA72i)"
|
|
1703
|
+
},
|
|
1704
|
+
{
|
|
1705
|
+
name: DEPTH_1_LABEL,
|
|
1706
|
+
color: "fbc02d",
|
|
1707
|
+
description: "Depth 1 \u2014 the run orchestration that executes an Issue (SKILL.md \xA72i)"
|
|
1708
|
+
},
|
|
1709
|
+
{
|
|
1710
|
+
name: DEPTH_2_LABEL,
|
|
1711
|
+
color: "c5def5",
|
|
1712
|
+
description: "Depth 2 \u2014 what measures a run (SKILL.md \xA72i)"
|
|
1713
|
+
}
|
|
1714
|
+
];
|
|
1715
|
+
var WORKFLOW_LABELS = [
|
|
1716
|
+
{
|
|
1717
|
+
name: EPIC_LABEL,
|
|
1718
|
+
color: "5319e7",
|
|
1719
|
+
description: "Tracks a batch of child issues from one split"
|
|
1720
|
+
},
|
|
1721
|
+
{ name: IN_PROGRESS_LABEL, color: "0075ca", description: "Work is actively in progress" },
|
|
1722
|
+
{
|
|
1723
|
+
name: RUN_SOLO_LABEL,
|
|
1724
|
+
color: "b60205",
|
|
1725
|
+
description: "Runs alone in a backlogrun: nothing starts beside it"
|
|
1726
|
+
},
|
|
1727
|
+
{
|
|
1728
|
+
name: RUN_LANE_LABEL,
|
|
1729
|
+
color: "0e8a16",
|
|
1730
|
+
description: "Judged safe to run beside others in a backlogrun"
|
|
1731
|
+
},
|
|
1732
|
+
...FILING_ROUTE_LABELS,
|
|
1733
|
+
...DEPTH_LABELS
|
|
1734
|
+
];
|
|
1635
1735
|
function has_any_label(labels, wanted) {
|
|
1636
1736
|
return (labels ?? []).some((label) => wanted.has(label.name.toLowerCase()));
|
|
1637
1737
|
}
|
|
@@ -3520,6 +3620,8 @@ export {
|
|
|
3520
3620
|
BREAKING_CHANGE_LABEL,
|
|
3521
3621
|
IN_PROGRESS_LABEL,
|
|
3522
3622
|
NEEDS_DECISION_LABEL,
|
|
3623
|
+
RUN_SOLO_LABEL,
|
|
3624
|
+
RUN_LANE_LABEL,
|
|
3523
3625
|
NEEDS_HUMAN_REVIEW_LABEL,
|
|
3524
3626
|
ALREADY_DONE_LABEL,
|
|
3525
3627
|
has_any_label,
|
|
@@ -1016,15 +1016,23 @@ var PROJECT_COMMANDS = {
|
|
|
1016
1016
|
},
|
|
1017
1017
|
start: {
|
|
1018
1018
|
script: "scripts/init/start.ts",
|
|
1019
|
-
description: "
|
|
1019
|
+
description: "Create a new project for the GitHub Issue workflow, from git init to labels",
|
|
1020
1020
|
category: "Project",
|
|
1021
|
-
reference: [
|
|
1021
|
+
reference: [
|
|
1022
|
+
`${PROFILE_ARGUMENTS} [--yes] [--github] [--public]`,
|
|
1023
|
+
"developer",
|
|
1024
|
+
["files", "git", "network", "processes"]
|
|
1025
|
+
]
|
|
1022
1026
|
},
|
|
1023
1027
|
init: {
|
|
1024
1028
|
script: "scripts/init/init.ts",
|
|
1025
1029
|
description: "Initialize config in a new project",
|
|
1026
1030
|
category: "Project",
|
|
1027
|
-
reference: [
|
|
1031
|
+
reference: [
|
|
1032
|
+
`${PROFILE_ARGUMENTS} [--no-install]`,
|
|
1033
|
+
"developer",
|
|
1034
|
+
["files", "network", "processes"]
|
|
1035
|
+
]
|
|
1028
1036
|
},
|
|
1029
1037
|
sync: {
|
|
1030
1038
|
script: "scripts/sync/sync.ts",
|
|
@@ -1165,9 +1173,9 @@ var WORKFLOW_COMMANDS = {
|
|
|
1165
1173
|
reference: ["--task-type <type> --body <text>", "automation", ["notifications"]],
|
|
1166
1174
|
tsx_arguments: OPTIONAL_ENV_FILE_FLAGS
|
|
1167
1175
|
},
|
|
1168
|
-
// The observation ledger's
|
|
1169
|
-
//
|
|
1170
|
-
//
|
|
1176
|
+
// The observation ledger's commit path for the lines no run's own commit carried
|
|
1177
|
+
// (joshuafolkken/kit#1756, joshuafolkken/kit#2763): a lane's lines sit in the primary checkout, which
|
|
1178
|
+
// its commit cannot see, and the recurrence count the promotion rule reads is a count of main.
|
|
1171
1179
|
"observations:flush": {
|
|
1172
1180
|
script: "scripts/observations/observations-flush-cli.ts",
|
|
1173
1181
|
description: "Commit the observation ledger as a pull request of its own, and merge it",
|
|
@@ -1493,6 +1501,7 @@ var time_shell = {
|
|
|
1493
1501
|
var NO_BACKGROUND = "";
|
|
1494
1502
|
var NO_FINISH = 0;
|
|
1495
1503
|
var LAUNCH_PATTERN = /running in background with ID:\s*([\w-]+)/iu;
|
|
1504
|
+
var AGENT_LAUNCH_PATTERN = /^Async agent launched[\s\S]*?\bagentId:\s*([\w-]+)/u;
|
|
1496
1505
|
var FINISH_PATTERN = /^<task-notification>[\s\S]*?<task-id>([\w-]+)<\/task-id>/u;
|
|
1497
1506
|
var OUTPUT_PATTERN = /tasks\/([\w-]+)\.output/u;
|
|
1498
1507
|
var BASH_ID_KEY = "bash_id";
|
|
@@ -1507,6 +1516,9 @@ function read_id_of(input) {
|
|
|
1507
1516
|
function launch_id(text) {
|
|
1508
1517
|
return LAUNCH_PATTERN.exec(text)?.[1] ?? NO_BACKGROUND;
|
|
1509
1518
|
}
|
|
1519
|
+
function agent_launch_id(text) {
|
|
1520
|
+
return AGENT_LAUNCH_PATTERN.exec(text)?.[1] ?? NO_BACKGROUND;
|
|
1521
|
+
}
|
|
1510
1522
|
function finished_id(text) {
|
|
1511
1523
|
return FINISH_PATTERN.exec(text)?.[1] ?? NO_BACKGROUND;
|
|
1512
1524
|
}
|
|
@@ -1571,6 +1583,7 @@ var time_background = {
|
|
|
1571
1583
|
NO_BACKGROUND,
|
|
1572
1584
|
NO_FINISH,
|
|
1573
1585
|
launch_id,
|
|
1586
|
+
agent_launch_id,
|
|
1574
1587
|
finished_id,
|
|
1575
1588
|
finished_at,
|
|
1576
1589
|
read_id,
|
|
@@ -2406,7 +2419,8 @@ function to_block2(raw) {
|
|
|
2406
2419
|
followup_stages: time_followup_stage.read_stages(text),
|
|
2407
2420
|
error_text: is_error === true ? text.slice(0, ERROR_TEXT_LIMIT) : "",
|
|
2408
2421
|
refusal_guard: is_error === true ? guard_from_refusal(text) : "",
|
|
2409
|
-
background_id: time_background.launch_id(text)
|
|
2422
|
+
background_id: time_background.launch_id(text),
|
|
2423
|
+
agent_id: time_background.agent_launch_id(text)
|
|
2410
2424
|
};
|
|
2411
2425
|
}
|
|
2412
2426
|
function to_blocks2(content) {
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
investigation_reads
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-F6OM6SIG.js";
|
|
4
4
|
import {
|
|
5
5
|
lane_guard_policy
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-2K52BRWV.js";
|
|
7
7
|
import {
|
|
8
8
|
hook_decision
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-KQG4776P.js";
|
|
10
10
|
import {
|
|
11
11
|
json_value,
|
|
12
12
|
time_spans
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-ZPLXLJ7O.js";
|
|
14
14
|
|
|
15
15
|
// scripts/delegation/duplicate-read-guard.ts
|
|
16
16
|
import { statSync } from "node:fs";
|