Skip to content

Commit 0949e45

Browse files
add zero-provider-resume end-to-end test
1 parent f46874f commit 0949e45

1 file changed

Lines changed: 45 additions & 1 deletion

File tree

global-template/docgen/test/semantic-index.test.mjs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ function fixture() {
1919
fs.mkdirSync(path.join(root, 'src'), { recursive: true });
2020
fs.mkdirSync(path.dirname(p.config), { recursive: true });
2121
writeJson(p.project, { schemaVersion: '2.0', kitVersion: '2.0.0' });
22-
writeJson(p.config, { schemaVersion: '2.0', projectName: 'Fixture', ignore: { useGitignore: true, useDocgenignore: true, binary: { enabled: true, maxTextFileBytes: 1024 * 1024 } }, context: { maxTokens: { default: 4000, generate: 4000 } }, execution: { generationBatchSize: 2, maxPlannedPages: 30 }, audit: { llmEnabled: false } });
22+
writeJson(p.config, { schemaVersion: '2.0', projectName: 'Fixture', ignore: { useGitignore: true, useDocgenignore: true, binary: { enabled: true, maxTextFileBytes: 1024 * 1024 } }, context: { maxTokens: { default: 4000, modelCore: 4000, modelEnterprise: 4000, plan: 4000, generate: 4000, audit: 2000 } }, budget: { maxProviderCalls: 10, maxEstimatedInputTokens: 200000, maxEstimatedOutputTokens: 50000, maxContextTokensPerCall: 10000 }, execution: { generationBatchSize: 2, maxPlannedPages: 30 }, audit: { llmEnabled: false }, retry: { maxAttempts: 1 } });
2323
writeJson(p.state, { schemaVersion: '2.0', kitVersion: '2.0.0', stages: {}, pages: {} });
2424
return root;
2525
}
@@ -34,6 +34,39 @@ function catalogFixture(root) {
3434
return p;
3535
}
3636

37+
function installFakeProvider(root) {
38+
const file = path.join(root, 'fake-provider.mjs');
39+
fs.writeFileSync(file, `#!/usr/bin/env node
40+
import fs from 'node:fs';
41+
import path from 'node:path';
42+
const prompt=fs.readFileSync(0,'utf8');
43+
const stage=process.env.DOCGEN_STAGE;
44+
const cwd=process.cwd();
45+
const target=(prompt.match(/Write exactly one JSON file: \\`([^\\`]+)\\`/i)||[])[1];
46+
const write=(rel,value)=>{const file=path.join(cwd,rel);fs.mkdirSync(path.dirname(file),{recursive:true});fs.writeFileSync(file,JSON.stringify(value,null,2)+'\\n');};
47+
if(stage==='modelCore'){
48+
write(target,{system:{components:[{id:'resource',kind:'component',name:'Resource',statement:'HTTP resource',classification:'FACT',confidence:1,evidence:[{path:'src/Resource.java',startLine:1}]}],relationships:[],workflows:[],unknowns:[]},business:{actors:[],capabilities:[],concepts:[],businessRules:[],decisions:[],branchConditions:[],lifecycles:[],invariants:[],useCases:[],unknowns:[]},flows:{businessFlows:[],controlFlows:[],requestFlows:[],trafficFlows:[],dataFlows:[],eventFlows:[]},catalogs:{endpoints:[],messageHandlers:[],externalDependencies:[],dataStores:[],scheduledJobs:[]}});
49+
}else if(stage==='modelEnterprise'){
50+
write(target,{security:{unknowns:[]},operations:{unknowns:[]},testing:{unknowns:[]},'data-governance':{unknowns:[]},decisions:{unknowns:[]},configuration:{unknowns:[]},'change-impact':{unknowns:[]},ownership:{unknowns:[]}});
51+
}else if(stage==='plan'){
52+
write(target,{schemaVersion:'2.0',metadata:{description:'Fixture docs'},pages:[{id:'overview',title:'System Overview',summary:'Fixture overview.',category:'orientation',mode:'explanation',type:'overview',order:1,audience:['engineer'],coverageTags:['architecture'],query:'resource architecture',requiredSections:[],risk:'low',relatedPages:[]}]});
53+
}else if(stage==='generate'){
54+
const json=(prompt.match(/Page contracts:\\n([\\s\\S]*?)\\n\\nFor every contract:/)||[])[1];
55+
const contracts=JSON.parse(json);
56+
for(const contract of contracts){
57+
const page=contract.page;
58+
const md='---\\ntitle: '+JSON.stringify(page.title)+'\\ndescription: '+JSON.stringify(page.summary)+'\\npageId: '+JSON.stringify(page.id)+'\\ncategory: '+JSON.stringify(page.category)+'\\nmode: '+JSON.stringify(page.mode)+'\\ntype: '+JSON.stringify(page.type)+'\\norder: '+page.order+'\\n---\\n# '+page.title+'\\n\\n'+page.summary+'\\n\\nThe repository exposes an HTTP resource.\\n';
59+
const output=path.join(cwd,contract.outputPath);fs.mkdirSync(path.dirname(output),{recursive:true});fs.writeFileSync(output,md);
60+
write(contract.traceabilityPath,{schemaVersion:'2.0',pageId:page.id,pagePath:contract.outputPath,claims:[{id:page.id+':resource',section:page.title,statement:'The repository exposes an HTTP resource.',classification:'FACT',confidence:1,evidence:[{path:'src/Resource.java',startLine:1}],sourceModelRefs:['system:resource']}]});
61+
}
62+
}else if(stage==='audit'){
63+
const output=(prompt.match(/report: \\`([^\\`]+)\\`/i)||[])[1]||'.docgen/audit/llm-risk.json';write(output,{schemaVersion:'2.0',pages:[]});
64+
}else{process.exitCode=2;console.error('unexpected stage '+stage);}
65+
`);
66+
fs.chmodSync(file, 0o755);
67+
return file;
68+
}
69+
3770
test('inventory excludes binary and docgenignore paths', () => {
3871
const root = fixture();
3972
fs.writeFileSync(path.join(root, 'src', 'Resource.java'), '@Path("/quotes")\nclass Resource { @GET void get() {} }\n');
@@ -98,6 +131,17 @@ test('deterministic audit rejects FACT evidence outside inventory', async () =>
98131
await assert.rejects(() => audit(root), /Quality failed/);
99132
});
100133

134+
test('full indexed pipeline uses four provider calls then zero on resume', () => {
135+
const root = fixture(); const p = projectPaths(root); const provider = installFakeProvider(root);
136+
fs.writeFileSync(path.join(root, 'src', 'Resource.java'), '@Path("/quotes")\nclass Resource { @GET void get() {} }\n');
137+
const config = readJson(p.config); config.commandCode = { executable: provider, trust: false, skipOnboarding: false, yolo: false, verbose: false, maxTurns: { default: 4 } }; writeJson(p.config, config);
138+
const first = spawnSync(process.execPath, [cli, 'all'], { cwd: root, encoding: 'utf8' }); assert.equal(first.status, 0, first.stderr || first.stdout);
139+
const firstBudget = readJson(p.budget); assert.equal(firstBudget.usage.providerCalls, 4);
140+
const second = spawnSync(process.execPath, [cli, 'all'], { cwd: root, encoding: 'utf8' }); assert.equal(second.status, 0, second.stderr || second.stdout);
141+
const secondBudget = readJson(p.budget); assert.equal(secondBudget.usage.providerCalls, 4);
142+
assert.equal(readJson(path.join(p.audit, 'quality-summary.json')).pass, true);
143+
});
144+
101145
test('v1 migration preserves docs and ignore policy while archiving workflow state', () => {
102146
const root = fixture(); const p = projectPaths(root);
103147
writeJson(p.config, { schemaVersion: '1.6', projectName: 'Migrated', commandCode: { executable: 'custom-cmdc', model: 'cheap-model' }, ignore: { useGitignore: true, binary: { maxTextFileBytes: 123456 } } });

0 commit comments

Comments
 (0)