drizzle-kit emite TypeScript invalido y literales bigint inconsistentes al regenerar schema.ts
Medido el 2026-09-07 regenerando drizzle/schema.ts contra DEV con introspect.sh (commit dd0cc537). Dos defectos del generador en la misma corrida, misma clase: la salida no transpila ni pasa lint. 1. schema.ts:1833, columna observaciones: un DEFAULT de string vacia salio como .default(') en vez de .default(''). Es TypeScript INVALIDO - el literal queda abierto y nada downstream compila. 2. schema.ts:1812: el literal 9223372036854775807 aparece TRES veces en el archivo, DOS entre comillas y UNA desnuda. La desnuda es error de eslint no-loss-of-precision. El archivo commiteado anterior tenia las TRES entre comillas: el generador NO es estable entre corridas sobre el mismo esquema. Ambos corregidos a mano en dd0cc537 porque regenerar los reproduce. Choca con la regla de no editar schema.ts a mano, que supone un generador que emite codigo valido; la regla sigue en pie para todo lo demas. Pendiente decidir: post-proceso en introspect.sh, o pinear/actualizar drizzle-kit.
Activity
-
coder03-mba-l-cc / coder
-
coder04-mba-l-ca
-
researcher-mba-l-cc / solo
-
Researcher started at 2026-10-08T11:56:56-03:00.
-
researcher-mba-l-cc @ 2026-10-08T11:56:56-03:00 Installed version: drizzle-kit 0.31.4 (pinned exact, package.json:59). No newer release fixes either defect - both are still open upstream as of their 2026-02 filing dates, so there is nothing to pin forward to. Defect 1 (empty-string default -> invalid .default(')): two OPEN, unmerged upstream PRs target exactly this - drizzle-team/drizzle-orm#5372 "fix(drizzle-kit): fix empty string default generating invalid TypeScript during introspect" (capaj, opened 2026-02-14) and #5380 "fix(kit-pg): handle empty string defaults in PostgreSQL introspection" (Shion1305, opened 2026-02-16). Neither merged. An older, closed WIP attempt at the same class of bug (dalton-oliveira, #3863, closed 2025-03-31) also never landed - this bug has gone unfixed across multiple contributor attempts for over a year, not a recent regression. Defect 2 (bigint literal 9223372036854775807 unstable quoting, 2 of 3 occurrences change between runs): no matching upstream issue found after search - likely never reported, or too narrow/specific to have its own ticket. The closest related upstream work (PR #4166, bigint-in-relations precision loss) is a different code path (relational query serialization, not introspect's TS-literal emission) and does not cover this. CONCLUSION: no version to pin. Upstream fix timeline for defect 1 is unknown (two competing unmerged PRs, no maintainer signal on which lands); defect 2 has no tracked fix at all. Recommend the post-processing step, not waiting on upstream. SPEC - post-process step for mba-introspect.sh, run immediately after drizzle-kit generate and before the file is treated as valid: 1. Empty-string default: regex-replace `\.default\('\)` -> `\.default\(''\)` (the generator drops the second quote when the default is the empty string; this is the exact shape from dd0cc537's manual fix). 2. Bigint literal quoting instability: regex all three occurrences of `9223372036854775807` (or any bare 19-digit literal that trips eslint no-loss-of-precision) in schema.ts and force-wrap each as a quoted string literal (drizzle-kit's own column type accepts the string form; this is what the previously-committed file already had for 2 of 3 and is the only form that both compiles and passes lint). 3. After the two substitutions, run `tsc --noEmit` and `eslint` against the regenerated schema.ts as a self-check inside the script, failing the script (not just warning) if either still fails - this converts "regenerate produced invalid output" from a silent human-catches-it-later failure into a loud script-exit-1. Scope: this only touches generated schema.ts post-processing inside mba-introspect.sh; no change to drizzle-kit itself, no change to the "schema.ts is generated, never hand-edited" rule (dd0cc537's manual edits were a one-off workaround before this spec existed, not a precedent to keep repeating by hand on every regen).
-
coder04-mba-l-ca / coder
-
Source correction: mba-introspect.sh is a thin exec wrapper for tools/introspect-dev.mjs. The actual generator already applies both requested fixes: bare 9223372036854775807 -> quoted (lines 205-210) and malformed .default(\x27).notNull() -> .default(\x27\x27).notNull() (211-217), then validates TypeScript syntax with transpileModule. Remaining defect: no tsc --noEmit or eslint self-check exits nonzero after regeneration. Implement that in tools/introspect-dev.mjs, including --check read-only semantics; do not duplicate patches in shell wrapper.
-
The existing JS entrypoint already patches empty-string defaults and bare bigint literals, then syntax-checks staged schema/relations. Added fail-loud tsc --noEmit --incremental false and eslint --max-warnings 0 for tracked schema/relations after update or a clean --check. A stale --check still fails before these gates; no tracked or tsbuildinfo writes in check mode. One-file diff to audit.
-
audit fail: tools/introspect-dev.mjs, the new block at :309-332 only. Both legs run live from the repo root. NOT exercised: a real drizzle-kit regeneration (needs the DEV database), and the --check-with-stale path, which cannot reach this block at all.
payload
{"scope":"tools/introspect-dev.mjs, the new block at :309-332 only. Both legs run live from the repo root. NOT exercised: a real drizzle-kit regeneration (needs the DEV database), and the --check-with-stale path, which cannot reach this block at all.","outcome":"fail","evidence":"eslint leg is sound: ./node_modules/.bin/eslint --max-warnings 0 drizzle/schema.ts drizzle/relations.ts exits 0 live, so no ignore-warning false abort. Three measured defects in the tsc leg. (1) It is bare tsc, not the project typecheck. package.json:14 defines typecheck as 'next typegen && tsc --noEmit' because next typegen OWNS tsconfig.json's include and emits .next/types/validator.ts, which the include glob picks up and which is the tree's only route-signature control. Measured: with .next/types EMPTY, bare tsc --noEmit --incremental false exited 0 over 388 src files; nothing in src references the generated PageProps globals, so the absence is silent. The gate therefore cannot be cited as equivalent to the ship gate. Fix is one word: invoke the typecheck script. (2) Control placement. The write loop at :289-306 has already overwritten drizzle/schema.ts and relations.ts before the block runs, so this detects a broken mirror after it is in the working tree; it does not guard against one, and the lane's recovery is a manual git checkout the error string does not mention. (3) --check with differs calls process.exit(1) at :307, ahead of the block, so --check never exercises either gate when the mirror is stale - the one state where it is suspect. On coder03's differential question: name the choice as tree-wide and proportionate IF you want, but as written the attribution is prose, not a control, and (2) means the before-capture needed for a grew-or-not comparison is already available for free at the top of the run. That makes the differential cheap, and it is what turns this from a green line into a check.","reportRef":null} -
Audit FAIL correction in tools/introspect-dev.mjs: answer is deliberately tree-wide. Full pnpm run typecheck now includes Next typegen, with baseline-vs-regenerated TS diagnostics so existing errors in other lanes are named but not mistaken for new mirror errors. Generated schema/relations are restored on new type or lint errors; --check remains read-only and fails on drift before any typegen write. The abort reports failing file paths. One-file diff returned to audit; coder lane did not run gates.
-
audit pass: tools/introspect-dev.mjs, the revised block :286-371. Static read plus the regex and parse checks below. NOT EXERCISED: no run against the DEV database, so neither the restore path nor the diagnostic diff has been seen to fire; that is the positive control this verdict does not have.
payload
{"scope":"tools/introspect-dev.mjs, the revised block :286-371. Static read plus the regex and parse checks below. NOT EXERCISED: no run against the DEV database, so neither the restore path nor the diagnostic diff has been seen to fire; that is the positive control this verdict does not have.","outcome":"pass","evidence":"All three FAIL findings are fixed, and each one checked against the bytes rather than the claim. It calls pnpm run typecheck, so next typegen runs and .next/types/validator.ts is in the program - the gate can now fail for the reason it exists. The baseline is captured before any write: the first loop only logs, the checkOnly branch exits at :309-313 ahead of typegen so --check stays read-only, and the writes happen in the second loop after the baseline. The catch restores both tracked files from the content read at the top, and the error strings say the mirror was restored. node --check parses. The diagnostic diff is keyed by file plus code plus message with counts, so a new instance of an existing error still trips count > baseline. Three residuals, none blocking. (1) The regex only matches NON-pretty tsc output; verified it matches 'src/actions/choferes.ts(180,9): error TS2345: ...' and does not match the pretty form. pretty is unset in tsconfig.json and spawnSync pipes give no TTY, so it holds today, but setting pretty true empties both diagnostic sets and the control silently degrades from abort to the warn branch. The gate calls the npm script, so it cannot pass --pretty false itself; a sanity check that a red baseline yields a nonempty set would catch it. (2) Two full project typechecks run on every non-check invocation even when the mirror is unchanged, so an introspection that regenerates nothing pays the whole cost; guarding on differs would skip both. (3) The restore writes back content read at the top of the run, and this checkout is shared by five lanes, so a concurrent edit to drizzle/schema.ts inside that window is clobbered by the restore. The pre-existing write had the same exposure, so this is not new, but the restore widens it. Also by design: --check never typechecks, so a stale-mirror check verifies staleness only.","reportRef":null} -
The 2026-10-08 audit PASS that cites --check exiting before typegen covers earlier bytes and is superseded by the later --check revision. Current tools/introspect-dev.mjs temporarily checks the candidate and restores tracked files in finally; this exact diff is awaiting audit. Do not ship on the earlier PASS.
-
audit-mba-l-cc 2026-10-08 16:49 ART. The MOVILBA-324 PASS recorded at 16:27 is SUPERSEDED and must not be used to ship. It was measured against bytes where --check compared the mirrors and exited at tools/introspect-dev.mjs:309-313 before any write. coder04 reports (tag coder04-mba-l-ca-muzrg3h8rerh) that --check now swaps a candidate into the tracked mirrors and restores in a finally block - behaviour those bytes did not have and that PASS therefore never covered. coder03 has asked for that to be reverted to the read-only --check (tag coder03-mba-l-cc-muzrcjc6x6ae) and told audit not to spend a verdict on the current bytes, so I have not reviewed them. There is at present NO valid audit verdict for tools/introspect-dev.mjs in the working tree. On the substance of the revert, audit agrees with it and the reason is one audit already put in the superseded PASS as a residual: five lanes share this checkout, so any window in which a tracked mirror holds an uncommitted candidate is a concurrent-clobber exposure, and a finally block does not close it - a kill, a crash or a full disk leaves the candidate in a tracked file with no lane aware of it. A safety property is judged on its failure path, so 'net no tracked change' is not the claim that matters. Stated limitation, accepted and recorded here as asked: --check verifies mirror CONTENT, not compilability. Independent of either shape, the PASSed version has never been run against movilba_dev with a deliberately broken mirror, so neither the restore path nor the diagnostic diff has been seen to fire. By audit's own coverage rule that is a green line, not yet a control, which is why the item does not ship on the verdict alone.
-
Old audit PASS superseded by new control. Added --check --verify-typecheck-gate: injects a TS2322 into the generated schema candidate, runs real project typecheck before/after, expects abort on the new diagnostic, restores both tracked mirrors. Red typecheck output with zero parsed TS diagnostics now fails loud, covering pretty-output drift. Diff and exact DEV rehearsal request sent to audit; no coder execution, no ship until its result.
-
Boundary corrected: --check is read-only mirror-content comparison only; it does not certify generated TypeScript compilability, because Next typegen writes and a transient tracked-file swap risks concurrent readers/crashes in the shared checkout. Standalone --verify-typecheck-gate injects a broken TS candidate, runs real project typecheck before/after, and must restore tracked files on abort. Parser fails loud if a red typecheck has no recognizable TS diagnostics. Exact DEV command and SHA evidence requested from audit; still SIN EJERCITAR until observed, no ship on prior PASS.
-
audit pass: tools/introspect-dev.mjs current bytes: read-only --check boundary plus the --verify-typecheck-gate broken-mirror control, RUN by audit against movilba_dev under the checkout lock. NOT EXERCISED: kill-mid-write restore path; --update-view-baseline.
payload
{"scope":"tools/introspect-dev.mjs current bytes: read-only --check boundary plus the --verify-typecheck-gate broken-mirror control, RUN by audit against movilba_dev under the checkout lock. NOT EXERCISED: kill-mid-write restore path; --update-view-baseline.","outcome":"pass","evidence":"PASS, and the control was OBSERVED firing, which is what this item was held for. Run by audit under the hub lock movilba-web-checkout, with .env.local supplying DEV_DATABASE_URL.\nObserved: 'verified DEV database: movilba_dev', then 'view mirror: 117 installed, 117 mirrored, 4 baselined lossy literal(s)', the candidate write, then 'drizzle/schema.ts(3894,14): error TS2322: Type string is not assignable to type number', then the abort from tools/introspect-dev.mjs:378 naming that new diagnostic, exit status 1.\nRestore verified byte-for-byte rather than taken from the message: drizzle/schema.ts f34b4bea...f20b and drizzle/relations.ts 19650192...3eb3 BEFORE the run and the identical two SHAs after; git status --porcelain drizzle/ empty; zero occurrences of __movilba324TypecheckControl left in the tree; pnpm typecheck back to zero TS errors afterwards. Neither the restore path nor the diagnostic diff is a green line any more - both have been seen to work against a deliberately broken mirror.\nBoundary checked in the bytes, not the summary: --check exits at :320-322 before the tracked write loop at :360-364, writing only staging files at :269 and :271, and the comment at :318-319 records the accepted limitation that --check verifies CONTENT, not compilability. The injection at :291 lands AFTER validateTypeScript at :268, which is what lets the broken line reach the project typecheck instead of being caught locally. The inverted guard at :391 is real: had typecheck ACCEPTED the broken mirror the run would still have aborted, so a silently passing control cannot be read as success. :356 and :369 abort on a nonzero status with no parseable diagnostic, closing the pretty-output drift hole.\nNOT EXERCISED: the kill-mid-write path - a SIGKILL or disk error between :362 and the catch still leaves a candidate in a tracked file, and the lock is what bounds that, not the code. Nothing measured about --update-view-baseline.","reportRef":null} -
Done. Audited PASS 2026-10-08: DEV broken-mirror positive control observed TS2322 abort and byte-identical restore; --check remains read-only content comparison. PM confirms shipped/live by v5.6.194/v5.6.192 on PROD, DEV and pod.