You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
#16887 already moved both migration generators off required onto storage.notNull — was that ADR-0113 alignment intended inside a NUMERIC card, and does it stand? #17218
The divergence this card was filed to decide had already landed when I filed it.#16887 (9cdffbe365, 2026-09-09 11:48Z) moved both generators off required onto storage.notNull; I filed this at 18:50Z. Measured twice since — by this seat from the ref, and independently by the #16294 delivering seat on a live PostgreSQL 16.13 cluster, which found f_requiredagreeing on all three producers both before and after its own diff.
⇒ The section headed "The divergence" below is FALSE on today's tree, and the two generate.ts lines it quotes do not exist. It is kept, struck, as the record of what was believed — ⛔ not as evidence. Full accounting: 5607877582.
The live question is now the one in the title: option A was taken de facto, inside a card scoped to the NUMERIC column family. Was that intended, and does it stand? ⛔ Still not this seat's to rule.
Filed by the domain:cli execution PM seat (#6024) to give an existing, well-formed question a carrier — ⛔ not to answer it. This seat does not rule contract or product decisions.
Why this card exists at all
This is cause 1 of #16294, which triage deliberately took out of that card on 2026-09-08 (5579710938) as a decision rather than a repair, and routed elsewhere:
⛔ That destination no longer exists.#16318 was ruled, dispatched, and closed completed on 2026-09-09 via PR #16887 — the very PR that then took this decision as a side effect.
The divergence ⛔ SUPERSEDED — false on the current tree
Driven on live PostgreSQL 16.13 (#16294's six-column probe), f_required — a field marked required: true with no storage.notNull — the driver leaves nullable; both generators emit NOT NULL:
Both generators read storage.notNull; neither reads required for nullability. The surviving fieldDef.required reads (:625, :925) are TypeScript optionality markers, ⛔ not NOT NULL emission. The driver's own rule is unchanged.
⇒ f_required now AGREES across all three producers. The scaffold follows the driver. Option A, below, is what shipped.
The two sides, neither of them mine to pick — now asked about a fait accompli
A — the scaffold follows the driver. ADR-0113 states the principle in createColumn's tail: "the physical NOT NULL comes from the EXPLICIT storage constraint, not from required … binding the DDL to it made every post-deploy tightening a destructive migration." The 2026-09-08 maintainer ruling withdrawing the field-required-notnull-explicit conversion sharpened it — docs/protocol-upgrade-guide.md:139: "Post-17 a column is NOT NULL because its author wrote storage: { notNull: true }, and for no other reason."This is what #16887 implemented.
B — the scaffold preserves the author's declaration. Triage's counter, which ⚠️is untouched by #16887 and is now the harder side, because reversing would be a change rather than a choice:
让生成器跟随驱动,意味着一个作者标了 required 的字段,脚手架不再发 NOT NULL —— 在那位作者读来就是脚手架把他的声明弄丢了,即便写入缝仍然执行它。
A scaffold is read by a human, once, at authoring time. Emitting a weaker table than the author's declaration suggests is a different failure from a driver doing the same at runtime, where the write seam still enforces required.
⚠️ What is actually undecided
⛔ Not "which behaviour" — that shipped. What is undecided is whether it was decided:
Filed by the
domain:cliexecution PM seat (#6024) to give an existing, well-formed question a carrier — ⛔ not to answer it. This seat does not rule contract or product decisions.Why this card exists at all
This is cause 1 of #16294, which triage deliberately took out of that card on 2026-09-08 (
5579710938) as a decision rather than a repair, and routed elsewhere:⛔ That destination no longer exists. #16318 was ruled, dispatched, and closed
completedon 2026-09-09 via PR #16887 — the very PR that then took this decision as a side effect.The divergence⛔ SUPERSEDED — false on the current treeWhat is actually there now, on
origin/main:Both generators read
storage.notNull; neither readsrequiredfor nullability. The survivingfieldDef.requiredreads (:625,:925) are TypeScript optionality markers, ⛔ not NOT NULL emission. The driver's own rule is unchanged.⇒
f_requirednow AGREES across all three producers. The scaffold follows the driver. Option A, below, is what shipped.The two sides, neither of them mine to pick — now asked about a fait accompli
A — the scaffold follows the driver. ADR-0113 states the principle in
createColumn's tail: "the physical NOT NULL comes from the EXPLICIT storage constraint, not fromrequired… binding the DDL to it made every post-deploy tightening a destructive migration." The 2026-09-08 maintainer ruling withdrawing thefield-required-notnull-explicitconversion sharpened it —docs/protocol-upgrade-guide.md:139: "Post-17 a column is NOT NULL because its author wrotestorage: { notNull: true }, and for no other reason." This is what #16887 implemented.B — the scaffold preserves the author's declaration. Triage's counter, which⚠️ is untouched by #16887 and is now the harder side, because reversing would be a change rather than a choice:
A scaffold is read by a human, once, at authoring time. Emitting a weaker table than the author's declaration suggests is a different failure from a driver doing the same at runtime, where the write seam still enforces
required.⛔ Not "which behaviour" — that shipped. What is undecided is whether it was decided:
required— which ADR-0113 moved the driver OFF — never readstorage.notNull, and dropdefaultValueentirely: 4 of 6 probed columns diverge on live Postgres #16294 for that reason. A decision taken as a side effect of an unrelated card is taken without the argument being had — regardless of whether the outcome is right.⇒ The maintainer needs to ratify or reverse, not choose fresh.
What is NOT in scope
required— which ADR-0113 moved the driver OFF — never readstorage.notNull, and dropdefaultValueentirely: 4 of 6 probed columns diverge on live Postgres #16294. Cause 2 also landed in feat(spec,driver-sql,cli): one physical representation for the NUMERIC column family, read by all three producers #16887. Cause 3 (defaultValueemitting no column DEFAULT) is the live remainder and is delivered in PR fix(cli): a generated migration carries the column DEFAULT driver-sql puts on the same field #17230.Grading
⛔ No priority and no
pm:state from this seat — triage's carrier. Lane and kind only, so the card has a reader.Siblings
required— which ADR-0113 moved the driver OFF — never readstorage.notNull, and dropdefaultValueentirely: 4 of 6 probed columns diverge on live Postgres #16294 — cause 3, delivered as PR fix(cli): a generated migration carries the column DEFAULT driver-sql puts on the same field #17230; its dev measured the baseline as 2 of 6 diverged, not the card's 4.real, generatorsnumeric, andratingisrealagainstinteger#16318 — ruled and landed via feat(spec,driver-sql,cli): one physical representation for the NUMERIC column family, read by all three producers #16887, the PR that took this decision in passing.os generate migrationemits no declared index at all — a generated table carries none of the object'suniqueconstraints, while driver-sql creates them #16317 (indexes, landed fix(cli): a generated migration carries the field-level unique index driver-sql creates #17208) · [finding] driver-sql and both migration generators default an absent or unknown fieldtypeto DIFFERENT families —stringversustext, so the unvalidated authoring door produces two different columns #16319 (absent/unknowntype, queued) — same producer pair.multiple: truecolumn, whichSqlDriver.createColumnreturns before ever constraining — and the pin asserts the generator side #17231 — a surviving divergence on the same probe: both generators emit NOT NULL on amultiple: truecolumn where the driver leaves it nullable.