@@ -3,11 +3,16 @@ import {cp, mkdir, mkdtemp, readFile, readdir, writeFile} from 'node:fs/promises
33import path from 'node:path' ;
44import { spawnSync } from 'node:child_process' ;
55import { fileURLToPath , pathToFileURL } from 'node:url' ;
6+ import { checkResultLinks } from './documentation/result-check.mjs' ;
67
78const repo = fileURLToPath ( new URL ( '../' , import . meta. url ) ) ;
89const [ consumer , tarball ] = process . argv . slice ( 2 ) ;
910if ( ! consumer || ! path . isAbsolute ( consumer ) || consumer . startsWith ( repo ) ) throw new Error ( 'Provide an external installed consumer directory.' ) ;
1011const work = await mkdtemp ( path . join ( consumer , 'documentation-' ) ) ;
12+ // Generated fixtures must still be reproducible through the installed core.
13+ // A shape-only check cannot establish field ownership or withdrawal identity.
14+ const generated = spawnSync ( process . execPath , [ path . join ( repo , 'scripts/generate-doc-scenarios.mjs' ) , consumer ] , { encoding : 'utf8' } ) ;
15+ if ( generated . status !== 0 ) throw new Error ( generated . stdout + generated . stderr ) ;
1116const examples = path . join ( work , 'examples' ) ;
1217await cp ( path . join ( repo , 'examples' ) , examples , { recursive : true } ) ;
1318function run ( command , args , overrides = { } ) {
@@ -25,11 +30,6 @@ const {StdioClientTransport} = await import(pathToFileURL(path.join(consumer, 'n
2530const { INTENT_RESULT_SCHEMA } = await import ( pathToFileURL ( path . join ( consumer , 'node_modules/@devcodex/intent-runtime/dist/index.js' ) ) . href ) ;
2631const { Validator} = await import ( pathToFileURL ( path . join ( consumer , 'node_modules/schema-dsl/dist/pure.cjs' ) ) . href ) ;
2732const validator = new Validator ( { logger : false , strict : false , useDefaults : false , coerceTypes : false , removeAdditional : false , allErrors : true } ) ;
28- function pointer ( root , text ) {
29- assert ( text === '' || text . startsWith ( '/' ) ) ;
30- assert ( ! / ~ (? ! [ 0 1 ] ) / u. test ( text ) ) ;
31- return text === '' ? root : text . slice ( 1 ) . split ( '/' ) . map ( s => s . replace ( / ~ 1 / g, '/' ) . replace ( / ~ 0 / g, '~' ) ) . reduce ( ( value , key ) => { assert ( value !== null && typeof value === 'object' && Object . hasOwn ( value , key ) , text ) ; return value [ key ] ; } , root ) ;
32- }
3333let resultExamples = 0 ;
3434for ( const stem of [ 'order' , 'clarification' ] ) {
3535 const input = JSON . parse ( await readFile ( path . join ( repo , 'website/content/public/examples/' + stem + '-request.json' ) , 'utf8' ) ) ;
@@ -41,24 +41,7 @@ for (const stem of ['order', 'clarification']) {
4141 const instanceConfig = input . config . instances [ input . request . instance ?? names [ 0 ] ] ;
4242 assert ( instanceConfig ) ;
4343 const materials = { ...instanceConfig , ...input . request } ;
44- function sources ( value ) {
45- if ( ! value || typeof value !== 'object' ) return ;
46- if ( 'root' in value && 'pointer' in value ) {
47- assert ( Object . hasOwn ( materials , value . root ) ) ;
48- const source = pointer ( materials [ value . root ] , value . pointer ) ;
49- if ( value . quote !== undefined ) assert ( ( typeof source === 'string' ? source : JSON . stringify ( source ) ) . includes ( value . quote ) ) ;
50- }
51- for ( const child of Object . values ( value ) ) sources ( child ) ;
52- }
53- sources ( result ) ;
54- const ids = new Set ( ) ;
55- function add ( value ) { assert ( ! ids . has ( value . id ) ) ; ids . add ( value . id ) ; }
56- function intents ( nodes ) { for ( const node of nodes ) { add ( node ) ; node . constraints . forEach ( add ) ; const local = new Set ( ) ; for ( const ref of node . references ) { assert ( ! local . has ( ref . id ) ) ; local . add ( ref . id ) ; } intents ( node . children ) ; } }
57- intents ( result . effective . intents ) ;
58- result . effective . constraints . forEach ( add ) ; result . effective . relations . forEach ( add ) ; result . issues . forEach ( add ) ;
59- for ( const change of result . turn . changes ) { if ( change . target . kind !== 'unresolved' ) assert ( ids . has ( change . target . id ) ) ; if ( change . conditionId ) assert ( ids . has ( change . conditionId ) ) ; }
60- for ( const id of result . turn . intentIds ) assert ( ids . has ( id ) ) ;
61- for ( const entry of result . evidence ?? [ ] ) pointer ( result , entry . target ) ;
44+ checkResultLinks ( result , materials ) ;
6245 resultExamples ++ ;
6346}
6447validator . clearCache ( ) ;
@@ -139,7 +122,7 @@ globalThis.fetch=async function(url,options){
139122 Object.assign(c.nodes[0],{domain:'订单',action:'查询',target:'订单000123',goal:'查询订单000123'});
140123 c.observations=[];
141124 const observation=(field,value)=>({ownerKey:'order',container:'inputs',field,presence:'known',withdrawn:false,valueJson:JSON.stringify(value),rawText:null,sources:[src],semantic:null});
142- if(request.input.includes('不取消订单' )){
125+ if(/不(?:要)?取消订单/.test( request.input)){
143126 c.constraints=[{key:'no-cancel',priorRef:null,ownerKey:'order',scope:'intent',referenceKey:null,kind:'prohibition',text:'不取消订单',expressionJson:null,sources:[src]}];
144127 c.changes.push({operation:'add',effect:'applied',targetKind:'constraint',targetKey:'no-cancel',conditionKey:null,description:'保留禁止取消约束',sources:[src],deltaHints:[]});
145128 }
@@ -159,13 +142,13 @@ globalThis.fetch=async function(url,options){
159142};
160143` ) ;
161144const runnableExamples = [ ] ;
162- for ( const name of [ 'basic' , 'parse' , 'multi-turn' ] ) {
145+ for ( const name of [ 'basic' , 'parse' , 'multi-turn' , 'native-response' ] ) {
163146 const trace = path . join ( work , name + '-results.json' ) ;
164147 const env = { INTENT_API_KEY : 'controlled-test-only' , INTENT_MODEL : 'controlled-language-reply' , INTENT_DOC_TRACE : trace , INTENT_DOC_FAILURE : '' } ;
165148 run ( process . execPath , [ '--import' , pathToFileURL ( preload ) . href , path . join ( examples , 'api' , name + '.mjs' ) ] , env ) ;
166149 const results = JSON . parse ( await readFile ( trace , 'utf8' ) ) . map ( record => record . result ) ;
167150 if ( name === 'basic' ) { assert . equal ( results . length , 1 ) ; assert . equal ( results [ 0 ] . fieldResults . length , 0 ) ; assert . equal ( results [ 0 ] . effective . intents [ 0 ] . constraints [ 0 ] . kind , 'prohibition' ) ; }
168- if ( name === 'parse' ) assert . equal ( results [ 0 ] . effective . intents [ 0 ] . inputs . orderId , '000123' ) ;
151+ if ( name === 'parse' || name === 'native-response' ) assert . equal ( results [ 0 ] . effective . intents [ 0 ] . inputs . orderId , '000123' ) ;
169152 if ( name === 'multi-turn' ) {
170153 assert . equal ( results . length , 3 ) ;
171154 const [ first , second , third ] = results ;
@@ -182,4 +165,4 @@ for (const name of ['basic', 'parse', 'multi-turn']) {
182165 runnableExamples . push ( { name, actualCoreResults : results . length , authenticationFailureHandled : true } ) ;
183166}
184167await writeFile ( path . join ( work , 'verification.json' ) , JSON . stringify ( { node : process . version , syntaxFiles, customExecutorStrictTypes : true , resultExamples, protocolRecords, globalMaintenance, runnableExamples, realProviderCalls : 0 , scope : 'User documentation installation/configuration/SDK examples and static result fixtures; not model semantic acceptance.' } , null , 2 ) + '\n' ) ;
185- console . log ( 'User examples verified: ' + syntaxFiles + ' ESM files, strict custom executor, ' + resultExamples + ' full responses, 3 actual SDK protocols, 3 runnable API examples and auth failure branches, ' + ( tarball ? 'isolated global setup/doctor/clean' : 'no new global install' ) + '.' ) ;
168+ console . log ( 'User examples verified: ' + syntaxFiles + ' ESM files, strict custom executor, ' + resultExamples + ' full responses, 3 actual SDK protocols, 4 runnable API examples and auth failure branches, ' + ( tarball ? 'isolated global setup/doctor/clean' : 'no new global install' ) + '.' ) ;
0 commit comments