Files
workdsh/workdsh-web/scripts/validate-acceptance.mjs
techflag 748234a317 Add 'workdsh-web/' from commit '03b63ea143747b6c75e1f60bace0d9f338918455'
git-subtree-dir: workdsh-web
git-subtree-mainline: d3a7b2143d
git-subtree-split: 03b63ea143
2026-09-26 10:26:35 +08:00

28 lines
1.8 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { existsSync, readFileSync } from 'node:fs';
import { resolve, relative } from 'node:path';
export function validateAcceptance(root) {
const failures = [];
const data = JSON.parse(readFileSync(resolve(root, 'docs/acceptance.json'), 'utf8'));
const doc = readFileSync(resolve(root, 'docs/ACCEPTANCE.md'), 'utf8');
const ledger = readFileSync(resolve(root, 'docs/STATUS.md'), 'utf8');
const described = new Set([...doc.matchAll(/^\| ((?:A|UI)\d+) \||^- ((?:T|J|B|Q)\d+(?:-P\d)?):/gm)].map(m => m[1] || m[2]));
const seen = new Set();
for (const item of data.cases) {
if (seen.has(item.id)) failures.push(`Duplicate acceptance: ${item.id}`);
seen.add(item.id);
if (!described.has(item.id)) failures.push(`Missing scenario description: ${item.id}`);
if (!['基础', 'P0', 'P1', 'P2', 'P3'].includes(item.phase)) failures.push(`Invalid single phase: ${item.id}`);
if (!['pending', 'passed', 'failed', 'blocked'].includes(item.status)) failures.push(`Invalid acceptance status: ${item.id}`);
if (!Array.isArray(item.tasks) || !item.tasks.length) failures.push(`Missing acceptance tasks: ${item.id}`);
else for (const task of item.tasks) if (!ledger.includes(`| ${task} |`)) failures.push(`Unknown task: ${task}`);
if (!Array.isArray(item.evidence)) { failures.push(`Invalid evidence: ${item.id}`); continue; }
if (item.status === 'passed' && !item.evidence.length) failures.push(`Passed without evidence: ${item.id}`);
for (const path of item.evidence) {
const target = resolve(root, path);
if (relative(root, target).startsWith('..') || !existsSync(target)) failures.push(`Invalid evidence path: ${item.id}`);
}
}
for (const id of described) if (!seen.has(id)) failures.push(`Unmapped acceptance: ${id}`);
return { failures, cases: data.cases };
}