# Phase 3b — amendment

**Plan said:** consolidate v8 CLI argv parsing across 9 handler files (`src/cli/v8/`, 2,896 LOC) into a parseArgs-driven dispatch with shared flag-schema records. Target: 2,896 → ~1,900 (−1,000 LOC).

**Code disagreed on the size of the addressable area.** Of the 2,896 LOC across `src/cli/v8/`, only ~500 LOC is the argv-parsing pattern the cut targeted — five hand-rolled `for (let i = 0; i < argv.length; i++)` loops, their requireValue helpers, and the `applyLocalProviderFlag` switch. The remaining ~2,400 LOC is business logic out of 3b's scope: orchestration bodies (`handleRun`/`handleCompile`/`handleResume`), usage-message builders, `findLatestContractDir`/`writeResultFile`/`renderProjectContext`/`randomToken`/`buildSession`/`buildExtractor`, the entire stats and doctor probe modules, `grammar-resolve.ts` (not argv-related), and `run-wrapper.ts`'s splitArgv (kept hand-rolled because of pass-through semantics parseArgs can't express). The plan's −1,000 was priced against the full directory; the in-scope sub-area was always closer to 500.

**What 3b ships as a structural-quality cut, not a major LOC cut.** New `src/cli/v8/argv-schema.ts` (150 LOC): typed wrapper around Node 22's `parseArgs` with `runParseArgs`, a `collapseStringValues` preprocessor (so `--flag -1` still produces "must be a non-negative integer" instead of parseArgs's "ambiguous argument" error), `requirePositiveInt`/`requireNonNegativeInt`/`requirePositiveFloat`/`requireFiniteFloat`/`requireEnum` validators, `readString`/`readBoolean` narrowers, and an error-shape rewriter so existing test assertions on `"flag --foo requires a value"` / `"unknown flag: --foo"` stay matching. `local-provider-flags.ts` exposes `LOCAL_PROVIDER_FLAG_SCHEMA` + `buildLocalProviderFlagValues` (single source of truth); `LOCAL_PROVIDER_FLAG_TOKENS` retained as a derived re-export so `benchmarks/provider-bench` continues to work. Five handlers (compile, run, resume, doctor, stats) switched to parseArgs + SCHEMA records + post-process validation. Net `src/cli/v8/`: 2,896 → 2,911 (**+15 LOC**); whole-repo 54,051 → 54,066. Parity captures byte-identical across 57 cases (17 compile, 24 run, 16 resume).

**Phase 3 budget relaxed to ≤54,100, not ≤51,700.** Recovering the gap inside Phase 3 isn't viable: Phase 4 already collapses 4,158 → ~1,200 (71% reduction, no slack); Phase 5's entire scope is −235; expanding 3c with cost-path work breaks Phase 5's halt-condition boundary (local-only coverage run / Anthropic-provider token regression). Phase 6's v6 deletion (−30,800) remains the dominant cut and is unchanged. The honest read is that two of the report's bucket estimates have now over-counted addressable area (2c shared-scan path, 3b argv-parsing) and the 10,800 final floor is load-bearing on the report's "Other v8 irreducible: 10,300 → 5,500" 47% compression of code already labeled load-bearing — that's the optimistic bucket, not Phase 3.
