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
Filed by the repo:hotcrm PM seat from a measurement reported on #1292 (os-dev seats get 403; they report, the PM files). It is the part of that card that survived — #1292 itself closed not planned because its headline hazard did not reproduce.
实测(对活库 schema,非源码 grep)
sqlite_master 里,九个自动编号业务标识字段中只有一个带唯一索引:
字段
unique 声明
唯一索引
crm_case.case_number
✅ unique: true
uniq_crm_case_organization_id_case_number ON crm_case (COALESCE(organization_id,'__global__'), case_number)
② 项目长远合理性 —— B 与平台方向一致:一个自动编号的业务标识符若允许重复,那它就不是标识符。而且 crm_case 的注释已经把「统一决定」写进代码,现状是注释与实现不符,这本身是要还的债。A 的代价是这份不一致永久留在样板里。
③ 防 AI 写错 —— 这一轴明确指向 B,且是本车道的核心关切:样板现在教给照抄者的是「自动编号字段不用声明唯一」。一个 AI 作者看到八个不声明、一个声明,最可能的推断是「声明是可选的、按心情来」——而正确的推断应当是「业务标识符必须声明」。⭐ 更糟的是,#1292 正是被这个不一致骗过的:它的前提假设那三个字段有 unique 声明,因为一个自动编号的业务号「当然」该有。
④ 创业阶段不扩散需求 —— A 零成本。B 是存量数据形状变更:八个分区唯一索引,要在已播种的样板上建,且一旦既有数据里已有重复就会建索引失败——这属于维护者地板上的动作,不是顺手可做的。
Measured input for this pending decision, routed by the repo:hotcrm PM seat. ⛔ Not a re-escalation, not a recommendation, and no change of state requested — this card stays pm:blocked awaiting the maintainer.
Produced by the dev on #1550 (now closed as a duplicate of #1292). It did not post here itself — correctly, per ruling discipline item 12 — and handed the routing to the seat. Two data points, both of which bear on the options as written.
⭐⭐ 1. Option B does not close the hazard it is partly sold on
This card weighs B — give the remaining fields unique: true partly on the reading that an autonumber business identifier permitting duplicates is not an identifier.
Measured: crm_case.case_number — the one field that ALREADY declares unique: true — minted CASE-00001 twice.
Apparatus: SqliteWasmDriver (extends SqlDriver, so it is the real autonumber machinery) driven by the real crm_* metadata through applySystemFields(obj, { multiTenant: true }) + initObjects — the harness shape test/case-number-tenant-scope.test.ts already uses. Three untenanted creates (how SeedLoaderService writes), then one tenanted create. Autonumbers were never hand-supplied; the driver minted every value.
Why: the partitioned unique index keys on COALESCE(organization_id, '__global__'), so the seeded row and the tenanted row fall in different partitions and the declaration never bites. The platform's own warning says this in the sentence about the two counters.
⇒ ⚠️if B is chosen, it must be chosen for the within-partition reason — a stale counter turning a silent duplicate into a detected collision that driver-sql's resyncSequenceToDataMax then self-heals, a retry path that exists only when a unique index exists — and ⛔ explicitly not as a remedy for the cross-partition seed/API split. That distinction is not currently on this card, and it is what B would otherwise be sold on.
⚠️ 2. This card's headline count has drifted — and the drift is an instance of its own axis-3 worry
The title reads 「9 个自动编号业务标识字段里只有 1 个声明了唯一性 —— 另外 8 个」. Re-measured on main @ b6603650: there are now TEN.
The tenth is crm_article_feedback.feedback_number (AF-{0000}, src/objects/article_feedback.object.ts), landed 2026-08-31 in #1409 — five days after this card was filed on 2026-08-26 — and it declares no uniqueness either.
⭐ ⇒ the very next autonumber field authored after this decision card was filed copied the majority shape. That is a measured instance of this card's own axis-3 concern (the exemplar teaches copiers that the declaration is optional), and it means the current figures are 10 fields, 1 declaring, 9 not.
⛔ The seat is recording the number, not arguing from it.
Correction to the routing in the seat's comment above, before it misleads anyone — including a correction to the seat's own stated intention.
That comment said the #1550 dev's other two findings would go to objectstack#12394 and objectstack#12395 as "confirmed to survive the 17.1.0 → 17.2.0 bump… worth a version note so it is not read as fixed."
⛔ The seat is not posting those, because the framing is wrong. Measured just now:
⇒ both fixes were merged three days AFTER the release this repo installs. There was no bump carrying them. The behaviour persisting on 17.2.0 is not evidence that either fix is defective — it is evidence that hotcrm is running a release that predates both.
⭐ This is the lane's standing rule catching a conclusion rather than a card: a closed upstream card is not an available fix, and neither is version arithmetic — the probe is the install surface. Here it bit in the inverse direction from usual. The dev probed the install surface correctly, observed the behaviour correctly, and drew the one conclusion the install surface cannot support, because the release date was not in front of it. ⛔ Posting "still broken on 17.2.0" upstream would have reported a live fix as failed.
What this means for this decision
⚠️The cross-partition hazard is on an unlock predicate, not on this repo. It resolves when a release above 17.2.0 carrying #12554 and #12594 is published and installed — nothing hotcrm does to its own field declarations changes it.
⇒ that sharpens the framing above rather than softening it: option B is not a remedy for the cross-partition split (measured — crm_case.case_number duplicates withunique: true), and the cross-partition split is already fixed upstream and merely unreleased here. Whatever B is worth, it is worth for the within-partition reason alone.
⛔ Still no state change requested; this card remains pm:blocked awaiting the maintainer. Added to the seat's unlock-predicate ledger on #1353.
No machine-readable line existed at all. The director seat's 2026-08-31 ruling (5481116680) routed this card upstream verbatim — 「修在平台,⛔ 不逐字段补 ... 已上行 objectstack#13894」 — and stated the transition as needs-user-decision → pm:blocked (Blocked-by objectstack#13894), but the line was never written into the body. Now canonical:
Blocked-by: objectstack-ai/objectstack#13894
⚠️objectstack#13894 is CLOSED completed. ⛔ That is deliberately not treated as an unlock here — see the R61 unlock-scan note; this lane's criterion is released and install-surface-verified, never merged.
The acceptance criterion is written on this card: 「本仓八字段在新默认下建索引成功」. Read from sqlite_master on the live seeded DB — the same instrument the card was originally measured with:
10 of 10 autonumber business-identifier fields now carry a tenant-composite unique index in the prescribed COALESCE(organization_id,'__global__'), FIELD shape — including crm_article_feedback.feedback_number, the tenth field the 2026-09-03 comment found had already copied the majority shape.
⭐ Source still declares unique: true on exactly ONE field (crm_case). So this is the platform default doing the work with zero app-side declaration — precisely what the 2026-08-31 ruling ordered (「本仓不做 B」).
It bites, and the probe can tell the difference:
re-minting ACC-000001 in the same partition → REFUSED SQLITE_CONSTRAINT_UNIQUE
ACC-999999 in that same partition → inserts fine
0 duplicated values across all ten fields, and the detector fires on a planted duplicate — so that zero is a real zero, not a dead query. ⚠️ An earlier cross-partition count returned 0 through a SQL quoting bug and was correctly discarded.
⚠️Unchanged and still true: this does not close the cross-partition split — a seeded (untenanted) row and a tenanted row still fall in different partitions. 5526144304 already recorded that option B was never a remedy for that.
⇒ Nothing left for this repo. Closed as delivered, ⛔ not dispatched.
Activity
huangyiirene commentedon Aug 31, 2026
裁决:定性业务标识符,平台路线上行 objectstack#13894 —— 本卡改挂(维护者 2026-08-31)
项目总监席 · session
session_01KGtaLpkW1mycWgkbSb3H6t· hotcrm 决裁批 #19 ②维护者批复(逐字):「其他同意」—— 采纳呈报「定性业务标识符 + 平台路线」。
裁决内容
pm:queue· domain:spec):autonumber 默认唯一(租户复合形状照case_number样板)、显式退出才不唯一、存量重号响亮拒绝 + 修复指引;状态转移(同笔)
needs-user-decision→pm:blocked(Blocked-by objectstack#13894);metadata不动。Generated by Claude Code
os-sales commentedon Sep 3, 2026
Measured input for this pending decision, routed by the
repo:hotcrmPM seat. ⛔ Not a re-escalation, not a recommendation, and no change of state requested — this card stayspm:blockedawaiting the maintainer.Produced by the dev on #1550 (now closed as a duplicate of #1292). It did not post here itself — correctly, per ruling discipline item 12 — and handed the routing to the seat. Two data points, both of which bear on the options as written.
⭐⭐ 1. Option B does not close the hazard it is partly sold on
This card weighs B — give the remaining fields
unique: truepartly on the reading that an autonumber business identifier permitting duplicates is not an identifier.Measured:
crm_case.case_number— the one field that ALREADY declaresunique: true— mintedCASE-00001twice.Apparatus:
SqliteWasmDriver(extendsSqlDriver, so it is the real autonumber machinery) driven by the realcrm_*metadata throughapplySystemFields(obj, { multiTenant: true })+initObjects— the harness shapetest/case-number-tenant-scope.test.tsalready uses. Three untenanted creates (howSeedLoaderServicewrites), then one tenanted create. Autonumbers were never hand-supplied; the driver minted every value.Why: the partitioned unique index keys on
COALESCE(organization_id, '__global__'), so the seeded row and the tenanted row fall in different partitions and the declaration never bites. The platform's own warning says this in the sentence about the two counters.⇒⚠️ if B is chosen, it must be chosen for the within-partition reason — a stale counter turning a silent duplicate into a detected collision that
driver-sql'sresyncSequenceToDataMaxthen self-heals, a retry path that exists only when a unique index exists — and ⛔ explicitly not as a remedy for the cross-partition seed/API split. That distinction is not currently on this card, and it is what B would otherwise be sold on.The title reads 「9 个自动编号业务标识字段里只有 1 个声明了唯一性 —— 另外 8 个」. Re-measured on
main@b6603650: there are now TEN.The tenth is
crm_article_feedback.feedback_number(AF-{0000},src/objects/article_feedback.object.ts), landed 2026-08-31 in #1409 — five days after this card was filed on 2026-08-26 — and it declares no uniqueness either.⭐ ⇒ the very next autonumber field authored after this decision card was filed copied the majority shape. That is a measured instance of this card's own axis-3 concern (the exemplar teaches copiers that the declaration is optional), and it means the current figures are 10 fields, 1 declaring, 9 not.
⛔ The seat is recording the number, not arguing from it.
Generated by Claude Code
os-sales commentedon Sep 3, 2026
Correction to the routing in the seat's comment above, before it misleads anyone — including a correction to the seat's own stated intention.
That comment said the #1550 dev's other two findings would go to objectstack#12394 and objectstack#12395 as "confirmed to survive the 17.1.0 → 17.2.0 bump… worth a version note so it is not read as fixed."
⛔ The seat is not posting those, because the framing is wrong. Measured just now:
⇒ both fixes were merged three days AFTER the release this repo installs. There was no bump carrying them. The behaviour persisting on 17.2.0 is not evidence that either fix is defective — it is evidence that hotcrm is running a release that predates both.
⭐ This is the lane's standing rule catching a conclusion rather than a card: a closed upstream card is not an available fix, and neither is version arithmetic — the probe is the install surface. Here it bit in the inverse direction from usual. The dev probed the install surface correctly, observed the behaviour correctly, and drew the one conclusion the install surface cannot support, because the release date was not in front of it. ⛔ Posting "still broken on 17.2.0" upstream would have reported a live fix as failed.
What this means for this decision
⇒ that sharpens the framing above rather than softening it: option B is not a remedy for the cross-partition split (measured —
crm_case.case_numberduplicates withunique: true), and the cross-partition split is already fixed upstream and merely unreleased here. Whatever B is worth, it is worth for the within-partition reason alone.⛔ Still no state change requested; this card remains
pm:blockedawaiting the maintainer. Added to the seat's unlock-predicate ledger on #1353.Generated by Claude Code
claude commentedon Sep 11, 2026
Half-state repair — R61 board audit (
repo:hotcrmseat,session_0132iDHq4FLW2zS9VPXqbf9f, 2026-09-11T01:4xZ)No machine-readable line existed at all. The director seat's 2026-08-31 ruling (
5481116680) routed this card upstream verbatim — 「修在平台,⛔ 不逐字段补 ... 已上行 objectstack#13894」 — and stated the transition asneeds-user-decision→pm:blocked (Blocked-by objectstack#13894), but the line was never written into the body. Now canonical:completed. ⛔ That is deliberately not treated as an unlock here — see the R61 unlock-scan note; this lane's criterion is released and install-surface-verified, never merged.Generated by Claude Code
chore(probe): record the R61 install-surface probe for the seven 17.4…
claude commentedon Sep 11, 2026
R61 install-surface probe verdict (#1888 / PR #1891) —
repo:hotcrmseat,session_0132iDHq4FLW2zS9VPXqbf9f🟢 MOOT — closed
completed. Ruled, routed upstream, delivered, verified.The acceptance criterion is written on this card: 「本仓八字段在新默认下建索引成功」. Read from
sqlite_masteron the live seeded DB — the same instrument the card was originally measured with:10 of 10 autonumber business-identifier fields now carry a tenant-composite unique index in the prescribed
COALESCE(organization_id,'__global__'), FIELDshape — includingcrm_article_feedback.feedback_number, the tenth field the 2026-09-03 comment found had already copied the majority shape.⭐ Source still declares
unique: trueon exactly ONE field (crm_case). So this is the platform default doing the work with zero app-side declaration — precisely what the 2026-08-31 ruling ordered (「本仓不做 B」).It bites, and the probe can tell the difference:
ACC-000001in the same partition →REFUSED SQLITE_CONSTRAINT_UNIQUEACC-999999in that same partition → inserts fine5526144304already recorded that option B was never a remedy for that.⇒ Nothing left for this repo. Closed as delivered, ⛔ not dispatched.
Generated by Claude Code