looply-cli 0.5.10 → 0.5.11
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/dist/.src-hash +1 -1
- package/dist/autonomy-controller.d.ts +23 -1
- package/dist/autonomy-controller.d.ts.map +1 -1
- package/dist/autonomy-controller.js +50 -9
- package/dist/autonomy-controller.js.map +1 -1
- package/dist/autonomy-store.d.ts +33 -1
- package/dist/autonomy-store.d.ts.map +1 -1
- package/dist/autonomy-store.js +58 -8
- package/dist/autonomy-store.js.map +1 -1
- package/dist/autonomy-tick.d.ts +23 -1
- package/dist/autonomy-tick.d.ts.map +1 -1
- package/dist/autonomy-tick.js +80 -14
- package/dist/autonomy-tick.js.map +1 -1
- package/dist/bin.d.ts.map +1 -1
- package/dist/bin.js +25 -5
- package/dist/bin.js.map +1 -1
- package/dist/branch-delivery-wiring.d.ts.map +1 -1
- package/dist/branch-delivery-wiring.js +6 -1
- package/dist/branch-delivery-wiring.js.map +1 -1
- package/dist/branch-delivery.d.ts +135 -6
- package/dist/branch-delivery.d.ts.map +1 -1
- package/dist/branch-delivery.js +540 -80
- package/dist/branch-delivery.js.map +1 -1
- package/dist/branch-replay.d.ts +45 -0
- package/dist/branch-replay.d.ts.map +1 -0
- package/dist/branch-replay.js +123 -0
- package/dist/branch-replay.js.map +1 -0
- package/dist/commit-ownership.d.ts +102 -0
- package/dist/commit-ownership.d.ts.map +1 -0
- package/dist/commit-ownership.js +97 -0
- package/dist/commit-ownership.js.map +1 -0
- package/dist/coordinator-state.d.ts.map +1 -1
- package/dist/coordinator-state.js +21 -1
- package/dist/coordinator-state.js.map +1 -1
- package/dist/daemon-cmd.d.ts.map +1 -1
- package/dist/daemon-cmd.js +24 -3
- package/dist/daemon-cmd.js.map +1 -1
- package/dist/deliver-cmd.d.ts +18 -0
- package/dist/deliver-cmd.d.ts.map +1 -1
- package/dist/deliver-cmd.js +71 -5
- package/dist/deliver-cmd.js.map +1 -1
- package/dist/delivery-settings-cache.d.ts +15 -1
- package/dist/delivery-settings-cache.d.ts.map +1 -1
- package/dist/delivery-settings-cache.js +31 -3
- package/dist/delivery-settings-cache.js.map +1 -1
- package/dist/environment-hold.d.ts +69 -0
- package/dist/environment-hold.d.ts.map +1 -0
- package/dist/environment-hold.js +120 -0
- package/dist/environment-hold.js.map +1 -0
- package/dist/gate.d.ts.map +1 -1
- package/dist/gate.js +15 -1
- package/dist/gate.js.map +1 -1
- package/dist/github-api.d.ts +19 -0
- package/dist/github-api.d.ts.map +1 -1
- package/dist/github-api.js +26 -0
- package/dist/github-api.js.map +1 -1
- package/dist/goal-adaptive.d.ts +1 -0
- package/dist/goal-adaptive.d.ts.map +1 -1
- package/dist/goal-adaptive.js +26 -13
- package/dist/goal-adaptive.js.map +1 -1
- package/dist/goal-compile.d.ts +37 -0
- package/dist/goal-compile.d.ts.map +1 -1
- package/dist/goal-compile.js +25 -1
- package/dist/goal-compile.js.map +1 -1
- package/dist/goal-replay.d.ts +83 -0
- package/dist/goal-replay.d.ts.map +1 -0
- package/dist/goal-replay.js +121 -0
- package/dist/goal-replay.js.map +1 -0
- package/dist/goal-reproof.d.ts +5 -0
- package/dist/goal-reproof.d.ts.map +1 -1
- package/dist/goal-reproof.js +11 -4
- package/dist/goal-reproof.js.map +1 -1
- package/dist/grant-pause.d.ts +48 -0
- package/dist/grant-pause.d.ts.map +1 -0
- package/dist/grant-pause.js +103 -0
- package/dist/grant-pause.js.map +1 -0
- package/dist/grant-reconcile.d.ts +8 -2
- package/dist/grant-reconcile.d.ts.map +1 -1
- package/dist/grant-reconcile.js +9 -2
- package/dist/grant-reconcile.js.map +1 -1
- package/dist/grant-waiting-wiring.d.ts +49 -0
- package/dist/grant-waiting-wiring.d.ts.map +1 -0
- package/dist/grant-waiting-wiring.js +77 -0
- package/dist/grant-waiting-wiring.js.map +1 -0
- package/dist/planner-timeouts.d.ts +14 -0
- package/dist/planner-timeouts.d.ts.map +1 -0
- package/dist/planner-timeouts.js +51 -0
- package/dist/planner-timeouts.js.map +1 -0
- package/dist/run-cmd.d.ts +12 -1
- package/dist/run-cmd.d.ts.map +1 -1
- package/dist/run-cmd.js +146 -10
- package/dist/run-cmd.js.map +1 -1
- package/dist/run-refusal-marks.d.ts +7 -1
- package/dist/run-refusal-marks.d.ts.map +1 -1
- package/dist/run-refusal-marks.js +4 -0
- package/dist/run-refusal-marks.js.map +1 -1
- package/dist/server-client.d.ts +15 -1
- package/dist/server-client.d.ts.map +1 -1
- package/dist/server-client.js +17 -0
- package/dist/server-client.js.map +1 -1
- package/dist/start-attempts.d.ts +4 -2
- package/dist/start-attempts.d.ts.map +1 -1
- package/dist/start-attempts.js +6 -1
- package/dist/start-attempts.js.map +1 -1
- package/package.json +2 -2
package/dist/run-cmd.js
CHANGED
|
@@ -63,9 +63,13 @@ const programme_mode_1 = require("./programme-mode");
|
|
|
63
63
|
const partial_asker_1 = require("./partial-asker");
|
|
64
64
|
const goal_ownership_1 = require("./goal-ownership");
|
|
65
65
|
const goal_compile_1 = require("./goal-compile");
|
|
66
|
+
const planner_timeouts_1 = require("./planner-timeouts");
|
|
66
67
|
const plan_recovery_1 = require("./plan-recovery");
|
|
67
68
|
const goal_execution_evidence_1 = require("./goal-execution-evidence");
|
|
68
69
|
const goal_reproof_1 = require("./goal-reproof");
|
|
70
|
+
const goal_replay_1 = require("./goal-replay");
|
|
71
|
+
const branch_replay_1 = require("./branch-replay");
|
|
72
|
+
const run_base_2 = require("./run-base");
|
|
69
73
|
const round_records_1 = require("./round-records");
|
|
70
74
|
const goal_gap_1 = require("./goal-gap");
|
|
71
75
|
const goal_adaptive_1 = require("./goal-adaptive");
|
|
@@ -128,6 +132,7 @@ class RunRefused extends Error {
|
|
|
128
132
|
code;
|
|
129
133
|
branch;
|
|
130
134
|
delivery;
|
|
135
|
+
environment;
|
|
131
136
|
/**
|
|
132
137
|
* The same refusal, for a machine.
|
|
133
138
|
*
|
|
@@ -152,11 +157,17 @@ class RunRefused extends Error {
|
|
|
152
157
|
* delivering run, the commit, and each required step's outcome. Carried to
|
|
153
158
|
* the mark so the daemon can settle the pursuit with facts, not a sentence.
|
|
154
159
|
*/
|
|
155
|
-
delivery
|
|
160
|
+
delivery,
|
|
161
|
+
/**
|
|
162
|
+
* Which machine fault, on an `environment` refusal only — carried to the mark so the
|
|
163
|
+
* controller's hold names it (`environment-hold.ts`).
|
|
164
|
+
*/
|
|
165
|
+
environment) {
|
|
156
166
|
super(message);
|
|
157
167
|
this.code = code;
|
|
158
168
|
this.branch = branch;
|
|
159
169
|
this.delivery = delivery;
|
|
170
|
+
this.environment = environment;
|
|
160
171
|
}
|
|
161
172
|
}
|
|
162
173
|
exports.RunRefused = RunRefused;
|
|
@@ -1024,6 +1035,9 @@ async function runLoop(opts) {
|
|
|
1024
1035
|
* ⚠️ AN ARROW, for the same flow-analysis reason as `recordDelivery` below.
|
|
1025
1036
|
*/
|
|
1026
1037
|
const deliveringBranch = async () => {
|
|
1038
|
+
// The branch this goal's work was REBUILT onto, when it was: that is the tree that was proved.
|
|
1039
|
+
if (rebuiltAs !== null)
|
|
1040
|
+
return rebuiltAs.branch;
|
|
1027
1041
|
if (deliveringRunId === null)
|
|
1028
1042
|
return branch;
|
|
1029
1043
|
const cut = (0, run_delivery_1.deliveringBranchOf)((0, lane_claims_1.readLaneClaims)(cwd), deliveringRunId);
|
|
@@ -2802,7 +2816,31 @@ async function runLoop(opts) {
|
|
|
2802
2816
|
* would put sixty minutes of verifier inside a sixty-minute window. They draw
|
|
2803
2817
|
* from one budget instead.
|
|
2804
2818
|
*/
|
|
2805
|
-
|
|
2819
|
+
/**
|
|
2820
|
+
* THE PLANNING TIER (`goal-compile.ts`, COMPILE_TIERS): after a timed-out planning of this goal
|
|
2821
|
+
* version, a longer limit and a smaller plan, so the worst case stays inside the window. The
|
|
2822
|
+
* verify budget shrinks with the plan — that is what pays for the longer compile.
|
|
2823
|
+
*/
|
|
2824
|
+
// PROJECT-scoped: a goal's next Start may be placed in another checkout, and must still know.
|
|
2825
|
+
const plannedTimeouts = binding.kind === 'bound' ? (0, planner_timeouts_1.plannerTimeoutsFor)(projectStateDirPath, `${binding.goal.id}@${binding.goal.version}`) : 0;
|
|
2826
|
+
const compileTier = (0, goal_compile_1.compileTierFor)(plannedTimeouts);
|
|
2827
|
+
const adaptiveTier = (0, goal_compile_1.compileTierFor)(plannedTimeouts, goal_compile_1.ADAPTIVE_COMPILE_TIERS);
|
|
2828
|
+
let compileTimedOut = false;
|
|
2829
|
+
/**
|
|
2830
|
+
* A PLANNER THAT RAN OUT OF TIME IS THE MACHINE'S LIMIT, NOT THE GOAL'S FAULT: the run leaves
|
|
2831
|
+
* with `environment` / `planner_timeout`, so the controller voids this Start (it costs no try),
|
|
2832
|
+
* and the timeout is counted so the next Start plans with the next tier. Null when no planning
|
|
2833
|
+
* timed out in this run — the exit is then whatever it was.
|
|
2834
|
+
*/
|
|
2835
|
+
const plannerTimedOut = (message) => {
|
|
2836
|
+
if (!compileTimedOut || binding.kind !== 'bound')
|
|
2837
|
+
return null;
|
|
2838
|
+
const n = (0, planner_timeouts_1.notePlannerTimeout)(projectStateDirPath, `${binding.goal.id}@${binding.goal.version}`);
|
|
2839
|
+
const next = (0, goal_compile_1.compileTierFor)(n);
|
|
2840
|
+
return new RunRefused(`${message} — planning took longer than its limit; the next Start plans with ${Math.round(next.timeoutMs / 60000)} minutes ` +
|
|
2841
|
+
`for at most ${next.maxSteps} steps, and this Start does not count`, 'environment', undefined, undefined, 'planner_timeout');
|
|
2842
|
+
};
|
|
2843
|
+
let verifyBudget = Math.min(verify_cmd_2.VERIFY_MAX_PER_RUN, compileTier.maxSteps);
|
|
2806
2844
|
/**
|
|
2807
2845
|
* EVERYTHING A START DOES BEFORE THE RUN, under one guard.
|
|
2808
2846
|
*
|
|
@@ -2882,6 +2920,10 @@ async function runLoop(opts) {
|
|
|
2882
2920
|
let deliveringRunId = null;
|
|
2883
2921
|
// L4b: the commit key 2 confirmed HEAD on, beside the run that delivered it.
|
|
2884
2922
|
let deliveringSha = null;
|
|
2923
|
+
/** This goal's work, rebuilt onto the base for the goal check (`goal-replay.ts`), when it was. */
|
|
2924
|
+
let rebuiltAs = null;
|
|
2925
|
+
/** Why it could not be rebuilt, when that was tried and failed: what the next revision plans around. */
|
|
2926
|
+
let replayTrouble = null;
|
|
2885
2927
|
/** F27: the tree this Start's evaluator judged, when a programme moved HEAD to the tree the lane holds. */
|
|
2886
2928
|
let judged = { kind: 'as-is', because: 'no goal-met check ran' };
|
|
2887
2929
|
/** The first compile's authority answer, kept so its reason is the acted-on one. */
|
|
@@ -2927,11 +2969,16 @@ async function runLoop(opts) {
|
|
|
2927
2969
|
checks: config.gates.map((g) => g.name),
|
|
2928
2970
|
}),
|
|
2929
2971
|
}, {
|
|
2930
|
-
compile: (i) =>
|
|
2972
|
+
compile: async (i) => {
|
|
2973
|
+
const out = await (0, goal_compile_1.compileGoal)(i, { invoke: planAgent, timeoutMs: compileTier.timeoutMs, maxSteps: compileTier.maxSteps });
|
|
2974
|
+
if (!out.ok && out.failure === 'timed-out')
|
|
2975
|
+
compileTimedOut = true;
|
|
2976
|
+
return out;
|
|
2977
|
+
},
|
|
2931
2978
|
// M3-2: checked at the committed tree before any step becomes an item; the compile recorded either way.
|
|
2932
2979
|
check: (steps) => (0, compile_check_1.checkCompiledPlan)(steps, compileReaders, compiledAt),
|
|
2933
2980
|
log: (line) => log(`compile : ${line}`),
|
|
2934
|
-
},
|
|
2981
|
+
}, compileTier.maxSteps);
|
|
2935
2982
|
// A step whose citation did not hold is re-planned, an empty plan is asked again as an instruction,
|
|
2936
2983
|
// and only then does a ticket get one direct step (`plan-recovery.ts`) — never a hand-back.
|
|
2937
2984
|
const compiled = recovered.compiled;
|
|
@@ -3193,6 +3240,53 @@ async function runLoop(opts) {
|
|
|
3193
3240
|
}
|
|
3194
3241
|
log(`goal : judging ${(0, goal_met_target_1.describeTarget)(judged)}`);
|
|
3195
3242
|
}
|
|
3243
|
+
/**
|
|
3244
|
+
* THE CODE MOVED AWAY FROM THIS GOAL'S WORK: REBUILD IT ONTO THE BASE, THEN JUDGE THAT TREE
|
|
3245
|
+
* (`goal-replay.ts`, owner ruling 2026-10-16). In a checkout Looply made, when HEAD holds none
|
|
3246
|
+
* of this plan's commits, they are replayed onto the base as a fresh run branch BEFORE the
|
|
3247
|
+
* evaluator looks — so the verdict and the gates are about the same tree, and the branch holds
|
|
3248
|
+
* only this goal's work. A replay that does not apply puts HEAD back; KEY 2 then plans what is
|
|
3249
|
+
* missing instead of refusing (`replan`).
|
|
3250
|
+
*/
|
|
3251
|
+
if (judged.kind === 'as-is' && (0, reaper_1.hasProvisionedMarker)(cwd)) {
|
|
3252
|
+
const rounds = await (0, round_records_1.readRoundRecords)(stateDir, ledger_store_1.nodeLedgerFs);
|
|
3253
|
+
if (rounds.ok) {
|
|
3254
|
+
const committed = (0, goal_execution_evidence_1.committedShasOf)({ scope: askedScope, items: owned, rounds: rounds.rounds });
|
|
3255
|
+
const aligned = await (0, goal_replay_1.alignWithOwnWork)({
|
|
3256
|
+
headSha: () => git.headSha(),
|
|
3257
|
+
changedPaths: () => git.changedPaths(),
|
|
3258
|
+
isAncestor: (a, of) => git.isAncestor(a, of),
|
|
3259
|
+
baseRef: async () => (await (0, run_base_2.resolveBaseBranch)(git, config.run.baseBranch).catch(() => null))?.ref ?? null,
|
|
3260
|
+
commitOf: (ref) => git.commitOf(ref),
|
|
3261
|
+
// The same patch replay the delivery rebuild uses: never a 3-way merge (`branch-replay.ts`).
|
|
3262
|
+
replay: (base, shas) => (0, branch_replay_1.replayOnto)((0, git_driver_1.nodeGitExec)(cwd), (dir) => (0, git_driver_1.nodeGitExec)(dir), base, shas),
|
|
3263
|
+
commitsBetween: async (base, sha) => (await (0, git_driver_1.nodeGitExec)(cwd)(['rev-list', '--reverse', `${base}..${sha}`])).stdout.split(/\r?\n/).filter((l) => l.trim() !== ''),
|
|
3264
|
+
createBranch: (name, from) => git.createBranch(name, from),
|
|
3265
|
+
}, { committed, branch: `${branch}-rebuilt`, aliases: (0, goal_replay_1.replayedAs)(projectStateDirPath, goalId) });
|
|
3266
|
+
if (aligned.kind === 'rebuilt') {
|
|
3267
|
+
(0, goal_replay_1.recordReplay)(projectStateDirPath, goalId, aligned.picked);
|
|
3268
|
+
(0, run_base_1.writeCheckoutGoal)(stateDir, { goalId, branch: aligned.branch, at: new Date().toISOString() });
|
|
3269
|
+
(0, lane_claims_1.recordLaneClaim)(cwd, {
|
|
3270
|
+
schema: lane_claims_1.LANE_CLAIMS_SCHEMA,
|
|
3271
|
+
kind: 'claims',
|
|
3272
|
+
at: new Date().toISOString(),
|
|
3273
|
+
branch: aligned.branch,
|
|
3274
|
+
runId,
|
|
3275
|
+
goalId,
|
|
3276
|
+
goalVersion: bound.version,
|
|
3277
|
+
planRevision: revision,
|
|
3278
|
+
servings: [],
|
|
3279
|
+
workspace: cwd,
|
|
3280
|
+
});
|
|
3281
|
+
rebuiltAs = { branch: aligned.branch, head: aligned.head };
|
|
3282
|
+
log(`goal : this goal's ${committed.length} commit(s) were not in the tree here — rebuilt onto ${aligned.base} as ${aligned.branch}; judging that`);
|
|
3283
|
+
}
|
|
3284
|
+
else if (aligned.kind === 'failed') {
|
|
3285
|
+
replayTrouble = aligned.because;
|
|
3286
|
+
log(`goal : ${aligned.because}`);
|
|
3287
|
+
}
|
|
3288
|
+
}
|
|
3289
|
+
}
|
|
3196
3290
|
adaptive = await (0, goal_adaptive_1.decideAdaptive)({
|
|
3197
3291
|
goalId: scope.goalId,
|
|
3198
3292
|
goalVersion: bound.version,
|
|
@@ -3233,10 +3327,19 @@ async function runLoop(opts) {
|
|
|
3233
3327
|
compile: async (i, maxSteps) => {
|
|
3234
3328
|
const at = await git.headTreeSha().catch(() => null);
|
|
3235
3329
|
const recovered = await (0, plan_recovery_1.compileWithRecovery)(i, {
|
|
3236
|
-
compile: (j) =>
|
|
3330
|
+
compile: async (j) => {
|
|
3331
|
+
const out = await (0, goal_compile_1.compileGoal)(j, {
|
|
3332
|
+
invoke: planAgent,
|
|
3333
|
+
maxSteps: Math.min(maxSteps, adaptiveTier.maxSteps),
|
|
3334
|
+
timeoutMs: adaptiveTier.timeoutMs,
|
|
3335
|
+
});
|
|
3336
|
+
if (!out.ok && out.failure === 'timed-out')
|
|
3337
|
+
compileTimedOut = true;
|
|
3338
|
+
return out;
|
|
3339
|
+
},
|
|
3237
3340
|
check: (steps) => (0, compile_check_1.checkCompiledPlan)(steps, compileReaders, at),
|
|
3238
3341
|
log: (line) => log(`goal : ${line}`),
|
|
3239
|
-
}, maxSteps);
|
|
3342
|
+
}, Math.min(maxSteps, adaptiveTier.maxSteps));
|
|
3240
3343
|
return recovered.compiled;
|
|
3241
3344
|
},
|
|
3242
3345
|
changedPaths: () => git.changedPaths(),
|
|
@@ -3272,16 +3375,47 @@ async function runLoop(opts) {
|
|
|
3272
3375
|
*/
|
|
3273
3376
|
if (!confirmed.ok && confirmed.moved === true && judged.kind !== 'carried') {
|
|
3274
3377
|
log('goal : the code moved on since this plan was delivered — running the gates again at the current tree');
|
|
3378
|
+
let reproofVerdict = null;
|
|
3275
3379
|
const again = await (0, goal_reproof_1.reproveAtHead)(head, (0, goal_execution_evidence_1.committedShasOf)(key2Input), {
|
|
3276
3380
|
changedPaths: () => git.changedPaths(),
|
|
3277
3381
|
isAncestor: (a, of) => git.isAncestor(a, of),
|
|
3278
3382
|
changedPathsBetween: (from, to) => git.changedPathsBetween(from, to),
|
|
3279
|
-
runGates: async (paths) =>
|
|
3383
|
+
runGates: async (paths) => {
|
|
3384
|
+
const gate = await (0, gate_1.runGate)({ steps: config.gates, changedPaths: paths, runner: (0, untrusted_gate_1.makeUntrustedGateRunner)(cwd) });
|
|
3385
|
+
reproofVerdict = gate.verdict;
|
|
3386
|
+
return gate.steps;
|
|
3387
|
+
},
|
|
3388
|
+
aliases: (0, goal_replay_1.replayedAs)(projectStateDirPath, goalId),
|
|
3280
3389
|
});
|
|
3281
3390
|
confirmed = again.ok
|
|
3282
3391
|
? (0, goal_execution_evidence_1.confirmGoalExecutionEvidence)({ ...key2Input, rechecked: { contains: again.contains, steps: again.steps } })
|
|
3283
3392
|
: { ok: false, because: `${goal_execution_evidence_1.CODE_MOVED_ON}, and it could not be checked again: ${again.because}` };
|
|
3284
3393
|
log(`goal : ${confirmed.ok ? 'the gates pass at the current tree, and this plan’s work is in it' : confirmed.because}`);
|
|
3394
|
+
if (!confirmed.ok) {
|
|
3395
|
+
/**
|
|
3396
|
+
* NEVER A HAND-BACK FOR THIS (owner ruling 2026-10-16). Three answers, none of them a
|
|
3397
|
+
* person's question:
|
|
3398
|
+
* - the gate could not RUN here (sandbox, tool): the machine's fault — retryable, and
|
|
3399
|
+
* the run's words name it, so the Start is voided (`environment`);
|
|
3400
|
+
* - the tree has uncommitted changes: not this run's to judge — retryable;
|
|
3401
|
+
* - the gates are red here, or the work is not in this tree (and could not be
|
|
3402
|
+
* rebuilt onto the base): a gap the work can close — the next revision plans it.
|
|
3403
|
+
*/
|
|
3404
|
+
if (reproofVerdict === 'blocked') {
|
|
3405
|
+
return {
|
|
3406
|
+
ok: false,
|
|
3407
|
+
reason: `gate blocked: step could not run — the environment is unavailable, not the change (${confirmed.because})`,
|
|
3408
|
+
unknown: true,
|
|
3409
|
+
};
|
|
3410
|
+
}
|
|
3411
|
+
if (!again.ok && /uncommitted change/.test(again.because))
|
|
3412
|
+
return { ok: false, reason: again.because, unknown: true };
|
|
3413
|
+
return {
|
|
3414
|
+
ok: false,
|
|
3415
|
+
reason: replayTrouble === null ? confirmed.because : `${confirmed.because} (${replayTrouble})`,
|
|
3416
|
+
replan: true,
|
|
3417
|
+
};
|
|
3418
|
+
}
|
|
3285
3419
|
}
|
|
3286
3420
|
/**
|
|
3287
3421
|
* 🔴 WHAT KEY 2 SAW, KEPT FOR THE FOURTH KEY.
|
|
@@ -3295,7 +3429,8 @@ async function runLoop(opts) {
|
|
|
3295
3429
|
*/
|
|
3296
3430
|
if (confirmed.ok) {
|
|
3297
3431
|
deliveringRunId = confirmed.round.runId;
|
|
3298
|
-
|
|
3432
|
+
// A REBUILT tree delivers its own tip: the original round's commit is not in it.
|
|
3433
|
+
deliveringSha = rebuiltAs !== null ? rebuiltAs.head : (confirmed.round.sha ?? null);
|
|
3299
3434
|
key2Saw = {
|
|
3300
3435
|
delivered: new Set(confirmed.delivered),
|
|
3301
3436
|
checks: new Map((confirmed.reproved ?? confirmed.round.gate?.steps ?? []).map((st) => [
|
|
@@ -3575,7 +3710,7 @@ async function runLoop(opts) {
|
|
|
3575
3710
|
await releaseHold();
|
|
3576
3711
|
// The branch the controller will ask the lane about: the one that delivered (F20).
|
|
3577
3712
|
const refusedOn = deliveredOn;
|
|
3578
|
-
throw said.terminal ? new RunRefused(said.message, said.code, refusedOn, delivery) : new Error(said.message);
|
|
3713
|
+
throw said.terminal ? new RunRefused(said.message, said.code, refusedOn, delivery) : (plannerTimedOut(said.message) ?? new Error(said.message));
|
|
3579
3714
|
}
|
|
3580
3715
|
}
|
|
3581
3716
|
const left = scope === null ? null : (0, core_1.workLeft)(runQueue.list());
|
|
@@ -3603,7 +3738,8 @@ async function runLoop(opts) {
|
|
|
3603
3738
|
throw new RunRefused(`nothing here can move without you — ${(0, queue_summary_1.describeNoReady)(runQueue.list())}`, 'human_required');
|
|
3604
3739
|
}
|
|
3605
3740
|
await releaseHold();
|
|
3606
|
-
|
|
3741
|
+
const nothing = `nothing to do — ${(0, queue_summary_1.describeNoReady)(runQueue.list())}`;
|
|
3742
|
+
throw plannerTimedOut(compileNote === null ? nothing : `${nothing} (${compileNote})`) ?? new Error(nothing);
|
|
3607
3743
|
}
|
|
3608
3744
|
/**
|
|
3609
3745
|
* THE APPROVAL BOUNDARY, AND THE ONLY PLACE IT COULD LIVE.
|