test(pdf): apply owner-approved revised S01 baseline metric
This commit is contained in:
@@ -34,8 +34,8 @@
|
||||
"originalCorpus": { "const": "PASS" },
|
||||
"actualAccentClippingFix": { "const": "PASS_AUTOMATED_FINITE_CORPUS" },
|
||||
"unchangedRevisedOracle": { "const": "FAIL" },
|
||||
"proposedBaselineDiagnostic": { "const": "PASS_DIAGNOSTIC_ONLY_NOT_GATE_REPLACEMENT" },
|
||||
"metricDisposition": { "const": "OWNER_DECISION_REQUIRED" },
|
||||
"proposedBaselineDiagnostic": { "const": "PASS_OWNER_APPROVED_S01_Y_METRIC" },
|
||||
"metricDisposition": { "const": "OWNER_APPROVED_S01_METRIC_ONLY" },
|
||||
"humanVisual": { "const": "NOT_TESTED" },
|
||||
"actualPrinting": { "const": "NOT_TESTED" }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"kind": "OWNER_METRIC_DISPOSITION_ONLY",
|
||||
"receivedLocalDate": "2026-10-30",
|
||||
"timezone": "Europe/Paris",
|
||||
"source": "Direct human reply to the explicit scoped approval question in this task; transcribed evidence, not a protected controller signature",
|
||||
"candidateCommit": "ba04d817fed26d659bfa2a56b089d6cac851dc34",
|
||||
"designVersion": 2,
|
||||
"metric": "S01_Y_BASELINE_TO_BASELINE",
|
||||
"positionToleranceMm": 2,
|
||||
"ownerReply": "Approve the revised S01 metric only",
|
||||
"preserve": ["Original oracle and28Windows/20Linux failures", "Horizontal2mm limit", "All other font/color/page/content/bounds/marker checks", "Version1 metric and historical references"],
|
||||
"notGranted": ["Human visual acceptance", "Physical printing acceptance", "Phase10 entry", "Cleanup permission", "Controller/policy activation", "Production deployment"]
|
||||
}
|
||||
@@ -104,6 +104,20 @@ test('an imported schema cannot weaken the trusted schema', () => shadow(base =>
|
||||
test('model quality cannot become PASS from the rejected development probes', () => shadow(base => {
|
||||
json(base, 'ACCEPTANCE', value => { value.verdicts.find(item => item.criterion === 'CV AI Accuracy').status = 'PASS'; });
|
||||
}));
|
||||
|
||||
test('the scoped S01 disposition cannot authorise a larger tolerance', () => shadow(base => {
|
||||
json(base, 'S01_METRIC_APPROVAL', value => { value.positionToleranceMm = 3; });
|
||||
}));
|
||||
|
||||
test('approved S01 cannot conceal a failing revised baseline', () => shadow(base => {
|
||||
json(base, 'TEST_EVIDENCE', index => {
|
||||
const artifact = index.artifacts.find(item => item.id === 'p10-windows-classification');
|
||||
const file = path.join(base, artifact.path);
|
||||
const value = JSON.parse(zlib.gunzipSync(fs.readFileSync(file)));
|
||||
value.rows[0].pdfBaselinePx += 100;
|
||||
const bytes = zlib.gzipSync(JSON.stringify(value)); fs.writeFileSync(file, bytes); artifact.sha256 = hash(bytes);
|
||||
});
|
||||
}));
|
||||
test('a mandatory entry blocker cannot be self-deferred', () => shadow(base => {
|
||||
json(base, 'ACCEPTANCE', value => { value.permissibleDeferrals.push('P10-ENTRY-01'); });
|
||||
}));
|
||||
|
||||
@@ -19,6 +19,36 @@ export function verifyBytes(bytes, expected) {
|
||||
demand(Buffer.isBuffer(bytes) && /^[a-f0-9]{64}$/.test(expected) && digest(bytes) === expected, 'Missing or changed evidence');
|
||||
}
|
||||
|
||||
export function qualifyRevisedS01(oracle, baseline, measurements) {
|
||||
const unique = rows => {
|
||||
demand(Array.isArray(rows) && rows.length > 0 && new Set(rows.map(row => row.fixture)).size === rows.length, 'S01 missing or duplicate fixtures');
|
||||
return new Map(rows.map(row => [row.fixture, row]));
|
||||
};
|
||||
const originals = unique(oracle.fixtures), coordinates = unique(baseline.rows), documents = unique(measurements.fixtures);
|
||||
demand(oracle.total === originals.size && originals.size === coordinates.size && originals.size === documents.size, 'S01 corpus membership differs');
|
||||
const tolerance = oracle.tolerances;
|
||||
demand(tolerance.positionMm === 2 && tolerance.fontPt === .5 && tolerance.pageDimensionMm === .5 && tolerance.rgbComponent === 1 / 255, 'S01 original tolerances changed');
|
||||
const finite = value => demand(typeof value === 'number' && Number.isFinite(value), 'S01 nonfinite coordinate');
|
||||
const fixtures = [...originals].map(([fixture, original]) => {
|
||||
const row = coordinates.get(fixture), document = documents.get(fixture);
|
||||
demand(row && document && document.settings.designVersion === 2 && /^[a-f0-9]{64}$/.test(row.pdfSha256) && row.pdfSha256 === document.pdfSha256, 'S01 source/version binding differs');
|
||||
finite(row.domBaselinePx); finite(row.pdfBaselinePx);
|
||||
const baselineDeltaMm = Math.abs(row.domBaselinePx - row.pdfBaselinePx) * 25.4 / 96;
|
||||
// Only the S01 vertical cell-top comparison is superseded by the owner's baseline metric.
|
||||
const failures = original.failures.filter(value => !value.startsWith('S01: position delta '));
|
||||
demand(original.comparisons.filter(value => value.token === 'S01').length === 1, 'S01 marker missing or duplicated');
|
||||
for (const comparison of original.comparisons) {
|
||||
for (const key of ['deltaXmm', 'deltaYmm', 'fontDeltaPt']) { finite(comparison[key]); demand(comparison[key] >= 0, 'S01 invalid difference'); }
|
||||
if (comparison.colorDelta !== null) { finite(comparison.colorDelta); demand(comparison.colorDelta >= 0, 'S01 invalid color difference'); }
|
||||
const vertical = comparison.token === 'S01' ? baselineDeltaMm : comparison.deltaYmm;
|
||||
if (comparison.previewPage !== comparison.pdfPage || Math.max(comparison.deltaXmm, vertical) > 2 || comparison.fontDeltaPt > .5 || (comparison.colorDelta !== null && comparison.colorDelta > 1 / 255))
|
||||
failures.push(`${comparison.token}: retained position/page/font/color check failed`);
|
||||
}
|
||||
return { fixture, pdfSha256: row.pdfSha256, baselineDeltaMm, pass: failures.length === 0, failures };
|
||||
});
|
||||
return { metric: 'S01_Y_BASELINE_TO_BASELINE', positionToleranceMm: 2, total: fixtures.length, passed: fixtures.filter(row => row.pass).length, fixtures };
|
||||
}
|
||||
|
||||
export function measureNative(format, text) {
|
||||
demand(Buffer.byteLength(text, 'utf8') <= 8 * 1024 * 1024, 'Native report exceeds its input bound');
|
||||
const result = { passed: 0, failed: 0, skipped: 0, retries: 0, unexecuted: 0, names: [] };
|
||||
@@ -177,7 +207,7 @@ export function validatePackage(base = directory) {
|
||||
verifyBytes(fs.readFileSync(file), expected);
|
||||
}
|
||||
const verifierFiles = JSON.parse(artifact(evidence.verifierSourceArtifactId).toString('utf8'));
|
||||
const expectedVerifierFiles = ['verify.mjs', 'verify.test.mjs', 'package.test.mjs', 'verify_git.py', 'HANDOFF_SCHEMA.json'].map(name => 'docs/automation/handoffs/pre-phase10/' + name).sort();
|
||||
const expectedVerifierFiles = ['verify.mjs', 'verify.test.mjs', 'package.test.mjs', 'verify_git.py', 'HANDOFF_SCHEMA.json', 'S01_METRIC_APPROVAL.json'].map(name => 'docs/automation/handoffs/pre-phase10/' + name).sort();
|
||||
demand(JSON.stringify(Object.keys(verifierFiles).sort()) === JSON.stringify(expectedVerifierFiles), 'Missing verifier source membership');
|
||||
for (const [name, expected] of Object.entries(verifierFiles)) {
|
||||
verifyBytes(fs.readFileSync(path.join(root, name)), expected);
|
||||
@@ -203,14 +233,24 @@ export function validatePackage(base = directory) {
|
||||
demand(probe.cases?.length === 3 && probe.cases.every(item => item.status === 'REJECTED_OR_FAILED'), 'This snapshot lacks its recorded negative CV-model evidence');
|
||||
const oracles = evidence.reports.filter(item => ['windows-template-oracle', 'linux-template-oracle'].includes(item.id));
|
||||
demand(oracles.length === 2 && oracles.every(item => item.status === 'PARTIAL' && item.exitCode !== 0), 'Original PDF failures were concealed');
|
||||
demand(decisions.get('Automated PDF Fidelity') === 'FAIL' && decisions.get('PDF Spacing') === 'PARTIAL', 'Revised PDF failures were promoted');
|
||||
const approval = JSON.parse(artifact('s01-metric-approval').toString('utf8'));
|
||||
verifyBytes(artifact('s01-metric-approval'), digest(readSafe('S01_METRIC_APPROVAL.json')));
|
||||
demand(approval.candidateCommit === 'ba04d817fed26d659bfa2a56b089d6cac851dc34' && evidence.testedCommit === approval.candidateCommit && approval.metric === 'S01_Y_BASELINE_TO_BASELINE' && approval.positionToleranceMm === 2 && approval.designVersion === 2 && approval.ownerReply === 'Approve the revised S01 metric only', 'S01 owner approval scope differs');
|
||||
const revisedS01 = {};
|
||||
for (const platform of ['windows', 'linux']) {
|
||||
const parse = id => JSON.parse(artifact(id).toString('utf8'));
|
||||
const result = qualifyRevisedS01(parse(platform + '-template-oracle-native'), parse('p10-' + platform + '-classification'), parse(platform + '-template-measurements'));
|
||||
demand(result.total === 36 && result.passed === 36, 'Approved revised S01 fidelity failed');
|
||||
revisedS01[platform] = { passed: result.passed, total: result.total };
|
||||
}
|
||||
demand(decisions.get('Automated PDF Fidelity') === 'PASS' && decisions.get('PDF Spacing') === 'PARTIAL', 'Scoped PDF or human spacing decision differs');
|
||||
const stages = documents.GATES.stages;
|
||||
demand(stages.map(item => item.sequence).join(',') === '5,6,7,8,9,10,11' && stages[0].manualApprovals.includes('phase10-development-entry') && stages[0].manualApprovals.includes('candidate-specific-cleanup-scope') && stages.every(item => item.permissibleConditionalDeferrals.length === 0), 'Source-derived stage/approval conditions changed');
|
||||
const observedLocalCommit = execFileSync('rtk', ['proxy', 'git', 'rev-parse', 'HEAD'], { cwd: root, encoding: 'utf8' }).trim();
|
||||
const observedWorkingTreeClean = !execFileSync('rtk', ['proxy', 'git', 'status', '--porcelain'], { cwd: root, encoding: 'utf8' }).trim();
|
||||
const branch = execFileSync('rtk', ['proxy', 'git', 'branch', '--show-current'], { cwd: root, encoding: 'utf8' }).trim();
|
||||
demand(branch === declared.sourceBranch, 'Wrong checkout branch');
|
||||
return { integrity: 'PASS', testedCommit: evidence.testedCommit, observedLocalCommit, observedWorkingTreeClean, reports: evidence.reports.length, artifacts: evidence.artifacts.length, phase10: 'BLOCKED', ...requireProtectedEntry() };
|
||||
return { integrity: 'PASS', testedCommit: evidence.testedCommit, observedLocalCommit, observedWorkingTreeClean, reports: evidence.reports.length, artifacts: evidence.artifacts.length, revisedS01, phase10: 'BLOCKED', ...requireProtectedEntry() };
|
||||
}
|
||||
|
||||
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
||||
|
||||
@@ -1,6 +1,50 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { measureNative, verifyBytes, assertPass, requireProtectedEntry } from './verify.mjs';
|
||||
import * as verifier from './verify.mjs';
|
||||
|
||||
function s01Fixture() {
|
||||
const hash = 'a'.repeat(64);
|
||||
return [{ total: 1, tolerances: { positionMm: 2, fontPt: .5, pageDimensionMm: .5, rgbComponent: 1 / 255 }, fixtures: [{ fixture: 'short-en-modern', pass: false, failures: ['S01: position delta x=0.00mm y=2.92mm'], comparisons: [{ token: 'S01', previewPage: 1, pdfPage: 1, deltaXmm: 0, deltaYmm: 2.92, fontDeltaPt: 0, colorDelta: 0 }] }] },
|
||||
{ rows: [{ fixture: 'short-en-modern', pdfSha256: hash, domBaselinePx: 92, pdfBaselinePx: 92 }] },
|
||||
{ fixtures: [{ fixture: 'short-en-modern', pdfSha256: hash, settings: { designVersion: 2 } }] }];
|
||||
}
|
||||
|
||||
test('approved S01 changes only the vertical coordinate metric and retains historical results', () => {
|
||||
const inputs = s01Fixture();
|
||||
assert.equal(verifier.qualifyRevisedS01(...inputs).passed, 1);
|
||||
assert.equal(inputs[0].fixtures[0].pass, false);
|
||||
assert.equal(inputs[0].fixtures[0].failures.length, 1);
|
||||
});
|
||||
test('approved S01 still rejects horizontal and actual vertical shifts above2mm', () => {
|
||||
for (const horizontal of [true, false]) {
|
||||
const inputs = s01Fixture();
|
||||
if (horizontal) inputs[0].fixtures[0].comparisons[0].deltaXmm = 2.01;
|
||||
else inputs[1].rows[0].pdfBaselinePx += 2.01 * 96 / 25.4;
|
||||
assert.equal(verifier.qualifyRevisedS01(...inputs).passed, 0);
|
||||
}
|
||||
});
|
||||
test('approved S01 retains font color and page checks', () => {
|
||||
for (const patch of [{ fontDeltaPt: .51 }, { colorDelta: .01 }, { pdfPage: 2 }]) {
|
||||
const inputs = s01Fixture(); Object.assign(inputs[0].fixtures[0].comparisons[0], patch);
|
||||
assert.equal(verifier.qualifyRevisedS01(...inputs).passed, 0);
|
||||
}
|
||||
});
|
||||
test('approved S01 retains every unrelated original failure', () => {
|
||||
const inputs = s01Fixture(); inputs[0].fixtures[0].failures.push('page 1: hidden section leaked');
|
||||
assert.equal(verifier.qualifyRevisedS01(...inputs).passed, 0);
|
||||
});
|
||||
test('approved S01 rejects missing duplicate foreign PDFs and version1 input', () => {
|
||||
for (const mutate of [x => x[1].rows.pop(), x => x[1].rows.push(x[1].rows[0]), x => x[1].rows[0].pdfSha256 = 'b'.repeat(64), x => x[2].fixtures[0].settings.designVersion = 1]) {
|
||||
const inputs = s01Fixture(); mutate(inputs); assert.throws(() => verifier.qualifyRevisedS01(...inputs));
|
||||
}
|
||||
});
|
||||
test('approved S01 rejects nonfinite coordinates and recomputes claimed deltas', () => {
|
||||
const inputs = s01Fixture(); inputs[1].rows[0].pdfBaselinePx = NaN;
|
||||
assert.throws(() => verifier.qualifyRevisedS01(...inputs));
|
||||
inputs[1].rows[0].pdfBaselinePx = 112; inputs[1].rows[0].baselineDeltaMm = 0;
|
||||
assert.equal(verifier.qualifyRevisedS01(...inputs).passed, 0);
|
||||
});
|
||||
|
||||
test('native Jest membership and counters agree before PASS', () => {
|
||||
const result = measureNative('jest', JSON.stringify({ numTotalTests: 1, numPassedTests: 1, numFailedTests: 0, numPendingTests: 0, testResults: [{ name: 'fictional.test.ts', assertionResults: [{ fullName: 'preserves facts', status: 'passed' }] }] }));
|
||||
|
||||
Reference in New Issue
Block a user