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
record history: a dynamic-mode currency change still reads as a plain number, because the record page builds the History format context without the tenant currency #27640
Who: anyone reading Activity › History on a record whose currency field is dynamic mode (no code of its own, the tenant default applies). What happens once PR #27638 lands: a fixed currency change reads $4,321,000.00 like the record page, but a dynamic one still reads as a plain grouped number (4,321,000.00) beside the record's $4,321,000.00, because the History tab is never handed the tenant's default currency.
Where
ui/packages/app-shell/src/views/RecordDetailView.tsx ~L2443 (origin/main): const fmtCtx = { t, locale: displayLocale, lookupLabels }; — passed to formatAuditValue for every change.
The record page passes the tenant currency into the History format context (tenantCurrency: useLocalization().currency or the value the page's cells already read); a dynamic currency change reads with the tenant's code.
A test on the record page's History tab drives a dynamic currency change. record mode stays a plain number (out of scope: its code is a sibling field).
Reader who acts
The domain:ui seat holding RecordDetailView.tsx (seat 1's record-page chain, #25966) or the one triage names; one wiring line plus a test.
reach
Public door: console record page › Activity › History on any object with a dynamic currency field, after PR #27638 lands (the card thread measured the gap in its report on #27486, comment 6501393530).
Dedupe
Search API is unavailable from this session; read instead: the 500 most recently created issues (open and closed) by title, grep tenantCurrency|history.*currency|dynamic.*currency → 2 hits: #27486 (the parent, fixed/number/percent) and #27189 (currency docs page). No duplicate.
Read fresh. One wiring line: the record page passes the tenant currency into the History format context, the same value its cells read, with a test on a dynamic currency change. record mode stays out of scope.
Unblocked · 2026-10-29T16:28Z: the blocker landed. PR #27638 merged at 16:27Z, and #27486 is closed as completed. Labels move from pm:blocked to pm:queue.
In-flight intersection on ui/packages/app-shell/src/views/RecordDetailView.tsx, read at the unblock: two open draft PRs also edit it.
A claimant serialises behind those PRs or names the overlap in its claim. Seat 4 does not pick this card: RecordDetailView.tsx is the record page, which sits outside seat 4's area.
Claim: PM loop round 2 · 2026-10-29T21:44Z
Session: session_01Utp6CY2n1JmZZKrHgtp9jC (seat; implementation by an in-seat subagent, mode:subagent)
Account: os-bill
Branch: claude/project-thread-pwdhvq (the seat's harness push branch — the measured platform exception to claude/issue-N-slug)
Worktree: objectstack-issue-27640
Domain: domain:ui
Seat: domain:ui#2
File surface: ui/packages/app-shell/src/views/RecordDetailView.tsx (the History fmtCtx and, only if needed, one hook read), one test beside it, a changeset; ⛔ everything else
Container & model: S, mode:subagent, model: TIER_DEFAULT (dispatch-gates --tier: no path-derived mandate), effort: medium
Clause-②: no (expected; the dev measures from the diff)
Metadata-protocol: none (expected; the dev measures from the diff)
Responsibility: the record page's History format context lacking the tenant currency | resolveFieldCurrency's order (ADR-0053) and #27638's tenantCurrency member are fixed inputs | every reader of Activity › History on a record with a dynamic currency field, today
Thread-read: 6502392385
Premise: holds as filed (seat read origin/main: fmtCtx = { t, locale: displayLocale, lookupLabels } at ~L2443, no tenantCurrency)
Serial constraints cleared: #27638 (the blocker) and #27636 / #27592 merged; seat 1 has signed off (maintainer, 2026-10-29T21:42Z), so its record-page area is open to seats 2–4; the spec seat's draft PR #27713 also edits RecordDetailView.tsx (an unrelated region), so whichever lands second rebases
Dispatch order: /mnt/project-files/ui-seat2/dispatch-27640.md in the Claude Code project (not on GitHub).
{
"issue": 27640,
"status": "done",
"branch": "claude/project-thread-pwdhvq",
"pr": "https://github.com/objectstack-ai/objectstack/pull/27779",
"head": "7be9046e251bb915602b55b537fc69f3a18b15f1",
"session": "session_01Utp6CY2n1JmZZKrHgtp9jC",
"premise_still_valid": true,
"summary": "RecordDetailView's History effect now passes the tenant default currency into its format context: fmtCtx = { t, locale: displayLocale, lookupLabels, tenantCurrency }. The value is read with const { currency: tenantCurrency } = useLocalization() from @object-ui/i18n. That is the same useLocalization().currency the record page's cells read (plugin-detail DetailView reads its tenantCurrency the same way), and the page held no copy of it before, so this is the one allowed hook read. tenantCurrency also joins the History effect's dependency list, so the stream re-formats when the tenant localization arrives. record-mode fields are unchanged. The newest Claim (comment 6509037808) names claude/project-thread-pwdhvq, which matches this branch. No assignee or reviewer was written on the card or the PR; the harness's post-PR assign/review step was skipped as the dispatch requires.",
"tests": "New file RecordDetailView.auditTenantCurrency-27640.test.tsx: Test Files 1 passed (1), Tests 3 passed (3). Cases: dynamic 1500->2500 under an EUR tenant reads 'Amount €1,500.00 → €2,500.00'; record-mode stays 'List price 1,500.00 → 2,500.00'; control with no tenant currency stays plain. Ablation, with the fix committed first and the change made through scripts/ablation-replace.mjs: the anchor 'lookupLabels, tenantCurrency };' was replaced by 'lookupLabels };'. The anchor count went 1 -> 0 and the blob went ab5f20a6e2c8 -> cb4dc3752561. The pin went red ('got: Amount 1,500.00 → 2,500.00') and the other 2 stayed green. After the restore the blob equals HEAD's (ab5f20a6e2c8). On head 7be9046e, every test file importing RecordDetailView plus the auditHistoryDisplay unit tests ran: 157 files, 156 passed and 1 skipped; 1079 tests passed and 8 skipped; lock VERDICT command-exit 0. On f804616f, pnpm --filter @object-ui/app-shell run type-check gave VERDICT command-exit 0. eslint on the 2 touched source files exited 0 with 0 errors. pnpm check:new-line-citations reported 0 new citations.",
"gates": "Local, at final head 7be9046e: the 34 derived commands each exited 0, node scripts/check-sdui-manifest.mjs and its --self-test included. 'node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran FILE' printed: 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN. One earlier run at 9d1e1008 recorded 'pnpm check:query-options-erasure :: exit 124'. That was my own 280s timeout, not a gate failure. A rerun without the cap exited 0, and the final-head run exited 0. CI check-runs on the PR were in_progress when this report was written. The families CI runs are cited from the PR's check-runs and were not re-run locally.",
"line_budget": "RecordDetailView.tsx +6/-3: the import, the 2-line comment, the hook read, the fmtCtx line and the effect deps line. Test +222/-0 (1 file). Changeset +10/-0. Total 241 changed lines, under the 3000 human-merge threshold.",
"files_changed": [
".changeset/27640-history-dynamic-currency.md",
"ui/packages/app-shell/src/views/RecordDetailView.auditTenantCurrency-27640.test.tsx",
"ui/packages/app-shell/src/views/RecordDetailView.tsx"
],
"deviations": [
"Diff line beyond 'the fmtCtx line plus the hook read': tenantCurrency was added to the History effect's dependency list. Without it, History would keep the plain-number face when the tenant localization resolves after the effect ran. displayLocale is listed there for the same reason.",
"Local package test narrowed: @object-ui/app-shell holds about 1914 test files. My own full-package run (pids I recorded: 6780 and its children) was stopped after 21 min with no result. The run was then narrowed to the 157 files that import RecordDetailView plus the auditHistoryDisplay tests. CI's Test UI runs the full package.",
"The first targeted test run failed on an unresolved import of @objectstack/spec/ui because dist had not been built. That was a build prerequisite, not a red. Building the dependency closure (turbo build --filter '@object-ui/app-shell^...') fixed it.",
"The report comment's first non-empty line is the seat signature, as the dispatch requires. The os-dev-report marker is on the second line, not the first as os-dev.md says. The dispatch was followed.",
"The worktree was created with the dispatch's 'git worktree add -B BRANCH ../objectstack-issue-27640 origin/main' form, which tracks origin/main. os-dev.md says --no-track. The branch was later pushed with -u to its own remote."
],
"dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
"mcp_calls": "0",
"api_writes": "2 — POST /repos/objectstack-ai/objectstack/dispatches (fleet-write relay pr_create -> PR #27779, read-back identical, 5698 bytes); POST issue comment on #27640 via scripts/pm/post-stamped.mjs (os-dev-report). git push x3 to claude/project-thread-pwdhvq (not REST).",
"open_questions": [],
"out_of_scope_findings": []
}
Activity
objectstack-fleet commentedon Oct 29, 2026
triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U
Path: 业务对象与记录 | none | P②
Triage: p2 ·
domain:ui·area:records·pm:blockedon PR #27638 · 2026-10-29T16:05Z⛔ Not a claim.
dynamiccurrency change.recordmode stays out of scope.RecordDetailView.tsxis a hot file, so run the in-flight intersection check.bug,pm:blocked.Generated by Claude Code
objectstack-fleet commentedon Oct 29, 2026
domain:ui#4 · os-bill · session_01Utp6CbDAucNyQ4UtzCJKyh
Unblocked · 2026-10-29T16:28Z: the blocker landed. PR #27638 merged at 16:27Z, and #27486 is closed as completed. Labels move from
pm:blockedtopm:queue.In-flight intersection on
ui/packages/app-shell/src/views/RecordDetailView.tsx, read at the unblock: two open draft PRs also edit it.Fixes #27056, the record page's related-column chain)Fixes #27478)A claimant serialises behind those PRs or names the overlap in its claim. Seat 4 does not pick this card:
RecordDetailView.tsxis the record page, which sits outside seat 4's area.Generated by Claude Code
objectstack-fleet commentedon Oct 29, 2026
domain:ui#2 · os-bill · session_01Utp6CY2n1JmZZKrHgtp9jC
Claim: PM loop round 2 · 2026-10-29T21:44Z
Session:
session_01Utp6CY2n1JmZZKrHgtp9jC(seat; implementation by an in-seat subagent,mode:subagent)Account:
os-billBranch:
claude/project-thread-pwdhvq(the seat's harness push branch — the measured platform exception toclaude/issue-N-slug)Worktree:
objectstack-issue-27640Domain:
domain:uiSeat:
domain:ui#2File surface:
ui/packages/app-shell/src/views/RecordDetailView.tsx(the HistoryfmtCtxand, only if needed, one hook read), one test beside it, a changeset; ⛔ everything elseContainer & model:
S,mode:subagent,model: TIER_DEFAULT(dispatch-gates --tier: no path-derived mandate),effort: mediumClause-②: no (expected; the dev measures from the diff)
Metadata-protocol: none (expected; the dev measures from the diff)
Responsibility: the record page's History format context lacking the tenant currency |
resolveFieldCurrency's order (ADR-0053) and #27638'stenantCurrencymember are fixed inputs | every reader of Activity › History on a record with adynamiccurrency field, todayThread-read: 6502392385
Premise: holds as filed (seat read
origin/main:fmtCtx = { t, locale: displayLocale, lookupLabels }at ~L2443, notenantCurrency)Serial constraints cleared: #27638 (the blocker) and #27636 / #27592 merged; seat 1 has signed off (maintainer, 2026-10-29T21:42Z), so its record-page area is open to seats 2–4; the spec seat's draft PR #27713 also edits
RecordDetailView.tsx(an unrelated region), so whichever lands second rebasesDispatch order:
/mnt/project-files/ui-seat2/dispatch-27640.mdin the Claude Code project (not on GitHub).Generated by Claude Code
objectstack-fleet commentedon Oct 29, 2026
domain:ui#2 · os-bill · session_01Utp6CY2n1JmZZKrHgtp9jC
os-dev-report
{ "issue": 27640, "status": "done", "branch": "claude/project-thread-pwdhvq", "pr": "https://github.com/objectstack-ai/objectstack/pull/27779", "head": "7be9046e251bb915602b55b537fc69f3a18b15f1", "session": "session_01Utp6CY2n1JmZZKrHgtp9jC", "premise_still_valid": true, "summary": "RecordDetailView's History effect now passes the tenant default currency into its format context: fmtCtx = { t, locale: displayLocale, lookupLabels, tenantCurrency }. The value is read with const { currency: tenantCurrency } = useLocalization() from @object-ui/i18n. That is the same useLocalization().currency the record page's cells read (plugin-detail DetailView reads its tenantCurrency the same way), and the page held no copy of it before, so this is the one allowed hook read. tenantCurrency also joins the History effect's dependency list, so the stream re-formats when the tenant localization arrives. record-mode fields are unchanged. The newest Claim (comment 6509037808) names claude/project-thread-pwdhvq, which matches this branch. No assignee or reviewer was written on the card or the PR; the harness's post-PR assign/review step was skipped as the dispatch requires.", "tests": "New file RecordDetailView.auditTenantCurrency-27640.test.tsx: Test Files 1 passed (1), Tests 3 passed (3). Cases: dynamic 1500->2500 under an EUR tenant reads 'Amount €1,500.00 → €2,500.00'; record-mode stays 'List price 1,500.00 → 2,500.00'; control with no tenant currency stays plain. Ablation, with the fix committed first and the change made through scripts/ablation-replace.mjs: the anchor 'lookupLabels, tenantCurrency };' was replaced by 'lookupLabels };'. The anchor count went 1 -> 0 and the blob went ab5f20a6e2c8 -> cb4dc3752561. The pin went red ('got: Amount 1,500.00 → 2,500.00') and the other 2 stayed green. After the restore the blob equals HEAD's (ab5f20a6e2c8). On head 7be9046e, every test file importing RecordDetailView plus the auditHistoryDisplay unit tests ran: 157 files, 156 passed and 1 skipped; 1079 tests passed and 8 skipped; lock VERDICT command-exit 0. On f804616f, pnpm --filter @object-ui/app-shell run type-check gave VERDICT command-exit 0. eslint on the 2 touched source files exited 0 with 0 errors. pnpm check:new-line-citations reported 0 new citations.", "gates": "Local, at final head 7be9046e: the 34 derived commands each exited 0, node scripts/check-sdui-manifest.mjs and its --self-test included. 'node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran FILE' printed: 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN. One earlier run at 9d1e1008 recorded 'pnpm check:query-options-erasure :: exit 124'. That was my own 280s timeout, not a gate failure. A rerun without the cap exited 0, and the final-head run exited 0. CI check-runs on the PR were in_progress when this report was written. The families CI runs are cited from the PR's check-runs and were not re-run locally.", "line_budget": "RecordDetailView.tsx +6/-3: the import, the 2-line comment, the hook read, the fmtCtx line and the effect deps line. Test +222/-0 (1 file). Changeset +10/-0. Total 241 changed lines, under the 3000 human-merge threshold.", "files_changed": [ ".changeset/27640-history-dynamic-currency.md", "ui/packages/app-shell/src/views/RecordDetailView.auditTenantCurrency-27640.test.tsx", "ui/packages/app-shell/src/views/RecordDetailView.tsx" ], "deviations": [ "Diff line beyond 'the fmtCtx line plus the hook read': tenantCurrency was added to the History effect's dependency list. Without it, History would keep the plain-number face when the tenant localization resolves after the effect ran. displayLocale is listed there for the same reason.", "Local package test narrowed: @object-ui/app-shell holds about 1914 test files. My own full-package run (pids I recorded: 6780 and its children) was stopped after 21 min with no result. The run was then narrowed to the 157 files that import RecordDetailView plus the auditHistoryDisplay tests. CI's Test UI runs the full package.", "The first targeted test run failed on an unresolved import of @objectstack/spec/ui because dist had not been built. That was a build prerequisite, not a red. Building the dependency closure (turbo build --filter '@object-ui/app-shell^...') fixed it.", "The report comment's first non-empty line is the seat signature, as the dispatch requires. The os-dev-report marker is on the second line, not the first as os-dev.md says. The dispatch was followed.", "The worktree was created with the dispatch's 'git worktree add -B BRANCH ../objectstack-issue-27640 origin/main' form, which tracks origin/main. os-dev.md says --no-track. The branch was later pushed with -u to its own remote." ], "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm", "mcp_calls": "0", "api_writes": "2 — POST /repos/objectstack-ai/objectstack/dispatches (fleet-write relay pr_create -> PR #27779, read-back identical, 5698 bytes); POST issue comment on #27640 via scripts/pm/post-stamped.mjs (os-dev-report). git push x3 to claude/project-thread-pwdhvq (not REST).", "open_questions": [], "out_of_scope_findings": [] }objectstack-fleet commentedon Oct 29, 2026
domain:ui#2 · os-bill · session_01Utp6CY2n1JmZZKrHgtp9jC
ACCEPT → PR #27779 comment 6510805303 (head
7be9046e). Contract review not owed (Clause-②: no,Metadata-protocol: none). Landing through the merge queue.Generated by Claude Code
objectstack-fleet commentedon Oct 29, 2026
domain:ui#2 · os-bill · session_01Utp6CY2n1JmZZKrHgtp9jC
Landed · 2026-10-29T23:45Z
561b7642e1a17c6f26f887fa3250092fd0ba8e77completedby the PR'sFixeslineState:
pm:dispatchedremoved; the assignee stays as the record of who carried it.Generated by Claude Code