@@ -68,7 +68,13 @@ import {
6868 authorableSurfaceShardTexts ,
6969 schemaManifestShardTexts ,
7070 writeShards ,
71+ type ShardArrayField ,
7172} from './lib/sharded-artifacts' ;
73+ import {
74+ AUTHORABLE_DEFAULTS_DIR_NAME ,
75+ authorableDefaultsShardTexts ,
76+ parseDefaultEntries ,
77+ } from './lib/authorable-defaults' ;
7278
7379const HERE = path . dirname ( fileURLToPath ( import . meta. url ) ) ;
7480const PKG = path . resolve ( HERE , '..' ) ;
@@ -103,10 +109,25 @@ function writeManifestShards(dir: string, schemas: readonly string[]): string {
103109}
104110
105111/** Aggregate a shard directory back into its sorted key set. */
106- function readShardKeys ( dir : string , field : 'keys' | 'schemas' ) : string [ ] {
112+ function readShardKeys ( dir : string , field : ShardArrayField ) : string [ ] {
107113 return aggregateCategoryShards ( dir , field ) ?. entries ?? [ ] ;
108114}
109115
116+ /**
117+ * Write the recorded default fingerprints as canonical authorable-defaults
118+ * shards (#4666).
119+ *
120+ * The sandbox has to carry this artifact for the same reason it carries the
121+ * authorable-surface one: the default-value ratchet runs on every invocation,
122+ * so a fixture tree without it is not a smaller version of a real tree — it is
123+ * a tree whose generated record is missing, which `--check` reports as such.
124+ * Seeding it keeps every fixture below judging the contract it means to judge.
125+ */
126+ function writeDefaultsShards ( dir : string , entries : readonly string [ ] ) : string {
127+ writeShards ( dir , authorableDefaultsShardTexts ( parseDefaultEntries ( [ ...entries ] . sort ( ) ) ) ) ;
128+ return shardBytes ( dir ) ;
129+ }
130+
110131/**
111132 * Every run loads the entire spec surface and emits ~1700 JSON Schemas (~7s
112133 * alone, more under turbo's parallel test load). A timeout here should mean
@@ -126,9 +147,11 @@ let sandbox: string;
126147let script : string ;
127148let manifestDir : string ;
128149let surfaceDir : string ;
150+ let defaultsDir : string ;
129151let surfaceBasePath : string ;
130152let pristine : string [ ] ;
131153let pristineSurface : string [ ] ;
154+ let pristineDefaults : string [ ] ;
132155/** The generator's own description line for the in-tree anchor, so fixtures
133156 * written here are byte-canonical exactly the way `gen:schema` writes it —
134157 * a hand-rolled string would trip the anchor's own hand-edit check (#5235). */
@@ -165,8 +188,13 @@ const readSurfaceBase = () => fs.readFileSync(surfaceBasePath, 'utf8');
165188beforeAll ( ( ) => {
166189 pristine = readShardKeys ( path . join ( PKG , SCHEMA_MANIFEST_DIR_NAME ) , 'schemas' ) ;
167190 pristineSurface = readShardKeys ( path . join ( PKG , AUTHORABLE_SURFACE_DIR_NAME ) , 'keys' ) ;
191+ pristineDefaults = readShardKeys ( path . join ( PKG , AUTHORABLE_DEFAULTS_DIR_NAME ) , 'defaults' ) ;
168192 expect ( pristine . length , `${ SCHEMA_MANIFEST_DIR_NAME } / is empty — it is a committed artifact` ) . toBeGreaterThan ( 0 ) ;
169193 expect ( pristineSurface . length , `${ AUTHORABLE_SURFACE_DIR_NAME } / is empty — it is a committed artifact` ) . toBeGreaterThan ( 0 ) ;
194+ expect (
195+ pristineDefaults . length ,
196+ `${ AUTHORABLE_DEFAULTS_DIR_NAME } / is empty — it is a committed artifact (#4666)` ,
197+ ) . toBeGreaterThan ( 0 ) ;
170198 const realBase = path . join ( PKG , 'authorable-surface.base.json' ) ;
171199 if ( ! fs . existsSync ( realBase ) ) {
172200 throw new Error (
@@ -184,15 +212,20 @@ beforeAll(() => {
184212 script = path . join ( sandbox , 'scripts' , 'build-schemas.ts' ) ;
185213 manifestDir = path . join ( sandbox , SCHEMA_MANIFEST_DIR_NAME ) ;
186214 surfaceDir = path . join ( sandbox , AUTHORABLE_SURFACE_DIR_NAME ) ;
215+ defaultsDir = path . join ( sandbox , AUTHORABLE_DEFAULTS_DIR_NAME ) ;
187216 surfaceBasePath = path . join ( sandbox , 'authorable-surface.base.json' ) ;
188217 // The authorable-surface ratchet runs after the manifest one; give it the
189218 // committed snapshot so a check that gets that far judges the same contract.
190219 writeSurfaceShards ( surfaceDir , pristineSurface ) ;
220+ // Same for the default-value ratchet (#4666), which runs after both: without
221+ // its committed record every fixture would fail on a missing artifact rather
222+ // than on the thing it is testing.
223+ writeDefaultsShards ( defaultsDir , pristineDefaults ) ;
191224 // Anchor for the #4650 deletion check: a git repo whose origin/main holds the
192225 // committed baseline. Only the baseline is tracked — src/node_modules stay
193226 // symlinked, untracked reads the same as any dirty worktree.
194227 git ( 'init' , '-q' , '-b' , 'main' , '.' ) ;
195- git ( 'add' , AUTHORABLE_SURFACE_DIR_NAME ) ;
228+ git ( 'add' , AUTHORABLE_SURFACE_DIR_NAME , AUTHORABLE_DEFAULTS_DIR_NAME ) ;
196229 git ( 'commit' , '-q' , '-m' , `baseline: committed ${ AUTHORABLE_SURFACE_DIR_NAME } /` ) ;
197230 // The in-tree anchor (#5235), authentic by construction: it mirrors the
198231 // baseline at the commit just made, which stays reachable from origin/main for
@@ -1827,12 +1860,16 @@ describe('build-schemas.ts — check (b) matches the exact retired key, not its
18271860 writeManifestShards ( path . join ( box , SCHEMA_MANIFEST_DIR_NAME ) , pristine ) ;
18281861 boxSurfaceDir = path . join ( box , AUTHORABLE_SURFACE_DIR_NAME ) ;
18291862 writeSurfaceShards ( boxSurfaceDir , pristineSurface ) ;
1863+ // The #4666 default ratchet runs on every invocation, so every box needs its
1864+ // committed record too — otherwise a fixture fails on a missing artifact
1865+ // instead of on the removal/rename it is actually testing.
1866+ writeDefaultsShards ( path . join ( box , AUTHORABLE_DEFAULTS_DIR_NAME ) , pristineDefaults ) ;
18301867 boxScript = path . join ( box , 'scripts' , 'build-schemas.ts' ) ;
18311868 boxRegistry = path . join ( box , 'src' , 'migrations' , 'registry.ts' ) ;
18321869 pristineRegistry = fs . readFileSync ( boxRegistry , 'utf8' ) ;
18331870
18341871 boxGit ( 'init' , '-q' , '-b' , 'main' , '.' ) ;
1835- boxGit ( 'add' , AUTHORABLE_SURFACE_DIR_NAME ) ;
1872+ boxGit ( 'add' , AUTHORABLE_SURFACE_DIR_NAME , AUTHORABLE_DEFAULTS_DIR_NAME ) ;
18361873 boxGit ( 'commit' , '-q' , '-m' , `baseline: committed ${ AUTHORABLE_SURFACE_DIR_NAME } /` ) ;
18371874 fs . writeFileSync (
18381875 path . join ( box , 'authorable-surface.base.json' ) ,
@@ -2137,10 +2174,11 @@ describe('build-schemas.ts — a deleted manifest key must prove itself (#4725)'
21372174
21382175 writeManifestShards ( boxManifestDir , pristine ) ;
21392176 writeSurfaceShards ( boxSurfaceDir , pristineSurface ) ;
2177+ writeDefaultsShards ( path . join ( box , AUTHORABLE_DEFAULTS_DIR_NAME ) , pristineDefaults ) ;
21402178 boxGit ( 'init' , '-q' , '-b' , 'main' , '.' ) ;
21412179 // BOTH artifacts tracked here: the merge-base manifest is what this gate
21422180 // reads, and the surface baseline keeps the #4650 gate honest alongside it.
2143- boxGit ( 'add' , SCHEMA_MANIFEST_DIR_NAME , AUTHORABLE_SURFACE_DIR_NAME ) ;
2181+ boxGit ( 'add' , SCHEMA_MANIFEST_DIR_NAME , AUTHORABLE_SURFACE_DIR_NAME , AUTHORABLE_DEFAULTS_DIR_NAME ) ;
21442182 boxGit ( 'commit' , '-q' , '-m' , 'baseline: committed manifest + authorable surface' ) ;
21452183 fs . writeFileSync (
21462184 path . join ( box , 'authorable-surface.base.json' ) ,
@@ -2466,7 +2504,7 @@ describe('build-schemas.ts — check (c) dates a tombstone by its exact key (#58
24662504 * so those lines read as deleted by this build (the main sandbox's shape). */
24672505 const seedBoxBase = ( ...extra : string [ ] ) : void => {
24682506 writeSurfaceShards ( boxSurfaceDir , [ ...pristineSurface , ...extra ] . sort ( ) ) ;
2469- boxGit ( 'add' , AUTHORABLE_SURFACE_DIR_NAME ) ;
2507+ boxGit ( 'add' , AUTHORABLE_SURFACE_DIR_NAME , AUTHORABLE_DEFAULTS_DIR_NAME ) ;
24702508 boxGit ( 'commit' , '-q' , '--allow-empty' , '-m' , 'base variant' ) ;
24712509 boxGit ( 'update-ref' , 'refs/remotes/origin/main' , boxGit ( 'rev-parse' , 'HEAD' ) ) ;
24722510 writeSurfaceShards ( boxSurfaceDir , pristineSurface ) ;
@@ -2495,12 +2533,16 @@ describe('build-schemas.ts — check (c) dates a tombstone by its exact key (#58
24952533 writeManifestShards ( path . join ( box , SCHEMA_MANIFEST_DIR_NAME ) , pristine ) ;
24962534 boxSurfaceDir = path . join ( box , AUTHORABLE_SURFACE_DIR_NAME ) ;
24972535 writeSurfaceShards ( boxSurfaceDir , pristineSurface ) ;
2536+ // The #4666 default ratchet runs on every invocation, so every box needs its
2537+ // committed record too — otherwise a fixture fails on a missing artifact
2538+ // instead of on the removal/rename it is actually testing.
2539+ writeDefaultsShards ( path . join ( box , AUTHORABLE_DEFAULTS_DIR_NAME ) , pristineDefaults ) ;
24982540 boxScript = path . join ( box , 'scripts' , 'build-schemas.ts' ) ;
24992541 boxRegistry = path . join ( box , 'src' , 'migrations' , 'registry.ts' ) ;
25002542 pristineRegistry = fs . readFileSync ( boxRegistry , 'utf8' ) ;
25012543
25022544 boxGit ( 'init' , '-q' , '-b' , 'main' , '.' ) ;
2503- boxGit ( 'add' , AUTHORABLE_SURFACE_DIR_NAME ) ;
2545+ boxGit ( 'add' , AUTHORABLE_SURFACE_DIR_NAME , AUTHORABLE_DEFAULTS_DIR_NAME ) ;
25042546 boxGit ( 'commit' , '-q' , '-m' , `baseline: committed ${ AUTHORABLE_SURFACE_DIR_NAME } /` ) ;
25052547 fs . writeFileSync (
25062548 path . join ( box , 'authorable-surface.base.json' ) ,
0 commit comments