Repository navigation
Commit ca753c0
Fixes #20045
Clause-②: yes
`Clause-②: yes` is the claim's line (comment `5854472496`), copied as it
stands. The changeset carries `Clause-②: yes (narrowing)`, because
AGENTS.md makes a narrowing BREAKING and `check:adr-0087-registration`
reads the arm there. ⚠ This diff widens nothing: it only refuses a shape
that parsed before. Read against `scripts/pm/clause2-line.mjs`
(「本卡放宽接受集或扩大公开面吗」), the value that fits is `no (narrowing)`, which is
ruling B's own declaration on #19629. The dev report raises this as an
open question. Neither line was changed on the dev's own judgement.
Branch `claude/issue-20045-inline-currency-column-scale`, base
`1c8b320a89`, merged with `origin/main` `b09ce67870` as `4a6e8ed61a`
through `scripts/pm/os-regen-merge.sh`. Every reading below was taken at
head `4a6e8ed61a` unless it says otherwise.
## What changes
Triage direction: comment `5825687357`, option A. Triage read the card
as inherited from ruling B `5791803339` on #19629 (`scale` retired from
the currency field) and ruling 乙 `5805782503` on #19910 (「a currency's
ISO 4217 minor unit decides its display」).
1. `InlineGridColumnSchema` (`packages/spec/src/data/field.zod.ts`) now
refuses an authored `scale` on a column that declares `type:
'currency'`. The refusal is one custom issue at the column's `scale`,
and it applies to any value, `scale: 0` included, computed or not. The
message carries ruling B's shape:
- first sentence: "`scale` is not valid on a `currency` inline grid
column — delete the key." This is the field refusal's first sentence
with only the subject swapped;
- remedy: the currency's ISO 4217 minor unit (2 for USD, 0 for JPY, 3
for KWD) decides how the cell displays the amount and the width a
computed amount is rounded to. It names no other key.
- No alias and no grace window.
- `scale` on a `number` column, and on a column that declares no `type`,
is unchanged.
2. The `prefix` describe no longer says 「(default '¥')」. It now reads:
the symbol replaces the resolved currency's own symbol; there is no
default; it replaces the symbol only. `prefix` is still accepted. The
`scale` describe drops "numeric/currency" and names the currency
refusal.
3. ADR-0087: the D3 semantic entry
`18.inline-grid-column-currency-scale-refused` is added, and
`registry.ts` was regenerated with `gen:migration-registry`.
4. The changeset makes `@objectstack/spec` `minor`, with a BREAKING
banner, a FROM → TO table and the `registered` disposition marker.
5. `dropped-refinements.baseline.json` gains the new refinement's rows,
exactly as the build's ratchet printed them: `data/InlineGridColumn`
(root) plus one `…inlineColumns.element` site on each of the 12
published schemas that embed the column. The header totals moved with
the body: 208 schemas, 590 sites after the merge.
6. `content/docs/references/data/field.mdx` was regenerated
(`check:generated --fix`, which proved only `check:docs` stale).
## ADR-0087 disposition: why D3 only
- **A D3 entry is owed.** Ruling B on #17152 (`5615360777`, restated
`5634031140`) says 「D3 每家族一条,D2 可无损表达者亦然;D2 只承载数据修复」.
- **No D2 conversion.** The card inherits ruling B on #19629, which says
no alias and no grace window. Its own entry,
`field-currency-scale-refused`, is "NOT mechanically converted,
deliberately". A load-path conversion that dropped the key would accept
it on every load, which is the grace window the ruling refused. This
entry follows that precedent.
- **No `retired-keys/` row.** The key is not removed. It stays in the
walked shape and stays live on `number` columns, and a
`RETIRED_KEYS_BY_MAJOR` row naming a live key reds gate (b2).
## Premise, measured
- On `1c8b320a89`, `InlineGridColumnSchema` was a bare `strictObject`
with no refinement, and `scale` was declared for a "computed
numeric/currency result".
- The ablation below is the executable half of that reading. With the
new refinement short-circuited, all six refusal pins go red, because
every currency-plus-`scale` shape parses again.
- The objectui side was read by content:
- at objectui `origin/main` `25c7d58`, `GridField.tsx` has `function
currencyAdornment` ×1 and `function currencyWidth` ×1, and `c.prefix ||
'¥'` ×0;
- at this repo's `.objectui-sha` pin `f8a9d0fb0596`, it has `c.prefix ||
'¥'` ×2 and the `currency ? 2` default ×1 (see Acceptance notes).
## Mechanism hypothesis H1, measured
- `InlineGridColumnSchema` was at `:895`, a `strictObject`, with
`prefix` at `:924` and `scale` at `:938`. **Confirmed.**
- "Reuse the refusal sentence or the shared helper" was **partly
falsified**. No helper exists: ruling B's sentence is a string literal
inside `FieldSchema`'s `superRefine` (`:2295–2307` on base). That block
is outside this claim's file surface. So the column carries the sentence
and remedy in its own constant, `INLINE_GRID_CURRENCY_SCALE_REFUSAL`.
- A parity pin keeps the two refusals from drifting apart. It reads both
refusals and asserts that the first sentences match (subject swapped),
that both carry the same minor-unit clause, and that neither names
`currencyConfig` or `precision`.
- `FieldSchema`'s currency-precision anchor was not touched. It changed
on `main` during this run (#20011, PR #20209). It merged cleanly and is
disjoint from this diff.
## Authored instances (H2), census on `1c8b320a89`
- `git grep inlineColumns` over the whole tree gives 30 files. Exactly
**one** authored block:
`examples/app-showcase/src/data/objects/invoice.object.ts`, with 7
identity-only `{ name }` columns, 0 declaring `type` and 0 declaring
`scale`. This is the control: the same instrument counts 7 column
entries in that block.
- Platform objects, `skills/**`, `content/docs/**` prose and examples,
and JSON/YAML fixtures: 0 inline grid columns.
- Objectui at the pin: 0 authored `inlineColumns` fixtures. Its only
hits are the two renderer files.
- Test fixtures: 1 carried `scale: 2` on a currency column
(`inline-related-columns.test.ts`, the "every renderer-read key" case).
It was re-judged: `scale` was deleted there, and the key stays covered
by the identity-only computed `amount` column in the same fixture.
- Deployed metadata: **NOT MEASURED**, because no instrument reaches it.
## Tests, at head `4a6e8ed61a`
All heavy runs went through `scripts/pm/os-verify-lock.sh`, and each
verdict below is read from its VERDICT line.
- `@objectstack/spec` build: exit 0.
- `check:generated`: "All 15 generated artifacts are up to date".
- spec `vitest --project local`: **542 files passed; 15932 passed, 2
todo**.
- spec `typecheck`: exit 0 (`check:test-typecheck: OK — 53 file(s) / 255
error(s) / 142 pinned signature(s) held`).
- spec `vitest --project repo`: 32 files / 586 passed, at `4dbb609b1a`
before the merge. It was not re-run on the merged head, because the run
took 15m23s on a box under load 30 to 49. It is declared to CI.
- The new file `inline-grid-column-currency-scale-refused.test.ts`
covers:
- refusal through `FieldSchema`, `ObjectSchema` and the standalone
column, located at `…inlineColumns[i].scale`, with `code: 'custom'`;
- every value, computed or not;
- controls: a `number` column, an untyped column, `prefix` accepted, and
the remedy parsing and re-parsing unchanged;
- field/column shape parity;
- the two describes;
- the D3 entry being registered.
**Ablation**, from committed state `aa4b6ca14f`, run with
`scripts/ablation-replace.mjs`:
- The anchor `if (column.type === 'currency' && column.scale !==
undefined) {` was hit ×1 and went ×1 → ×0. The replacement `if (false &&
…` went ×0 → ×1. The blob changed from `147220988d04` to `ddf1ebbf0437`.
- Result: **6 failed | 22 passed** (28). All six refusal/parity pins
went red, and the controls stayed green, which is the expected
direction.
- Restore: blob `147220988d04` == HEAD, and `git diff HEAD` is empty.
- The subject is imported from `src` (`./field.zod`), so no dist rebuild
was involved.
**Gates.** `dispatch-gates.mjs --commands` was re-derived on
`4a6e8ed61a` and gave 111 families, the same list as before the merge.
`--ran` reconciliation: "111 derived famil(ies) accounted for — 109 run,
2 NOT-MEASURED".
- `NOT MEASURED: check:dual-build-cjs-loads`, reason: PREREQUISITE NOT
MET. 33 packages have no `dist/`, and only a full-repo build satisfies
that. This diff changes no entry point, export map or build config.
- `NOT MEASURED: check:type-check-debt`. Before the merge it exited 3
(`@objectstack/driver-turso` unbuilt). On the merged head, with that
package built, `--re-measure` began a workspace-closure `turbo build`
outside the verify lock. It was stopped by its recorded PID after 9
minutes, with no verdict. This diff changes no exported type:
`check:api-surface` is green, and `superRefine` keeps
`InlineGridColumnSchema` a `ZodObject`. It touches none of the four
DEBT-ledgered packages.
## Deviations
- **File surface.** `packages/spec/dropped-refinements.baseline.json` is
outside the claim's listed surface. The build refuses a new refinement
without it. The file is hand-edited on purpose and has no generator, and
its rows were applied exactly as the gate printed them, including the
merge-time header recount. The claim's surface names "its own
refinement", so this is reported as that refinement's mechanical
consequence, ⛔ not as scope growth.
- **Merge.** `origin/main` moved the same ledger's header totals
(#20204), which caused a textual conflict. It was resolved by recounting
the merged body.
## Acceptance notes
- **Reach of the refusal.** Only a DECLARED column `type` is judged. A
column that declares no `type` gets its type from the child field when
objectui hydrates it (`deriveMasterDetail.ts` `hydrateColumns`, which
spreads the authored column). So `{ name: 'amount', scale: 2 }` over a
currency child field still parses. The column schema cannot see the
child object. Once the objectui follow-up stops reading an authored
`scale` on currency columns, that key is ignored on such a column. That
lands on the objectui follow-up card (triage note 4), not here.
- **Pinned console vs this describe.** The new `prefix` describe ("No
default") is true of objectui `main` (`25c7d58`). The console bundled at
`.objectui-sha` `f8a9d0fb0596` still falls back to `¥` and rounds a
computed currency with no `scale` to 2. The describe becomes true of the
bundled console when the pin moves past objectui PR #10405. Deleting
`scale` loses no decimals under either console: the pin falls back to 2,
and `main` to the ISO minor unit. So no zero-decimal window opens.
- **Stale notes outside this surface**, recorded only (carrier: none):
- `packages/spec/liveness/field.json` → `inlineColumns.children.prefix`
/ `.scale` notes still cite `c.prefix || '¥'` and `c.scale ?? currency
default 2`;
- the `packages/spec/src/data/field-scale.ts` docblock sentence "The one
`2` that looks like a currency default belongs to an inline grid
COLUMN's rounding" describes the pre-objectui#10355 grid.
- **The objectui `GridField` follow-up** (drop the authored-`scale` read
on currency columns) is objectui's own card, per triage note 4. Nothing
in objectui changes here.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01QcAS3qiYYZNezaxZxaUdMV)_
---------
Co-authored-by: Claude <noreply@anthropic.com>
1 parent c02fa12 commit ca753c0
8 files changed
Lines changed: 388 additions & 10 deletions
File tree
- .changeset
- content/docs/references/data
- packages/spec
- src
- data
- migrations
- entries/semantic
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
206 | 206 | | |
207 | 207 | | |
208 | 208 | | |
209 | | - | |
| 209 | + | |
210 | 210 | | |
211 | 211 | | |
212 | 212 | | |
| |||
216 | 216 | | |
217 | 217 | | |
218 | 218 | | |
219 | | - | |
| 219 | + | |
220 | 220 | | |
221 | 221 | | |
222 | 222 | | |
| |||
356 | 356 | | |
357 | 357 | | |
358 | 358 | | |
359 | | - | |
| 359 | + | |
360 | 360 | | |
361 | 361 | | |
362 | 362 | | |
| |||
366 | 366 | | |
367 | 367 | | |
368 | 368 | | |
369 | | - | |
| 369 | + | |
370 | 370 | | |
371 | 371 | | |
372 | 372 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
5 | | - | |
6 | | - | |
| 5 | + | |
| 6 | + | |
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
| |||
71 | 71 | | |
72 | 72 | | |
73 | 73 | | |
| 74 | + | |
74 | 75 | | |
75 | 76 | | |
76 | 77 | | |
| |||
170 | 171 | | |
171 | 172 | | |
172 | 173 | | |
| 174 | + | |
173 | 175 | | |
174 | 176 | | |
175 | 177 | | |
| |||
254 | 256 | | |
255 | 257 | | |
256 | 258 | | |
| 259 | + | |
257 | 260 | | |
258 | 261 | | |
259 | 262 | | |
| |||
299 | 302 | | |
300 | 303 | | |
301 | 304 | | |
| 305 | + | |
302 | 306 | | |
303 | 307 | | |
304 | 308 | | |
| |||
338 | 342 | | |
339 | 343 | | |
340 | 344 | | |
| 345 | + | |
341 | 346 | | |
342 | 347 | | |
343 | 348 | | |
| |||
623 | 628 | | |
624 | 629 | | |
625 | 630 | | |
| 631 | + | |
626 | 632 | | |
627 | 633 | | |
628 | 634 | | |
| |||
658 | 664 | | |
659 | 665 | | |
660 | 666 | | |
| 667 | + | |
| 668 | + | |
| 669 | + | |
| 670 | + | |
| 671 | + | |
661 | 672 | | |
662 | 673 | | |
663 | 674 | | |
| |||
711 | 722 | | |
712 | 723 | | |
713 | 724 | | |
| 725 | + | |
714 | 726 | | |
715 | 727 | | |
716 | 728 | | |
| |||
727 | 739 | | |
728 | 740 | | |
729 | 741 | | |
| 742 | + | |
730 | 743 | | |
731 | 744 | | |
732 | 745 | | |
| |||
958 | 971 | | |
959 | 972 | | |
960 | 973 | | |
| 974 | + | |
961 | 975 | | |
962 | 976 | | |
963 | 977 | | |
| |||
980 | 994 | | |
981 | 995 | | |
982 | 996 | | |
| 997 | + | |
983 | 998 | | |
984 | 999 | | |
985 | 1000 | | |
| |||
1004 | 1019 | | |
1005 | 1020 | | |
1006 | 1021 | | |
| 1022 | + | |
1007 | 1023 | | |
1008 | 1024 | | |
1009 | 1025 | | |
| |||
1039 | 1055 | | |
1040 | 1056 | | |
1041 | 1057 | | |
| 1058 | + | |
1042 | 1059 | | |
1043 | 1060 | | |
1044 | 1061 | | |
| |||
0 commit comments