@miller-tech/uap 1.207.1 → 1.209.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 (41) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/cli/deliver.js +57 -7
  3. package/dist/cli/deliver.js.map +1 -1
  4. package/dist/dashboard/server.d.ts.map +1 -1
  5. package/dist/dashboard/server.js +2 -0
  6. package/dist/dashboard/server.js.map +1 -1
  7. package/dist/delivery/agentic-executor.d.ts.map +1 -1
  8. package/dist/delivery/agentic-executor.js +10 -1
  9. package/dist/delivery/agentic-executor.js.map +1 -1
  10. package/dist/delivery/await-run.d.ts.map +1 -1
  11. package/dist/delivery/await-run.js +6 -1
  12. package/dist/delivery/await-run.js.map +1 -1
  13. package/dist/delivery/convergence-loop.d.ts +11 -0
  14. package/dist/delivery/convergence-loop.d.ts.map +1 -1
  15. package/dist/delivery/convergence-loop.js +5 -1
  16. package/dist/delivery/convergence-loop.js.map +1 -1
  17. package/dist/delivery/epic-mission.d.ts.map +1 -1
  18. package/dist/delivery/epic-mission.js +12 -1
  19. package/dist/delivery/epic-mission.js.map +1 -1
  20. package/dist/delivery/orphan-guard.d.ts +10 -3
  21. package/dist/delivery/orphan-guard.d.ts.map +1 -1
  22. package/dist/delivery/orphan-guard.js +41 -5
  23. package/dist/delivery/orphan-guard.js.map +1 -1
  24. package/dist/delivery/run-state.d.ts +27 -0
  25. package/dist/delivery/run-state.d.ts.map +1 -1
  26. package/dist/delivery/run-state.js +54 -1
  27. package/dist/delivery/run-state.js.map +1 -1
  28. package/dist/delivery/task-sync.d.ts.map +1 -1
  29. package/dist/delivery/task-sync.js +10 -2
  30. package/dist/delivery/task-sync.js.map +1 -1
  31. package/dist/models/long-fetch.d.ts +22 -0
  32. package/dist/models/long-fetch.d.ts.map +1 -1
  33. package/dist/models/long-fetch.js +51 -2
  34. package/dist/models/long-fetch.js.map +1 -1
  35. package/dist/models/openai-compat-client.d.ts.map +1 -1
  36. package/dist/models/openai-compat-client.js +10 -1
  37. package/dist/models/openai-compat-client.js.map +1 -1
  38. package/package.json +1 -1
  39. package/src/policies/enforcers/__pycache__/_common.cpython-312.pyc +0 -0
  40. package/templates/hooks/__pycache__/deliver_autoroute.cpython-312.pyc +0 -0
  41. package/tools/agents/scripts/__pycache__/toolcall_path_normalizer.cpython-312.pyc +0 -0
@@ -187,7 +187,7 @@ export function bestKeepFastScore(gateResults, fastRungIds) {
187
187
  export { resolveAcceptanceVerdict } from '../delivery/mission-acceptance.js';
188
188
  import { createAgenticExecutor, noopApplier, selectExecutorMode, lockContractFiles } from '../delivery/agentic-executor.js';
189
189
  import { createRepairEscalation } from '../delivery/repair-escalation.js';
190
- import { clearStop, isRunBudgetExpired, isStopRequested, makeStopLatch, requestStop, runBudgetMinutes, loadRunState, newRunId, saveRunState, isEpicResume, MAX_PERSISTED_PHASES } from '../delivery/run-state.js';
190
+ import { clearProjectStop, clearStop, finalRunStatus, isRunBudgetExpired, isStopRequested, makeStopLatch, requestStop, runBudgetMinutes, loadRunState, newRunId, saveRunState, isEpicResume, MAX_PERSISTED_PHASES } from '../delivery/run-state.js';
191
191
  import { planDeliveryPhases, shouldDecompose } from '../delivery/decompose.js';
192
192
  import { initLedger, markItem } from '../delivery/completion-ledger.js';
193
193
  import { loadUapConfigRaw } from '../utils/config-loader.js';
@@ -2678,15 +2678,36 @@ async function runDeliver(instruction, options) {
2678
2678
  const budgetMinutes = runBudgetMinutes(projectRoot);
2679
2679
  const runStartedAtMs = Date.now();
2680
2680
  let stoppedForBudget = false;
2681
+ // Captured at OBSERVATION time: isStopRequested consumes the project-level
2682
+ // STOP file when it sees it, so this flag is the only record of the stop
2683
+ // that survives to final bookkeeping (a re-check there returns false and the
2684
+ // run lands 'failed' — the misread that caused the 2026-08-15 stop/relaunch
2685
+ // thrash).
2686
+ let stoppedByRequest = false;
2681
2687
  const stopLatch = makeStopLatch(() => {
2682
2688
  if (isRunBudgetExpired(runStartedAtMs, budgetMinutes)) {
2683
2689
  stoppedForBudget = true;
2684
2690
  return true;
2685
2691
  }
2686
- return isStopRequested(projectRoot, runId);
2692
+ if (isStopRequested(projectRoot, runId)) {
2693
+ stoppedByRequest = true;
2694
+ return true;
2695
+ }
2696
+ return false;
2687
2697
  });
2688
2698
  loopConfig.shouldStop = stopLatch;
2689
2699
  clearStop(projectRoot, runId);
2700
+ // A project-level STOP that PREDATES this launch was aimed at a previous
2701
+ // run — consuming it keeps it from instant-stopping this one at turn 0
2702
+ // (observed 2026-08-15: a leaked STOP latched a resume dead in 0 turns).
2703
+ // mtime-gated against PROCESS start, not this line's timestamp: planning
2704
+ // runs for minutes before we get here, and a stop touched during planning
2705
+ // (the impatient pre-runId window the project STOP exists for) is a live
2706
+ // operator signal that must reach the stop latch untouched.
2707
+ const processStartedAtMs = Date.now() - process.uptime() * 1000;
2708
+ if (clearProjectStop(projectRoot, processStartedAtMs)) {
2709
+ console.error(chalk.dim(' cleared a stale project-level STOP left over from a previous run'));
2710
+ }
2690
2711
  // The restored checkpoint feeds exactly one loop (the in-flight phase).
2691
2712
  let resumeCheckpoint = resumeState?.checkpoint;
2692
2713
  // A model switch cannot serialize into the checkpoint; when the interrupted
@@ -2997,6 +3018,15 @@ async function runDeliver(instruction, options) {
2997
3018
  persistCompleted: ({ summaries, completed }) => {
2998
3019
  runState.phaseSummaries = [...summaries];
2999
3020
  runState.completedEpicIds = [...completed];
3021
+ // Advance the visible phase pointer as epics are ACCEPTED. Followers
3022
+ // read state.json for progress; a phaseIndex frozen at 0 through a
3023
+ // 30-minute first epic read as "stuck at phase 1/20" and got a healthy
3024
+ // run cooperatively stopped (2026-08-15). Clamped to the plan's last
3025
+ // index: the loader validates the cursor's range and silently DROPS an
3026
+ // out-of-range value (split sub-epic ids can push completed.length past
3027
+ // the top-level plan), which would erase the very progress signal this
3028
+ // write exists to provide.
3029
+ runState.phaseIndex = Math.min(completed.length, Math.max(0, (runState.phases?.length ?? 1) - 1));
3000
3030
  // The checkpoint belongs to the finished epic (phased-path parity) —
3001
3031
  // never seed a later loop with a completed epic's session state.
3002
3032
  runState.checkpoint = undefined;
@@ -3415,15 +3445,27 @@ async function runDeliver(instruction, options) {
3415
3445
  disposeSnapshot(regressSnapshot);
3416
3446
  }
3417
3447
  }
3448
+ // Surface the observed stop on the result itself: the JSON output (and the
3449
+ // MCP deliver tool reading it) is what the NEXT agent decides from, and a
3450
+ // stopped run that prints as a plain failure gets relaunched instead of
3451
+ // resumed. The epic path may have set this already; the plain loop's stop is
3452
+ // only visible here, via the latch flags.
3453
+ if (!result.success && (stoppedByRequest || stoppedForBudget))
3454
+ result.stopped = true;
3418
3455
  haloTracer.finish(result);
3419
3456
  // Durable-run bookkeeping + task/memory trail (all fail-soft): the run's
3420
3457
  // outcome lands in the task DB and short-term memory so future sessions
3421
3458
  // know exactly what was delivered (or what failed and why).
3422
- runState.status = result.success
3423
- ? 'delivered'
3424
- : isStopRequested(projectRoot, runId)
3425
- ? 'interrupted'
3426
- : 'failed';
3459
+ // Deliberate side effect: isStopRequested CONSUMES a project-level STOP it
3460
+ // finds, on the success path too — a stop file that outlived its run would
3461
+ // silently stop the NEXT mission (that stale-STOP hazard is real; observed
3462
+ // 2026-08-15). Hoisted so the consumption is visible, not buried in an
3463
+ // argument list to a pure function.
3464
+ const lateStopFilePresent = isStopRequested(projectRoot, runId);
3465
+ runState.status = finalRunStatus(result.success,
3466
+ // The latch flags ride along directly so this mapping cannot silently
3467
+ // regress if the result.stopped annotation above ever moves below it.
3468
+ result.stopped === true || stoppedByRequest || stoppedForBudget, lateStopFilePresent);
3427
3469
  if (result.success)
3428
3470
  runState.checkpoint = undefined;
3429
3471
  clearStop(projectRoot, runId);
@@ -3534,6 +3576,14 @@ async function runDeliver(instruction, options) {
3534
3576
  `\`uap deliver --resume\`, and raise the budget for this mission with delivery.maxRunMinutes ` +
3535
3577
  `in .uap.json if the mission is genuinely this long.`));
3536
3578
  }
3579
+ else if (result.stopped) {
3580
+ // Budget stops are named by the branch above; anything else that set
3581
+ // result.stopped is a cooperative stop of some kind — keep the copy
3582
+ // cause-neutral so it stays true if new stop sources appear.
3583
+ console.log(chalk.yellow(` Stopped by a cooperative stop request — interrupted, not failed. The work is ` +
3584
+ `checkpointed and the lock is released. Resume it with \`uap deliver --resume ${runId}\`; ` +
3585
+ `relaunching from scratch discards the accepted work.`));
3586
+ }
3537
3587
  if (result.finalFeedback) {
3538
3588
  console.log(chalk.dim(stripControl(result.finalFeedback)));
3539
3589
  }