@delete101020/aidlc 4.0.39 → 4.0.42
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/README.md +1 -1
- package/dist/bundle.js +1676 -223
- package/dist/templates/ainative/artifacts/build-plan.md +4 -0
- package/dist/templates/ainative/artifacts/implement.md +18 -5
- package/dist/templates/ainative/artifacts/review.md +3 -2
- package/dist/templates/ainative/artifacts/verify.md +3 -2
- package/dist/templates/ainative/skills/native-build-plan.md +9 -0
- package/dist/templates/ainative/skills/native-implement.md +26 -2
- package/dist/templates/ainative/skills/native-review.md +7 -3
- package/dist/templates/ainative/skills/native-verify.md +7 -2
- package/dist/templates/ainative/validators/verdict.mjs +109 -0
- package/dist/templates/sdlc/validators/ci.mjs +3 -1
- package/package.json +1 -1
package/dist/bundle.js
CHANGED
|
@@ -19700,6 +19700,7 @@ var require_FollowUpHookSchema = __commonJS({
|
|
|
19700
19700
|
return typeof p === "string" && path17.posix.basename(p.replace(/\\/g, "/")) === exports2.FOLLOW_UPS_FILE;
|
|
19701
19701
|
});
|
|
19702
19702
|
}
|
|
19703
|
+
var STEP_KEYS_NOT_HOOKS = ["on_reject"];
|
|
19703
19704
|
function collectFollowUpHookIssues(raw) {
|
|
19704
19705
|
const issues = [];
|
|
19705
19706
|
const pipelines = raw?.pipelines;
|
|
@@ -19720,7 +19721,7 @@ var require_FollowUpHookSchema = __commonJS({
|
|
|
19720
19721
|
const label = typeof step.name === "string" ? step.name : typeof step.agent === "string" ? step.agent : String(si);
|
|
19721
19722
|
const at = `pipelines.${pid}.steps.${label}`;
|
|
19722
19723
|
for (const key of Object.keys(step)) {
|
|
19723
|
-
if (!key.startsWith("on_")) {
|
|
19724
|
+
if (!key.startsWith("on_") || STEP_KEYS_NOT_HOOKS.includes(key)) {
|
|
19724
19725
|
continue;
|
|
19725
19726
|
}
|
|
19726
19727
|
if (!isHookKey(key)) {
|
|
@@ -19763,15 +19764,18 @@ var require_WorkspaceSchema = __commonJS({
|
|
|
19763
19764
|
"../core/dist/schema/WorkspaceSchema.js"(exports2) {
|
|
19764
19765
|
"use strict";
|
|
19765
19766
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
19766
|
-
exports2.WorkspaceValidationError = exports2.WorkspaceSchema = void 0;
|
|
19767
|
-
exports2.normalizeStep =
|
|
19767
|
+
exports2.WorkspaceValidationError = exports2.WorkspaceSchema = exports2.AMBIGUOUS_STEP_INDEX = exports2.DEFAULT_MAX_BATCHES = exports2.DEFAULT_MAX_SEND_BACKS = void 0;
|
|
19768
|
+
exports2.normalizeStep = normalizeStep5;
|
|
19768
19769
|
exports2.stepSkillAlternatives = stepSkillAlternatives;
|
|
19769
19770
|
exports2.resolveStepSkills = resolveStepSkills;
|
|
19770
19771
|
exports2.producesEntries = producesEntries;
|
|
19771
19772
|
exports2.requiresEntries = requiresEntries;
|
|
19772
19773
|
exports2.stepAgentId = stepAgentId3;
|
|
19773
19774
|
exports2.stepDagId = stepDagId;
|
|
19775
|
+
exports2.findStepIndex = findStepIndex2;
|
|
19776
|
+
exports2.sendBackIssues = sendBackIssues;
|
|
19774
19777
|
exports2.collectWorkspaceRefIssues = collectWorkspaceRefIssues3;
|
|
19778
|
+
exports2.unsafeRunnerArg = unsafeRunnerArg;
|
|
19775
19779
|
exports2.validateWorkspace = validateWorkspace6;
|
|
19776
19780
|
var zod_1 = require_zod();
|
|
19777
19781
|
var FollowUpHookSchema_1 = require_FollowUpHookSchema();
|
|
@@ -19947,6 +19951,46 @@ var require_WorkspaceSchema = __commonJS({
|
|
|
19947
19951
|
* (infinite loop, network stall). Defaults to 120_000 when omitted.
|
|
19948
19952
|
*/
|
|
19949
19953
|
auto_review_timeout_ms: zod_1.z.number().int().positive().optional(),
|
|
19954
|
+
/**
|
|
19955
|
+
* Where an `auto_review` reject sends the work. Without it the step is
|
|
19956
|
+
* rejected in place and the run stops — right for a check on the step's
|
|
19957
|
+
* own output, wrong for verify/review, where running the check again on
|
|
19958
|
+
* the same code gives the same answer and it is `implement` that has to
|
|
19959
|
+
* change. The target reopens with the reason as its feedback, the steps
|
|
19960
|
+
* after it reset, and the autopilot loop carries on from there.
|
|
19961
|
+
*
|
|
19962
|
+
* The target is a step name (or agent id) before this one, without
|
|
19963
|
+
* `human_review` — work a human gate approved goes back through a human.
|
|
19964
|
+
* A validator can name the same target in its verdict (`sendBackTo`), or
|
|
19965
|
+
* name this step / `null` to stop here instead. Bounded by the
|
|
19966
|
+
* pipeline's `max_send_backs`.
|
|
19967
|
+
*/
|
|
19968
|
+
on_reject: zod_1.z.object({ send_back_to: zod_1.z.string().min(1) }).optional(),
|
|
19969
|
+
/**
|
|
19970
|
+
* Minutes the step's agent may run under `aidlc run exec` / Run to
|
|
19971
|
+
* completion before it is stopped (the whole process tree: SIGTERM, then
|
|
19972
|
+
* SIGKILL). A timed-out step fails the run — it is not sent back and does
|
|
19973
|
+
* not count toward `max_send_backs` — and stays `awaiting_work`. Unset
|
|
19974
|
+
* means no limit.
|
|
19975
|
+
*/
|
|
19976
|
+
timeout_minutes: zod_1.z.number().positive().optional(),
|
|
19977
|
+
/**
|
|
19978
|
+
* Run the step as a series of agent sessions ("batches") instead of one.
|
|
19979
|
+
* Each session does a slice of the work and ends its first `produces`
|
|
19980
|
+
* file with `Status: continue` or `Status: done`; on `continue` the exec
|
|
19981
|
+
* loop starts a fresh session on the same revision. A missing or
|
|
19982
|
+
* unreadable `Status:` line fails the step. `timeout_minutes` applies to
|
|
19983
|
+
* each batch.
|
|
19984
|
+
*/
|
|
19985
|
+
batches: zod_1.z.boolean().optional(),
|
|
19986
|
+
/**
|
|
19987
|
+
* Batches one `aidlc run exec` may run on this step before it stops for a
|
|
19988
|
+
* person ({@link DEFAULT_MAX_BATCHES} when unset). Running exec again
|
|
19989
|
+
* allows as many more.
|
|
19990
|
+
*/
|
|
19991
|
+
max_batches: zod_1.z.number().int().positive().optional(),
|
|
19992
|
+
/** Stop the loop after every `continue` batch, for a person to look before the next. */
|
|
19993
|
+
pause_between_batches: zod_1.z.boolean().optional(),
|
|
19950
19994
|
/** When true, the runner pauses for human approval before advancing. */
|
|
19951
19995
|
human_review: zod_1.z.boolean().default(false),
|
|
19952
19996
|
/**
|
|
@@ -20008,12 +20052,42 @@ var require_WorkspaceSchema = __commonJS({
|
|
|
20008
20052
|
recipe: zod_1.z.string().min(1).optional(),
|
|
20009
20053
|
steps: zod_1.z.array(PipelineStepSchema).min(1),
|
|
20010
20054
|
on_failure: zod_1.z.enum(["stop", "continue"]).default("stop"),
|
|
20011
|
-
budget: PipelineBudgetSchema.optional()
|
|
20055
|
+
budget: PipelineBudgetSchema.optional(),
|
|
20056
|
+
/**
|
|
20057
|
+
* How many times the autopilot loop may send work back (`on_reject`)
|
|
20058
|
+
* before it stops for a human. Counted from the last time a human acted on
|
|
20059
|
+
* the run — approve, reject, rerun, request update — so a run that was
|
|
20060
|
+
* steered by hand does not start out at the ceiling. Defaults to
|
|
20061
|
+
* {@link DEFAULT_MAX_SEND_BACKS}; 0 stops at the first reject.
|
|
20062
|
+
*/
|
|
20063
|
+
max_send_backs: zod_1.z.number().int().min(0).optional(),
|
|
20064
|
+
/**
|
|
20065
|
+
* The run is meant to go unattended. `aidlc run exec` / Run to completion
|
|
20066
|
+
* then refuses to start unless it is safe to leave alone — on a branch
|
|
20067
|
+
* other than main, a clean working tree, the approval-gate hook registered
|
|
20068
|
+
* for Claude steps — and the hook blocks on its own errors instead of
|
|
20069
|
+
* allowing. See `runs/autopilotPreflight.ts`.
|
|
20070
|
+
*/
|
|
20071
|
+
autopilot: zod_1.z.boolean().optional()
|
|
20072
|
+
}).superRefine((p, ctx) => {
|
|
20073
|
+
for (const issue of sendBackIssues(p.steps)) {
|
|
20074
|
+
ctx.addIssue({ code: "custom", path: ["steps", issue.stepIdx, "on_reject", "send_back_to"], message: issue.message });
|
|
20075
|
+
}
|
|
20012
20076
|
});
|
|
20077
|
+
exports2.DEFAULT_MAX_SEND_BACKS = 3;
|
|
20078
|
+
exports2.DEFAULT_MAX_BATCHES = 10;
|
|
20013
20079
|
var RecipeGateSchema = zod_1.z.object({
|
|
20014
20080
|
human_review: zod_1.z.boolean().optional(),
|
|
20015
20081
|
auto_review: zod_1.z.boolean().optional(),
|
|
20016
|
-
auto_review_runner: zod_1.z.string().min(1).optional()
|
|
20082
|
+
auto_review_runner: zod_1.z.string().min(1).optional(),
|
|
20083
|
+
/** Where this step's auto-review reject sends the work — see the step's `on_reject`. */
|
|
20084
|
+
on_reject: zod_1.z.object({ send_back_to: zod_1.z.string().min(1) }).optional(),
|
|
20085
|
+
/** Run-time limit for this step — see the step's `timeout_minutes`. */
|
|
20086
|
+
timeout_minutes: zod_1.z.number().positive().optional(),
|
|
20087
|
+
/** Batched sessions for this step — see the step's `batches`. */
|
|
20088
|
+
batches: zod_1.z.boolean().optional(),
|
|
20089
|
+
max_batches: zod_1.z.number().int().positive().optional(),
|
|
20090
|
+
pause_between_batches: zod_1.z.boolean().optional()
|
|
20017
20091
|
});
|
|
20018
20092
|
var RecipeSchema = zod_1.z.object({
|
|
20019
20093
|
id: zod_1.z.string().min(1),
|
|
@@ -20038,9 +20112,13 @@ var require_WorkspaceSchema = __commonJS({
|
|
|
20038
20112
|
* plan) and none after, a risky one wants them everywhere. Only the fields
|
|
20039
20113
|
* present override; the rest inherit.
|
|
20040
20114
|
*/
|
|
20041
|
-
gates: zod_1.z.record(zod_1.z.string(), RecipeGateSchema).optional()
|
|
20115
|
+
gates: zod_1.z.record(zod_1.z.string(), RecipeGateSchema).optional(),
|
|
20116
|
+
/** Sets the assembled pipeline's `autopilot` — see the pipeline's. */
|
|
20117
|
+
autopilot: zod_1.z.boolean().optional(),
|
|
20118
|
+
/** Sets the assembled pipeline's `max_send_backs`, over the source pipeline's. */
|
|
20119
|
+
max_send_backs: zod_1.z.number().int().min(0).optional()
|
|
20042
20120
|
});
|
|
20043
|
-
function
|
|
20121
|
+
function normalizeStep5(step) {
|
|
20044
20122
|
if (typeof step === "string") {
|
|
20045
20123
|
return {
|
|
20046
20124
|
agent: step,
|
|
@@ -20086,6 +20164,14 @@ var require_WorkspaceSchema = __commonJS({
|
|
|
20086
20164
|
auto_review: obj.auto_review === true,
|
|
20087
20165
|
auto_review_runner: typeof obj.auto_review_runner === "string" ? obj.auto_review_runner : void 0,
|
|
20088
20166
|
auto_review_timeout_ms: typeof obj.auto_review_timeout_ms === "number" && obj.auto_review_timeout_ms > 0 ? obj.auto_review_timeout_ms : void 0,
|
|
20167
|
+
...isOnReject(obj.on_reject) ? { on_reject: { send_back_to: obj.on_reject.send_back_to } } : {},
|
|
20168
|
+
...typeof obj.timeout_minutes === "number" && obj.timeout_minutes > 0 ? { timeout_minutes: obj.timeout_minutes } : {},
|
|
20169
|
+
...obj.batches === true ? {
|
|
20170
|
+
batches: {
|
|
20171
|
+
max: typeof obj.max_batches === "number" && obj.max_batches >= 1 ? Math.floor(obj.max_batches) : exports2.DEFAULT_MAX_BATCHES,
|
|
20172
|
+
pause: obj.pause_between_batches === true
|
|
20173
|
+
}
|
|
20174
|
+
} : {},
|
|
20089
20175
|
human_review: obj.human_review === true,
|
|
20090
20176
|
...git && { git }
|
|
20091
20177
|
};
|
|
@@ -20136,9 +20222,57 @@ var require_WorkspaceSchema = __commonJS({
|
|
|
20136
20222
|
return "";
|
|
20137
20223
|
}
|
|
20138
20224
|
function stepDagId(step) {
|
|
20139
|
-
const norm =
|
|
20225
|
+
const norm = normalizeStep5(step);
|
|
20140
20226
|
return norm.name ?? norm.agent;
|
|
20141
20227
|
}
|
|
20228
|
+
exports2.AMBIGUOUS_STEP_INDEX = -2;
|
|
20229
|
+
function findStepIndex2(steps, ref) {
|
|
20230
|
+
const asInt = parseInt(ref, 10);
|
|
20231
|
+
if (!isNaN(asInt) && String(asInt) === ref) {
|
|
20232
|
+
return asInt >= 0 && asInt < steps.length ? asInt : -1;
|
|
20233
|
+
}
|
|
20234
|
+
const byName = steps.findIndex((s) => s.name === ref);
|
|
20235
|
+
if (byName >= 0) {
|
|
20236
|
+
return byName;
|
|
20237
|
+
}
|
|
20238
|
+
const byAgent = steps.map((s, i) => s.agent === ref ? i : -1).filter((i) => i >= 0);
|
|
20239
|
+
if (byAgent.length > 1) {
|
|
20240
|
+
return exports2.AMBIGUOUS_STEP_INDEX;
|
|
20241
|
+
}
|
|
20242
|
+
return byAgent.length === 1 ? byAgent[0] : -1;
|
|
20243
|
+
}
|
|
20244
|
+
function isOnReject(v) {
|
|
20245
|
+
return !!v && typeof v === "object" && typeof v.send_back_to === "string" && v.send_back_to.length > 0;
|
|
20246
|
+
}
|
|
20247
|
+
function sendBackIssues(steps) {
|
|
20248
|
+
const norms = steps.map((s) => normalizeStep5(s));
|
|
20249
|
+
const issues = [];
|
|
20250
|
+
norms.forEach((n, i) => {
|
|
20251
|
+
const target = n.on_reject?.send_back_to;
|
|
20252
|
+
if (!target) {
|
|
20253
|
+
return;
|
|
20254
|
+
}
|
|
20255
|
+
const id = n.name ?? n.agent;
|
|
20256
|
+
const add = (message) => {
|
|
20257
|
+
issues.push({ stepIdx: i, message: `Step "${id}": ${message}` });
|
|
20258
|
+
};
|
|
20259
|
+
if (!n.auto_review) {
|
|
20260
|
+
add("`on_reject` routes an auto-review reject, and this step has `auto_review` off.");
|
|
20261
|
+
return;
|
|
20262
|
+
}
|
|
20263
|
+
const t = findStepIndex2(norms, target);
|
|
20264
|
+
if (t === exports2.AMBIGUOUS_STEP_INDEX) {
|
|
20265
|
+
add(`\`on_reject.send_back_to\` "${target}" is an agent with more than one step; name the step.`);
|
|
20266
|
+
} else if (t < 0) {
|
|
20267
|
+
add(`\`on_reject.send_back_to\` "${target}" is not a step of this pipeline.`);
|
|
20268
|
+
} else if (t >= i) {
|
|
20269
|
+
add(`\`on_reject.send_back_to\` "${target}" must be a step before this one.`);
|
|
20270
|
+
} else if (norms[t].human_review) {
|
|
20271
|
+
add(`\`on_reject.send_back_to\` "${target}" has \`human_review: true\`. Work a human approved goes back through a human \u2014 turn that gate off or drop \`on_reject\`.`);
|
|
20272
|
+
}
|
|
20273
|
+
});
|
|
20274
|
+
return issues;
|
|
20275
|
+
}
|
|
20142
20276
|
function collectWorkspaceRefIssues3(config) {
|
|
20143
20277
|
const issues = [];
|
|
20144
20278
|
const agentIds = new Set(config.agents.map((a) => a.id));
|
|
@@ -20156,7 +20290,7 @@ var require_WorkspaceSchema = __commonJS({
|
|
|
20156
20290
|
}
|
|
20157
20291
|
for (const pipeline of config.pipelines) {
|
|
20158
20292
|
for (const step of pipeline.steps) {
|
|
20159
|
-
const norm =
|
|
20293
|
+
const norm = normalizeStep5(step);
|
|
20160
20294
|
const id = norm.name ?? norm.agent;
|
|
20161
20295
|
if (!agentIds.has(norm.agent)) {
|
|
20162
20296
|
issues.push({
|
|
@@ -20282,8 +20416,60 @@ var require_WorkspaceSchema = __commonJS({
|
|
|
20282
20416
|
/** Claude tier alias (or any `model:` value) → concrete model id, lowercased keys. */
|
|
20283
20417
|
model_aliases: zod_1.z.record(zod_1.z.string(), zod_1.z.string()).default({}),
|
|
20284
20418
|
/** Model id → rate. The key `*` applies to every model of this provider. */
|
|
20285
|
-
rates: zod_1.z.record(zod_1.z.string(), ProviderRateSchema).default({})
|
|
20419
|
+
rates: zod_1.z.record(zod_1.z.string(), ProviderRateSchema).default({}),
|
|
20420
|
+
/**
|
|
20421
|
+
* Extra command-line arguments for this runner's CLI, added to every step it
|
|
20422
|
+
* runs — chiefly what a headless agent may do without asking:
|
|
20423
|
+
*
|
|
20424
|
+
* ```yaml
|
|
20425
|
+
* providers:
|
|
20426
|
+
* default:
|
|
20427
|
+
* args: [--permission-mode, acceptEdits, --allowedTools, "Bash(npm test:*)"]
|
|
20428
|
+
* ```
|
|
20429
|
+
*
|
|
20430
|
+
* Committed with the workspace, so the whole team runs with the same
|
|
20431
|
+
* permissions instead of each clone's own `.claude/settings.json`. Flags
|
|
20432
|
+
* that switch permission checks off altogether are refused — see
|
|
20433
|
+
* {@link unsafeRunnerArg}.
|
|
20434
|
+
*/
|
|
20435
|
+
args: zod_1.z.array(zod_1.z.string()).default([])
|
|
20436
|
+
}).superRefine((p, ctx) => {
|
|
20437
|
+
const bad = unsafeRunnerArg(p.args);
|
|
20438
|
+
if (bad) {
|
|
20439
|
+
ctx.addIssue({
|
|
20440
|
+
code: "custom",
|
|
20441
|
+
path: ["args"],
|
|
20442
|
+
message: `\`${bad}\` switches the agent's permission checks off, and \`args\` is committed for everyone who runs this workspace \u2014 unattended runs included. Allow the tools it needs instead (\`--allowedTools\` for Claude), or run it in a sandbox of your own with \`runner: custom\`.`
|
|
20443
|
+
});
|
|
20444
|
+
}
|
|
20286
20445
|
});
|
|
20446
|
+
function unsafeRunnerArg(args) {
|
|
20447
|
+
const flags = /* @__PURE__ */ new Set([
|
|
20448
|
+
"--dangerously-skip-permissions",
|
|
20449
|
+
"--allow-dangerously-skip-permissions",
|
|
20450
|
+
"--dangerously-bypass-approvals-and-sandbox",
|
|
20451
|
+
"--yolo",
|
|
20452
|
+
"--allow-all",
|
|
20453
|
+
"--allow-all-paths"
|
|
20454
|
+
]);
|
|
20455
|
+
const values = {
|
|
20456
|
+
"--permission-mode": "bypassPermissions",
|
|
20457
|
+
"--sandbox": "danger-full-access",
|
|
20458
|
+
"-s": "danger-full-access"
|
|
20459
|
+
};
|
|
20460
|
+
for (let i = 0; i < args.length; i++) {
|
|
20461
|
+
const [flag, inline] = args[i].split(/=(.*)/s, 2);
|
|
20462
|
+
if (flags.has(flag)) {
|
|
20463
|
+
return args[i];
|
|
20464
|
+
}
|
|
20465
|
+
const unsafe = values[flag];
|
|
20466
|
+
const value = inline ?? args[i + 1];
|
|
20467
|
+
if (unsafe && value === unsafe) {
|
|
20468
|
+
return `${flag} ${unsafe}`;
|
|
20469
|
+
}
|
|
20470
|
+
}
|
|
20471
|
+
return null;
|
|
20472
|
+
}
|
|
20287
20473
|
exports2.WorkspaceSchema = zod_1.z.object({
|
|
20288
20474
|
/** Schema version — bump on breaking changes. Currently always "1.0". */
|
|
20289
20475
|
version: zod_1.z.string().min(1),
|
|
@@ -20394,7 +20580,7 @@ var require_PipelineAssembler = __commonJS({
|
|
|
20394
20580
|
"use strict";
|
|
20395
20581
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
20396
20582
|
exports2.PipelineAssembleError = void 0;
|
|
20397
|
-
exports2.assemblePipeline =
|
|
20583
|
+
exports2.assemblePipeline = assemblePipeline5;
|
|
20398
20584
|
exports2.recipePipelineId = recipePipelineId4;
|
|
20399
20585
|
exports2.pipelineRecipeLabel = pipelineRecipeLabel;
|
|
20400
20586
|
var WorkspaceSchema_1 = require_WorkspaceSchema();
|
|
@@ -20405,7 +20591,7 @@ var require_PipelineAssembler = __commonJS({
|
|
|
20405
20591
|
}
|
|
20406
20592
|
};
|
|
20407
20593
|
exports2.PipelineAssembleError = PipelineAssembleError4;
|
|
20408
|
-
function
|
|
20594
|
+
function assemblePipeline5(config, opts) {
|
|
20409
20595
|
const recipe = config.recipes.find((r) => r.id === opts.recipeId);
|
|
20410
20596
|
if (!recipe) {
|
|
20411
20597
|
const available = config.recipes.map((r) => r.id).join(", ") || "(none defined)";
|
|
@@ -20482,14 +20668,40 @@ var require_PipelineAssembler = __commonJS({
|
|
|
20482
20668
|
if (auto_review_runner) {
|
|
20483
20669
|
step.auto_review_runner = auto_review_runner;
|
|
20484
20670
|
}
|
|
20671
|
+
const on_reject = gate.on_reject ?? norm.on_reject;
|
|
20672
|
+
if (on_reject) {
|
|
20673
|
+
step.on_reject = { send_back_to: on_reject.send_back_to };
|
|
20674
|
+
}
|
|
20675
|
+
const timeout_minutes = gate.timeout_minutes ?? norm.timeout_minutes;
|
|
20676
|
+
if (timeout_minutes !== void 0) {
|
|
20677
|
+
step.timeout_minutes = timeout_minutes;
|
|
20678
|
+
}
|
|
20679
|
+
const batched = gate.batches ?? norm.batches !== void 0;
|
|
20680
|
+
if (batched) {
|
|
20681
|
+
step.batches = true;
|
|
20682
|
+
const max = gate.max_batches ?? norm.batches?.max;
|
|
20683
|
+
if (max !== void 0) {
|
|
20684
|
+
step.max_batches = max;
|
|
20685
|
+
}
|
|
20686
|
+
if (gate.pause_between_batches ?? norm.batches?.pause) {
|
|
20687
|
+
step.pause_between_batches = true;
|
|
20688
|
+
}
|
|
20689
|
+
}
|
|
20485
20690
|
return step;
|
|
20486
20691
|
});
|
|
20692
|
+
const sendBackProblems = (0, WorkspaceSchema_1.sendBackIssues)(steps);
|
|
20693
|
+
if (sendBackProblems.length > 0) {
|
|
20694
|
+
throw new PipelineAssembleError4(`Recipe "${recipe.id}" assembled a pipeline whose \`on_reject\` cannot work:
|
|
20695
|
+
` + sendBackProblems.map((i) => ` - ${i.message}`).join("\n"));
|
|
20696
|
+
}
|
|
20487
20697
|
const assembled = {
|
|
20488
20698
|
id: opts.pipelineId ?? recipe.id,
|
|
20489
20699
|
derived_from: source.id,
|
|
20490
20700
|
recipe: recipe.id,
|
|
20491
20701
|
steps,
|
|
20492
|
-
on_failure: source.on_failure
|
|
20702
|
+
on_failure: source.on_failure,
|
|
20703
|
+
...(recipe.max_send_backs ?? source.max_send_backs) !== void 0 ? { max_send_backs: recipe.max_send_backs ?? source.max_send_backs } : {},
|
|
20704
|
+
...(recipe.autopilot ?? source.autopilot) !== void 0 ? { autopilot: recipe.autopilot ?? source.autopilot } : {}
|
|
20493
20705
|
};
|
|
20494
20706
|
const refIssues = (0, WorkspaceSchema_1.collectWorkspaceRefIssues)({
|
|
20495
20707
|
...config,
|
|
@@ -21495,6 +21707,7 @@ var require_PipelineRunner = __commonJS({
|
|
|
21495
21707
|
const step = state.steps[idx];
|
|
21496
21708
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
21497
21709
|
const next = clone(state);
|
|
21710
|
+
delete next.sendBacks;
|
|
21498
21711
|
if (step.status === "approved") {
|
|
21499
21712
|
for (const i of followersOf(pipeline, idx)) {
|
|
21500
21713
|
const follower = next.steps[i];
|
|
@@ -21552,13 +21765,34 @@ var require_PipelineRunner = __commonJS({
|
|
|
21552
21765
|
runner: verdict.runner
|
|
21553
21766
|
});
|
|
21554
21767
|
if (verdict.decision === "reject") {
|
|
21768
|
+
const route = autoRejectRoute(next, pipeline, idx, norm, verdict);
|
|
21769
|
+
if ("targetIdx" in route) {
|
|
21770
|
+
const count = next.sendBacks ?? 0;
|
|
21771
|
+
const max = pipeline.max_send_backs ?? WorkspaceSchema_1.DEFAULT_MAX_SEND_BACKS;
|
|
21772
|
+
if (count < max) {
|
|
21773
|
+
sendBack(next, {
|
|
21774
|
+
idx,
|
|
21775
|
+
targetIdx: route.targetIdx,
|
|
21776
|
+
reason: verdict.reason,
|
|
21777
|
+
at: verdict.at,
|
|
21778
|
+
pipeline,
|
|
21779
|
+
source: route.source
|
|
21780
|
+
});
|
|
21781
|
+
next.sendBacks = count + 1;
|
|
21782
|
+
return next;
|
|
21783
|
+
}
|
|
21784
|
+
route.note = `Sent back ${count} time${count === 1 ? "" : "s"} already (max_send_backs: ${max}) \u2014 stopping for a human instead of going round again.`;
|
|
21785
|
+
}
|
|
21786
|
+
const reason = "note" in route && route.note ? `${verdict.reason}
|
|
21787
|
+
|
|
21788
|
+
${route.note}` : verdict.reason;
|
|
21555
21789
|
nextStep.status = "rejected";
|
|
21556
|
-
nextStep.rejectReason =
|
|
21790
|
+
nextStep.rejectReason = reason;
|
|
21557
21791
|
nextStep.history = pushHistory(nextStep.history, {
|
|
21558
21792
|
kind: "reject",
|
|
21559
21793
|
at: verdict.at,
|
|
21560
21794
|
revision: nextStep.revision,
|
|
21561
|
-
reason
|
|
21795
|
+
reason,
|
|
21562
21796
|
sentBackToIdx: idx,
|
|
21563
21797
|
...nextStep.skill ? { skill: nextStep.skill } : {},
|
|
21564
21798
|
...nextStep.chosenModel ? { model: nextStep.chosenModel } : {}
|
|
@@ -21574,6 +21808,35 @@ var require_PipelineRunner = __commonJS({
|
|
|
21574
21808
|
}
|
|
21575
21809
|
return advance(next, idx, pipeline);
|
|
21576
21810
|
}
|
|
21811
|
+
function autoRejectRoute(state, pipeline, idx, norm, verdict) {
|
|
21812
|
+
const label = (i) => `"${(0, RunState_1.stepIdentity)(state.steps[i])}" (step ${i + 1})`;
|
|
21813
|
+
const configured = norm.on_reject?.send_back_to;
|
|
21814
|
+
const cfgIdx = configured ? (0, WorkspaceSchema_1.findStepIndex)(pipeline.steps.map(WorkspaceSchema_1.normalizeStep), configured) : -1;
|
|
21815
|
+
if (configured && !(cfgIdx >= 0 && cfgIdx < idx)) {
|
|
21816
|
+
return { note: `\`on_reject.send_back_to\` "${configured}" is not a step before this one \u2014 fix the pipeline.` };
|
|
21817
|
+
}
|
|
21818
|
+
if (verdict.sendBackTo === void 0) {
|
|
21819
|
+
return cfgIdx >= 0 ? { targetIdx: cfgIdx, source: "config" } : {};
|
|
21820
|
+
}
|
|
21821
|
+
if (verdict.sendBackTo === null) {
|
|
21822
|
+
return {};
|
|
21823
|
+
}
|
|
21824
|
+
const asked = String(verdict.sendBackTo);
|
|
21825
|
+
const v = (0, WorkspaceSchema_1.findStepIndex)(state.steps, asked);
|
|
21826
|
+
if (v === idx) {
|
|
21827
|
+
return {};
|
|
21828
|
+
}
|
|
21829
|
+
if (v < 0 || v > idx) {
|
|
21830
|
+
return { note: `The validator asked to send this back to "${asked}", which is not a step before this one.` };
|
|
21831
|
+
}
|
|
21832
|
+
if (v !== cfgIdx) {
|
|
21833
|
+
const allowed = cfgIdx >= 0 ? `only ${label(cfgIdx)} is` : "no step is (see `on_reject.send_back_to`)";
|
|
21834
|
+
return {
|
|
21835
|
+
note: `The validator suggests sending this back to ${label(v)}; ${allowed} sent back automatically. Send it back by hand if you agree.`
|
|
21836
|
+
};
|
|
21837
|
+
}
|
|
21838
|
+
return { targetIdx: v, source: "verdict" };
|
|
21839
|
+
}
|
|
21577
21840
|
function retryAutoReview(args) {
|
|
21578
21841
|
const { pipeline } = args;
|
|
21579
21842
|
const state = alignedOrThrow(args.state, pipeline);
|
|
@@ -21596,6 +21859,7 @@ var require_PipelineRunner = __commonJS({
|
|
|
21596
21859
|
throw new PipelineRunError3(`Step "${step.agent}" no longer has auto_review enabled in pipeline "${pipeline.id}".`);
|
|
21597
21860
|
}
|
|
21598
21861
|
const next = clone(state);
|
|
21862
|
+
delete next.sendBacks;
|
|
21599
21863
|
next.steps[idx] = {
|
|
21600
21864
|
...step,
|
|
21601
21865
|
status: "awaiting_auto_review",
|
|
@@ -21616,7 +21880,9 @@ var require_PipelineRunner = __commonJS({
|
|
|
21616
21880
|
if (step.status !== "awaiting_review") {
|
|
21617
21881
|
throw new PipelineRunError3(`Cannot approve step "${step.agent}": status is "${step.status}", expected "awaiting_review"`);
|
|
21618
21882
|
}
|
|
21619
|
-
|
|
21883
|
+
const next = clone(state);
|
|
21884
|
+
delete next.sendBacks;
|
|
21885
|
+
return advance(next, idx, pipeline);
|
|
21620
21886
|
}
|
|
21621
21887
|
function rejectStep3(args) {
|
|
21622
21888
|
const { state, reason, targetIdx, pipeline } = args;
|
|
@@ -21625,75 +21891,19 @@ var require_PipelineRunner = __commonJS({
|
|
|
21625
21891
|
if (!step) {
|
|
21626
21892
|
throw new PipelineRunError3(`No step at index ${idx}`);
|
|
21627
21893
|
}
|
|
21628
|
-
if (step.status !== "awaiting_review") {
|
|
21629
|
-
throw new PipelineRunError3(`Cannot reject step "${step.agent}": status is "${step.status}", expected "awaiting_review"`);
|
|
21630
|
-
}
|
|
21631
21894
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
21632
21895
|
const isCascade = typeof targetIdx === "number" && targetIdx >= 0 && targetIdx < idx;
|
|
21896
|
+
if (step.status !== "awaiting_review" && !(isCascade && step.status === "rejected")) {
|
|
21897
|
+
throw new PipelineRunError3(`Cannot reject step "${step.agent}": status is "${step.status}", expected "awaiting_review"`);
|
|
21898
|
+
}
|
|
21633
21899
|
if (isCascade) {
|
|
21634
21900
|
const next2 = clone(state);
|
|
21635
|
-
|
|
21636
|
-
|
|
21637
|
-
kind: "reject",
|
|
21638
|
-
at: now,
|
|
21639
|
-
revision: next2.steps[idx].revision,
|
|
21640
|
-
reason,
|
|
21641
|
-
sentBackToIdx: targetIdx,
|
|
21642
|
-
...next2.steps[idx].skill ? { skill: next2.steps[idx].skill } : {},
|
|
21643
|
-
...next2.steps[idx].chosenModel ? { model: next2.steps[idx].chosenModel } : {}
|
|
21644
|
-
});
|
|
21645
|
-
const usesDag = pipeline ? pipeline.steps.map(WorkspaceSchema_1.normalizeStep).some((s) => s.depends_on.length > 0) : false;
|
|
21646
|
-
const targetIdxN = targetIdx;
|
|
21647
|
-
const resetIndices = usesDag && pipeline ? collectDagResetSet(pipeline, state, targetIdxN, idx) : sequentialRange(targetIdxN, idx);
|
|
21648
|
-
for (const i of resetIndices) {
|
|
21649
|
-
const s = next2.steps[i];
|
|
21650
|
-
if (i === targetIdxN) {
|
|
21651
|
-
const newRev = s.revision + 1;
|
|
21652
|
-
next2.steps[i] = {
|
|
21653
|
-
...s,
|
|
21654
|
-
status: "awaiting_work",
|
|
21655
|
-
revision: newRev,
|
|
21656
|
-
feedback: blame,
|
|
21657
|
-
rejectReason: void 0,
|
|
21658
|
-
autoReviewVerdict: void 0,
|
|
21659
|
-
artifactsProduced: [],
|
|
21660
|
-
finishedAt: void 0,
|
|
21661
|
-
startedAt: now,
|
|
21662
|
-
history: pushHistory(s.history, {
|
|
21663
|
-
kind: "rerun",
|
|
21664
|
-
at: now,
|
|
21665
|
-
revision: newRev,
|
|
21666
|
-
feedback: blame
|
|
21667
|
-
})
|
|
21668
|
-
};
|
|
21669
|
-
} else if (i === idx) {
|
|
21670
|
-
next2.steps[i] = {
|
|
21671
|
-
...s,
|
|
21672
|
-
status: "pending",
|
|
21673
|
-
rejectReason: void 0,
|
|
21674
|
-
autoReviewVerdict: void 0,
|
|
21675
|
-
artifactsProduced: [],
|
|
21676
|
-
startedAt: void 0,
|
|
21677
|
-
finishedAt: void 0,
|
|
21678
|
-
history: rejectedHistory
|
|
21679
|
-
};
|
|
21680
|
-
} else {
|
|
21681
|
-
next2.steps[i] = {
|
|
21682
|
-
...s,
|
|
21683
|
-
status: "pending",
|
|
21684
|
-
rejectReason: void 0,
|
|
21685
|
-
autoReviewVerdict: void 0,
|
|
21686
|
-
artifactsProduced: [],
|
|
21687
|
-
startedAt: void 0,
|
|
21688
|
-
finishedAt: void 0
|
|
21689
|
-
};
|
|
21690
|
-
}
|
|
21691
|
-
}
|
|
21692
|
-
next2.currentStepIdx = targetIdx;
|
|
21693
|
-
next2.status = "running";
|
|
21901
|
+
sendBack(next2, { idx, targetIdx, reason, at: now, pipeline });
|
|
21902
|
+
delete next2.sendBacks;
|
|
21694
21903
|
return next2;
|
|
21695
21904
|
}
|
|
21696
21905
|
const next = clone(state);
|
|
21906
|
+
delete next.sendBacks;
|
|
21697
21907
|
next.steps[idx] = {
|
|
21698
21908
|
...step,
|
|
21699
21909
|
status: "rejected",
|
|
@@ -21726,6 +21936,7 @@ var require_PipelineRunner = __commonJS({
|
|
|
21726
21936
|
}
|
|
21727
21937
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
21728
21938
|
const next = clone(state);
|
|
21939
|
+
delete next.sendBacks;
|
|
21729
21940
|
const newRev = step.revision + 1;
|
|
21730
21941
|
const carriedFeedback = feedback ?? step.feedback;
|
|
21731
21942
|
next.steps[idx] = {
|
|
@@ -21788,6 +21999,7 @@ var require_PipelineRunner = __commonJS({
|
|
|
21788
21999
|
}
|
|
21789
22000
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
21790
22001
|
const next = clone(state);
|
|
22002
|
+
delete next.sendBacks;
|
|
21791
22003
|
const normalized = pipeline.steps.map(WorkspaceSchema_1.normalizeStep);
|
|
21792
22004
|
const usesDag = normalized.some((s) => s.depends_on.length > 0);
|
|
21793
22005
|
const upper = state.status === "completed" ? pipeline.steps.length - 1 : state.currentStepIdx;
|
|
@@ -21931,6 +22143,7 @@ var require_PipelineRunner = __commonJS({
|
|
|
21931
22143
|
const step = state.steps[idx];
|
|
21932
22144
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
21933
22145
|
const next = clone(state);
|
|
22146
|
+
delete next.sendBacks;
|
|
21934
22147
|
const newRev = step.revision + 1;
|
|
21935
22148
|
const carriedFeedback = feedback ?? step.feedback;
|
|
21936
22149
|
next.steps[idx] = {
|
|
@@ -22077,6 +22290,70 @@ var require_PipelineRunner = __commonJS({
|
|
|
22077
22290
|
next.status = "completed";
|
|
22078
22291
|
}
|
|
22079
22292
|
}
|
|
22293
|
+
function sendBack(next, args) {
|
|
22294
|
+
const { idx, targetIdx, reason, at: now, pipeline, source } = args;
|
|
22295
|
+
const before = clone(next);
|
|
22296
|
+
const step = next.steps[idx];
|
|
22297
|
+
const blame = `Rejected at step ${idx + 1} (${step.agent})${reason ? `: ${reason}` : ""}`;
|
|
22298
|
+
const rejectedHistory = pushHistory(step.history, {
|
|
22299
|
+
kind: "reject",
|
|
22300
|
+
at: now,
|
|
22301
|
+
revision: step.revision,
|
|
22302
|
+
reason,
|
|
22303
|
+
sentBackToIdx: targetIdx,
|
|
22304
|
+
...source ? { source } : {},
|
|
22305
|
+
...step.skill ? { skill: step.skill } : {},
|
|
22306
|
+
...step.chosenModel ? { model: step.chosenModel } : {}
|
|
22307
|
+
});
|
|
22308
|
+
const usesDag = pipeline ? pipeline.steps.map(WorkspaceSchema_1.normalizeStep).some((s) => s.depends_on.length > 0) : false;
|
|
22309
|
+
const resetIndices = usesDag && pipeline ? collectDagResetSet(pipeline, before, targetIdx, idx) : sequentialRange(targetIdx, idx);
|
|
22310
|
+
for (const i of resetIndices) {
|
|
22311
|
+
const s = next.steps[i];
|
|
22312
|
+
if (i === targetIdx) {
|
|
22313
|
+
const newRev = s.revision + 1;
|
|
22314
|
+
next.steps[i] = {
|
|
22315
|
+
...s,
|
|
22316
|
+
status: "awaiting_work",
|
|
22317
|
+
revision: newRev,
|
|
22318
|
+
feedback: blame,
|
|
22319
|
+
rejectReason: void 0,
|
|
22320
|
+
autoReviewVerdict: void 0,
|
|
22321
|
+
artifactsProduced: [],
|
|
22322
|
+
finishedAt: void 0,
|
|
22323
|
+
startedAt: now,
|
|
22324
|
+
history: pushHistory(s.history, {
|
|
22325
|
+
kind: "rerun",
|
|
22326
|
+
at: now,
|
|
22327
|
+
revision: newRev,
|
|
22328
|
+
feedback: blame
|
|
22329
|
+
})
|
|
22330
|
+
};
|
|
22331
|
+
} else if (i === idx) {
|
|
22332
|
+
next.steps[i] = {
|
|
22333
|
+
...s,
|
|
22334
|
+
status: "pending",
|
|
22335
|
+
rejectReason: void 0,
|
|
22336
|
+
autoReviewVerdict: void 0,
|
|
22337
|
+
artifactsProduced: [],
|
|
22338
|
+
startedAt: void 0,
|
|
22339
|
+
finishedAt: void 0,
|
|
22340
|
+
history: rejectedHistory
|
|
22341
|
+
};
|
|
22342
|
+
} else {
|
|
22343
|
+
next.steps[i] = {
|
|
22344
|
+
...s,
|
|
22345
|
+
status: "pending",
|
|
22346
|
+
rejectReason: void 0,
|
|
22347
|
+
autoReviewVerdict: void 0,
|
|
22348
|
+
artifactsProduced: [],
|
|
22349
|
+
startedAt: void 0,
|
|
22350
|
+
finishedAt: void 0
|
|
22351
|
+
};
|
|
22352
|
+
}
|
|
22353
|
+
}
|
|
22354
|
+
next.currentStepIdx = targetIdx;
|
|
22355
|
+
next.status = "running";
|
|
22356
|
+
}
|
|
22080
22357
|
function clone(value) {
|
|
22081
22358
|
return JSON.parse(JSON.stringify(value));
|
|
22082
22359
|
}
|
|
@@ -25489,7 +25766,7 @@ var require_PlanGenerator = __commonJS({
|
|
|
25489
25766
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
25490
25767
|
exports2.generatePlan = generatePlan;
|
|
25491
25768
|
exports2.renderPlanMarkdown = renderPlanMarkdown;
|
|
25492
|
-
function
|
|
25769
|
+
function normalizeStep5(step) {
|
|
25493
25770
|
if (typeof step === "string") {
|
|
25494
25771
|
return { name: step };
|
|
25495
25772
|
}
|
|
@@ -25605,7 +25882,7 @@ var require_PlanGenerator = __commonJS({
|
|
|
25605
25882
|
}
|
|
25606
25883
|
function generatePlan(epicId, context, pipeline, workspace) {
|
|
25607
25884
|
const complexity = inferScopeComplexity(context.scope);
|
|
25608
|
-
const steps = (pipeline.steps || []).map(
|
|
25885
|
+
const steps = (pipeline.steps || []).map(normalizeStep5);
|
|
25609
25886
|
const agentCountPerPhase = allocateAgentCount(complexity, steps.length);
|
|
25610
25887
|
const phaseAllocations = steps.map((step) => {
|
|
25611
25888
|
const agentId = step.agent || "unknown";
|
|
@@ -26727,6 +27004,11 @@ var require_EpicStepEdit = __commonJS({
|
|
|
26727
27004
|
}
|
|
26728
27005
|
function commitEpicStepEdit2(args) {
|
|
26729
27006
|
const { workspaceRoot, doc, plan } = args;
|
|
27007
|
+
const sendBack = (0, WorkspaceSchema_1.sendBackIssues)(plan.pipeline.steps);
|
|
27008
|
+
if (sendBack.length > 0) {
|
|
27009
|
+
throw new EpicStepEditError2(`This edit would leave \`on_reject\` pointing at a step it cannot send work to:
|
|
27010
|
+
` + sendBack.map((i) => ` - ${i.message}`).join("\n"));
|
|
27011
|
+
}
|
|
26730
27012
|
args.writeWorkspace(plan.pipeline);
|
|
26731
27013
|
try {
|
|
26732
27014
|
RunStateStore_1.RunStateStore.save(workspaceRoot, plan.runState);
|
|
@@ -26773,6 +27055,7 @@ var require_EpicStepEdit = __commonJS({
|
|
|
26773
27055
|
delete next.auto_review;
|
|
26774
27056
|
delete next.auto_review_runner;
|
|
26775
27057
|
delete next.auto_review_timeout_ms;
|
|
27058
|
+
delete next.on_reject;
|
|
26776
27059
|
}
|
|
26777
27060
|
const nextRaw = [...raw];
|
|
26778
27061
|
nextRaw[idx] = next;
|
|
@@ -28681,6 +28964,69 @@ var require_resolveCommand = __commonJS({
|
|
|
28681
28964
|
}
|
|
28682
28965
|
});
|
|
28683
28966
|
|
|
28967
|
+
// ../core/dist/runner/processTree.js
|
|
28968
|
+
var require_processTree = __commonJS({
|
|
28969
|
+
"../core/dist/runner/processTree.js"(exports2) {
|
|
28970
|
+
"use strict";
|
|
28971
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
28972
|
+
exports2.STOP_GRACE_MS = void 0;
|
|
28973
|
+
exports2.processGroupSpawnOptions = processGroupSpawnOptions;
|
|
28974
|
+
exports2.stopOnAbort = stopOnAbort;
|
|
28975
|
+
exports2.stopProcessTree = stopProcessTree;
|
|
28976
|
+
var child_process_1 = require("child_process");
|
|
28977
|
+
exports2.STOP_GRACE_MS = 1e4;
|
|
28978
|
+
function processGroupSpawnOptions() {
|
|
28979
|
+
return process.platform === "win32" ? {} : { detached: true };
|
|
28980
|
+
}
|
|
28981
|
+
function stopOnAbort(proc, signal, graceMs = exports2.STOP_GRACE_MS) {
|
|
28982
|
+
if (!signal) {
|
|
28983
|
+
return () => {
|
|
28984
|
+
};
|
|
28985
|
+
}
|
|
28986
|
+
let timer;
|
|
28987
|
+
const onAbort = () => {
|
|
28988
|
+
stopProcessTree(proc, "SIGTERM");
|
|
28989
|
+
timer = setTimeout(() => stopProcessTree(proc, "SIGKILL"), graceMs);
|
|
28990
|
+
timer.unref?.();
|
|
28991
|
+
};
|
|
28992
|
+
if (signal.aborted) {
|
|
28993
|
+
onAbort();
|
|
28994
|
+
} else {
|
|
28995
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
28996
|
+
}
|
|
28997
|
+
return () => {
|
|
28998
|
+
signal.removeEventListener("abort", onAbort);
|
|
28999
|
+
if (timer) {
|
|
29000
|
+
clearTimeout(timer);
|
|
29001
|
+
stopProcessTree(proc, "SIGKILL");
|
|
29002
|
+
}
|
|
29003
|
+
};
|
|
29004
|
+
}
|
|
29005
|
+
function stopProcessTree(proc, sig) {
|
|
29006
|
+
const pid = proc.pid;
|
|
29007
|
+
if (!pid) {
|
|
29008
|
+
return;
|
|
29009
|
+
}
|
|
29010
|
+
if (process.platform === "win32") {
|
|
29011
|
+
try {
|
|
29012
|
+
(0, child_process_1.spawn)("taskkill", ["/pid", String(pid), "/T", "/F"], { stdio: "ignore", windowsHide: true }).on("error", () => {
|
|
29013
|
+
});
|
|
29014
|
+
} catch {
|
|
29015
|
+
}
|
|
29016
|
+
return;
|
|
29017
|
+
}
|
|
29018
|
+
try {
|
|
29019
|
+
process.kill(-pid, sig);
|
|
29020
|
+
} catch {
|
|
29021
|
+
try {
|
|
29022
|
+
proc.kill(sig);
|
|
29023
|
+
} catch {
|
|
29024
|
+
}
|
|
29025
|
+
}
|
|
29026
|
+
}
|
|
29027
|
+
}
|
|
29028
|
+
});
|
|
29029
|
+
|
|
28684
29030
|
// ../core/dist/runner/DefaultRunner.js
|
|
28685
29031
|
var require_DefaultRunner = __commonJS({
|
|
28686
29032
|
"../core/dist/runner/DefaultRunner.js"(exports2) {
|
|
@@ -28693,6 +29039,7 @@ var require_DefaultRunner = __commonJS({
|
|
|
28693
29039
|
var mcp_1 = require_mcp();
|
|
28694
29040
|
var ndjson_1 = require_ndjson();
|
|
28695
29041
|
var resolveCommand_1 = require_resolveCommand();
|
|
29042
|
+
var processTree_1 = require_processTree();
|
|
28696
29043
|
var DefaultRunner3 = class {
|
|
28697
29044
|
opts;
|
|
28698
29045
|
/**
|
|
@@ -28731,6 +29078,10 @@ var require_DefaultRunner = __commonJS({
|
|
|
28731
29078
|
ctx.skill,
|
|
28732
29079
|
...model ? ["--model", model] : [],
|
|
28733
29080
|
...this.opts.extraArgs ?? [],
|
|
29081
|
+
...ctx.extraArgs ?? [],
|
|
29082
|
+
// `--allowedTools` and friends take any number of values, and would take
|
|
29083
|
+
// the prompt as one more; `--` ends the options.
|
|
29084
|
+
"--",
|
|
28734
29085
|
userMessage
|
|
28735
29086
|
];
|
|
28736
29087
|
const cmd = (0, resolveCommand_1.resolveCommand)(bin);
|
|
@@ -28740,8 +29091,10 @@ var require_DefaultRunner = __commonJS({
|
|
|
28740
29091
|
// inside a Claude Code session — a fresh `claude` rejects it as invalid.
|
|
28741
29092
|
// ctx.env (workspace-configured) is layered last so explicit keys win.
|
|
28742
29093
|
env: (0, claudeEnv_1.buildClaudeSpawnEnv)(ctx.env),
|
|
28743
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
29094
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
29095
|
+
...(0, processTree_1.processGroupSpawnOptions)()
|
|
28744
29096
|
});
|
|
29097
|
+
const detach = (0, processTree_1.stopOnAbort)(proc, ctx.signal);
|
|
28745
29098
|
let finalText = "";
|
|
28746
29099
|
let costUsd;
|
|
28747
29100
|
const handleEvent = (evt) => {
|
|
@@ -28767,11 +29120,13 @@ var require_DefaultRunner = __commonJS({
|
|
|
28767
29120
|
});
|
|
28768
29121
|
return new Promise((resolve5) => {
|
|
28769
29122
|
proc.on("error", (err) => {
|
|
29123
|
+
detach();
|
|
28770
29124
|
ctx.onError(`Failed to spawn ${bin}: ${err.message}
|
|
28771
29125
|
`);
|
|
28772
29126
|
resolve5({ success: false, output: finalText, costUsd });
|
|
28773
29127
|
});
|
|
28774
29128
|
proc.on("close", (code) => {
|
|
29129
|
+
detach();
|
|
28775
29130
|
sink.flush();
|
|
28776
29131
|
resolve5({ success: code === 0, output: finalText, costUsd });
|
|
28777
29132
|
});
|
|
@@ -28842,6 +29197,7 @@ var require_CodexRunner = __commonJS({
|
|
|
28842
29197
|
var ndjson_1 = require_ndjson();
|
|
28843
29198
|
var models_1 = require_models();
|
|
28844
29199
|
var resolveCommand_1 = require_resolveCommand();
|
|
29200
|
+
var processTree_1 = require_processTree();
|
|
28845
29201
|
var CodexRunner2 = class {
|
|
28846
29202
|
opts;
|
|
28847
29203
|
/**
|
|
@@ -28878,14 +29234,17 @@ var require_CodexRunner = __commonJS({
|
|
|
28878
29234
|
this.opts.sandbox ?? "workspace-write",
|
|
28879
29235
|
...model ? ["--model", model] : [],
|
|
28880
29236
|
...this.opts.extraArgs ?? [],
|
|
29237
|
+
...ctx.extraArgs ?? [],
|
|
28881
29238
|
buildPrompt(ctx)
|
|
28882
29239
|
];
|
|
28883
29240
|
const cmd = (0, resolveCommand_1.resolveCommand)(bin);
|
|
28884
29241
|
const proc = (0, child_process_1.spawn)(cmd.command, [...cmd.args, ...args], {
|
|
28885
29242
|
cwd: ctx.workspaceRoot,
|
|
28886
29243
|
env: { ...process.env, ...ctx.env },
|
|
28887
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
29244
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
29245
|
+
...(0, processTree_1.processGroupSpawnOptions)()
|
|
28888
29246
|
});
|
|
29247
|
+
const detach = (0, processTree_1.stopOnAbort)(proc, ctx.signal);
|
|
28889
29248
|
let streamed = "";
|
|
28890
29249
|
let lastMessage = "";
|
|
28891
29250
|
let sawDelta = false;
|
|
@@ -28937,11 +29296,13 @@ var require_CodexRunner = __commonJS({
|
|
|
28937
29296
|
proc.stderr.on("data", (d) => ctx.onError(d.toString("utf8")));
|
|
28938
29297
|
return new Promise((resolve5) => {
|
|
28939
29298
|
proc.on("error", (err) => {
|
|
29299
|
+
detach();
|
|
28940
29300
|
ctx.onError(`Failed to spawn ${bin}: ${err.message}
|
|
28941
29301
|
`);
|
|
28942
29302
|
resolve5({ success: false, output: "", usage });
|
|
28943
29303
|
});
|
|
28944
29304
|
proc.on("close", (code) => {
|
|
29305
|
+
detach();
|
|
28945
29306
|
sink.flush();
|
|
28946
29307
|
resolve5({
|
|
28947
29308
|
success: code === 0,
|
|
@@ -29014,6 +29375,7 @@ var require_CopilotRunner = __commonJS({
|
|
|
29014
29375
|
var ndjson_1 = require_ndjson();
|
|
29015
29376
|
var models_1 = require_models();
|
|
29016
29377
|
var resolveCommand_1 = require_resolveCommand();
|
|
29378
|
+
var processTree_1 = require_processTree();
|
|
29017
29379
|
var GRAPH_SERVERS2 = ["ast-graph", "codegraph"];
|
|
29018
29380
|
var CopilotRunner2 = class {
|
|
29019
29381
|
opts;
|
|
@@ -29051,14 +29413,17 @@ var require_CopilotRunner = __commonJS({
|
|
|
29051
29413
|
...this.opts.keepBuiltinMcps ? [] : ["--disable-builtin-mcps"],
|
|
29052
29414
|
...graph ? ["--additional-mcp-config", copilotMcpConfig(graph)] : [],
|
|
29053
29415
|
...model ? ["--model", model] : [],
|
|
29054
|
-
...this.opts.extraArgs ?? []
|
|
29416
|
+
...this.opts.extraArgs ?? [],
|
|
29417
|
+
...ctx.extraArgs ?? []
|
|
29055
29418
|
];
|
|
29056
29419
|
const cmd = (0, resolveCommand_1.resolveCommand)(bin);
|
|
29057
29420
|
const proc = (0, child_process_1.spawn)(cmd.command, [...cmd.args, ...args], {
|
|
29058
29421
|
cwd: ctx.workspaceRoot,
|
|
29059
29422
|
env: { ...process.env, ...ctx.env },
|
|
29060
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
29423
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
29424
|
+
...(0, processTree_1.processGroupSpawnOptions)()
|
|
29061
29425
|
});
|
|
29426
|
+
const detach = (0, processTree_1.stopOnAbort)(proc, ctx.signal);
|
|
29062
29427
|
let streamed = "";
|
|
29063
29428
|
let lastMessage = "";
|
|
29064
29429
|
const deltaSeen = /* @__PURE__ */ new Set();
|
|
@@ -29120,11 +29485,13 @@ var require_CopilotRunner = __commonJS({
|
|
|
29120
29485
|
proc.stdin.end((0, CodexRunner_1.buildPrompt)(ctx));
|
|
29121
29486
|
return new Promise((resolve5) => {
|
|
29122
29487
|
proc.on("error", (err) => {
|
|
29488
|
+
detach();
|
|
29123
29489
|
ctx.onError(`Failed to spawn ${bin}: ${err.message}
|
|
29124
29490
|
`);
|
|
29125
29491
|
resolve5({ success: false, output: "" });
|
|
29126
29492
|
});
|
|
29127
29493
|
proc.on("close", (code) => {
|
|
29494
|
+
detach();
|
|
29128
29495
|
sink.flush();
|
|
29129
29496
|
resolve5({
|
|
29130
29497
|
success: code === 0,
|
|
@@ -30374,7 +30741,10 @@ var require_promptComposer = __commonJS({
|
|
|
30374
30741
|
const inlineInstructions = !!instructions && !harness.projectInstructions;
|
|
30375
30742
|
const language = artifactLanguage?.trim() || null;
|
|
30376
30743
|
const depth = (0, strictMode_1.strictModeSection)(input.strictMode === false ? false : true);
|
|
30377
|
-
|
|
30744
|
+
const history = input.runHistory ? `## Prior revisions
|
|
30745
|
+
|
|
30746
|
+
Earlier rejections and feedback for this step: \`${input.runHistory.file}\` \u2192 \`steps[${input.runHistory.stepIdx}].history\`. Do not bring back what they rejected.` : null;
|
|
30747
|
+
if (!inlinePersona && !inlineInstructions && !language && !depth && !history) {
|
|
30378
30748
|
return {
|
|
30379
30749
|
text: skills,
|
|
30380
30750
|
included: { persona: false, instructions: false, language: false, depth: false }
|
|
@@ -30399,6 +30769,9 @@ var require_promptComposer = __commonJS({
|
|
|
30399
30769
|
if (depth) {
|
|
30400
30770
|
parts.push(depth);
|
|
30401
30771
|
}
|
|
30772
|
+
if (history) {
|
|
30773
|
+
parts.push(history);
|
|
30774
|
+
}
|
|
30402
30775
|
const skillText = inlinePersona ? stripPersonaDirectives(skills) : skills;
|
|
30403
30776
|
parts.push(["## Phase Behavior", "", skillText.trim()].join("\n"));
|
|
30404
30777
|
return {
|
|
@@ -30750,6 +31123,235 @@ var require_commandBodyFreshness = __commonJS({
|
|
|
30750
31123
|
}
|
|
30751
31124
|
});
|
|
30752
31125
|
|
|
31126
|
+
// ../core/dist/runs/autopilotPreflight.js
|
|
31127
|
+
var require_autopilotPreflight = __commonJS({
|
|
31128
|
+
"../core/dist/runs/autopilotPreflight.js"(exports2) {
|
|
31129
|
+
"use strict";
|
|
31130
|
+
var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o, m, k, k2) {
|
|
31131
|
+
if (k2 === void 0) k2 = k;
|
|
31132
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
31133
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
31134
|
+
desc = { enumerable: true, get: function() {
|
|
31135
|
+
return m[k];
|
|
31136
|
+
} };
|
|
31137
|
+
}
|
|
31138
|
+
Object.defineProperty(o, k2, desc);
|
|
31139
|
+
} : function(o, m, k, k2) {
|
|
31140
|
+
if (k2 === void 0) k2 = k;
|
|
31141
|
+
o[k2] = m[k];
|
|
31142
|
+
});
|
|
31143
|
+
var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o, v) {
|
|
31144
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
31145
|
+
} : function(o, v) {
|
|
31146
|
+
o["default"] = v;
|
|
31147
|
+
});
|
|
31148
|
+
var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ function() {
|
|
31149
|
+
var ownKeys = function(o) {
|
|
31150
|
+
ownKeys = Object.getOwnPropertyNames || function(o2) {
|
|
31151
|
+
var ar = [];
|
|
31152
|
+
for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
|
|
31153
|
+
return ar;
|
|
31154
|
+
};
|
|
31155
|
+
return ownKeys(o);
|
|
31156
|
+
};
|
|
31157
|
+
return function(mod) {
|
|
31158
|
+
if (mod && mod.__esModule) return mod;
|
|
31159
|
+
var result = {};
|
|
31160
|
+
if (mod != null) {
|
|
31161
|
+
for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31162
|
+
}
|
|
31163
|
+
__setModuleDefault(result, mod);
|
|
31164
|
+
return result;
|
|
31165
|
+
};
|
|
31166
|
+
}();
|
|
31167
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
31168
|
+
exports2.AUTOPILOT_ENV = exports2.APPROVAL_GATE_SCRIPT = void 0;
|
|
31169
|
+
exports2.findApprovalGate = findApprovalGate2;
|
|
31170
|
+
exports2.autopilotPreflight = autopilotPreflight;
|
|
31171
|
+
exports2.hasEmptyCiChecks = hasEmptyCiChecks2;
|
|
31172
|
+
exports2.emptyCiChecksMessage = emptyCiChecksMessage2;
|
|
31173
|
+
var child_process_1 = require("child_process");
|
|
31174
|
+
var fs14 = __importStar(require("fs"));
|
|
31175
|
+
var os3 = __importStar(require("os"));
|
|
31176
|
+
var path17 = __importStar(require("path"));
|
|
31177
|
+
var claudeHome_1 = require_claudeHome();
|
|
31178
|
+
var EpicScaffold_1 = require_EpicScaffold();
|
|
31179
|
+
var WorkspaceSchema_1 = require_WorkspaceSchema();
|
|
31180
|
+
exports2.APPROVAL_GATE_SCRIPT = "aidlc-approval-gate";
|
|
31181
|
+
exports2.AUTOPILOT_ENV = "AIDLC_AUTOPILOT";
|
|
31182
|
+
var PROTECTED_BRANCHES = ["main", "master"];
|
|
31183
|
+
function findApprovalGate2(root, opts = {}) {
|
|
31184
|
+
const files = [
|
|
31185
|
+
path17.join(root, ".claude", "settings.json"),
|
|
31186
|
+
path17.join(root, ".claude", "settings.local.json"),
|
|
31187
|
+
path17.join(opts.userConfigDir ?? (0, claudeHome_1.claudeConfigDir)(), "settings.json")
|
|
31188
|
+
];
|
|
31189
|
+
let brokenReason = null;
|
|
31190
|
+
for (const file of files) {
|
|
31191
|
+
let settings = null;
|
|
31192
|
+
try {
|
|
31193
|
+
settings = JSON.parse(fs14.readFileSync(file, "utf8"));
|
|
31194
|
+
} catch {
|
|
31195
|
+
continue;
|
|
31196
|
+
}
|
|
31197
|
+
const groups = settings?.hooks?.PreToolUse;
|
|
31198
|
+
if (!Array.isArray(groups)) {
|
|
31199
|
+
continue;
|
|
31200
|
+
}
|
|
31201
|
+
for (const g of groups) {
|
|
31202
|
+
if (!Array.isArray(g?.hooks) || !matcherCoversBash(g.matcher)) {
|
|
31203
|
+
continue;
|
|
31204
|
+
}
|
|
31205
|
+
for (const h of g.hooks) {
|
|
31206
|
+
if (typeof h?.command !== "string" || !h.command.includes(exports2.APPROVAL_GATE_SCRIPT)) {
|
|
31207
|
+
continue;
|
|
31208
|
+
}
|
|
31209
|
+
const script = hookScriptPath(h.command, root);
|
|
31210
|
+
if (!script) {
|
|
31211
|
+
continue;
|
|
31212
|
+
}
|
|
31213
|
+
if (!fs14.existsSync(script)) {
|
|
31214
|
+
brokenReason = `${rel(root, file)} runs ${script}, which does not exist.`;
|
|
31215
|
+
continue;
|
|
31216
|
+
}
|
|
31217
|
+
if (runsScriptDirectly(h.command) && process.platform !== "win32" && !isExecutable(script)) {
|
|
31218
|
+
brokenReason = `${rel(root, script)} is registered in ${rel(root, file)} but is not executable (chmod +x it).`;
|
|
31219
|
+
continue;
|
|
31220
|
+
}
|
|
31221
|
+
return { found: true, settingsFile: file, script };
|
|
31222
|
+
}
|
|
31223
|
+
}
|
|
31224
|
+
}
|
|
31225
|
+
return {
|
|
31226
|
+
found: false,
|
|
31227
|
+
reason: brokenReason ?? 'no PreToolUse hook running .claude/hooks/aidlc-approval-gate.py on Bash in .claude/settings.json, .claude/settings.local.json or your user settings \u2014 see ONBOARDING.md, "Turn on the approval gate".'
|
|
31228
|
+
};
|
|
31229
|
+
}
|
|
31230
|
+
function autopilotPreflight(args) {
|
|
31231
|
+
const { root, state, config } = args;
|
|
31232
|
+
const problems = [];
|
|
31233
|
+
const git = (gitArgs) => {
|
|
31234
|
+
try {
|
|
31235
|
+
return (0, child_process_1.execFileSync)("git", gitArgs, {
|
|
31236
|
+
cwd: root,
|
|
31237
|
+
encoding: "utf8",
|
|
31238
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
31239
|
+
maxBuffer: 64 * 1024 * 1024
|
|
31240
|
+
});
|
|
31241
|
+
} catch {
|
|
31242
|
+
return null;
|
|
31243
|
+
}
|
|
31244
|
+
};
|
|
31245
|
+
if (git(["rev-parse", "--is-inside-work-tree"])?.trim() !== "true") {
|
|
31246
|
+
problems.push("This is not a git checkout. Autopilot works on a branch of its own, so it needs git.");
|
|
31247
|
+
} else {
|
|
31248
|
+
const branch = git(["symbolic-ref", "--short", "-q", "HEAD"])?.trim();
|
|
31249
|
+
const remoteDefault = git(["symbolic-ref", "--short", "-q", "refs/remotes/origin/HEAD"])?.trim().replace(/^origin\//, "");
|
|
31250
|
+
const protectedBranches = /* @__PURE__ */ new Set([...PROTECTED_BRANCHES, ...remoteDefault ? [remoteDefault] : []]);
|
|
31251
|
+
if (!branch) {
|
|
31252
|
+
problems.push("HEAD is detached. Check out a branch for this epic (git switch -c <branch>) so the agent's commits land on it.");
|
|
31253
|
+
} else if (protectedBranches.has(branch)) {
|
|
31254
|
+
problems.push(`You are on "${branch}". Autopilot does not commit to it \u2014 switch to a branch for this epic (git switch -c <branch>).`);
|
|
31255
|
+
}
|
|
31256
|
+
const skip = [
|
|
31257
|
+
toPosix(path17.relative(root, path17.join((0, EpicScaffold_1.epicsRoot)(root, config), state.runId))),
|
|
31258
|
+
".aidlc"
|
|
31259
|
+
];
|
|
31260
|
+
const dirty = dirtyPaths(git(["status", "--porcelain=v1", "-z", "--untracked-files=all"]) ?? "").filter((p) => !skip.some((s) => p === s || p.startsWith(`${s}/`)));
|
|
31261
|
+
if (dirty.length > 0) {
|
|
31262
|
+
const shown = dirty.slice(0, 5).join(", ") + (dirty.length > 5 ? `, and ${dirty.length - 5} more` : "");
|
|
31263
|
+
problems.push(`The working tree has uncommitted changes (${shown}). Commit or stash them first: the agent would build on them, and its own changes would be mixed in with them.`);
|
|
31264
|
+
}
|
|
31265
|
+
}
|
|
31266
|
+
const claudeSteps = new Set(state.steps.filter((s) => s.status !== "approved").map((s) => config.agents.find((a) => a.id === s.agent)).filter((a) => a?.runner === "default").map((a) => a.id));
|
|
31267
|
+
if (claudeSteps.size > 0) {
|
|
31268
|
+
const gate = findApprovalGate2(root, { userConfigDir: args.userConfigDir });
|
|
31269
|
+
if (!gate.found) {
|
|
31270
|
+
problems.push(`The approval gate is not on: ${gate.reason}`);
|
|
31271
|
+
}
|
|
31272
|
+
}
|
|
31273
|
+
args.pipeline.steps.forEach((s, i) => {
|
|
31274
|
+
if (state.steps[i]?.status === "approved") {
|
|
31275
|
+
return;
|
|
31276
|
+
}
|
|
31277
|
+
const norm = (0, WorkspaceSchema_1.normalizeStep)(s);
|
|
31278
|
+
const runner = norm.auto_review ? norm.auto_review_runner : void 0;
|
|
31279
|
+
if (runner && hasEmptyCiChecks2(root, runner)) {
|
|
31280
|
+
problems.push(emptyCiChecksMessage2(runner, norm.name ?? norm.agent));
|
|
31281
|
+
}
|
|
31282
|
+
});
|
|
31283
|
+
return problems;
|
|
31284
|
+
}
|
|
31285
|
+
var EMPTY_CHECKS = /\bCHECKS\s*=\s*\[\s*\]/;
|
|
31286
|
+
function hasEmptyCiChecks2(root, runner) {
|
|
31287
|
+
let text;
|
|
31288
|
+
try {
|
|
31289
|
+
text = fs14.readFileSync(path17.isAbsolute(runner) ? runner : path17.join(root, runner), "utf8");
|
|
31290
|
+
} catch {
|
|
31291
|
+
return false;
|
|
31292
|
+
}
|
|
31293
|
+
const code = text.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/.*$/gm, "");
|
|
31294
|
+
return EMPTY_CHECKS.test(code);
|
|
31295
|
+
}
|
|
31296
|
+
function emptyCiChecksMessage2(runner, step) {
|
|
31297
|
+
return `${runner} has no commands in CHECKS, so it passes whatever "${step}" builds. Add your lint, typecheck and test commands to it before leaving a run alone.`;
|
|
31298
|
+
}
|
|
31299
|
+
function dirtyPaths(out2) {
|
|
31300
|
+
const parts = out2.split("\0");
|
|
31301
|
+
const paths = [];
|
|
31302
|
+
for (let i = 0; i < parts.length; i++) {
|
|
31303
|
+
const entry = parts[i];
|
|
31304
|
+
if (entry.length < 4) {
|
|
31305
|
+
continue;
|
|
31306
|
+
}
|
|
31307
|
+
paths.push(entry.slice(3));
|
|
31308
|
+
if (entry[0] === "R" || entry[0] === "C") {
|
|
31309
|
+
i++;
|
|
31310
|
+
}
|
|
31311
|
+
}
|
|
31312
|
+
return paths;
|
|
31313
|
+
}
|
|
31314
|
+
function matcherCoversBash(matcher) {
|
|
31315
|
+
if (!matcher || matcher === "*") {
|
|
31316
|
+
return true;
|
|
31317
|
+
}
|
|
31318
|
+
try {
|
|
31319
|
+
return new RegExp(`^(?:${matcher})$`).test("Bash");
|
|
31320
|
+
} catch {
|
|
31321
|
+
return matcher.split("|").map((m) => m.trim()).includes("Bash");
|
|
31322
|
+
}
|
|
31323
|
+
}
|
|
31324
|
+
function hookScriptPath(command, root) {
|
|
31325
|
+
const expanded = command.replace(/\$\{?CLAUDE_PROJECT_DIR\}?/g, root).replace(/["']/g, "");
|
|
31326
|
+
const token = expanded.split(/\s+/).find((t) => t.includes(exports2.APPROVAL_GATE_SCRIPT));
|
|
31327
|
+
if (!token) {
|
|
31328
|
+
return null;
|
|
31329
|
+
}
|
|
31330
|
+
const p = token.startsWith("~/") ? path17.join(os3.homedir(), token.slice(2)) : token;
|
|
31331
|
+
return path17.resolve(root, p);
|
|
31332
|
+
}
|
|
31333
|
+
function runsScriptDirectly(command) {
|
|
31334
|
+
const first = command.replace(/["']/g, "").trim().split(/\s+/)[0] ?? "";
|
|
31335
|
+
return first.includes(exports2.APPROVAL_GATE_SCRIPT);
|
|
31336
|
+
}
|
|
31337
|
+
function isExecutable(file) {
|
|
31338
|
+
try {
|
|
31339
|
+
fs14.accessSync(file, fs14.constants.X_OK);
|
|
31340
|
+
return true;
|
|
31341
|
+
} catch {
|
|
31342
|
+
return false;
|
|
31343
|
+
}
|
|
31344
|
+
}
|
|
31345
|
+
function rel(root, p) {
|
|
31346
|
+
const r = path17.relative(root, p);
|
|
31347
|
+
return r.startsWith("..") ? p : toPosix(r);
|
|
31348
|
+
}
|
|
31349
|
+
function toPosix(p) {
|
|
31350
|
+
return p.split(path17.sep).join("/");
|
|
31351
|
+
}
|
|
31352
|
+
}
|
|
31353
|
+
});
|
|
31354
|
+
|
|
30753
31355
|
// ../core/dist/runs/GitRunStateStore.js
|
|
30754
31356
|
var require_GitRunStateStore = __commonJS({
|
|
30755
31357
|
"../core/dist/runs/GitRunStateStore.js"(exports2) {
|
|
@@ -31374,20 +31976,323 @@ Expected a JS/TS module at "${scriptPath}" with a default-exported function retu
|
|
|
31374
31976
|
at,
|
|
31375
31977
|
runner
|
|
31376
31978
|
};
|
|
31377
|
-
} finally {
|
|
31378
|
-
if (timer) {
|
|
31379
|
-
clearTimeout(timer);
|
|
31979
|
+
} finally {
|
|
31980
|
+
if (timer) {
|
|
31981
|
+
clearTimeout(timer);
|
|
31982
|
+
}
|
|
31983
|
+
}
|
|
31984
|
+
if (!raw || raw.decision !== "pass" && raw.decision !== "reject" || typeof raw.reason !== "string") {
|
|
31985
|
+
return {
|
|
31986
|
+
decision: "reject",
|
|
31987
|
+
reason: `Auto-reviewer returned malformed verdict: ${JSON.stringify(raw)}`,
|
|
31988
|
+
at,
|
|
31989
|
+
runner
|
|
31990
|
+
};
|
|
31991
|
+
}
|
|
31992
|
+
const verdict = { decision: raw.decision, reason: raw.reason, at, runner };
|
|
31993
|
+
const sendBackTo = raw.sendBackTo;
|
|
31994
|
+
if (sendBackTo !== void 0) {
|
|
31995
|
+
verdict.sendBackTo = sendBackTo === null || typeof sendBackTo === "string" || typeof sendBackTo === "number" ? sendBackTo : JSON.stringify(sendBackTo);
|
|
31996
|
+
}
|
|
31997
|
+
return verdict;
|
|
31998
|
+
}
|
|
31999
|
+
}
|
|
32000
|
+
});
|
|
32001
|
+
|
|
32002
|
+
// ../core/dist/runs/revisionFeedback.js
|
|
32003
|
+
var require_revisionFeedback = __commonJS({
|
|
32004
|
+
"../core/dist/runs/revisionFeedback.js"(exports2) {
|
|
32005
|
+
"use strict";
|
|
32006
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
32007
|
+
exports2.revisionFeedback = revisionFeedback;
|
|
32008
|
+
function revisionFeedback(state, stepIdx) {
|
|
32009
|
+
const step = state.steps[stepIdx];
|
|
32010
|
+
if (!step || step.revision <= 1) {
|
|
32011
|
+
return null;
|
|
32012
|
+
}
|
|
32013
|
+
const history = step.history ?? [];
|
|
32014
|
+
const prev = step.revision - 1;
|
|
32015
|
+
const reject = findLast(history, (h) => h.kind === "reject" && h.revision === prev && h.sentBackToIdx === stepIdx);
|
|
32016
|
+
const reason = reject?.kind === "reject" ? reject.reason?.trim() : void 0;
|
|
32017
|
+
const carried = findLast(history, (h) => h.kind === "rerun" && h.revision === prev);
|
|
32018
|
+
const fbRaw = step.feedback?.trim();
|
|
32019
|
+
const fb = fbRaw && !(carried?.kind === "rerun" && carried.feedback?.trim() === fbRaw) ? fbRaw : void 0;
|
|
32020
|
+
const lines = [];
|
|
32021
|
+
if (reason && !fb?.includes(reason)) {
|
|
32022
|
+
lines.push(`Rejected at step ${stepIdx + 1} (${step.agent}): ${reason}`);
|
|
32023
|
+
}
|
|
32024
|
+
if (fb && !reason?.includes(fb)) {
|
|
32025
|
+
lines.push(fb);
|
|
32026
|
+
}
|
|
32027
|
+
if (lines.length === 0) {
|
|
32028
|
+
return null;
|
|
32029
|
+
}
|
|
32030
|
+
return [`Revision ${step.revision}. Address before anything else:`, ...lines.map((l) => `- ${l}`)].join("\n");
|
|
32031
|
+
}
|
|
32032
|
+
function findLast(entries, pred) {
|
|
32033
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
32034
|
+
if (pred(entries[i])) {
|
|
32035
|
+
return entries[i];
|
|
32036
|
+
}
|
|
32037
|
+
}
|
|
32038
|
+
return void 0;
|
|
32039
|
+
}
|
|
32040
|
+
}
|
|
32041
|
+
});
|
|
32042
|
+
|
|
32043
|
+
// ../core/dist/runs/runLock.js
|
|
32044
|
+
var require_runLock = __commonJS({
|
|
32045
|
+
"../core/dist/runs/runLock.js"(exports2) {
|
|
32046
|
+
"use strict";
|
|
32047
|
+
var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o, m, k, k2) {
|
|
32048
|
+
if (k2 === void 0) k2 = k;
|
|
32049
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
32050
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
32051
|
+
desc = { enumerable: true, get: function() {
|
|
32052
|
+
return m[k];
|
|
32053
|
+
} };
|
|
32054
|
+
}
|
|
32055
|
+
Object.defineProperty(o, k2, desc);
|
|
32056
|
+
} : function(o, m, k, k2) {
|
|
32057
|
+
if (k2 === void 0) k2 = k;
|
|
32058
|
+
o[k2] = m[k];
|
|
32059
|
+
});
|
|
32060
|
+
var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o, v) {
|
|
32061
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
32062
|
+
} : function(o, v) {
|
|
32063
|
+
o["default"] = v;
|
|
32064
|
+
});
|
|
32065
|
+
var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ function() {
|
|
32066
|
+
var ownKeys = function(o) {
|
|
32067
|
+
ownKeys = Object.getOwnPropertyNames || function(o2) {
|
|
32068
|
+
var ar = [];
|
|
32069
|
+
for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
|
|
32070
|
+
return ar;
|
|
32071
|
+
};
|
|
32072
|
+
return ownKeys(o);
|
|
32073
|
+
};
|
|
32074
|
+
return function(mod) {
|
|
32075
|
+
if (mod && mod.__esModule) return mod;
|
|
32076
|
+
var result = {};
|
|
32077
|
+
if (mod != null) {
|
|
32078
|
+
for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32079
|
+
}
|
|
32080
|
+
__setModuleDefault(result, mod);
|
|
32081
|
+
return result;
|
|
32082
|
+
};
|
|
32083
|
+
}();
|
|
32084
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
32085
|
+
exports2.runLockFile = runLockFile;
|
|
32086
|
+
exports2.acquireRunLock = acquireRunLock;
|
|
32087
|
+
var fs14 = __importStar(require("fs"));
|
|
32088
|
+
var path17 = __importStar(require("path"));
|
|
32089
|
+
var RunStateStore_1 = require_RunStateStore();
|
|
32090
|
+
function runLockFile(root, runId) {
|
|
32091
|
+
return RunStateStore_1.RunStateStore.file(root, runId).replace(/\.json$/, ".lock");
|
|
32092
|
+
}
|
|
32093
|
+
function acquireRunLock(root, runId) {
|
|
32094
|
+
const file = runLockFile(root, runId);
|
|
32095
|
+
fs14.mkdirSync(path17.dirname(file), { recursive: true });
|
|
32096
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
32097
|
+
try {
|
|
32098
|
+
fs14.writeFileSync(file, JSON.stringify({ pid: process.pid, at: (/* @__PURE__ */ new Date()).toISOString() }), { flag: "wx" });
|
|
32099
|
+
return {
|
|
32100
|
+
release: () => {
|
|
32101
|
+
if (lockPid(file) === process.pid) {
|
|
32102
|
+
fs14.rmSync(file, { force: true });
|
|
32103
|
+
}
|
|
32104
|
+
}
|
|
32105
|
+
};
|
|
32106
|
+
} catch (err) {
|
|
32107
|
+
if (err.code !== "EEXIST") {
|
|
32108
|
+
throw err;
|
|
32109
|
+
}
|
|
32110
|
+
}
|
|
32111
|
+
const pid = lockPid(file);
|
|
32112
|
+
if (pid !== null && isAlive(pid)) {
|
|
32113
|
+
return { heldBy: pid };
|
|
32114
|
+
}
|
|
32115
|
+
fs14.rmSync(file, { force: true });
|
|
32116
|
+
}
|
|
32117
|
+
return { heldBy: lockPid(file) ?? -1 };
|
|
32118
|
+
}
|
|
32119
|
+
function lockPid(file) {
|
|
32120
|
+
try {
|
|
32121
|
+
const pid = JSON.parse(fs14.readFileSync(file, "utf8")).pid;
|
|
32122
|
+
return typeof pid === "number" && Number.isInteger(pid) && pid > 0 ? pid : null;
|
|
32123
|
+
} catch {
|
|
32124
|
+
return null;
|
|
32125
|
+
}
|
|
32126
|
+
}
|
|
32127
|
+
function isAlive(pid) {
|
|
32128
|
+
try {
|
|
32129
|
+
process.kill(pid, 0);
|
|
32130
|
+
return true;
|
|
32131
|
+
} catch (err) {
|
|
32132
|
+
return err.code === "EPERM";
|
|
32133
|
+
}
|
|
32134
|
+
}
|
|
32135
|
+
}
|
|
32136
|
+
});
|
|
32137
|
+
|
|
32138
|
+
// ../core/dist/runs/codeFingerprint.js
|
|
32139
|
+
var require_codeFingerprint = __commonJS({
|
|
32140
|
+
"../core/dist/runs/codeFingerprint.js"(exports2) {
|
|
32141
|
+
"use strict";
|
|
32142
|
+
var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o, m, k, k2) {
|
|
32143
|
+
if (k2 === void 0) k2 = k;
|
|
32144
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
32145
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
32146
|
+
desc = { enumerable: true, get: function() {
|
|
32147
|
+
return m[k];
|
|
32148
|
+
} };
|
|
32149
|
+
}
|
|
32150
|
+
Object.defineProperty(o, k2, desc);
|
|
32151
|
+
} : function(o, m, k, k2) {
|
|
32152
|
+
if (k2 === void 0) k2 = k;
|
|
32153
|
+
o[k2] = m[k];
|
|
32154
|
+
});
|
|
32155
|
+
var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o, v) {
|
|
32156
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
32157
|
+
} : function(o, v) {
|
|
32158
|
+
o["default"] = v;
|
|
32159
|
+
});
|
|
32160
|
+
var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ function() {
|
|
32161
|
+
var ownKeys = function(o) {
|
|
32162
|
+
ownKeys = Object.getOwnPropertyNames || function(o2) {
|
|
32163
|
+
var ar = [];
|
|
32164
|
+
for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
|
|
32165
|
+
return ar;
|
|
32166
|
+
};
|
|
32167
|
+
return ownKeys(o);
|
|
32168
|
+
};
|
|
32169
|
+
return function(mod) {
|
|
32170
|
+
if (mod && mod.__esModule) return mod;
|
|
32171
|
+
var result = {};
|
|
32172
|
+
if (mod != null) {
|
|
32173
|
+
for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32174
|
+
}
|
|
32175
|
+
__setModuleDefault(result, mod);
|
|
32176
|
+
return result;
|
|
32177
|
+
};
|
|
32178
|
+
}();
|
|
32179
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
32180
|
+
exports2.codeFingerprint = codeFingerprint;
|
|
32181
|
+
var child_process_1 = require("child_process");
|
|
32182
|
+
var fs14 = __importStar(require("fs"));
|
|
32183
|
+
var os3 = __importStar(require("os"));
|
|
32184
|
+
var path17 = __importStar(require("path"));
|
|
32185
|
+
function codeFingerprint(root, exclude) {
|
|
32186
|
+
const git = (args, env) => (0, child_process_1.execFileSync)("git", args, {
|
|
32187
|
+
cwd: root,
|
|
32188
|
+
encoding: "utf8",
|
|
32189
|
+
env: env ? { ...process.env, ...env } : process.env,
|
|
32190
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
32191
|
+
maxBuffer: 64 * 1024 * 1024
|
|
32192
|
+
}).trim();
|
|
32193
|
+
let realIndex;
|
|
32194
|
+
try {
|
|
32195
|
+
realIndex = path17.resolve(root, git(["rev-parse", "--git-path", "index"]));
|
|
32196
|
+
} catch {
|
|
32197
|
+
return null;
|
|
32198
|
+
}
|
|
32199
|
+
const dir = fs14.mkdtempSync(path17.join(os3.tmpdir(), "aidlc-fp-"));
|
|
32200
|
+
const index = path17.join(dir, "index");
|
|
32201
|
+
try {
|
|
32202
|
+
if (fs14.existsSync(realIndex)) {
|
|
32203
|
+
fs14.copyFileSync(realIndex, index);
|
|
32204
|
+
}
|
|
32205
|
+
const env = { GIT_INDEX_FILE: index };
|
|
32206
|
+
git(["add", "-A", "--", "."], env);
|
|
32207
|
+
const skip = exclude.filter((p) => p && !p.startsWith(".."));
|
|
32208
|
+
if (skip.length > 0) {
|
|
32209
|
+
git(["rm", "-r", "-q", "--cached", "--ignore-unmatch", "--", ...skip], env);
|
|
32210
|
+
}
|
|
32211
|
+
return git(["write-tree"], env);
|
|
32212
|
+
} catch {
|
|
32213
|
+
return null;
|
|
32214
|
+
} finally {
|
|
32215
|
+
fs14.rmSync(dir, { recursive: true, force: true });
|
|
32216
|
+
}
|
|
32217
|
+
}
|
|
32218
|
+
}
|
|
32219
|
+
});
|
|
32220
|
+
|
|
32221
|
+
// ../core/dist/runs/batchStatus.js
|
|
32222
|
+
var require_batchStatus = __commonJS({
|
|
32223
|
+
"../core/dist/runs/batchStatus.js"(exports2) {
|
|
32224
|
+
"use strict";
|
|
32225
|
+
var __createBinding = exports2 && exports2.__createBinding || (Object.create ? function(o, m, k, k2) {
|
|
32226
|
+
if (k2 === void 0) k2 = k;
|
|
32227
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
32228
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
32229
|
+
desc = { enumerable: true, get: function() {
|
|
32230
|
+
return m[k];
|
|
32231
|
+
} };
|
|
32232
|
+
}
|
|
32233
|
+
Object.defineProperty(o, k2, desc);
|
|
32234
|
+
} : function(o, m, k, k2) {
|
|
32235
|
+
if (k2 === void 0) k2 = k;
|
|
32236
|
+
o[k2] = m[k];
|
|
32237
|
+
});
|
|
32238
|
+
var __setModuleDefault = exports2 && exports2.__setModuleDefault || (Object.create ? function(o, v) {
|
|
32239
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
32240
|
+
} : function(o, v) {
|
|
32241
|
+
o["default"] = v;
|
|
32242
|
+
});
|
|
32243
|
+
var __importStar = exports2 && exports2.__importStar || /* @__PURE__ */ function() {
|
|
32244
|
+
var ownKeys = function(o) {
|
|
32245
|
+
ownKeys = Object.getOwnPropertyNames || function(o2) {
|
|
32246
|
+
var ar = [];
|
|
32247
|
+
for (var k in o2) if (Object.prototype.hasOwnProperty.call(o2, k)) ar[ar.length] = k;
|
|
32248
|
+
return ar;
|
|
32249
|
+
};
|
|
32250
|
+
return ownKeys(o);
|
|
32251
|
+
};
|
|
32252
|
+
return function(mod) {
|
|
32253
|
+
if (mod && mod.__esModule) return mod;
|
|
32254
|
+
var result = {};
|
|
32255
|
+
if (mod != null) {
|
|
32256
|
+
for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32257
|
+
}
|
|
32258
|
+
__setModuleDefault(result, mod);
|
|
32259
|
+
return result;
|
|
32260
|
+
};
|
|
32261
|
+
}();
|
|
32262
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
32263
|
+
exports2.readBatchStatus = readBatchStatus;
|
|
32264
|
+
exports2.readBatchStatusFile = readBatchStatusFile;
|
|
32265
|
+
var fs14 = __importStar(require("fs"));
|
|
32266
|
+
var path17 = __importStar(require("path"));
|
|
32267
|
+
var LINE = /^[\s>#*_-]*status[\s*_]*:[\s*_`]*([a-z]+)[*_`]*(.*)$/i;
|
|
32268
|
+
var TAIL = /^\s*(?:$|[—–-]\s|[(.,;])/;
|
|
32269
|
+
function readBatchStatus(text, file = "the report") {
|
|
32270
|
+
let last = null;
|
|
32271
|
+
for (const line of text.split(/\r?\n/)) {
|
|
32272
|
+
const m = LINE.exec(line);
|
|
32273
|
+
if (m) {
|
|
32274
|
+
last = { word: m[1].toLowerCase(), tail: m[2] };
|
|
31380
32275
|
}
|
|
31381
32276
|
}
|
|
31382
|
-
if (!
|
|
31383
|
-
return {
|
|
31384
|
-
|
|
31385
|
-
|
|
31386
|
-
|
|
31387
|
-
|
|
31388
|
-
|
|
32277
|
+
if (!last) {
|
|
32278
|
+
return { error: `${file} has no \`Status: continue\` or \`Status: done\` line.` };
|
|
32279
|
+
}
|
|
32280
|
+
if ((last.word === "continue" || last.word === "done") && TAIL.test(last.tail)) {
|
|
32281
|
+
return { status: last.word };
|
|
32282
|
+
}
|
|
32283
|
+
return {
|
|
32284
|
+
error: `The last Status line in ${file} reads "${last.word}${last.tail}", not \`Status: continue\` or \`Status: done\`.`
|
|
32285
|
+
};
|
|
32286
|
+
}
|
|
32287
|
+
function readBatchStatusFile(root, rel) {
|
|
32288
|
+
const abs = path17.isAbsolute(rel) ? rel : path17.join(root, rel);
|
|
32289
|
+
let text;
|
|
32290
|
+
try {
|
|
32291
|
+
text = fs14.readFileSync(abs, "utf8");
|
|
32292
|
+
} catch {
|
|
32293
|
+
return { error: `${rel} does not exist, so the batch did not say whether it is done.` };
|
|
31389
32294
|
}
|
|
31390
|
-
return
|
|
32295
|
+
return readBatchStatus(text, rel);
|
|
31391
32296
|
}
|
|
31392
32297
|
}
|
|
31393
32298
|
});
|
|
@@ -31445,9 +32350,16 @@ var require_execEngine = __commonJS({
|
|
|
31445
32350
|
var runProgress_1 = require_runProgress();
|
|
31446
32351
|
var budget_1 = require_budget();
|
|
31447
32352
|
var producesSnapshot_1 = require_producesSnapshot();
|
|
32353
|
+
var revisionFeedback_1 = require_revisionFeedback();
|
|
32354
|
+
var runLock_1 = require_runLock();
|
|
32355
|
+
var codeFingerprint_1 = require_codeFingerprint();
|
|
32356
|
+
var batchStatus_1 = require_batchStatus();
|
|
32357
|
+
var autopilotPreflight_1 = require_autopilotPreflight();
|
|
32358
|
+
var processTree_1 = require_processTree();
|
|
31448
32359
|
var pricing_1 = require_pricing();
|
|
31449
32360
|
var models_1 = require_models();
|
|
31450
32361
|
var WorkspaceSchema_1 = require_WorkspaceSchema();
|
|
32362
|
+
var RunState_1 = require_RunState();
|
|
31451
32363
|
var artifactLanguage_1 = require_artifactLanguage();
|
|
31452
32364
|
var strictMode_1 = require_strictMode();
|
|
31453
32365
|
var inheritedContext_1 = require_inheritedContext();
|
|
@@ -31463,6 +32375,21 @@ var require_execEngine = __commonJS({
|
|
|
31463
32375
|
}
|
|
31464
32376
|
}
|
|
31465
32377
|
async function runExecLoop2(root, runId, opts, hooks = {}) {
|
|
32378
|
+
if (opts.dryRun) {
|
|
32379
|
+
return execLoop2(root, runId, opts, hooks);
|
|
32380
|
+
}
|
|
32381
|
+
const lock = (0, runLock_1.acquireRunLock)(root, runId);
|
|
32382
|
+
if ("heldBy" in lock) {
|
|
32383
|
+
hooks.onRunFailed?.(`Run "${runId}" is already being executed (pid ${lock.heldBy}). Stop that one first, or wait for it to finish.`);
|
|
32384
|
+
return { kind: "error" };
|
|
32385
|
+
}
|
|
32386
|
+
try {
|
|
32387
|
+
return await execLoop2(root, runId, opts, hooks);
|
|
32388
|
+
} finally {
|
|
32389
|
+
lock.release();
|
|
32390
|
+
}
|
|
32391
|
+
}
|
|
32392
|
+
async function execLoop2(root, runId, opts, hooks) {
|
|
31466
32393
|
const untilIdx = opts.untilIdx ?? -1;
|
|
31467
32394
|
const initialState = RunStateStore_1.RunStateStore.load(root, runId);
|
|
31468
32395
|
if (!initialState) {
|
|
@@ -31475,8 +32402,23 @@ var require_execEngine = __commonJS({
|
|
|
31475
32402
|
return { kind: "error" };
|
|
31476
32403
|
}
|
|
31477
32404
|
const budget = initialPipeline.budget;
|
|
32405
|
+
const batchesRun = /* @__PURE__ */ new Map();
|
|
32406
|
+
if (initialPipeline.autopilot && !opts.dryRun) {
|
|
32407
|
+
let problems;
|
|
32408
|
+
try {
|
|
32409
|
+
const ws = WorkspaceLoader_1.WorkspaceLoader.load(root);
|
|
32410
|
+
problems = (0, autopilotPreflight_1.autopilotPreflight)({ root, state: initialState, pipeline: initialPipeline, config: ws.config });
|
|
32411
|
+
} catch (err) {
|
|
32412
|
+
problems = [`Could not check the workspace: ${errMsg(err)}`];
|
|
32413
|
+
}
|
|
32414
|
+
if (problems.length > 0) {
|
|
32415
|
+
hooks.onRunFailed?.(`Pipeline "${initialPipeline.id}" is an autopilot pipeline, and it is not safe to leave this run alone yet:
|
|
32416
|
+
` + problems.map((p) => ` - ${p}`).join("\n"));
|
|
32417
|
+
return { kind: "error" };
|
|
32418
|
+
}
|
|
32419
|
+
}
|
|
31478
32420
|
while (true) {
|
|
31479
|
-
if (opts.shouldCancel?.()) {
|
|
32421
|
+
if (opts.shouldCancel?.() || opts.signal?.aborted) {
|
|
31480
32422
|
hooks.onCancelled?.();
|
|
31481
32423
|
return { kind: "cancelled" };
|
|
31482
32424
|
}
|
|
@@ -31542,47 +32484,56 @@ var require_execEngine = __commonJS({
|
|
|
31542
32484
|
hooks.onRunFailed?.(`Unexpected step status "${step.status}" \u2014 cannot exec.`);
|
|
31543
32485
|
return { kind: "error" };
|
|
31544
32486
|
}
|
|
31545
|
-
const
|
|
31546
|
-
if (
|
|
32487
|
+
const ran = await execStep(root, state, runId, opts, hooks);
|
|
32488
|
+
if (ran === "failed") {
|
|
31547
32489
|
return { kind: "error" };
|
|
31548
32490
|
}
|
|
31549
|
-
if (
|
|
31550
|
-
return { kind: "
|
|
32491
|
+
if (ran === "stalled") {
|
|
32492
|
+
return { kind: "stalled" };
|
|
32493
|
+
}
|
|
32494
|
+
if (ran === "stopped") {
|
|
32495
|
+
return { kind: "cancelled" };
|
|
31551
32496
|
}
|
|
31552
|
-
if (
|
|
32497
|
+
if (ran === "batch") {
|
|
32498
|
+
const overBudget2 = checkRunBudget(root, runId, state.currentStepIdx, budget, hooks);
|
|
32499
|
+
if (overBudget2) {
|
|
32500
|
+
return overBudget2;
|
|
32501
|
+
}
|
|
32502
|
+
const idx = state.currentStepIdx;
|
|
32503
|
+
const cfg = initialPipeline.steps[idx] ? (0, WorkspaceSchema_1.normalizeStep)(initialPipeline.steps[idx]).batches : void 0;
|
|
32504
|
+
const key = `${idx}:${step.revision}`;
|
|
32505
|
+
const n = (batchesRun.get(key) ?? 0) + 1;
|
|
32506
|
+
batchesRun.set(key, n);
|
|
31553
32507
|
const after = RunStateStore_1.RunStateStore.load(root, runId);
|
|
31554
|
-
const
|
|
31555
|
-
|
|
31556
|
-
|
|
31557
|
-
|
|
31558
|
-
|
|
31559
|
-
|
|
31560
|
-
}) : [];
|
|
31561
|
-
const lastStepCost = after?.steps[state.currentStepIdx]?.costUsd;
|
|
31562
|
-
const verdict = (0, budget_1.checkBudget)({ stepCosts, stepAccounting, budget, lastStepCost });
|
|
31563
|
-
if (!verdict.ok) {
|
|
31564
|
-
hooks.onBudget?.({
|
|
31565
|
-
spent: verdict.spent,
|
|
31566
|
-
limit: verdict.limit,
|
|
31567
|
-
ok: false,
|
|
31568
|
-
exceeded: verdict.exceeded,
|
|
31569
|
-
onExceed: budget.on_exceed,
|
|
32508
|
+
const batchNo = after ? batchesOf(after.steps[idx]).length : n;
|
|
32509
|
+
if (cfg && n >= cfg.max) {
|
|
32510
|
+
hooks.onStalled?.({
|
|
32511
|
+
stepIdx: idx,
|
|
32512
|
+
agent: step.agent,
|
|
32513
|
+
revision: step.revision,
|
|
31570
32514
|
runId,
|
|
31571
|
-
|
|
31572
|
-
estimated: verdict.estimated,
|
|
31573
|
-
blindSteps: verdict.blindSteps
|
|
32515
|
+
reason: `"${step.agent}" ran ${n} batch${n === 1 ? "" : "es"} (\`max_batches: ${cfg.max}\`) and still says \`Status: continue\`. Read its progress before letting it carry on: running exec again allows ${cfg.max} more.`
|
|
31574
32516
|
});
|
|
31575
|
-
return
|
|
31576
|
-
}
|
|
31577
|
-
|
|
31578
|
-
|
|
31579
|
-
|
|
31580
|
-
|
|
31581
|
-
|
|
31582
|
-
|
|
31583
|
-
|
|
31584
|
-
|
|
31585
|
-
|
|
32517
|
+
return { kind: "stalled" };
|
|
32518
|
+
}
|
|
32519
|
+
if (cfg?.pause) {
|
|
32520
|
+
hooks.onBatchPause?.({
|
|
32521
|
+
stepIdx: idx,
|
|
32522
|
+
agent: step.agent,
|
|
32523
|
+
batch: batchNo,
|
|
32524
|
+
runId,
|
|
32525
|
+
report: batchReport(initialPipeline, after ?? state, idx) ?? ""
|
|
32526
|
+
});
|
|
32527
|
+
return { kind: "batch_pause" };
|
|
32528
|
+
}
|
|
32529
|
+
continue;
|
|
32530
|
+
}
|
|
32531
|
+
if (opts.dryRun) {
|
|
32532
|
+
return { kind: "dry_run" };
|
|
32533
|
+
}
|
|
32534
|
+
const overBudget = checkRunBudget(root, runId, state.currentStepIdx, budget, hooks);
|
|
32535
|
+
if (overBudget) {
|
|
32536
|
+
return overBudget;
|
|
31586
32537
|
}
|
|
31587
32538
|
if (untilIdx >= 0 && state.currentStepIdx >= untilIdx) {
|
|
31588
32539
|
hooks.onUntilStop?.({ untilIdx });
|
|
@@ -31590,10 +32541,49 @@ var require_execEngine = __commonJS({
|
|
|
31590
32541
|
}
|
|
31591
32542
|
}
|
|
31592
32543
|
}
|
|
32544
|
+
function checkRunBudget(root, runId, stepIdx, budget, hooks) {
|
|
32545
|
+
if (!budget) {
|
|
32546
|
+
return null;
|
|
32547
|
+
}
|
|
32548
|
+
const after = RunStateStore_1.RunStateStore.load(root, runId);
|
|
32549
|
+
const stepCosts = after ? after.steps.map((s) => s.costUsd) : [];
|
|
32550
|
+
const stepAccounting = after ? after.steps.map((s) => {
|
|
32551
|
+
if (typeof s.costUsd === "number") {
|
|
32552
|
+
return s.costEstimated ? "estimated" : "measured";
|
|
32553
|
+
}
|
|
32554
|
+
return s.startedAt ? "blind" : void 0;
|
|
32555
|
+
}) : [];
|
|
32556
|
+
const lastStepCost = after?.steps[stepIdx]?.costUsd;
|
|
32557
|
+
const verdict = (0, budget_1.checkBudget)({ stepCosts, stepAccounting, budget, lastStepCost });
|
|
32558
|
+
if (!verdict.ok) {
|
|
32559
|
+
hooks.onBudget?.({
|
|
32560
|
+
spent: verdict.spent,
|
|
32561
|
+
limit: verdict.limit,
|
|
32562
|
+
ok: false,
|
|
32563
|
+
exceeded: verdict.exceeded,
|
|
32564
|
+
onExceed: budget.on_exceed,
|
|
32565
|
+
runId,
|
|
32566
|
+
measured: verdict.measured,
|
|
32567
|
+
estimated: verdict.estimated,
|
|
32568
|
+
blindSteps: verdict.blindSteps
|
|
32569
|
+
});
|
|
32570
|
+
return budget.on_exceed === "fail" ? { kind: "error" } : { kind: "budget_pause" };
|
|
32571
|
+
}
|
|
32572
|
+
hooks.onBudget?.({
|
|
32573
|
+
spent: verdict.spent,
|
|
32574
|
+
limit: budget.max_usd,
|
|
32575
|
+
ok: true,
|
|
32576
|
+
runId,
|
|
32577
|
+
measured: verdict.measured,
|
|
32578
|
+
estimated: verdict.estimated,
|
|
32579
|
+
blindSteps: verdict.blindSteps
|
|
32580
|
+
});
|
|
32581
|
+
return null;
|
|
32582
|
+
}
|
|
31593
32583
|
function loadSkills(ws, skillIds) {
|
|
31594
32584
|
return skillIds.map((id) => ws.skills.load(id)).join("\n\n---\n\n");
|
|
31595
32585
|
}
|
|
31596
|
-
function buildStepPrompt(ws, agent, skillIds, runner, root, epicId) {
|
|
32586
|
+
function buildStepPrompt(ws, agent, skillIds, runner, root, epicId, stepRec, stepIdx) {
|
|
31597
32587
|
const harness = (0, types_1.harnessCapabilities)(runner);
|
|
31598
32588
|
return (0, promptComposer_1.composeAgentPrompt)({
|
|
31599
32589
|
skills: loadSkills(ws, skillIds),
|
|
@@ -31603,7 +32593,8 @@ var require_execEngine = __commonJS({
|
|
|
31603
32593
|
artifactLanguage: (0, artifactLanguage_1.resolveArtifactLanguage)(ws.config),
|
|
31604
32594
|
// Per epic, not per workspace: how deep a phase goes is a property of the
|
|
31605
32595
|
// work item. An epic that never set it reads as strict.
|
|
31606
|
-
strictMode: (0, strictMode_1.resolveEpicStrictMode)((0, EpicScaffold_1.epicsRoot)(root, ws.config), epicId)
|
|
32596
|
+
strictMode: (0, strictMode_1.resolveEpicStrictMode)((0, EpicScaffold_1.epicsRoot)(root, ws.config), epicId),
|
|
32597
|
+
runHistory: stepRec.revision > 1 ? { file: path17.relative(root, RunStateStore_1.RunStateStore.file(root, epicId)).split(path17.sep).join("/"), stepIdx } : null
|
|
31607
32598
|
});
|
|
31608
32599
|
}
|
|
31609
32600
|
async function execStep(root, state, runId, opts, hooks) {
|
|
@@ -31615,17 +32606,17 @@ var require_execEngine = __commonJS({
|
|
|
31615
32606
|
ws = WorkspaceLoader_1.WorkspaceLoader.load(root);
|
|
31616
32607
|
} catch (err) {
|
|
31617
32608
|
hooks.onStepFailed?.({ stepIdx, agent: agentId, message: `Failed to load workspace: ${errMsg(err)}` });
|
|
31618
|
-
return
|
|
32609
|
+
return "failed";
|
|
31619
32610
|
}
|
|
31620
32611
|
const pipeline = ws.config.pipelines.find((p) => p.id === state.pipelineId);
|
|
31621
32612
|
if (!pipeline) {
|
|
31622
32613
|
hooks.onStepFailed?.({ stepIdx, agent: agentId, message: `Pipeline "${state.pipelineId}" not found in workspace.yaml.` });
|
|
31623
|
-
return
|
|
32614
|
+
return "failed";
|
|
31624
32615
|
}
|
|
31625
32616
|
const agent = ws.config.agents.find((a) => a.id === agentId);
|
|
31626
32617
|
if (!agent) {
|
|
31627
32618
|
hooks.onStepFailed?.({ stepIdx, agent: agentId, message: `Agent "${agentId}" not found in workspace.yaml.` });
|
|
31628
|
-
return
|
|
32619
|
+
return "failed";
|
|
31629
32620
|
}
|
|
31630
32621
|
const stepCfg = pipeline.steps[stepIdx];
|
|
31631
32622
|
const norm = stepCfg ? (0, WorkspaceSchema_1.normalizeStep)(stepCfg) : void 0;
|
|
@@ -31640,22 +32631,38 @@ var require_execEngine = __commonJS({
|
|
|
31640
32631
|
runner = ws.runners.resolve(agent);
|
|
31641
32632
|
} catch (err) {
|
|
31642
32633
|
hooks.onStepFailed?.({ stepIdx, agent: agentId, message: `Failed to resolve runner for agent "${agentId}": ${errMsg(err)}` });
|
|
31643
|
-
return
|
|
32634
|
+
return "failed";
|
|
31644
32635
|
}
|
|
31645
32636
|
try {
|
|
31646
|
-
prompt2 = buildStepPrompt(ws, agent, skillIds, runner, root, state.runId);
|
|
32637
|
+
prompt2 = buildStepPrompt(ws, agent, skillIds, runner, root, state.runId, stepRec, stepIdx);
|
|
31647
32638
|
} catch (err) {
|
|
31648
32639
|
hooks.onStepFailed?.({ stepIdx, agent: agentId, message: `Failed to load skills for agent "${agentId}": ${errMsg(err)}` });
|
|
31649
|
-
return
|
|
32640
|
+
return "failed";
|
|
31650
32641
|
}
|
|
31651
32642
|
const skillText = prompt2.text;
|
|
31652
32643
|
const env = ws.envResolver.resolveLayered(ws.config.environment ?? {}, agent.env ?? {});
|
|
32644
|
+
if (pipeline.autopilot) {
|
|
32645
|
+
env[autopilotPreflight_1.AUTOPILOT_ENV] = "1";
|
|
32646
|
+
}
|
|
31653
32647
|
const contextStr = Object.entries(state.context).map(([k, v]) => `${k}=${v}`).join(" ");
|
|
31654
32648
|
const epicRoot = path17.relative(root, (0, EpicScaffold_1.epicsRoot)(root, ws.config)).split(path17.sep).join("/");
|
|
31655
32649
|
const inherited = state.context.from_epic ? `
|
|
31656
32650
|
|
|
31657
32651
|
About these inputs: ${(0, inheritedContext_1.inheritedContextNote)(epicRoot)}` : "";
|
|
31658
|
-
const
|
|
32652
|
+
const baseMessage = opts.message ?? (contextStr ? contextStr + inherited : `Execute step: ${agentId}`);
|
|
32653
|
+
const feedback = (0, revisionFeedback_1.revisionFeedback)(state, stepIdx);
|
|
32654
|
+
const report = norm?.batches ? batchReport(pipeline, state, stepIdx) : null;
|
|
32655
|
+
if (norm?.batches && !report) {
|
|
32656
|
+
hooks.onStepFailed?.({
|
|
32657
|
+
stepIdx,
|
|
32658
|
+
agent: agentId,
|
|
32659
|
+
message: `Step "${agentId}" has \`batches: true\` but no \`produces\` file to write its \`Status:\` line in.`
|
|
32660
|
+
});
|
|
32661
|
+
return "failed";
|
|
32662
|
+
}
|
|
32663
|
+
const batchNo = report ? batchesOf(stepRec).length + 1 : 0;
|
|
32664
|
+
const batchNote = report ? batchInstructions(report, batchNo, stepRec.revision) : null;
|
|
32665
|
+
const userMessage = [baseMessage, feedback, batchNote].filter(Boolean).join("\n\n");
|
|
31659
32666
|
if (opts.dryRun) {
|
|
31660
32667
|
hooks.onDryRunPreview?.({
|
|
31661
32668
|
skills: skillIds.join(", "),
|
|
@@ -31664,7 +32671,7 @@ About these inputs: ${(0, inheritedContext_1.inheritedContextNote)(epicRoot)}` :
|
|
|
31664
32671
|
env,
|
|
31665
32672
|
inlined: prompt2.included
|
|
31666
32673
|
});
|
|
31667
|
-
return
|
|
32674
|
+
return "done";
|
|
31668
32675
|
}
|
|
31669
32676
|
hooks.onStepStart?.({
|
|
31670
32677
|
stepIdx,
|
|
@@ -31678,20 +32685,69 @@ About these inputs: ${(0, inheritedContext_1.inheritedContextNote)(epicRoot)}` :
|
|
|
31678
32685
|
const aliases = (0, pricing_1.providerAliases)(ws.config.providers, agent.runner);
|
|
31679
32686
|
const resolvedModel = (0, models_1.resolveProviderModel)(agent.runner, agentModel, aliases);
|
|
31680
32687
|
const producedBefore = (0, producesSnapshot_1.snapshotProduces)({ state, pipeline, workspaceRoot: root, stepIdx });
|
|
31681
|
-
const
|
|
31682
|
-
|
|
31683
|
-
|
|
31684
|
-
|
|
31685
|
-
|
|
31686
|
-
|
|
31687
|
-
|
|
31688
|
-
|
|
31689
|
-
|
|
31690
|
-
|
|
31691
|
-
|
|
31692
|
-
|
|
32688
|
+
const codeExclude = [
|
|
32689
|
+
path17.relative(root, path17.join((0, EpicScaffold_1.epicsRoot)(root, ws.config), state.runId)),
|
|
32690
|
+
".aidlc"
|
|
32691
|
+
];
|
|
32692
|
+
const sentBackHere = isAutoSendBackTarget(state, stepIdx);
|
|
32693
|
+
const codeBefore = sentBackHere || report ? (0, codeFingerprint_1.codeFingerprint)(root, codeExclude) : null;
|
|
32694
|
+
const stop = new AbortController();
|
|
32695
|
+
const minutes = norm?.timeout_minutes;
|
|
32696
|
+
let timedOut = false;
|
|
32697
|
+
const timer = minutes ? setTimeout(() => {
|
|
32698
|
+
timedOut = true;
|
|
32699
|
+
stop.abort();
|
|
32700
|
+
}, minutes * 6e4) : void 0;
|
|
32701
|
+
const onStopNow = () => stop.abort();
|
|
32702
|
+
opts.signal?.addEventListener("abort", onStopNow, { once: true });
|
|
32703
|
+
let result;
|
|
32704
|
+
try {
|
|
32705
|
+
result = await settledOrAbandoned(runner.run({
|
|
32706
|
+
skill: skillText,
|
|
32707
|
+
env,
|
|
32708
|
+
args: userMessage ? [userMessage] : [],
|
|
32709
|
+
workspaceRoot: root,
|
|
32710
|
+
model: agentModel,
|
|
32711
|
+
modelAliases: aliases,
|
|
32712
|
+
extraArgs: ws.config.providers[agent.runner]?.args,
|
|
32713
|
+
signal: stop.signal,
|
|
32714
|
+
onOutput: (chunk) => hooks.onOutput?.(chunk),
|
|
32715
|
+
onError: (chunk) => hooks.onErrorOutput?.(chunk),
|
|
32716
|
+
claude: null
|
|
32717
|
+
}), stop.signal);
|
|
32718
|
+
} finally {
|
|
32719
|
+
if (timer) {
|
|
32720
|
+
clearTimeout(timer);
|
|
32721
|
+
}
|
|
32722
|
+
opts.signal?.removeEventListener("abort", onStopNow);
|
|
32723
|
+
}
|
|
32724
|
+
if (stop.signal.aborted) {
|
|
32725
|
+
recordInterrupted(root, runId, stepIdx, timedOut ? { why: "timeout", minutes } : { why: "stopped" });
|
|
32726
|
+
if (timedOut) {
|
|
32727
|
+
hooks.onStepFailed?.({
|
|
32728
|
+
stepIdx,
|
|
32729
|
+
agent: agentId,
|
|
32730
|
+
message: `Step "${agentId}" ran past its ${minutes}-minute limit (\`timeout_minutes\`) and was stopped. It is still awaiting work on revision ${stepRec.revision}; nothing was sent back. Whatever it half-wrote is still in the working tree.`
|
|
32731
|
+
});
|
|
32732
|
+
return "failed";
|
|
32733
|
+
}
|
|
32734
|
+
hooks.onStepStopped?.({ stepIdx, agent: agentId, revision: stepRec.revision, runId });
|
|
32735
|
+
return "stopped";
|
|
32736
|
+
}
|
|
32737
|
+
if (!result || !result.success) {
|
|
31693
32738
|
hooks.onStepFailed?.({ stepIdx, agent: agentId, message: `Step "${agentId}" failed (non-zero exit).` });
|
|
31694
|
-
return
|
|
32739
|
+
return "failed";
|
|
32740
|
+
}
|
|
32741
|
+
const codeUnchanged = codeBefore !== null && (0, codeFingerprint_1.codeFingerprint)(root, codeExclude) === codeBefore;
|
|
32742
|
+
if (sentBackHere && codeUnchanged && batchNo <= 1) {
|
|
32743
|
+
hooks.onStalled?.({
|
|
32744
|
+
stepIdx,
|
|
32745
|
+
agent: agentId,
|
|
32746
|
+
revision: stepRec.revision,
|
|
32747
|
+
runId,
|
|
32748
|
+
reason: `Revision ${stepRec.revision} of "${agentId}" changed no code \u2014 the working tree is what it was before it ran (its report aside). Sent back ${state.sendBacks} time${state.sendBacks === 1 ? "" : "s"}; stopping rather than have the same code reviewed again.`
|
|
32749
|
+
});
|
|
32750
|
+
return "stalled";
|
|
31695
32751
|
}
|
|
31696
32752
|
const stale = (0, producesSnapshot_1.unchangedProduces)(producedBefore, root);
|
|
31697
32753
|
if (stale.length > 0) {
|
|
@@ -31700,37 +32756,64 @@ About these inputs: ${(0, inheritedContext_1.inheritedContextNote)(epicRoot)}` :
|
|
|
31700
32756
|
agent: agentId,
|
|
31701
32757
|
message: `Step "${agentId}" reported success but left its artifacts unchanged: ${stale.join(", ")}. The agent may have failed to write them. Check its output, then rerun the step.`
|
|
31702
32758
|
});
|
|
31703
|
-
return
|
|
32759
|
+
return "failed";
|
|
32760
|
+
}
|
|
32761
|
+
if (report) {
|
|
32762
|
+
const read = (0, batchStatus_1.readBatchStatusFile)(root, report);
|
|
32763
|
+
if ("error" in read) {
|
|
32764
|
+
hooks.onStepFailed?.({
|
|
32765
|
+
stepIdx,
|
|
32766
|
+
agent: agentId,
|
|
32767
|
+
message: `Step "${agentId}" runs in batches and its report cannot say whether it is done: ${read.error} Add the line, then run exec again.`
|
|
32768
|
+
});
|
|
32769
|
+
return "failed";
|
|
32770
|
+
}
|
|
32771
|
+
if (read.status === "continue") {
|
|
32772
|
+
if (codeUnchanged) {
|
|
32773
|
+
hooks.onStalled?.({
|
|
32774
|
+
stepIdx,
|
|
32775
|
+
agent: agentId,
|
|
32776
|
+
revision: stepRec.revision,
|
|
32777
|
+
runId,
|
|
32778
|
+
reason: `Batch ${batchNo} of "${agentId}" asked for another session but changed no code \u2014 the working tree is what it was before it ran (its report aside). Stopping rather than start the same batch again.`
|
|
32779
|
+
});
|
|
32780
|
+
return "stalled";
|
|
32781
|
+
}
|
|
32782
|
+
const fresh = RunStateStore_1.RunStateStore.load(root, runId);
|
|
32783
|
+
const rec = fresh?.steps[stepIdx];
|
|
32784
|
+
if (!fresh || !rec) {
|
|
32785
|
+
hooks.onStepFailed?.({ stepIdx, agent: agentId, message: `Run "${runId}" disappeared.` });
|
|
32786
|
+
return "failed";
|
|
32787
|
+
}
|
|
32788
|
+
recordProvenance(rec, { agent, resolvedModel, agentModel, skillIds, alternatives, modelOpts });
|
|
32789
|
+
const cost = addBatchCost(rec, batchNo, result, batchCost(result, ws, agent.runner, resolvedModel ?? agentModel));
|
|
32790
|
+
rec.history = [...rec.history ?? [], {
|
|
32791
|
+
kind: "batch",
|
|
32792
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
32793
|
+
revision: rec.revision,
|
|
32794
|
+
batch: batchNo,
|
|
32795
|
+
...cost !== void 0 ? { costUsd: cost } : {}
|
|
32796
|
+
}];
|
|
32797
|
+
persist(root, fresh);
|
|
32798
|
+
hooks.onBatchDone?.({
|
|
32799
|
+
stepIdx,
|
|
32800
|
+
agent: agentId,
|
|
32801
|
+
revision: rec.revision,
|
|
32802
|
+
batch: batchNo,
|
|
32803
|
+
costUsd: cost,
|
|
32804
|
+
costEstimated: rec.costEstimated,
|
|
32805
|
+
runId
|
|
32806
|
+
});
|
|
32807
|
+
return "batch";
|
|
32808
|
+
}
|
|
31704
32809
|
}
|
|
31705
32810
|
let next;
|
|
31706
32811
|
let freshState;
|
|
31707
32812
|
try {
|
|
31708
32813
|
freshState = RunStateStore_1.RunStateStore.load(root, runId);
|
|
31709
32814
|
const rec = freshState.steps[stepIdx];
|
|
31710
|
-
rec
|
|
31711
|
-
rec.
|
|
31712
|
-
if (alternatives) {
|
|
31713
|
-
rec.skill = skillIds[0];
|
|
31714
|
-
}
|
|
31715
|
-
if (modelOpts.models) {
|
|
31716
|
-
rec.chosenModel = agentModel;
|
|
31717
|
-
}
|
|
31718
|
-
rec.usage = result.usage;
|
|
31719
|
-
if (typeof result.costUsd === "number") {
|
|
31720
|
-
rec.costUsd = result.costUsd;
|
|
31721
|
-
rec.costEstimated = void 0;
|
|
31722
|
-
} else {
|
|
31723
|
-
const est = (0, pricing_1.estimateCostUsd)({
|
|
31724
|
-
table: (0, pricing_1.ratesFromConfig)(ws.config.providers),
|
|
31725
|
-
provider: agent.runner,
|
|
31726
|
-
model: resolvedModel ?? agentModel,
|
|
31727
|
-
usage: result.usage
|
|
31728
|
-
});
|
|
31729
|
-
if (est) {
|
|
31730
|
-
rec.costUsd = est.usd;
|
|
31731
|
-
rec.costEstimated = true;
|
|
31732
|
-
}
|
|
31733
|
-
}
|
|
32815
|
+
recordProvenance(rec, { agent, resolvedModel, agentModel, skillIds, alternatives, modelOpts });
|
|
32816
|
+
addBatchCost(rec, batchNo, result, batchCost(result, ws, agent.runner, resolvedModel ?? agentModel));
|
|
31734
32817
|
next = (0, PipelineRunner_1.markStepDone)({ state: freshState, pipeline, workspaceRoot: root });
|
|
31735
32818
|
} catch (err) {
|
|
31736
32819
|
if (err instanceof PipelineRunner_1.PipelineRunError && err.missing?.length) {
|
|
@@ -31738,7 +32821,7 @@ About these inputs: ${(0, inheritedContext_1.inheritedContextNote)(epicRoot)}` :
|
|
|
31738
32821
|
} else {
|
|
31739
32822
|
hooks.onStepFailed?.({ stepIdx, agent: agentId, message: errMsg(err) });
|
|
31740
32823
|
}
|
|
31741
|
-
return
|
|
32824
|
+
return "failed";
|
|
31742
32825
|
}
|
|
31743
32826
|
persist(root, next, freshState);
|
|
31744
32827
|
const doneStep = next.steps[stepIdx];
|
|
@@ -31751,7 +32834,111 @@ About these inputs: ${(0, inheritedContext_1.inheritedContextNote)(epicRoot)}` :
|
|
|
31751
32834
|
runner: agent.runner,
|
|
31752
32835
|
model: resolvedModel
|
|
31753
32836
|
});
|
|
31754
|
-
return
|
|
32837
|
+
return "done";
|
|
32838
|
+
}
|
|
32839
|
+
function batchesOf(rec) {
|
|
32840
|
+
if (!rec) {
|
|
32841
|
+
return [];
|
|
32842
|
+
}
|
|
32843
|
+
return (rec.history ?? []).flatMap((h) => h.kind === "batch" && h.revision === rec.revision ? [h] : []);
|
|
32844
|
+
}
|
|
32845
|
+
function batchReport(pipeline, state, stepIdx) {
|
|
32846
|
+
const cfg = pipeline.steps[stepIdx];
|
|
32847
|
+
if (!cfg) {
|
|
32848
|
+
return null;
|
|
32849
|
+
}
|
|
32850
|
+
const norm = (0, WorkspaceSchema_1.normalizeStep)(cfg);
|
|
32851
|
+
const first = norm.produces.find((p) => !norm.produces_optional.includes(p));
|
|
32852
|
+
return first ? (0, RunState_1.resolvePath)(first, state.context) : null;
|
|
32853
|
+
}
|
|
32854
|
+
function batchInstructions(report, batchNo, revision) {
|
|
32855
|
+
const lines = [
|
|
32856
|
+
`This step runs in batches: this is batch ${batchNo} of revision ${revision}, in a fresh session.`,
|
|
32857
|
+
batchNo === 1 && revision > 1 ? `Make this batch the fixes the feedback above asks for. Keep the progress table ${report} already has from the earlier revision, so you know what is done, and add the fixes to it.` : batchNo === 1 ? "Start with the first batch in the plan." : `${report} records what earlier batches did. Read it first, then do the next batch in the plan.`,
|
|
32858
|
+
`Do that one batch only, then update ${report}: its progress table, and as its last line \`Status: continue\` if any of the step's work is left, or \`Status: done\` when all of it is finished. A batch may be split smaller if it does not fit; never do two in one session.`
|
|
32859
|
+
];
|
|
32860
|
+
return lines.join(" ");
|
|
32861
|
+
}
|
|
32862
|
+
function recordProvenance(rec, p) {
|
|
32863
|
+
rec.runner = p.agent.runner;
|
|
32864
|
+
rec.model = p.resolvedModel;
|
|
32865
|
+
if (p.alternatives) {
|
|
32866
|
+
rec.skill = p.skillIds[0];
|
|
32867
|
+
}
|
|
32868
|
+
if (p.modelOpts.models) {
|
|
32869
|
+
rec.chosenModel = p.agentModel;
|
|
32870
|
+
}
|
|
32871
|
+
}
|
|
32872
|
+
function batchCost(result, ws, provider, model) {
|
|
32873
|
+
if (typeof result.costUsd === "number") {
|
|
32874
|
+
return { usd: result.costUsd, estimated: false };
|
|
32875
|
+
}
|
|
32876
|
+
const est = (0, pricing_1.estimateCostUsd)({
|
|
32877
|
+
table: (0, pricing_1.ratesFromConfig)(ws.config.providers),
|
|
32878
|
+
provider,
|
|
32879
|
+
model,
|
|
32880
|
+
usage: result.usage
|
|
32881
|
+
});
|
|
32882
|
+
return est ? { usd: est.usd, estimated: true } : void 0;
|
|
32883
|
+
}
|
|
32884
|
+
function addBatchCost(rec, batchNo, result, cost) {
|
|
32885
|
+
const carry = batchNo > 1;
|
|
32886
|
+
rec.usage = carry ? addUsage(rec.usage, result.usage) : result.usage;
|
|
32887
|
+
if (!cost) {
|
|
32888
|
+
return void 0;
|
|
32889
|
+
}
|
|
32890
|
+
if (carry && typeof rec.costUsd === "number") {
|
|
32891
|
+
rec.costUsd += cost.usd;
|
|
32892
|
+
rec.costEstimated = rec.costEstimated || cost.estimated || void 0;
|
|
32893
|
+
} else {
|
|
32894
|
+
rec.costUsd = cost.usd;
|
|
32895
|
+
rec.costEstimated = cost.estimated || void 0;
|
|
32896
|
+
}
|
|
32897
|
+
return cost.usd;
|
|
32898
|
+
}
|
|
32899
|
+
function addUsage(a, b) {
|
|
32900
|
+
if (!a) {
|
|
32901
|
+
return b;
|
|
32902
|
+
}
|
|
32903
|
+
if (!b) {
|
|
32904
|
+
return a;
|
|
32905
|
+
}
|
|
32906
|
+
const sum = (x, y) => x === void 0 && y === void 0 ? void 0 : (x ?? 0) + (y ?? 0);
|
|
32907
|
+
return { inputTokens: sum(a.inputTokens, b.inputTokens), outputTokens: sum(a.outputTokens, b.outputTokens) };
|
|
32908
|
+
}
|
|
32909
|
+
async function settledOrAbandoned(run, signal) {
|
|
32910
|
+
let timer;
|
|
32911
|
+
const abandoned = new Promise((resolve5) => {
|
|
32912
|
+
const giveUp = () => {
|
|
32913
|
+
timer = setTimeout(() => resolve5(null), processTree_1.STOP_GRACE_MS + 5e3);
|
|
32914
|
+
};
|
|
32915
|
+
if (signal.aborted) {
|
|
32916
|
+
giveUp();
|
|
32917
|
+
} else {
|
|
32918
|
+
signal.addEventListener("abort", giveUp, { once: true });
|
|
32919
|
+
}
|
|
32920
|
+
});
|
|
32921
|
+
try {
|
|
32922
|
+
return await Promise.race([run, abandoned]);
|
|
32923
|
+
} finally {
|
|
32924
|
+
if (timer) {
|
|
32925
|
+
clearTimeout(timer);
|
|
32926
|
+
}
|
|
32927
|
+
}
|
|
32928
|
+
}
|
|
32929
|
+
function recordInterrupted(root, runId, stepIdx, what) {
|
|
32930
|
+
const fresh = RunStateStore_1.RunStateStore.load(root, runId);
|
|
32931
|
+
const rec = fresh?.steps[stepIdx];
|
|
32932
|
+
if (!fresh || !rec) {
|
|
32933
|
+
return;
|
|
32934
|
+
}
|
|
32935
|
+
rec.history = [...rec.history ?? [], {
|
|
32936
|
+
kind: "interrupted",
|
|
32937
|
+
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
32938
|
+
revision: rec.revision,
|
|
32939
|
+
...what
|
|
32940
|
+
}];
|
|
32941
|
+
RunStateStore_1.RunStateStore.save(root, fresh);
|
|
31755
32942
|
}
|
|
31756
32943
|
async function runAutoReviewStep(root, runId, hooks) {
|
|
31757
32944
|
const state = RunStateStore_1.RunStateStore.load(root, runId);
|
|
@@ -31781,18 +32968,43 @@ About these inputs: ${(0, inheritedContext_1.inheritedContextNote)(epicRoot)}` :
|
|
|
31781
32968
|
return false;
|
|
31782
32969
|
}
|
|
31783
32970
|
persist(root, next, state);
|
|
32971
|
+
const idx = state.currentStepIdx;
|
|
32972
|
+
const sentBack = verdict.decision === "reject" && next.currentStepIdx !== idx && next.steps[idx].status === "pending";
|
|
31784
32973
|
hooks.onAutoReviewResult?.({
|
|
31785
32974
|
agent: step.agent,
|
|
31786
32975
|
decision: verdict.decision,
|
|
31787
|
-
reason: verdict.reason,
|
|
31788
|
-
runId
|
|
32976
|
+
reason: next.steps[idx].rejectReason ?? verdict.reason,
|
|
32977
|
+
runId,
|
|
32978
|
+
...sentBack ? {
|
|
32979
|
+
sentBackTo: {
|
|
32980
|
+
stepIdx: next.currentStepIdx,
|
|
32981
|
+
agent: next.steps[next.currentStepIdx].agent,
|
|
32982
|
+
revision: next.steps[next.currentStepIdx].revision,
|
|
32983
|
+
count: next.sendBacks ?? 0,
|
|
32984
|
+
max: pipeline.max_send_backs ?? WorkspaceSchema_1.DEFAULT_MAX_SEND_BACKS
|
|
32985
|
+
}
|
|
32986
|
+
} : {}
|
|
31789
32987
|
});
|
|
31790
32988
|
return true;
|
|
31791
32989
|
}
|
|
32990
|
+
function isAutoSendBackTarget(state, stepIdx) {
|
|
32991
|
+
if (!state.sendBacks) {
|
|
32992
|
+
return false;
|
|
32993
|
+
}
|
|
32994
|
+
let latest = null;
|
|
32995
|
+
for (const s of state.steps) {
|
|
32996
|
+
for (const h of s.history ?? []) {
|
|
32997
|
+
if (h.kind === "reject" && h.source && (!latest || h.at >= latest.at)) {
|
|
32998
|
+
latest = { at: h.at, to: h.sentBackToIdx };
|
|
32999
|
+
}
|
|
33000
|
+
}
|
|
33001
|
+
}
|
|
33002
|
+
return latest?.to === stepIdx;
|
|
33003
|
+
}
|
|
31792
33004
|
async function autoApproveStep(root, state, hooks) {
|
|
31793
33005
|
const ws = WorkspaceLoader_1.WorkspaceLoader.load(root);
|
|
31794
33006
|
const pipeline = ws.config.pipelines.find((p) => p.id === state.pipelineId);
|
|
31795
|
-
const next = (0, PipelineRunner_1.approveStep)({ state, pipeline });
|
|
33007
|
+
const next = { ...(0, PipelineRunner_1.approveStep)({ state, pipeline }), sendBacks: state.sendBacks };
|
|
31796
33008
|
persist(root, next, state);
|
|
31797
33009
|
hooks.onAutoApproved?.({ agent: state.steps[state.currentStepIdx].agent });
|
|
31798
33010
|
}
|
|
@@ -31967,6 +33179,10 @@ var require_runReport = __commonJS({
|
|
|
31967
33179
|
return ` - \u2714 approved (rev ${h.revision}${h.skill ? `, ${h.skill}` : ""}${h.model ? `, ${h.model}` : ""})`;
|
|
31968
33180
|
case "undo":
|
|
31969
33181
|
return ` - \u21B6 mark-done undone (rev ${h.revision}, was ${h.from})`;
|
|
33182
|
+
case "interrupted":
|
|
33183
|
+
return h.why === "timeout" ? ` - \u23F1 stopped after ${h.minutes ?? "?"} min (timeout_minutes, rev ${h.revision})` : ` - \u23F9 stopped mid-step (rev ${h.revision})`;
|
|
33184
|
+
case "batch":
|
|
33185
|
+
return ` - \u21BB batch ${h.batch} done, more to come (rev ${h.revision}${typeof h.costUsd === "number" ? `, $${h.costUsd.toFixed(4)}` : ""})`;
|
|
31970
33186
|
default:
|
|
31971
33187
|
return " - (unknown event)";
|
|
31972
33188
|
}
|
|
@@ -32612,6 +33828,8 @@ into working code on a feature branch.
|
|
|
32612
33828
|
dependsOn: ["review"]
|
|
32613
33829
|
}
|
|
32614
33830
|
];
|
|
33831
|
+
var VERDICT_VALIDATOR = ".aidlc/validators/verdict.mjs";
|
|
33832
|
+
var CI_VALIDATOR = ".aidlc/validators/ci.mjs";
|
|
32615
33833
|
var AINATIVE_RECIPES = [
|
|
32616
33834
|
{
|
|
32617
33835
|
id: "native-quick",
|
|
@@ -32620,7 +33838,7 @@ into working code on a feature branch.
|
|
|
32620
33838
|
},
|
|
32621
33839
|
{
|
|
32622
33840
|
id: "native-lite",
|
|
32623
|
-
description: "Small change with a precedent already in the codebase \u2014 no spec, no separate verify. The human gates sit up front, on intent and build-plan, where a wrong direction is cheapest to correct; implement and review then run to the end unattended. Trade-off: review is the only quality gate left, and nobody reads it before the branch is finished \u2014 prefer native-fix when the change has no precedent to follow.",
|
|
33841
|
+
description: "Small change with a precedent already in the codebase \u2014 no spec, no separate verify. The human gates sit up front, on intent and build-plan, where a wrong direction is cheapest to correct; implement and review then run to the end unattended. Trade-off: review is the only quality gate left, and nobody reads it before the branch is finished \u2014 a hold verdict stops the run, but prefer native-fix when the change has no precedent to follow.",
|
|
32624
33842
|
steps: ["intent", "build-plan", "implement", "review"],
|
|
32625
33843
|
// Spelled out for all four steps, including the two that would inherit
|
|
32626
33844
|
// `true` anyway: where the humans stand is the point of this recipe, so
|
|
@@ -32629,7 +33847,48 @@ into working code on a feature branch.
|
|
|
32629
33847
|
intent: { human_review: true },
|
|
32630
33848
|
"build-plan": { human_review: true },
|
|
32631
33849
|
implement: { human_review: false },
|
|
32632
|
-
review
|
|
33850
|
+
// Nobody reads review.md before the run ends, so something has to: a
|
|
33851
|
+
// `hold` (or no readable verdict) rejects the step instead of letting
|
|
33852
|
+
// the run report `completed`.
|
|
33853
|
+
review: { human_review: false, auto_review: true, auto_review_runner: VERDICT_VALIDATOR }
|
|
33854
|
+
}
|
|
33855
|
+
},
|
|
33856
|
+
{
|
|
33857
|
+
id: "native-autopilot",
|
|
33858
|
+
description: "Left to run on its own once the plan is approved \u2014 no spec. A person approves intent and build-plan, then implement, verify and review run unattended: CI checks implement, and a failed verify or a review hold sends the work back to implement on its own, up to three times. The run stops at review for a person to approve the finished branch. Needs a branch of its own, the approval-gate hook and real CHECKS in .aidlc/validators/ci.mjs.",
|
|
33859
|
+
steps: ["intent", "build-plan", "implement", "verify", "review"],
|
|
33860
|
+
autopilot: true,
|
|
33861
|
+
max_send_backs: 3,
|
|
33862
|
+
gates: {
|
|
33863
|
+
intent: { human_review: true, timeout_minutes: 20 },
|
|
33864
|
+
"build-plan": { human_review: true, timeout_minutes: 20 },
|
|
33865
|
+
// A CI reject reruns implement on its own feedback; it is never sent
|
|
33866
|
+
// anywhere else. Each batch is a fresh session with its own 30 minutes.
|
|
33867
|
+
implement: {
|
|
33868
|
+
human_review: false,
|
|
33869
|
+
auto_review: true,
|
|
33870
|
+
auto_review_runner: CI_VALIDATOR,
|
|
33871
|
+
batches: true,
|
|
33872
|
+
timeout_minutes: 30
|
|
33873
|
+
},
|
|
33874
|
+
verify: {
|
|
33875
|
+
human_review: false,
|
|
33876
|
+
auto_review: true,
|
|
33877
|
+
auto_review_runner: VERDICT_VALIDATOR,
|
|
33878
|
+
on_reject: { send_back_to: "implement" },
|
|
33879
|
+
timeout_minutes: 20
|
|
33880
|
+
},
|
|
33881
|
+
// A person still approves the end of the run (a `ship` stops here), but
|
|
33882
|
+
// only once: a `hold` goes back to implement without waiting for them.
|
|
33883
|
+
// Once the validators have earned trust, `human_review: false` makes a
|
|
33884
|
+
// `ship` complete the run.
|
|
33885
|
+
review: {
|
|
33886
|
+
human_review: true,
|
|
33887
|
+
auto_review: true,
|
|
33888
|
+
auto_review_runner: VERDICT_VALIDATOR,
|
|
33889
|
+
on_reject: { send_back_to: "implement" },
|
|
33890
|
+
timeout_minutes: 20
|
|
33891
|
+
}
|
|
32633
33892
|
}
|
|
32634
33893
|
},
|
|
32635
33894
|
{
|
|
@@ -32842,7 +34101,9 @@ into working code on a feature branch.
|
|
|
32842
34101
|
description: r.description,
|
|
32843
34102
|
from: workflow.pipelineId,
|
|
32844
34103
|
steps: r.steps,
|
|
32845
|
-
...r.gates ? { gates: r.gates } : {}
|
|
34104
|
+
...r.gates ? { gates: r.gates } : {},
|
|
34105
|
+
...r.autopilot !== void 0 ? { autopilot: r.autopilot } : {},
|
|
34106
|
+
...r.max_send_backs !== void 0 ? { max_send_backs: r.max_send_backs } : {}
|
|
32846
34107
|
})),
|
|
32847
34108
|
sidebar: {
|
|
32848
34109
|
views: [
|
|
@@ -33073,12 +34334,15 @@ export default async function ci(_ctx) {
|
|
|
33073
34334
|
}
|
|
33074
34335
|
`;
|
|
33075
34336
|
function writeBuiltinAutoReviewValidators(extensionPath, root, workflow) {
|
|
34337
|
+
const runners = [
|
|
34338
|
+
...workflow.phases.filter((p) => p.autoReview).map((p) => p.autoReviewRunner),
|
|
34339
|
+
...(workflow.recipes ?? []).flatMap((r) => Object.values(r.gates ?? {}).map((g) => g.auto_review_runner))
|
|
34340
|
+
];
|
|
33076
34341
|
const seen = /* @__PURE__ */ new Set();
|
|
33077
|
-
for (const
|
|
33078
|
-
if (!
|
|
34342
|
+
for (const rel of runners) {
|
|
34343
|
+
if (!rel) {
|
|
33079
34344
|
continue;
|
|
33080
34345
|
}
|
|
33081
|
-
const rel = phase.autoReviewRunner;
|
|
33082
34346
|
if (path17.isAbsolute(rel) || rel.startsWith("..")) {
|
|
33083
34347
|
continue;
|
|
33084
34348
|
}
|
|
@@ -34135,13 +35399,14 @@ var require_dist = __commonJS({
|
|
|
34135
35399
|
"../core/dist/index.js"(exports2) {
|
|
34136
35400
|
"use strict";
|
|
34137
35401
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
34138
|
-
exports2.
|
|
34139
|
-
exports2.
|
|
34140
|
-
exports2.
|
|
34141
|
-
exports2.
|
|
34142
|
-
exports2.
|
|
34143
|
-
exports2.
|
|
34144
|
-
exports2.
|
|
35402
|
+
exports2.commitEpicStepEdit = exports2.planSetEpicStepGates = exports2.planRemoveEpicStep = exports2.planAddEpicStep = exports2.EpicWorkflowSwitchError = exports2.canSwitchEpicWorkflow = exports2.epicWorkflowLock = exports2.applyEpicWorkflowSwitch = exports2.stageEpicWorkflowSwitch = exports2.planEpicWorkflowSwitch = exports2.EpicDescriptionError = exports2.setEpicDescription = exports2.lockedEpicDirError = exports2.EpicScaffoldError = exports2.epicsRoot = exports2.mapStepStatusToEpic = exports2.mirrorRunStateToEpic = exports2.scaffoldEpic = exports2.resolveArtifactCommitConfig = exports2.commitApprovedArtifacts = exports2.PipelineAdaptError = exports2.applyAdaptation = exports2.parseAdaptationVerdict = exports2.buildAdaptationPrompt = exports2.buildPhaseCatalog = exports2.slugEpicId = exports2.parseClassificationVerdict = exports2.buildClassificationPrompt = exports2.heuristicClassify = exports2.PipelineAssembleError = exports2.pipelineRecipeLabel = exports2.recipePipelineId = exports2.assemblePipeline = exports2.unsafeRunnerArg = exports2.DEFAULT_MAX_BATCHES = exports2.DEFAULT_MAX_SEND_BACKS = exports2.AMBIGUOUS_STEP_INDEX = exports2.sendBackIssues = exports2.findStepIndex = exports2.collectWorkspaceRefIssues = exports2.resolveStepSkills = exports2.stepSkillAlternatives = exports2.stepDagId = exports2.stepAgentId = exports2.requiresEntries = exports2.producesEntries = exports2.normalizeStep = exports2.WorkspaceValidationError = exports2.validateWorkspace = exports2.WorkspaceSchema = void 0;
|
|
35403
|
+
exports2.generatePlan = exports2.collectContext = exports2.followUpHookFailures = exports2.pendingFollowUpDone = exports2.applyFollowUpHookRun = exports2.trackFollowUpChildren = exports2.writeFollowUpHookLedger = exports2.readFollowUpHookLedger = exports2.followUpHookLedgerPath = exports2.runFollowUpHook = exports2.fillFollowUpHookCommand = exports2.resolveFollowUpHooks = exports2.epicPipelineId = exports2.FOLLOW_UP_HOOK_TIMEOUT_MS = exports2.FOLLOW_UP_HOOKS_LEDGER = exports2.stepProducesFollowUps = exports2.collectFollowUpHookIssues = exports2.FOLLOW_UP_HOOK_PLACEHOLDERS = exports2.FOLLOW_UP_HOOK_KEYS = exports2.FOLLOW_UP_INTENT = exports2.FOLLOW_UPS_FILE = exports2.MANUAL_FOLLOW_UP_KEY_PREFIX = exports2.followUpDefaults = exports2.nextManualFollowUpKey = exports2.withFollowUpProvenance = exports2.openManifestFollowUp = exports2.combinedParentId = exports2.followUpChildId = exports2.followUpsOf = exports2.readEpicFollowUps = exports2.parseFollowUps = exports2.FollowUpsParseError = exports2.FollowUpManifestSchema = exports2.FollowUpItemSchema = exports2.SIGNAL_FILE = exports2.FOLLOW_UP_ARTIFACT = exports2.readEpicSignal = exports2.existingEpicIds = exports2.followUpIdFor = exports2.followUpEpicId = exports2.renderIntentMarkdown = exports2.openFollowUpEpic = exports2.openIncidentEpic = exports2.SignalParseError = exports2.isSignal = exports2.parseSignal = exports2.SignalSchema = exports2.EpicStepEditError = exports2.resolveStepRef = exports2.describeGateEffect = void 0;
|
|
35404
|
+
exports2.readUserConfig = exports2.readGitUserName = exports2.ensureUserConfigIgnored = exports2.USER_CONFIG_RELPATH = exports2.USER_CONFIG_IGNORE_LINE = exports2.suggestEpicId = exports2.resolveEpicIdPrefixChain = exports2.resolveEpicIdPrefix = exports2.epicIdDateStamp = exports2.deriveEpicIdPrefix = exports2.EPIC_ID_PREFIX_PATTERN = exports2.EPIC_ID_PREFIX_KEY = exports2.resolveArtifactLanguage = exports2.commandBodyPredatesArtifactLanguage = exports2.artifactLanguageSection = exports2.ARTIFACT_LANGUAGE_HEADING = exports2.stripPersonaDirectives = exports2.composeAgentPrompt = exports2.PROJECT_INSTRUCTION_FILES = exports2.findProjectInstructions = exports2.stripPersonaMetadata = exports2.PersonaLoader = exports2.SkillNotFoundError = exports2.SkillLoader = exports2.EnvVarMissingError = exports2.EnvResolver = exports2.epicPipelineReport = exports2.planEpicPipelineExtraction = exports2.epicOwningPipeline = exports2.unstageEpicPipeline = exports2.stageEpicPipeline = exports2.writeEpicPipelines = exports2.splitEpicPipelines = exports2.mergeEpicPipelines = exports2.epicPipelinePath = exports2.EPIC_PIPELINE_FILENAME = exports2.unusedAfterStepRemoval = exports2.skillReferences = exports2.agentReferences = exports2.renameSkillRefs = exports2.renameAgentRefs = exports2.dropRecipesForPipeline = exports2.dropRecipeStep = exports2.recipesDrawingFrom = exports2.WORKSPACE_DIR = exports2.WORKSPACE_FILENAME = exports2.WorkspaceParseError = exports2.WorkspaceNotFoundError = exports2.WorkspaceLoader = exports2.renderPlanMarkdown = void 0;
|
|
35405
|
+
exports2.hasEmptyCiChecks = exports2.findApprovalGate = exports2.autopilotPreflight = exports2.STOP_GRACE_MS = exports2.stopProcessTree = exports2.stopOnAbort = exports2.processGroupSpawnOptions = exports2.claudeModelArg = exports2.DefaultRunner = exports2.RunnerRegistry = exports2.targetPath = exports2.scopePaths = exports2.discoverAssets = exports2.commandBodyIsStale = exports2.readEpicTags = exports2.normalizeTags = exports2.normalizeTag = exports2.epicMatchesTags = exports2.applyTagEdit = exports2.MAX_TAG_LENGTH = exports2.EPIC_TAGS_KEY = exports2.inheritedContextNote = exports2.INHERITED_CONTEXT_MARKER = exports2.strictModeSection = exports2.resolveEpicStrictMode = exports2.epicStrictMode = exports2.commandBodyPredatesStrictMode = exports2.STRICT_MODE_KEY = exports2.STRICT_MODE_HEADING = exports2.setEpicWatched = exports2.setEpicListFlat = exports2.setEpicSort = exports2.setActiveEpic = exports2.recordEpicOpened = exports2.readEpicListFlat = exports2.readEpicSort = exports2.readEpicFocus = exports2.pushRecent = exports2.epicSortFrom = exports2.epicIdFromBranch = exports2.epicFocusFrom = exports2.WATCHED_EPICS_KEY = exports2.RECENT_EPICS_LIMIT = exports2.RECENT_EPICS_KEY = exports2.EPIC_LIST_FLAT_KEY = exports2.EPIC_SORT_KEY = exports2.ACTIVE_EPIC_KEY = exports2.writeUserEpicIdPrefix = exports2.userConfigPath = exports2.updateUserConfig = void 0;
|
|
35406
|
+
exports2.isStepOptional = exports2.isRunComplete = exports2.deriveRunProgress = exports2.PipelineRunError = exports2.retryAutoReview = exports2.submitAutoReviewVerdict = exports2.dirtyUpstreamOf = exports2.rerunApprovedStep = exports2.canRerunApprovedStep = exports2.chooseStepModel = exports2.chooseStepSkill = exports2.requestStepUpdate = exports2.rerunStep = exports2.rejectStep = exports2.approveStep = exports2.undoStepDone = exports2.canUndoStepDone = exports2.markStepDone = exports2.canStartStep = exports2.startRun = exports2.activateBackendFromWorkspace = exports2.activateRunStateBackend = exports2.resolveRunStateBackend = exports2.GitRunStateStore = exports2.RUN_ID_PATTERN = exports2.FileRunStateStore = exports2.RunStateStore = exports2.harnessCapabilities = exports2.NO_HARNESS_CAPABILITIES = exports2.RunnerValidationError = exports2.validateRunnerExport = exports2.CustomRunnerLoader = exports2.buildClaudeSpawnEnv = exports2.hasClaudeLogin = exports2.isInsideClaudeCodeSession = exports2.createJsonSink = exports2.createLineSink = exports2.isCodexMcpConfigured = exports2.codexConfigPath = exports2.readProjectMcpServer = exports2.mcpRegistrarFor = exports2.codexMcpRegistrar = exports2.claudeMcpRegistrar = exports2.copilotMcpConfig = exports2.copilotGraphServer = exports2.CopilotRunner = exports2.CodexRunner = exports2.AUTOPILOT_ENV = exports2.APPROVAL_GATE_SCRIPT = exports2.emptyCiChecksMessage = void 0;
|
|
35407
|
+
exports2.isClaudeTierAlias = exports2.CLAUDE_TIER_ALIASES = exports2.FAST_MODEL = exports2.CODING_MODEL = exports2.PLANNING_MODEL = exports2.isBuiltinPreset = exports2.BUILTIN_PRESET_IDS = exports2.writeBuiltinAutoReviewValidators = exports2.resolvePrimaryStack = exports2.getSdlcArtifactTemplates = exports2.getBuiltinArtifactTemplates = exports2.phaseArtifactFileName = exports2.sdlcClaudeCommand = exports2.builtinClaudeCommand = exports2.loadAllBuiltinPresets = exports2.loadBuiltinPreset = exports2.planRecipeMigration = exports2.getBuiltinRecipeSummaries = exports2.getAllBuiltinPipelineSummaries = exports2.getSdlcBuiltinPipelineSummary = exports2.getBuiltinPipelineSummary = exports2.getBuiltinWorkflowByPipelineId = exports2.getBuiltinWorkflow = exports2.workflowSlug = exports2.builtinTemplatesRoot = exports2.pipelineCommandId = exports2.PHASES = exports2.BUILTIN_WORKFLOWS = exports2.withBackfilledStepNames = exports2.describeDrift = exports2.reconcileRunSteps = exports2.RUN_STATE_SCHEMA_VERSION = exports2.migrateRunState = exports2.stepIdentity = exports2.resolvePath = exports2.AutoReviewerError = exports2.runAutoReview = exports2.renderRunReport = exports2.verifyRun = exports2.runExecLoop = exports2.estimateCostUsd = exports2.providerAliases = exports2.ratesFromConfig = exports2.mergeRates = exports2.BUILTIN_RATES = exports2.unchangedProduces = exports2.snapshotProduces = exports2.checkBudget = exports2.weighStepProgress = exports2.isActiveStatus = void 0;
|
|
35408
|
+
exports2.defaultClaudeConfigDir = exports2.getClaudeConfigDirOverride = exports2.setClaudeConfigDir = exports2.resolveDeclaredPath = exports2.expandHome = exports2.ProfileLoadError = exports2.UnknownStandardError = exports2.builtinProfiles = exports2.loadActiveProfile = exports2.loadProfile = exports2.listProfileManifests = exports2.resolveStandard = exports2.workspaceStandard = exports2.isBuiltinProfileId = exports2.ProfileSchema = exports2.TRACE_RULES = exports2.PROFILES_DIR = exports2.DEFAULT_PROFILE_ID = exports2.BUILTIN_PROFILE_IDS = exports2.setEpicMemoryHook = exports2.isEpicMemoryHookEnabled = exports2.installAnnotationTools = exports2.relativeEpicRoot = exports2.provisionDeclaredWorkflows = exports2.provisionWorkflowFiles = exports2.writeWorkflowArtifactTemplates = exports2.writeWorkflowCommands = exports2.provisionShortcutDocs = exports2.writeTwoLayerCommands = exports2.shortcutCommandDoc = exports2.backboneCommandDoc = exports2.unprovisionedPhases = exports2.nextEligiblePhase = exports2.resolveComposition = exports2.shortcutCommandId = exports2.getCanonicalPhase = exports2.isCanonicalPhase = exports2.BACKBONE_COMMAND_ID = exports2.CANONICAL_PHASE_IDS = exports2.CANONICAL_PHASES = exports2.renderTemplate = exports2.DEFAULT_GLOBAL_WORKFLOW_IDS = exports2.detectGlobalBuiltinSource = exports2.uninstallWorkflowGlobalsByIds = exports2.isWorkflowGloballyInstalled = exports2.installWorkflowGlobalsByIds = exports2.installGlobalDefaults = exports2.stepModelOptions = exports2.pickAgentModel = exports2.resolveProviderModel = void 0;
|
|
35409
|
+
exports2.AIDLC_CORE_VERSION = exports2.AIDLC_CLI_GUIDE_TEXT = exports2.AIDLC_KNOWLEDGE = exports2.clearResolveCommandCache = exports2.resolveCommand = exports2.remapClaudePath = exports2.claudeConfigEnv = exports2.claudeJsonPath = exports2.isDefaultClaudeConfigDir = exports2.claudeConfigDir = exports2.resolveClaudeConfigDir = void 0;
|
|
34145
35410
|
var WorkspaceSchema_1 = require_WorkspaceSchema();
|
|
34146
35411
|
Object.defineProperty(exports2, "WorkspaceSchema", { enumerable: true, get: function() {
|
|
34147
35412
|
return WorkspaceSchema_1.WorkspaceSchema;
|
|
@@ -34176,6 +35441,24 @@ var require_dist = __commonJS({
|
|
|
34176
35441
|
Object.defineProperty(exports2, "collectWorkspaceRefIssues", { enumerable: true, get: function() {
|
|
34177
35442
|
return WorkspaceSchema_1.collectWorkspaceRefIssues;
|
|
34178
35443
|
} });
|
|
35444
|
+
Object.defineProperty(exports2, "findStepIndex", { enumerable: true, get: function() {
|
|
35445
|
+
return WorkspaceSchema_1.findStepIndex;
|
|
35446
|
+
} });
|
|
35447
|
+
Object.defineProperty(exports2, "sendBackIssues", { enumerable: true, get: function() {
|
|
35448
|
+
return WorkspaceSchema_1.sendBackIssues;
|
|
35449
|
+
} });
|
|
35450
|
+
Object.defineProperty(exports2, "AMBIGUOUS_STEP_INDEX", { enumerable: true, get: function() {
|
|
35451
|
+
return WorkspaceSchema_1.AMBIGUOUS_STEP_INDEX;
|
|
35452
|
+
} });
|
|
35453
|
+
Object.defineProperty(exports2, "DEFAULT_MAX_SEND_BACKS", { enumerable: true, get: function() {
|
|
35454
|
+
return WorkspaceSchema_1.DEFAULT_MAX_SEND_BACKS;
|
|
35455
|
+
} });
|
|
35456
|
+
Object.defineProperty(exports2, "DEFAULT_MAX_BATCHES", { enumerable: true, get: function() {
|
|
35457
|
+
return WorkspaceSchema_1.DEFAULT_MAX_BATCHES;
|
|
35458
|
+
} });
|
|
35459
|
+
Object.defineProperty(exports2, "unsafeRunnerArg", { enumerable: true, get: function() {
|
|
35460
|
+
return WorkspaceSchema_1.unsafeRunnerArg;
|
|
35461
|
+
} });
|
|
34179
35462
|
var PipelineAssembler_1 = require_PipelineAssembler();
|
|
34180
35463
|
Object.defineProperty(exports2, "assemblePipeline", { enumerable: true, get: function() {
|
|
34181
35464
|
return PipelineAssembler_1.assemblePipeline;
|
|
@@ -34739,6 +36022,38 @@ var require_dist = __commonJS({
|
|
|
34739
36022
|
Object.defineProperty(exports2, "claudeModelArg", { enumerable: true, get: function() {
|
|
34740
36023
|
return DefaultRunner_1.claudeModelArg;
|
|
34741
36024
|
} });
|
|
36025
|
+
var processTree_1 = require_processTree();
|
|
36026
|
+
Object.defineProperty(exports2, "processGroupSpawnOptions", { enumerable: true, get: function() {
|
|
36027
|
+
return processTree_1.processGroupSpawnOptions;
|
|
36028
|
+
} });
|
|
36029
|
+
Object.defineProperty(exports2, "stopOnAbort", { enumerable: true, get: function() {
|
|
36030
|
+
return processTree_1.stopOnAbort;
|
|
36031
|
+
} });
|
|
36032
|
+
Object.defineProperty(exports2, "stopProcessTree", { enumerable: true, get: function() {
|
|
36033
|
+
return processTree_1.stopProcessTree;
|
|
36034
|
+
} });
|
|
36035
|
+
Object.defineProperty(exports2, "STOP_GRACE_MS", { enumerable: true, get: function() {
|
|
36036
|
+
return processTree_1.STOP_GRACE_MS;
|
|
36037
|
+
} });
|
|
36038
|
+
var autopilotPreflight_1 = require_autopilotPreflight();
|
|
36039
|
+
Object.defineProperty(exports2, "autopilotPreflight", { enumerable: true, get: function() {
|
|
36040
|
+
return autopilotPreflight_1.autopilotPreflight;
|
|
36041
|
+
} });
|
|
36042
|
+
Object.defineProperty(exports2, "findApprovalGate", { enumerable: true, get: function() {
|
|
36043
|
+
return autopilotPreflight_1.findApprovalGate;
|
|
36044
|
+
} });
|
|
36045
|
+
Object.defineProperty(exports2, "hasEmptyCiChecks", { enumerable: true, get: function() {
|
|
36046
|
+
return autopilotPreflight_1.hasEmptyCiChecks;
|
|
36047
|
+
} });
|
|
36048
|
+
Object.defineProperty(exports2, "emptyCiChecksMessage", { enumerable: true, get: function() {
|
|
36049
|
+
return autopilotPreflight_1.emptyCiChecksMessage;
|
|
36050
|
+
} });
|
|
36051
|
+
Object.defineProperty(exports2, "APPROVAL_GATE_SCRIPT", { enumerable: true, get: function() {
|
|
36052
|
+
return autopilotPreflight_1.APPROVAL_GATE_SCRIPT;
|
|
36053
|
+
} });
|
|
36054
|
+
Object.defineProperty(exports2, "AUTOPILOT_ENV", { enumerable: true, get: function() {
|
|
36055
|
+
return autopilotPreflight_1.AUTOPILOT_ENV;
|
|
36056
|
+
} });
|
|
34742
36057
|
var CodexRunner_1 = require_CodexRunner();
|
|
34743
36058
|
Object.defineProperty(exports2, "CodexRunner", { enumerable: true, get: function() {
|
|
34744
36059
|
return CodexRunner_1.CodexRunner;
|
|
@@ -43913,7 +45228,7 @@ var require_package = __commonJS({
|
|
|
43913
45228
|
"package.json"(exports2, module2) {
|
|
43914
45229
|
module2.exports = {
|
|
43915
45230
|
name: "@delete101020/aidlc",
|
|
43916
|
-
version: "4.0.
|
|
45231
|
+
version: "4.0.42",
|
|
43917
45232
|
description: "AIDLC Native CLI, a fork of AIDLC \u2014 drive Claude through the six-stage AI-Native SDLC Playbook: Plan \u2192 Design \u2192 Build \u2192 Test \u2192 Deploy \u2192 Maintain, with artifact gates, requirements traceability, an incident loop back to Plan, and Spec Kit support.",
|
|
43918
45233
|
license: "MIT",
|
|
43919
45234
|
repository: {
|
|
@@ -47180,6 +48495,76 @@ function providerChecks(ws) {
|
|
|
47180
48495
|
}
|
|
47181
48496
|
return checks;
|
|
47182
48497
|
}
|
|
48498
|
+
function autopilotChecks(root, ws) {
|
|
48499
|
+
const checks = [];
|
|
48500
|
+
const autopilot = ws.config.pipelines.filter((p) => p.autopilot).map((p) => p.id);
|
|
48501
|
+
const needed = autopilot.length > 0;
|
|
48502
|
+
const missing = (label, info2) => needed ? fail(label, info2) : warn(label, info2);
|
|
48503
|
+
if (needed) {
|
|
48504
|
+
checks.push(ok(`autopilot pipeline${autopilot.length !== 1 ? "s" : ""}`, autopilot.join(", ")));
|
|
48505
|
+
}
|
|
48506
|
+
const usesClaude = ws.config.agents.some((a) => a.runner === "default");
|
|
48507
|
+
if (usesClaude) {
|
|
48508
|
+
const gate = (0, import_core5.findApprovalGate)(root);
|
|
48509
|
+
checks.push(gate.found ? ok("approval gate hook", path4.relative(root, gate.settingsFile).split(path4.sep).join("/") || gate.settingsFile) : missing("approval gate hook", gate.reason));
|
|
48510
|
+
const args = ws.config.providers.default?.args ?? [];
|
|
48511
|
+
const viaArgs = args.some((a) => /^--(allowedTools|allowed-tools|permission-mode)(=|$)/.test(a));
|
|
48512
|
+
const viaSettings = claudeAllowListFiles(root);
|
|
48513
|
+
checks.push(viaArgs ? ok("headless permissions", "providers.default.args") : viaSettings.length > 0 ? ok("headless permissions", `permissions.allow in ${viaSettings.join(", ")}`) : missing(
|
|
48514
|
+
"headless permissions",
|
|
48515
|
+
'nothing allows Claude to edit files or run commands without asking, and under --print nobody can be asked \u2014 set providers.default.args (e.g. [--permission-mode, acceptEdits, --allowedTools, "Bash(npm test:*)"])'
|
|
48516
|
+
));
|
|
48517
|
+
}
|
|
48518
|
+
for (const id of autopilot) {
|
|
48519
|
+
const pipeline = ws.config.pipelines.find((p) => p.id === id);
|
|
48520
|
+
const runners = new Set(pipeline.steps.map((s) => ws.config.agents.find((a) => a.id === (typeof s === "string" ? s : s.agent))?.runner).filter((r) => !!r && r !== "default"));
|
|
48521
|
+
for (const runner of runners) {
|
|
48522
|
+
checks.push(warn(
|
|
48523
|
+
`"${id}" on ${runner}`,
|
|
48524
|
+
`the approval gate is a Claude Code hook, and ${runner} steps run without it \u2014 they rely on ${runner}'s own sandbox`
|
|
48525
|
+
));
|
|
48526
|
+
}
|
|
48527
|
+
}
|
|
48528
|
+
const unattended = [
|
|
48529
|
+
...ws.config.pipelines.filter((p) => p.autopilot).map((p) => ({ label: `"${p.id}"`, pipeline: p, fatal: true }))
|
|
48530
|
+
];
|
|
48531
|
+
for (const r of ws.config.recipes.filter((r2) => r2.autopilot)) {
|
|
48532
|
+
try {
|
|
48533
|
+
unattended.push({ label: `recipe "${r.id}"`, pipeline: (0, import_core5.assemblePipeline)(ws.config, { recipeId: r.id }), fatal: false });
|
|
48534
|
+
} catch {
|
|
48535
|
+
}
|
|
48536
|
+
}
|
|
48537
|
+
for (const { label, pipeline, fatal } of unattended) {
|
|
48538
|
+
for (const s of pipeline.steps) {
|
|
48539
|
+
const norm = (0, import_core5.normalizeStep)(s);
|
|
48540
|
+
const runner = norm.auto_review ? norm.auto_review_runner : void 0;
|
|
48541
|
+
if (!runner) {
|
|
48542
|
+
continue;
|
|
48543
|
+
}
|
|
48544
|
+
const step = norm.name ?? norm.agent;
|
|
48545
|
+
checks.push((0, import_core5.hasEmptyCiChecks)(root, runner) ? (fatal ? fail : warn)(`${label} CI checks`, (0, import_core5.emptyCiChecksMessage)(runner, step)) : ok(`${label} auto-review on "${step}"`, runner));
|
|
48546
|
+
}
|
|
48547
|
+
}
|
|
48548
|
+
return checks;
|
|
48549
|
+
}
|
|
48550
|
+
function claudeAllowListFiles(root) {
|
|
48551
|
+
const files = [
|
|
48552
|
+
path4.join(root, ".claude", "settings.json"),
|
|
48553
|
+
path4.join(root, ".claude", "settings.local.json"),
|
|
48554
|
+
path4.join((0, import_core5.claudeConfigDir)(), "settings.json")
|
|
48555
|
+
];
|
|
48556
|
+
return files.filter((f) => {
|
|
48557
|
+
try {
|
|
48558
|
+
const allow = JSON.parse(fs3.readFileSync(f, "utf8"))?.permissions?.allow;
|
|
48559
|
+
return Array.isArray(allow) && allow.length > 0;
|
|
48560
|
+
} catch {
|
|
48561
|
+
return false;
|
|
48562
|
+
}
|
|
48563
|
+
}).map((f) => {
|
|
48564
|
+
const r = path4.relative(root, f);
|
|
48565
|
+
return r.startsWith("..") ? f.replace(os.homedir(), "~") : r.split(path4.sep).join("/");
|
|
48566
|
+
});
|
|
48567
|
+
}
|
|
47183
48568
|
function registerDoctor(program3) {
|
|
47184
48569
|
program3.command("doctor").description("Validate workspace, claude binary, env, skills, and run state files").option("--json", "Output all checks as JSON (exit 1 still signals failures)").action((opts, cmd) => {
|
|
47185
48570
|
const root = resolveWorkspaceRoot(cmd);
|
|
@@ -47288,6 +48673,7 @@ function registerDoctor(program3) {
|
|
|
47288
48673
|
if (ws) {
|
|
47289
48674
|
emitSection("Harness parity", parityChecks(root, ws));
|
|
47290
48675
|
emitSection("Providers", providerChecks(ws));
|
|
48676
|
+
emitSection("Unattended runs", autopilotChecks(root, ws));
|
|
47291
48677
|
}
|
|
47292
48678
|
const runChecks = [];
|
|
47293
48679
|
const runsDir = path4.join(root, ".aidlc", "runs");
|
|
@@ -47598,21 +48984,9 @@ function findPipelineForRun(root, state) {
|
|
|
47598
48984
|
return null;
|
|
47599
48985
|
}
|
|
47600
48986
|
}
|
|
47601
|
-
var AMBIGUOUS_STEP =
|
|
48987
|
+
var AMBIGUOUS_STEP = import_core7.AMBIGUOUS_STEP_INDEX;
|
|
47602
48988
|
function resolveStepIdx(state, step) {
|
|
47603
|
-
|
|
47604
|
-
if (!isNaN(asInt) && String(asInt) === step) {
|
|
47605
|
-
return asInt >= 0 && asInt < state.steps.length ? asInt : -1;
|
|
47606
|
-
}
|
|
47607
|
-
const byName = state.steps.findIndex((s) => s.name === step);
|
|
47608
|
-
if (byName >= 0) {
|
|
47609
|
-
return byName;
|
|
47610
|
-
}
|
|
47611
|
-
const byAgent = state.steps.map((s, i) => s.agent === step ? i : -1).filter((i) => i >= 0);
|
|
47612
|
-
if (byAgent.length > 1) {
|
|
47613
|
-
return AMBIGUOUS_STEP;
|
|
47614
|
-
}
|
|
47615
|
-
return byAgent.length === 1 ? byAgent[0] : -1;
|
|
48989
|
+
return (0, import_core7.findStepIndex)(state.steps, step);
|
|
47616
48990
|
}
|
|
47617
48991
|
function stepLabel(s) {
|
|
47618
48992
|
return s.name ?? s.agent;
|
|
@@ -48752,19 +50126,40 @@ function registerRun(program3) {
|
|
|
48752
50126
|
console.log(import_chalk10.default.green("\u{1F389} Run completed \u2014 all steps approved."));
|
|
48753
50127
|
}
|
|
48754
50128
|
});
|
|
48755
|
-
cmd.command("reject <runId>").description(
|
|
50129
|
+
cmd.command("reject <runId>").description(
|
|
50130
|
+
'Reject the current awaiting_review step.\n Without --to the work stays on this step (then `run rerun`). With --to it goes\n back to an earlier step: that step reopens with the reason as its feedback and\n the steps after it reset to pending. Mirrors the extension\'s "Send back to step N".'
|
|
50131
|
+
).requiredOption("--reason <text>", "Why the step was rejected").option("--to <step>", "Earlier step to send the work back to (0-based index, step name or agent id)").action((runId, opts, actionCmd) => {
|
|
48756
50132
|
const root = resolveWorkspaceRoot(actionCmd);
|
|
48757
50133
|
const state = requireRun(root, runId);
|
|
48758
50134
|
const pipeline = requirePipelineForRun(root, state);
|
|
50135
|
+
const idx = state.currentStepIdx;
|
|
50136
|
+
let targetIdx;
|
|
50137
|
+
if (opts.to !== void 0) {
|
|
50138
|
+
targetIdx = requireStepIdx(state, opts.to);
|
|
50139
|
+
if (targetIdx >= idx) {
|
|
50140
|
+
console.error(import_chalk10.default.red(
|
|
50141
|
+
`--to must name a step before the rejected one (${idx}:${state.steps[idx].agent}), got ${targetIdx}:${state.steps[targetIdx].agent}.`
|
|
50142
|
+
));
|
|
50143
|
+
process.exit(1);
|
|
50144
|
+
}
|
|
50145
|
+
}
|
|
48759
50146
|
let next;
|
|
48760
50147
|
try {
|
|
48761
|
-
next = (0, import_core13.rejectStep)({ state, reason: opts.reason, pipeline });
|
|
50148
|
+
next = (0, import_core13.rejectStep)({ state, reason: opts.reason, targetIdx, pipeline });
|
|
48762
50149
|
} catch (err) {
|
|
48763
50150
|
console.error(import_chalk10.default.red(err instanceof Error ? err.message : String(err)));
|
|
48764
50151
|
process.exit(1);
|
|
48765
50152
|
}
|
|
48766
50153
|
saveRunState(root, next, state);
|
|
48767
|
-
const step = state.steps[
|
|
50154
|
+
const step = state.steps[idx];
|
|
50155
|
+
if (targetIdx !== void 0) {
|
|
50156
|
+
const target = next.steps[targetIdx];
|
|
50157
|
+
console.log(import_chalk10.default.red("\u2718") + ` Rejected "${step.agent}" \u2014 sent back to "${target.agent}" (rev ${target.revision})`);
|
|
50158
|
+
console.log(import_chalk10.default.dim(` Reason: ${opts.reason}`));
|
|
50159
|
+
console.log(import_chalk10.default.dim(` When done: aidlc run mark-done ${runId}`));
|
|
50160
|
+
printRunSummary(next);
|
|
50161
|
+
return;
|
|
50162
|
+
}
|
|
48768
50163
|
console.log(import_chalk10.default.red("\u2718") + ` Rejected "${step.agent}"`);
|
|
48769
50164
|
console.log(import_chalk10.default.dim(` Reason: ${opts.reason}`));
|
|
48770
50165
|
console.log(import_chalk10.default.dim(` Rerun: aidlc run rerun ${runId} [--feedback "..."]`));
|
|
@@ -48867,7 +50262,7 @@ function registerRun(program3) {
|
|
|
48867
50262
|
console.log(JSON.stringify(state, null, 2));
|
|
48868
50263
|
});
|
|
48869
50264
|
cmd.command("exec <runId>").description(
|
|
48870
|
-
"Execute the current step by spawning the claude CLI, then auto-advance.\n Streams output live. Stops at human_review steps unless --auto-approve.\n Exit codes: 0 completed (or stopped at --until), 2 paused on a gate\n (awaiting review / rejected / budget), 1 error. --require-complete maps\n
|
|
50265
|
+
"Execute the current step by spawning the claude CLI, then auto-advance.\n Streams output live. Stops at human_review steps unless --auto-approve.\n Exit codes: 0 completed (or stopped at --until), 2 paused on a gate\n (awaiting review / rejected / sent back max_send_backs times / no code\n change after a send-back or a batch / max_batches / pause_between_batches /\n budget / stopped), 1 error (a step that ran\n past its timeout_minutes included). --require-complete maps any\n non-completed outcome to 1 for CI gating.\n Ctrl+C once: stop after the running step. Twice: stop it now."
|
|
48871
50266
|
).option("--until <step>", "Stop after this step completes (index or agent id)").option("--auto-approve", "Also auto-approve human_review steps without pausing").option("--require-complete", "Exit 1 unless the run reaches completed (for CI gating)").option("--json", "Suppress decorative output; print a final JSON summary to stdout (claude stream goes to stderr)").option("--message <text>", "Override the user message sent to claude (default: context pairs)").option("--dry-run", "Print the assembled prompt without spawning claude").option("--skill <id>", "On steps that offer alternative skills (default_skill), run this one").action(async (runId, opts, actionCmd) => {
|
|
48872
50267
|
const root = resolveWorkspaceRoot(actionCmd);
|
|
48873
50268
|
if (opts.json) {
|
|
@@ -48974,12 +50369,38 @@ async function execLoop(root, runId, opts) {
|
|
|
48974
50369
|
const initialState = requireRun(root, runId);
|
|
48975
50370
|
const untilIdx = opts.until !== void 0 ? requireStepIdx(initialState, opts.until) : -1;
|
|
48976
50371
|
const claudeOut = opts.json ? process.stderr : process.stdout;
|
|
48977
|
-
|
|
48978
|
-
|
|
48979
|
-
|
|
48980
|
-
|
|
48981
|
-
|
|
48982
|
-
);
|
|
50372
|
+
let cancelRequested = false;
|
|
50373
|
+
const stopNow = new AbortController();
|
|
50374
|
+
const onSigint = () => {
|
|
50375
|
+
if (!cancelRequested) {
|
|
50376
|
+
cancelRequested = true;
|
|
50377
|
+
console.error(import_chalk10.default.yellow("\n\u23F9 Stopping after the running step finishes. Press Ctrl+C again to stop it now."));
|
|
50378
|
+
} else if (!stopNow.signal.aborted) {
|
|
50379
|
+
console.error(import_chalk10.default.yellow("\n\u23F9 Stopping the running step now\u2026"));
|
|
50380
|
+
stopNow.abort();
|
|
50381
|
+
} else {
|
|
50382
|
+
process.exit(130);
|
|
50383
|
+
}
|
|
50384
|
+
};
|
|
50385
|
+
process.on("SIGINT", onSigint);
|
|
50386
|
+
try {
|
|
50387
|
+
return await (0, import_core13.runExecLoop)(
|
|
50388
|
+
root,
|
|
50389
|
+
runId,
|
|
50390
|
+
{
|
|
50391
|
+
untilIdx,
|
|
50392
|
+
autoApprove: opts.autoApprove,
|
|
50393
|
+
message: opts.message,
|
|
50394
|
+
dryRun: opts.dryRun,
|
|
50395
|
+
skill: opts.skill,
|
|
50396
|
+
shouldCancel: () => cancelRequested,
|
|
50397
|
+
signal: stopNow.signal
|
|
50398
|
+
},
|
|
50399
|
+
cliExecHooks(runId, claudeOut)
|
|
50400
|
+
);
|
|
50401
|
+
} finally {
|
|
50402
|
+
process.off("SIGINT", onSigint);
|
|
50403
|
+
}
|
|
48983
50404
|
}
|
|
48984
50405
|
async function driveAutoReview(root, runId, state) {
|
|
48985
50406
|
const pipeline = requirePipelineForRun(root, state);
|
|
@@ -49079,6 +50500,35 @@ ${reason}`)),
|
|
|
49079
50500
|
\u2718 Step "${e.agent}" was rejected.`));
|
|
49080
50501
|
info(import_chalk10.default.dim(` Rerun: aidlc run rerun ${e.runId} [--feedback "..."]`));
|
|
49081
50502
|
},
|
|
50503
|
+
onStepStopped: (e) => {
|
|
50504
|
+
info(import_chalk10.default.yellow(`
|
|
50505
|
+
\u23F9 Stopped "${e.agent}" mid-step (rev ${e.revision}). It is still awaiting work.`));
|
|
50506
|
+
info(import_chalk10.default.dim(" Anything it half-wrote is still in the working tree \u2014 check git status."));
|
|
50507
|
+
info(import_chalk10.default.dim(` Resume: aidlc run exec ${e.runId}`));
|
|
50508
|
+
},
|
|
50509
|
+
onCancelled: () => info(import_chalk10.default.yellow("\n\u23F9 Stopped after the step that was running.")),
|
|
50510
|
+
onStalled: (e) => {
|
|
50511
|
+
info(import_chalk10.default.yellow(`
|
|
50512
|
+
\u23F8 ${e.reason}`));
|
|
50513
|
+
info(import_chalk10.default.dim(` What it was asked, and what it did: aidlc run report ${e.runId}`));
|
|
50514
|
+
info(import_chalk10.default.dim(` Then make the change and: aidlc run mark-done ${e.runId} \u2014 or try again: aidlc run exec ${e.runId}`));
|
|
50515
|
+
},
|
|
50516
|
+
onBatchDone: (e) => {
|
|
50517
|
+
sep4();
|
|
50518
|
+
info(import_chalk10.default.cyan(`
|
|
50519
|
+
\u21BB Batch ${e.batch} of "${e.agent}" done \u2014 starting the next in a fresh session.`));
|
|
50520
|
+
if (typeof e.costUsd === "number") {
|
|
50521
|
+
info(import_chalk10.default.dim(` cost: $${e.costUsd.toFixed(4)}`));
|
|
50522
|
+
}
|
|
50523
|
+
},
|
|
50524
|
+
onBatchPause: (e) => {
|
|
50525
|
+
info(import_chalk10.default.cyan(`
|
|
50526
|
+
\u23F8 Batch ${e.batch} of "${e.agent}" done; pausing (pause_between_batches).`));
|
|
50527
|
+
if (e.report) {
|
|
50528
|
+
info(import_chalk10.default.dim(` Progress: ${e.report}`));
|
|
50529
|
+
}
|
|
50530
|
+
info(import_chalk10.default.dim(` Next batch: aidlc run exec ${e.runId}`));
|
|
50531
|
+
},
|
|
49082
50532
|
onStepSkipped: (e) => {
|
|
49083
50533
|
info(import_chalk10.default.yellow(`
|
|
49084
50534
|
\u2933 Step "${e.agent}" was rejected \u2014 carrying on.`) + import_chalk10.default.dim(` ${e.reason}`));
|
|
@@ -49089,6 +50539,9 @@ ${reason}`)),
|
|
|
49089
50539
|
onAutoReviewResult: (e) => {
|
|
49090
50540
|
if (e.decision === "pass") {
|
|
49091
50541
|
info(import_chalk10.default.green("\u2714 Auto-review passed") + import_chalk10.default.dim(` \u2014 ${e.reason}`));
|
|
50542
|
+
} else if (e.sentBackTo) {
|
|
50543
|
+
const to = e.sentBackTo;
|
|
50544
|
+
info(import_chalk10.default.yellow(`\u21A9 Auto-review rejected \u2014 sent back to "${to.agent}" (rev ${to.revision}, send-back ${to.count} of ${to.max})`) + import_chalk10.default.dim(` \u2014 ${e.reason}`));
|
|
49092
50545
|
} else {
|
|
49093
50546
|
info(import_chalk10.default.red("\u2718 Auto-review rejected") + import_chalk10.default.dim(` \u2014 ${e.reason}`));
|
|
49094
50547
|
info(import_chalk10.default.dim(` Fix the issue, then: aidlc run rerun ${e.runId} [--feedback "..."]`));
|