Skip to content

Commit c448fef

Browse files
committed
fix(spec): 基线编码统一为裸字符,写盘端与文件共用一个序列化器 (#5990)
`--update-import-baseline` 用 JSON.stringify 写裸字符,而仓内 `docs-import-surface.baseline.json` 落盘是 \uXXXX 转义。两者 JSON.parse 后逐条等价,门禁只读 parse 后的 entries,所以一直是绿的 —— 代价全落在复核: 每跑一次该命令,136 条 entry 行被原样重写一遍,真实的 1 行决定被埋掉。 选路 2(基线统一为裸字符 + 一次性转换提交),判据是该 ratchet 的设计意图: 只减不增、变化应当显眼。实测支撑 —— 本仓 305 个 tracked .json 中 151 个带 非 ASCII,只有这一个用转义;同类手工棘轮与全部生成物都落裸字符,且 lib/sharded-artifacts.ts 的 serializeShard 已把「2 空格 + 结尾换行」的裸字符 写法确立为分片规范字节。选路 1 会让这个文件成为全仓唯一的转义孤例。 两侧一起改,不只改一侧: - IMPORT_BASELINE_COMMENT 与新的 serializeImportBaseline() 移入 lib/docs-import-surface.ts,写盘端改为调用它; - 基线文件由生成器重写(内容 100% 来自生成器),entries 在 parse 层与 origin/main 逐条相同(136 条不变),唯一语义变化是 #6069 有意留下的 过期路径 api-surface.json -> api-surface/; - 新增字节级往返 pin:读committed 文件 -> JSON.parse -> 用同一个序列化器 重新序列化 -> 要求字节相同。它同时钉住编码、缩进、键序、结尾换行,以及 _comment 的新鲜度,任一侧再分叉即红。 复现修复:连续两次跑 --update-import-baseline,文件 sha256 不变(修复前每次 都产生 137 增 137 删)。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014wsZeReNTqiceBfLb5Pyf5
1 parent e3ef52b commit c448fef

4 files changed

Lines changed: 280 additions & 153 deletions

File tree

Lines changed: 137 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -1,141 +1,141 @@
11
{
2-
"_comment": "Accepted gaps between the reference docs' import examples and the real export surface of @objectstack/spec (#4570): a documented JSON Schema whose entry point exports no matching type alias (\"no type export\") or no matching schema const (\"no schema const export\"). The name is omitted from the generated import line \u2014 the docs never advertise an import that cannot compile \u2014 and listed here so the omission is countable instead of silent. Shrink-only ratchet: a NEW gap fails check:docs (fix it by adding `export type X = z.infer<typeof XSchema>;` next to the schema and regenerating api-surface.json, or by retiring the schema together with its alias), and a stale entry fails until its line is deleted. Growing this list is a maintainer decision that shows up as this file in the diff. Regenerate with: tsx scripts/build-docs.ts --update-import-baseline (after gen:schema).",
2+
"_comment": "Accepted gaps between the reference docs' import examples and the real export surface of @objectstack/spec (#4570): a documented JSON Schema whose entry point exports no matching type alias (\"no type export\") or no matching schema const (\"no schema const export\"). The name is omitted from the generated import line the docs never advertise an import that cannot compile and listed here so the omission is countable instead of silent. Shrink-only ratchet: a NEW gap fails check:docs (fix it by adding `export type X = z.infer<typeof XSchema>;` next to the schema and regenerating api-surface/, or by retiring the schema together with its alias), and a stale entry fails until its line is deleted. Growing this list is a maintainer decision that shows up as this file in the diff. Regenerate with: tsx scripts/build-docs.ts --update-import-baseline (after gen:schema).",
33
"entries": [
4-
"ai/AIModelConfig \u2014 no type export",
5-
"ai/CodeContent \u2014 no type export",
6-
"ai/FileContent \u2014 no type export",
7-
"ai/ImageContent \u2014 no type export",
8-
"ai/TextContent \u2014 no type export",
9-
"api/AnalyticsResultResponse \u2014 no type export",
10-
"api/ApiMapping \u2014 no type export",
11-
"api/Discovery \u2014 no type export",
12-
"api/GetAnalyticsMetaRequest \u2014 no type export",
13-
"api/HttpFindQueryParams \u2014 no type export",
14-
"api/MetadataBulkUnregisterRequest \u2014 no type export",
15-
"api/MetadataExportRequest \u2014 no type export",
16-
"api/MetadataImportRequest \u2014 no type export",
17-
"api/MetadataOverlaySaveRequest \u2014 no type export",
18-
"api/MetadataQueryRequest \u2014 no type export",
19-
"api/MetadataValidateRequest \u2014 no type export",
20-
"api/SubscriptionEvent \u2014 no type export",
21-
"automation/ApproverType \u2014 no type export",
22-
"automation/FlowNodeAction \u2014 no type export",
23-
"automation/FlowVariable \u2014 no type export",
24-
"automation/GuardRef \u2014 no type export",
25-
"automation/StateMachine \u2014 no type export",
26-
"automation/StateNode \u2014 no type export",
27-
"data/AddressValue \u2014 no type export",
28-
"data/AggregationFunction \u2014 no type export",
29-
"data/AggregationMetricType \u2014 no type export",
30-
"data/CalendarDateValue \u2014 no type export",
31-
"data/ClockTimeValue \u2014 no type export",
32-
"data/ContextTokenPlaceholder \u2014 no type export",
33-
"data/DataEngineAggregateRequest \u2014 no type export",
34-
"data/DataEngineCountRequest \u2014 no type export",
35-
"data/DataEngineDeleteRequest \u2014 no type export",
36-
"data/DataEngineExecuteRequest \u2014 no type export",
37-
"data/DataEngineFindOneRequest \u2014 no type export",
38-
"data/DataEngineFindRequest \u2014 no type export",
39-
"data/DataEngineInsertRequest \u2014 no type export",
40-
"data/DataEngineUpdateRequest \u2014 no type export",
41-
"data/DataEngineVectorFindRequest \u2014 no type export",
42-
"data/DateGranularity \u2014 no type export",
43-
"data/DateMacroPlaceholder \u2014 no type export",
44-
"data/DimensionType \u2014 no type export",
45-
"data/DriverSslToggle \u2014 no type export",
46-
"data/DriverType \u2014 no type export",
47-
"data/EqualityOperator \u2014 no type export",
48-
"data/FileLikeValue \u2014 no type export",
49-
"data/FileReferenceIdValue \u2014 no type export",
50-
"data/FileValue \u2014 no type export",
51-
"data/HookEvent \u2014 no type export",
52-
"data/Index \u2014 no type export",
53-
"data/InstantValue \u2014 no type export",
54-
"data/LocationValue \u2014 no type export",
55-
"data/Object \u2014 no type export",
56-
"data/ObjectOwnershipEnum \u2014 no type export",
57-
"data/Query \u2014 no type export",
58-
"data/ReferenceIdValue \u2014 no type export",
59-
"data/SeedMode \u2014 no type export",
60-
"data/SetOperator \u2014 no type export",
61-
"data/SpecialOperator \u2014 no type export",
62-
"data/StringOperator \u2014 no type export",
63-
"data/TimeUpdateInterval \u2014 no type export",
64-
"data/TransformType \u2014 no type export",
65-
"integration/ConnectorAction \u2014 no type export",
66-
"integration/ConnectorInstanceAPIKeyAuth \u2014 no type export",
67-
"integration/ConnectorInstanceBasicAuth \u2014 no type export",
68-
"integration/ConnectorInstanceBearerAuth \u2014 no type export",
69-
"integration/ConnectorInstanceNoAuth \u2014 no type export",
70-
"integration/ConnectorTrigger \u2014 no type export",
71-
"kernel/DependencyStatusEnum \u2014 no type export",
72-
"kernel/EventMetadata \u2014 no type export",
73-
"kernel/Manifest \u2014 no type export",
74-
"kernel/MetadataCategoryEnum \u2014 no type export",
75-
"kernel/PackageStatusEnum \u2014 no type export",
76-
"kernel/Plugin \u2014 no type export",
77-
"qa/TestActionType \u2014 no type export",
78-
"qa/TestAssertionType \u2014 no type export",
79-
"qa/TestContext \u2014 no type export",
80-
"security/OWDModel \u2014 no type export",
81-
"security/ShareRecipientType \u2014 no type export",
82-
"security/SharingLevel \u2014 no type export",
83-
"security/SharingRuleType \u2014 no type export",
84-
"shared/IsolationLevelEnum \u2014 no type export",
85-
"shared/MutationEventEnum \u2014 no type export",
86-
"shared/SortDirectionEnum \u2014 no type export",
87-
"studio/PanelLocation \u2014 no type export",
88-
"system/AddFieldOperation \u2014 no type export",
89-
"system/CreateObjectOperation \u2014 no type export",
90-
"system/DeleteObjectOperation \u2014 no type export",
91-
"system/DeployStatusEnum \u2014 no type export",
92-
"system/ExecuteSqlOperation \u2014 no type export",
93-
"system/KernelServiceMap \u2014 no type export",
94-
"system/Locale \u2014 no type export",
95-
"system/MetadataState \u2014 no type export",
96-
"system/MigrationDependency \u2014 no type export",
97-
"system/ModifyFieldOperation \u2014 no type export",
98-
"system/RemoveFieldOperation \u2014 no type export",
99-
"system/RenameObjectOperation \u2014 no type export",
100-
"system/ServiceConfig \u2014 no type export",
101-
"system/ServiceCriticality \u2014 no type export",
102-
"system/ServiceStatus \u2014 no type export",
103-
"ui/AIChatWindowProps \u2014 no type export",
104-
"ui/ActionType \u2014 no type export",
105-
"ui/BreakpointColumnMap \u2014 no type export",
106-
"ui/BreakpointOrderMap \u2014 no type export",
107-
"ui/CalendarConfig \u2014 no type export",
108-
"ui/DerivedMeasureOp \u2014 no type export",
109-
"ui/ElementButtonProps \u2014 no type export",
110-
"ui/ElementFilterProps \u2014 no type export",
111-
"ui/ElementFormProps \u2014 no type export",
112-
"ui/ElementImageProps \u2014 no type export",
113-
"ui/ElementMetadataViewerProps \u2014 no type export",
114-
"ui/ElementNumberProps \u2014 no type export",
115-
"ui/ElementRecordPickerProps \u2014 no type export",
116-
"ui/ElementTextInputProps \u2014 no type export",
117-
"ui/ElementTextProps \u2014 no type export",
118-
"ui/GanttConfig \u2014 no type export",
119-
"ui/GanttQuickFilter \u2014 no type export",
120-
"ui/GroupingField \u2014 no type export",
121-
"ui/KanbanConfig \u2014 no type export",
122-
"ui/NavigationMode \u2014 no type export",
123-
"ui/ObjectListView \u2014 no type export",
124-
"ui/ObjectUserFilters \u2014 no type export",
125-
"ui/PageAccordionProps \u2014 no type export",
126-
"ui/PageCardProps \u2014 no type export",
127-
"ui/PageComponentType \u2014 no type export",
128-
"ui/PageHeaderProps \u2014 no type export",
129-
"ui/PageTabsProps \u2014 no type export",
130-
"ui/RecordActivityProps \u2014 no type export",
131-
"ui/RecordChatterProps \u2014 no type export",
132-
"ui/RecordDetailsProps \u2014 no type export",
133-
"ui/RecordHighlightsField \u2014 no type export",
134-
"ui/RecordHighlightsProps \u2014 no type export",
135-
"ui/RecordPathProps \u2014 no type export",
136-
"ui/RecordRelatedListProps \u2014 no type export",
137-
"ui/ReportType \u2014 no type export",
138-
"ui/TreeConfig \u2014 no type export",
139-
"ui/ViewItemName \u2014 no type export"
4+
"ai/AIModelConfig no type export",
5+
"ai/CodeContent no type export",
6+
"ai/FileContent no type export",
7+
"ai/ImageContent no type export",
8+
"ai/TextContent no type export",
9+
"api/AnalyticsResultResponse no type export",
10+
"api/ApiMapping no type export",
11+
"api/Discovery no type export",
12+
"api/GetAnalyticsMetaRequest no type export",
13+
"api/HttpFindQueryParams no type export",
14+
"api/MetadataBulkUnregisterRequest no type export",
15+
"api/MetadataExportRequest no type export",
16+
"api/MetadataImportRequest no type export",
17+
"api/MetadataOverlaySaveRequest no type export",
18+
"api/MetadataQueryRequest no type export",
19+
"api/MetadataValidateRequest no type export",
20+
"api/SubscriptionEvent no type export",
21+
"automation/ApproverType no type export",
22+
"automation/FlowNodeAction no type export",
23+
"automation/FlowVariable no type export",
24+
"automation/GuardRef no type export",
25+
"automation/StateMachine no type export",
26+
"automation/StateNode no type export",
27+
"data/AddressValue no type export",
28+
"data/AggregationFunction no type export",
29+
"data/AggregationMetricType no type export",
30+
"data/CalendarDateValue no type export",
31+
"data/ClockTimeValue no type export",
32+
"data/ContextTokenPlaceholder no type export",
33+
"data/DataEngineAggregateRequest no type export",
34+
"data/DataEngineCountRequest no type export",
35+
"data/DataEngineDeleteRequest no type export",
36+
"data/DataEngineExecuteRequest no type export",
37+
"data/DataEngineFindOneRequest no type export",
38+
"data/DataEngineFindRequest no type export",
39+
"data/DataEngineInsertRequest no type export",
40+
"data/DataEngineUpdateRequest no type export",
41+
"data/DataEngineVectorFindRequest no type export",
42+
"data/DateGranularity no type export",
43+
"data/DateMacroPlaceholder no type export",
44+
"data/DimensionType no type export",
45+
"data/DriverSslToggle no type export",
46+
"data/DriverType no type export",
47+
"data/EqualityOperator no type export",
48+
"data/FileLikeValue no type export",
49+
"data/FileReferenceIdValue no type export",
50+
"data/FileValue no type export",
51+
"data/HookEvent no type export",
52+
"data/Index no type export",
53+
"data/InstantValue no type export",
54+
"data/LocationValue no type export",
55+
"data/Object no type export",
56+
"data/ObjectOwnershipEnum no type export",
57+
"data/Query no type export",
58+
"data/ReferenceIdValue no type export",
59+
"data/SeedMode no type export",
60+
"data/SetOperator no type export",
61+
"data/SpecialOperator no type export",
62+
"data/StringOperator no type export",
63+
"data/TimeUpdateInterval no type export",
64+
"data/TransformType no type export",
65+
"integration/ConnectorAction no type export",
66+
"integration/ConnectorInstanceAPIKeyAuth no type export",
67+
"integration/ConnectorInstanceBasicAuth no type export",
68+
"integration/ConnectorInstanceBearerAuth no type export",
69+
"integration/ConnectorInstanceNoAuth no type export",
70+
"integration/ConnectorTrigger no type export",
71+
"kernel/DependencyStatusEnum no type export",
72+
"kernel/EventMetadata no type export",
73+
"kernel/Manifest no type export",
74+
"kernel/MetadataCategoryEnum no type export",
75+
"kernel/PackageStatusEnum no type export",
76+
"kernel/Plugin no type export",
77+
"qa/TestActionType no type export",
78+
"qa/TestAssertionType no type export",
79+
"qa/TestContext no type export",
80+
"security/OWDModel no type export",
81+
"security/ShareRecipientType no type export",
82+
"security/SharingLevel no type export",
83+
"security/SharingRuleType no type export",
84+
"shared/IsolationLevelEnum no type export",
85+
"shared/MutationEventEnum no type export",
86+
"shared/SortDirectionEnum no type export",
87+
"studio/PanelLocation no type export",
88+
"system/AddFieldOperation no type export",
89+
"system/CreateObjectOperation no type export",
90+
"system/DeleteObjectOperation no type export",
91+
"system/DeployStatusEnum no type export",
92+
"system/ExecuteSqlOperation no type export",
93+
"system/KernelServiceMap no type export",
94+
"system/Locale no type export",
95+
"system/MetadataState no type export",
96+
"system/MigrationDependency no type export",
97+
"system/ModifyFieldOperation no type export",
98+
"system/RemoveFieldOperation no type export",
99+
"system/RenameObjectOperation no type export",
100+
"system/ServiceConfig no type export",
101+
"system/ServiceCriticality no type export",
102+
"system/ServiceStatus no type export",
103+
"ui/AIChatWindowProps no type export",
104+
"ui/ActionType no type export",
105+
"ui/BreakpointColumnMap no type export",
106+
"ui/BreakpointOrderMap no type export",
107+
"ui/CalendarConfig no type export",
108+
"ui/DerivedMeasureOp no type export",
109+
"ui/ElementButtonProps no type export",
110+
"ui/ElementFilterProps no type export",
111+
"ui/ElementFormProps no type export",
112+
"ui/ElementImageProps no type export",
113+
"ui/ElementMetadataViewerProps no type export",
114+
"ui/ElementNumberProps no type export",
115+
"ui/ElementRecordPickerProps no type export",
116+
"ui/ElementTextInputProps no type export",
117+
"ui/ElementTextProps no type export",
118+
"ui/GanttConfig no type export",
119+
"ui/GanttQuickFilter no type export",
120+
"ui/GroupingField no type export",
121+
"ui/KanbanConfig no type export",
122+
"ui/NavigationMode no type export",
123+
"ui/ObjectListView no type export",
124+
"ui/ObjectUserFilters no type export",
125+
"ui/PageAccordionProps no type export",
126+
"ui/PageCardProps no type export",
127+
"ui/PageComponentType no type export",
128+
"ui/PageHeaderProps no type export",
129+
"ui/PageTabsProps no type export",
130+
"ui/RecordActivityProps no type export",
131+
"ui/RecordChatterProps no type export",
132+
"ui/RecordDetailsProps no type export",
133+
"ui/RecordHighlightsField no type export",
134+
"ui/RecordHighlightsProps no type export",
135+
"ui/RecordPathProps no type export",
136+
"ui/RecordRelatedListProps no type export",
137+
"ui/ReportType no type export",
138+
"ui/TreeConfig no type export",
139+
"ui/ViewItemName no type export"
140140
]
141141
}

packages/spec/scripts/build-docs.ts

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import {
3030
evaluateBaseline,
3131
loadEntrySurfaces,
3232
resolveImports,
33+
serializeImportBaseline,
3334
type CategorySurface,
3435
} from './lib/docs-import-surface';
3536
import { escapeMdxDescription } from './lib/escape-mdx';
@@ -249,18 +250,6 @@ const ENTRY_SURFACES: ReadonlyMap<string, CategorySurface> = loadEntrySurfaces(
249250
/** Every unresolvable import name this run met, one stable line each. */
250251
const importGaps = new Set<string>();
251252

252-
const IMPORT_BASELINE_COMMENT =
253-
'Accepted gaps between the reference docs\' import examples and the real export surface of ' +
254-
'@objectstack/spec (#4570): a documented JSON Schema whose entry point exports no matching type ' +
255-
'alias ("no type export") or no matching schema const ("no schema const export"). The name is ' +
256-
'omitted from the generated import line — the docs never advertise an import that cannot compile ' +
257-
'— and listed here so the omission is countable instead of silent. Shrink-only ratchet: a NEW gap ' +
258-
'fails check:docs (fix it by adding `export type X = z.infer<typeof XSchema>;` next to the schema ' +
259-
'and regenerating api-surface/, or by retiring the schema together with its alias), and a ' +
260-
'stale entry fails until its line is deleted. Growing this list is a maintainer decision that ' +
261-
'shows up as this file in the diff. Regenerate with: ' +
262-
'tsx scripts/build-docs.ts --update-import-baseline (after gen:schema).';
263-
264253
/**
265254
* Resolve a schema name to its page, AS SEEN FROM the category being rendered.
266255
* Returns null when the schema isn't one we generate a page for, or when the
@@ -943,10 +932,11 @@ if (managedCount > 0) {
943932
const gaps = [...importGaps].sort();
944933

945934
if (UPDATE_IMPORT_BASELINE) {
946-
fs.writeFileSync(
947-
IMPORT_BASELINE_PATH,
948-
JSON.stringify({ _comment: IMPORT_BASELINE_COMMENT, entries: gaps }, null, 2) + '\n',
949-
);
935+
// Serialized through the lib, never inline: the same function is what the
936+
// round-trip pin in `docs-import-surface.test.ts` re-serializes the
937+
// committed file with, so this writer and that file cannot drift into two
938+
// encodings again (#5990).
939+
fs.writeFileSync(IMPORT_BASELINE_PATH, serializeImportBaseline(gaps));
950940
console.log(`Wrote ${gaps.length} import-surface gap(s) to ${path.relative(REPO_ROOT, IMPORT_BASELINE_PATH)} — review the diff before committing.`);
951941
} else {
952942
const baseline: { entries?: string[] } = fs.existsSync(IMPORT_BASELINE_PATH)

0 commit comments

Comments
 (0)