The named-combos pipeline dropdown offered four engines (headroom,
session-dedup, ccr, llmlingua) that stackedPipelineStepSchema rejects, so
selecting one made PUT /api/context/combos/[id] return HTTP 400 while
saveCombo swallowed the non-OK response (if (!res.ok) return). Editing the
default 'Standard Savings' combo and changing an engine reproduced the 400.
- Add canonical STACKED_PIPELINE_ENGINE_INTENSITIES next to the schema as the
single source of truth; the client dropdown imports it so it can never drift
from the discriminated union the API validates against.
- Surface save errors and empty-name/empty-pipeline validation in the editor
instead of failing silently.
- Add a parity unit test asserting the UI engine map equals the schema union
and that every (engine, intensity) the UI emits is accepted.
Integrated into release/v3.8.37 — golden-lock for provider.ts translate-path. Cherry-picked onto release tip; snapshot regenerated against the current provider set (UPDATE_GOLDEN=1, 167 entries); golden test 3/3 deterministic.
Integrated into release/v3.8.37 — computeFinishReason finalizes tool_calls on early stream end (Responses translator). Cherry-picked onto release tip; responses-translation-fixes 29/29 green.
The headroom proxy lifecycle (#4649) reads HEADROOM_URL (src/lib/headroom/detect.ts,
default http://localhost:8787) but it was missing from the env contract, tripping
check:env-doc-sync. Adds the var to both .env.example (commented, has a default) and
the Proxy Health table in ENVIRONMENT.md.
Integrated into release/v3.8.37 — render server-masked key verbatim (drop redundant maskKey call). Note: release's maskKey already guards '****' (since v3.8.34), so this is a safe simplification; added a contract test pinning the **** passthrough invariant (2/2 green, would fail against the pre-guard maskKey = the historical double-mask bug).
Implements improvements 1-4 from the v3.8.36 release benchmark (_tasks/release-bench/v3.8.36/PLANO-MELHORIA.md):
1. Quality Ratchet decoupled from flaky coverage (ci.yml): the shard→coverage→ratchet
chain meant a single flaky Coverage Shard SKIPPED the whole Quality Ratchet on the
release PR (v3.8.36 #4854), so cycle drift only surfaced post-merge in #5029. The job
now runs on !cancelled(); coverage download is continue-on-error and the ratchet runs
--allow-missing, so the DETERMINISTIC gates (eslint/complexity/cognitive/duplication/
codeql) stay blocking even when coverage is unavailable.
2. Fast-path drift gates (quality.yml PR→release): added check:complexity,
check:cognitive-complexity, and a new lightweight check:pack-policy (pack-artifact
unexpected-files check WITHOUT a build, via --policy-only) so drift + stray-tarball-file
regressions are caught/rebaselined PER-PR instead of cascading onto the release PR.
3. Build heap default 4096→8192 MB (build-next-isolated.mjs): the clean graph peaks
~3.9 GB and brushed the old 4 GB ceiling; 8 GB gives headroom. Comment notes heap is
NOT the fix for a poisoned scope (run check:build-scope instead).
4. check:build-scope gate (new): fails if .ts/.tsx/.js/.jsx files in the tsconfig scope
exceed a threshold — catches worktrees/cruft leaking into the build scope (the v3.8.36
OOM root cause: 355,215 vs 4,547 files) BEFORE it detonates next build. Wired into the
fast-path.
Root cause of the local build:release OOM/GC-livelock (deploy blocker, 2026-06-25):
tsconfig.json uses include: ["**/*.ts","**/*.tsx","**/*.js","**/*.jsx"] (recursive
glob) but exclude did NOT list .claude — where git worktrees live (.claude/worktrees/).
With 69 active port-* worktrees, the TS scope was 355,215 files (352,261 of them inside
.claude/worktrees) vs 4,547 real source files. next build's type-check/scan processed ~70x
the codebase, OOMing at 4GB AND 16GB and GC-livelocking at 32GB/64GB. CI built fine because
its checkout is clean (no worktrees). After excluding .claude/.worktrees, build:release
completes in 17m with the DEFAULT 4GB heap.
Changes:
- tsconfig.json exclude: + .claude .worktrees .source coverage @omniroute .tmp dist _ideia;
removed 6 stale entries for dirs that no longer exist.
- .dockerignore: + .claude .source (the _* glob already covered underscore dirs).
- CLAUDE.md: standardize ALL worktrees under .claude/worktrees/ (was split with .worktrees/),
the single gitignored + build-excluded location the native EnterWorktree tool uses.
Replace weak Math.random-based ID generation with crypto.randomUUID() in quota pool, quota group, and migration runner FTS5 probe table name generation. Also remove unnecessary typeof-gated fallback that only ran on ancient Node versions.