fix(swagger): hoist the one inline predicate that makes the generator run away #164
Reference in New Issue
Block a user
No description provided.
Delete Branch "fix/swagger-generator-runaway"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What & why
npm run swaggercannot run on this tree at all. It dies with swagger-autogen'sand generates nothing. So the committed OpenAPI spec cannot be regenerated by anyone, and the standing obligation in CLAUDE.md — "never ship a route that isn't in the spec" — is currently unmeetable. This blocks engagement Phase 1, which removes two routes, and every later phase that adds one.
It is not a local quirk: it reproduces on a pristine
origin/edgeworktree, under Node 24 and Node 20 (the CI version, checked in a container), and at61abb3e— the commit whose own PR last regenerated the spec.The cause
Bisected to a single statement in
server/src/router/v1/admin/teams.router.js:Hoisting that arrow to a named const fixes it outright.
The diagnosis this corrects
Three files currently tell the next person the wrong thing, so the comments are corrected too.
Phase 8 shipped a bare regex literal before
.test(. Phase 9 hit the crash, hoisted the regex, and read the symptom as a per-file route limit — measured at 20teamsRouter.*statements — then splitteamsVoice.router.jsout and leftteams.router.jsat 19, "one under the edge", with that reasoning written intoteams.router.js,teamsVoice.router.jsandadmin/index.js.There is no edge to sit under. Probing every router file individually:
teams.router.js, 19 statementsDELETE /integrations/:teamIdroute.custom(...)arrow hoistedSo the trigger is the inline arrow reaching
.test(, not how much is in the file. The count was a proxy for how much text the parser chewed before reaching the real trigger, which is why removing any statement appeared to help. Hoisting the regex was half the fix; the predicate wrapped around it needed hoisting too.The rule the comments now state: nothing that reaches
.test(may sit inside a route statement.The
teamsVoice.router.jssplit is left in place — it is a good split on its own terms — but its note now says so rather than claiming it is mechanically load-bearing.How it was tested
npm run swagger— succeeds, first time on this tree. The regeneratedswagger-output.jsonis byte-identical to the committed one, so this is a generator fix and not a spec change; nothing is committed for it.npm run routes:manifest -- --check— clean, no URL moved.npm test --prefix server— 1162 passing, 0 failing.npm run check:modules— clean.Checklist
AI-assisted contributions (required)
Claude Code. I have reviewed and understand every change, and take responsibility for it. AI-authored commits are marked with aCo-Authored-Bytrailer.License
`npm run swagger` cannot run on this tree. It dies with swagger-autogen's "FATAL ERROR: invalid array length - Allocation failed", generating nothing, and it reproduces on a pristine checkout under both Node 20 and Node 24 — so the committed spec cannot be regenerated by anyone, and any PR that adds or changes a route is unable to meet the standing obligation to update it. Bisected to one statement in `teams.router.js`: param('teamId').custom((v) => v === 'default' || TEAM_ID.test(v)) Hoisting that arrow to a named const fixes it outright. Nothing else changes and the regenerated spec is byte-identical to the committed one, so this is a generator fix, not a spec change. The diagnosis worth keeping, because the file's own comment recorded a different one. Phase 8 shipped a bare regex LITERAL before `.test(` and phase 9 hoisted the regex, blaming a per-file route limit measured at twenty statements; the file has sat at nineteen ever since on the theory that it was one under the edge. That theory is wrong. Probing every router file individually, `teams.router.js` at nineteen statements dies while a THREE-route file carrying only this one route also dies — so the trigger is the inline arrow reaching `.test(`, not the count. Hoisting the regex was half the fix; the predicate around it needed hoisting too. The comments in `teams.router.js`, `teamsVoice.router.js` and `admin/index.js` are corrected to say so, since all three currently tell the next person to keep counting statements. Co-Authored-By: Claude <noreply@anthropic.com>