Repository navigation
Commit b7075d9
<!-- claude-projects-attribution: {"github_login":"os-bill"} -->
_Requested by **Bill** · [project
thread](https://claude.ai/code/project/chan_016iMXWSZDzqWRWvWzdNo8wg?thread=cmsg_016iMXWSZDzqWRWvWzdNo8wg8JgVyS9BQnLALTRES6fash)_
epic:#8345#1 · os-bill · session_01Utp6CZWjnSeed8H4dMjt9d
Fixes #30102
Supersedes #30174 (same branch and head `a0c8d7ca`, body unchanged;
reopened through the fleet relay, which the dispatch protocol requires
for a pull request).
Ruling-ref: 6539345871
Not release-paired: `docs/adr/**` only, no changeset — the diff
publishes nothing from any released package (`skip-changeset`).
Clause-②: no
Metadata-protocol: none
## 维护者速读
- **改了什么:** ADR-0144 开放项 2、3、4、6、9 各加一条 *Note (2026-11-04)* 标为已定:2
取单据日当天或之前最近一条汇率,datetime 按组织 `localization.timezone` 取日历日(裁决 6539345871
B);3 精确小数、除法、一次远离零舍入到本位币 **CLDR** 小数位,汇率原样存不舍入;4 未设本位币拒写
`ERR_HOME_CURRENCY_UNSET`,不默认;6 同币种汇率 1 不查表;9 三个错误码已入 ledger。D9 与 TL;DR
记下裁决 A′(18.3.0 把 R1 与 R2 核心一起发出,#27193/#27190/#27196 为
R2.1);Context/Consequences 两处把「ISO 4217 最小单位」改为 CLDR 小数位;状态块「the only
ledger additions」删去,改为三个码。开放项 13 未动。
- **为什么改:** ADR 每有答复就要修订;main 上这几项仍写着「未决」、ledger 仍写「两个码」,与 18.3.0
已发出的代码不一致。
- **风险与回滚:** 纯文字,不动代码、schema、skills;每条注记按 `file#symbol` 引用
main(`f68b47ca`)上的树,符号锚门禁全部解析;Tier H(`docs/adr/**`)。回滚即撤 PR。
- **先看:** Open items 2、3、4、6、9 末尾的注记,再看 D9 末尾的注记与状态块「Builds on」一行。
- **两分钟验证:** `pnpm check:adr-anchors`、`pnpm check:adr-index`、`pnpm
check:adr-symbol-anchors`、`node scripts/check-adr-links.mjs` 均退出 0。
- **需要你做的:** Tier H:席位跑 CONTRACT_REVIEW_TIER 复审并 ACCEPT 后,由 `os-zhuang`
或 `hotlong` 在该 head 批准。
## What changes
One file, `docs/adr/0144-…`, eleven edits, each in the dated-note form
PR #28181 used for Open items 11–13. Every claim about behaviour cites
the tree on `main` at `f68b47ca` by `file#symbol`, read for this PR, not
recalled; every landing cites the pull request and its merge commit.
**Open items (the Task list's first bullet):**
- **Item 2 — which rate row.** Settled as workload row M2-2 read it: the
organization's `sys_exchange_rate` row for the record's currency with
the latest `effective_date` on or before the document date; a later row
never applies; none in force refuses `ERR_EXCHANGE_RATE_MISSING`.
Evidence: the `find` under `$lte` / `desc` / `limit: 1`, as a system
read in the row's own organization (`engine.ts#homeAmountServing`); a
non-positive rate counts as missing and the read is memoized per
(organization, currency, day)
(`home-amount-projection.ts#projectHomeAmounts`,
`#memoizeHomeAmountServing`). **Ruling 6539345871 letter B** is recorded
here: a `datetime` document date is its calendar day in the
organization's `localization.timezone`, UTC when unset or unknown, never
the request zone (`#documentDateOf`); not chosen: A. The blank-date
`VALIDATION_FAILED` / `required` refusal is named. Review 6539117549 and
its delta 6539668963 are cited.
- **Item 3 — arithmetic and rounding.** Settled with one correction to
the item's own sentence: the digit count is CLDR's, not ISO 4217's.
Amount ÷ rate in exact scaled-decimal (`BigInt`), **rounded once, half
away from zero** (`1.005` → `1.01`, `-0.125` → `-0.13`) to the home
currency's fraction digits, stored as the bare number ADR-0104 D1
requires (`#divideToPlaces`, `#divideRoundHalfAwayFromZero`,
`#toScaledDecimal`); **the rate is stored unrounded** so the home amount
reproduces from the stored pair; a declared `scale` on the rate field
reaches display only because every numeric column takes the one
`decimal(65, 30)` representation
(`numeric-column-representation.ts#numericColumnFor`), and the spec-side
refusal of a scale below 12 is named as spec-lane work, not decided.
`CURRENCY_FRACTION_DIGITS` is CLDR `currencyData` (IQD 0 vs 3; HUF, COP,
IDR, PKR and other unused-minor-unit codes 0 vs 2), exported from
`@objectstack/spec/data` for this one reader; review F1 / should-fix S2
and the ruling's S2 order are cited.
- **Item 4 — unset home currency.** Settled by refusal:
`ERR_HOME_CURRENCY_UNSET` / 400 before anything is written, no default
(`#HomeCurrencyUnsetError`, thrown by `#projectHomeAmounts`); the
review's reasoning against D5's rejected fallbacks and D8 rule 5, and
why the code is its own ledger member, are recorded (6539117549 ③.1).
The settings bridge is named (`engine.ts#setHomeLocalizationResolver`,
`plugin.ts`): no service or unregistered key reads as unset and refuses;
any other settings error is the write's failure. The refusal is at
write, not registration. The lock (#27198, PR #28297 `291bf44a`) refuses
a change to a set value and passes the first setting of an unset one
(`localization-currency-lock.ts#localizationCurrencyWritePredicate`).
- **Item 6 — same currency as home.** Settled as the row read it: rate
`1`, no lookup, no rate row needed, still rounded, rate field stores `1`
(`#projectHomeAmounts`, the `code === home` arm).
- **Item 9 — refusal codes.** Settled: three codes in ADR-0112's
extension ledger under `@objectstack/objectql`
(`error-code-ledger.zod.ts#ERROR_CODE_LEDGER`):
`ERR_CURRENCY_CODE_REQUIRED` (#27186, PR #27339 `57c51aab`;
`record-currency-code.ts#RecordCurrencyCodeRequiredError`),
`ERR_EXCHANGE_RATE_MISSING` (`#ExchangeRateMissingError`, what its
message names) and `ERR_HOME_CURRENCY_UNSET`
(`#HomeCurrencyUnsetError`), the last two in PR #28302. The two
`VALIDATION_FAILED` reuses (`required` on a blank document date;
`invalid_value` on a divergent predicate update,
`#settleBulkHomeAmounts`) and the `validate()` preview
(`engine-references-and-master-detail.ts#previewHomeAmounts`,
`engine-validate.ts`) are recorded.
**Ruling 6539345871 letter A′ (second bullet):** a dated note at the end
of **D9**: 18.3.0 (Version Packages #26517, version commit `83d7e4ae`,
merged 2026-11-03) carries R1 and the R2 core together —
`sys_exchange_rate` (#27185, PR #27246 `194e66c0`),
`currencyConfig.homeAmount` (#27191, PR #28096 `73b72709`), the
write-time projection (#27192, PR #28302 `6762dd91`) and the
`localization.currency` lock (#27198, PR #28297 `291bf44a`), each named
in its package's `## 18.3.0` CHANGELOG section and on
`content/docs/releases/v18/18-3.mdx`; the pairing rule holds as written;
what changed is the release gate of ruling 6522614678 (letter A), in one
respect, with the ruling's reason; #27193 / #27190 / #27196 are R2.1;
the options not chosen (A, B, C). The **TL;DR** delivery bullet gets a
two-sentence note pointing at D9, since the claim's file surface lists
TL;DR and the bullet otherwise contradicts it.
**Rounding mode and the unrounded rate (third bullet):** in the Item 3
note, as above.
**CLDR, not ISO 4217 minor units (fourth bullet):** in the Item 3 note;
in **Context §1** (the ISO 4217 value-domain bullet, whose "no reader"
sentence gets a dated note: the values have their reader, and they are
CLDR fraction digits); and in **Consequences** ("may get their first
reader" — they did, as CLDR digits).
**"The only ledger additions" (fifth bullet):** the Status block's
"Builds on" line now reads three codes — a blank code, a missing rate,
an unset home currency (Open items 4 and 9) — registered in the ledger,
with a dated note saying what the sentence said before and why the
"only" claim is dropped. The **Evidence** line says where the 2026-11-04
notes were read (`f68b47ca`).
**Open item 13 (sixth bullet):** untouched. The seat reported PR #28128
S1 unruled at this head.
**Not touched:** code, `skills/**`, `.claude/**`, every other ADR,
`docs/adr/README.md` (`adr-index --report` says it is current: the
record's first status line did not change).
## Why
The record's Open items preamble says "This record is amended with each
answer." Items 2, 3, 4, 6 and 9 were answered by PR #28302 (its body's
"ADR-0144 open items settled here" and its two contract-review records),
and 18.3.0 shipped them on 2026-11-03; ruling 6539345871 amended the
release pairing (A′) and settled the `datetime` day (B) and ordered the
ADR amendment (review should-fix S4). On `main` the five items still
read as open, the Status block still says two ledger codes, and Item 3
and Context §1 still say ISO 4217 minor units where the tree reads CLDR
digits. Card #30102 carries this amendment from the predecessor's
sign-off ledger.
## Verification
Head `a0c8d7ca`: two docs commits on `claude/project-thread-b5ine2`,
branched from `origin/main` at `f68b47ca` — the amendment (`244f2ff0`)
and the contract review's two should-fixes (Provenance §1 names ruling
6539345871 and §3 the `f68b47ca` reading; the Open item 2 note quotes
the rate predicate verbatim). The four ADR checks below were re-run on
`a0c8d7ca`, all exit 0; the 21-command gate sweep and its `--ran`
reconciliation ran on `244f2ff0`, and the second commit changes prose in
the same file only.
- `pnpm check:adr-anchors` (self-test 133 assertions + full sweep): exit
0.
- `pnpm check:adr-index` (self-test 46 assertions + `--report`): exit 0,
`docs/adr/README.md` current.
- `pnpm check:adr-symbol-anchors`: exit 0 — every `file#symbol` this PR
adds resolves (the sweep reports 3107 anchors across 149 records, 0 line
anchors).
- `node scripts/check-adr-links.mjs`: exit 0 (979 relative links
resolve).
- `node scripts/check-commit-card-trailers.mjs --range
origin/main..HEAD`: exit 0.
- `node scripts/pm/dispatch-gates.mjs --commands <the ADR path>` derives
21 commands (13 by path, 8 whole-tree). Each was run with its exit code
captured before any pipe:
| Command | Exit |
|:--|:--|
| `node scripts/check-adr-links.mjs` | 0 |
| `node scripts/check-adr-links.mjs --self-test` | 0 |
| `node scripts/check-closing-keyword-parity.mjs` | 0 |
| `node scripts/check-closing-keyword-parity.mjs --self-test` | 0 |
| `node scripts/check-comment-mask-corpus.mjs` | 0 |
| `node scripts/ci/plan-test-core-shards.mjs --self-test` | 0 |
| `pnpm --filter @objectstack/lint run check:doc-formula-expressions` |
0 |
| `pnpm check:adr-anchors` | 0 |
| `pnpm check:adr-index` | 0 |
| `pnpm check:adr-symbol-anchors` | 0 |
| `pnpm check:ci-filter-parity` | 0 |
| `pnpm check:closed-ceremony-text` | 0 |
| `pnpm check:cross-package-test-inputs` | 0 |
| `pnpm check:doc-authoring` | 0 |
| `pnpm check:driver-memory-census` | 0 |
| `pnpm check:gitlink-declared` | 0 |
| `pnpm check:nul-bytes` | 0 |
| `pnpm check:pm-governed-merges` | 0 |
| `pnpm check:pm-prior-rulings` | 0 |
| `pnpm check:refd-timer-probe` | 0 |
| `pnpm check:watch-hint-literal` | 0 |
`pnpm --filter @objectstack/lint run check:doc-formula-expressions`
first exited **3** (PREREQUISITE NOT MET: `@objectstack/formula` and
`@objectstack/lint` unbuilt in a fresh clone; the gate measured
nothing); after `pnpm exec turbo run build --filter=@objectstack/formula
--filter=@objectstack/lint` it exited 0, the code recorded above.
`dispatch-gates --ran` reconciliation on `244f2ff0`: 21 derived families
accounted for, 21 run, 0 NOT-MEASURED, 0 UNRUN.
- Clone depth: this checkout is shallow (50 commits), so the merge
commits of #26517 (`83d7e4ae`, 2026-11-03T14:44Z), #28302 (`6762dd91`),
#28297 (`291bf44a`) and #28096 (`73b72709`) were confirmed against the
GitHub API and against the `## 18.3.0` CHANGELOG sections and
`content/docs/releases/v18/18-3.mdx` on `main`; `194e66c0`, `a3d24c99`,
`6dc06b2e` and `57c51aab` are in the clone or confirmed the same way.
- Model tier: `dispatch-gates --tier` derives the mandated tier for
`docs/adr/**` at effort xhigh; the text was drafted and read at that
tier.
## Human Minimum
- [x] 1. Schemas start as Zod; `packages/spec` holds no runtime logic.
(not touched)
- [x] 2. Every name I added uses the casing for its kind. (no names
added)
- [x] 3. No formatter ran; markdown only.
- [x] 4. One issue, one branch off an up-to-date `main`, one pull
request.
- [x] 5. A change that publishes carries a changeset: this diff
publishes nothing (`docs/adr/**` only), so `skip-changeset`; both
declaration lines are above.
- [x] 6. `packages/spec` touched: n/a.
- [x] 7. No hand edits to `content/docs/references/`,
`packages/*/CHANGELOG.md` or `content/docs/releases/`.
- [x] 8. Title, body and comments are in English (the 维护者速读 block and
quoted rulings are Chinese by the Communication rule).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01Utp6CaFs7UbZV5xCiu37Kk
---------
Co-authored-by: Claude <noreply@anthropic.com>
1 parent e826e77 commit b7075d9
1 file changed
Lines changed: 125 additions & 5 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
14 | | - | |
15 | | - | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
16 | 20 | | |
17 | 21 | | |
18 | 22 | | |
| |||
29 | 33 | | |
30 | 34 | | |
31 | 35 | | |
32 | | - | |
| 36 | + | |
| 37 | + | |
33 | 38 | | |
34 | 39 | | |
35 | 40 | | |
| |||
51 | 56 | | |
52 | 57 | | |
53 | 58 | | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
54 | 62 | | |
55 | 63 | | |
56 | 64 | | |
57 | 65 | | |
58 | 66 | | |
59 | 67 | | |
60 | 68 | | |
61 | | - | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
62 | 72 | | |
63 | 73 | | |
64 | 74 | | |
65 | 75 | | |
66 | | - | |
| 76 | + | |
| 77 | + | |
67 | 78 | | |
68 | 79 | | |
69 | 80 | | |
| |||
94 | 105 | | |
95 | 106 | | |
96 | 107 | | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
97 | 113 | | |
98 | 114 | | |
99 | 115 | | |
| |||
275 | 291 | | |
276 | 292 | | |
277 | 293 | | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
278 | 313 | | |
279 | 314 | | |
280 | 315 | | |
| |||
306 | 341 | | |
307 | 342 | | |
308 | 343 | | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
309 | 347 | | |
310 | 348 | | |
311 | 349 | | |
| |||
333 | 371 | | |
334 | 372 | | |
335 | 373 | | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
336 | 393 | | |
337 | 394 | | |
338 | 395 | | |
339 | 396 | | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
340 | 417 | | |
341 | 418 | | |
342 | 419 | | |
343 | 420 | | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
344 | 439 | | |
345 | 440 | | |
346 | 441 | | |
347 | 442 | | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
348 | 448 | | |
349 | 449 | | |
350 | 450 | | |
| |||
354 | 454 | | |
355 | 455 | | |
356 | 456 | | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
| 460 | + | |
| 461 | + | |
| 462 | + | |
| 463 | + | |
| 464 | + | |
| 465 | + | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
| 470 | + | |
| 471 | + | |
| 472 | + | |
| 473 | + | |
| 474 | + | |
| 475 | + | |
| 476 | + | |
357 | 477 | | |
358 | 478 | | |
359 | 479 | | |
| |||
0 commit comments