@@ -6,9 +6,17 @@ import {
66 Format ,
77 FieldKind ,
88 PromptStyle ,
9+ recover ,
10+ recoverSchema ,
11+ scalar ,
12+ enumField ,
13+ object ,
14+ FieldRecovery ,
915 type OutputFormatSpec ,
1016 type PromptField ,
1117 type PromptOverrides ,
18+ type RecoverSchema ,
19+ type FieldSpec ,
1220} from "../src/index.js" ;
1321
1422// The shared corpus lives at the repo root. This file is at
@@ -60,6 +68,15 @@ function buildOutputSpec(c: CaseSpec): OutputFormatSpec {
6068 return { format : toFormat ( c . format ) , rootName : c . rootName , style : PromptStyle . GUIDE , fields } ;
6169}
6270
71+ function buildRecoverSchema ( c : CaseSpec ) : RecoverSchema {
72+ const fields : FieldSpec [ ] = c . fields . map ( ( f ) => {
73+ if ( f . kind === "ENUM" ) return enumField ( f . name , f . required , f . enumValues ?? null , { } ) ;
74+ if ( f . kind === "OBJECT" ) return object ( f . name , f . required , f . array ?? false , f . nested ? buildRecoverSchema ( f . nested ) : null ) ;
75+ return scalar ( f . name , FieldKind [ f . kind ] , f . required ) ;
76+ } ) ;
77+ return recoverSchema ( toFormat ( c . format ) , c . rootName , fields ) ;
78+ }
79+
6380describe ( "output-prompt-conformance corpus" , ( ) => {
6481 const names = existsSync ( CORPUS )
6582 ? readdirSync ( CORPUS )
@@ -89,6 +106,19 @@ describe("output-prompt-conformance corpus", () => {
89106 // determinism: identical across runs
90107 expect ( renderOutputFormat ( ofs , overrides ) ) . toBe ( actual ) ;
91108 }
109+
110+ if ( spec . roundTrip ) {
111+ const exampleFragment = readFileSync ( join ( dir , "expected.exampleOnly.txt" ) , "utf8" ) ;
112+ const outcome = recover ( exampleFragment , buildRecoverSchema ( spec ) ) ;
113+ // Skew guard: a field the renderer emitted must read back cleanly. We assert
114+ // NO state is MALFORMED or LOST_* (robust to DEFAULTED and to how a nested
115+ // OBJECT-container path classifies); any such state means the renderer emitted
116+ // an example the recover parser cannot read.
117+ const bad = [ FieldRecovery . MALFORMED , FieldRecovery . LOST_REQUIRED , FieldRecovery . LOST_OPTIONAL ] as const ;
118+ for ( const [ field , state ] of outcome . report . states ( ) ) {
119+ expect ( [ field , bad . includes ( state as ( typeof bad ) [ number ] ) ] ) . toEqual ( [ field , false ] ) ;
120+ }
121+ }
92122 } ) ;
93123 }
94124} ) ;
0 commit comments