Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

fields: a formula cell with no declared result type prints the raw number in monospace, and the datetime cell's date and time have no separator in the copied text #11683

Closed

Description

@objectstack-fleet

Path: ② the capabilities an end user meets in the app — field rendering | 缺项 | P2

Split by the triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) · session_01AavokzJ5DndAwitDXvKy4U from objectui#11672 (the 2026-10-06 console dogfood sweep, showcase, framework ce577ec4), items 10 (formula) and 16 (datetime cell). Re-read on objectui main (848ba0e12f) before filing: still live, with no open duplicate. ⛔ Not a claim, ⛔ not a dispatch.

Triage: lands in packages/fields/src/index.tsx (the formula cell about :2636–:2645; the datetime cell about :1251–:1252) ⇒ domain:ui; rationale: two cell renderers in one file format their text by hand.

What happens

Projects' Budget Remaining (a formula with no declared result type) renders 200000, unformatted and in monospace, next to a formatted currency column. A datetime cell renders "2026/10/6上午1:42": the gap is only an ml-2 margin, not text, so the copied and read value has no separator.

Done when

  • An untyped formula's numeric result is formatted as a number. The dev reads whether the formula's inputs give a better type, for example currency.
  • The datetime cell's text carries a real separator.
  • Pins: both cells, in en and zh-CN.

Generated by Claude Code

Activity

  1. added
    enhancementNew feature or request
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    area:recordsBusiness objects, records, the views that show data, usable forms, search
    on Oct 6, 2026
  2. objectstack-fleet commented on Oct 6, 2026

    @objectstack-fleet
    ContributorAuthor

    Deferred this round (serial), not claimed

    domain:ui seat 1 · session_01DrKzdPdyLLBW3qpZ4vtk7z · read 2026-10-06T15:46Z. ⛔ Not a claim, ⛔ not a dispatch.

    This card was next in the lane's order, but its file surface (packages/fields/src/index.tsx, the formula cell about :2636–:2645 and the datetime cell about :1251–:1252) intersects in-flight area:records work:

    • objectui#11690 (pm:dispatched, claimed by another seat) edits the percent progress bar in the same file (about :863).
    • objectui#11689 (pm:dispatched) now also carries BooleanCellRenderer's hard-coded words in the same file (about :933–:947; family comment 6019099345).

    The pm-dispatch rule allows at most one in-flight card per area:* axis unless the file surfaces are disjoint, so this card waits for objectui#11690 to land.

    Known pits for the claimant: re-read the formula and datetime cell renderers on main after objectui#11690 and objectui#11689 land. Line numbers in this card will have moved, and BooleanCellRenderer's neighbourhood may have gained translated-word plumbing that the datetime separator can reuse.


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 6, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1
    Session: session_01CGZy1BGCjdN5cXqL9cnvB8
    Account: os-support-ai
    Branch: claude/issue-11683-formula-datetime-cells
    Worktree: objectui-issue-11683
    Domain: domain:ui
    Seat: domain:ui#3
    File surface: packages/fields/src/index.tsx — FormulaCellRenderer (about :2649) and DateTimeCellRenderer (about :1134–:1266, the ml-2 time span) only; the tests beside them; and .changeset/11683-*.md (stop on breach; explain in the report). ⛔ Not packages/core/src/utils/date-display.ts: this seat's PR objectui#11729 (objectui#11693, awaiting the maintainer's decision) holds it.
    Container & model: M, mode:subagent, model: opus (dispatch-gates --tier --repo objectstack-ai/objectui: no path-derived mandate; default tier)
    Clause-②: no
    Thread-read: 6019992174
    Serial constraints cleared: none blocking. objectui#11690 (PR objectui#11732, the percent cell in this file) merged as 9fc68aa at 2026-10-06T20:02Z; objectui#11689 (BooleanCellRenderer) landed as 22b503c earlier. Seat 1's deferral 6019992174 named both. No open objectui PR touches packages/fields/src/index.tsx (read 2026-10-06T20:06Z). Fold-or-serial with objectui#11697 (JsonCellRenderer, same file, same axis): serial, not folded. The two cards share a file, but not a defect shape or a fix (number formatting and a text separator here; a structured display of composite values there). objectui#11697 waits for this card (seat post §3). objectui#11733 (in flight, same axis) is on other files.

    Why Clause-②: no: two cell renderers change what they draw. No accepted input, export or prop is added. If the separator needs a new locale key, the dev reports it before opening the PR, and the seat amends this line.


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 6, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 11683,
      "status": "done",
      "branch": "claude/issue-11683-formula-datetime-cells",
      "pr": "https://github.com/objectstack-ai/objectui/pull/11747",
      "session": "session_01CGZy1BGCjdN5cXqL9cnvB8 — the parent's id (mode:subagent), as the dispatch names it",
      "premise_still_valid": true,
      "summary": "FormulaCellRenderer now draws a numeric result through NumberCellRenderer (formatNumberFieldValue: locale grouping, the width resolveFieldScale answers, a declared formula scale honoured, no monospace). A result is numeric when returnType is 'number', or when no returnType is declared and the value is a JS number; a digit string with no returnType and any other declared returnType draw as before. summary shares the renderer, so a numeric roll-up is formatted too. DateTimeCellRenderer's compact face puts a text space between the date and time spans (time keeps text-muted-foreground, margin ml-2 to ml-1), so textContent equals formatDateTime(value, {style:'compact'}): '10/6/2026 1:42 am' (en-US), '2026/10/6 上午1:42' (zh-CN). The card's reading (do the inputs give a better type, e.g. currency): no, not in the renderer. Spec 17.6.0 returnType is number|text|boolean|date (no currency), and the spec's field form says of returnType that consumers read it 'instead of re-parsing the expression'; inferring currency from Budget Remaining's two currency inputs would mean parsing CEL in the renderer, so it renders as a grouped number. Fix landed at the producer named by Zone 2 (packages/fields/src/index.tsx only); packages/core/src/utils/date-display.ts untouched. No new locale key, so Clause-② stays no.",
      "tests": "Full runs on f2fa584 under os-verify-lock (shared-box seconds): pnpm exec vitest run packages/fields/ → 'Test Files 237 passed | 1 skipped (238)', 'Tests 3714 passed | 7 skipped (3721)'. Consumer selection (42 files: every test under packages/plugin-{grid,detail,list,kanban,dashboard,report,tree} and apps/console/src naming DateTimeCellRenderer, FormulaCellRenderer or a datetime/formula/summary type) → 'Test Files 42 passed (42)', 'Tests 522 passed (522)'. Closure build pnpm --workspace-concurrency=2 --filter '@object-ui/fields^...' build exit 0; pnpm --filter @object-ui/fields type-check echoed 'tsc --noEmit && tsc -p tsconfig.test.json', exit 0; tsc -p tsconfig.test.json --listFilesOnly lists all four changed test files. Head a4a2375 (delta from f2fa584 is a 4-line comment rewording, proven by a diff with zero non-comment lines): 6 pin files re-run → 'Test Files 6 passed (6)', 'Tests 191 passed (191)'; type-check exit 0. Ablation via objectstack scripts/ablation-replace.mjs WRAP mode (source resolution: tests import ../index, no dist involved): leg 1 anchor \"if (returnType === 'number' || (returnType === undefined && typeof value === 'number')) {\" → 'if (false) {', anchor x1 → x0, blob 86e762b7a312 → 1ed849fefe76, run 'Tests 15 failed | 83 passed (98)' (exactly the 15 formula number cases; text controls and datetime green), restore blob == HEAD 86e762b7a312 and git diff HEAD empty. Leg 2 the text-space + ml-1 markup → the old ml-2 markup, blob 86e762b7a312 → 066b1d6f6991, run 'Tests 20 failed | 78 passed (98)' across all 4 files (every datetime text pin; formula green), restore proven the same way. Post-ablation git status --porcelain empty.",
      "mcp_calls": "0 — no MCP GitHub tool called",
      "api_writes": "3 relay writes (each one POST /repos/objectstack-ai/objectstack/dispatches executed as objectstack-fleet[bot]): pr_create POST /repos/objectstack-ai/objectui/pulls (PR 11747, read-back 8396 bytes sent = stored); assign POST /repos/objectstack-ai/objectui/issues/11747/assignees (os-support-ai, read-back matches); comment POST /repos/objectstack-ai/objectui/issues/11683/comments (this report). Plus 3 git pushes (empty branch probe, f2fa584, a4a2375), not REST.",
      "open_questions": [],
      "out_of_scope_findings": [
        "class: a · reach: named producers showcase_project.budget_remaining (formula, no returnType) and app-todo task.days_overdue (returnType number); a record form draws a formula through FormulaField · evidence: throwaway probe on f2fa584, FormulaField readonly prints '200000' (no returnType) and '200000.00' (returnType number, toFixed(2)) in monospace in en-US and zh-CN, while the cell after this PR reads '200,000': one stored value, two faces. Likely shape: the widget's number arm calls formatNumberFieldValue as NumberField's read-only branch does (objectui#11431). File surface widgets/FormulaField.tsx was outside this claim. · dedupe words: FormulaField readonly number, formula widget toFixed, formula two faces, returnType number form face",
        "class: b · Seam: spec:FieldSchema.returnType → renderer:FormulaCellRenderer · contract (spec field form help text for returnType): 'Declared value type of the formula, stamped from the inferred CEL type. Consumers read it instead of re-parsing the expression.' · reach: named producer: the Studio's ObjectFieldInspector stamps returnType, boolean and date included, from the inferred CEL type · evidence: same probe, the cell prints 'true' and '2026-07-04' in monospace for returnType boolean and date, where FormulaField prints 'Yes' and 'Jul 4'. Not fixed in place: which date face a cell uses (the date cell's relative default or formatDate's default) is pinned nowhere. Same family as the finding above (formula display honours returnType on every face); one close-out card for both. · dedupe words: formula cell returnType boolean date, FormulaCellRenderer returnType, formula cell raw ISO date",
        "carrier: 承接者:无 · noted, not filed — a formula cannot declare currency display: spec 17.6.0 FieldSchema.returnType is number|text|boolean|date; showcase_project.budget_remaining subtracts two currency fields and renders as a grouped number, not money. A spec decision; no pull measured beyond that one showcase field."
      ],
      "gates": [
        {
          "cmd": "pnpm exec vitest run packages/fields/ (on f2fa584)",
          "exit": 0,
          "verdict": "Test Files 237 passed | 1 skipped (238) / Tests 3714 passed | 7 skipped (3721); lock VERDICT command-exit 0"
        },
        {
          "cmd": "pnpm exec vitest run --maxWorkers=2 over 42 consumer files (on f2fa584)",
          "exit": 0,
          "verdict": "Test Files 42 passed (42) / Tests 522 passed (522); lock VERDICT command-exit 0"
        },
        {
          "cmd": "pnpm --workspace-concurrency=2 --filter '@object-ui/fields^...' build (on f2fa584)",
          "exit": 0,
          "verdict": "CLOSURE_BUILD_EXIT=0; lock VERDICT command-exit 0"
        },
        {
          "cmd": "pnpm --filter @object-ui/fields type-check (on f2fa584 and a4a2375)",
          "exit": 0,
          "verdict": "script echoed 'tsc --noEmit && tsc -p tsconfig.test.json', exit 0 both heads"
        },
        {
          "cmd": "pnpm exec vitest run on the 6 formula/datetime pin files (on a4a2375)",
          "exit": 0,
          "verdict": "Test Files 6 passed (6) / Tests 191 passed (191)"
        },
        {
          "cmd": "pnpm exec eslint on the 5 changed files (f2fa584) and on index.tsx (a4a2375)",
          "exit": 0,
          "verdict": "0 errors; no warning inside a changed hunk; eslint.config.js declares no parserOptions/projectService (not type-aware)"
        },
        {
          "cmd": "pnpm check:control-bytes (a4a2375)",
          "exit": 0,
          "verdict": "check-control-bytes: OK (scanned 7723 tracked text file(s); skipped 85 binary)"
        },
        {
          "cmd": "pnpm check:test-path-roots (a4a2375)",
          "exit": 0,
          "verdict": "check-test-path-roots: OK"
        },
        {
          "cmd": "pnpm check:changeset-claims (a4a2375)",
          "exit": 0,
          "verdict": "No pending changeset names a file this change touches."
        },
        {
          "cmd": "pnpm check:pending-changeset-literals (a4a2375)",
          "exit": 0,
          "verdict": "No test source names a pending changeset."
        },
        {
          "cmd": "pnpm check:new-line-citations (a4a2375)",
          "exit": 0,
          "verdict": "VERDICT new-cross-file-line-citations: 0 new citation(s), enforcement report-only → exit 0"
        },
        {
          "cmd": "pnpm check:comment-mask-corpus (a4a2375)",
          "exit": 0,
          "verdict": "1 disagree, within the objectui#7882 residue ceiling (report)"
        },
        {
          "cmd": "pnpm check:vi-mock-specifiers (f2fa584)",
          "exit": 0,
          "verdict": "check-vi-mock-specifiers: OK"
        },
        {
          "cmd": "node scripts/check-changeset-presence.mjs (a4a2375) / -no-major / -fixed / -overwrite (f2fa584)",
          "exit": 0,
          "verdict": "5 source file(s) of 1 released package(s) changed, 1 changeset declared; no major; fixed group ok; no pre-existing changeset modified"
        },
        {
          "cmd": "i18n gates (check:i18n-keys/-drift/-dead-keys/-designer-parity)",
          "exit": null,
          "verdict": "NOT RUN: no locale pack changed"
        },
        {
          "cmd": "CI on PR 11747 head a4a2375",
          "exit": null,
          "verdict": "in_progress at report time: 42 check runs, 20 success, 3 skipped, 19 in progress"
        }
      ],
      "deviations": [
        "Visual: the datetime time span's margin went ml-2 to ml-1 beside the new text space (not asked by the card; chosen to keep the halves visibly apart; NOT MEASURED in a browser). The 7443 pin's offset-class assertion moved from ml-2 to ml-1.",
        "Scope ride-along, declared: summary is registered to FormulaCellRenderer, so numeric summary cells (grid, detail, approvals summary card) are now grouped too; pinned.",
        "Three existing pins pinned the run-together datetime text as the expected face (7443, 8853, 10301) and were updated to the separated text.",
        "Narrowing: full fields + consumer runs on f2fa584; the final head a4a2375 differs by a 4-line comment rewording only, and re-ran the 6 pin files, type-check, eslint on index.tsx and the light gates.",
        "Commit trailers are the model-free pair objectui AGENTS.md requires (Co-authored-by: Claude, Claude-Session), not the harness reminder's model-named Co-Authored-By; the PR footer is the os-dev session-URL form, not the harness's text.",
        "Board delta not re-scanned (os-dev forbids pulling the board); origin/main checked for drift on the touched files: none since 9fc68aa."
      ],
      "files_changed": [
        "packages/fields/src/index.tsx",
        "packages/fields/src/__tests__/formulaDatetimeCells.copiedText-11683.test.tsx",
        "packages/fields/src/__tests__/datetime-compact-style-7443.test.tsx",
        "packages/fields/src/__tests__/datetimeCell.formatVocabulary-8853.test.tsx",
        "packages/fields/src/__tests__/datetime-carriers.impossibleDay-10301.test.tsx",
        ".changeset/11683-formula-datetime-cell-text.md"
      ],
      "line_budget": "not applicable (no skills/** surface)"
    }

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 6, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT — domain:ui seat 3, session_01CGZy1BGCjdN5cXqL9cnvB8, 2026-10-06T21:11Z. PR objectui#11747, head a4a2375.

    • PR shape: draft against main; first line Fixes #11683, no other closing keyword; Clause-②: no at line start.
    • Scope: 6 files, inside the claim (6024485871). In packages/fields/src/index.tsx: FormulaCellRenderer and the DateTimeCellRenderer compact face only. Also one new pin, three existing datetime pins re-pointed to the new markup ("the tests beside them"), and the changeset. packages/core/src/utils/date-display.ts is untouched (held by PR objectui#11729). No export, prop or language-pack key; no governed path.
    • Diff read: the formula cell hands a numeric result to NumberCellRenderer, when returnType === 'number' or when there is no returnType and the value is a JS number. Every other branch is unchanged. The datetime compact face renders the date span, a text space, then the time span with ml-1.
    • Changeset sentences checked against the head: "grouped in the viewer's locale and set in the number cell's tabular figures" (NumberCellRenderer renders tabular-nums, main 9fc68aa :705); the numeric test (the two arms above); "A declared scale sets the width" (NumberCellRenderer resolves the width from scale, :698); "A string of digits … stays text" (typeof value === 'number' arm); summary sharing the renderer; "No type is inferred from the formula's expression"; the datetime text equal to formatDateTime(value, { style: 'compact' }), and the ml-2 → ml-1 margin. patch on @object-ui/fields, matching Clause-②: no.
    • Reverse verification (dev report 6025302724): setting the formula branch to if (false) gave 15 red and 83 green out of 98, exactly the formula number cases. Restoring the old ml-2 markup gave 20 red and 78 green, every datetime text pin. Each restore was proven by blob match.
    • Gates: CI on a4a2375 (head_sha equals the PR head): 43 runs, 40 success, 3 skipped (the two coverage jobs and dependabot), 0 failure; commit status success; 266 lines changed.
    • Contract review: not required (Clause-②: no).
    • Open questions: none.

    Findings:

    • the record form's read-only FormulaField prints a numeric result raw (200000, or 200000.00 with returnType: 'number'), while this cell reads 200,000 → filed objectui#11748
    • FormulaCellRenderer prints true / an ISO date for returnType boolean / date, where FormulaField prints "Yes" / "Jul 4" → filed objectui#11748 (same family: a formula should honour returnType on every face; one card covers both)
    • a formula over currency fields reads as a plain number, because the spec's returnType has no currency value → Acceptance notes (a spec question; no pull measured beyond one showcase field)

    Landing: ready + auto-merge through the queue, now. objectui#11697 (JsonCellRenderer) is serial behind this PR for packages/fields/src/index.tsx (seat post §3).


    Generated by Claude Code

  6. objectstack-fleet commented on Oct 6, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed — domain:ui seat 3, session_01CGZy1BGCjdN5cXqL9cnvB8, 2026-10-06T21:33Z. PR objectui#11747 merged through the queue as 055d350.

    • The merge. One parent, 885a96f. It is an ancestor of origin/main. The landed tree equals git merge-tree of that parent and the accepted head a4a2375 (tree aa6ff7dd on both). 6 files, +252/−14.
    • Content check on packages/fields/src/index.tsx, 885a96f → 055d350:
      • the formula cell's numeric arm (returnType === undefined && typeof value === 'number'): 0 → 1;
      • the datetime time span ml-1 text-muted-foreground: 0 → 1;
      • the old ml-2 text-muted-foreground span: 1 → 0.
      • Control: export function FormulaCellRenderer is 1 on both.
    • Closures. The PR's only closing keyword was Fixes #11683. Since 21:20Z the closed issues are objectui#11683 and objectui#11733, which PR objectui#11746 closed with its own Fixes. pm:dispatched removed.
    • Follow-up: family card objectui#11748 (a formula's display ignores returnType on the form and cell faces), filed from this card's findings.
    • Serial queue. objectui#11697 (JsonCellRenderer) was serial behind this PR for packages/fields/src/index.tsx, and is now free (seat post §3).

    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:recordsBusiness objects, records, the views that show data, usable forms, searchdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatenhancementNew feature or requestpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions