Skip to content

Commit fc8eda2

Browse files
committed
test(spec): keep the pin file's prose true after the re-key
The naming and sort rule is written at the head of the pin list, with the two cohorts that used to head their own blocks (phase 2, the #4593 backfill) filed there. Notes that pointed at a pin by position or by a numeral now name it; "positional and stay vacant" goes, since no pin name is positional any more; the count history gains a +0 receipt saying the numerals it cites are the pins' former names. Claude-Session: https://claude.ai/code/session_013RDBh5DqXd2xnLwvHLgLFr Co-authored-by: Claude <noreply@anthropic.com>
1 parent ece9f71 commit fc8eda2

1 file changed

Lines changed: 92 additions & 53 deletions

File tree

‎packages/spec/src/type-alias-convention.pin.test.ts‎

Lines changed: 92 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
// tree and this file goes RED with the alias named, and the fix is the one the
2626
// ADR prescribes: declare `XParsed` next to the bare alias and delete the pin
2727
// line. The list therefore moves in both directions, and it moves for the right
28-
// reason — phase 2 grew it by 35 for a reason it records at the block itself.
28+
// reason — phase 2 grew it by 35 for a reason recorded at the head of the list.
2929
//
3030
// ## It is also the gate's registry
3131
//
@@ -285,6 +285,30 @@ import type * as M188 from './ai/build-progress.zod.js';
285285
// Iso...` declarations and never the prose sitting beside them.
286286
// ---------------------------------------------------------------------------
287287

288+
// How a pin is named, and where it goes. A pin is named for the pair that is
289+
// already unique to it — its module and its schema: `Iso_`, then the module's
290+
// path below `src/` without `.zod.ts`, each kebab segment camelCased and the
291+
// segments joined by `_` (`ai/knowledge-document.zod.ts` becomes
292+
// `ai_knowledgeDocument`), then `__`, then the schema's export name. The block
293+
// is sorted by that name in code-unit order (the order `LC_ALL=C sort` gives),
294+
// one heading per module, and a note about a module's pins sits under its
295+
// heading and names the pins it is about. A new pin's name AND its place are
296+
// therefore functions of the schema alone: two branches that each pin a
297+
// different schema write different lines in different places, and git merges
298+
// them with nobody renumbering anything.
299+
//
300+
// The names used to be a dense counter, `Iso0` up to `Iso881`, each new pin
301+
// taking "the next free number" — so two branches off one base took the SAME
302+
// number for two different schemas, at insertion points hundreds of lines
303+
// apart, and git merged the pair cleanly into two declarations of one name
304+
// (`Iso871`, then `Iso877` / `Iso878`; both are recorded in the history at the
305+
// bottom of this file). #19665 retired the counter. An `IsoNNN` that a note or
306+
// that history still cites is the pin's former name, true of the file when it
307+
// was written. The `Mn` import aliases above keep their positional numbering.
308+
//
309+
// Two cohorts used to head blocks of their own; their pins are now filed under
310+
// their modules like every other pin.
311+
//
288312
// Phase 2 (#6083) additions. These 35 schemas were never in phase 1's
289313
// population: their bare alias already read `z.input` before the flip, so the
290314
// phase-1 gate — which only looked at bare `z.infer` aliases — never asked
@@ -293,12 +317,11 @@ import type * as M188 from './ai/build-progress.zod.js';
293317
// assertion, so a vacuous pass could not be mistaken for isomorphism) says
294318
// these 35 coincide. The other 22 it found got an `XParsed` instead.
295319
//
296-
// #4593 — the documented-schema type-alias backfill (2026-08-08).
297-
//
298-
// Every schema below already had a published JSON Schema and a reference page,
299-
// and the page's `import type { X }` line was being dropped because no alias
300-
// carried the name (`docs-import-surface.baseline.json`, "no type export").
301-
// The backfill declares the bare alias; each schema here measured isomorphic, so
320+
// #4593 — the documented-schema type-alias backfill (2026-08-08). Every schema
321+
// in it already had a published JSON Schema and a reference page, and the
322+
// page's `import type { X }` line was being dropped because no alias carried
323+
// the name (`docs-import-surface.baseline.json`, "no type export"). The
324+
// backfill declares the bare alias; each schema in it measured isomorphic, so
302325
// it takes a pin rather than an `XParsed` synonym — the (RISE) case, and the
303326
// largest single rise this file has taken.
304327

@@ -374,11 +397,13 @@ export type Iso_ai_usage__AIUsageRecordSchema = Assert<Eq< z.input< typeof M10.A
374397
export type Iso_ai_usage__TokenUsageSchema = Assert<Eq< z.input< typeof M10.TokenUsageSchema >, z.infer< typeof M10.TokenUsageSchema > >>;
375398

376399
// api/analytics.zod.ts
377-
// [#17551] The ADR-0021 dataset selection and its two nested directives. Their
378-
// seven shared members ARE `AnalyticsQuerySchema`'s own declarations (Iso300
379-
// above pins that schema isomorphic), and the four dataset-only members carry
380-
// no default, transform, catch or pipe — so the author state and the parsed
381-
// state coincide and no `XParsed` name would be anything but a synonym.
400+
// [#17551] The ADR-0021 dataset selection (`DatasetSelectionSchema`) and its two
401+
// nested directives (`DatasetCompareToSchema`, `DatasetTotalsSchema`). Their
402+
// seven shared members ARE `AnalyticsQuerySchema`'s own declarations
403+
// (`Iso_data_analytics__AnalyticsQuerySchema` pins that schema isomorphic), and
404+
// the four dataset-only members carry no default, transform, catch or pipe — so
405+
// the author state and the parsed state coincide and no `XParsed` name would be
406+
// anything but a synonym.
382407
export type Iso_api_analytics__AnalyticsEndpoint = Assert<Eq< z.input< typeof M11.AnalyticsEndpoint >, z.infer< typeof M11.AnalyticsEndpoint > >>;
383408
export type Iso_api_analytics__AnalyticsQueryRequestSchema = Assert<Eq< z.input< typeof M11.AnalyticsQueryRequestSchema >, z.infer< typeof M11.AnalyticsQueryRequestSchema > >>;
384409
export type Iso_api_analytics__DatasetCompareToSchema = Assert<Eq< z.input< typeof M11.DatasetCompareToSchema >, z.infer< typeof M11.DatasetCompareToSchema > >>;
@@ -742,11 +767,11 @@ export type Iso_automation_timeRelativeTrigger__TimeRelativeTriggerSchema = Asse
742767
export type Iso_automation_webhook__WebhookTriggerType = Assert<Eq< z.input< typeof M44.WebhookTriggerType >, z.infer< typeof M44.WebhookTriggerType > >>;
743768

744769
// data/analytics.zod.ts
745-
// [#16041] Added after the generated corpus (numbers continue from the file's
746-
// end, see the #4395 note above). The closed `timeDimensions[].dateRange`
747-
// vocabulary: a bare `z.enum` derived from `DATE_RANGE_PRESETS`, and the union
748-
// of that enum with `z.array(z.string())` — no default, no transform on either
749-
// arm, so author and parsed states coincide.
770+
// [#16041] The closed `timeDimensions[].dateRange` vocabulary:
771+
// `AnalyticsDateRangePresetSchema`, a bare `z.enum` derived from
772+
// `DATE_RANGE_PRESETS`, and `AnalyticsDateRangeSchema`, the union of that enum
773+
// with `z.array(z.string())` — no default, no transform on either arm, so
774+
// author and parsed states coincide.
750775
export type Iso_data_analytics__AggregationMetricType = Assert<Eq< z.input< typeof M55.AggregationMetricType >, z.infer< typeof M55.AggregationMetricType > >>;
751776
export type Iso_data_analytics__AnalyticsDateRangePresetSchema = Assert<Eq< z.input< typeof M55.AnalyticsDateRangePresetSchema >, z.infer< typeof M55.AnalyticsDateRangePresetSchema > >>;
752777
export type Iso_data_analytics__AnalyticsDateRangeSchema = Assert<Eq< z.input< typeof M55.AnalyticsDateRangeSchema >, z.infer< typeof M55.AnalyticsDateRangeSchema > >>;
@@ -838,8 +863,9 @@ export type Iso_data_fieldValue__LocationValueSchema = Assert<Eq< z.input< typeo
838863
export type Iso_data_fieldValue__ReferenceIdValueSchema = Assert<Eq< z.input< typeof M178.ReferenceIdValueSchema >, z.infer< typeof M178.ReferenceIdValueSchema > >>;
839864

840865
// data/field.zod.ts
841-
// #8993 partial masking: keepHead/keepTail are plain optional-free ints — no
842-
// transform, no defaults, so input === infer and the bare alias needs no Parsed.
866+
// #8993 partial masking (`FieldMaskingKeepSchema`): keepHead/keepTail are plain
867+
// optional-free ints — no transform, no defaults, so input === infer and the
868+
// bare alias needs no Parsed.
843869
export type Iso_data_field__AddressSchema = Assert<Eq< z.input< typeof M66.AddressSchema >, z.infer< typeof M66.AddressSchema > >>;
844870
export type Iso_data_field__CurrencyValueSchema = Assert<Eq< z.input< typeof M66.CurrencyValueSchema >, z.infer< typeof M66.CurrencyValueSchema > >>;
845871
export type Iso_data_field__FieldMaskingKeepSchema = Assert<Eq< z.input< typeof M66.FieldMaskingKeepSchema >, z.infer< typeof M66.FieldMaskingKeepSchema > >>;
@@ -907,15 +933,10 @@ export type Iso_identity_scim__SCIMNameSchema = Assert<Eq< z.input< typeof M77.S
907933
export type Iso_identity_scim__SCIMPatchOperationSchema = Assert<Eq< z.input< typeof M77.SCIMPatchOperationSchema >, z.infer< typeof M77.SCIMPatchOperationSchema > >>;
908934

909935
// integration/connector.zod.ts
910-
// [#4395] Added after the generated corpus, so its number continues from the
911-
// file's end rather than from its neighbours — the `IsoNNN` label is only a
912-
// unique name (the gate reads the `z.input< typeof Mn.XSchema >` occurrence,
913-
// not the label), and renumbering 300+ following lines to close the gap would
914-
// be a merge-conflict magnet for no reader benefit. Grouped with its siblings
915-
// here because the FILE heading is what a reader navigates by.
916-
// A bare `z.enum`, exactly like `ConnectorType` / `ConnectorStatus` two lines
917-
// up: no default, no transform, so author and parsed states coincide and D5
918-
// gives it no `XParsed`.
936+
// [#4395] `ConnectorActionEffectSchema`, added after the generated corpus: a
937+
// bare `z.enum`, exactly like its `ConnectorType` / `ConnectorStatus` siblings
938+
// in this module — no default, no transform, so author and parsed states
939+
// coincide and D5 gives it no `XParsed`.
919940
export type Iso_integration_connector__ConnectorActionEffectSchema = Assert<Eq< z.input< typeof M78.ConnectorActionEffectSchema >, z.infer< typeof M78.ConnectorActionEffectSchema > >>;
920941
export type Iso_integration_connector__ConnectorActionSchema = Assert<Eq< z.input< typeof M78.ConnectorActionSchema >, z.infer< typeof M78.ConnectorActionSchema > >>;
921942
export type Iso_integration_connector__ConnectorConflictResolutionSchema = Assert<Eq< z.input< typeof M78.ConnectorConflictResolutionSchema >, z.infer< typeof M78.ConnectorConflictResolutionSchema > >>;
@@ -966,8 +987,7 @@ export type Iso_kernel_manifest__PluginRuntimeSchema = Assert<Eq< z.input< typeo
966987
// (Iso408 `CustomizationOriginSchema` / Iso409 `FieldChangeSchema` /
967988
// Iso410 `MergeConflictSchema` / Iso411 `MergeResultSchema` removed with
968989
// their module — #13135's ADR-0049 retirement of the paper
969-
// metadata-customization protocol. The Iso numbers are positional and stay
970-
// vacant.)
990+
// metadata-customization protocol.)
971991

972992
// kernel/metadata-loader.zod.ts
973993
export type Iso_kernel_metadataLoader__MetadataFallbackStrategySchema = Assert<Eq< z.input< typeof M87.MetadataFallbackStrategySchema >, z.infer< typeof M87.MetadataFallbackStrategySchema > >>;
@@ -1129,7 +1149,7 @@ export type Iso_shared_connectorAuth__ConnectorInstanceBearerAuthSchema = Assert
11291149
export type Iso_shared_connectorAuth__ConnectorInstanceNoAuthSchema = Assert<Eq< z.input< typeof M109.ConnectorInstanceNoAuthSchema >, z.infer< typeof M109.ConnectorInstanceNoAuthSchema > >>;
11301150

11311151
// shared/duration.zod.ts — the closed DURATION vocabulary (#18122), step ① of
1132-
// ruling A on #18115 and the counterpart of the instant above. Both are
1152+
// ruling A on #18115 and the counterpart of the `shared/epoch` instant. Both are
11331153
// `z.number().int().nonnegative()`: no default, no transform, the (RISE) case.
11341154
// The refinement is deliberate rather than incidental, so these two pins are
11351155
// what goes red the day someone gives a duration type a `.default()` — which
@@ -1177,7 +1197,8 @@ export type Iso_shared_metadataTypes__MetadataFormatSchema = Assert<Eq< z.input<
11771197
export type Iso_shared_protection__ProtectionSchema = Assert<Eq< z.input< typeof M115.ProtectionSchema >, z.infer< typeof M115.ProtectionSchema > >>;
11781198

11791199
// shared/value-domain.zod.ts — the ONE standard-domain vocabulary (#14168);
1180-
// `SpecifierValueDomainSchema` (Iso758) is an alias of it, so both pins hold
1200+
// `SpecifierValueDomainSchema` is an alias of it, so its pin
1201+
// (`Iso_system_settingsManifest__SpecifierValueDomainSchema`) and this one hold
11811202
// or fall together. A `z.enum` has no default or transform, the (RISE) case.
11821203
export type Iso_shared_valueDomain__ValueDomainSchema = Assert<Eq< z.input< typeof M184.ValueDomainSchema >, z.infer< typeof M184.ValueDomainSchema > >>;
11831204

@@ -1391,7 +1412,8 @@ export type Iso_system_tracing__TracePropagationFormat = Assert<Eq< z.input< typ
13911412
export type Iso_system_tracing__TraceStateSchema = Assert<Eq< z.input< typeof M150.TraceStateSchema >, z.infer< typeof M150.TraceStateSchema > >>;
13921413

13931414
// system/translation.zod.ts
1394-
// #15178 split the bundle type in two. The platform face is the per-app shape
1415+
// #15178 split the bundle type in two (`PlatformTranslationDataSchema`,
1416+
// `PlatformTranslationBundleSchema`). The platform face is the per-app shape
13951417
// plus one more optional group, so its two states coincide exactly as the
13961418
// per-app face's do — pinned rather than given a permanent `XParsed` synonym.
13971419
export type Iso_system_translation__ActionResultDialogTranslationSchema = Assert<Eq< z.input< typeof M152.ActionResultDialogTranslationSchema >, z.infer< typeof M152.ActionResultDialogTranslationSchema > >>;
@@ -1438,11 +1460,12 @@ export type Iso_ui_chart__ChartGroupBySchema = Assert<Eq< z.input< typeof M158.C
14381460
export type Iso_ui_chart__ChartTypeSchema = Assert<Eq< z.input< typeof M158.ChartTypeSchema >, z.infer< typeof M158.ChartTypeSchema > >>;
14391461

14401462
// ui/component.zod.ts
1441-
// #5775 — the shared `children` contract for `page:section`/`page:footer`/
1442-
// `page:sidebar`. A lone optional array with no default, transform, catch or
1443-
// pipe anywhere in its tree, so the two shapes coincide and the phase-2 flip of
1444-
// the bare name changes nothing. `check:spec-parsed-alias` sent it here rather
1445-
// than to a `PageContainerPropsParsed`, which would be a permanent synonym.
1463+
// #5775 — `PageContainerProps`, the shared `children` contract for
1464+
// `page:section`/`page:footer`/`page:sidebar`. A lone optional array with no
1465+
// default, transform, catch or pipe anywhere in its tree, so the two shapes
1466+
// coincide and the phase-2 flip of the bare name changes nothing.
1467+
// `check:spec-parsed-alias` sent it here rather than to a
1468+
// `PageContainerPropsParsed`, which would be a permanent synonym.
14461469
// `ElementNumberPropsSchema` (Iso818) left the family on the ui#6206
14471470
// convergence: its `filter` now carries `z.array(ViewFilterRuleSchema)`, whose
14481471
// own input ≠ infer (`operator` is normalized on parse — `ViewFilterRuleParsed`
@@ -1452,21 +1475,25 @@ export type Iso_ui_chart__ChartTypeSchema = Assert<Eq< z.input< typeof M158.Char
14521475
// #14406 — the LAST record-form `filter` in `ComponentPropsMap`: its `filter`
14531476
// now carries `z.array(ViewFilterRuleSchema)` too, so `ElementRecordPickerPropsParsed`
14541477
// is declared and this pin deleted.
1455-
// `record:reference_rail` (#8691) — deliberately default-free on the same
1456-
// principle as the object-* family below: the renderer's `limit ?? 3` /
1478+
// `record:reference_rail` (#8691: `ReferenceRailEntrySchema`,
1479+
// `RecordReferenceRailProps`) — deliberately default-free on the same
1480+
// principle as the object-* family: the renderer's `limit ?? 3` /
14571481
// `hideEmpty !== false` fallbacks stay the renderer's facts, so "the author
14581482
// said nothing" survives the parse, and input === infer holds for both shapes.
1459-
// #8744 — the three record types the rail fix left behind, default-free on
1460-
// the same principle. `RecordAlertProps` itself is deliberately NOT pinned:
1461-
// its `visible` carries `ExpressionInputSchema`, whose bare-string arm
1462-
// TRANSFORMS to the canonical `{ dialect, source }` envelope, so
1463-
// input ≠ infer by construction — the alias stays `z.input` (the authoring
1483+
// #8744 — the three record types the rail fix left behind
1484+
// (`RecordAlertActionSchema`, `RecordQuickActionsProps`, `RecordHistoryProps`),
1485+
// default-free on the same principle. `RecordAlertProps` itself is
1486+
// deliberately NOT pinned: its `visible` carries `ExpressionInputSchema`, whose
1487+
// bare-string arm TRANSFORMS to the canonical `{ dialect, source }` envelope,
1488+
// so input ≠ infer by construction — the alias stays `z.input` (the authoring
14641489
// face), per the convention's own rule for Expression-carrying shapes.
1465-
// The object-* block family (#7751) — deliberately default-free in its first,
1466-
// warning-tier step ("the author said nothing" must stay distinguishable from
1467-
// "the author asked for the renderer's fallback"), so input === infer holds.
1468-
// A default added to any of these goes red here, and the fix is the ADR's:
1469-
// declare the XParsed alias and delete the pin line.
1490+
// The object-* block family (#7751; `ObjectFormPropsSchema` and
1491+
// `ObjectMasterDetailFormPropsSchema` are the members still pinned) —
1492+
// deliberately default-free in its first, warning-tier step ("the author said
1493+
// nothing" must stay distinguishable from "the author asked for the renderer's
1494+
// fallback"), so input === infer holds. A default added to any of them goes
1495+
// red here, and the fix is the ADR's: declare the XParsed alias and delete the
1496+
// pin line.
14701497
// `ObjectGridPropsSchema` (Iso839) left the family exactly that way on the
14711498
// ui#6207 convergence: its `data` now carries `ViewDataSchema`, whose own
14721499
// input ≠ infer, so `ObjectGridPropsParsed` is declared and the pin deleted.
@@ -1534,14 +1561,13 @@ export type Iso_ui_report__ReportType = Assert<Eq< z.input< typeof M164.ReportTy
15341561
// ui/responsive.zod.ts
15351562
// (Iso696 `BreakpointName` / Iso697 `ResponsiveConfigSchema` removed with
15361563
// their schemas — #11027's ADR-0049 retirement of the responsive layout
1537-
// vocabulary. The Iso numbers are positional and stay vacant.)
1564+
// vocabulary.)
15381565
// (Iso824 `BreakpointColumnMapSchema` / Iso825 `BreakpointOrderMapSchema`
15391566
// removed with their schemas — #11027, see the Iso696/Iso697 note above.)
15401567
export type Iso_ui_responsive__ResponsiveStylesSchema = Assert<Eq< z.input< typeof M165.ResponsiveStylesSchema >, z.infer< typeof M165.ResponsiveStylesSchema > >>;
15411568
export type Iso_ui_responsive__StyleMapSchema = Assert<Eq< z.input< typeof M165.StyleMapSchema >, z.infer< typeof M165.StyleMapSchema > >>;
15421569

1543-
// ui/theme.zod.ts (Iso700–Iso704) left with the module at #10485 — the Iso
1544-
// numbers are positional and stay vacant.
1570+
// ui/theme.zod.ts — its five pins (Iso700–Iso704) left with the module at #10485.
15451571

15461572
// ui/view.zod.ts
15471573
// (Iso829 `KanbanConfigSchema` left this list in #17393: the author-settable
@@ -2242,6 +2268,19 @@ describe('ADR-0122 type-alias convention', () => {
22422268
// Iso877/Iso878; #17551 landed on main first, so its ids stand and this
22432269
// card's pins renumbered to Iso880/Iso881 — ids are claims about pins, not
22442270
// positions, so the renumbering asserts nothing new.
2271+
//
2272+
// 789 -> 789 is #19665, which moves no pin in or out: it RENAMES every
2273+
// pin. The dense counter these receipts allocate from — "the next free id"
2274+
// — let two branches off one base give one name to two different schemas,
2275+
// and git merged each pair cleanly because the two insertion points sat far
2276+
// apart: `Iso871` above, then `Iso877` / `Iso878` — each a duplicate
2277+
// identifier that no merge flags and only the type-check of this file
2278+
// reports. So each pin is now named for its module and schema, and the
2279+
// block is sorted by that name (the rule is written at the head of the
2280+
// list). Every `IsoNNN` cited above is a pin's former name,
2281+
// true of the file when its entry was written, like the counts beside it.
2282+
// The set `check:spec-parsed-alias` reads is identical member for member,
2283+
// and so is each assertion — only the names moved. +0.
22452284
expect(pins).toHaveLength(789);
22462285

22472286
// The count is stated in PROSE twice as well — this case's title and the

0 commit comments

Comments
 (0)