Skip to content

Commit 43c7c91

Browse files
author
docgen-ci
committed
fix: preserve domain classification catalogs and align audit regressions
1 parent e9c5d8a commit 43c7c91

2 files changed

Lines changed: 15 additions & 8 deletions

File tree

global-template/docgen/lib/audit-guard.mjs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -125,11 +125,16 @@ function sanitizeSemanticObject(root, value, inventory, sourceCache) {
125125
const evidence = dedupeEvidence(evidenceFromAliases(value)
126126
.map((entry) => canonicalEvidence(root, entry, inventory, sourceCache))
127127
.filter(Boolean));
128-
const requested = normalizeClassification(value.classification ?? value.claimClassification ?? value.certainty);
128+
const rawClassification = value.classification ?? value.claimClassification ?? value.certainty;
129+
const scalarClassification = rawClassification === undefined || typeof rawClassification === 'string' || typeof rawClassification === 'number';
130+
const requested = normalizeClassification(rawClassification);
129131
const hasLineEvidence = evidence.some((entry) => entry.startLine && !entry.__stale);
130-
value.classification = requested === 'FACT' && !hasLineEvidence ? 'INFERENCE' : requested;
131-
value.confidence = normalizeConfidence(value.confidence ?? value.confidenceScore, value.classification);
132-
if (value.classification !== 'FACT') value.confidence = Math.min(value.confidence, 0.7);
132+
const normalizedClassification = requested === 'FACT' && !hasLineEvidence ? 'INFERENCE' : requested;
133+
// A field named `classification` can be a domain catalog rather than semantic
134+
// metadata. Preserve arrays/objects and only normalize scalar metadata.
135+
if (scalarClassification) value.classification = normalizedClassification;
136+
value.confidence = normalizeConfidence(value.confidence ?? value.confidenceScore, normalizedClassification);
137+
if (scalarClassification && normalizedClassification !== 'FACT') value.confidence = Math.min(value.confidence, 0.7);
133138
value.evidence = evidence.map(({ __stale, ...entry }) => entry);
134139
removeEvidenceAliases(value);
135140
delete value.claimClassification;

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

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -189,14 +189,16 @@ test('recovery never accepts stale pre-existing plan artifacts when provider wri
189189
assert.equal(readJson(p.state).stages.plan.status, 'failed');
190190
});
191191

192-
test('audit rejects unknown model references and publish rejects stale source artifacts', async () => {
192+
test('audit sanitizes unknown model references and publish rejects stale source artifacts', async () => {
193193
const root = fixture(); const p = projectPaths(root); const provider = installFakeProvider(root);
194194
fs.writeFileSync(path.join(root, 'src', 'Resource.java'), 'class Resource {}\n');
195195
const config = readJson(p.config); config.commandCode = { executable: provider, trust: false, skipOnboarding: false, yolo: false, maxTurns: { default: 30 } }; writeJson(p.config, config);
196196
const run = spawnSync(process.execPath, [cli, 'all'], { cwd: root, encoding: 'utf8', env: { ...process.env, DOCGEN_PROGRESS: '0' } }); assert.equal(run.status, 0, run.stderr || run.stdout);
197197
const traceFile = path.join(p.traceability, 'pages', 'overview.json'); const trace = readJson(traceFile); trace.claims[0].sourceModelRefs = ['system:does-not-exist']; writeJson(traceFile, trace);
198-
await assert.rejects(() => audit(root), /Quality failed/); const report = readJson(path.join(p.audit, 'deterministic.json')); assert(report.errors.some((error) => /unknown sourceModelRef/.test(error)));
199-
trace.claims[0].sourceModelRefs = ['system:resource']; writeJson(traceFile, trace); await audit(root);
198+
const summary = await audit(root);
199+
const sanitizedTrace = readJson(traceFile);
200+
assert.deepEqual(sanitizedTrace.claims[0].sourceModelRefs, []);
201+
assert.equal(summary.deterministicFailures, 0);
200202
fs.appendFileSync(path.join(root, 'src', 'Resource.java'), '// stale\n');
201203
assert.throws(() => publish(root), /stale relative to current source/);
202204
});
@@ -221,7 +223,7 @@ test('enterprise model bundle repairs a missing decisions object without discard
221223
const config = readJson(p.config); config.commandCode = { executable: provider, trust: false, skipOnboarding: false, yolo: false, maxTurns: { default: 30 } }; config.budget.maxProviderCalls = 12; writeJson(p.config, config);
222224
const run = spawnSync(process.execPath, [cli, 'all'], { cwd: root, encoding: 'utf8', env: { ...process.env, DOCGEN_PROGRESS: '0', DOCGEN_TEST_OMIT_MODEL_ONCE: 'decisions' } });
223225
assert.equal(run.status, 0, `STDERR:\n${run.stderr}\nSTDOUT:\n${run.stdout}`);
224-
assert.match(run.stderr, /modelEnterprise REPAIR \| bundle omitted decisions/);
226+
assert.match(run.stderr, /modelEnterprise REPAIR \| unresolved: decisions/);
225227
assert.equal(fs.existsSync(path.join(p.model, 'decisions.json')), true);
226228
assert.equal(readJson(p.state).stages.modelEnterprise.status, 'completed');
227229
const budget = readJson(p.budget); assert.equal(budget.usage.providerCalls, 5); assert.equal(budget.usage.failedCalls, 0);

0 commit comments

Comments
 (0)