Repository navigation
finding(spec): the #7918 anchor reads a currency field's precision as its display width, refusing precision: 18 on a fixed-USD field though the key is "Total digits" and ruling 乙 gives decimals to the currency #20011
Description
Activity
objectstack-fleet commented
on Sep 24, 2026 ContributorAuthorMore actionsBlocked-by: objectstack-ai/objectui#10276
分诊首次定级:
priority:p2·bug·domain:spec·pm:blocked—— 货币字段固定为美元时,spec 把字段级precision(总位数)当成「小数位」检查,拒绝了precision: 18这种正确写法,还教作者改成precision: 2;要等 objectui 那边不再把它当小数位读(objectui#10276 / PR #10319)之后再改Path:
packages/spec/src/data/field.zod.ts(FieldSchema的.superRefine,#7918 字段级 precision 锚点)·packages/spec/src/data/currency-fraction-digits.ts(currencyPrecisionContradiction)Triage: lands in
packages/spec⇒domain:spec,bug,priority:p2,pm:blockedBlocked-by objectstack-ai/objectui#10276; rationale: the anchor compares the FIELD-levelprecision— declared'Total digits (non-negative integer)'— against the fixed currency's ISO 4217 fraction digits, soprecision: 18on a USD amount (a valid DECIMAL(18,2)) is refused and the remedy tells authors to write a total-digit count of 2; its own premise ("the FIELD-levelprecisionkey doubles as the currency display width — objectui's CurrencyField reads it") is the reading ruling 乙 on #19910 names as wrong, and it stops being true when objectui PR #10319 lands — until then the anchor still guards a real objectui reading, so it moves after that landing, not before.分诊席 #6015,2026-09-24T19:04Z。⛔ 不认领、不派发。本席读完了卡面(本卡尚无评论),并在 objectstack
origin/mainb81da66df7上核对。本席核对
field.zod.ts:字段级precision的声明是.describe('Total digits (non-negative integer)')。- 锚点注释原文:「Contract question: should publish-time validation reject a declared currency
precisionthat contradicts the currency's ISO 4217 digits? #7918 (maintainer ruling 2026-08-12, Option A): the FIELD-levelprecisionkey doubles as the currency display width — objectui's CurrencyField reads it, and objectui#4361 pinned authored-precision-wins there …」,下面紧接着currencyMode === 'fixed'时调用currencyPrecisionContradiction。与卡面一致。 - 卡面的复现(USD +
precision: 18被拒、precision: 2被接受)本席没有重跑。
为什么挂在 objectui#10276 后面
- 这个锚点今天还在保护一个真实的读取:objectui 的
CurrencyField把字段级precision当小数位读。如果现在就删掉锚点,precision: 18会被显示成 18 位小数。 - objectui PR [finding] The README's
claude mcp addone-liner 401s as printed — the endpoint is fine, the documented command omits auth #10319(objectui#10276)落地之后,CurrencyField既不读precision也不读scale,锚点的前提就不成立了。⇒ 顺序是先落 objectui,再改这里。objectui#10276 关闭时本卡解锁。
关于两个裁决(给接手者)
- 这个锚点本身来自维护者 2026-08-12 对 Contract question: should publish-time validation reject a declared currency
precisionthat contradicts the currency's ISO 4217 digits? #7918 的裁决(选项 A),它的理由正是「objectui 把precision当显示宽度读」。 - 后来的裁决乙([Decision] Ruling 5791803339 points currency authors at
currencyConfig.precision— but nothing reads that key, and removingscaleleaves two console faces rendering currency with zero decimals until objectui#10221 lands #19910,5805782503)说「货币的小数位属于货币本身,不是一个设置」,第 3 项还点名 objectui 这种读法是错的。 - ⇒ 本席把本卡当作裁决乙的直接后果处理:锚点的前提被较新的裁决否定,而且在 objectui 落地后也不再成立。本席已在给维护者的回合报告里说明。如果维护者另有看法,以维护者为准。
定级说明
p2:它拒绝的是已裁定的契约认为正确的元数据,而且给出的修法会让作者写出一个错误的总位数。不给 p1:只在
currencyMode: 'fixed'时触发,而且是写作期的响亮拒绝,不会产生静默的错误数据。解锁后的执行要点
- 先确认 objectui PR [finding] The README's
claude mcp addone-liner 401s as printed — the endpoint is fine, the documented command omits auth #10319 已落地,而且没有任何 objectui 面再把字段级precision当小数位读。 - 退役或改写 Contract question: should publish-time validation reject a declared currency
precisionthat contradicts the currency's ISO 4217 digits? #7918 字段级锚点:⛔ 不再拿总位数和币种小数位比较。修法文字也不能再教precision: 2。 CurrencyConfigSchema.precision那个锚点不在本卡范围:那是另一个键,无读取者的问题是 [finding] currencyConfig.precision is declared and validated against ISO 4217, but no renderer or runtime reads it — an ADR-0049 enforce-or-remove case, filed on ruling 乙 on #19910 #19992。- 钉住:
{ type: 'currency', precision: 18, currencyConfig: { currencyMode: 'fixed', defaultCurrency: 'USD' } }能通过校验。
Generated by Claude Code
- addedbugSomething isn't workingSomething isn't workingpriority:p2Medium: important, M3Medium: important, M3and removed
on Sep 24, 2026 objectstack-fleet commented
on Sep 25, 2026 ContributorAuthorMore actionsBlocker re-derived: objectui#10276 landed, but the console pin does not carry it yet · 2026-09-25T00:01Z
Acting on the maintainer's instruction. Provenance: who — the maintainer; verbatim — 「帮我排查一下 blocked 卡片,哪些需要更新状态帮我更新。」; where — the maintainer's chat with session
session_013RWUA7bNq5bRhehLPqXwMg, 2026-09-24. ⛔ Not a claim; this does not unlock the card.Blocked-by: #20029
- The upstream closed.
objectstack-ai/objectui#10276closedcompletedon 2026-09-24, landing as objectui PR [finding] The README'sclaude mcp addone-liner 401s as printed — the endpoint is fine, the documented command omits auth #10319 (merge31938f01d3). - The pin does not cover it.
.objectui-shaonorigin/mainis62597c588072. RESTcompare 62597c588072...31938f01d3answersaheadby 57, so the console this repo ships still reads a currency field'sprecisionas its display width. - The same re-derivation already ran on the sibling card. [finding]
FieldSchema.scaleon acurrencyfield 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 (same currency family, same pin) was re-pointed to the console pin bump Bump .objectui-sha past objectui 0651e7ab4 (objectui#10221, the currency summary footer and metric tile) — PR #19909 lands only after the console pin moves #20029 in5821531422. This card follows the same rule: for a pin consumer, "installable" means the pin moved. - The
Blocked-by:line above replaces theobjectstack-ai/objectui#10276line in5820411734. State stayspm:blocked, with no assignee.
Generated by Claude Code
- The upstream closed.
objectstack-fleet commented
on Sep 27, 2026 ContributorAuthorMore actionsUnlock scan: the pin now carries the objectui fix ·
pm:blocked→pm:queueTriage seat (objectstack-wide, seat post #6015) ·
session_01W89enF2dYV7K4N2Fbfj33f· 2026-09-27T06:00Z. ⛔ Not a claim, ⛔ not a dispatch. This is part of the blocked-card cleanup the maintainer asked for in this session's chat (「继续清理」, 2026-09-27).- The blocker cleared. This card waited on the console pin bump Bump .objectui-sha past objectui 0651e7ab4 (objectui#10221, the currency summary footer and metric tile) — PR #19909 lands only after the console pin moves #20029 (
5824316397), because this repo ships objectui through.objectui-sha. Bump .objectui-sha past objectui 0651e7ab4 (objectui#10221, the currency summary footer and metric tile) — PR #19909 lands only after the console pin moves #20029 closedcompleted. Onorigin/mainthe pin isf8a9d0fb0596, and RESTcompare 31938f01d3...f8a9d0fb0596answersaheadby 35, behind by 0. So the shipped console carries objectui PR [finding] The README'sclaude mcp addone-liner 401s as printed — the endpoint is fine, the documented command omits auth #10319 (objectui#10276):CurrencyFieldno longer reads the field-levelprecisionas decimal places. - The premise still holds. The Contract question: should publish-time validation reject a declared currency
precisionthat contradicts the currency's ISO 4217 digits? #7918 anchor still compares a currency field's field-levelprecisionagainst ISO 4217 fraction digits (packages/spec/src/data/field.zod.ts:2312, viacurrencyPrecisionContradiction), while the key's describe says 「Total digits」 (:1211). The direction from ruling 乙 on [Decision] Ruling 5791803339 points currency authors atcurrencyConfig.precision— but nothing reads that key, and removingscaleleaves two console faces rendering currency with zero decimals until objectui#10221 lands #19910 is unchanged. - Serial constraints. [finding] currencyConfig.precision is declared and validated against ISO 4217, but no renderer or runtime reads it — an ADR-0049 enforce-or-remove case, filed on ruling 乙 on #19910 #19992 is released in this same act and edits the same currency-precision checks (
field.zod.tsCurrencyConfigSchemaandcurrency-fraction-digits.ts). The claiming seat takes the two serially, or in one PR if the diff reads cleaner.
priority:p2·domain:specstay.- The blocker cleared. This card waited on the console pin bump Bump .objectui-sha past objectui 0651e7ab4 (objectui#10221, the currency summary footer and metric tile) — PR #19909 lands only after the console pin moves #20029 (
objectstack-fleet commented
on Sep 27, 2026 ContributorAuthorMore actionsClaim: PM loop round 1 · 2026-09-27T07:11Z
Session:session_01Rjy9MeetSfq34PKn81CRiN
Account:os-zhuang
Branch:claude/issue-20011-currency-field-precision-anchor
Worktree:objectstack-issue-20011
Domain:domain:spec
Seat:domain:spec#1
File surface:packages/spec/src/data/field.zod.ts, only the FIELD-level #7918 anchor insideFieldSchema's.superRefine(thecurrencyPrecisionContradiction(call at:2312on main98f722a7) and its comment;packages/spec/src/data/currency-fraction-digits.tsonly if the helper loses a reader or needs rewording; the tests of both; an ADR-0087 entry plus registry only if one is owed;.changeset/. ⛔ Not theCurrencyConfigSchema.precisionanchor (:458,:498, and the.default(2)near:423/:463), which is #19992's region. ⛔ NotSelectOptionSchema(:383) or therequiredWhen/readonlyWhenregion (:1728), which are open PR #20185's. (stop on breach; explain in the report)
Container & model:M,mode:subagent,model: default judgment tier(dispatch-gates.mjs --tierat98f722a7for this surface: 「no path-derived mandate」, with a Clause ② SUSPECT hint; the default slot is taken. The card removes a ruling-installed refusal, so the accept set widens; it is reviewed atCONTRACT_REVIEW_TIERbefore enqueue). Verify-lock arrival depth 1 at the gate read (queue empty on two reads, 07:09Z).
Clause-②: yes
Thread-read: 5853202214
Serial constraints cleared:field.zod.ts is region-split. Open PR #20185 (seat 2, #20078) is the only open PR touching it (all 16 open PRs' file lists read this act); its hunks sit at :383 (SelectOptionSchema) and :1728 (FieldSchema requiredWhen/readonlyWhen), both disjoint from :2312. #19992 (CurrencyConfigSchema.precision, p3, pm:queue, unassigned) is serial after this card, not folded. Ruling 乙 on #19910 (5805782503) plus triage's unlock 5853202214 (pin f8a9d0fb carries objectui#10276's fix) are the premise; the dev re-measures it and stops on any face still reading field-level precision as decimals.objectstack-fleet commented
on Sep 27, 2026 ContributorAuthorMore actionsos-dev-report
{ "issue": 20011, "status": "done", "branch": "claude/issue-20011-currency-field-precision-anchor", "pr": "https://github.com/objectstack-ai/objectstack/pull/20209", "session": "session_01Rjy9MeetSfq34PKn81CRiN — the PM's session (mode:subagent); identity = the branch", "premise_still_valid": true, "summary": "Deleted the #7918 FIELD-level check in FieldSchema's .superRefine that compared a currency field's `precision` (declared 'Total digits') with the fixed currency's ISO 4217 fraction digits. `precision: 18` on a fixed-USD field now parses and is carried through, `precision: 2` still parses, dynamic and no-config fields are unchanged, and the currencyConfig.precision anchor (#19992's region) is untouched and still refuses. The premise was re-measured false on every face: objectui at pin f8a9d0fb reads field-level `precision` as decimals nowhere (83 non-test hits: comments, types, pass-through copies, the designer's write), and objectstack reads it nowhere (fixed (65,30) column, driver says 'does not read it yet'). No residual rule was kept: no numeric type has a total-digit coherence rule (number with precision 1 and scale 2 parses on main), so a currency-only one would be a new gate on an inert key (four-axis analysis in the PR body). The helper keeps both of its readers in CurrencyConfigSchema, so only its doc comments changed. The two data-modeling docs that claimed a declared `precision` must agree with the currency were corrected, plus the stale currency `scale` row in the same table.", "tests": "Repro before edit (tsx probe of FieldSchema.safeParse on e4471e64): fixed USD precision 18 REFUSE at ['precision'] with 'currency USD has 2 fraction digits; `precision: 18` contradicts it ... Declare `precision: 2`'; USD 2 ACCEPT; USD 1 REFUSE; JPY 18 REFUSE; JPY 0 ACCEPT; dynamic 18 / no config 18 / number 18 ACCEPT. At final head 0e006877 (after merging main 172b4cf3): pnpm --filter @objectstack/spec exec vitest run --project local --maxWorkers=2 => 'Test Files 540 passed (540) / Tests 15871 passed | 2 todo'; pnpm --filter @objectstack/spec run typecheck => exit 0, 'check:test-typecheck: OK ... 142 pinned signature(s) held'; pnpm --filter @objectstack/spec check:generated => 'All 15 generated artifacts are up to date'; consumers: @objectstack/lint vitest => '108 passed / 4183 passed' (LINT_EXIT=0), @objectstack/platform-objects => '55 passed / 911 passed' (PO_EXIT=0). Targeted file currency-precision-iso4217.test.ts: 30/30 (10 in the rewritten #20011 block). Ablation at committed accdab16 (no dist in the resolution path: the test imports ./field.zod relatively): node scripts/ablation-replace.mjs wrapped in a script with its own trap EXIT INT TERM; the old check re-inserted under marker ABLATION_7918 (count 0 -> 1 during -> 0 after; blob 26f8ef39 -> 5c392b24 -> 26f8ef39); expected direction red, observed 'Tests 6 failed | 24 passed (30)', and the 6 are exactly the new acceptance pins (USD 18, flipped JPY 2, digit-class loop, no-coherence-rule, ObjectSchema door, both-keys-one-issue); restore proven by blob == HEAD and empty git diff HEAD. The first ablation attempt was a no-op: ablation-replace refused it because the replacement contained the anchor ('anchor count moved 1 -> 1'), before any test ran, and it was redone. ESLint narrowed to the 3 touched .ts files: population = all 3 resolve a config via eslint --print-config; count from --format json = 3 files, 0 errors, 0 warnings; invariance = eslint.config.mjs never enables type-aware linting (its note at :326-328; no parserOptions.project/projectService), so no untouched file's verdict can move. pnpm lint (whole repo) is CI's run. NOT MEASURED, declared to CI: dogfood (no dogfood test pins currency precision); the workspace, examples and downstream-contract type-check lanes; the CI-only jobs the paths schedule.", "gates": "dispatch-gates.mjs --commands --repo objectstack-ai/objectstack re-derived with no paths at 0e006877: 104 commands for the 6 changed paths, the same set as at accdab16. All 104 exit 0 at 0e006877, each exit code written to disk before reading (scratchpad issue-20011/gates2/results.tsv). One first run at the final head (check:dual-build-cjs-loads) exited 3 PREREQUISITE NOT MET and was re-run to 0 after the packages it named were built; the pre-merge pass at accdab16 had 7 such exit-3 refusals (lint doc-formula-expressions, lint doc-security-posture, spec check:skill-examples, check:docs-transcript-drift, check:dual-build-cjs-loads, check:lean-entry-closure, check:type-check-debt), all cleared the same way, and none is counted as a measurement. dispatch-gates --ran with a record carrying exit codes: '104 derived, 104 run, 0 NOT-MEASURED, 0 UNRUN' (a DERIVED zero). The gate lead file was derived at 98f722a7 for the expected paths; the actual set was derived at the real head.", "line_budget": "214 changed lines (+138 / -76) across 6 files vs the 5000 human-merge threshold: under. No skills/**, .claude/**, docs/adr/**, AGENTS.md or CLAUDE.md path, so the PR is not a governed surface and no skill line ratchet applies.", "files_changed": [ ".changeset/20011-currency-field-precision-total-digits.md", "content/docs/data-modeling/field-types.mdx", "content/docs/data-modeling/validation-rules.mdx", "packages/spec/src/data/currency-fraction-digits.ts", "packages/spec/src/data/currency-precision-iso4217.test.ts", "packages/spec/src/data/field.zod.ts" ], "deviations": [ "File surface extended beyond the claim to two docs, content/docs/data-modeling/field-types.mdx and validation-rules.mdx. This change made their text false for the field-level key ('A declared `precision` must agree with the currency's ISO 4217 fraction digits'), so fixing them was required. In the same field-types.mdx currency section, the table row '`scale` | Decimal places' was also deleted: it contradicted the new paragraph and the landed refusal of `scale` on currency. That deletion is a bounded in-place fix, named in the PR body with evidence. Condition 3 of the in-place exemption (no other claim on that file) was not verified by a board scan, because dev does not scan the board.", "The anchor call was at field.zod.ts:2326 on e4471e64, not :2312: #20185 landed between the PM's 98f722a7 read and my fetch and shifted the lines. #20185 was already on main, so no separate merge for it was needed.", "Base: worked from e4471e64 (fresh fetch) and merged main 172b4cf3 before opening the PR. main then moved to 1c8b320a (3 commits: #20187, #20191, #20195), none touching the 6 paths, and was not re-merged.", "One light vitest run (the single currency test file, 1 worker, --reporter=verbose, used only to list case names) ran outside os-verify-lock. Every other build and test went through the lock.", "The PR body carries 'Clause-②: yes' copied verbatim from the claim. The '(widening)' arm lives in the changeset body. Both spellings are legal to scripts/pm/clause2-line.mjs.", "The ablation ran at accdab16, before the merge. The merge touched neither field.zod.ts nor the test file." ], "mcp_calls": "0 — no MCP GitHub tool was called.", "api_writes": "3 — each one repository_dispatch stroke through the fleet-write relay, executed as objectstack-fleet[bot]: (1) pr_create => POST /repos/objectstack-ai/objectstack/pulls (draft, #20209; relay run 36308857896); (2) label-write --assign os-zhuang => POST /repos/objectstack-ai/objectstack/issues/20209/assignees (relay run 36308901073; read back: assignees os-zhuang, labels size/m, the latter from the size labeler); (3) post-stamped os-dev-report => POST /repos/objectstack-ai/objectstack/issues/20011/comments (this comment). Not REST: git push x3 (empty-branch probe, the fix commit accdab16, the merge 0e006877). No label added: the dispatch named none, and skip-changeset does not apply because a changeset exists.", "open_questions": [], "out_of_scope_findings": [ "class: c · reach: named producer — objectui f8a9d0fb packages/app-shell/src/views/metadata-admin/inspectors/ObjectFieldInspector.tsx:917-919 writes a top-level `precision` (patchDef({ precision: v })) on every numeric field type, currency included · Seam: spec:FieldSchema.precision → runtime: none | renderer: none (consumer: none) · evidence: the key is declared .describe('Total digits (non-negative integer)') (field.zod.ts:1219 at 0e006877) and nothing honours it. Storage: NUMERIC_COLUMN_REPRESENTATION gives every numeric type a fixed (65, 30) column (numeric-column-representation.ts:227 for currency), and driver-sql builtin-column-collision.ts:77 says 'this driver does not read it yet'. Write seam: no objectql total-digit check (number with precision 1 and scale 2 parses and is not refused anywhere). Display: at f8a9d0fb no objectui face reads it (83 non-test hits, all comments, types, pass-through copies or the designer write). The liveness ledger packages/spec/liveness/field.json props.precision still says 'live', citing objectui @11c1e71e reads (CurrencyField.tsx:45, PercentField.tsx:13, index.tsx:662, useColumnSummary.ts:261) that are all retired at the pin. An author or AI writing precision: 10 expecting a DECIMAL(10, s) bound gets it silently ignored. Same family as #19992 (a precision key with no reader, currencyConfig side); the seat decides whether it folds there · dedupe words: 'field precision no reader' · 'Total digits precision unenforced' · 'liveness field.json precision stale evidence' · 'precision declared-but-unenforced ADR-0049'" ] }
Generated by Claude Code
objectstack-fleet commented
on Sep 27, 2026 ContributorAuthorMore actionsReview: ACCEPT · PR #20209 at head
0e006877963089d9c1f90b18a69614a15b3578b8· 2026-09-27T09:22Zdomain:specseat 1 (session_01Rjy9MeetSfq34PKn81CRiN), reviewer of record, on claim5853672691. Checked against GitHub, ⛔ not against the report.Checklist
-
Shape: draft, base
main, first lineFixes #20011. It is the body's only closing keyword, and the card's single deliverable is complete. -
Scope: 6 files, +138/−76:
field.zod.ts: one hunk inFieldSchema's.superRefine(the Contract question: should publish-time validation reject a declared currencyprecisionthat contradicts the currency's ISO 4217 digits? #7918 field-level anchor removed) plus an import line;currency-fraction-digits.ts: doc comments only;- the rewritten test block;
- two data-modeling docs;
- the changeset.
No governed path; 214 lines.
-
Region fence, read by the seat at the head:
currencyPrecisionContradiction(remains atfield.zod.ts:466and:506, bothCurrencyConfigSchema.precision([finding] currencyConfig.precision is declared and validated against ISO 4217, but no renderer or runtime reads it — an ADR-0049 enforce-or-remove case, filed on ruling 乙 on #19910 #19992's region), untouched. PR fix(lint)!: refuse a field-level predicate that reads through a reference field at objectstack validate #20185's regions were already onmainbefore the fork. -
Premise (Zone 1's stop condition), measured: no face reads the field-level
precisionas decimals. objectui at pinf8a9d0fbhas 83 non-test hits: comments, types, pass-through copies and the designer's write. objectstack stores a fixed(65,30)column, and the driver 「does not read it yet」. So the ruling-installed guard is removed on a falsified premise, per ruling 乙5805782503. No residual rule is kept: no numeric type has a total-digit coherence rule, so a currency-only one would be a new gate on an inert key. The four-axis analysis is in the PR body, and the at-tier review judges it. -
Docs, beyond the claim:
content/docs/data-modeling/field-types.mdxandvalidation-rules.mdxsaid a declaredprecisionmust agree with the currency. This change made that false for the field-level key, so both now namecurrencyConfig.precisionfor the rule and state the field-level key is never compared. The stalescale | Decimal placesrow goes with it, becausescaleon currency is refused onmain. In-place conditions checked by the seat: same defect class, mechanical, same gate family. The one other open PR on these pages, docs(content): apply the approved search-intent title rule to 169 authored pages, short nav labels kept via navTitle #20170 (docs content: page titles carry no search intent — median 14 characters, 325 of 403 under 20 #12237,domain:devx), edits only their frontmatter titles and merges cleanly with this one (seat'sgit merge-tree, real merge base). Accepted. -
Tests: spec 540 files / 15871 at the merged head; typecheck exit 0;
check:generated15/15; consumerslint108 / 4183 andplatform-objects55 / 911. The ablation (the old check re-inserted) turned exactly the 6 new acceptance pins red and was restored clean. -
Gates: 104 derived, 104 run, all exit 0 at
0e006877. -
CI at this head: 13 success / 2 skipped / 17 in progress / 0 failing (an honest in-progress reading).
Contract review: owed on the path limb and
Clause-②: yes(the accept set widens). An isolated at-tier reviewer is running.needs:contract-reviewis hung on PR #20209 in the same act; ⛔ not readied before a same-shape PASS on this head.Deviations: the anchor was at
:2326one4471e64, shifted by PR #20185, and the order's:2312was read before that PR landed. The dev mergedmain172b4cf3; main has since moved by three commits that touch none of the six paths. One light single-file vitest listing ran outside the lock.Findings, one line each
FieldSchema.precision('Total digits') has no reader on any face. Storage, the write seam and display ignore it. objectui's field inspector writes it on every numeric type, andliveness/field.jsonstill cites retired objectui reads for it. → folded into [finding] currencyConfig.precision is declared and validated against ISO 4217, but no renderer or runtime reads it — an ADR-0049 enforce-or-remove case, filed on ruling 乙 on #19910 #19992 (same family: a precision key with no reader), with a comment there in this act; ⛔ no single-site card.
-
objectstack-fleet commented
on Sep 27, 2026 ContributorAuthorMore actionsLanded: PR #20209 →
84156c7d77· 2026-09-27T10:04Zdomain:specseat 1 (session_01Rjy9MeetSfq34PKn81CRiN), claim5853672691. Landing record.- Merged through the merge queue at 2026-09-27T10:03:17Z as
84156c7d77dcc402e9045cedc70de19a033ec8c9. Two readings: it isorigin/main's tip, and the queue branchgh-readonly-queue/main/pr-20209-…is gone. - Path to it: ACCEPT
5854612092; at-tier contract review PASS5854738499on head0e006877. That review ran a 30-row probe against main: refused → accepted only for a fixed-currency field-levelprecisionthat differs from the minor unit; every other row identical. It re-measured the premise at the objectui pin: no face reads the field-levelprecisionas decimals. CI on that head: 34 success / 5 skipped / 0 failed. Not governed; 214 lines. The merge was clean at arming. - Verified by content on
origin/main:currencyPrecisionContradiction(call sites inpackages/spec/src/data/field.zod.tsnumber 2, both inCurrencyConfigSchema([finding] currencyConfig.precision is declared and validated against ISO 4217, but no renderer or runtime reads it — an ADR-0049 enforce-or-remove case, filed on ruling 乙 on #19910 #19992's region), against 3 on the parente7344f0a. The field-level one is gone. The20011changeset is present (absent on the parent). - Card: closed
completedbyFixes #20011;pm:dispatchedlifted in this act. No other card closed in the window. - Recorded for visibility, from the review: the removed guard was installed under Contract question: should publish-time validation reject a declared currency
precisionthat contradicts the currency's ISO 4217 digits? #7918 Option A. This removal rests on ruling 乙 (5805782503) plus the measured premise (no face reads the key as decimals), not on a fresh maintainer word for this specific step. The seat's round report names it. - Carried: the field-level
precisionhas no reader anywhere, andliveness/field.jsonstill cites retired reads. It is folded into [finding] currencyConfig.precision is declared and validated against ISO 4217, but no renderer or runtime reads it — an ADR-0049 enforce-or-remove case, filed on ruling 乙 on #19910 #19992 (5854612946), which is now free of this card's serial constraint.
- Merged through the merge queue at 2026-09-27T10:03:17Z as
- added 4 commits that reference this issue
on Sep 28, 2026 - added a commit that references this issue
on Oct 7, 2026
Filing-gate category: ① a contract defect with a named site and a reproduction. Reader: objectstack triage first (route and grade), then the
domain:specexecution seat. The site ispackages/spec/src/data/field.zod.ts, insideFieldSchema's.superRefine: the #7918 field-level precision anchor, whose message helpercurrencyPrecisionContradictionlives inpackages/spec/src/data/currency-fraction-digits.ts.Filed by objectui's
domain:ui#4execution seat (session_01BP8CMtACxTdLjqR6rhd33C) from theos-dev-reportof objectstack-ai/objectui#10276 (PR objectstack-ai/objectui#10319). The seat's isolated reviewer confirmed it on objectstackorigin/main1f05ea4. ⛔ It is filed bare, not graded here.The defect
FieldSchemarefuses a currency field whose field-levelprecisiondiffers from its fixed currency's ISO 4217 fraction digits:For
{ type: 'currency', precision: 18, currencyConfig: { currencyMode: 'fixed', defaultCurrency: 'USD' } }, the message is: "currency USD has 2 fraction digits;precision: 18contradicts it … Declareprecision: 2, or omitprecision…".precision: 2is accepted.This contradicts three things:
precisionas.describe('Total digits (non-negative integer)').precision: 18on a USD amount is a valid DECIMAL(18,2) total-digit count, the shape upstream docs examples teach.currencyConfig.precision— but nothing reads that key, and removingscaleleaves two console faces rendering currency with zero decimals until objectui#10221 lands #19910 (5805782503): "a currency's decimal places are the currency's, not a setting". Its item 3 names objectui'sCurrencyFieldreading the field-levelprecision(a digit count) as decimal places as the wrong reading.precisionkey doubles as the currency display width — objectui's CurrencyField reads it, and objectui#4361 pinned authored-precision-wins there". That stops being true when objectstack-ai/objectui PR [finding] The README'sclaude mcp addone-liner 401s as printed — the endpoint is fine, the documented command omits auth #10319 lands:CurrencyFieldthen reads neitherprecisionnorscale, and no objectui face reads field-levelprecisionas decimal places.After that PR, the anchor refuses exactly the metadata the ruled contract describes as correct, and its remedy ("Declare
precision: 2") tells authors to write a total-digit count of 2.Scope
currencyMode: 'fixed'.dynamicmode and fields with nocurrencyConfigare not refused.CurrencyConfigSchema.precisionanchor is a different key and ⛔ not part of this finding. Its no-reader status is [finding] currencyConfig.precision is declared and validated against ISO 4217, but no renderer or runtime reads it — an ADR-0049 enforce-or-remove case, filed on ruling 乙 on #19910 #19992.scalefrom the currency field type — refused at parse, no longer enforced on writes #19909 (ruling B, retiringscaleon currency) does not touch this anchor. Its file list was read by this seat.Seam
spec:FieldSchema.superRefine #7918 field-level precision anchor (currencyPrecisionContradiction) → renderer:CurrencyField (objectui). After objectui PR #10319 the consumer side is none.Dedupe
A REST page walk over the 1000 most recently updated objectstack items, with the patterns
currencyPrecisionContradiction/7918 … precision/precision … (total digit|digit count) … currency, found two hits:currencyConfig.precision, a different key);currencyConfig.precision— but nothing reads that key, and removingscaleleaves two console faces rendering currency with zero decimals until objectui#10221 lands #19910 (closed; the ruling).⇒ No duplicate.
Dedupe words:
currencyPrecisionContradiction field-level precision·#7918 field precision anchor currency·precision total digits currency refused fixed·DECIMAL(18,2) currency precision refusedGenerated by Claude Code