@miller-tech/uap 1.154.0 → 1.156.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/cli/deliver.d.ts +1 -18
- package/dist/cli/deliver.d.ts.map +1 -1
- package/dist/cli/deliver.js +73 -167
- package/dist/cli/deliver.js.map +1 -1
- package/dist/delivery/agentic-executor.d.ts.map +1 -1
- package/dist/delivery/agentic-executor.js +7 -4
- package/dist/delivery/agentic-executor.js.map +1 -1
- package/dist/delivery/context-budget.d.ts +32 -3
- package/dist/delivery/context-budget.d.ts.map +1 -1
- package/dist/delivery/context-budget.js +33 -3
- package/dist/delivery/context-budget.js.map +1 -1
- package/dist/delivery/convergence-loop.js +2 -2
- package/dist/delivery/convergence-loop.js.map +1 -1
- package/dist/delivery/epic-controller.d.ts +18 -0
- package/dist/delivery/epic-controller.d.ts.map +1 -1
- package/dist/delivery/epic-controller.js +24 -1
- package/dist/delivery/epic-controller.js.map +1 -1
- package/dist/delivery/epic-mission.d.ts +31 -0
- package/dist/delivery/epic-mission.d.ts.map +1 -1
- package/dist/delivery/epic-mission.js +21 -2
- package/dist/delivery/epic-mission.js.map +1 -1
- package/dist/delivery/index.d.ts +3 -0
- package/dist/delivery/index.d.ts.map +1 -1
- package/dist/delivery/index.js +3 -0
- package/dist/delivery/index.js.map +1 -1
- package/dist/delivery/mission-acceptance.d.ts +61 -0
- package/dist/delivery/mission-acceptance.d.ts.map +1 -0
- package/dist/delivery/mission-acceptance.js +107 -0
- package/dist/delivery/mission-acceptance.js.map +1 -0
- package/dist/delivery/run-state.d.ts +9 -4
- package/dist/delivery/run-state.d.ts.map +1 -1
- package/dist/delivery/run-state.js +9 -0
- package/dist/delivery/run-state.js.map +1 -1
- package/dist/delivery/spec-registry.d.ts +72 -0
- package/dist/delivery/spec-registry.d.ts.map +1 -0
- package/dist/delivery/spec-registry.js +80 -0
- package/dist/delivery/spec-registry.js.map +1 -0
- package/package.json +1 -1
- package/src/policies/enforcers/__pycache__/_common.cpython-312.pyc +0 -0
- package/templates/hooks/__pycache__/deliver_autoroute.cpython-312.pyc +0 -0
- package/tools/agents/scripts/__pycache__/toolcall_path_normalizer.cpython-312.pyc +0 -0
package/dist/cli/deliver.d.ts
CHANGED
|
@@ -6,19 +6,6 @@
|
|
|
6
6
|
* test, lint) until all required gates pass or the turn budget is exhausted.
|
|
7
7
|
*/
|
|
8
8
|
import type { TaskComplexity } from '../models/types.js';
|
|
9
|
-
import { type AcceptanceResult } from '../delivery/acceptance-judge.js';
|
|
10
|
-
/**
|
|
11
|
-
* Map an acceptance verdict to a loop gate result, honoring primary vs secondary
|
|
12
|
-
* mode. PURE — unit-tested in isolation from the model call.
|
|
13
|
-
*
|
|
14
|
-
* - Genuine fully-met verdict → pass.
|
|
15
|
-
* - PRIMARY (acceptance is the sole convergence target, no objective project
|
|
16
|
-
* gates): an inconclusive / no-evidence verdict is NOT "done" — fail so the
|
|
17
|
-
* loop keeps building (bounded by the ceiling). Prevents a vacuous turn-1
|
|
18
|
-
* "success" on an empty repo where the judge has nothing to evaluate.
|
|
19
|
-
* - SECONDARY (real objective gates exist): fail OPEN on judge flakiness — a
|
|
20
|
-
* green objective delivery is never blocked by the judge's nondeterminism.
|
|
21
|
-
*/
|
|
22
9
|
/**
|
|
23
10
|
* Decide how deliver establishes its convergence target when (or whether) the
|
|
24
11
|
* project exposes objective gates. PURE — unit-tested. See call site for the
|
|
@@ -64,11 +51,7 @@ export declare function resolveEvaluatorPreset(opts: {
|
|
|
64
51
|
generatorPreset: string;
|
|
65
52
|
envEvaluator?: string;
|
|
66
53
|
}): string | null;
|
|
67
|
-
export
|
|
68
|
-
passed: boolean;
|
|
69
|
-
feedback: string;
|
|
70
|
-
score?: number;
|
|
71
|
-
};
|
|
54
|
+
export { resolveAcceptanceVerdict } from '../delivery/mission-acceptance.js';
|
|
72
55
|
import type { AutoPlan } from '../delivery/auto-optimizer.js';
|
|
73
56
|
export interface DeliverOptions {
|
|
74
57
|
maxTurns?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deliver.d.ts","sourceRoot":"","sources":["../../src/cli/deliver.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAqBH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"deliver.d.ts","sourceRoot":"","sources":["../../src/cli/deliver.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/deliver.js
CHANGED
|
@@ -20,21 +20,9 @@ import { RoutingPresets, resolvePresetModel } from '../models/types.js';
|
|
|
20
20
|
import { measureQueryComplexity } from '../utils/query-complexity.js';
|
|
21
21
|
import { authorAcceptanceGate } from '../delivery/self-gate.js';
|
|
22
22
|
import { applyPendingIntents } from '../delivery/pending-intents.js';
|
|
23
|
-
import { runAcceptanceGate
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
/**
|
|
27
|
-
* Map an acceptance verdict to a loop gate result, honoring primary vs secondary
|
|
28
|
-
* mode. PURE — unit-tested in isolation from the model call.
|
|
29
|
-
*
|
|
30
|
-
* - Genuine fully-met verdict → pass.
|
|
31
|
-
* - PRIMARY (acceptance is the sole convergence target, no objective project
|
|
32
|
-
* gates): an inconclusive / no-evidence verdict is NOT "done" — fail so the
|
|
33
|
-
* loop keeps building (bounded by the ceiling). Prevents a vacuous turn-1
|
|
34
|
-
* "success" on an empty repo where the judge has nothing to evaluate.
|
|
35
|
-
* - SECONDARY (real objective gates exist): fail OPEN on judge flakiness — a
|
|
36
|
-
* green objective delivery is never blocked by the judge's nondeterminism.
|
|
37
|
-
*/
|
|
23
|
+
import { runAcceptanceGate } from '../delivery/acceptance-judge.js';
|
|
24
|
+
import { buildMissionAcceptanceGate, resolveAcceptanceVerdict } from '../delivery/mission-acceptance.js';
|
|
25
|
+
import { createSpecRegistry } from '../delivery/spec-registry.js';
|
|
38
26
|
/**
|
|
39
27
|
* Decide how deliver establishes its convergence target when (or whether) the
|
|
40
28
|
* project exposes objective gates. PURE — unit-tested. See call site for the
|
|
@@ -72,32 +60,16 @@ export function resolveEvaluatorPreset(opts) {
|
|
|
72
60
|
return null;
|
|
73
61
|
return wanted;
|
|
74
62
|
}
|
|
75
|
-
export
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
const gaps = `ACCEPTANCE GAPS — implement these to complete the spec:\n${formatAcceptanceReport(r)}`;
|
|
79
|
-
if (acceptancePrimary) {
|
|
80
|
-
if (r.parseError) {
|
|
81
|
-
// No-evidence / unparseable: not done, and NOT progress. Omit the score —
|
|
82
|
-
// runAcceptanceGate reports score:1 on its fail-open paths, which would
|
|
83
|
-
// otherwise saturate the loop's acceptance-progress (bestAcceptance) and
|
|
84
|
-
// mask real per-criterion gains on later turns.
|
|
85
|
-
return {
|
|
86
|
-
passed: false,
|
|
87
|
-
feedback: `Acceptance inconclusive (${r.parseError}). Keep implementing the spec — ensure the source files exist and are complete.`,
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
return { passed: false, score: r.score, feedback: gaps };
|
|
91
|
-
}
|
|
92
|
-
return { passed: r.passed, score: r.score, feedback: r.passed ? '' : gaps };
|
|
93
|
-
}
|
|
63
|
+
// Legacy export surface: test/cli/acceptance-verdict.test.ts (and any external
|
|
64
|
+
// consumer) imports the verdict fold from deliver.js — keep the re-export.
|
|
65
|
+
export { resolveAcceptanceVerdict } from '../delivery/mission-acceptance.js';
|
|
94
66
|
import { createAgenticExecutor, noopApplier, selectExecutorMode, lockContractFiles } from '../delivery/agentic-executor.js';
|
|
95
67
|
import { createRepairEscalation } from '../delivery/repair-escalation.js';
|
|
96
68
|
import { clearStop, isStopRequested, loadRunState, newRunId, saveRunState } from '../delivery/run-state.js';
|
|
97
69
|
import { planDeliveryPhases, shouldDecompose } from '../delivery/decompose.js';
|
|
98
70
|
import { initLedger, markItem } from '../delivery/completion-ledger.js';
|
|
99
71
|
import { loadUapConfigRaw } from '../utils/config-loader.js';
|
|
100
|
-
import {
|
|
72
|
+
import { createUserValidationRunner, resolveUserValidationMode, synthesizeUserValidationRung, } from '../delivery/user-validation.js';
|
|
101
73
|
import { deriveUserPaths, loadUserPaths, mergeUserPaths, USER_PATHS_FILE } from '../delivery/user-paths.js';
|
|
102
74
|
/** Raw .uap.json reader usable before the main cfgRawEarly declaration. */
|
|
103
75
|
function cfgRawEarlyForUvFactory(projectRoot) {
|
|
@@ -1247,102 +1219,23 @@ async function runDeliver(instruction, options) {
|
|
|
1247
1219
|
}
|
|
1248
1220
|
// Phased missions re-point the judge at the current phase's goal — judging
|
|
1249
1221
|
// phase 1 against the FULL mission would fail every phase by construction.
|
|
1250
|
-
|
|
1251
|
-
//
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
//
|
|
1258
|
-
//
|
|
1259
|
-
//
|
|
1260
|
-
// current acceptance spec (epic) began. Incremented by the iteration hook,
|
|
1261
|
-
// reset wherever acceptanceSpec is re-pointed.
|
|
1262
|
-
// Per-ROOT under parallel dispatch: concurrent loops must not zero or
|
|
1263
|
-
// inflate each other's evidence (an inflated count could let the breaker
|
|
1264
|
-
// accept a task with zero writes of its own). projectRoot's entry is the
|
|
1265
|
-
// historic shared counter the phased/epic paths keep using.
|
|
1266
|
-
const writesByRoot = new Map();
|
|
1267
|
-
const evidenceFor = (root) => {
|
|
1268
|
-
let e = writesByRoot.get(root);
|
|
1269
|
-
if (!e) {
|
|
1270
|
-
e = { writes: 0 };
|
|
1271
|
-
writesByRoot.set(root, e);
|
|
1272
|
-
}
|
|
1273
|
-
return e;
|
|
1274
|
-
};
|
|
1275
|
-
const specChangeEvidence = evidenceFor(projectRoot);
|
|
1276
|
-
// Breaker state is per SPEC: one shared instance thrashes its current-spec
|
|
1277
|
-
// slot under parallel dispatch and can then never trip.
|
|
1278
|
-
const acceptanceFlipLimit = Number(process.env.UAP_DELIVER_ACCEPTANCE_FLIP_LIMIT ?? 2);
|
|
1279
|
-
const acceptanceBreakers = new Map();
|
|
1280
|
-
const breakerFor = (spec, root) => {
|
|
1281
|
-
let b = acceptanceBreakers.get(spec);
|
|
1282
|
-
if (!b) {
|
|
1283
|
-
if (acceptanceBreakers.size > 100)
|
|
1284
|
-
acceptanceBreakers.clear(); // runaway guard
|
|
1285
|
-
b = createAcceptanceChurnBreaker(acceptanceFlipLimit, () => evidenceFor(root).writes > 0);
|
|
1286
|
-
acceptanceBreakers.set(spec, b);
|
|
1287
|
-
}
|
|
1288
|
-
return b;
|
|
1289
|
-
};
|
|
1222
|
+
// Per-root specs, write evidence, and churn breakers live in the registry
|
|
1223
|
+
// (see src/delivery/spec-registry.ts for the parallel-dispatch semantics).
|
|
1224
|
+
const specs = createSpecRegistry({
|
|
1225
|
+
initialSpec: instruction,
|
|
1226
|
+
sharedRoot: projectRoot,
|
|
1227
|
+
flipLimit: Number(process.env.UAP_DELIVER_ACCEPTANCE_FLIP_LIMIT ?? 2),
|
|
1228
|
+
});
|
|
1229
|
+
// Judge composition (execution/visual gates in primary mode, per-root
|
|
1230
|
+
// spec resolution, churn breaker in secondary mode) lives in
|
|
1231
|
+
// src/delivery/mission-acceptance.ts; this stays a wiring decision.
|
|
1290
1232
|
const acceptanceGate = options.acceptance && !skipJudgeForSimple
|
|
1291
|
-
?
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
// redetected execution rung on later turns.
|
|
1298
|
-
let visualNote = '';
|
|
1299
|
-
if (acceptancePrimary) {
|
|
1300
|
-
const exec = await runExecutionGate(root);
|
|
1301
|
-
if (!exec.passed) {
|
|
1302
|
-
return {
|
|
1303
|
-
passed: false,
|
|
1304
|
-
feedback: `EXECUTION FAILED — the code must run before it can be accepted:\n${exec.outputTail}`,
|
|
1305
|
-
};
|
|
1306
|
-
}
|
|
1307
|
-
// Visual gate: watch the artifact RUN — blank canvas, static rAF
|
|
1308
|
-
// scene, or runtime errors during observation block acceptance, and
|
|
1309
|
-
// the observation summary becomes judge evidence (a code-evidence
|
|
1310
|
-
// judge cannot see a never-started animation; this can).
|
|
1311
|
-
const visual = await runVisualGate(root);
|
|
1312
|
-
if (!visual.skipped && !visual.passed) {
|
|
1313
|
-
return { passed: false, feedback: visual.feedback };
|
|
1314
|
-
}
|
|
1315
|
-
visualNote = visualRuntimeNote(visual);
|
|
1316
|
-
}
|
|
1317
|
-
// Secondary mode reaches this gate ONLY on turns whose objective
|
|
1318
|
-
// gates all passed — hand the judge that fact as evidence, so
|
|
1319
|
-
// requirements like "make the tests pass" are graded on the gate
|
|
1320
|
-
// result instead of speculated about from static code.
|
|
1321
|
-
const resolvedSpec = acceptanceSpecByRoot.get(root) ?? acceptanceSpec;
|
|
1322
|
-
const uvNote = buildUserPathsNote(root);
|
|
1323
|
-
const baseNote = acceptancePrimary
|
|
1324
|
-
? visualNote
|
|
1325
|
-
: 'Objective project gates (build/test suite) ALL PASSED on this turn — treat test/build-related requirements as objectively verified.';
|
|
1326
|
-
const runtimeNote = [baseNote, uvNote?.note].filter(Boolean).join(' ');
|
|
1327
|
-
const r = await runAcceptanceGate({
|
|
1328
|
-
spec: resolvedSpec,
|
|
1329
|
-
projectRoot: root,
|
|
1330
|
-
executor: verdictExecutor,
|
|
1331
|
-
...(runtimeNote ? { runtimeNote } : {}),
|
|
1332
|
-
});
|
|
1333
|
-
const verdict = resolveAcceptanceVerdict(r, acceptancePrimary);
|
|
1334
|
-
// Secondary mode only: this gate is reached exclusively on turns whose
|
|
1335
|
-
// objective gates ALL passed, so a bounded number of consecutive judge
|
|
1336
|
-
// rejections hands the verdict back to the gates instead of wedging.
|
|
1337
|
-
if (!acceptancePrimary) {
|
|
1338
|
-
const checked = breakerFor(resolvedSpec, root).check(resolvedSpec, verdict);
|
|
1339
|
-
if (checked.overridden) {
|
|
1340
|
-
console.log(chalk.yellow(' ⚖ acceptance: judge rejected consecutive objectively-green turns — accepting on gates (raise UAP_DELIVER_ACCEPTANCE_FLIP_LIMIT to let the judge argue longer)'));
|
|
1341
|
-
}
|
|
1342
|
-
return checked;
|
|
1343
|
-
}
|
|
1344
|
-
return verdict;
|
|
1345
|
-
}
|
|
1233
|
+
? buildMissionAcceptanceGate({
|
|
1234
|
+
primary: acceptancePrimary,
|
|
1235
|
+
specs,
|
|
1236
|
+
judgeExecutor: verdictExecutor,
|
|
1237
|
+
note: (line) => console.log(chalk.yellow(` ${line}`)),
|
|
1238
|
+
})
|
|
1346
1239
|
: undefined;
|
|
1347
1240
|
const seams = {
|
|
1348
1241
|
ladderRunner: tieredRunner,
|
|
@@ -1368,8 +1261,7 @@ async function runDeliver(instruction, options) {
|
|
|
1368
1261
|
: undefined;
|
|
1369
1262
|
return composeIterationHooks((record) => printProgress(record), (record) => {
|
|
1370
1263
|
// Feed the acceptance breaker's zero-diff guard.
|
|
1371
|
-
|
|
1372
|
-
evidenceFor(evidenceRoot).writes += record.filesApplied.length;
|
|
1264
|
+
specs.recordWrites(evidenceRoot, record.filesApplied.length);
|
|
1373
1265
|
return undefined;
|
|
1374
1266
|
}, (record) => haloTracer.onIteration(record), repair ? (record) => repair.onIteration(record) : undefined, coordinator ? (record) => coordinator.onIteration(record) : undefined, escalation ? (record) => escalation.onIteration(record) : undefined);
|
|
1375
1267
|
};
|
|
@@ -1474,9 +1366,13 @@ async function runDeliver(instruction, options) {
|
|
|
1474
1366
|
// single-session context thrash — and a trivial mission simply decomposes to
|
|
1475
1367
|
// one epic, so the wrapper is cheap. Disable per-run with --no-epics /
|
|
1476
1368
|
// UAP_DELIVER_EPICS=0 / `.uap.json` deliver.epics false|'off'. Never on
|
|
1477
|
-
// self-gate
|
|
1369
|
+
// self-gate. A resume re-enters the epic path ONLY when the interrupted
|
|
1370
|
+
// run was epic-kind: completed epics carry forward as prior summaries and
|
|
1371
|
+
// the mid-epic loop checkpoint is discarded (epics restart at the epic
|
|
1372
|
+
// boundary). Non-epic resumes stay on the cursor-honoring paths below.
|
|
1478
1373
|
const cfgEpics = cfgRaw.deliver?.epics;
|
|
1479
|
-
const epicsEnabled = !needsSelfGate &&
|
|
1374
|
+
const epicsEnabled = !needsSelfGate &&
|
|
1375
|
+
(!resumeState || resumeState.runnerKind === 'epic') &&
|
|
1480
1376
|
options.epics !== false &&
|
|
1481
1377
|
process.env.UAP_DELIVER_EPICS !== '0' &&
|
|
1482
1378
|
cfgEpics !== false && cfgEpics !== 'off';
|
|
@@ -1573,7 +1469,10 @@ async function runDeliver(instruction, options) {
|
|
|
1573
1469
|
// a silent de-escalation. Falls back to the normal executor when no
|
|
1574
1470
|
// stronger model is configured in this environment.
|
|
1575
1471
|
let runExecutor = executor;
|
|
1576
|
-
|
|
1472
|
+
// Epic-kind resumes never use runExecutor (fresh epic loops re-escalate on
|
|
1473
|
+
// their own) and discard the checkpoint at the dispatch — a re-bind message
|
|
1474
|
+
// here would falsely claim the escalation carried over.
|
|
1475
|
+
if (resumeCheckpoint?.modelEscalated && !epicsEnabled) {
|
|
1577
1476
|
if (escalateExecutor && !agentic) {
|
|
1578
1477
|
// Agentic runs keep their tool-loop executor: the blind escalation
|
|
1579
1478
|
// executor pairs with the noop applier and would never touch the repo.
|
|
@@ -1640,20 +1539,10 @@ async function runDeliver(instruction, options) {
|
|
|
1640
1539
|
: line.includes('parallel tasks:') || line.includes('post-merge verification')
|
|
1641
1540
|
? chalk.cyan(line)
|
|
1642
1541
|
: chalk.dim(line)),
|
|
1643
|
-
beginTaskSpec: (root, spec) =>
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
evidenceFor(root).writes = 0;
|
|
1648
|
-
},
|
|
1649
|
-
endTaskSpec: (root) => {
|
|
1650
|
-
acceptanceSpecByRoot.delete(root);
|
|
1651
|
-
// An in-tree task re-pointed the shared spec; restore the mission-
|
|
1652
|
-
// level spec so a later watch-ci re-converge never judges against a
|
|
1653
|
-
// stale task prompt.
|
|
1654
|
-
if (root === projectRoot)
|
|
1655
|
-
acceptanceSpec = missionText;
|
|
1656
|
-
},
|
|
1542
|
+
beginTaskSpec: (root, spec) => specs.begin(root, spec),
|
|
1543
|
+
// Restore the mission-level spec after an in-tree task so a later
|
|
1544
|
+
// watch-ci re-converge never judges against a stale task prompt.
|
|
1545
|
+
endTaskSpec: (root) => specs.end(root, missionText),
|
|
1657
1546
|
openTask: (title) => openDeliveryTask(title, projectRoot, parentTaskId),
|
|
1658
1547
|
completeTask: (record, r) => completeDeliveryTask(record, r),
|
|
1659
1548
|
// P3 — per-task memory retrieval: pull the few most relevant established
|
|
@@ -1764,10 +1653,7 @@ async function runDeliver(instruction, options) {
|
|
|
1764
1653
|
resumeCheckpoint = undefined; // consumed by this loop
|
|
1765
1654
|
return loop.deliver(prompt);
|
|
1766
1655
|
},
|
|
1767
|
-
setPhaseSpec: (spec) =>
|
|
1768
|
-
acceptanceSpec = spec;
|
|
1769
|
-
specChangeEvidence.writes = 0;
|
|
1770
|
-
},
|
|
1656
|
+
setPhaseSpec: (spec) => specs.setShared(spec),
|
|
1771
1657
|
openTask: (title) => openDeliveryTask(title, projectRoot, missionTask?.id),
|
|
1772
1658
|
completeTask: (record, r) => completeDeliveryTask(record, r),
|
|
1773
1659
|
persistCursor: (index) => {
|
|
@@ -1821,15 +1707,32 @@ async function runDeliver(instruction, options) {
|
|
|
1821
1707
|
thoughtExperiment: false,
|
|
1822
1708
|
}),
|
|
1823
1709
|
epicParallelTasks,
|
|
1710
|
+
// Deterministic epic-boundary resume: reuse the PERSISTED plan and
|
|
1711
|
+
// accepted-epic set — replanning on resume would mint new epic ids
|
|
1712
|
+
// (resetting the completion ledger's done marks) and draw new
|
|
1713
|
+
// boundaries over already-built work, which the anti-no-op rail then
|
|
1714
|
+
// refuses to accept (a wedge).
|
|
1715
|
+
initialEpics: resumeState?.runnerKind === 'epic' ? resumeState.phases : undefined,
|
|
1716
|
+
initialDone: resumeState?.runnerKind === 'epic' ? (resumeState.completedEpicIds ?? []) : [],
|
|
1717
|
+
initialPriorSummaries: resumeState?.runnerKind === 'epic' ? (resumeState.phaseSummaries ?? []) : [],
|
|
1718
|
+
persistPlan: (plan) => {
|
|
1719
|
+
runState.phases = plan;
|
|
1720
|
+
saveRunState(runState);
|
|
1721
|
+
},
|
|
1722
|
+
persistCompleted: ({ summaries, completed }) => {
|
|
1723
|
+
runState.phaseSummaries = [...summaries];
|
|
1724
|
+
runState.completedEpicIds = [...completed];
|
|
1725
|
+
// The checkpoint belongs to the finished epic (phased-path parity) —
|
|
1726
|
+
// never seed a later loop with a completed epic's session state.
|
|
1727
|
+
runState.checkpoint = undefined;
|
|
1728
|
+
saveRunState(runState);
|
|
1729
|
+
},
|
|
1824
1730
|
runOrchestrated: (missionText, plan, parentTaskId) => runOrchestratedMissionCore(buildOrchestratedDeps(missionText, plan, epicParallelTasks, parentTaskId)),
|
|
1825
1731
|
runEpicLoop: async (scoped) => {
|
|
1826
1732
|
const loop = new ConvergenceLoop({ ...loopConfig, baselineCheck: false, resumeFrom: undefined, onIteration: makeIterationHook() }, executor, seams);
|
|
1827
1733
|
return loop.deliver(scoped);
|
|
1828
1734
|
},
|
|
1829
|
-
setEpicSpec: (spec) =>
|
|
1830
|
-
acceptanceSpec = spec;
|
|
1831
|
-
specChangeEvidence.writes = 0; // fresh epic — breaker needs fresh diff evidence
|
|
1832
|
-
},
|
|
1735
|
+
setEpicSpec: (spec) => specs.setShared(spec), // fresh epic — breaker needs fresh diff evidence
|
|
1833
1736
|
judgeEpic: options.acceptance && !skipJudgeForSimple
|
|
1834
1737
|
? async (spec) => {
|
|
1835
1738
|
try {
|
|
@@ -1937,15 +1840,15 @@ async function runDeliver(instruction, options) {
|
|
|
1937
1840
|
console.log(chalk.dim(' lazy attempt did not pass — engaging the full convergence stack'));
|
|
1938
1841
|
}
|
|
1939
1842
|
}
|
|
1940
|
-
// Resume
|
|
1941
|
-
//
|
|
1942
|
-
//
|
|
1943
|
-
//
|
|
1944
|
-
//
|
|
1945
|
-
//
|
|
1946
|
-
//
|
|
1843
|
+
// Resume routing: an epic-kind resume re-enters the epic path (fidelity —
|
|
1844
|
+
// completed epics carry forward as prior summaries). Everything else takes
|
|
1845
|
+
// a cursor-honoring sequential path — phased when a phase plan was
|
|
1846
|
+
// persisted, otherwise the single flat loop. When that CHANGES the
|
|
1847
|
+
// execution model (e.g. an epic run resumed under --no-epics), warn
|
|
1848
|
+
// loudly, never silently: different prompts, no contract publication,
|
|
1849
|
+
// DAG flattened to linear order.
|
|
1947
1850
|
if (resumeState?.runnerKind) {
|
|
1948
|
-
const resumeTarget = phases && phases.length >= 2 ? 'phased' : 'single';
|
|
1851
|
+
const resumeTarget = epicsEnabled ? 'epic' : phases && phases.length >= 2 ? 'phased' : 'single';
|
|
1949
1852
|
if (resumeState.runnerKind !== resumeTarget) {
|
|
1950
1853
|
const targetDesc = resumeTarget === 'phased'
|
|
1951
1854
|
? 'sequential phased path (the only cursor-honoring runner)'
|
|
@@ -1959,6 +1862,10 @@ async function runDeliver(instruction, options) {
|
|
|
1959
1862
|
result = result;
|
|
1960
1863
|
}
|
|
1961
1864
|
else if (epicsEnabled) {
|
|
1865
|
+
if (resumeState && resumeCheckpoint) {
|
|
1866
|
+
console.log(chalk.dim(' resume: mid-epic loop checkpoint discarded — epic missions resume at the epic boundary (completed epics carry forward as summaries).'));
|
|
1867
|
+
resumeCheckpoint = undefined;
|
|
1868
|
+
}
|
|
1962
1869
|
runState.runnerKind = 'epic';
|
|
1963
1870
|
saveRunState(runState);
|
|
1964
1871
|
result = await runEpicMission();
|
|
@@ -1991,8 +1898,7 @@ async function runDeliver(instruction, options) {
|
|
|
1991
1898
|
// Re-point the judge at the MISSION: epic/phased runners leave
|
|
1992
1899
|
// acceptanceSpec on the LAST epic/phase spec, and a re-converge pass
|
|
1993
1900
|
// would otherwise be judged against that stale slice.
|
|
1994
|
-
|
|
1995
|
-
specChangeEvidence.writes = 0; // evidence resets wherever the spec re-points
|
|
1901
|
+
specs.setShared(instruction); // evidence resets wherever the spec re-points
|
|
1996
1902
|
const branch = currentBranch(projectRoot) ?? undefined;
|
|
1997
1903
|
result = await runCiReconverge({
|
|
1998
1904
|
instruction,
|