diff --git a/tools/verify-quality-center-ux-1.44.0.mjs b/tools/verify-quality-center-ux-1.44.0.mjs new file mode 100644 index 0000000..b698746 --- /dev/null +++ b/tools/verify-quality-center-ux-1.44.0.mjs @@ -0,0 +1,112 @@ +import fs from 'node:fs'; +import path from 'node:path'; + +const root = process.cwd(); +const read = relative => fs.readFileSync(path.join(root, relative), 'utf8'); +const js = read('public/quality-center-ux.js'); +const css = read('public/quality-center-ux.css'); +const runtime = read('public/design-system/theme-runtime.js'); +const html = read('public/index.html'); +const pkg = JSON.parse(read('package.json')); + +const failures = []; +const expect = (condition, message) => { + if (!condition) failures.push(message); +}; +const includesAll = (source, values, label) => { + for (const value of values) expect(source.includes(value), `${label}: ${value}`); +}; + +includesAll(html, [ + 'id="quality-center"', + 'id="quality-summary-average"', + 'id="quality-summary-ready"', + 'id="quality-summary-blocked"', + 'id="quality-summary-total"', + 'id="quality-search"', + 'id="quality-status"', + 'id="quality-grade"', + 'id="quality-list"', + 'id="quality-detail-content"', + 'id="quality-readiness"', + 'id="quality-open-article"', + 'id="quality-open-ai"', + 'id="quality-run-analysis"', + 'id="quality-issues"', + 'data-quality-issue-filter="error"', + 'class="quality-duplicates"', + 'class="quality-images"', + 'class="quality-history"', +], 'Bestehender Quality-Center-Vertrag fehlt'); + +includesAll(runtime, [ + 'quality-center-ux.css?v=1.44.0', + 'quality-center-ux.js?v=1.44.0', + 'data-ux-quality-center', + 'loadQualityCenterAssets()', +], 'Theme-Runtime bindet Quality Center nicht vollständig ein'); + +expect(pkg.scripts?.['verify:quality-center-ux'] === 'node tools/verify-quality-center-ux-1.44.0.mjs', 'verify:quality-center-ux Script fehlt'); +expect(pkg.scripts?.['verify:all']?.includes('npm run verify:quality-center-ux'), 'verify:all enthält das Quality-Center-Gate nicht'); + +includesAll(js, [ + 'ux-quality-priority-board', + 'data-ux-quality-status', + 'ux-quality-filter-panel', + 'ux-quality-filter-chips', + 'ux-quality-main-actions', + 'ux-quality-more-actions', + 'ux-quality-issue-section', + 'ux-quality-secondary', + 'quality-summary-blocked', + 'quality-summary-ready', + 'quality-summary-total', + 'quality-status', + 'quality-open-article', + 'quality-open-ai', + 'quality-run-analysis', + 'quality-readiness', + 'quality-issues', + 'MutationObserver', + 'requestAnimationFrame', + 'scrollIntoView', + 'aria-pressed', + 'ArrowLeft', + 'ArrowRight', +], 'Quality-Center-UX-Vertrag fehlt'); + +includesAll(css, [ + '#quality-center.ux-quality-center-ready', + '.ux-quality-priority-board', + '.ux-quality-priorities', + '.ux-quality-filter-panel', + '.ux-quality-filter-chips', + '.ux-quality-main-actions', + '.ux-quality-issue-section', + '.ux-quality-secondary', + '@media (max-width: 760px)', + '@media (max-width: 470px)', + '@media (prefers-reduced-motion: reduce)', + ':focus-visible', + 'var(--', +], 'Quality-Center-CSS-Vertrag fehlt'); + +expect(!/\bfetch\s*\(/.test(js), 'Additive Quality-Center-UX darf keine eigenen Netzwerkaufrufe ausführen'); +expect(!/\bapi\s*\(/.test(js), 'Additive Quality-Center-UX darf die Vendoo-API nicht direkt aufrufen'); +expect(!/\.innerHTML\s*=/.test(js), 'Quality-Center-UX darf keine innerHTML-Zuweisungen verwenden'); +expect(!/\.outerHTML\s*=/.test(js), 'Quality-Center-UX darf keine outerHTML-Zuweisungen verwenden'); +expect(!/\.onclick\s*=/.test(js), 'Quality-Center-UX darf keine onclick-Zuweisungen verwenden'); +expect(!/confirm\s*\(/.test(js), 'Gefährliche Quality-Center-Aktionen müssen in der bestehenden geprüften Logik bleiben'); +expect(!/\b(?:DELETE|PATCH|POST|PUT)\b/.test(js), 'Quality-Center-UX darf keine Schreiboperationen implementieren'); +expect(!/runQualityAnalysis\s*\(/.test(js), 'UX-Schicht darf keine Qualitätsanalyse direkt auslösen'); +expect(!/generateQualityAiSuggestion\s*\(/.test(js), 'UX-Schicht darf keine AI-Korrektur direkt auslösen'); +expect(!/applyQualityAiSuggestion\s*\(/.test(js), 'UX-Schicht darf keine AI-Vorschläge direkt anwenden'); +expect(!/state\.quality/.test(js), 'Additive UX darf den produktiven Quality-State nicht direkt verändern'); + +if (failures.length) { + console.error('Quality Center UX Gate fehlgeschlagen:'); + for (const failure of failures) console.error(`- ${failure}`); + process.exit(1); +} + +console.log('Quality Center UX Gate bestanden.'); \ No newline at end of file