# V16.17 — Execution-Core Consolidation & Hardening

## Why this release exists

V16.16 closed the critical-path and cost gaps, but a hardening audit of the
execution core found a set of **confirmed** defects where the runtime kept a
second authority, silently dropped evidence, or turned an unknown into a
measured zero. This release is a consolidation/hardening pass — it does **not**
add a new feature family. It removes ambiguity from owners that already exist.

Every item below was reproduced in the baseline before it was changed. Items
that were already correct were left alone.

## Confirmed gaps fixed

| § | Defect (confirmed in the baseline) | Consequence | Fix (single owner) |
|---|-----------------------------------|-------------|--------------------|
| 3 | `buildDelegationWaves` candidate probe called `assessParallelSafety([...wave, candidate], { maxParallel })`, **dropping `moduleEdges`, `generatedEdges`, `pairStrategy`** | A declared module/generated-output edge or a `pairStrategy` was ignored during wave admission, so two coupled writers could be admitted in parallel | Compile the conflict inputs ONCE into `probeOptions` and pass that exact object to every candidate probe (`lib/delegation-safety.mjs`) |
| 3b | `classifyScope`/`graphScopeFor` dropped structured declarations (`generatedOutputs`, `services`, `externalEffects`, `commands`) when translating to the conflict graph | A generated-output / declared-service / declared-effect scope re-classified as independent once it reached the graph | Carry the structured declarations verbatim into `normalizeScope` |
| 4 | `lib/task-graph.mjs` kept its own `overlaps()` write/write + read/write implementation (production-reachable) | Two conflict authorities could disagree | `tasksConflict`/`overlaps` delegate to `lib/execution-conflict-graph-v16-15.mjs` |
| 5 | `EXTERNAL_SIDE_EFFECT_PATTERN` (`publish\|deploy\|release\|tag`) read bare prose words | Ordinary source-writing prose (`update release notes`, `fix HTML tag rendering`) was mislabeled `externalSideEffect:true`/serial-only, refusing real parallelism | `classifyScope` reads the canonical graph's STRONG/WEAK hierarchy; a fixed canonical weak pattern (`deploy\s+(to\s+)?\S+`) |
| 7 | `rpcPromptPath(agent)` cached by agent name only and wrote a non-content-addressed `agent.md`; `buildRuntimeEpoch` ignored the agent system prompt | A changed privileged prompt (e.g. a tightened verifier PASS rule) did not invalidate a warm worker | Content-addressed prompt file (`agent.<hash>.md`); `systemPromptHash` folded into the runtime epoch |
| 8 | `reserveRunCost()` was stateless per request | N waves each "fit" while their sum blew the ceiling | `lib/run-budget-ledger-v16-17.mjs` cumulative run ledger |
| 9 | No run-level wall-clock deadline (only per-child) | A run could grind forever while every child stayed individually alive | Run deadline in the same ledger; expiry stops optional work, never verification |
| 10 | `aggregateUsageSamples` summed samples on a blind DELTA assumption; a second `normalizeProviderUsage` existed in the research broker; production wrote `Number(usage?.totalTokens ?? 0)` | A cumulative series was double-counted, and an UNKNOWN provider report became a MEASURED zero | `lib/provider-usage-normalizer-v16-17.mjs` is the ONE authority (CUMULATIVE/DELTA/UNKNOWN) |

## Laws (unchanged, now enforced in one place)

- **ONE AUTHORITY PER SUBSYSTEM.** Conflicts → the conflict graph. Usage →
  the provider normalizer. Run spend/time → the run budget ledger. PASS → the
  local deterministic verifier.
- **UNKNOWN IS NOT ZERO.** A missing provider token field is `NOT_MEASURED`
  (value `null`), never `0`. A genuine measured `0` stays a distinct MEASURED 0.
- **NO SUMMING OF CUMULATIVE SAMPLES.** The semantics decide the reduction.
- **SILENCE IS NEVER SAFETY.** An undeclared writer scope fails closed; a
  dropped declaration is treated as a conflict.
- **A DEADLINE STOPS OPTIONAL WORK, NEVER VERIFICATION.** `verificationIntact`
  is always `true`.
- **PRIVILEGED CONTEXT IS FENCED.** A changed system prompt changes the runtime
  epoch and therefore every warm-worker key and cached artifact.
- **NO FABRICATED SAVINGS.** Speedup/token claims require MEASURED evidence;
  unknown tokens stay `NOT_MEASURED`; synthetic numbers are labeled.
- **CONCURRENCY FOLLOWS THE DECISION.** A compiled SERIAL or PARENT_DIRECT wave
  carries `concurrency: 1` by construction; only a PARALLEL decision carries a
  bound, and a budget downgrade lowers the NUMERAL with the verdict — never the
  parallel number after a refusal.
- **PACKING FOLLOWS THE DECISION.** A non-PARALLEL wave is re-packed into
  single-scope conflict rows at compile time, so a downstream executor cannot
  read a multi-scope `safe` row and parallelize a wave the policy refused.
- **ONE PLAN WAVE DERIVATION.** `computeSafeWaves` runs once, inside
  `compileExecutionPlan`; the controller consumes `compiledPlan.waves`
  verbatim. A re-introduced per-wave `planWave(` call is a HARD source-integrity
  failure (`forbidden` marker), not a warning.

## Owners

| Capability | Owner |
|---|---|
| Wave admission | `lib/delegation-safety.mjs` |
| Conflict verdicts | `lib/execution-conflict-graph-v16-15.mjs` |
| Task dependency topology | `lib/task-graph.mjs` (delegates conflicts) |
| Provider usage interpretation | `lib/provider-usage-normalizer-v16-17.mjs` |
| Run cumulative spend + deadline | `lib/run-budget-ledger-v16-17.mjs` |
| Runtime/privileged epoch | `lib/runtime-epoch.mjs` |
| Verification receipts / PASS | `lib/verification-receipt-cache-v16-12.mjs` + local verifier |
| Production composition | `pi/extensions/ues.ts` + `lib/parallel-coding-runtime-v16-15.mjs` |

## Remaining-architecture audit (V16.17 directive §4 areas)

Classified against the live tree with fresh evidence. `IMPLEMENTED` = new
V16.17 work; `ALREADY_FIXED` = a single authority already owns it in the
baseline and was NOT reopened; no area was left unclassified.

| Area | Classification | Evidence |
|---|---|---|
| PreparedAgentExecution | IMPLEMENTED (§1) | `prepareAgentExecution`/`sameExecution` in `lib/pi-rpc-pool.mjs`; one descriptor feeds prewarm and run; `test/v16-17-prepared-execution.test.mjs` |
| Execution Plan Compiler | IMPLEMENTED (§2) | `lib/execution-plan-compiler-v16-17.mjs` (order + conflicts + economy + ledger composed ONCE); ues.ts executes `compiledPlan.waves` verbatim; `test/v16-17-execution-plan.test.mjs` |
| Admission before expensive effects | IMPLEMENTED (§3) | compile-time `admission` record (`createWorktrees`, `prewarm`, `rpcChildren`, default-deny `deepseekCalls:0`/`browserLaunches:false`); executor gates worktree creation and prewarm from the record; the reserve callback aligns with the default-deny |
| Prewarm lease lifecycle | ALREADY_FIXED | pool `idleTimeoutMs`/`release`/`discard`; ues `discardUnconsumedPrewarm` via `wavePrewarmKeys`; `prewarmWaveWorkers` stops failed workers; honest warm-reuse accounting (V16.16); the pool now fails closed on a same-key + incompatible-spec fingerprint (V16.17 post-tag) |
| Multi-writer staging integration | **NOT_IMPLEMENTED** | The runtime integration authority (`lib/integration-transaction-v16-15.mjs`) applies each child patch DIRECTLY to the live root in deterministic order and reverses every applied patch on failure. That is transactional and ordered, but it is NOT staging-first: there is no transaction-owned staging worktree, no composition-sensitive verification in staging, and no single aggregate root mutation. The compiled plan now reports the honest label `transactional-direct-multi-writer` / `integrationStagingFirst: false`. A true staging-first implementation is left as future work; the V16.17 MASTER directive is therefore **not** fully complete. |
| Root generation staging fence | PARTIAL | A wave-start HEAD guard rejects a stale generation (`staleGeneration` → `FAILURE_CLASS.STALE`), and the integration transaction re-checks live-root identity before applying. This is a guard, NOT a staging-first fence: there is no staged aggregate apply. Do not read this row as staging-first integration. |
| Verification Proof DAG | ALREADY_FIXED | `planProofReuse` partition + `executeProofPlan` effectful half, wired in the wave loop |
| Canonical receipt identity | ALREADY_FIXED | `receiptCacheKey` (workspace fingerprint + gate name + command/args + policy digest + runtime identity + cwd) in `lib/verification-receipt-cache-v16-12.mjs`; receipts carry `stdoutSha256`/`stderrSha256` |
| Failure attribution/repair | ALREADY_FIXED | `classifyChildFailure` + `decideRetry` are the ONE authority (`lib/integration-transaction-v16-15.mjs`); `module.retryDecision` is a thin delegation receiving raw failure facts; identical-fingerprint escalation; one automatic retry |
| Wave-context singleflight | ALREADY_FIXED (scoped) | `hydrateRuntimeModule` joins concurrent hydrations through `entry.promise` (promise-join, counted), and one immutable capsule snapshot is built per wave per attempt. **Scope caveat:** this is MODULE-HYDRATION singleflight, not a per-child stable-prefix/AGENTS read singleflight; children still perform their own stable-prefix/AGENTS reads. Do not read this row as a claim that all per-child shared reads are deduplicated. |
| Thin ues.ts / transitive lazy loading | ALREADY_FIXED (policy-enforced) | heavy stacks only through `LAZY_RUNTIME_MODULES` (`test/v16-16-cold-start.test.mjs`, `test/execution-acceleration-wiring-v16-12.test.mjs` forbid static imports); the remaining static imports are policy-listed non-heavy helpers |
| Pi cold-start measurement | PARTIAL | `bench-v16-16-critical-path.mjs` scenario L measures isolated module import/hydration cells with stated budgets, and reports `NOT_MEASURED` with a reason where the Pi host makes isolation unsafe. **Scope caveat:** an isolated module import timing is NOT proof of a Pi HOST cold start; the real Pi host path is covered only by the `smoke:pi` / `accept:fresh-pi` acceptance domain, not by this bench cell. |
| Artifact/package/dead-code lifecycle | VERIFIED | `package.json#files` ships `lib/` + `pi/` + this doc; pack includes every v16-17 module; `.ues-work` is never packed |



## Not changed (already correct in the baseline)

The audit matrix distinguishes `CONFIRMED_GAP` from `ALREADY_FIXED` and
`NOT_APPLICABLE`. Items already owned by a single authority (integration
transaction, receipt identity, completion state machine, crash recovery,
sandbox identity) were left as-is; this release only removed the confirmed
second-authority / dropped-evidence / unknown-as-zero defects above.

## Verification

- `node --test test/v16-17-execution-core.test.mjs` — architecture invariants
  for §3–§10.
- `node --test test/v16-17-execution-plan.test.mjs` — §2 compile-once laws:
  order serialization evidence, decision-concurrency coupling, single-scope
  re-packing of non-PARALLEL waves, verbatim serial execution under
  `maxParallel=3`, and MEASURED history provenance reaching
  `decideParallelExecution`.
- `node --test test/v16-17-prepared-execution.test.mjs` — §1 one-descriptor
  prewarm/run compatibility plus same-key fingerprint fail-closed laws.
- `node --test test/v16-17-prepared-execution-production.test.mjs` — §1/§9 on
  the REAL shipped extension: one frozen prepared descriptor is consumed by the
  RPC pool, every fencing env key is bound to the run, and an expired run
  deadline refuses the wave before any child spawn.
- `node --test test/v16-17-structured-plan-production.test.mjs` — the run
  budget ledger exists exactly once on the real structured-plan path, with a
  real `runStartedAt` and honest `NOT_MEASURED` token accounting.
- `node --test test/v16-17-structured-plan-smoke.test.mjs` — bounded
  PRODUCTION smoke through `executeStructuredPlan` (one read-only + one writer,
  and two independent writers) in a real temporary Git repo: the ledger is
  active, children run in real worktrees, only declared source files integrate,
  and the local verifier remains the sole PASS authority.
- `node --test test/v16-17-structured-execution-meter.test.mjs` — the
  V16.17.1 deadline/context bridge: an absolute run deadline can only tighten
  (never extend), the real RPC resolver applies it after ordinary policy, the
  pool threads the ledger deadline into the real worker run boundary, and the
  measured wave-context chars settle without inventing provider tokens.
- `npm run integrity` — V16.17 source-integrity contracts pin the ONE-authority
  boundaries (including a `forbidden` marker that fails if a per-wave
  `planWave(` call is ever re-introduced), so a future edit cannot silently
  re-fork them.

## Post-tag semantic-fix record (v16.17.0 audit)

A post-tag source audit of `v16.17.0` found production-semantic holes that the
original release gate did not exercise. They are corrected on `main` and ship
as the `v16.17.1` hardening patch (no behavior change beyond the fixes below,
no publish from this document):

- **Run budget ledger is initialized exactly once.** `executeStructuredPlan`
  previously used `runBudgetLedger` without creating it, so the real
  wave-failure path threw `ReferenceError: runBudgetLedger is not defined`.
  Exactly ONE run-scoped ledger is now created from the canonical
  `rootPolicy.v16_6` budget with the real `runId` / `runStartedAt` / wall-clock
  config. A missing `runStartedAt` resolves to the current run start, never
  epoch 0 (`test/v16-17-structured-plan-production.test.mjs`).
- **Cumulative budget is runtime-cumulative.** The static plan is compiled once;
  each wave's admission reads the CURRENT ledger (wave N observes what waves
  1..N-1 settled) and may only NARROW concurrency, never widen it and never
  skip verification. CUMULATIVE counters sum across waves; PEAK/CAPACITY
  counters (`simultaneousCalls`, `activeWriterConcurrency`, `activeProcessSlots`)
  take the max, so two sequential waves of 2 peak at 2, never 4.
- **Run deadline is enforced during execution.** `remainingRunMs()` gates each
  expensive phase (worktree creation, prewarm, RPC child, verification,
  integration); a child timeout is clamped by `min(policyChildTimeout,
  remainingRunMs)`; an expiry before required verification returns an honest
  TIMED_OUT/BLOCKED and never claims PASS.
- **Critical-path history type drift resolved.** The history supplier is
  resolved exactly once, so MEASURED component provenance reaches
  `decideParallelExecution` instead of silently falling back to ESTIMATED.
- **Prepare-once is real.** `runAgentRpc` passes the ONE prepared descriptor to
  both prewarm and run (correctness-sensitive fencing env is part of the
  prepared spec); the pool fails closed on a same-key + incompatible-spec
  fingerprint instead of reusing a drifted warm worker.
- **Capsule failure fails closed.** If `buildChildCapsule` throws, a
  deterministic fallback inline-renders the required shared facts and the child
  delta; if that also fails, no child is spawned and the wave reports a context
  assembly failure. A child is never handed a snapshot reference it cannot
  resolve.
- **Multi-writer integration is NOT staging-first.** The honest label is
  `transactional-direct-multi-writer` (see the remaining-architecture table).
  This is a correction of a prior over-claim, not a new capability.

### Additional production defects found while building the smoke

- **Runtime artifacts leaked into isolated worktrees.** A writer child's run
  telemetry and journal root resolved from its worktree `cwd`, so `.ues-work`
  (and `.ues-traces`) were written INSIDE the sandbox. The integration
  preflight then refused the whole wave with `forbidden-path`/`root-overlap`,
  which made every writer wave unintegrable on a root that had ever run UES.
  Telemetry/journal/ownership roots now resolve to the sandbox OWNER root, and
  each sandbox is stripped of UES runtime dirs before integration. The live
  root is never mutated by the hygiene step, and the sandbox may only ever
  integrate its declared source files.
- **Delegation scope double-wrap.** The wave executor passed the fleet's
  normalized scope (`scope.original`, i.e. the wave scope) into
  `runPreparedChild` instead of the prepared item, so the delegated child
  received the wrong task/cwd. It now resolves the prepared item by task id.
  This was pre-existing at `v16.17.0` and blocked the real child path.

## V16.17.1 hardening record

The `v16.17.1` patch release carries the release-gate and transport fixes made
after the post-tag audit. Behavior is unchanged outside the defects below:

- **Bounded RPC deadlines are never inflated.** `resolveRpcRunTimeouts` treats
  an explicit `hardTimeoutMs` as a cap (the old 30s floor could raise a 5s
  run-deadline cap back to 30s), and `createAdaptiveDeadline` preserves an
  explicit sub-second caller deadline instead of flooring it.
- **Absolute structured-run deadlines survive the transport boundary.** The
  ledger registers its `runDeadlineAt` in the structured-execution meter; the
  pool resolves `min(registered, caller)` at the worker boundary, an expired
  run fails closed before spawn, and a late startup failure cannot renew time
  through the CLI fallback.
- **Pool metadata is one record.** `workers` and `workerSpecs` are deleted
  together via `forgetWorker` on every path (prune, spec mismatch, run failure,
  prewarm failure, discard); `stopAll` clears specs and reservations.
- **Measured wave context settles honestly.** Production hydration of
  `PARALLEL_CODING_RUNTIME` goes through the metered wrapper
  (`lib/parallel-coding-runtime-metered-v16-17.mjs`); the canonical measured
  char total (shared snapshot ONCE + child deltas) bridges to the ledger's
  cumulative `childContextChars`, while provider tokens stay `NOT_MEASURED`.
- **Release gate covers the regressions.** `npm run eval:v16.17` includes
  `test/v16-17-structured-execution-meter.test.mjs`,
  `test/process-lifecycle-v16-17-1.test.mjs`,
  `test/service-lifecycle-v16-17-1.test.mjs`,
  `test/agent-loop-production-abort-v16-17-1.test.mjs` and
  `test/process-runner.test.mjs`; `scripts/check-release-consistency.mjs`
  requires them.
- **Non-blocking process-tree termination on every hot path.**
  `terminateProcessTreeAsync` (async helper behind its own deadline, per-pid
  in-flight dedup, structured kill result) is used by the supervised runner,
  `process-runner`, `git-async-runtime`, the RPC pool, the browser worker
  client, the LSP pool, the `ues.ts` CLI child runner and both browser-cleanup
  defaults. The synchronous legacy owner stays only for sync decision
  branches with a bounded Windows path. Drain fallbacks arm before the kill
  helper; `exit` settles bounded even when a grandchild holds the pipe.
- **Byte-accurate bounded output.** The shared `createTailByteBuffer` owner
  (O(limit) memory, byte accounting) backs `process-runner` and
  `git-async-runtime`; render shape (tail-only) and the pinned
  `maxBuffer`/`maxBytes` contracts are unchanged. The supervised-runner
  `createBoundedOutputBuffer` owner is likewise O(limit) runtime storage (not
  just bounded rendering): fixed bounded head plus rolling bounded tail plus a
  total counter, middle bytes never retained, trimmed slices copied, retained
  payload `retainedBytes` (= headKept + tailKept) <= limitBytes plus at most
  one in-flight chunk.
- **Managed-service hot path.** Async bounded log queue, memory-tail
  readiness, bounded shutdown with honest `stop-timeout` retention, no blind
  kill of stale pids. Covered by `test/service-lifecycle-v16-17-1.test.mjs`
  on real OS processes.
- **Agent loop production wiring.** `test/agent-loop-production-abort-v16-17-1.test.mjs`
  proves the real watchdog aborts a live repeated-narration stream exactly
  once, the stream really stops, one bounded recovery follows, and the budget
  fails closed.

### V16.17.1 honesty notes (NOT_IMPLEMENTED / PARTIAL)

- Multi-writer staging-first integration: NOT_IMPLEMENTED. The current
  integration remains transactional-direct-multi-writer with the local
  verifier as the sole PASS authority.
- Pi host cold-start on a real device: PARTIAL. Module-import level
  lazy-hydration (`lib/lazy-runtime.mjs`, cold-start eval suite) is measured;
  no real-device wall-clock cold-start was taken for this patch.
- Provider token usage: NOT_MEASURED wherever the provider reports no usage
  metadata (null, never estimated; `chars/4` is never presented as tokens).
