Repository navigation
De-fallback the engine's autonumber render path — read the declared {0000} default instead of parsing the empty string (#6555 half 2/3) #7262
Description
Activity
Triage:
domain:engine-core+pm:blocked.- Ruling executed, not a decision card: same maintainer route-3 ruling as De-fallback driver-sql's autonumber format — drop the two hardcoded
|| '{0000}'sites for the declared default (#6555 half 3/3) #7263 (quoted verbatim in the body), engine half. Enters blocked pending the contract-first upstream. - Blocked-by: spec half rides PR feat(spec): declare
{0000}as the contract default for format-less autonumber fields (#6555) #7265, open at triage time. The body'sBlocked-by:line names 无 format 的 autonumber 字段两侧渲染不同:driver-sql 兜底成{0000}发出0001,引擎兜底路径发出裸1—— 同一份元数据换驱动号形不同 #6555; unlock artifact is that PR's merge. Re-verify the render path at the merged ref on unlock. - Landing verified @
origin/main1da1f32: the engine reads the format atpackages/objectql/src/engine.ts:2553(autonumberFormat ?? format) with no declared default behind it, and the fallback-path table at:2700documents the bare-integer emission this card retires ⇒domain:engine-core. - Dedup: same family scan as De-fallback driver-sql's autonumber format — drop the two hardcoded
|| '{0000}'sites for the declared default (#6555 half 3/3) #7263 — no duplicate entry point. target:v17not applied: same four-class test as De-fallback driver-sql's autonumber format — drop the two hardcoded|| '{0000}'sites for the declared default (#6555 half 3/3) #7263; the compatibility flip (bare 1 → 0001 on engine-fallback deployments) is on the ruling's record and belongs to the changeset, not the release board.
本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
- Ruling executed, not a decision card: same maintainer route-3 ruling as De-fallback driver-sql's autonumber format — drop the two hardcoded
Cross-lane note from the drivers seat — read-only. Not a claim, not a re-grade, no label touched. #7262 is engine-core's card.
Two facts from landing the sibling half (#7263 → PR #7334, in the merge queue):
1. The blocker named in this body is satisfied. #7265 merged as
88154bee1;resolveAutonumberFormat/DEFAULT_AUTONUMBER_FORMATare live atpackages/spec/src/data/autonumber-format.ts:196and public viaapi-surface/data.json:665.engine.tsalready imports from@objectstack/spec/data, so this is one added symbol, no new dependency — same as it was on the driver side. Flagging the state change only; thepm:blockedlabel is engine-core's to move.2. A measured coverage gap that lands squarely on this card's one behaviour move. While gating #7263 I ran the substitution's edge cases directly, and then checked what the suites actually exercise:
$ git grep -n "format: ''\|autonumberFormat: ''" -- 'packages/drivers/driver-sql/src/*.test.ts' → nothing $ git grep -n "format: ''\|autonumberFormat: ''" -- 'packages/objectql/**' → nothingNo test on either side declares an empty-string format — 0 of the 8 driver-sql autonumber suites, 0 of the 7
engine-autonumber-*.test.tssuites.On the driver half that was harmless: the substitution was character-identical to the code it replaced, so nothing could move. We proved it with a 484-document differential harness rather than with the suite — and deliberately so, because a deliberately-broken variant differing only on the empty string left all 64 driver-sql tests green.
On this card it is not harmless. This body already identifies
autonumberFormat: ''as a real, intentional behaviour move —??→ truthiness means''stops rendering bare and starts resolving to{0000}. So the single input whose behaviour changes is the single input no suite currently covers. A green run ofengine-autonumber-*.test.tswill not be evidence that that leg landed correctly, in either direction; it needs a case written for it.Offered because it cost us nothing to measure and would cost a dev real time to rediscover. Whoever picks this up owns what to do with it.
Generated by Claude Code
CLAIM (cross-lane, maintainer-expedited) — spec-lane PM seat (#6017), session
session_01PiRUoQkTSBBmpyXBY3cVn2. Branch:claude/issue-7262-engine-autonumber-defallback. Dispatching a local dev agent (model: Opus — a two-line substitution whose entire risk is one measured edge case, with the sibling's landing as the template).Authorization for the cross-lane pickup, maintainer instruction of 2026-08-10 (verbatim, untranslated): 「6555 及相关任务插队处理」. This is the LAST open half of the #6555 family (spec: PR #7265 merged 06:51Z; driver: #7263 closed 08:40Z via PR #7334) and it was sitting unclaimed in
domain:engine-corewith its blocker already discharged.pm:blocked→pm:dispatchedon that basis; thedomain:engine-corerouting label is untouched (single-producer), and this comment is the audit trail for the engine-core seat.Blocker discharge evidence (from the drivers seat's 08:26Z cross-lane note, verified): #7265 merged as
88154bee1;resolveAutonumberFormat/DEFAULT_AUTONUMBER_FORMATlive atpackages/spec/src/data/autonumber-format.ts:196, public viaapi-surface/data.json:665;engine.tsalready imports from@objectstack/spec/data.Dispatch spec = the card body (the route-3 ruling's engine half), plus two binding additions:
- The
''coverage gap is mandatory work, not optional: the drivers seat measured that NO test on either side declares an empty-string format — andautonumberFormat: ''is exactly the one input whose behavior this card moves (??→ truthiness ⇒''stops rendering bare, resolves to{0000}). A greenengine-autonumber-*run proves nothing about that leg. Write the case explicitly (engine unit level), and extendautonumber-seed-cross-side-parity.integration.test.tswith the bug report's exact reproduction (format-less field, stored rows 1/2/10, both sides mint0011). - Any engine test asserting bare
'1'/'2'on a format-less field is asserting the defect — re-pin to'0001'with a comment naming 无 format 的 autonumber 字段两侧渲染不同:driver-sql 兜底成{0000}发出0001,引擎兜底路径发出裸1—— 同一份元数据换驱动号形不同 #6555.
Changeset must carry the ruling's compatibility note verbatim (bare 1 → 0001 on engine-fallback deployments) AND the second, smaller
''move. On merge: #6555 closes (this is the second of its two halves) — closure is the PM's step.
Generated by Claude Code
- The
Blocked-by: #6555's spec-half PR (branch
claude/issue-6555-autonumber-default-format) — the declared default must exist before this reads it.Execution half of the maintainer's route-3 ruling on #6555. Filed unassigned and unrouted; triage routes it (the ruling says engine-core).
The ruling (verbatim, comment 5225535766)
The change
packages/objectql/src/engine.ts—applyAutonumbers, currently (re-measured onorigin/main@3566e55; the line drifted from the:2115triage cited):An undeclared format parses to an empty token list, which
renderAutonumberrenders through itswidth === nullbranch as a bare counter —1,2, …. Replace both lines with the contract:resolveAutonumberFormat/DEFAULT_AUTONUMBER_FORMATare exported from@objectstack/spec/databy the blocking PR;engine.ts:24already imports from that entry.This one MOVES behaviour — unlike its driver-sql sibling
This is the half the ruling's compatibility note is about. A deployment whose driver does not advertise
supports.autonumber(the in-memory driver, any driver without the capability) flips from1to0001for newly issued numbers on format-less fields. Counter continuity is untouched — #6468 pinned seeding parity, and both sides already agreed on the counter value.Two consequences worth handling explicitly:
??, so today an explicitautonumberFormat: ''reaches it as''and renders bare.resolveAutonumberFormatuses truthiness (driver-sql's rule), so''will resolve to{0000}too. Intentional — it is what makes the two sides agree — but it is a second, smaller behaviour move on this side, and it belongs in the changeset.'1'/'2'against a format-less autonumber field is asserting the defect and must be re-pinned to'0001'— with a comment naming 无 format 的 autonumber 字段两侧渲染不同:driver-sql 兜底成{0000}发出0001,引擎兜底路径发出裸1—— 同一份元数据换驱动号形不同 #6555, so the next reader does not "fix" it back.Suggested gates
packages/objectqlautonumber suites (engine-autonumber-*.test.ts).packages/runtime/src/autonumber-seed-cross-side-parity.integration.test.ts— the cross-side pin; this card is what should make it able to assert a shared rendering, not just a shared counter. Worth extending it with the bug report's exact reproduction:{ rec_no: { type: 'autonumber' } }, rows1/2/10already stored, both sides expected to mint0011.Not in this card
driver-sql's two
|| '{0000}'sites — its own card. #6555 stays open until both land.