@miller-tech/uap 1.153.0 → 1.155.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.
Files changed (45) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/cli/deliver.d.ts.map +1 -1
  3. package/dist/cli/deliver.js +125 -141
  4. package/dist/cli/deliver.js.map +1 -1
  5. package/dist/delivery/agentic-executor.d.ts.map +1 -1
  6. package/dist/delivery/agentic-executor.js +7 -4
  7. package/dist/delivery/agentic-executor.js.map +1 -1
  8. package/dist/delivery/changed-files.d.ts +23 -0
  9. package/dist/delivery/changed-files.d.ts.map +1 -0
  10. package/dist/delivery/changed-files.js +53 -0
  11. package/dist/delivery/changed-files.js.map +1 -0
  12. package/dist/delivery/context-budget.d.ts +32 -3
  13. package/dist/delivery/context-budget.d.ts.map +1 -1
  14. package/dist/delivery/context-budget.js +33 -3
  15. package/dist/delivery/context-budget.js.map +1 -1
  16. package/dist/delivery/convergence-loop.js +2 -2
  17. package/dist/delivery/convergence-loop.js.map +1 -1
  18. package/dist/delivery/epic-controller.d.ts +31 -6
  19. package/dist/delivery/epic-controller.d.ts.map +1 -1
  20. package/dist/delivery/epic-controller.js +30 -6
  21. package/dist/delivery/epic-controller.js.map +1 -1
  22. package/dist/delivery/epic-mission.d.ts +31 -0
  23. package/dist/delivery/epic-mission.d.ts.map +1 -1
  24. package/dist/delivery/epic-mission.js +27 -7
  25. package/dist/delivery/epic-mission.js.map +1 -1
  26. package/dist/delivery/index.d.ts +4 -0
  27. package/dist/delivery/index.d.ts.map +1 -1
  28. package/dist/delivery/index.js +4 -0
  29. package/dist/delivery/index.js.map +1 -1
  30. package/dist/delivery/phased-mission.d.ts +55 -0
  31. package/dist/delivery/phased-mission.d.ts.map +1 -0
  32. package/dist/delivery/phased-mission.js +50 -0
  33. package/dist/delivery/phased-mission.js.map +1 -0
  34. package/dist/delivery/run-state.d.ts +10 -1
  35. package/dist/delivery/run-state.d.ts.map +1 -1
  36. package/dist/delivery/run-state.js +60 -4
  37. package/dist/delivery/run-state.js.map +1 -1
  38. package/dist/delivery/spec-registry.d.ts +72 -0
  39. package/dist/delivery/spec-registry.d.ts.map +1 -0
  40. package/dist/delivery/spec-registry.js +80 -0
  41. package/dist/delivery/spec-registry.js.map +1 -0
  42. package/package.json +1 -1
  43. package/src/policies/enforcers/__pycache__/_common.cpython-312.pyc +0 -0
  44. package/templates/hooks/__pycache__/deliver_autoroute.cpython-312.pyc +0 -0
  45. package/tools/agents/scripts/__pycache__/toolcall_path_normalizer.cpython-312.pyc +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"deliver.d.ts","sourceRoot":"","sources":["../../src/cli/deliver.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"deliver.d.ts","sourceRoot":"","sources":["../../src/cli/deliver.ts"],"names":[],"mappings":"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"}
@@ -20,7 +20,8 @@ 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, formatAcceptanceReport, createAcceptanceChurnBreaker } from '../delivery/acceptance-judge.js';
23
+ import { runAcceptanceGate, formatAcceptanceReport } from '../delivery/acceptance-judge.js';
24
+ import { createSpecRegistry } from '../delivery/spec-registry.js';
24
25
  import { runExecutionGate } from '../delivery/execution-gate.js';
25
26
  import { runVisualGate, visualRuntimeNote } from '../delivery/visual-gate.js';
26
27
  /**
@@ -94,7 +95,7 @@ export function resolveAcceptanceVerdict(r, acceptancePrimary) {
94
95
  import { createAgenticExecutor, noopApplier, selectExecutorMode, lockContractFiles } from '../delivery/agentic-executor.js';
95
96
  import { createRepairEscalation } from '../delivery/repair-escalation.js';
96
97
  import { clearStop, isStopRequested, loadRunState, newRunId, saveRunState } from '../delivery/run-state.js';
97
- import { phaseInstruction, planDeliveryPhases, shouldDecompose } from '../delivery/decompose.js';
98
+ import { planDeliveryPhases, shouldDecompose } from '../delivery/decompose.js';
98
99
  import { initLedger, markItem } from '../delivery/completion-ledger.js';
99
100
  import { loadUapConfigRaw } from '../utils/config-loader.js';
100
101
  import { buildUserPathsNote, createUserValidationRunner, resolveUserValidationMode, synthesizeUserValidationRung, } from '../delivery/user-validation.js';
@@ -121,6 +122,8 @@ import { createGitWorktreeProvider } from '../delivery/candidate-workspace.js';
121
122
  import { createTaskWorkspaceManager, resolveParallelTasks } from '../delivery/task-workspace.js';
122
123
  import { runOrchestratedMission as runOrchestratedMissionCore } from '../delivery/orchestrated-mission.js';
123
124
  import { runCiReconverge } from '../delivery/ci-reconverge.js';
125
+ import { runPhasedMission as runPhasedMissionCore } from '../delivery/phased-mission.js';
126
+ import { changedFiles } from '../delivery/changed-files.js';
124
127
  import { runEpicMission as runEpicMissionCore } from '../delivery/epic-mission.js';
125
128
  import { createHaloDeliveryTracer } from '../delivery/halo-trace.js';
126
129
  import { haloTracePath, isHaloTracingEnabled } from '../observability/halo-exporter.js';
@@ -165,28 +168,6 @@ function currentBranch(projectRoot) {
165
168
  * agentic executor mutates the repo directly and returns an empty file set), so
166
169
  * the watcher stages a known list instead of a blanket `git add -A`.
167
170
  */
168
- function changedFiles(projectRoot) {
169
- try {
170
- const r = spawnSync('git', ['status', '--porcelain', '-z'], {
171
- cwd: projectRoot,
172
- encoding: 'utf-8',
173
- });
174
- if (r.status !== 0 || !r.stdout)
175
- return [];
176
- return r.stdout
177
- .split('\0')
178
- .filter(Boolean)
179
- // porcelain lines are "XY <path>"; drop the 3-char status prefix.
180
- .map((line) => line.slice(3))
181
- .filter(Boolean)
182
- // Harness-owned state (run checkpoints, traces, mined weaknesses) must
183
- // never ride into the delivery commit on repos that don't ignore .uap/.
184
- .filter((f) => !f.startsWith('.uap/') && !f.startsWith('.uap\\'));
185
- }
186
- catch {
187
- return [];
188
- }
189
- }
190
171
  function fail(message) {
191
172
  console.error(chalk.red(message));
192
173
  process.exitCode = 2;
@@ -1267,46 +1248,13 @@ async function runDeliver(instruction, options) {
1267
1248
  }
1268
1249
  // Phased missions re-point the judge at the current phase's goal — judging
1269
1250
  // phase 1 against the FULL mission would fail every phase by construction.
1270
- let acceptanceSpec = instruction;
1271
- // Parallel orchestrated tasks run in ISOLATED worktree roots; each loop's
1272
- // judge must grade against ITS task's spec, not a shared mutable. The
1273
- // acceptance gate resolves by the root it is invoked with; the phased and
1274
- // epic paths (single loop at a time) keep using the shared variable.
1275
- const acceptanceSpecByRoot = new Map();
1276
- // Secondary-judge churn breaker: bounds consecutive judge rejections of
1277
- // objectively-green turns per spec (env UAP_DELIVER_ACCEPTANCE_FLIP_LIMIT,
1278
- // default 2), after which the objective gates win. Primary mode is exempt.
1279
- // Change-evidence for the breaker's zero-diff guard: files applied since the
1280
- // current acceptance spec (epic) began. Incremented by the iteration hook,
1281
- // reset wherever acceptanceSpec is re-pointed.
1282
- // Per-ROOT under parallel dispatch: concurrent loops must not zero or
1283
- // inflate each other's evidence (an inflated count could let the breaker
1284
- // accept a task with zero writes of its own). projectRoot's entry is the
1285
- // historic shared counter the phased/epic paths keep using.
1286
- const writesByRoot = new Map();
1287
- const evidenceFor = (root) => {
1288
- let e = writesByRoot.get(root);
1289
- if (!e) {
1290
- e = { writes: 0 };
1291
- writesByRoot.set(root, e);
1292
- }
1293
- return e;
1294
- };
1295
- const specChangeEvidence = evidenceFor(projectRoot);
1296
- // Breaker state is per SPEC: one shared instance thrashes its current-spec
1297
- // slot under parallel dispatch and can then never trip.
1298
- const acceptanceFlipLimit = Number(process.env.UAP_DELIVER_ACCEPTANCE_FLIP_LIMIT ?? 2);
1299
- const acceptanceBreakers = new Map();
1300
- const breakerFor = (spec, root) => {
1301
- let b = acceptanceBreakers.get(spec);
1302
- if (!b) {
1303
- if (acceptanceBreakers.size > 100)
1304
- acceptanceBreakers.clear(); // runaway guard
1305
- b = createAcceptanceChurnBreaker(acceptanceFlipLimit, () => evidenceFor(root).writes > 0);
1306
- acceptanceBreakers.set(spec, b);
1307
- }
1308
- return b;
1309
- };
1251
+ // Per-root specs, write evidence, and churn breakers live in the registry
1252
+ // (see src/delivery/spec-registry.ts for the parallel-dispatch semantics).
1253
+ const specs = createSpecRegistry({
1254
+ initialSpec: instruction,
1255
+ sharedRoot: projectRoot,
1256
+ flipLimit: Number(process.env.UAP_DELIVER_ACCEPTANCE_FLIP_LIMIT ?? 2),
1257
+ });
1310
1258
  const acceptanceGate = options.acceptance && !skipJudgeForSimple
1311
1259
  ? async (root) => {
1312
1260
  // Primary mode: the only objective rung is the trivial bootstrap, and the
@@ -1338,7 +1286,7 @@ async function runDeliver(instruction, options) {
1338
1286
  // gates all passed — hand the judge that fact as evidence, so
1339
1287
  // requirements like "make the tests pass" are graded on the gate
1340
1288
  // result instead of speculated about from static code.
1341
- const resolvedSpec = acceptanceSpecByRoot.get(root) ?? acceptanceSpec;
1289
+ const resolvedSpec = specs.resolve(root);
1342
1290
  const uvNote = buildUserPathsNote(root);
1343
1291
  const baseNote = acceptancePrimary
1344
1292
  ? visualNote
@@ -1355,7 +1303,7 @@ async function runDeliver(instruction, options) {
1355
1303
  // objective gates ALL passed, so a bounded number of consecutive judge
1356
1304
  // rejections hands the verdict back to the gates instead of wedging.
1357
1305
  if (!acceptancePrimary) {
1358
- const checked = breakerFor(resolvedSpec, root).check(resolvedSpec, verdict);
1306
+ const checked = specs.breaker(resolvedSpec, root).check(resolvedSpec, verdict);
1359
1307
  if (checked.overridden) {
1360
1308
  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)'));
1361
1309
  }
@@ -1388,8 +1336,7 @@ async function runDeliver(instruction, options) {
1388
1336
  : undefined;
1389
1337
  return composeIterationHooks((record) => printProgress(record), (record) => {
1390
1338
  // Feed the acceptance breaker's zero-diff guard.
1391
- if (record.filesApplied.length > 0)
1392
- evidenceFor(evidenceRoot).writes += record.filesApplied.length;
1339
+ specs.recordWrites(evidenceRoot, record.filesApplied.length);
1393
1340
  return undefined;
1394
1341
  }, (record) => haloTracer.onIteration(record), repair ? (record) => repair.onIteration(record) : undefined, coordinator ? (record) => coordinator.onIteration(record) : undefined, escalation ? (record) => escalation.onIteration(record) : undefined);
1395
1342
  };
@@ -1494,9 +1441,13 @@ async function runDeliver(instruction, options) {
1494
1441
  // single-session context thrash — and a trivial mission simply decomposes to
1495
1442
  // one epic, so the wrapper is cheap. Disable per-run with --no-epics /
1496
1443
  // UAP_DELIVER_EPICS=0 / `.uap.json` deliver.epics false|'off'. Never on
1497
- // self-gate or resume (those are special single-pass modes).
1444
+ // self-gate. A resume re-enters the epic path ONLY when the interrupted
1445
+ // run was epic-kind: completed epics carry forward as prior summaries and
1446
+ // the mid-epic loop checkpoint is discarded (epics restart at the epic
1447
+ // boundary). Non-epic resumes stay on the cursor-honoring paths below.
1498
1448
  const cfgEpics = cfgRaw.deliver?.epics;
1499
- const epicsEnabled = !needsSelfGate && !resumeState &&
1449
+ const epicsEnabled = !needsSelfGate &&
1450
+ (!resumeState || resumeState.runnerKind === 'epic') &&
1500
1451
  options.epics !== false &&
1501
1452
  process.env.UAP_DELIVER_EPICS !== '0' &&
1502
1453
  cfgEpics !== false && cfgEpics !== 'off';
@@ -1593,7 +1544,10 @@ async function runDeliver(instruction, options) {
1593
1544
  // a silent de-escalation. Falls back to the normal executor when no
1594
1545
  // stronger model is configured in this environment.
1595
1546
  let runExecutor = executor;
1596
- if (resumeCheckpoint?.modelEscalated) {
1547
+ // Epic-kind resumes never use runExecutor (fresh epic loops re-escalate on
1548
+ // their own) and discard the checkpoint at the dispatch — a re-bind message
1549
+ // here would falsely claim the escalation carried over.
1550
+ if (resumeCheckpoint?.modelEscalated && !epicsEnabled) {
1597
1551
  if (escalateExecutor && !agentic) {
1598
1552
  // Agentic runs keep their tool-loop executor: the blind escalation
1599
1553
  // executor pairs with the noop applier and would never touch the repo.
@@ -1660,20 +1614,10 @@ async function runDeliver(instruction, options) {
1660
1614
  : line.includes('parallel tasks:') || line.includes('post-merge verification')
1661
1615
  ? chalk.cyan(line)
1662
1616
  : chalk.dim(line)),
1663
- beginTaskSpec: (root, spec) => {
1664
- acceptanceSpecByRoot.set(root, spec);
1665
- if (root === projectRoot)
1666
- acceptanceSpec = spec;
1667
- evidenceFor(root).writes = 0;
1668
- },
1669
- endTaskSpec: (root) => {
1670
- acceptanceSpecByRoot.delete(root);
1671
- // An in-tree task re-pointed the shared spec; restore the mission-
1672
- // level spec so a later watch-ci re-converge never judges against a
1673
- // stale task prompt.
1674
- if (root === projectRoot)
1675
- acceptanceSpec = missionText;
1676
- },
1617
+ beginTaskSpec: (root, spec) => specs.begin(root, spec),
1618
+ // Restore the mission-level spec after an in-tree task so a later
1619
+ // watch-ci re-converge never judges against a stale task prompt.
1620
+ endTaskSpec: (root) => specs.end(root, missionText),
1677
1621
  openTask: (title) => openDeliveryTask(title, projectRoot, parentTaskId),
1678
1622
  completeTask: (record, r) => completeDeliveryTask(record, r),
1679
1623
  // P3 — per-task memory retrieval: pull the few most relevant established
@@ -1756,57 +1700,51 @@ async function runDeliver(instruction, options) {
1756
1700
  const parallelTasks = resolveParallelTasks(cfgRaw.deliver?.parallelTasks);
1757
1701
  return runOrchestratedMissionCore(buildOrchestratedDeps(instruction, phases, parallelTasks));
1758
1702
  };
1703
+ /**
1704
+ * Wire deliver's ambient context into the extracted phased runner
1705
+ * (src/delivery/phased-mission.ts) — the cursor-honoring resume path and
1706
+ * the fallback when orchestration is explicitly disabled.
1707
+ */
1759
1708
  const runPhasedMission = async () => {
1760
- const all = {
1761
- success: true,
1762
- alreadyDelivered: false,
1763
- turns: 0,
1764
- bestScore: 0,
1765
- bestTurn: 0,
1766
- history: [],
1767
- finalFeedback: '',
1768
- finalOutput: '',
1769
- totalDurationMs: 0,
1770
- };
1771
- for (; phaseIndex < phases.length; phaseIndex++) {
1772
- runState.phaseIndex = phaseIndex;
1773
- saveRunState(runState);
1774
- const phase = phases[phaseIndex];
1775
- console.log(chalk.bold(`▶ phase ${phaseIndex + 1}/${phases.length}: ${phase.title}`));
1776
- const phaseTask = await openDeliveryTask(`${phase.title} ${phase.goal.slice(0, 120)}`, projectRoot, missionTask?.id);
1777
- const phaseLoop = new ConvergenceLoop({
1778
- ...loopConfig,
1779
- baselineCheck: false,
1780
- resumeFrom: resumeCheckpoint,
1781
- onIteration: makeIterationHook(),
1782
- }, resumeCheckpoint ? runExecutor : executor, seams);
1783
- const resumedTurns = resumeCheckpoint?.history.length ?? 0;
1784
- resumeCheckpoint = undefined;
1785
- const phaseText = phaseInstruction(instruction, phases, phaseIndex, phaseSummaries);
1786
- // The acceptance judge grades THIS phase's goal, not the whole mission.
1787
- acceptanceSpec = phaseText;
1788
- specChangeEvidence.writes = 0;
1789
- const phaseResult = await phaseLoop.deliver(phaseText);
1790
- all.turns += phaseResult.turns - resumedTurns;
1791
- all.history.push(...phaseResult.history);
1792
- all.totalDurationMs += phaseResult.totalDurationMs;
1793
- if (phaseResult.bestScore > all.bestScore) {
1794
- all.bestScore = phaseResult.bestScore;
1795
- all.bestTurn = phaseResult.bestTurn;
1796
- }
1797
- all.finalFeedback = phaseResult.finalFeedback;
1798
- all.finalOutput = phaseResult.finalOutput;
1799
- completeDeliveryTask(phaseTask, phaseResult);
1800
- if (!phaseResult.success) {
1801
- all.success = false;
1802
- break;
1803
- }
1804
- phaseSummaries.push(`${phase.title}: ${phase.goal.slice(0, 140)} (delivered in ${phaseResult.turns} turn(s))`);
1805
- runState.phaseSummaries = [...phaseSummaries];
1806
- runState.checkpoint = undefined; // belongs to the finished phase
1807
- saveRunState(runState);
1808
- }
1809
- return all;
1709
+ const startCheckpoint = resumeCheckpoint;
1710
+ return runPhasedMissionCore({
1711
+ instruction,
1712
+ phases: phases,
1713
+ startIndex: phaseIndex,
1714
+ initialSummaries: [...phaseSummaries],
1715
+ hasResumeCheckpoint: Boolean(startCheckpoint),
1716
+ resumedTurns: startCheckpoint?.history.length ?? 0,
1717
+ runPhaseLoop: async ({ prompt, resume }) => {
1718
+ const loop = new ConvergenceLoop({
1719
+ ...loopConfig,
1720
+ baselineCheck: false,
1721
+ resumeFrom: resume ? startCheckpoint : undefined,
1722
+ onIteration: makeIterationHook(),
1723
+ },
1724
+ // The interrupted run may have escalated models; only the RESUMED
1725
+ // loop re-binds the escalated executor (historic behavior).
1726
+ resume && startCheckpoint ? runExecutor : executor, seams);
1727
+ if (resume)
1728
+ resumeCheckpoint = undefined; // consumed by this loop
1729
+ return loop.deliver(prompt);
1730
+ },
1731
+ setPhaseSpec: (spec) => specs.setShared(spec),
1732
+ openTask: (title) => openDeliveryTask(title, projectRoot, missionTask?.id),
1733
+ completeTask: (record, r) => completeDeliveryTask(record, r),
1734
+ persistCursor: (index) => {
1735
+ phaseIndex = index;
1736
+ runState.phaseIndex = index;
1737
+ saveRunState(runState);
1738
+ },
1739
+ persistCompleted: (summaries) => {
1740
+ phaseSummaries.length = 0;
1741
+ phaseSummaries.push(...summaries);
1742
+ runState.phaseSummaries = [...summaries];
1743
+ runState.checkpoint = undefined; // belongs to the finished phase
1744
+ saveRunState(runState);
1745
+ },
1746
+ note: (line) => console.log(line.startsWith('▶') ? chalk.bold(line) : chalk.dim(line)),
1747
+ });
1810
1748
  };
1811
1749
  /**
1812
1750
  * P7 — epic controller: run a massive mission as a SEQUENCE of epics. Each
@@ -1844,15 +1782,32 @@ async function runDeliver(instruction, options) {
1844
1782
  thoughtExperiment: false,
1845
1783
  }),
1846
1784
  epicParallelTasks,
1785
+ // Deterministic epic-boundary resume: reuse the PERSISTED plan and
1786
+ // accepted-epic set — replanning on resume would mint new epic ids
1787
+ // (resetting the completion ledger's done marks) and draw new
1788
+ // boundaries over already-built work, which the anti-no-op rail then
1789
+ // refuses to accept (a wedge).
1790
+ initialEpics: resumeState?.runnerKind === 'epic' ? resumeState.phases : undefined,
1791
+ initialDone: resumeState?.runnerKind === 'epic' ? (resumeState.completedEpicIds ?? []) : [],
1792
+ initialPriorSummaries: resumeState?.runnerKind === 'epic' ? (resumeState.phaseSummaries ?? []) : [],
1793
+ persistPlan: (plan) => {
1794
+ runState.phases = plan;
1795
+ saveRunState(runState);
1796
+ },
1797
+ persistCompleted: ({ summaries, completed }) => {
1798
+ runState.phaseSummaries = [...summaries];
1799
+ runState.completedEpicIds = [...completed];
1800
+ // The checkpoint belongs to the finished epic (phased-path parity) —
1801
+ // never seed a later loop with a completed epic's session state.
1802
+ runState.checkpoint = undefined;
1803
+ saveRunState(runState);
1804
+ },
1847
1805
  runOrchestrated: (missionText, plan, parentTaskId) => runOrchestratedMissionCore(buildOrchestratedDeps(missionText, plan, epicParallelTasks, parentTaskId)),
1848
1806
  runEpicLoop: async (scoped) => {
1849
1807
  const loop = new ConvergenceLoop({ ...loopConfig, baselineCheck: false, resumeFrom: undefined, onIteration: makeIterationHook() }, executor, seams);
1850
1808
  return loop.deliver(scoped);
1851
1809
  },
1852
- setEpicSpec: (spec) => {
1853
- acceptanceSpec = spec;
1854
- specChangeEvidence.writes = 0; // fresh epic — breaker needs fresh diff evidence
1855
- },
1810
+ setEpicSpec: (spec) => specs.setShared(spec), // fresh epic — breaker needs fresh diff evidence
1856
1811
  judgeEpic: options.acceptance && !skipJudgeForSimple
1857
1812
  ? async (spec) => {
1858
1813
  try {
@@ -1960,22 +1915,52 @@ async function runDeliver(instruction, options) {
1960
1915
  console.log(chalk.dim(' lazy attempt did not pass — engaging the full convergence stack'));
1961
1916
  }
1962
1917
  }
1918
+ // Resume routing: an epic-kind resume re-enters the epic path (fidelity —
1919
+ // completed epics carry forward as prior summaries). Everything else takes
1920
+ // a cursor-honoring sequential path — phased when a phase plan was
1921
+ // persisted, otherwise the single flat loop. When that CHANGES the
1922
+ // execution model (e.g. an epic run resumed under --no-epics), warn
1923
+ // loudly, never silently: different prompts, no contract publication,
1924
+ // DAG flattened to linear order.
1925
+ if (resumeState?.runnerKind) {
1926
+ const resumeTarget = epicsEnabled ? 'epic' : phases && phases.length >= 2 ? 'phased' : 'single';
1927
+ if (resumeState.runnerKind !== resumeTarget) {
1928
+ const targetDesc = resumeTarget === 'phased'
1929
+ ? 'sequential phased path (the only cursor-honoring runner)'
1930
+ : 'single-loop path (no phase plan was persisted by the original run)';
1931
+ console.log(chalk.yellow(` ⚠ resume: the interrupted run executed as '${resumeState.runnerKind}'; resuming on the ${targetDesc} — prompts and per-phase context will differ from the original execution model.`));
1932
+ }
1933
+ }
1963
1934
  if (lazySolved) {
1935
+ runState.runnerKind = 'single';
1936
+ saveRunState(runState);
1964
1937
  result = result;
1965
1938
  }
1966
1939
  else if (epicsEnabled) {
1940
+ if (resumeState && resumeCheckpoint) {
1941
+ console.log(chalk.dim(' resume: mid-epic loop checkpoint discarded — epic missions resume at the epic boundary (completed epics carry forward as summaries).'));
1942
+ resumeCheckpoint = undefined;
1943
+ }
1944
+ runState.runnerKind = 'epic';
1945
+ saveRunState(runState);
1967
1946
  result = await runEpicMission();
1968
1947
  }
1969
1948
  else if (phases && phases.length >= 2 && orchestrateEnabled && !resumeState) {
1970
1949
  // A RESUMED phased run must not route here: the orchestrated runner
1971
1950
  // ignores phaseIndex/resumeCheckpoint and would restart the DAG from
1972
1951
  // scratch. runPhasedMission below is the only cursor-honoring path.
1952
+ runState.runnerKind = 'orchestrated';
1953
+ saveRunState(runState);
1973
1954
  result = await runOrchestratedMission();
1974
1955
  }
1975
1956
  else if (phases && phases.length >= 2) {
1957
+ runState.runnerKind = 'phased';
1958
+ saveRunState(runState);
1976
1959
  result = await runPhasedMission();
1977
1960
  }
1978
1961
  else {
1962
+ runState.runnerKind = 'single';
1963
+ saveRunState(runState);
1979
1964
  if (resumeCheckpoint)
1980
1965
  loopConfig.resumeFrom = resumeCheckpoint;
1981
1966
  const loop = new ConvergenceLoop(loopConfig, runExecutor, seams);
@@ -1988,8 +1973,7 @@ async function runDeliver(instruction, options) {
1988
1973
  // Re-point the judge at the MISSION: epic/phased runners leave
1989
1974
  // acceptanceSpec on the LAST epic/phase spec, and a re-converge pass
1990
1975
  // would otherwise be judged against that stale slice.
1991
- acceptanceSpec = instruction;
1992
- specChangeEvidence.writes = 0; // evidence resets wherever the spec re-points
1976
+ specs.setShared(instruction); // evidence resets wherever the spec re-points
1993
1977
  const branch = currentBranch(projectRoot) ?? undefined;
1994
1978
  result = await runCiReconverge({
1995
1979
  instruction,