Skip to content

[finding] FieldSchema.scale on a currency field is offered to authors by the field designer, ignored by every display face, and still enforced on writes — half-live in the direction that surprises #19629

Description

@os-steve

Ruled: 5791803339 · letter B · 2026-09-23T08:49Z

Filed at 2026-09-22T02:11Z by the domain:spec seat 4 (session_01AmH9bKvGoLjiY86Q4Z3og2, seat post #18917), from the
out_of_scope_findings of the #19579 round, marked class (c) by the dev. ⛔ Filed unassigned, ⛔ no
priority:*, ⛔ no type — routing and grading are triage's. ⛔ Not a claim. ⛔ Not a ruling.

⭐ This card exists because a ruling said it must. Ruling batch #194 item 1 letter A′ scoped number and
currency to ride #19579's PR only if a consumer census showed one consistent absent-value per type, and
「where consumers disagree, that type gets its own card with the readings」. The currency census came back
inconsistent. ⇒ this is that card, with those readings.

The defect, in one sentence

FieldSchema.scale on a currency field is offered to authors by a named producer, ignored by every
display face
, and still enforced on writes — so setting it buys a narrower write contract and no visible
change. Half-live, in the direction that surprises rather than refuses.

⏱️ Readings — attributed, ⛔ NOT re-taken by this seat

⚠️ Every leg below is the #19579 dev's, taken at objectui origin/main 0cf2d6644b and re-read identically
at the pinned .objectui-sha 87af769e9a. This seat has ⛔ not re-driven them and does ⛔ not assert
them; it files them because the ruling instructs it to and because a card with the readings is worth more
than a card that asks someone to find them again. Whoever takes this re-measures leg 1 first — a producer
is the difference between a dead key and a trap.

Leg 1 — the producer is named, and it is stored metadata, ⛔ not a React prop. The metadata-admin field
designer ships a scale control:
packages/app-shell/src/views/metadata-admin/inspectors/ObjectFieldInspector.tsx:907-909 —
label={tr('designer.field.scale')}, onCommit={(v) => patchDef({ scale: v })}, with the label declared in
i18n.ts:1477 / :3448. ⇒ an author is invited to set it, in a UI this platform ships, and the value is
re-authorable stored metadata.

Leg 2 — no display face reads it on a currency field. CurrencyCellRenderer formats through
formatCurrency(value, currency, locale) and passes no scale; packages/fields/src/widgets/CurrencyField.tsx
reads precision and says so in-line (「No scale passed: this is a currency widget whose precision is a …」);
fraction digits otherwise come from the currency's own ISO 4217 minor-unit count.

Leg 3 — the write path DOES enforce it. packages/objectql/src/validation/record-validator.ts:789-812
enforces max_scale on a currency write from that same declaration. ⭐ This seat did verify the gate's
shape first-hand on origin/main while reviewing #19624, quoted:

if (
  def.scale !== undefined &&
  Number.isInteger(def.scale) &&
  def.scale >= 0
) {

⇒ the enforcement is real and is gated on the declaration being present.

⇒ The observable consequence

An author sets scale: 3 on a currency field in the designer and gets:

  • no display change — the cell still renders at the currency's ISO minor-unit width;
  • a narrower write contract — values with more than 3 decimals are now refused.

⚠️ ⛔ Nothing tells them either fact. This is the 「declared ≠ enforced」 family, except inverted: the
declaration is enforced, just not where the author was looking.

Why a guessed default is refused here

The ruling names it: a global 0 would turn an undeclared currency from $25.00 into $25, which is
exactly why plain letter A was refused. ⇒ ⛔ this card does not propose a default, and the shape of
the answer is open — align the display faces to the declaration, retire the key from the currency surface, or
split display width from write allowance. ⛔ This card states no preference.

Seam

spec:FieldSchema.scale → producer:ObjectFieldInspector | renderer:CurrencyCellRenderer |
renderer:CurrencyField | objectql:record-validator max_scale

Why it lands in THIS repo

The ruling puts the declaration in packages/spec; the consumer half follows in objectui. 〈多仓协调〉rule 1:
「issue 住在修复落地的仓」.

⛔ Independent card, ⛔ NOT a sub-issue of #19579 and ⛔ not blocked by it. ⚠️ Related but ⛔ not a
duplicate: the sibling card filed in the same act covers number, whose obstruction is different (a
declared 0 also turns grouping off).

Dedupe

currency scale ignored display · currency precision vs scale · formatCurrency ISO 4217 minor units ·
CurrencyField precision · max_scale currency write · designer offers scale currency

Activity

  1. objectstack-fleet commented on Sep 22, 2026

    @objectstack-fleet
    Contributor

    Triage: moved to the decision box by the triage seat (session_01Tw7jnJinGHvoGSi8aFkhPJ), 2026-09-22T18:45Z. ⛔ Not dispatchable until ruled.

    Path: records · 每种字段都渲染得出、收得下、存得住 | records-forms.field-type-constraints(② 步骤够不到) | P② | 待裁
    Governing text: 维护者裁决 batch #194 item 1 letter A′;ADR-0049 enforce-or-remove;〈基本裁决原则〉「声明而未兑现是实现缺口,补实现或退役,⛔ 不在消费端收窄」
    Prior rulings on this card: batch #194 item 1 A′ ordered this card to exist; ⛔ no ruling on the key's meaning

    维护者速读

    货币字段有个「小数位」设置:设计器请作者填,显示的时候根本不看,但保存数据时又会按它把数据退回去。也就是说,作者被引导去填一个只会挡自己、不会改变任何显示效果的值。

    两条路:让显示真的按它走(它从此有意义),或者把它从货币字段上彻底拿掉(设计器不再提供,保存也不再按它判)。

    席位建议拿掉:它从来没生效过,所以没有人依赖它的效果;而留着它就等于一直在教 AI 和人去写一个系统不兑现的设置。

    ⚠️ 这和 #19628 是同一个设置的两个问题,建议一起裁,否则两张卡会给出互相打架的答案。

    要您定的一件事:A(让显示按它走)还是 B(货币字段上彻底拿掉它)?

    The reading this rests on

    在 currency(货币)字段上,scale 这个设置是三面不一致的:

    1. 设计器主动请作者填它 —— 对象字段检查器上就有这个输入,提交后写进字段定义(ObjectFieldInspector.tsx:907-909,patchDef({ scale: v }))。这满足「(c) 元数据陷阱」的具名生产者要求:由写它的人以外的人存储并再编辑。
    2. 显示面不看它 —— 货币的渲染走另一条路。
    3. 写入校验却照样按它拒绝 —— record-validator.ts:789-812:def.scale 在 number/currency/rating/slider 上被直接当成允许的小数位。

    ⇒ 作者被引导去填一个「看不见效果、却会退回你数据」的值。

    ⚠️ 一个必须避开的坑(已实测):CurrencyConfigSchema 上另有一个 precision,而且它自己的别名表把 scale 映到 precision(field.zod.ts:420),spec 在 :1205-1206 明确警告这是另一个面,⛔ 不要和 FieldSchema.scale 混为一谈。卡片的第二条腿指的是那个面。

    Options

    A —— 对齐: 让货币的显示面也读 FieldSchema.scale。设计器的输入从此说话算话。
    B —— 退役: 设计器不再在货币字段上提供 scale,写入校验也不再对货币按它判。键在货币上彻底退休。

    四棱

    • 实际业务需求:有具名生产者(设计器就在请作者填),所以这不是投机面;但⛔ 没有测到任何人依赖货币的 scale 显示效果 —— 因为它从来没生效过。
    • 项目长远合理性:「声明即强制」。今天是最糟的中间态:请人填、不兑现、还按它拒收。A 和 B 都终结这个中间态,A 让它有意义,B 让它消失。
    • 防 AI 写错:这一轴指向 B 更强。AI 从设计器上看见这个输入,会把它写进元数据;写了之后行为不变,但写入会因它被拒 —— 这正是「声明一个运行时不兑现的能力」的教科书形状。B 让它当场不存在;A 让它生效,但也把一个新行为写进已发布面。
    • 创业阶段不扩散:B 删一个入口,A 加一段显示逻辑。阶段姿态默认从紧,且废弃立即退休、不设过渡窗口。

    席位推荐:B,并与 #19628 同批裁(同一个 scale 的两个问题,分开裁会互相打架)。⚠️ 但两条路都改已发布的作者面:A 改显示行为,B 拿掉一个设计器入口并放宽一处写入校验 —— 放宽校验触安全/边界之外的「已发布契约语义」,按红线归维护者,⛔ 席位不代裁。


    Generated by Claude Code

  2. objectstack-fleet commented on Sep 23, 2026

    @objectstack-fleet
    Contributor

    Ruling: batch #215 item 1 · letter B · maintainer 「215 同意」 2026-09-23T08:44Z

    Director seat, summon #28 (session_01GLdRPcbaCBQCTvVmU6YEUY). Presented in this seat's chat with recommendation B (retire scale from the currency field type; currencyConfig.precision stays the one decimal-places knob for money); the maintainer approved the batch as presented. B′ (also enforce a declared currencyConfig.precision on writes) was offered as an optional add-on and ⛔ not taken — precision is documented as a display width on both sides of the seam, so a write-side refusal would be a contract expansion, not this card's fix. A (align every money face to FieldSchema.scale) ⛔ not taken: it leaves two overlapping decimal-places knobs on one field type.

    Governing text: 〈基本裁决原则〉「声明而未兑现是实现缺口,补实现或退役,⛔ 不在消费端收窄」; ADR-0049 enforce-or-remove; batch #194 item 1 A′ (the absent-value ruling that ordered this card; packages/spec/src/data/field-scale.ts docblock); #7501 (an over-scale write is REFUSED, never rounded); #7918 / #11423 (CurrencyConfigSchema.precision and its ISO contradiction check). Prior rulings read: fieldschema.scale,fieldschema,scale,currency,field,offered,authors,designer,ignored,display,face,enforced (+4 more) → 187 hits; ADR-0032 Decision §3, ADR-0005 Decision §5, ADR-0031 Decision §6, ADR-0031 Decision §7, ADR-0035 Decision §3, ADR-0041 Decision §4, ADR-0045 Decision §6, ADR-0055 Decision §1, ADR-0058 D3; thread: none; repo: objectstack-ai/objectstack — none rules on this key's meaning.

    Reading corrected on the card: 「ignored by every display face」 is false — the grid summary footer's currency arm reads column.scale ?? 0 (objectui packages/plugin-grid/src/useColumnSummary.ts:343). Today's three faces on a currency field: cell → the currency's ISO minor units / currencyConfig.precision; summary footer → scale ?? 0; write validator → scale (packages/objectql/src/validation/record-validator.ts:789). Control reading: examples/** holds 2 currency fields, 0 declare scale.

    Ruled shape — B, scale is retired from currency

    1. packages/spec (FieldSchema): scale on a field of type: 'currency' is REFUSED at parse with a remedy naming currencyConfig.precision (the per-type superRefine house pattern). ⛔ No alias, ⛔ no grace window (阶段姿态: retirement is immediate). The scale describe names the type set it still applies to. An ADR-0087 migration entry covers stored metadata (a scale on a currency field → move the value to currencyConfig.precision, or delete it).
    2. packages/objectql record validator: the max_scale branch no longer reads def.scale for currency — the type leaves the enforced set; percent / number / rating / slider are unchanged.
    3. objectui (the consumer half, filed by this seat as currency fields: hide the scale designer control; the summary footer and the metric tile take a currency's decimals from its ISO 4217 minor unit (objectstack#19910 ruling 乙) objectui#10221, pm:blocked on this card): the field designer stops offering scale on a currency field; the summary footer's currency arm derives fraction digits the way the cell does — ⛔ no ?? N, ⛔ no scale read on currency.
    4. Pins: a currency field carrying scale fails parse with the remedy; a currency write with more decimals than any declared precision is still ACCEPTED when nothing declares a width (today's contract, unchanged); the footer and the cell agree on a currency column.

    Execution

    needs-user-decision → pm:queue in this stroke; domain:spec · priority:p3 · Clause-②: no (a narrowing). Same scale surface as #19628 (ruled A′ in the same batch): two cards, two dispatches, one reading of the key.

  3. os-support-ai commented on Sep 23, 2026

    @os-support-ai
    Collaborator

    Claim: PM loop — execute ruling B: scale is retired from the currency field type (refused at parse with a remedy naming currencyConfig.precision), and the record validator stops enforcing scale on currency, dispatched at 2026-09-23T14:40Z
    Session: session_013RDBh5DqXd2xnLwvHLgLFr
    Branch: claude/issue-19629-currency-scale-retired
    Worktree: objectstack-issue-19629
    Domain: domain:spec
    Seat: domain:spec#1
    File surface: packages/spec/src/data/field.zod.ts (the currency arm of FieldSchema's per-type superRefine, and the scale describe) and its tests; one ADR-0087 semantic entry with packages/spec/src/migrations/registry.ts regenerated, ⛔ never hand-edited; whatever the generators rewrite; .changeset/. Cross-lane, declared by the ruling's item 2: packages/objectql/src/validation/record-validator.ts (the max_scale branch drops currency from its enforced set; percent / number / rating / slider unchanged) and its tests. ⛔ The objectui half is objectstack-ai/objectui#10221, pm:blocked on this card, and is not this claim.
    Container & model: M, mode:subagent, model: opus (default judgment tier)
    Clause-②: no
    Thread-read: 5791803339
    Serial constraints cleared: census over all 22 open PRs at 2026-09-23T14:40Z (254 file rows; lit control 55 packages/spec/ rows). field.zod.ts and record-validator.ts are CLEAR. PR #19728 edits packages/objectql/src/validation/rule-validator.ts, a different file. registry.ts is held by other open PRs, which is its normal state, resolved by the generator. #19628 is the linked card on the same scale key (ruled A′ in the same batch). Linked cards are ⛔ never dispatched in the same batch, so it waits for this one.

    The ruling this executes: 5791803339 (batch #215 item 1, letter B, 「215 同意」): ⛔ no alias, ⛔ no grace window; B′ (enforcing currencyConfig.precision on writes) was ⛔ not taken.


    Generated by Claude Code

  4. objectstack-fleet commented on Sep 23, 2026

    @objectstack-fleet
    Contributor

    os-dev-report
    {
    "issue": 19629,
    "status": "done",
    "branch": "claude/issue-19629-currency-scale-retired",
    "pr": "#19909",
    "session": "session_013RDBh5DqXd2xnLwvHLgLFr",
    "premise_still_valid": true,
    "summary": "Executed ruling 5791803339, letter B. (1) FieldSchema refuses scale on a currency field at parse. It uses the per-type superRefine house pattern, raises one custom issue at scale whose remedy names currencyConfig.precision, and has no alias and no grace window. The scale describe names the set the key still applies to: number, percent, rating and slider (enforced on writes) and formula (rounded). (2) The record validator's max_scale branch skips currency; number, percent, rating and slider are unchanged, and min, max and the finite check still apply to currency. (3) ADR-0087 semantic entry field-currency-scale-refused was added and registry.ts regenerated with gen:migration-registry. (4) scale: 2 was deleted from 15 example Field.currency sites (app-crm 4, app-showcase 11) and from 13 documentation examples, plus the schema.mdx table row. The generated reference docs (field.mdx, object.mdx, migration.mdx) were regenerated. The changeset is minor for spec and objectql, with a BREAKING banner, Clause-②: no (narrowing) and the adr-0087 registered marker. Premise measured on BASE 1f89ba0: a currency field with scale: 2 parsed; a currency write of 1.234 with scale: 2 was refused with max_scale {scale:2, actual:3}; max_scale read def.scale on all of number, percent, rating and slider (plus currency). FOUR READINGS DIFFER FROM THE RULING and are raised in open_questions, not acted on. (a) currencyConfig.precision has zero readers at .objectui-sha pin 62597c588072 and in this repo's non-test code. The edit widget reads the field-level precision; the cell reads only the ISO minor unit. Adding a bare currencyConfig also materializes defaultCurrency 'CNY'. The remedy was written as ruled, but so that following it cannot add a currencyConfig. (b) The ruling's control '2 example currency fields, 0 declare scale' is wrong: 15 did. (c) A fourth face, the dashboard ObjectMetricWidget currency arm, reads scale ?? 0. (d) The validator half moves writes from refused to accepted, a direction the #19320 precedent declared as widening. Assignee was already set when I started (os-support-ai); I never wrote it. The newest Claim names this branch. One deviation: my first push was a bare git push, not wrapped in write-pace. The local permission classifier refused it before it reached the network. It was re-sent correctly through write-pace.",
    "tests": "HEAD 7c0a33c. Every test run went through os-verify-lock. spec vitest run --project local: 527 files, 15509 passed, 1 todo; --project repo: 35 files, 602 passed (both ran at a5858ed; the only later commit is a docblock-only line in field-scale.ts). objectql --project local: 305 files, 5093 passed; --project repo: 1 file, 5 passed. platform-objects: 54 files, 883 passed. metadata-core: 16 files, 285 passed. driver-sql: 179 files passed, 11 skipped; 2645 tests passed, 168 skipped. service-automation: 142 files, 1697 passed (includes the flow oracle). example-crm: 5 files, 45 passed. example-showcase: 29 files, 384 passed. typecheck exit 0 for spec, objectql, metadata-core, driver-sql, service-automation, example-crm and example-showcase. turbo build over packages and examples: 73 of 73 successful. Gates: dispatch-gates --commands derived 119 families; all 119 were run on 7c0a33c with exit codes captured before any pipe, and all exited 0. --ran reconciliation: '119 derived famil(ies) accounted for — 119 run, 0 NOT-MEASURED (a DERIVED zero — all 119 recorded an exit code and none of them is 3)'. Three families first answered PREREQUISITE NOT MET (exit 3) on a partial build and were re-run after the full build: dual-build-cjs-loads, type-check-debt, skill-examples. check:objectui-pin-citations went red once on my own new docblock; it was fixed in 7c0a33c. check:generated: 'All 15 generated artifacts are up to date'. check-adr-0087-registration: '[BREAKING+bang+clause-②-narrowing] registered field-currency-scale-refused'. check-changeset-no-major: no major; its level axis reads the PR body and was NOT MEASURED locally. Lint was narrowed to the diff: eslint --no-inline-config --format json over the 24 changed ts/mjs files counted 24 files, 0 errors, 0 warnings and no ignore notices. eslint.config.mjs never enables type-aware linting (its comment at lines 326-328), so no untouched file's verdict can move; the full pnpm lint belongs to CI. Reverse verification ran from the committed state with a trap on EXIT/INT/TERM. The file was restored to its BASE blob and the landing was proved by hash and by an anchor count of 0, then the file was restored with git checkout HEAD -- and the restore was proved by hash equality with the HEAD blob and an empty git diff HEAD. Both subjects resolve through a relative src import, so no rebuild or dist preflight was involved. field.zod.ts at BASE blob cc96254284 gave 5 failed, 3 passed in field-currency-scale-refused.test.ts: the four refusal pins and the describe pin went red and the three controls stayed green; restored to 0c24baa382. record-validator.ts at BASE blob 2e2d3981d2 gave 1 failed, 111 passed in record-validator.test.ts: only the legacy-scale-accepted pin went red, while the unchanged-contract pin, the min/max/finite pin and the number/percent controls stayed green; restored to c200751358.",
    "mcp_calls": "0",
    "api_writes": "7 attempted writes, 6 landed. git push through write-pace: 5 attempts, 4 landed (the empty-branch probe, 2dbab9f, a5858ed on a retry after one remote HTTP 500, and 7c0a33c). fleet-write relay: 1 POST /repos/objectstack-ai/objectstack/dispatches (HTTP 204, run 35894914237 success), which executed op pr_create as POST /repos/objectstack-ai/objectstack/pulls with draft true and opened #19909. This os-dev-report comment is 1 POST /repos//issues/19629/comments via post-stamped. 0 label writes: the dispatch forbids them. 0 PATCH writes to the PR body. Denied before the network: 1 bare git push, refused by the local classifier.",
    "open_questions": [
    {
    "question": "The ruled remedy names currencyConfig.precision, but at .objectui-sha pin 62597c588072 nothing reads that key. The cell uses only the currency's ISO 4217 minor unit. The edit widget, packages/fields/src/widgets/CurrencyField.tsx:76-77, reads the FIELD-level precision, and its own comment says currencyConfig.precision is a different key it never reads. This repo's liveness ledger agrees. The ruling's reading 'cell reads ISO minor units / currencyConfig.precision' therefore does not hold. Also, adding a currencyConfig block materializes defaultCurrency 'CNY', so a naive move changes the currency the field displays. Which key, if any, should the refusal and the migration entry point to?",
    "options": [
    "A: keep as ruled and shipped. The remedy says delete by default, and move to currencyConfig.precision only on a field that already declares a currencyConfig. Cost: the remedy still names a key no face reads.",
    "B: name the field-level precision, which the pinned edit widget reads as display width and which #7918 already checks against a fixed currency. Cost: its describe says 'Total digits', which contradicts that reading (see findings), and the cell ignores it. Replacement sentence for the refusal and the entry: 'Delete the key. To pin the amount's display width, declare the field-level precision instead.'",
    "C: name no knob. Replacement: 'Delete the key: a currency amount's decimal places come from its currency (the ISO 4217 minor unit).' Also drop the move arm from the migration entry. Cost: departs from the ruling's letter."
    ],
    "recommendation": "C, or A until the seat rules. C removes the one remaining pointer to an unread key, and every one of the 15 in-tree sites was a delete anyway. The four-axis framework was not carried in the dispatch, so this recommendation is not axis-scored. Changing the remedy means re-running the parse-refusal pin's named-subject assertion (field-currency-scale-refused.test.ts, first test)."
    },
    {
    "question": "Landing order. At the pin, the grid summary footer and the dashboard ObjectMetricWidget currency arm read scale ?? 0. With scale: 2 deleted from the 15 example fields, those two faces render currency with zero decimals from this merge until objectui#10221 lands with a pin bump. The metric widget is not in objectui#10221's ruled scope.",
    "options": [
    "A: land this PR as is and accept the transitional window.",
    "B: hold this PR's merge until objectui#10221, widened to cover the metric widget, lands and the pin moves.",
    "C: unblock objectui#10221 now. Deriving the footer and metric digits from the currency does not depend on this spec change, so it can land first."
    ],
    "recommendation": "C, then land this. The consumer half has no build dependency on the spec narrowing, and landing it first closes the zero-decimal window."
    },
    {
    "question": "Clause-② direction. The ruling and the Claim say no, and the PR and changeset declare Clause-②: no (narrowing). But the validator half moves writes from refused to accepted, for currency defs that still carry scale. The #19320 precedent declared a max_scale allowance change of that direction as yes (widening).",
    "options": [
    "A: keep no (narrowing) as ruled. After this change no authored currency field can declare scale, so the widened cell set is stored or hand-built defs only.",
    "B: re-declare yes (narrowing) in both the PR body and the changeset."
    ],
    "recommendation": "A. It is the ruling, and the widening reaches only defs the spec now refuses. It is flagged because the precedent reads the other way."
    }
    ],
    "out_of_scope_findings": [
    "class: c · Seam: spec:CurrencyConfigSchema.precision → renderer: none (consumer: none at .objectui-sha pin 62597c588072; objectstack non-test code: none). The key is taught as a currency width by content/docs/data-modeling/fields.mdx (currencyConfig example with precision 2) and now by this PR's ruled remedy. Every face silently drops it: the cell renders the ISO minor unit, and the widget reads the field-level precision (CurrencyField.tsx:76-77, whose comment says 'a different key on the currencyConfig block that this widget never reads'). Named producer: authored metadata and the docs example. · dedupe words: currencyConfig precision unread · currency precision no reader · CurrencyField field precision · currencyConfig precision display width",
    "class: b · Seam: spec:FieldSchema.precision → renderer:CurrencyField. The contract text says precision is 'Total digits (non-negative integer)' (field.zod.ts describe; schema.mdx table 'Total digits (including scale)'). But FieldSchema's own #7918 superRefine judges a currency field's precision as FRACTION digits against the ISO 4217 count, and the pinned CurrencyField renders it as fraction digits. So the documentation YAML examples with precision: 18 on a currency field (schema.mdx ×3, types.mdx) would render 18 fraction digits in the edit widget. This predates this PR; those lines were not touched. · dedupe words: precision total digits currency · currency precision 18 docs · field precision fraction digits currency · #7918 field precision",
    "class: b · Seam: spec:FieldSchema.scale (retired on currency) → renderer:ObjectMetricWidget. The pinned console's plugin-dashboard/src/ObjectMetricWidget.tsx:229 currency arm reads valueFieldDef.scale ?? 0. After this PR it is a reader of a key the spec now refuses on currency, and it reaches no row in the ruling's face list. Carrier: objectui#10221 (the ruling's consumer half); I name it as a sub-issue or scope extension of that card, not a new card. · dedupe words: metric widget currency scale · ObjectMetricWidget scale currency · dashboard metric decimals currency",
    "carrier: checklist-author seat (承接者:无 named) · noted, not filed. docs/qa/platform-checklist/areas/records-forms.json still describes f_currency as 'scale 2 currencyConfig{precision 2}', and its knownGaps text ('scale not enforced on write') has been stale since #7501. Recorded in the PR's Acceptance notes.",
    "carrier: none (承接者:无) · noted, not filed. The FieldSchema alias table renames decimals / decimalPlaces to scale, so on a currency field that rename now leads into this refusal. The refusal's remedy carries the author on, so this is not a defect. Recorded in Acceptance notes.",
    "carrier: none (承接者:无) · noted, not filed. hotcrm (hotcrm#1206, cited by the flow oracle) declares scale: 2 on a currency quote field, which becomes a refused parse downstream. The migration entry covers it. Recorded in Acceptance notes."
    ]
    }

  5. os-support-ai commented on Sep 23, 2026

    @os-support-ai
    Collaborator

    Hold note, 2026-09-23T17:25Z: PR #19909 executes ruling 5791803339 to the letter. The round measured counter-facts: currencyConfig.precision has no reader at the objectui pin or in this repo's non-test code, and two console faces (the grid summary footer and ObjectMetricWidget) read scale ?? 0, so deleting scale from the 15 example fields shows those amounts with zero decimals until objectui#10221 lands. Filed as decision card #19910. ⛔ The seat does not arm PR #19909 for merge until #19910 is answered.


    Generated by Claude Code

  6. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    Contributor

    Ruling correction: batch #215 item 1 · letter B unchanged · one control reading corrected · director seat 2026-09-24T00:33Z

    Director seat, summon #28 (续) (session_01GLdRPcbaCBQCTvVmU6YEUY). Ruling 5791803339 said 「examples/** holds 2 currency fields, 0 declare scale」. That reading was WRONG: the instrument matched type: 'currency' literals and missed the Field.currency(…) builder. Re-taken on origin/main fdeeea0: 16 Field.currency( sites in examples/**, 15 of them declare scale: 2 — as the #19629 round found and PR #19909 deletes under the ruling's migration prescription. The letter (B) stands. The counter-facts that round measured about currencyConfig.precision (no reader anywhere) are the subject of #19910, presented to the maintainer as batch #218 item 2; ⛔ nothing is re-ruled here.

  7. 10 remaining items

  8. objectstack-fleet commented on Sep 24, 2026

    @objectstack-fleet
    Contributor

    Blocker re-derived: objectui#10221 landed; the card now waits on the console pin bump #20029

    Blocked-by: #20029
    Unlock-action: re-check PR #19909

    domain:spec execution seat 1 (session_013RDBh5DqXd2xnLwvHLgLFr), 2026-09-24T20:14Z. The upstream objectstack-ai/objectui#10221 closed, so per comment 5818216091 the blocker is re-derived rather than released.

  9. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    Contributor

    Unlocked: #20029 closed and the pin covers objectui#10221's fix; PR #19909 goes to the queue

    domain:spec execution seat 1 (session_013RDBh5DqXd2xnLwvHLgLFr), 2026-09-25T00:38Z, running its 留守 item as named in the shift brief 5824072704 on #6017. The Blocked-by: #20029 line in 5821531422 was re-derived and no new blocker was found, so this act replaces pm:blocked with pm:dispatched. The claim and the assignee stay until the PR merges.

  10. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    Contributor

    Landed — PR #19909 → 5b9402d89b on origin/main, verified by content

    domain:spec execution seat 1 (session_013RDBh5DqXd2xnLwvHLgLFr), 2026-09-25T01:02Z. This is the 留守 item named in the shift brief 5824072704 on #6017.

    Path.

    Re-measured on origin/main, parent against squash:

    reading parent squash
    field.zod.ts: if (field.type === 'currency' && field.scale !== undefined) (the refusal) 0 1
    field.zod.ts: the ruled first sentence "scale is not valid on a currency field — delete the key." 0 1
    field.zod.ts: the describe clause "REFUSED on a currency field — delete it there" 0 1
    the refusal block itself (13 lines) mentioning currencyConfig or precision (ruling 乙 ⛔) — 0
    18.field-currency-scale-refused.ts exists / its currencyConfig mentions 0 / — 1 / 0
    registry.ts: 'field-currency-scale-refused' 0 1
    record-validator.ts: t !== 'currency' && (currency leaves the max_scale set) 0 1
    object.form.ts: the scale row offered on ['number','currency','percent'] (round-3 fix) 1 0
    object.form.ts: the scale row offered on ['number','percent'] 0 1
    examples/**: Field.currency( lines that carry scale: 2 8 0
    dark control: object.form.ts's precision row (#7918), unchanged 1 1
    dark control: field.zod.ts's pre-existing currencyConfig.precision mention (a comment at :486, outside this PR) 1 1

    Card state.

    • pm:dispatched is removed and the assignee is cleared in this act (relay run 36080204764, read back as 3 labels and 0 assignees).
    • GitHub closed the card completed through Fixes #19629.
    • The 留守 Routine trig_01FU95dKzWatpxgAxF9m18w2 is deleted after this record.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:recordsBusiness objects, records, the views that show data, usable forms, searchdomain:specpriority:p3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions