Skip to content

fix(ci,api): green main again — the four breaks that stopped every deploy for five days - #770

Merged
serge-ivo merged 3 commits into
mainfrom
fix/ci-and-deploy-regressions
Sep 6, 2026
Merged

fix(ci,api): green main again — the four breaks that stopped every deploy for five days#770
serge-ivo merged 3 commits into
mainfrom
fix/ci-and-deploy-regressions

Conversation

@serge-ivo

Copy link
Copy Markdown
Contributor

Main has been red since 50aecb9 (2026-09-01) and the API Worker has not deployed since 5876486. Production is running 5876486; everything after it — including d5701824's prompt-section tracing and 1e038c43's engine-invocation-mode change — is undeployed.

Four independent breaks. Main stays red until all four are gone, so they land together.

1. File-size ratchet (#302) — the one that made CI red

Three files grew without the pin move the guard asks for:

FilePinActualFrom
workers/api/src/routes/coding.ts810 → 815+51e038c43 (#731)
agents/coder/web/src/CodingTab.tsx1478 → 1490+121e038c43 (#731)
workers/api/src/agent-think.ts1238 → 1251+13d5701824 (#732)

Reasons are written beside each pin, read off the diffs after the fact — which is the cost of raising a pin late, and is recorded as such on this file's own entry.

The ratchet runs ~11s in, before install, so CI never reached the test suite. That is why breaks 2–4 were only ever visible in the deploy workflows.

2. pages.ts never built before pnpm test

pnpm test could not collect workers/host/src/admin-api-proxy.test.ts: Cannot find module './pages.js'. pages.ts is build output (build.js inlines store/ into it) and is gitignored, so it does not exist in a fresh checkout — and neither ci.yml nor deploy-api.yml built it before running the suite.

Fixing only the ratchet would have moved main's redness here rather than clearing it.

Both workflows now build console → admin → host pages before pnpm test, the same chain and order as deploy-host.yml. In ci.yml this reuses the Build Console step that was already there as the job's last step, after the tests that needed it — moved, not duplicated. No docs build is added to deploy-api.yml: build.js guards a missing docs dir, so Zensical stays out of the API path.

3. Type-only import cycle

lib/usage.ts → lib/prompt-section-estimates.ts → lib/usage.ts, introduced by d5701824. Both edges are import type, so nothing failed at runtime — import-graph.test.ts is what catches it.

UsageKind now lives in usage-shape.ts, the leaf that already exists for exactly this and imports nothing; usage.ts re-exports it, so it stays the module you import a kind from. This is the connector-graph remedy that test documents (a leaf, not a deferred import) — EXPECTED_DEFERRED is untouched.

4. classifyEngineMetering had zero production callers

1e038c43 replaced its only call site with a direct expectedEngineInvocationMode check, re-opening the exact gap guard #556 was written to catch.

The invocation-mode refinement was right and is kept — it now lives inside the classifier as a third input, so one function still answers "can this reach the ledger" and the guard is satisfied by wiring rather than by a token call.

That detour also carried a second, quieter bug. It had to launder the engine name through asClient, which falls back to "claude" for anything outside its four-name list. So aider, opencode, goose, amp, crush and cursor-agent every one read as structured and recorded no absence at all — a day of unmeasured aider work looked identical to a day of measured Claude Code work on the Usage page. Going through the classifier (normalizePaneCommand + STRUCTURED_ENGINES) fixes that too.

Five new tests pin both behaviours: codex-launched-raw, the absent-launchCommand default (so no existing session reclassifies retroactively), and the six engines that were being swallowed.

Verification

  • pages.ts moved aside reproduces break 2 exactly; the added build chain clears it.
  • Full suite 606 files / 10845 tests passing (was 603 passed, 3 failed).
  • Green: ratchet, biome, docs:drift, qa-config, test-isolation, e2e-projects.
  • tsc clean: api, api tests (tsconfig.test.json), mcp, console.

Note on delivery

This repo's convention is commit-straight-to-main; this is a PR because it was explicitly requested for review before merge. Deploy API Worker will not run on merge unless workers/api/** changes — it does here, so merging should both green CI and ship the API backlog from 5876486 forward.

🤖 Generated with Claude Code

serge-the-devand others added 2 commits September 6, 2026 09:50
…ploy for five days
CI has failed on every commit since 50aecb9 (2026-09-01) and the API Worker has
not deployed since 5876486. Production is running 5876486; everything after it,
including the prompt-section tracing and the engine-invocation-mode change, is
undeployed. Four independent breaks, fixed together because main is red until all
four are gone.
1. File-size ratchet (#302). Three files grew without the pin move the guard asks
for: routes/coding.ts +5 and CodingTab.tsx +12 (both 1e038c4, #731),
agent-think.ts +13 (d570182, #732). Pins raised to 815/1490/1251 with the
reason beside each, read off the diffs after the fact — which is the cost of
raising a pin late, and is recorded as such on this file's own entry.
The ratchet runs 11s in, before install, so CI never reached the test suite.
That is why breaks 2-4 were only ever visible in the deploy workflows.
2. `pnpm test` could not collect workers/host/src/admin-api-proxy.test.ts:
`Cannot find module './pages.js'`. pages.ts is build output (build.js inlines
store/ into it) and is gitignored, so it does not exist in a fresh checkout —
and NEITHER ci.yml NOR deploy-api.yml built it before running the suite. Fixing
only the ratchet would have moved main's redness here rather than clearing it.
Both workflows now build console -> admin -> host pages before `pnpm test`, the
same chain and order as deploy-host.yml. In ci.yml this reuses the Build Console
step that was already there as the job's LAST step, after the tests that needed
it; it is moved rather than duplicated. No docs build is added to deploy-api.yml
-- build.js guards a missing docs dir, so Zensical stays out of the API path.
3. Type-only import cycle usage.ts -> prompt-section-estimates.ts -> usage.ts,
introduced by d570182. `UsageKind` now lives in usage-shape.ts, the leaf that
already exists for exactly this and imports nothing; usage.ts re-exports it, so
it stays the module you import a kind from. This is the connector-graph remedy
import-graph.test.ts documents (a leaf, not a deferred import) — EXPECTED_DEFERRED
is untouched.
4. `classifyEngineMetering` had zero production callers. 1e038c4 replaced its only
call site with a direct `expectedEngineInvocationMode` check, re-opening the exact
gap guard #556 was written to catch. The invocation-mode refinement was right and
is kept — it now lives INSIDE the classifier as a third input, so one function
still answers "can this reach the ledger" and the guard is satisfied by wiring
rather than by a token call.
That detour also had to launder the engine name through `asClient`, which falls
back to "claude" for anything outside its four-name list. So aider, opencode,
goose, amp, crush and cursor-agent every one read as structured and recorded no
absence at all — a day of unmeasured aider work looked exactly like a day of
measured Claude Code work on the Usage page. Going through the classifier, which
uses normalizePaneCommand + STRUCTURED_ENGINES, fixes that too. Five tests pin
both behaviours: codex-launched-raw, the absent-launchCommand default (so no old
session reclassifies), and the six engines that were being swallowed.
Verified locally: pages.ts moved aside reproduces break 2 exactly, and the added
build chain clears it. Full suite 606 files / 10845 tests passing (was 603 passed,
3 failed). Ratchet, biome, docs:drift, qa-config, test-isolation, e2e-projects all
green; tsc clean for api, api tests, mcp and console.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… raw 10px
A FIFTH break on main, and it was invisible: the design-tokens gate (#367) is step
10 of ci.yml and the file-size ratchet is step 5, so while the ratchet failed 11s
in this gate never ran. Fixing the ratchet is what surfaced it.
`EnginesModal.tsx:128` shipped `text-[10px]` in 1e038c4 — the same commit behind
two of the three pin overruns and the metering regression. #390 puts the floor at
11px, and the gate's own instruction for anything below it is to round UP, so this
is `text-2xs`: the nearest step, and the one `BuildsPanel.tsx:30` already uses for
exactly this pill-badge idiom. No new --text-* entry is warranted for 0.32px.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…th (pre-existing bug from 17d8265)
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@serge-ivo
serge-ivo merged commit e2e61fa into mainSep 6, 2026
1 check passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@serge-ivo@serge-the-dev