Skip to content

Commit 2742e53

Browse files
fix(spec): step 18's rationale gains the form-view-subform-columns-closed fragment (#21090)
Part of #20901 Clause-②: no One `STEP18_RATIONALE` fragment in `packages/spec/src/migrations/registry.ts`: id `form-view-subform-columns-closed`, `order` 54 (the highest at base `5dbeb7d7b7` was 53), inserted where its id sorts. It covers the form-view carrier closure, the D2 conversion `form-view-subform-columns-canonicalized`, and the identity-only sibling `inline-grid-column-identity-only-currency-scale-refused`. Each sentence restates the two entry sources and the conversion source. The list sits outside the generated markers and is hand-written; `gen:migration-registry` is a no-op on this diff. A `patch` changeset for `@objectstack/spec` is included because the rationale string ships in `dist/migrations`. This is review item 4 of the at-tier record `5921114874` on #20953. The card stays open, and the seat closes it by hand. ## Verification at head `8ebaf237c4` (merges origin/main `dff98c1f51`) - Rationale pins (`step18-rationale-merge`, `compliance-families-retirement`, `conversions-major18-merge`): 31 passed. `migrations.test.ts` and `inline-grid-column-carriers.test.ts`: 179 passed. Spec local suite: 588 files, 17318 passed. Spec typecheck: exit 0. - `check:generated`: all 15 artifacts are up to date after a spec build. The upgrade guide prints majors up to `PROTOCOL_MAJOR` (17), so it does not print step 18 and has no diff here. - `dispatch-gates --ran`: 82 derived, 82 run, 0 NOT-MEASURED. - Ablation (fragment removed, anchor 1 to 0, restored to the HEAD blob): no pin went red. The merge test pins the sort order and the joined text; no test pins this fragment by id. ## Acceptance notes - The review counted entries without a fragment of their own id: 207 of 253 at `06f079864a`. Fragments are per retirement family, so the number of families without one is not counted. `carrier:` none named. Noted here under the filing gate, with no `reach:` measured today. The generated guide prints major 17 only (`build-upgrade-guide.ts` loops to `PROTOCOL_MAJOR`, 17 at this head). Step 18's rationale does reach `os migrate meta --step`, whose default chain ends at major 18 (`packages/cli/src/commands/migrate/meta.ts`). There, a family without a fragment is left out of the paragraph, not misstated. This was read from the source and not measured at that door. --- _Generated by [Claude Code](https://claude.ai/code/session_01Sfe5YjBLwB9J3y8fvm2xq1)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent cf0346e commit 2742e53

2 files changed

Lines changed: 41 additions & 0 deletions

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'@objectstack/spec': patch
3+
---
4+
5+
fix(spec): protocol 18's migration rationale now covers the form view's inline grid columns and the identity-only currency `scale` refusal (#20901)
6+
7+
**`@objectstack/spec`**
8+
9+
- **`MIGRATIONS_BY_MAJOR[18].rationale` gains one fragment, `form-view-subform-columns-closed`.** It is the paragraph `os migrate meta --step` shows for the protocol 17 → 18 hop. The new sentences say that a form view's `subforms[].columns` now takes the strict `InlineGridColumnSchema` a relationship field's `inlineColumns` takes, that the conversion `form-view-subform-columns-canonicalized` respells a `{ field }` column as `{ name }` in stored rows and assembled artifacts while an author writing `field` is refused, and that `defineStack` refuses `scale` on a column that declares no `type` when its `name` is a `currency` field of a child object declared in the same stack (`inline-grid-column-identity-only-currency-scale-refused`).
10+
- Text only: no schema, conversion or migration entry changes, and `conversionIds` and `semantic` for step 18 are unchanged.

‎packages/spec/src/migrations/registry.ts‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5504,6 +5504,37 @@ const STEP18_RATIONALE: readonly RationaleFragment[] = [
55045504
+ 'the key with the prescription; the mechanical conversion strips it from stored '
55055505
+ 'sources (pure lossless delete — it never had an effect on this surface to lose).',
55065506
},
5507+
{
5508+
id: 'form-view-subform-columns-closed',
5509+
order: 54,
5510+
text:
5511+
'It also closes the form view\'s inline grid columns: `subforms[].columns`, on `view.form` '
5512+
+ 'and on `formViews` entries, was `z.array(z.any())` while a relationship field\'s '
5513+
+ '`inlineColumns` was already the strict `InlineGridColumnSchema`, so a mis-keyed column '
5514+
+ 'published clean and drew a blank grid column, and `scale` on a currency column, which the '
5515+
+ 'other carrier refuses under the maintainer\'s rulings of 2026-09-23 (option B) and '
5516+
+ '2026-09-24 (option 乙), published green. The carrier now references that schema, so both '
5517+
+ 'carriers are judged by it, with its own prescriptions. The D2 conversion '
5518+
+ '`form-view-subform-columns-canonicalized` respells a `{ field }` column as `{ name }`, the '
5519+
+ 'respelling `field-column-lists-canonicalized` makes on `inlineColumns`: it rewrites stored '
5520+
+ 'rows and assembled artifacts and lists the edit under `os migrate meta`, and it is retired '
5521+
+ 'from the load path, so an author writing `field` meets the refusal. A view saved with a '
5522+
+ 'failing column is refused with the column schema\'s prescription, and a stored row carrying '
5523+
+ 'one is diagnosed at rehydration; neither is stripped, because which column an unknown key '
5524+
+ 'or a mixed `field`/`name` entry meant is the author\'s call, and a conversion that dropped '
5525+
+ 'the key would accept at load what the parse now refuses. Its D3 record is the semantic '
5526+
+ 'entry `form-view-subform-columns-closed`. On both carriers, the reach of '
5527+
+ '`inline-grid-column-currency-scale-refused` extends to a column that declares no `type`: '
5528+
+ 'such a column takes its type from the child field, which the column schema cannot see, '
5529+
+ 'when the console hydrates it, so `defineStack`\'s cross-reference check re-parses a column '
5530+
+ 'whose `name` is a `currency` field of the child object as the type it renders as, and the '
5531+
+ 'refusal of its `scale` is the column schema\'s own. Reach: the child object must be '
5532+
+ 'declared in the same stack; a column naming no field of it, or a subform whose child '
5533+
+ 'object comes from another package, is not judged there. It has no D2 conversion, for the '
5534+
+ 'declared-type entry\'s reason: deleting the key is the migration, and a conversion that '
5535+
+ 'dropped it would accept it at load, the grace window ruling B refused. Its D3 record is '
5536+
+ 'the semantic entry `inline-grid-column-identity-only-currency-scale-refused`.',
5537+
},
55075538
{
55085539
id: 'list-view-page-mount-retired',
55095540
order: 27,

0 commit comments

Comments
 (0)