# V16.18 — Adaptive Full-Power Optimization

> Status labels used in this document:
> **IMPLEMENTED** (code + tests on `main`), **MEASURED** (counted by a script in
> this repository, reproducible), **SIMULATED** (a model of behaviour, not a
> runtime observation), **PARTIAL** (some of the intent is implemented),
> **NOT_IMPLEMENTED**, **NOT_MEASURED** (no truthful measurement exists).

## Why this release exists

V16.17.1 hardened the process lifecycle and consolidated the execution core. The
remaining problem was not capability — it was **over-orchestration**: a task
whose scope nobody had looked at yet could pay for STANDARD context, STANDARD
tool surface, STANDARD skill budget, STANDARD delegation authority, planner
roles, memory ranking, capability inventory and LSP infrastructure *before* any
runtime evidence proved those were needed.

V16.18 changes **WHEN** the existing capabilities activate. It removes none of
them.

The architecture is now:

```
SMALL TASK   -> cheap classification -> lightweight discovery
             -> direct parent execution -> targeted verification
MEDIUM TASK  -> balanced context/orchestration
             -> semantic/affected-test intelligence when useful
             -> bounded delegation when useful -> stronger verification
HARD TASK    -> full DEEP capability, unchanged
```

Core principle: **CAPABILITY MUST NOT BE REMOVED. OVERHEAD MUST BECOME ADAPTIVE.**

## Confirmed root causes (measured against the pre-change source)

1. **UNKNOWN SCOPE WAS TREATED AS BROAD.** `classifyExecutionComplexity()` mapped
   `affectedFiles = undefined` to `-1`, which failed the `easy` classifier, so
   `boundedSingleFile` was false and the profile fell through to the BALANCED
   default. A first turn therefore paid STANDARD spend before anyone had looked
   at the repository. **Fixed.**
2. **THE LSP STACK WAS EAGERLY REACHABLE.** Two static imports
   (`pi/extensions/ues.ts` -> `shutdownLspPool`, and
   `lib/fast-static-verification.mjs` -> `diagnoseCode`) put the whole
   language-server stack on the cold path of every task, including a docs or
   config task that can never produce a diagnostic. **Fixed.**
3. **DUPLICATE WORKSPACE CAPTURES PER RUN.** `workspaceDecisionInputs()`,
   `boundedWorkspaceDiff()` and `boundedWorkspaceHead()` each took their own full
   `captureWorkspaceStateV2()` (four Git processes plus an untracked-content hash
   each) to answer three questions about the same repository state. **Fixed.**
4. **CONTEXT HAD ONE STAGE.** Every non-FAST run built the full manifest
   (semantic index, hierarchy, repository graph, memory ranking, capability
   fabric) even when a handful of declared files were sufficient. **Fixed.**
5. **THE PLANNER COULD RUN ON A PROVEN BOUNDED EDIT.** `requirePlanCheck` is the
   right owner of *when* a plan is needed, but nothing removed the architect +
   plan-checker turn for a change the runtime had already proven bounded.
   **Fixed** (value gate).
6. **INDEPENDENT CONCURRENCY CEILINGS.** The test runner, RPC pool, child fleet,
   LSP pool, semantic index, writer lane, browser lane and service manager each
   resolved their own local maximum. **PARTIAL** (see *Remaining limitations*).

## What changed

### 1. Provisional FAST discovery — IMPLEMENTED

`lib/orchestration-budget-v16-6.mjs`

* New exported concepts: `PROVISIONAL_FAST_DISCOVERY_BOUNDS` (max 3 candidate
  files, 1 subsystem, 5 discovery operations),
  `PROVISIONAL_EXCLUDED_CHANGE_KINDS` (`security`, `architecture`, `data`),
  `PROVISIONAL_BLOCKING_SIGNALS`, `affectedScopeKnown()`,
  `provisionalFastDiscoveryEligible()`, `escalateProvisionalDiscovery()`.
* The provisional lane is applied **before** every escalation floor, so it is a
  spending **ceiling**: everything after it can only raise the profile.
* It can never open for: a retry, high/critical risk, long-horizon work, a
  verifier/runtime failure history, positive evidence score, a sensitive domain,
  a security/architecture/data change kind, or any declared risk signal.
* **UNKNOWN IS NEUTRAL, NOT TINY.** The classification still refuses to call an
  unknown-scope task `easy`; the budget records
  `provisionalFastDiscovery.scopeKnownAtStart = false` and `resolved = false`, and
  the lane is an **obligation** to re-decide, not a claim about the task.
* **A KNOWN scope needs runtime proof.** A caller-declared file count no longer
  opens the lane by itself: `known-scope-not-runtime-proven` blocks it. Only a
  bounded discovery that actually *grounded* <=3 candidate files in <=1 subsystem
  (`runtime-proven-bounded-scope`) keeps a small fix in the light lane — which is
  exactly the V16.18 §7 requirement that a user need not know the file path.

`escalateProvisionalDiscovery(budget, observation)` is the **lossless escalation
half**. It recomputes the whole decision from the same refinement inputs merged
with the observed discovery facts, so a run that started cheap obtains every
existing capability in the SAME run:

| observation | outcome |
| --- | --- |
| <=3 files, <=1 subsystem | `bounded` (stays FAST) |
| >3 files or >1 subsystem | `escalated-balanced` |
| bounded discovery could not ground the scope (`insufficient`) | `escalated-balanced` |
| competing root causes / unclear dependency ownership / multi-module tests | `escalated-balanced` |
| runtime found auth/security/payment/schema evidence | `escalated-by-safety-floor` (DEEP) |
| repeated verifier failure | `escalated-deep` (via the retry refinement) |

### 2. Run-scoped workspace state — IMPLEMENTED

`lib/workspace-state-owner.mjs` gains `createRunWorkspaceStateOwner()` beside the
existing per-capture `createWorkspaceStateOwner()`. One immutable generation is
shared by admission, budget, context, cache, advisor, telemetry, hygiene and the
planner; a real mutation invalidates it **once** and the next reader performs
**exactly one** fresh capture. `isCurrent()` fails closed, so no cache, advisor or
verifier can be handed a pre-edit identity as if it were current.

`pi/extensions/ues.ts` wires it as `ACTIVE_RUN_WORKSPACE_OWNER` with
`runWorkspaceStateFor()`, `invalidateRunWorkspaceState()` (called at the
post-write boundary, next to the shared-context ledger epoch bump),
`refreshRunWorkspaceState()` and `clearActiveRunWorkspaceOwner()` in the run's
`finally`. `workspaceDecisionInputs()`, `boundedWorkspaceDiff()` and
`boundedWorkspaceHead()` now accept the shared generation instead of capturing
their own.

The snapshot itself is unchanged: it is still the proven
`captureWorkspaceStateV2()` output, wrapped, never weakened.

### 3. True lazy LSP hydration — IMPLEMENTED

* `lib/lazy-runtime.mjs` gains `LAZY_RUNTIME_MODULES.LSP_PROVIDER` (part of the
  `CODE` stack) as the ONE owner of the cached, joined, single-flight hydration.
* `lib/fast-static-verification.mjs` stays **eager as verifier POLICY** but no
  longer statically imports the provider; it hydrates on **first real diagnostic
  use** only. A hydration failure degrades to an incomplete result that the
  existing completeness gate already treats as "not proven" — never a fake PASS.
* `pi/extensions/ues.ts` no longer imports `shutdownLspPool` statically. The
  local `shutdownLspPool()` wrapper returns immediately
  (`lsp-provider-never-hydrated`) when the stack was never loaded, so a session
  end does not import the whole LSP stack to stop an empty pool. When the stack
  WAS hydrated, shutdown still runs through the module that owns the pool, so no
  `tsserver` / `typescript-language-server` process can leak.
* Verified by static import-graph analysis: `lsp-provider` is **no longer
  eagerly reachable** from `pi/extensions/ues.ts`.

### 4. Two-stage context pipeline — IMPLEMENTED

`lib/context-engine-v11.mjs` gains `CONTEXT_PIPELINE_STAGE`,
`buildLightTaskContext()` and `lightContextInsufficient()`.

`LIGHT_CONTEXT` contains only the task text, declared/referenced and changed
files, nearest instructions, a bounded name search, bounded file ranges, the
direct failure delta and the known verification requirement. It builds **no**
semantic index, **no** hierarchy, **no** repository graph, **no** memory ranking
and **no** capability inventory — and it reports that honestly in
`performance.*Built = false` and `memoryRetrieval.skipped = "light-stage"`.

`FULL_CONTEXT` (`buildAdaptiveTaskContext`) is unchanged and retains every
capability. `lightContextInsufficient()` is the escalation decision: no bounded
excerpt, no scope evidence, a light-stage gap, context quality below threshold, a
high-risk domain, cross-subsystem scope, competing root causes, unclear
dependency ownership, multi-module tests, an explicit full-context request or a
verification-detail requirement all escalate. LIGHT -> FULL is **lossless** and
bounded to one escalation.

`pi/extensions/ues.ts` admits LIGHT only for `FAST` + attempt 1 + non-high risk +
non-long-horizon + no browser, and records the resolved stage in
`contextStageRecord` on the `context.after-build` hook, so a light run cannot
silently claim full intelligence (or the reverse).

**Post-release audit (hardening pass).** `lightContextInsufficient()` used to read
`quality.recall`, a field the quality owner never emits (`measureContextQuality()`
reports `requiredFileRecall` and `checks.requiredRecallAcceptable`). The
documented "context quality below threshold" escalation was therefore a silent
no-op: a LIGHT pack that missed a declared file could still be treated as
sufficient. It now escalates on the measured recall (including a measured zero)
and on the quality owner's explicit verdict, and never on an unmeasured one.
Test D6 pins a pack where one of two declared files is absent.

### 5. Planner value gate — IMPLEMENTED

`lib/planning-speed-policy.mjs` gains `plannerValueGate()`. It can only turn the
planner **off** for a change the task policy and the runtime evidence both declare
bounded, and it can **never** turn it on against the task policy, nor remove a
floor: high/critical risk, long-horizon, explicit phases, architecture evidence,
ambiguous ownership, unclear dependency ownership, cross-package dependency,
>3 candidate files, >1 subsystem and repeated implementation failure all keep the
planner. `pi/extensions/ues.ts` gates `planningGate` on it and journals the
decision (`planning.value-gate`).

Planning recovery keeps its bounded, fingerprint-based behaviour
(`classifyPlanningFailure`, `planningFailureFingerprint`); V16.18 adds nothing
that would retry a deterministic planning failure blindly.

### 6. Global resource governor — PARTIAL

`lib/resource-governor-v16-18.mjs` is a **lease coordinator**, not a scheduler. It
defines classes (`CPU_HEAVY`, `IO_HEAVY`, `MODEL_CHILD`, `WRITER`, `LSP`,
`BROWSER`, `SERVICE`) with conservative global caps, and it can only **narrow**
what the existing subsystem owners already allow.

Laws: a lease requires an explicit class; global caps make nested oversubscription
structurally impossible; re-entrancy is **depth, not width** (which is why the
governor is deadlock-free); every exit path — success, throw, abort, timeout —
releases, and a release is idempotent; `state()` reports counted metrics only.

`pi/extensions/ues.ts` guards the **advisor consult** with a `MODEL_CHILD` lease
and fails **open** on refusal (`RESOURCE_LEASE_REFUSED`): AUTO journals
`advisor.resource-lease-refused` and continues locally, FORCE keeps its existing
fail-loudly contract. This is the V16.18 §15 requirement that an unavailable
advisor must never block the coding task.

See *Remaining limitations* for what is deliberately **not** yet leased.

### 7. Weak-model decision capsule + failure delta — IMPLEMENTED

`lib/leaf-runtime-optimizer.mjs` gains `buildDecisionCapsule()` and
`renderDecisionCapsule()`. The capsule is generated **deterministically** from
state the runtime already holds (GOAL, KNOWN, KNOWN FILES, CURRENT FAILURE,
UNKNOWN, CURRENT ACTION, VERIFICATION REQUIRED, DO NOT REPEAT). It is not a
planner: it adds no plan, no authority and no reasoning budget. A section with no
evidence renders as `UNKNOWN` — it never guesses, and it never emits `undefined`,
`null` or `[object Object]`.

It is attached only to a LIGHT/FAST turn in `pi/extensions/ues.ts`. The bounded
`failureDelta()` (pre-existing owner) feeds its CURRENT FAILURE line.

### 8. Post-audit hardening (stale generation + stage-keyed cache) — IMPLEMENTED

A negative-space audit of the first V16.18 wiring found two places where a
LIGHT-stage reader could observe the wrong generation:

* the context cache was keyed without the stage, so a LIGHT-eligible turn
  could read a stored FULL pack (token waste) and a stored LIGHT pack could be
  mistaken for full intelligence. Only FULL packs are now cached, and only a
  run that needs FULL reads the cache.
* the consult-cache identity, the patch-review diff/grounding and the
  pre-verification/completion snapshots read the run-start observation rather
  than the live generation. All of them now read through
  `runWorkspaceStateFor()` (one refresh after a mutation, zero captures for
  read-only turns), and post-write invalidation runs even when the
  evidence ledger is absent.

Pinned by `test/adaptive-efficiency-v16-18.test.mjs` section K and by the
`Only FULL_CONTEXT packs are cached` / live-generation markers in the V16.18
source-integrity contract.

## Existing owners reused (no new duplicate subsystem)

| Capability | Owner (reused) |
| --- | --- |
| Execution profile / spend decision | `lib/orchestration-budget-v16-6.mjs` |
| Run budget surface | `lib/v16-6-runtime.mjs` |
| Workspace identity + capture | `lib/workspace-fingerprint.mjs` (wrapped, unchanged) |
| Workspace state generation | `lib/workspace-state-owner.mjs` (extended, not forked) |
| Lazy hydration + single-flight | `lib/lazy-runtime.mjs` (extended) |
| Verifier policy | `lib/fast-static-verification.mjs` (still eager as POLICY) |
| Context intelligence | `lib/context-engine-v11.mjs`, `lib/context-manifest.mjs` |
| Context quality | `lib/context-quality.mjs` |
| Planner gating | `lib/planning-speed-policy.mjs` |
| Planning recovery | `lib/planning-recovery.mjs` |
| Failure delta / leaf policy | `lib/leaf-runtime-optimizer.mjs` |
| Verification authority | `lib/verification-ladder-v16-10.mjs`, local verifier |
| Deferred tool surface | `lib/deferred-tool-hydration.mjs` |

**New owners added: exactly one** — `lib/resource-governor-v16-18.mjs`. It was
necessary because the *shared ceiling* between the independently-limited
subsystems did not exist anywhere, and adding it to any one subsystem would have
made that subsystem the authority over the others.

## Runtime gap audit (hardening pass)

This pass re-checked every V16.18 claim against the live wiring rather than the
marker list. The result does not upgrade any label:

| Area | Audit evidence | Status |
| --- | --- | --- |
| Provisional lane | Built in `computeOrchestrationBudget()`; resolved at run start from changed-file evidence via `resolveProvisionalFastDiscovery()` in `pi/extensions/ues.ts`. No pre-turn symbol search. | **IMPLEMENTED** for workspace evidence; **NOT_IMPLEMENTED** for pre-turn symbol discovery |
| LIGHT/FULL context | `buildLightTaskContext()` + `lightContextInsufficient()` are wired in `runAgent()`, only for FAST attempt 1. The quality-threshold branch was a no-op and is now fixed (test D6). | **IMPLEMENTED** for the admitted lane; **PARTIAL** overall (BALANCED/DEEP always FULL) |
| Workspace generation | `ACTIVE_RUN_WORKSPACE_OWNER`, `runWorkspaceStateFor()`, post-write invalidation and run-end clear are wired; readers use the live generation. | **IMPLEMENTED** |
| Lazy LSP | No static `lsp-provider` edge from the extension or verifier; shutdown short-circuits when un-hydrated. | **IMPLEMENTED** |
| Planner value gate | `plannerValueGate()` gates `planningGate`; journals `planning.value-gate`. | **IMPLEMENTED** |
| Resource governor | Advisor consult takes a `MODEL_CHILD` lease and fails open. No other subsystem takes leases. | **PARTIAL** (unchanged, explicitly documented) |
| Decision capsule | Attached to FAST or LIGHT turns only, from runtime-held state. | **IMPLEMENTED** |
| Browser / live advisor / tokens | No live session and no provider token accounting in this environment. | **NOT_MEASURED** |

No safety floor was lowered by this audit. Unproven gaps remain labelled
**PARTIAL** or **NOT_IMPLEMENTED** above and in *Remaining limitations*.

## Verification

* `npm run eval:v16.18` — the required regression suite
  (`test/adaptive-efficiency-v16-18.test.mjs`, 52 tests) plus the source-integrity
  contracts (`test/source-integrity-v16-18.test.mjs`).
* `npm run bench:v16.18` — the adaptive-efficiency benchmark; it **exits non-zero**
  if any measured invariant is false.
* `npm run integrity`, `npm run runtime:exports`, `npm run syntax`, `npm test`.
* `npm run release:verify` — the full fresh release gate (unchanged).

## Measured results

All numbers below are **MEASURED** on this host by
`scripts/bench-v16-18-adaptive-efficiency.mjs` (median of 3 runs). Provider token
usage is **NOT_MEASURED**: no provider session exists offline, so no token saving
is claimed anywhere in this document.

### Cold path

| Metric | Before | After |
| --- | --- | --- |
| LSP provider eagerly reachable from `pi/extensions/ues.ts` | `true` | **`false`** |
| Eager lib modules reachable | 137 | **136** |
| Eager lib import (fresh process, median) | ~186 ms | ~182 ms |

The eager-module count changes by one because the LSP stack is no longer a
*static* dependency; the cold-path import time difference is small and within
run-to-run noise, so **no cold-start elimination is claimed**. The real win is
that the whole language-server stack (tsserver resolution, diagnostics budget,
managed pool, process supervisor) is no longer loaded for a docs/config task.

### Adaptive spend

| Scenario | Profile | Provisional | Context ceiling | Advertised tools | Advisor turns | Children | LIGHT ctx | FULL ctx |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| A tiny (typo/metadata) | FAST | yes | 8 000 | 6 | 0 | 1 | ~43 ms | ~151 ms |
| B small code fix | FAST | yes | 8 000 | 6 | 0 | 1 | ~38 ms | ~150 ms |
| C medium (6 files) | BALANCED | no | 20 000 | 12 | 2 | 2 | ~37 ms | ~249 ms |
| D hard (security) | DEEP | no | 48 000 | 20 | 4 | 3 | ~52 ms | ~161 ms |
| E background service | FAST | yes | 8 000 | 6 | 0 | 1 | ~37 ms | ~173 ms |
| F release-critical (deploy) | DEEP | no | 48 000 | 20 | 4 | 3 | ~33 ms | ~178 ms |

The `LIGHT ctx` column is the measured wall time of `buildLightTaskContext()`; the
`FULL ctx` column is the measured wall time of `buildAdaptiveTaskContext()` on the
same fixture. A LIGHT stage is therefore roughly **3-6x cheaper in wall time** on
these fixtures, and it performs no semantic index, hierarchy, repository graph,
memory retrieval or capability inventory at all.

### Honest labels

| Claim | Label |
| --- | --- |
| Unknown scope no longer forces BALANCED | **IMPLEMENTED + MEASURED** |
| Provisional lane escalates losslessly | **IMPLEMENTED + MEASURED** (unit) |
| LSP no longer eagerly reachable | **IMPLEMENTED + MEASURED** (static graph) |
| One workspace generation per run | **IMPLEMENTED + MEASURED** (unit) |
| LIGHT/FULL context two-stage | **IMPLEMENTED + MEASURED** (wall time) |
| Planner value gate | **IMPLEMENTED + MEASURED** (unit) |
| Resource governor + advisor lease | **IMPLEMENTED + MEASURED** (unit) |
| Weak-model decision capsule | **IMPLEMENTED + MEASURED** (unit) |
| Cold-start elimination | **NOT_MEASURED** (only the LSP eager edge changed) |
| Token reduction | **NOT_MEASURED** (no provider session offline) |
| Browser / live-advisor scenarios | **NOT_MEASURED** (require a real session) |

## Remaining limitations (PARTIAL / NOT_IMPLEMENTED)

* **The resource governor is integrated at ONE point.** Only the advisor consult
  is lease-guarded. The test runner, RPC worker pool, subagent fleet, LSP pool,
  semantic index, writer lane, browser lane and service manager keep their own
  local limits and do **not** yet take leases. The governor exists, is tested and
  can only narrow, but full coverage is **PARTIAL**. Adding leases to those owners
  is a follow-up with real integration-test risk that this release does not take.
* **LIGHT_CONTEXT is admitted only for the FAST/attempt-1 lane.** BALANCED and
  DEEP runs still build the full manifest unconditionally. A medium task that
  turns out to be narrow does not currently start light. **PARTIAL.**
* **The provisional lane resolves from workspace evidence and retry evidence.**
  There is no runtime *symbol-search* discovery step that grounds candidate files
  before the first model turn; the bounded discovery is performed by the model's
  own first tool calls and by the LIGHT context stage's name search. A dedicated
  pre-turn discovery pass is **NOT_IMPLEMENTED**.
* **Advisor/browser AUTO fail-open is unchanged from V16.17.1** apart from the new
  lease refusal path. A live-provider fail-open test is **NOT_MEASURED** offline.
* **No provider token accounting** was added. Token economy remains
  **NOT_MEASURED**.
* The V16.17.1 process-lifecycle hardening was **not touched**: async bounded
  Windows process-tree teardown, exit/close drain handling, inherited pipes,
  bounded stdout/stderr capture, service lifecycle, RPC deadline propagation, the
  absolute deadline, worker cleanup and the agent narration watchdog are all
  preserved verbatim.

## Compatibility

* Public profile vocabulary is unchanged: **FAST / BALANCED / DEEP**.
* `provisionalFastDiscovery` is an **internal** state, not a fourth public
  profile.
* No permission, safety, containment or verification setting is weakened. The
  local verifier remains the only PASS authority, and
  `npm run release:verify` still requires fresh full gates.
* `lib/fast-static-verification.mjs` remains eagerly imported as verifier policy;
  only the module it reaches for is now hydrated on demand.
