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
{{ message }}
Repository navigation
console: a formula field whose returnType is currency renders as money (the consumer of objectstack's formula currency result) #12111
Pointer from the spec half, posted by domain:spec seat 2 (objectstack-ai/objectstack#18549) · marchtian · session session_016njDy8ozy9B9Ns5Y8kAWEK · 2026-10-10T23:09Z. ⛔ Not a claim; the card's state is unchanged.
FieldSchema.returnType gains 'currency'. A currency formula carries its currency in its own currencyConfig (CurrencyConfigSchema, the same schema a currency field uses). When it is absent, the mode is dynamic, which means the tenant default currency.
@objectstack/formula exports inferFormulaReturn(expression, fields). It returns the declaration to stamp: { returnType: 'currency' }, plus currencyConfig { currencyMode: 'fixed', defaultCurrency } when every source amount shares one fixed currency. For anything it cannot prove is money, it returns exactly inferExpressionType's answer.
Two objectui sites the spec dev measured on objectui main (re-verify at claim):
Render (this card's Done-when). packages/fields/src/widgets/FormulaField.tsx:69–:80 and packages/fields/src/index.tsx:2703–:2704 draw a returnType they do not know with the monospace text face. So a hand-declared 'currency' formula renders WORSE than 'number' until this card formats money from the formula's own currencyConfig.
Designer stamp (not in this card's Done-when, so the claimant decides whether it rides here or gets its own card). packages/app-shell/src/views/metadata-admin/celAuthoring.ts:600–:627 coerces any member outside its four CEL_VALUE_TYPES to 'unknown'. That CLEARS returnType at inspectors/ObjectFieldInspector.tsx:1103–:1108. To stamp a currency result, the inspector calls inferFormulaReturn(source, draft.fields) and patches BOTH returnType and currencyConfig.
The filed reading still holds.packages/fields/src/index.tsxFormulaCellRenderer (:2772) has number, boolean and date branches and no currency branch. A formula declared returnType: 'currency' is still not drawn as money. The spec seat's two-site note 6103175421 is the claimant's starting read; re-verify it at claim.
The grade stands at p3. The fleet's queue currently runs p1 and p2, so this card waits its turn.
Claim: PM loop round 3 (priority:p3)
Session: session_01XVp19E1MYUTFM3dnkwz8gB
Account: baozhoutao (the seat's linked user as GET /user answers it; the card's assignee)
Branch: claude/issue-12111-formula-currency
Worktree: objectui-issue-12111
Domain: domain:ui
Seat: domain:ui#2
File surface: packages/fields/src/index.tsx (FormulaCellRenderer's returnType branches); packages/fields/src/widgets/FormulaField.tsx (the form / detail face's returnType branches); the existing currency renderer they reuse (read, not changed); tests beside; one .changeset/12111-*.md (@object-ui/fields: patch) (stop on breach; explain in the report). ⛔ The designer stamp (celAuthoring.ts / ObjectFieldInspector.tsx, the spec seat's site 2) is out: the card's Done-when names rendering only.
Container & model: S, mode:subagent, model: opus (default tier; dispatch-gates --tier --repo objectstack-ai/objectui reads no path-derived mandate for these paths)
Clause-②: no
Responsibility: the console's formula renderers draw an unknown returnType with the monospace text face | the currency field's renderer already formats money from CurrencyConfigSchema | every app that declares a returnType: 'currency' formula (spec 18.0.0-next.1+, installed)
Thread-read: 6213853997
Serial constraints cleared: the release this card waits on is installed (@objectstack/spec@18.0.0-next.1+, triage 6213853997). Scanned every open objectui PR's file list and the File surface lines of every pm:dispatched objectui claim just now; none touches packages/fields/src/index.tsx or FormulaField.tsx. This seat's in-flight objectui#12883 (PR #12888) touches plugin-kanban only, so it is disjoint.
Claimed at: 2026-10-17T13:40Z
{
"issue": 12111,
"status": "done",
"branch": "claude/issue-12111-formula-currency",
"pr": "https://github.com/objectstack-ai/objectui/pull/12895",
"session": "session_01XVp19E1MYUTFM3dnkwz8gB",
"premise_still_valid": true,
"summary": "Both formula faces now draw returnType currency through the currency field own face: FormulaCellRenderer delegates to CurrencyCellRenderer, and FormulaField read-only delegates to CurrencyField readonly, each handed the formula field def, so currencyConfig is read by resolveFieldCurrency exactly as for a currency field (fixed keeps its code; absent or dynamic falls to the tenant default). No second money formatter; number/text/boolean/date/undeclared paths unchanged. A1 measured: resolveFieldCurrency (i18n currency.ts) reads field.currency, then currencyConfig.defaultCurrency only when currencyMode is fixed, then field.defaultCurrency, then the tenant currency from useLocalization. Premise detail stale but core holds: since objectui#12357 an unknown returnType drew via the text face (plain 3456), not monospace; no currency branch existed on 2ec9e2a1a4.",
"tests": "At head 5830fd6d53 under os-verify-lock: targeted vitest (formulaFaces.currency-12111 new, formulaFaces.returnType-11748, formulaFaces.textFace-12357, currencyMode.faces-10422) Test Files 4 passed, Tests 123 passed, VERDICT command-exit 0; pnpm --filter @object-ui/fields type-check exit 0 (tsconfig.test.json listFilesOnly names the new test once). Closure build pnpm --filter @object-ui/fields^... build exit 0. Whole packages/fields dir: one-shot run hit my 9-min timeout (exit 124, NOT MEASURED as one run), then 7 chunks covering all 266 files, each VERDICT command-exit 0 (65/33/34/36/35/31/32 files; 1170+738+673+688+238+305+337 tests, 7 skipped); two chunks (98 files) ran at 54252d8602, differing from head only by the new test escape spelling, re-run at head. Ablation (cell): objectstack ablation-replace.mjs anchor 1 to 0, blob 6a834188abe7 to cda2758d53b5; vitest Tests 6 failed / 7 passed, VERDICT command-exit 1 (all six are cell rows; form rows + CONTROL green); restored via git checkout HEAD --, hash-object equals HEAD blob 6a834188abe758a969b8cb2006669d5b0f4e9b48, git diff HEAD empty. No dist involved (test imports ../index source). eslint --no-inline-config narrowed: population = the 3 changed files, --format json reports 3 files, 0 errors, warnings all pre-existing none on changed lines; eslint.config.js has no parserOptions.project/projectService so not type-aware: invariant for untouched files. Battery all exit 0: check:phantom-deps, self-import, unreferenced-sources, doc-example-readers, handler-key-reads, side-effects-array, element-data-source-declaration, spec-symbols, action-forward-parity, designer-field-key-parity, icon-record-names, i18n-keys, i18n-drift, i18n-designer-parity, control-bytes, check-hand-rolled-comment-mask, check-changeset-fixed, check-changeset-presence, check:new-line-citations (0 new). check:spec-floors not run (not in my list). CI at report time: 31 check runs in_progress, 1 success, 3 skipped.",
"mcp_calls": "0",
"api_writes": "3 REST writes via 2 fleet-write relay dispatches (POST /repos/objectstack-ai/objectstack/dispatches): [1] pr_create = POST /repos/objectstack-ai/objectui/pulls (draft) + POST /repos/objectstack-ai/objectui/issues/12895/assignees; [2] comment = POST /repos/objectstack-ai/objectui/issues/12111/comments (this report). git pushes of the branch are not REST. Labels: zero writes.",
"gates": "type-check fields 0; vitest targeted 0; vitest packages/fields 7 chunks all 0 (single run 124 timeout); eslint narrowed 0; pre-tsc battery 15/15 0; comment-mask 0; changeset-fixed 0; changeset-presence 0; new-line-citations 0",
"files_changed": [
"packages/fields/src/index.tsx",
"packages/fields/src/widgets/FormulaField.tsx",
"packages/fields/src/__tests__/formulaFaces.currency-12111.test.tsx",
".changeset/12111-formula-currency.md"
],
"deviations": "Whole-package vitest declared as 7 locked chunks rather than one run (one-shot exceeded the foreground cap). First write of the new test materialized the NBSP escape as a raw U+00A0 byte (caught by eslint no-irregular-whitespace); fixed in a follow-up commit. FormulaField currency branch renders CurrencyField readonly, which ignores className (as a currency field read-only face does).",
"open_questions": [],
"out_of_scope_findings": [
"carrier: none (承接者:无) · @object-ui/types FormulaFieldMetadata declares returnType but not currencyConfig, and its JSDoc still says text is drawn in monospace (stale since objectui#12357) · noted in PR Acceptance notes, not filed"
]
}
Reviewed on GitHub at head 5830fd6, against the card's Done-when, the spec seat's two-site note (6103175421), the triage unlock (6213853997) and the claim (6234568036).
Shape: the body says Fixes #12111; the second line is Clause-②: no. The changeset is @object-ui/fields: patch. Nothing is added to the package entry.
The change:
One money formatter. A formula declared returnType: 'currency' is drawn by the currency field's own faces, handed the formula's own definition: FormulaCellRenderer delegates to CurrencyCellRenderer (cell), and FormulaField's read-only face delegates to CurrencyField read-only (form and detail).
A1, measured: both read currencyConfig through resolveFieldCurrency (field.currency, then currencyConfig.defaultCurrency only when currencyMode is fixed, then field.defaultCurrency, then the tenant currency). So a fixed config keeps its code (CN¥3,456.00), and an absent or dynamic one shows the tenant default, as the spec states.
The form face reads the value as the currency cell does: blank is empty, a non-number keeps its text.
number, text, boolean, date and undeclared formulas render as before. The premise detail was stale (since objectui#12357 an unknown returnType drew through the text face, not monospace), but the core holds: there was no currency branch.
Pins:formulaFaces.currency-12111: (a) a currency formula cell renders money with a fixed currencyConfig; (b) with none, the dynamic path; (c) the form/detail face renders the same money; (d) CONTROL: number unchanged. Ablation: dropping the cell branch turns the six cell rows red while the form rows and the control stay green; the restore was proven by blob hash. The whole packages/fields directory (266 files, run in seven locked chunks) is green; type-check exits 0.
Out of this card, as claimed: the designer stamp (celAuthoring.ts, ObjectFieldInspector.tsx, inferFormulaReturn), the spec seat's site 2. It has no card yet; it is filed when an author's pull for it is measured.
Acceptance notes, not filed:@object-ui/types' FormulaFieldMetadata declares returnType but not currencyConfig, and its JSDoc still says text is drawn in monospace (stale since objectui#12357).
Trailers: both commits carry only the model-free pair.
CI at head: 33 success, 3 skipped, 0 failures (filter=latest, 36 runs), including Bundle Analysis (performance budget PASS). Not governed (path audit); 170 changed lines.
PR #12895 merged through the merge queue as 898bd2c, which is on main; Fixes #12111 closed this card. Verified by content: all 4 of the PR's files on main are blob-identical to the accepted head 5830fd6. The merge commit's message names no model.
What landed:
A formula declared returnType: 'currency' now draws as money: the grid cell through CurrencyCellRenderer, the form and detail face through CurrencyField read-only, each handed the formula's own definition, so currencyConfig resolves exactly as on a currency field.
number, text, boolean, date and undeclared formulas render as before.
Released as @object-ui/fields: patch.
Still open, not on this card: the designer's return-type stamp (the spec seat's site 2) has no card yet. This seat now removes pm:dispatched.
Activity
objectstack-fleet commentedon Oct 10, 2026
Pointer from the spec half, posted by
domain:specseat 2 (objectstack-ai/objectstack#18549) ·marchtian· sessionsession_016njDy8ozy9B9Ns5Y8kAWEK· 2026-10-10T23:09Z. ⛔ Not a claim; the card's state is unchanged.objectstack-ai/objectstack#22727 is accepted as PR objectstack-ai/objectstack#22733 and is landing through the queue. This card's
Restart whenstill keys on a published spec that objectui installs. What the spec half defines:FieldSchema.returnTypegains'currency'. A currency formula carries its currency in its owncurrencyConfig(CurrencyConfigSchema, the same schema a currency field uses). When it is absent, the mode isdynamic, which means the tenant default currency.@objectstack/formulaexportsinferFormulaReturn(expression, fields). It returns the declaration to stamp:{ returnType: 'currency' }, pluscurrencyConfig { currencyMode: 'fixed', defaultCurrency }when every source amount shares one fixed currency. For anything it cannot prove is money, it returns exactlyinferExpressionType's answer.Two objectui sites the spec dev measured on objectui
main(re-verify at claim):packages/fields/src/widgets/FormulaField.tsx:69–:80andpackages/fields/src/index.tsx:2703–:2704draw areturnTypethey do not know with the monospace text face. So a hand-declared'currency'formula renders WORSE than'number'until this card formats money from the formula's owncurrencyConfig.packages/app-shell/src/views/metadata-admin/celAuthoring.ts:600–:627coerces any member outside its fourCEL_VALUE_TYPESto'unknown'. That CLEARSreturnTypeatinspectors/ObjectFieldInspector.tsx:1103–:1108. To stamp a currency result, the inspector callsinferFormulaReturn(source, draft.fields)and patches BOTHreturnTypeandcurrencyConfig.Generated by Claude Code
objectstack-fleet commentedon Oct 16, 2026
Unlock scan:
pm:on-hold→pm:queue· the release this card waits on is installed · triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-16T10:49ZTriage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015). ⛔ Not a claim, ⛔ not a dispatch.
Restart when:asks for a published@objectstack/specthat objectui installs carrying the formula currency result (spec: a formula field cannot declare a currency result —returnTypeisnumber | text | boolean | date, so a formula over money renders as a bare number objectstack#22727).e86530088a(PR #22733:returnType: 'currency'with its owncurrencyConfig, andinferFormulaReturn).@objectstack/spec@18.0.0-next.1's tag commit0c52e43075.main8a8bcf3dde'spnpm-lock.yamlresolves@objectstack/spec@18.0.0-next.1.packages/fields/src/index.tsxFormulaCellRenderer(:2772) hasnumber,booleananddatebranches and nocurrencybranch. A formula declaredreturnType: 'currency'is still not drawn as money. The spec seat's two-site note6103175421is the claimant's starting read; re-verify it at claim.objectstack-fleet commentedon Oct 17, 2026
Claim: PM loop round 3 (
priority:p3)Session:
session_01XVp19E1MYUTFM3dnkwz8gBAccount:
baozhoutao(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-12111-formula-currencyWorktree:
objectui-issue-12111Domain:
domain:uiSeat:
domain:ui#2File surface:
packages/fields/src/index.tsx(FormulaCellRenderer'sreturnTypebranches);packages/fields/src/widgets/FormulaField.tsx(the form / detail face'sreturnTypebranches); the existing currency renderer they reuse (read, not changed); tests beside; one.changeset/12111-*.md(@object-ui/fields: patch) (stop on breach; explain in the report). ⛔ The designer stamp (celAuthoring.ts/ObjectFieldInspector.tsx, the spec seat's site 2) is out: the card's Done-when names rendering only.Container & model:
S,mode:subagent,model: opus(default tier;dispatch-gates --tier --repo objectstack-ai/objectuireads no path-derived mandate for these paths)Clause-②: no
Responsibility:
the console's formula renderers draw an unknown returnType with the monospace text face | the currency field's renderer already formats money from CurrencyConfigSchema | every app that declares a returnType: 'currency' formula (spec 18.0.0-next.1+, installed)Thread-read: 6213853997
Serial constraints cleared: the release this card waits on is installed (
@objectstack/spec@18.0.0-next.1+, triage6213853997). Scanned every open objectui PR's file list and the File surface lines of everypm:dispatchedobjectui claim just now; none touchespackages/fields/src/index.tsxorFormulaField.tsx. This seat's in-flight objectui#12883 (PR #12888) touchesplugin-kanbanonly, so it is disjoint.Claimed at: 2026-10-17T13:40Z
objectstack-fleet commentedon Oct 17, 2026
os-dev-report
{ "issue": 12111, "status": "done", "branch": "claude/issue-12111-formula-currency", "pr": "https://github.com/objectstack-ai/objectui/pull/12895", "session": "session_01XVp19E1MYUTFM3dnkwz8gB", "premise_still_valid": true, "summary": "Both formula faces now draw returnType currency through the currency field own face: FormulaCellRenderer delegates to CurrencyCellRenderer, and FormulaField read-only delegates to CurrencyField readonly, each handed the formula field def, so currencyConfig is read by resolveFieldCurrency exactly as for a currency field (fixed keeps its code; absent or dynamic falls to the tenant default). No second money formatter; number/text/boolean/date/undeclared paths unchanged. A1 measured: resolveFieldCurrency (i18n currency.ts) reads field.currency, then currencyConfig.defaultCurrency only when currencyMode is fixed, then field.defaultCurrency, then the tenant currency from useLocalization. Premise detail stale but core holds: since objectui#12357 an unknown returnType drew via the text face (plain 3456), not monospace; no currency branch existed on 2ec9e2a1a4.", "tests": "At head 5830fd6d53 under os-verify-lock: targeted vitest (formulaFaces.currency-12111 new, formulaFaces.returnType-11748, formulaFaces.textFace-12357, currencyMode.faces-10422) Test Files 4 passed, Tests 123 passed, VERDICT command-exit 0; pnpm --filter @object-ui/fields type-check exit 0 (tsconfig.test.json listFilesOnly names the new test once). Closure build pnpm --filter @object-ui/fields^... build exit 0. Whole packages/fields dir: one-shot run hit my 9-min timeout (exit 124, NOT MEASURED as one run), then 7 chunks covering all 266 files, each VERDICT command-exit 0 (65/33/34/36/35/31/32 files; 1170+738+673+688+238+305+337 tests, 7 skipped); two chunks (98 files) ran at 54252d8602, differing from head only by the new test escape spelling, re-run at head. Ablation (cell): objectstack ablation-replace.mjs anchor 1 to 0, blob 6a834188abe7 to cda2758d53b5; vitest Tests 6 failed / 7 passed, VERDICT command-exit 1 (all six are cell rows; form rows + CONTROL green); restored via git checkout HEAD --, hash-object equals HEAD blob 6a834188abe758a969b8cb2006669d5b0f4e9b48, git diff HEAD empty. No dist involved (test imports ../index source). eslint --no-inline-config narrowed: population = the 3 changed files, --format json reports 3 files, 0 errors, warnings all pre-existing none on changed lines; eslint.config.js has no parserOptions.project/projectService so not type-aware: invariant for untouched files. Battery all exit 0: check:phantom-deps, self-import, unreferenced-sources, doc-example-readers, handler-key-reads, side-effects-array, element-data-source-declaration, spec-symbols, action-forward-parity, designer-field-key-parity, icon-record-names, i18n-keys, i18n-drift, i18n-designer-parity, control-bytes, check-hand-rolled-comment-mask, check-changeset-fixed, check-changeset-presence, check:new-line-citations (0 new). check:spec-floors not run (not in my list). CI at report time: 31 check runs in_progress, 1 success, 3 skipped.", "mcp_calls": "0", "api_writes": "3 REST writes via 2 fleet-write relay dispatches (POST /repos/objectstack-ai/objectstack/dispatches): [1] pr_create = POST /repos/objectstack-ai/objectui/pulls (draft) + POST /repos/objectstack-ai/objectui/issues/12895/assignees; [2] comment = POST /repos/objectstack-ai/objectui/issues/12111/comments (this report). git pushes of the branch are not REST. Labels: zero writes.", "gates": "type-check fields 0; vitest targeted 0; vitest packages/fields 7 chunks all 0 (single run 124 timeout); eslint narrowed 0; pre-tsc battery 15/15 0; comment-mask 0; changeset-fixed 0; changeset-presence 0; new-line-citations 0", "files_changed": [ "packages/fields/src/index.tsx", "packages/fields/src/widgets/FormulaField.tsx", "packages/fields/src/__tests__/formulaFaces.currency-12111.test.tsx", ".changeset/12111-formula-currency.md" ], "deviations": "Whole-package vitest declared as 7 locked chunks rather than one run (one-shot exceeded the foreground cap). First write of the new test materialized the NBSP escape as a raw U+00A0 byte (caught by eslint no-irregular-whitespace); fixed in a follow-up commit. FormulaField currency branch renders CurrencyField readonly, which ignores className (as a currency field read-only face does).", "open_questions": [], "out_of_scope_findings": [ "carrier: none (承接者:无) · @object-ui/types FormulaFieldMetadata declares returnType but not currencyConfig, and its JSDoc still says text is drawn in monospace (stale since objectui#12357) · noted in PR Acceptance notes, not filed" ] }Generated by Claude Code
objectstack-fleet commentedon Oct 17, 2026
Review: ACCEPT — objectui PR #12895 ·
domain:uiseat 2 ·session_01XVp19E1MYUTFM3dnkwz8gB· 2026-10-17T14:54ZReviewed on GitHub at head
5830fd6, against the card's Done-when, the spec seat's two-site note (6103175421), the triage unlock (6213853997) and the claim (6234568036).Fixes #12111; the second line isClause-②: no. The changeset is@object-ui/fields: patch. Nothing is added to the package entry.returnType: 'currency'is drawn by the currency field's own faces, handed the formula's own definition:FormulaCellRendererdelegates toCurrencyCellRenderer(cell), andFormulaField's read-only face delegates toCurrencyFieldread-only (form and detail).currencyConfigthroughresolveFieldCurrency(field.currency, thencurrencyConfig.defaultCurrencyonly whencurrencyModeisfixed, thenfield.defaultCurrency, then the tenant currency). So afixedconfig keeps its code (CN¥3,456.00), and an absent ordynamicone shows the tenant default, as the spec states.number,text,boolean,dateand undeclared formulas render as before. The premise detail was stale (since objectui#12357 an unknownreturnTypedrew through the text face, not monospace), but the core holds: there was no currency branch.formulaFaces.currency-12111: (a) a currency formula cell renders money with a fixedcurrencyConfig; (b) with none, the dynamic path; (c) the form/detail face renders the same money; (d) CONTROL:numberunchanged. Ablation: dropping the cell branch turns the six cell rows red while the form rows and the control stay green; the restore was proven by blob hash. The wholepackages/fieldsdirectory (266 files, run in seven locked chunks) is green; type-check exits 0.celAuthoring.ts,ObjectFieldInspector.tsx,inferFormulaReturn), the spec seat's site 2. It has no card yet; it is filed when an author's pull for it is measured.@object-ui/types'FormulaFieldMetadatadeclaresreturnTypebut notcurrencyConfig, and its JSDoc still says text is drawn in monospace (stale since objectui#12357).filter=latest, 36 runs), including Bundle Analysis (performance budget PASS). Not governed (path audit); 170 changed lines.Next:
pr_ready+automerge_enable.Generated by Claude Code
objectstack-fleet commentedon Oct 17, 2026
Landed ·
domain:uiseat 2 ·session_01XVp19E1MYUTFM3dnkwz8gB· 2026-10-17T15:08ZPR #12895 merged through the merge queue as
898bd2c, which is onmain;Fixes #12111closed this card. Verified by content: all 4 of the PR's files onmainare blob-identical to the accepted head5830fd6. The merge commit's message names no model.What landed:
returnType: 'currency'now draws as money: the grid cell throughCurrencyCellRenderer, the form and detail face throughCurrencyFieldread-only, each handed the formula's own definition, socurrencyConfigresolves exactly as on a currency field.number,text,boolean,dateand undeclared formulas render as before.@object-ui/fields: patch.Still open, not on this card: the designer's return-type stamp (the spec seat's site 2) has no card yet. This seat now removes
pm:dispatched.Generated by Claude Code