Repository navigation
[Epic] multi-currency (shape C′): record currency, dated exchange rates, write-time home-currency projection — 17 children, R1/R2/R3 release pairing (ruling 6465431966) #8345
Description
epic:#8345#1 · os-bill · session_01Utp6CbTZrFqRYNgjSaSbN5
Epic: multi-currency (shape C′) · pm:epic · opened by the director seat (summon #53, session_01QSeKYo7qYsX6HsAneHBMP2) on ruling 6465431966 (#27119 Q1 = 乙-现在, maintainer 「同意立专题卡」 2026-10-28).
Epic PM seat: ⏳ vacant · former session session_01Utp6CbTZrFqRYNgjSaSbN5 (account os-bill, project seat, registered 2026-10-28T10:42Z) signed off 2026-10-31T06:55Z on the maintainer's word 「这两个处理完就下班」 (project thread, 2026-10-31T05:03Z), after #27192 (PR #28302) and #27198 (PR #28297) landed. check-handover exit 0. Successor: /pm-dispatch epic:#8345 and read this body first.
Seat ledger at sign-off:
- Landed: R1 (spec(field): retire the
@deprecatedCurrencyValueSchema(still exported atfield.zod.ts:581) — ADR-0104 D1 says deleted; prerequisite of the multi-currency epic #8345 #27182 docs(adr): ADR for multi-currency — record currency, dated rates, write-time home projection (Q0–Q4 and parameters 1–4 as ruled on #27119); dated note on ADR-0104 (epic #8345, lands in R1 first) #27183 spec(field):currencyMode: 'record'+currencyField— a record-mode amount points at a sibling ISO 4217 code field (multi-currency M0-1, epic #8345) #27184 objectql: record-mode guards — blank code refuses the write; ungrouped sum/avg/min/max over a record-mode field refused; summary roll-up over one refused at registration (multi-currency M0-2, epic #8345) #27186 analytics seam: grouped results carry a per-row currency; cube door refuses an ungrouped aggregate over a record-mode field; guards on today's surface (multi-currency M0-3, epic #8345) #27187 ui: record-mode currency —resolveFieldCurrencyreads the sibling code field's value; form pre-fills the organization currency; grid / drawer / dashboard / footer per-row display; Studio field editor (multi-currency M0-4, epic #8345) #27188 docs(data-modeling): the currency page — dynamic / fixed / record modes, the sibling code field, what refuses (multi-currency M0-5, epic #8345) #27189), the mode-switch backfill objectql + cli: backfill the currency code when a stored amount switches to record mode, and a 409 acknowledgement at the metadata door (multi-currency, epic #8345) #27577, the fixed-vs-fixed refusal service-analytics: refuse fixed-versus-fixed cross-currency measures at dataset compile (multi-currency, epic #8345) #27579, and the R2 core: platform-objects:sys_exchange_rate{ currency, rate, effective_date, source } — tenant-scoped, admin-only, audited; Setup list view (multi-currency M1-1, epic #8345; released with M2) #27185sys_exchange_rate, spec(field):homeAmount: { field, rateDate, rateField? }on a record-mode amount — the stored home-currency projection declared by pointer (multi-currency M2-1, epic #8345; released with M2-2) #27191homeAmount, objectql: write-time home projection — rate lookup by document date, decimal arithmetic, minor-unit rounding, missing rate refuses, computed fields read-only (multi-currency M2-2, epic #8345) #27192 projection (PR feat(objectql): store a record-mode amount converted into the home currency on every write (multi-currency M2-2) #28302,6762dd91), service-settings: locklocalization.currencyonce asys_exchange_raterow or ahomeAmountdeclaration exists; Setup shows what uses it (multi-currency M1-3, epic #8345) #27198 lock (PR feat(service-settings): the default currency locks once an exchange rate or a home-currency amount uses it, and Setup names what uses it (multi-currency M1-3) #28297). - Release: ruling 6539345871 (A′): 18.3.0 = R1 + R2 core in one Version Packages (chore: version packages #26517). Maintainer 2026-10-31T06:49Z: 「18.3 先不发」, so chore: version packages #26517 stays open; nothing in the R2 core may land a breaking change before it ships.
- Next (R2.1, dispatchable under
pm:epic): cli:os migrate recompute-home-amounts --object X [--since DATE] [--apply]— report then apply; rows with a missing rate are listed and skipped (multi-currency M2-3, epic #8345) #27193 recompute (blocker landed) → migrate: adding ahomeAmountfield to an existing object is the normal add-column path; backfill = recompute — one proving test (multi-currency M2-4, epic #8345) #27194 migrate proof (pm:blockedon cli:os migrate recompute-home-amounts --object X [--since DATE] [--apply]— report then apply; rows with a missing rate are listed and skipped (multi-currency M2-3, epic #8345) #27193); ui: home field read-only with "converted at RATE on DATE"; live preview when a rate exists; Studio editor forhomeAmount(multi-currency M3-2, epic #8345; the read-only display is released with M2) #27196 UI home field read-only (blockers landed); import: verifysys_import_jobservessys_exchange_rate(CSV of currency, rate, effective_date); add the importer only if it does not (multi-currency M1-2, epic #8345) #27190 import check is in the server lane'spm:queue. R3: analytics: consolidated measures over the home field work unchanged (proof); a metric over a record-mode field must name the home field or group by code (multi-currency M3-1, epic #8345) #27195 consolidated-measures proof (blockers landed), examples + QA: showcaseinvoicegoes multi-currency (code field, record amount, home field, document date), seeded rates, a rate-sync flow template, a platform-checklist item and a browser dogfood run (multi-currency M3-3, epic #8345) #27197 showcase + QA (pm:blockedon ui: home field read-only with "converted at RATE on DATE"; live preview when a rate exists; Studio editor forhomeAmount(multi-currency M3-2, epic #8345; the read-only display is released with M2) #27196). - Owed by the next epic PM: one Tier H ADR-0144 amendment PR: settle Open items 2, 3, 4, 6, 9 from PR feat(objectql): store a record-mode amount converted into the home currency on every write (multi-currency M2-2) #28302's body section "ADR-0144 open items settled here"; record ruling 6539345871 A′ and B (a
datetimedocument date is read in the organization'slocalization.timezone); the rounding mode (half away from zero, once);CURRENCY_FRACTION_DIGITSis CLDR digits, not ISO 4217 minor units; drop "the only ledger additions" (three codes now). Also file onedomain:speccard: refuse arateFieldscale below 12, and the CLDR-versus-ISO digit table (review 6539117549, S2; open question 3 on objectql: write-time home projection — rate lookup by document date, decimal arithmetic, minor-unit rounding, missing rate refuses, computed fields read-only (multi-currency M2-2, epic #8345) #27192). - Follow-up cards in lanes (not epic-reserved): cli + docs: judge --code before boot in os migrate record-currency-codes, and document the command and the record-mode switch (multi-currency, epic #8345) #28168 (server
pm:queue:--codebefore boot, CLI docs), service-analytics: a dataset's currency guard compares acountthat names an amount field, refusing an amount-per-row ratio as cross-currency (multi-currency, epic #8345) #28194 (count operand in the currency guard, dispatched to the server lane). - Cross-lane notes:
os migrate record-currency-codesnow triggers the projection, so a codeless row on an object withhomeAmountand no rate fails the backfill loudly (review flag F2 on PR feat(objectql): store a record-mode amount converted into the home currency on every write (multi-currency M2-2) #28302). The lock is deployment-wide on ahomeAmountdeclaration; a per-organization relaxation would be a new card.
Territory (declared): packages/spec/src/data/field.zod.ts (the currency block: CurrencyConfigSchema, CurrencyValueSchema retirement), packages/spec/src/data/object.zod.ts (currency pointer arms), packages/spec/src/contracts/analytics-service.ts (per-row currency key), packages/objectql/src (record-validator currency arms, aggregate door, the write-time home projection, recompute), packages/platform-objects/src (sys_exchange_rate, Setup nav), packages/services/service-settings/src (home-currency lock), packages/services/service-analytics/src (cube door, grouped currency), packages/cli/src/commands/migrate (recompute command), ui/packages/{i18n,fields,plugin-dashboard,app-shell} (currency readers, form, Studio editor), examples/app-showcase (invoice), content/docs/data-modeling, one new docs/adr/* record. Spec and seam children go to the domain:spec seat's queue; the rest are dispatched by the epic PM.
维护者速读
- 改了什么: 多币种按 C′ 形状分四期交付:记录币种(金额字段指向同对象上的 ISO 4217 币种字段)→ 平台汇率表
sys_exchange_rate→ 写入时按单据日期折成本位币并存下影子列(缺汇率拒写、改汇率显式重算)→ 报表、前端与示例。 - 为什么改: 平台今天没有任何键承载「这条记录是什么币种」;跨币种求和静默算错(USD 100 + JPY 15000 = 15100)。港口客户要按客户币种开票、按日汇率对账、折本位币合并报表。
- 风险与回滚: 全部是新增声明,不写
record的应用零变化;两处必须成对发布(R1、R2,见下);浮点算钱用最小单位整数或 decimal;本位币一经使用即锁定。 - 先看: 设计 6464438764、工作量 6464936321、裁决 6465431966(都在 [Decision] Currency, all of it: resume multi-currency (#8345) and in what shape, and one rule for an amount whose currency is not known (Studio's USD, the template's USD,
fixed's CNY, the example's USD) #27119)。 - 两分钟验证: 三张不同币种的发票在列表里各显其符号,仪表盘指向影子列出本位币合计,指向原始金额不分组被拒。
- 需要您做的: 召唤
/pm-dispatch epic:#8345;批 docs(adr): ADR for multi-currency — record currency, dated rates, write-time home projection (Q0–Q4 and parameters 1–4 as ruled on #27119); dated note on ADR-0104 (epic #8345, lands in R1 first) #27183(ADR,Tier H);R1 / R2 各在一次 Version Packages 发布里合并。
Rulings this epic executes
- Shape C′ and sub-questions Q0–Q4, parameters 1–4: ruling 6465431966 on [Decision] Currency, all of it: resume multi-currency (#8345) and in what shape, and one rule for an amount whose currency is not known (Studio's USD, the template's USD,
fixed's CNY, the example's USD) #27119. Design record: 6464438764. Workload rows and precedents: 6464936321. Earlier measurement round on this card: 6041378776 / 6041482631 (the probes are this epic's fixtures). Q2 X (one rule for an unknown currency) is executed outside the epic: ui(studio): the dataset inspector storescurrency: 'USD'when the currency format is picked with no currency — store nothing and inherit the field / tenant chain (#27119 Q2 X, G1) #27156, spec(field):fixed-modecurrencyConfigwith nodefaultCurrencymaterialises'CNY'— require the code, drop the default (narrowing; #27119 Q2 X, G3) #27157 (prerequisite of M0-1), docs+examples(currency):opportunity.dataset.tshard-codescurrency: 'USD'over a tenant-currency field, and two protocol docs claim exchange rates / a stored currency code — delete the key, rewrite the two sentences (#27119 Q2 X G4 + Q3) #27158, spec(formula): acurrencyhole with no argument still formats in US dollars — refuse it at authoring in every template dialect (follow-up of #26660) #26939. - Design rules from the summon: no platform or tenant switch (
currencyMode: 'record'is the switch); no injected columns, no fixed field names — authors declare every currency-related field and reference it by pointer; "enabled currencies" is derived, not a setting; the form pre-fills the organization currency at the renderer; metadata never names the home currency.
Children (17), by release
R1 — record currency + guards (one Version Packages release; ⛔ never ship #27184 alone)
- spec(field): retire the
@deprecatedCurrencyValueSchema(still exported atfield.zod.ts:581) — ADR-0104 D1 says deleted; prerequisite of the multi-currency epic #8345 #27182 C0 · spec · retireCurrencyValueSchema· XS ·pm:queuedomain:spec - docs(adr): ADR for multi-currency — record currency, dated rates, write-time home projection (Q0–Q4 and parameters 1–4 as ruled on #27119); dated note on ADR-0104 (epic #8345, lands in R1 first) #27183 M3-4 · ADR (Tier H) · S · lands first
- spec(field):
currencyMode: 'record'+currencyField— a record-mode amount points at a sibling ISO 4217 code field (multi-currency M0-1, epic #8345) #27184 M0-1 · spec ·recordmode +currencyField· M · Blocked-by spec(field):fixed-modecurrencyConfigwith nodefaultCurrencymaterialises'CNY'— require the code, drop the default (narrowing; #27119 Q2 X, G3) #27157, spec(field): retire the@deprecatedCurrencyValueSchema(still exported atfield.zod.ts:581) — ADR-0104 D1 says deleted; prerequisite of the multi-currency epic #8345 #27182, docs(adr): ADR for multi-currency — record currency, dated rates, write-time home projection (Q0–Q4 and parameters 1–4 as ruled on #27119); dated note on ADR-0104 (epic #8345, lands in R1 first) #27183 - objectql: record-mode guards — blank code refuses the write; ungrouped sum/avg/min/max over a record-mode field refused; summary roll-up over one refused at registration (multi-currency M0-2, epic #8345) #27186 M0-2 · objectql · guards (blank code, ungrouped aggregate, summary) · M · Blocked-by spec(field):
currencyMode: 'record'+currencyField— a record-mode amount points at a sibling ISO 4217 code field (multi-currency M0-1, epic #8345) #27184 - analytics seam: grouped results carry a per-row currency; cube door refuses an ungrouped aggregate over a record-mode field; guards on today's surface (multi-currency M0-3, epic #8345) #27187 M0-3 · seam spec + analytics · per-row currency, cube door, today's guards · M · Blocked-by spec(field):
currencyMode: 'record'+currencyField— a record-mode amount points at a sibling ISO 4217 code field (multi-currency M0-1, epic #8345) #27184 - ui: record-mode currency —
resolveFieldCurrencyreads the sibling code field's value; form pre-fills the organization currency; grid / drawer / dashboard / footer per-row display; Studio field editor (multi-currency M0-4, epic #8345) #27188 M0-4 · ui · per-row display, form, Studio · M–L · Blocked-by spec(field):currencyMode: 'record'+currencyField— a record-mode amount points at a sibling ISO 4217 code field (multi-currency M0-1, epic #8345) #27184 - docs(data-modeling): the currency page — dynamic / fixed / record modes, the sibling code field, what refuses (multi-currency M0-5, epic #8345) #27189 M0-5 · docs · currency page · S · Blocked-by spec(field):
currencyMode: 'record'+currencyField— a record-mode amount points at a sibling ISO 4217 code field (multi-currency M0-1, epic #8345) #27184
R2 — rates + write-time home projection (one release; the rate table never ships without its reader)
- platform-objects:
sys_exchange_rate{ currency, rate, effective_date, source } — tenant-scoped, admin-only, audited; Setup list view (multi-currency M1-1, epic #8345; released with M2) #27185 M1-1 · platform-objects ·sys_exchange_rate+ Setup · M - import: verify
sys_import_jobservessys_exchange_rate(CSV of currency, rate, effective_date); add the importer only if it does not (multi-currency M1-2, epic #8345) #27190 M1-2 · import check · XS–S · Blocked-by platform-objects:sys_exchange_rate{ currency, rate, effective_date, source } — tenant-scoped, admin-only, audited; Setup list view (multi-currency M1-1, epic #8345; released with M2) #27185 - service-settings: lock
localization.currencyonce asys_exchange_raterow or ahomeAmountdeclaration exists; Setup shows what uses it (multi-currency M1-3, epic #8345) #27198 M1-3 · service-settings · home-currency lock · M · Blocked-by platform-objects:sys_exchange_rate{ currency, rate, effective_date, source } — tenant-scoped, admin-only, audited; Setup list view (multi-currency M1-1, epic #8345; released with M2) #27185, spec(field):homeAmount: { field, rateDate, rateField? }on a record-mode amount — the stored home-currency projection declared by pointer (multi-currency M2-1, epic #8345; released with M2-2) #27191 - spec(field):
homeAmount: { field, rateDate, rateField? }on a record-mode amount — the stored home-currency projection declared by pointer (multi-currency M2-1, epic #8345; released with M2-2) #27191 M2-1 · spec ·homeAmountpointer · M · Blocked-by spec(field):currencyMode: 'record'+currencyField— a record-mode amount points at a sibling ISO 4217 code field (multi-currency M0-1, epic #8345) #27184 - objectql: write-time home projection — rate lookup by document date, decimal arithmetic, minor-unit rounding, missing rate refuses, computed fields read-only (multi-currency M2-2, epic #8345) #27192 M2-2 · objectql · write-time projection (L) · Blocked-by spec(field):
homeAmount: { field, rateDate, rateField? }on a record-mode amount — the stored home-currency projection declared by pointer (multi-currency M2-1, epic #8345; released with M2-2) #27191, platform-objects:sys_exchange_rate{ currency, rate, effective_date, source } — tenant-scoped, admin-only, audited; Setup list view (multi-currency M1-1, epic #8345; released with M2) #27185 - cli:
os migrate recompute-home-amounts --object X [--since DATE] [--apply]— report then apply; rows with a missing rate are listed and skipped (multi-currency M2-3, epic #8345) #27193 M2-3 · cli · recompute · M · Blocked-by objectql: write-time home projection — rate lookup by document date, decimal arithmetic, minor-unit rounding, missing rate refuses, computed fields read-only (multi-currency M2-2, epic #8345) #27192 - migrate: adding a
homeAmountfield to an existing object is the normal add-column path; backfill = recompute — one proving test (multi-currency M2-4, epic #8345) #27194 M2-4 · migrate proof · S · Blocked-by cli:os migrate recompute-home-amounts --object X [--since DATE] [--apply]— report then apply; rows with a missing rate are listed and skipped (multi-currency M2-3, epic #8345) #27193 - ui: home field read-only with "converted at RATE on DATE"; live preview when a rate exists; Studio editor for
homeAmount(multi-currency M3-2, epic #8345; the read-only display is released with M2) #27196 M3-2 · ui · home field read-only (+ preview) · M · Blocked-by spec(field):homeAmount: { field, rateDate, rateField? }on a record-mode amount — the stored home-currency projection declared by pointer (multi-currency M2-1, epic #8345; released with M2-2) #27191, ui: record-mode currency —resolveFieldCurrencyreads the sibling code field's value; form pre-fills the organization currency; grid / drawer / dashboard / footer per-row display; Studio field editor (multi-currency M0-4, epic #8345) #27188
R3 — proof and polish
- analytics: consolidated measures over the home field work unchanged (proof); a metric over a record-mode field must name the home field or group by code (multi-currency M3-1, epic #8345) #27195 M3-1 · analytics · consolidated measures proof · S–M · Blocked-by objectql: write-time home projection — rate lookup by document date, decimal arithmetic, minor-unit rounding, missing rate refuses, computed fields read-only (multi-currency M2-2, epic #8345) #27192, analytics seam: grouped results carry a per-row currency; cube door refuses an ungrouped aggregate over a record-mode field; guards on today's surface (multi-currency M0-3, epic #8345) #27187
- examples + QA: showcase
invoicegoes multi-currency (code field, record amount, home field, document date), seeded rates, a rate-sync flow template, a platform-checklist item and a browser dogfood run (multi-currency M3-3, epic #8345) #27197 M3-3 · examples + QA · showcase invoice, rate-sync flow template, checklist, dogfood · M · Blocked-by objectql: write-time home projection — rate lookup by document date, decimal arithmetic, minor-unit rounding, missing rate refuses, computed fields read-only (multi-currency M2-2, epic #8345) #27192, ui: home field read-only with "converted at RATE on DATE"; live preview when a rate exists; Studio editor forhomeAmount(multi-currency M3-2, epic #8345; the read-only display is released with M2) #27196
Critical path: #27157 → #27184 → #27191 → #27192 → #27193 → #27197. Commitment: R1 (about 4–5 agent-days); R2 starts after the customer confirms the consolidation terms (home currency, rate source, which date drives the rate).
Release pairing rule (the only half-state risk)
A published record mode without M0-2/M0-3/M0-4 is worse than today (declared, not refused, wrong symbol); a published homeAmount key without M2-2 is a declaration the runtime never honours. The epic PM marks each R1 / R2 PR body ⛔ not released alone — pairs with …, and the maintainer merges Version Packages only when a pair is complete.
History
The 2026-08 filing (overseas port / terminal customer), the 2026-08-13 v18 scheduling, the 2026-10-07 measurement round and the 2026-10-08 pause are this card's earlier revisions and comments; the hold ended with ruling 6465431966.
Activity
hotlong commentedon Aug 13, 2026
Triage: confirming the filer's
domain:spec— M1/M2 both start frompackages/spec/src/data/field.zod.tsandcurrency-fraction-digits.ts(newsys_exchange_rateshape, CEL stdlib surface declared there), and the guard-rail item explicitly asks for a schema-level refusal. M3 (service-analyticsaggregation) is a downstream consumer, not the anchor.Hold (2026-08-13): maintainer already scheduled this for v18 (per issue body) — adding
pm:on-hold(the label was missing;domain:spec/target:v18were already set by the filer).Restart trigger files:
packages/spec/src/data/field.zod.ts(currencyConfigshape)packages/spec/src/data/currency-fraction-digits.tspackages/services/service-analytics/src/analytics-service.ts(ADR-0053 currency labeling chain)Generated by Claude Code
os-zhuang commentedon Aug 19, 2026
Hold-condition completion (triage seat, session
session_014qTKTqjme5Fp5BH9iRmy6t, on-hold weak-hit audit): the v18 park is sound and stands, but it had no executable boundary wake — the repo emits no v18 signal today (zero milestones, no v18 refs, spec at 17.0.0, no.changeset/pre.json, releases end at v17), so the only wake was the trigger-file list, which over-fires on incidental churn and never fires on "v18 opened". Adding the boundary leg; the existing trigger-file list stays for re-pricing.Restart-when: the v18 cycle opens — first true of:
.changeset/pre.jsonexists on origin/main,packages/spec/package.jsonversion matches^18., a milestone or ref matching v18 exists (git ls-remote origin 'refs/*v18*'), orcontent/docs/releases/v18.mdxis created — or a maintainer re-schedules the cardGenerated by Claude Code
os-warren commentedon Aug 24, 2026
H17 trigger-file notice (spec seat,
session_01Rxnd8cyFnoU8V5y21PaTsy, post-landing patrol): this hold's declared trigger filepackages/spec/src/data/field.zod.tswas touched by PR #11406 (merged9086761ed, 2026-08-24 ~15:0xZ). Scope of the touch: the #9689deleteBehaviorfamily only — the authored-set_null-on-master_detailparse rejection plus the ruled idempotent-materialization conditional in the.overwrite(). Zero currency surface moved:currencyConfigshape,currency-fraction-digits.tsand the analytics chain are untouched, and no v18 boundary signal exists (this hold'sRestart-when:legs all still read false). Posting per the opportunistic-restart mechanism so the hold owner can judge; from this seat's reading the restart does not fire — no action taken on the hold's state. One forward pointer worth having on this card: the merged PR's ADR draft records the principle "never materialize a default the schema itself would refuse as authored", which will constrain how this card's future currencyprecision/fractionDigitsshapes declare their defaults (#11423 is the near-term instance, now queued).Generated by Claude Code
os-warren commentedon Aug 24, 2026
H17 trigger-file notice (spec seat,
session_01Rxnd8cyFnoU8V5y21PaTsy, merge-time per the #11423 claim's declaration): this hold's declared trigger filepackages/spec/src/data/field.zod.tswas touched by PR #11766 (Fixes #11423, merged 21:55Z) — and unlike the three prior comment-only touches on record here, this one moves currency surface:CurrencyConfigSchema's.overwrite()gains a one-conditional guard so theprecisiondefault 2 is no longer materialized onto a barefixedconfig whose currency's ISO 4217/CLDR fraction digits contradict it (JPY/KRW/KWD class) — parse output omits the key andparse(parse(x))holds. The superRefine rejection of an AUTHORED contradictory precision is unchanged;currency-fraction-digits.tsand the analytics chain are untouched.Restart determination: this hold's
Restart-when:legs (v18 boundary signals / maintainer re-schedule) all still read false — the hold stays parked, no state change made. Forward note for whoever prices this card at v18: the merged guard is the second instance of the recorded principle "never materialize a default the schema itself would refuse as authored" (with #11406's master_detail conditional), and any futureprecision/fractionDigitsdefault this card's M1–M3 shapes declare must be designed under it from the start.Generated by Claude Code
os-support-ai commentedon Aug 25, 2026
H17 trigger-file notification (spec seat R5,
session_01K93P8PbH7kVjsAXkqzH1zY, 2026-08-25): this wave's dispatch for #11566 (maxLength shape + applicability tightening, ruled 2026-08-24) touchespackages/spec/src/data/field.zod.ts, a declaredRestart-touchtrigger file of this hold. Notification only, per the on-hold trigger-file protocol — no rider work from this hold is taken into that dispatch, and the hold stands unchanged (v18Restart-whenunaffected).Generated by Claude Code
os-litant commentedon Aug 25, 2026
H17 trigger-file notification (spec seat R6,
session_01NDGG54XF5gbTLdQzCtnaVV, 2026-08-25): this wave's dispatch for #11949 (+#11950 family-folded — minLength shape/applicability tightening per the maintainer's ruling B of 2026-08-25, plus the deferred maxLength ledger registration) touchespackages/spec/src/data/field.zod.ts, a declaredRestart-touchtrigger file of this hold. Notification only, per the on-hold trigger-file protocol and this card's own precedent (the R5 #11566 dispatch notice above): no rider work from this hold is taken into the dispatch — the touch is the bounded-stringminLengthconstraint only, zero currency surface — and the hold stands unchanged (all v18Restart-when:legs still read false).Generated by Claude Code
os-warren commentedon Aug 31, 2026
H17 trigger-file notification (domain:spec seat,
session_01PBjwYLS6BciTQW3c9xQiD2, 2026-08-31): this wave's dispatch for the objectui#6140 + objectui#6153 spec half (declarerows?: numberon markdown/html field metadata anddescription?: stringon select options — maintainer ruling A of 2026-08-25) touchespackages/spec/src/data/field.zod.ts, a declaredRestart-touchtrigger file of this hold. Notification only, per this card's own R5/R6 precedent: no rider work from this hold is taken into the dispatch — the touch is field-metadata key declaration, zero currency surface — and the hold stands unchanged (the v18Restart-when:legs still read false).Generated by Claude Code
zhuangjianguo commentedon Sep 3, 2026
H17 trigger-file notification (
domain:specseat, session_0174WZTU6XcFcS7g2kykC53i, 2026-09-03T18:15Z): this round's dispatch for #13916 (rewrite the false sentence "the canonical spellingdepends_onalready exists at the field level" in the option-description docblock and its two echoes in the sibling test file — fact layer only, per triage 5486900363) touchespackages/spec/src/data/field.zod.ts, a declaredRestart-touchtrigger file of this hold. Notification only, per this card's R5/R6 precedent: no rider work from this hold is taken into the dispatch — the touch is comment text, zero currency surface — and the hold stands unchanged. TheRestart-when:legs re-read onorigin/mainat 18:14Z all still read false: norefs/*v18*on origin,packages/specat 17.2.0, no.changeset/pre.json, nocontent/docs/releases/v18.mdx.Generated by Claude Code
claude commentedon Sep 4, 2026
H17 trigger-file notification (
domain:specseat, sessionsession_0174WZTU6XcFcS7g2kykC53i, 2026-09-04T00:43Z): this round's dispatch for #14168 (maintainer ruling A of 2026-09-02 —FieldSchemagains avalueDomainslot whose vocabulary is exactlySpecifierValueDomainSchema's three members, shared by reference) touchespackages/spec/src/data/field.zod.ts, a declaredRestart-touchtrigger file of this hold. Notification only, per this card's R5/R6 precedent: no rider work from this hold is taken into the dispatch. Honest characterisation of the touch: a constraint slot on string-storing fields whose vocabulary includesiso_4217_currencyas a value domain (membership of a currency CODE) —currencyConfig, thecurrencyfield type,currency-fraction-digits.tsand the analytics chain are untouched, and no exchange-rate or home-currency surface moves. TheRestart-when:legs re-read onorigin/main97a22639at 2026-09-04T00:43Z all still read false: norefs/*v18*on origin,packages/specat 17.2.0, no.changeset/pre.json, nocontent/docs/releases/v18.mdx. The hold stands unchanged.Generated by Claude Code
claude commentedon Sep 4, 2026
H17 landing notification (
domain:specseat, sessionsession_0174WZTU6XcFcS7g2kykC53i, 2026-09-04T04:09Z): the dispatch notified at 00:43Z (comment 5534029200) has landed — PR #15133 merged at 04:05:20Z, merge commit1d7e76a6, touchingpackages/spec/src/data/field.zod.ts, a declaredRestart-touchtrigger file of this hold. Landed shape, characterised honestly:FieldSchema.valueDomain, a write-time membership constraint ontextfields whose vocabulary includesiso_4217_currency(membership of a currency CODE);currencyConfig, thecurrencyfield type,currency-fraction-digits.tsand the analytics chain are untouched, and no exchange-rate or home-currency surface moves. Notification only: no rider work from this hold was taken. TheRestart-when:legs re-read onorigin/main5c584231aat 04:06Z all still read false: norefs/*v18*on origin,packages/specat 17.2.0, no.changeset/pre.json, nocontent/docs/releases/v18.mdx. The hold stands unchanged.Generated by Claude Code
23 remaining items
objectstack-fleet commentedon Oct 28, 2026
Epic opened ·
pm:on-hold→pm:epic· director seat · summon #53 ·session_01QSeKYo7qYsX6HsAneHBMP2· 2026-10-28T09:48ZRuling 6465431966 on #27119 (Q1 = 乙-现在, maintainer 「同意立专题卡」). The body is rewritten as the epic parent (shape C′, the rulings executed, the declared territory, the 17 children by release, the pairing rule); the earlier text stays in the body's revision history. Title rewritten in the same act. Thread-read: 6462572182.
Children filed in this act: R1 #27182 #27183 #27184 #27186 #27187 #27188 #27189 · R2 #27185 #27190 #27198 #27191 #27192 #27193 #27194 #27196 · R3 #27195 #27197. Spec and seam children (#27182
pm:queue; #27184 #27187 #27191pm:blocked) carrydomain:specfor the spec seat; the rest carrypm:epicfor the epic PM,pm:blockedwhere aBlocked-by:line stands. Prerequisite outside the tree: #27157.Next: the maintainer summons
/pm-dispatch epic:#8345; that session registers its ID in the body and dispatches from #27183 and #27182.objectstack-fleet commentedon Oct 28, 2026
Epic PM · subtree triage and plan · 2026-10-28T11:20Z
Session
session_01Utp6CbTZrFqRYNgjSaSbN5(accountos-bill, seatepic:#8345). Authority: Bill (maintainer), project thread, 2026-10-28 — 「其他同意你的建议,开始派发」, 「你可以自己打domain」, 「epic的卡你统一派」, 「并发可以5」, 「你自主完成后续阶段」, and for the ADR 「写 adr 你现在没有 fable,先用 opus 写,10 小时后用 fable 复审。」Domain (the landing package;
pm:epicstays on all): #27183domain:skills(governed ADR) · #27185 #27186 #27190 #27192 #27193 #27194 #27195 #27198domain:server· #27188 #27196domain:ui· #27189 #27197domain:devx.Spec children moved into the subtree: #27184 #27187 #27191 gain
pm:epic(keepdomain:spec,pm:blocked, theirBlocked-by:); the epic PM dispatches them. #27182 stays with the spec seat that claimed it (claim 6467480691); the epic follows it to merge.Staging (each stage releasable on its own): stage 0 #27157 (other seat), #27182 (spec seat), #27183 (claimed here, 6467611450). R1: #27184 first; once its PR is up, #27186 #27187 #27188 build on its branch in parallel, #27189 alongside; all R1 PRs merge in one window, then one release. R2 waits for the customer's consolidation terms; #27191 and #27185 may be drafted early. R3: #27195 #27197. Concurrency cap 5.
docs(adr): ADR-0144 takes the three should-fixes of contract review 6…
objectstack-fleet commentedon Oct 29, 2026
epic:#8345#1 · os-bill · session_01Utp6CbTZrFqRYNgjSaSbN5
Open question for the maintainer: ADR-0144 Open item 12 (epic PM, 2026-10-29T01:30Z)
Should today's cross-currency arithmetic between
fixedfields of different codes be refused? There are two shapes:currencycontradicts afixedfield's code, andfixedcodes (e.g. afixedUSD amount minus afixedEUR amount), which ADR-0144 Context §1 counts among today's silently wrong numbers.Ruling
6465431966(#27119) did not decide this, because its C′ sentence names record-mode fields only. For R1 the epic PM confined #27187 / PR #27338's compile guards to record-mode amounts (decision6485365183on #27187; tree evidence #27338507ed8f9). Refusing thefixed-only shapes would be a narrowing of what compiles today (BREAKING for@objectstack/service-analytics), so it needs the maintainer's word. #27338's first draft (fea128ce) leaned toward refusing both. That lean is quoted here, not adopted. Nothing in R1 waits on the answer.docs(adr): ADR-0144 takes the three should-fixes of delta review 6485…
objectstack-fleet commentedon Oct 29, 2026
epic:#8345#1 · os-bill · session_01Utp6CYKQd1fNzSJRDLNwnW
Ruling confirmed: ADR-0144 Open item 12 (fixed-versus-fixed cross-currency arithmetic in dataset measures) · letter A · maintainer chose 「A 拒收,R1 之后单独立卡」 on the decision card in the project review thread 「决定 fixed 字段跨币种计算」 2026-10-29T02:42Z
Recorded by the review thread's session
session_01Utp6CYKQd1fNzSJRDLNwnW(project thread), answering the open question6485374827above. The maintainer read the six-section brief (options A / A′ / B / C / D, four axes, confidence gaps) and answered with the letter; the brief is kept in the project files (decisions/fixed-fixed-跨币种-呈批.md). ⛔ Not a claim; this comment implements nothing.A — both fixed-only shapes are refused at dataset compile, as their own card after R1.
currencywhose code differs from the aggregated field'sfixedcode →DATASET_INVALID/ 400, naming the fix (delete the measure'scurrency; the column takes the field's code). A measurecurrencythat restates thefixedcode stays accepted.fixedcodes →DATASET_INVALID/ 400, naming the fix (derive from measures in one currency, or drop the operand in the other). A non-monetary operand (acount) is not compared.fixedcode against the tenant's currency (not known at compile — "cannot answer, do not block"); a measurecurrencyover adynamicfield (the explicit code is the top of the [Decision] Currency, all of it: resume multi-currency (#8345) and in what shape, and one rule for an amount whose currency is not known (Studio's USD, the template's USD,fixed's CNY, the example's USD) #27119 Q2 X chain and stays legal). The record-mode arms are already in PR feat(spec,service-analytics): record-currency analytics — grouped answers name a per-row currency, the cube door refuses an ungrouped amount aggregate, compile guards on measure currencies #27338.compileDatasetcall (registration and request), so the refusal reaches boot registration,queryDatasetand the Studio draft preview alike.Execution parameters, fixed in this ruling:
fea128ce(measure-currency-coherence.tsfixed arms, the two moved pins incurrency-mode-relay.test.tsandquery-dataset.test.ts, the guard tests), dropped at507ed8f9.Clause-②: yes (narrowing)·Metadata-protocol: narrowed·@objectstack/service-analyticsminor with a BREAKING paragraph (the fixed group refusesmajorbefore GA,check-changeset-no-major) · ADR-0087 markernot-required (no-migration-prescription)— the prescription is the refusal message, no stored shape converts.fixed-modecurrencyConfigwith nodefaultCurrencymaterialises'CNY'— require the code, drop the default (narrowing; #27119 Q2 X, G3) #27157 / PR fix(spec)!: a fixed currency config needs its code — currencyConfig.defaultCurrency loses its CNY default #27218: the full dogfood battery on the final head, and a survey of in-tree dataset metadata for both shapes (0 expected inexamples/**; a deployed tenant's stored datasets cannot be surveyed from the repository and the PR body says so).os-decision-facets
formula-return.ts),record 模式的两条护栏已在 feat(spec,service-analytics): record-currency analytics — grouped answers name a per-row currency, the cube door refuses an ungrouped amount aggregate, compile guards on measure currencies #27338,A 把 fixed 模式拉平,不留双重标准。currency是 AI 作者的常见动作(G1 Studio 曾自动塞 USD,G4 示例曾被照抄);A 下写错立刻看到错误与改法。compileDataset腿上加两条分支;不与 R1 配对。Prior rulings read: 6465431966 ([Decision] Currency, all of it: resume multi-currency (#8345) and in what shape, and one rule for an amount whose currency is not known (Studio's USD, the template's USD,
fixed's CNY, the example's USD) #27119 Q1, C′ names record mode only) · 6464202770 ([Decision] Currency, all of it: resume multi-currency (#8345) and in what shape, and one rule for an amount whose currency is not known (Studio's USD, the template's USD,fixed's CNY, the example's USD) #27119 Q2 X) · measurement round 6041378776 Q6 (recommended A) · design record 6464438764 §7 · workload 6464936321 M0-3 · epic PM decision 6485365183 (analytics seam: grouped results carry a per-row currency; cube door refuses an ungrouped aggregate over a record-mode field; guards on today's surface (multi-currency M0-3, epic #8345) #27187) · ADR-0144 Open item 12 · precedent spec(field):fixed-modecurrencyConfigwith nodefaultCurrencymaterialises'CNY'— require the code, drop the default (narrowing; #27119 Q2 X, G3) #27157 / PR fix(spec)!: a fixed currency config needs its code — currencyConfig.defaultCurrency loses its CNY default #27218 (narrowing kit).Generated by Claude Code
objectstack-fleet commentedon Oct 29, 2026
epic:#8345#1 · os-bill · session_01Utp6CbQvr4k5jUAV39NCn1
Ruling confirmed: ADR-0144 new open item (an existing
dynamic/fixedamount field switched torecordmode on an object that already holds rows) · letter B · maintainer chose 「B 放行,欠显式回填(荐)」 on the decision card in the project review thread 「决定切换 record 模式时的旧数据」 2026-10-29T08:39ZRecorded by the review thread's session
session_01Utp6CbQvr4k5jUAV39NCn1(project thread), answering the escalation in PR #27339's contract review6490309706③ ("Escalated to the epic PM … Whether that mode switch is refused while such rows exist, or a backfill operation is owed (the D7 parameter 1 shape), is decided nowhere in the ADR"). The maintainer read the six-section brief (options A / B / B′ / C / D, four axes, confidence gaps) and answered with the letter; the brief is kept in the project files (decisions/record-模式切换存量行-呈批.md). ⛔ Not a claim; this comment implements nothing.B — the switch is allowed; it owes an explicit, audited backfill of the code; no row is ever refused for resting.
What stays as PR #27339 / #27340 / #27338 have it at
cf5be508(the write side is the ADR-0113 D1 non-regression invariant applied to the record pair):ERR_CURRENCY_CODE_REQUIRED/ 400, prescription first) on the next write that touches the amount or the code.nullgroup of a grouped aggregate, and is outside every currency-paired filter — until it is backfilled.What the ruling adds, as its own card after R1, ⛔ landed before R2 (the R2 home projection has no code to convert such a row, and a consolidated
sumover the home field would silently omit it):@objectstack/objectql, modelled onsummary-backfill.ts: for one object and onerecord-mode amount field, write an operator-supplied ISO 4217 code into every row whose amount is not blank and whose code field is blank. The code is given explicitly (--code USD); ⛔ it is never derived from the retireddefaultCurrency, the tenant'slocalization.currencyor anything else (D8 rule 4, [Decision] Currency, all of it: resume multi-currency (#8345) and in what shape, and one rule for an amount whose currency is not known (Studio's USD, the template's USD,fixed's CNY, the example's USD) #27119 Q2 X). A row that already holds a code is never touched. Dry run by default,--applyto write, idempotent (a second run finds nothing), per-row counts (written / skipped: code present / skipped: amount blank). Nosys_migrationflag: nothing gates on the run.os migrate record-currency-codes --object <o> --field <amount> --code <ISO> [--apply]in@objectstack/cli, the same split assummary-backfill.ts/os migrate summary-nulls.packages/cliis the other lane: filed as aSeam:cross-lane half of the card.detectDestructiveObjectChanges(packages/metadata-protocol/src/protocol.ts, thesaveMetaItemPhase 3a-destructive gate) gains one finding,currency_mode_to_record— previouscurrencyConfig.currencyModenotrecord, nextrecord, field stored — answered as the existing HTTP 409destructive_changewith the existingforceremedy; the message names the three consequences above and the command in 2. It reads no rows, like its siblingsfield_type_changeandfield_required_no_default. It fires only where a previous version exists (RESTPUT /meta, Studio, package publish); a code-declared package registered at boot has no previous version to diff, and ⛔ no boot-time refusal is added — a registry that refuses on data state takes the application down after a deploy.skills/**(Tier H, one line): switching a stored field torecordleaves existing rows codeless; run the backfill.os migrate recompute-home-amounts --object X [--since DATE] [--apply]— report then apply; rows with a missing rate are listed and skipped (multi-currency M2-3, epic #8345) #27193 (R2 recompute): rows with a blank code are reported as their own class, apart from rows with a missing rate (parameter 1).Declarations (the card's to confirm against the tree): the engine function is additive; the 409 finding is a new member of an existing refusal face — the Clause-② reading of #27339's review (registering a refusal member widens the face) applies,
Clause-②: yes (widening),Metadata-protocol: none(what an author can write is unchanged;forcelifts the acknowledgement). Not judged, left open: how a cloud-managed tenant without a CLI reaches the backfill (an admin route or Studio action, M3 or later); whether the backfill writes throughengine.updateor at the driver assummary-backfill.tsdoes (the card follows the precedent it picks and says why).Not chosen: A (refuse while rows exist — no reliable refusal point on the code-package path; a Studio-only refusal is a double standard and pushes authors to the invisible copy-by-hand workaround); B′ (backfill without the 409); C (status quo — R2 consolidation silently low); D (derive the code at the switch — D8 rule 4).
os-decision-facets
required同类,平台为后者已有 409;B 在保存那一刻点名后果与命令,写入守卫触碰时带处方拒收。os migrate命令族 / Phase 3a finding 列表),零新键、零新门禁、零新 wire 码;唯一跨车道的是 cli 半,按Seam:卡。Prior rulings read: 6465431966 ([Decision] Currency, all of it: resume multi-currency (#8345) and in what shape, and one rule for an amount whose currency is not known (Studio's USD, the template's USD,
fixed's CNY, the example's USD) #27119 Q1, C′; D7 parameter 1) · 6464202770 ([Decision] Currency, all of it: resume multi-currency (#8345) and in what shape, and one rule for an amount whose currency is not known (Studio's USD, the template's USD,fixed's CNY, the example's USD) #27119 Q2 X, nothing guesses) · 6486427200 ([Epic] multi-currency (shape C′): record currency, dated exchange rates, write-time home-currency projection — 17 children, R1/R2/R3 release pairing (ruling 6465431966) #8345 Open item 12, letter A) · feat(objectql): record-currency guards — blank code refuses the write; ungrouped sum/avg/min/max over a record-mode amount refused; summary roll-up over one refused at registration #27339 contract review 6490309706 ③ · ADR-0113 D1 · ADR-0027 MigrationPlan (field_required_no_default⇒ default or backfill) · ADR-0144 D5, D7, D8 rule 4, D9, Consequences, Open item 8 · precedentssummary-backfill.ts/os migrate summary-nulls,os migrate activity-changed-fields.Generated by Claude Code
os-bill commentedon Oct 30, 2026
epic:#8345#1 · os-bill · session_01Utp6CZQpM1MNKd4cQai54c
Ruling confirmed: R2 development starts now; only the R2 release waits for the customer's consolidation terms · letter A · maintainer chose 「A 现在启动 R2 开发」 on the decision card in the project review thread 「查清多币种 #27579 为何排在发版后」 2026-10-30T12:15Z
Recorded by the review thread's session
session_01Utp6CZQpM1MNKd4cQai54c(project thread). The brief is kept in the project files (epic-8345/post-r1-status-2026-10-30.md). ⛔ Not a claim; this comment implements nothing.What the maintainer asked (2026-10-30T11:26Z): why the epic's follow-ups wait for the 18.3.0 release. Findings: ruling 6486427200 required only that #27579 come after R1 lands (「ships in whichever Version Packages release it is ready for」); the "after the release" hold was the epic PM seat's own scheduling, with no technical or process ground, and it was overtaken by the lane — #27579 landed as PR #27991 (2026-10-30T07:17Z) with docs follow-up PR #28015. The pairing rule in ruling 6465431966 constrains releases, not development; the R2 gate in that ruling's commitment line is the customer's terms (home currency, rate source, which date drives the rate).
A — build R2 now, release R2 when the customer confirms the terms.
homeAmount: { field, rateDate, rateField? }on a record-mode amount — the stored home-currency projection declared by pointer (multi-currency M2-1, epic #8345; released with M2-2) #27191 (homeAmountpointer,domain:spec) goes first in the spec seat's queue; its shape does not depend on the customer's terms (rateDateis author-declared).sys_import_jobservessys_exchange_rate(CSV of currency, rate, effective_date); add the importer only if it does not (multi-currency M1-2, epic #8345) #27190 is released to thedomain:serverlane (it carriespm:epic+pm:queuetogether, the same hygiene issue triage fixed on service-analytics: refuse fixed-versus-fixed cross-currency measures at dataset compile (multi-currency, epic #8345) #27579 in 6515345174).localization.currencyonce asys_exchange_raterow or ahomeAmountdeclaration exists; Setup shows what uses it (multi-currency M1-3, epic #8345) #27198 and objectql: write-time home projection — rate lookup by document date, decimal arithmetic, minor-unit rounding, missing rate refuses, computed fields read-only (multi-currency M2-2, epic #8345) #27192 build on spec(field):homeAmount: { field, rateDate, rateField? }on a record-mode amount — the stored home-currency projection declared by pointer (multi-currency M2-1, epic #8345; released with M2-2) #27191's branch in parallel once its PR is up, as R1 did on feat(spec):currencyMode: 'record'+currencyField— a record-mode amount points at a sibling ISO 4217 code field (multi-currency M0-1) #27268; cli:os migrate recompute-home-amounts --object X [--since DATE] [--apply]— report then apply; rows with a missing rate are listed and skipped (multi-currency M2-3, epic #8345) #27193, migrate: adding ahomeAmountfield to an existing object is the normal add-column path; backfill = recompute — one proving test (multi-currency M2-4, epic #8345) #27194, ui: home field read-only with "converted at RATE on DATE"; live preview when a rate exists; Studio editor forhomeAmount(multi-currency M3-2, epic #8345; the read-only display is released with M2) #27196 follow their Blocked-by lines.invoicegoes multi-currency (code field, record amount, home field, document date), seeded rates, a rate-sync flow template, a platform-checklist item and a browser dogfood run (multi-currency M3-3, epic #8345) #27197) and the rate-lookup date in objectql: write-time home projection — rate lookup by document date, decimal arithmetic, minor-unit rounding, missing rate refuses, computed fields read-only (multi-currency M2-2, epic #8345) #27192 only, which is the one rework risk.Ruling-ref: this comment.
Generated by Claude Code
countthat names an amount field, refusing an amount-per-row ratio as cross-currency (multi-currency, epic #8345) #28194os-bill commentedon Oct 31, 2026
Ruling: 18.3.0 (Version Packages #26517) and the R2 core · Q1 letter A′ · Q2 letter B · maintainer 「同意」 (os-bill, project thread 「决定 18.3.0 是否带出半成品 R2」, 2026-10-31T05:03Z, on the v2 brief recommending A′ and B) · 2026-10-31T05:1xZ
Question 1 — how 18.3.0 ships against R2. The brief's v1 premise (the
homeAmountkey onmainwithout its engine, ADR-0144 D9's half-state) was overtaken on 2026-10-31: the home-currency lock PR #28297 is ready with auto-merge (contract review PASS 6538875208, seat ACCEPT 6538881146) and the write-time projection PR #28302 passed its contract review with no must-fix (6539117549). Ruled A′:main, thenrefresh_version_pris dispatched and the maintainer merges chore: version packages #26517 and approves thereleaseenvironment. 18.3.0 therefore carries R1 and the R2 core together:sys_exchange_rate(platform-objects:sys_exchange_rate{ currency, rate, effective_date, source } — tenant-scoped, admin-only, audited; Setup list view (multi-currency M1-1, epic #8345; released with M2) #27185),currencyConfig.homeAmount(spec(field):homeAmount: { field, rateDate, rateField? }on a record-mode amount — the stored home-currency projection declared by pointer (multi-currency M2-1, epic #8345; released with M2-2) #27191), the write-time home projection (objectql: write-time home projection — rate lookup by document date, decimal arithmetic, minor-unit rounding, missing rate refuses, computed fields read-only (multi-currency M2-2, epic #8345) #27192) and the home-currency lock (service-settings: locklocalization.currencyonce asys_exchange_raterow or ahomeAmountdeclaration exists; Setup shows what uses it (multi-currency M1-3, epic #8345) #27198). No declaration ships without the engine that fills it; D9's pairing rule holds as written.localization.currency, the rate table'ssourcevalues, the author'srateDatepointer — and the engine hard-codes none of them; the customer has no R2 rows to recompute. R2 development continues as ruled.os migrate recompute-home-amounts --object X [--since DATE] [--apply]— report then apply; rows with a missing rate are listed and skipped (multi-currency M2-3, epic #8345) #27193 (recompute), import: verifysys_import_jobservessys_exchange_rate(CSV of currency, rate, effective_date); add the importer only if it does not (multi-currency M1-2, epic #8345) #27190 (import check) and ui: home field read-only with "converted at RATE on DATE"; live preview when a rate exists; Studio editor forhomeAmount(multi-currency M3-2, epic #8345; the read-only display is released with M2) #27196 (home field read-only display) are R2.1: released in a later Version Packages, none of them a half-state (the home and rate fields arereadonlyand render as such today).⛔ not released alone … waits for the customer's confirmationsentences in.changeset/27192-*and.changeset/27198-*are reworded to the R2-core pairing (they ship as CHANGELOG text), and the "ISO 4217 minor units" wording follows review should-fix S2 (the table is CLDR's digit counts).Clause-②: yes (widening)stands: the lock and the rate table release in the same version.homeAmount, holding feat(objectql): store a record-mode amount converted into the home currency on every write (multi-currency M2-2) #28302 in draft until 18.3.0 published — a release switch in code guarding an engine already written and reviewed); B (hold chore: version packages #26517 until the customer confirms — 674 pending changesets and R1 wait for an undated event); A (merge chore: version packages #26517 before feat(objectql): store a record-mode amount converted into the home currency on every write (multi-currency M2-2) #28302 — the half-state D9 forbids).Question 2 — the rate day of a
datetimedocument date (#28302 open question 2, escalated by the contract review). Ruled B: adatetimerateDatevalue is read as the calendar day in the organization'slocalization.timezone(defaultUTC, so an organization on the default is unchanged), not the UTC day. Execution:HomeAmountServinggainstimezone(organizationId)besidehomeCurrency(organizationId), read through the same settings bridge (getMany('localization', …)), never from the request context, so REST, import and flow writes pick the same day;documentDateOf(value, timezone)formats withIntl.DateTimeFormat('en-CA', { timeZone })(the readingautonumber-format.tsalready uses); adatevalue is its own day. Reason:localization.timezoneis already whattoday()and analytics date bucketing resolve against (its manifest, lines 9–14), and under the UTC reading an organization on UTC+8 takes the previous day's rate for every document stamped 00:00–08:00 local while reports bucket it into the local day; the day is stored semantics, cheaper settled before release than recomputed after. Lands in #28302's fix round; the ADR amendment (review S4) records it. Not chosen: A (UTC now, organization timezone as a later card — a semantic change over stored rows once released). The skills/docs steer toward adatefield is no longer needed.一句话:18.3.0 等引擎 #28302 与币种锁 #28297 落地后一起发出(R2 核心随 R1 发,#27193/#27190/#27196 为 R2.1);datetime 单据日期按组织
localization.timezone的日历日取汇率。维护者原话「同意」(两问均按呈批推荐:A′ / B)。Prior rulings read: 6465431966(C′ 与 D1–D9)、6522614678(R2 开发现在、发布等客户——本裁决改其发布门一条)、6469382727(scale 12)、6486427200、6492000994。呈批全文:/mnt/project-files/decisions/26517-发版带出R2半成品-呈批.md(项目文件)。Execution after the ruling. The epic PM (
session_01Utp6CbTZrFqRYNgjSaSbN5) carries both into #28302's fix round and the ADR-0144 amendment PR; #28297 may merge now; once #28302 is onmain, dispatchrefresh_version_prand tell the maintainer #26517 is ready to merge. Ledger row in the project's rulings file.Generated by Claude Code
objectstack-fleet commentedon Oct 31, 2026
epic:#8345#1 · os-bill · session_01Utp6CbTZrFqRYNgjSaSbN5
Sign-off brief: epic PM seat · 2026-10-31T06:55Z
The seat is vacant. The ledger is in this card's body (the "Seat ledger at sign-off" section).
check-handoverexited 0: no unreleased claim, and no decision outside the inbox.localization.currencyonce asys_exchange_raterow or ahomeAmountdeclaration exists; Setup shows what uses it (multi-currency M1-3, epic #8345) #27198 lock), PR feat(objectql): store a record-mode amount converted into the home currency on every write (multi-currency M2-2) #28302 (objectql: write-time home projection — rate lookup by document date, decimal arithmetic, minor-unit rounding, missing rate refuses, computed fields read-only (multi-currency M2-2, epic #8345) #27192 projection, with the timezone day from ruling 6539345871 B). Each has a contract review and a seat ACCEPT on its final head.pm:dispatchedwas removed from docs(adr): ADR for multi-currency — record currency, dated rates, write-time home projection (Q0–Q4 and parameters 1–4 as ruled on #27119); dated note on ADR-0104 (epic #8345, lands in R1 first) #27183, objectql: write-time home projection — rate lookup by document date, decimal arithmetic, minor-unit rounding, missing rate refuses, computed fields read-only (multi-currency M2-2, epic #8345) #27192 and service-settings: locklocalization.currencyonce asys_exchange_raterow or ahomeAmountdeclaration exists; Setup shows what uses it (multi-currency M1-3, epic #8345) #27198, andpm:blockedfrom cli:os migrate recompute-home-amounts --object X [--since DATE] [--apply]— report then apply; rows with a missing rate are listed and skipped (multi-currency M2-3, epic #8345) #27193 and analytics: consolidated measures over the home field work unchanged (proof); a metric over a record-mode field must name the home field or group by code (multi-currency M3-1, epic #8345) #27195, whose blockers have landed.domain:speccard, both listed in the body.