diff --git a/scripts/ai-generation-guard.mjs b/scripts/ai-generation-guard.mjs
index 8f96be3..a3996f6 100644
--- a/scripts/ai-generation-guard.mjs
+++ b/scripts/ai-generation-guard.mjs
@@ -90,7 +90,7 @@ async function inspect(options) {
const parseJS = (text, file) => parse(text, { sourceType: 'unambiguous', plugins: [...(/\.[cm]?tsx?$/.test(file) ? ['typescript'] : []), 'jsx'], createImportExpressions: true });
const contracts = new Map();
// Parse public barrels and manifest exports for import contracts.
- // Implementation text is only a conservative blocker for CSS scope exclusions.
+ // Implementation class bindings only conservatively block CSS scope exclusions.
for (const [pkg, dir] of [['@hm-design/ui', 'ui'], ['@hm-design/center-graphic', 'center-graphic']]) {
const base = path.join(workspace, 'packages', dir);
const manifest = JSON.parse(fs.readFileSync(path.join(base, 'package.json'), 'utf8'));
@@ -465,7 +465,7 @@ async function inspect(options) {
&& (records.some(record => normalize(path.relative(target, record.file)) === issue.file) || issue.file === normalize(path.relative(target, entry.file)) || !issue.file));
for (const [required, feature, code, label] of [[runtimeUI || uiComponents, 'theme', 'CSS-001', 'Theme CSS'], [utilities, 'utilities', 'CSS-002', 'Tailwind utility CSS entry'], [status, 'status', 'CSS-003', 'Public @hm-design/ui/dashboard-status.css entry']]) if (required && !cssFeatures.has(feature)) add(incompleteCSSGraph ? 'NOT VERIFIED' : 'FAIL', code, focus[0]?.file ?? entry.file, null, incompleteCSSGraph ? `${label} connection is not proven; resolve the incomplete bootstrap / CSS graph` : `Required ${label} is missing from the resolved bootstrap / CSS graph`, true);
}
- styleChecks = styleAnalysis({ records: [...graph.values()].filter(r => applicableFiles.has(r.file)), target, postcss, walk, selectedFile, knownSlot, origin, add, storybook, scopeRecords: [...graph.values()], implementationFiles: contractFiles.filter(f => f.startsWith('packages/')).map(f => path.join(workspace, f)), entries: entries.map(e => e.file), scopeIncomplete: storybook || issues.some(i => /^(?:ENTRY-|CORE-|CSS-005|SB-004)/.test(i.code)) });
+ styleChecks = styleAnalysis({ records: [...graph.values()].filter(r => applicableFiles.has(r.file)), target, postcss, walk, parseJS, selectedFile, knownSlot, origin, add, storybook, scopeRecords: [...graph.values()], implementationFiles: contractFiles.filter(f => f.startsWith('packages/')).map(f => path.join(workspace, f)), entries: entries.map(e => e.file), scopeIncomplete: storybook || issues.some(i => /^(?:ENTRY-|CORE-|CSS-005|SB-004)/.test(i.code)) });
return finish();
function finish() {
const styleEvidence = { staticStatus: verdict(styleChecks.map(c => c.staticStatus)), runtimeStatus: 'NOT VERIFIED', designIntentStatus: verdict(styleChecks.map(c => c.designIntentStatus)), finalStatus: styleChecks.some(c => c.staticStatus === 'FAIL') ? 'FAIL' : 'NOT VERIFIED', checks: styleChecks };
diff --git a/scripts/ai-generation-guard.test.mjs b/scripts/ai-generation-guard.test.mjs
index 2883bf5..bfae4ab 100644
--- a/scripts/ai-generation-guard.test.mjs
+++ b/scripts/ai-generation-guard.test.mjs
@@ -7,6 +7,9 @@ import { spawnSync } from 'node:child_process';
import { createHash } from 'node:crypto';
import { performance } from 'node:perf_hooks';
import test from 'node:test';
+import { parse } from '@babel/parser';
+import postcss from 'postcss';
+import { styleAnalysis } from './guard-style-analysis.mjs';
test('64. finite conditional templates and concatenation validate every Token branch', () => {
fixture({ 'src/App.tsx': 'import { Button } from "@hm-design/ui"; const name = location.hash ? "fg-primary" : "bg-content"; export default () => ' }, root => {
@@ -861,3 +864,161 @@ test('86. Component implementation classes and unrelated graph mutations stay pr
assert.equal(r.styleEvidence.checks.find(c => c.selector.startsWith('.legacy')).applicability.classInputsComplete, false);
});
});
+
+// Exercise implementation binding analysis without editing the real packages.
+function implementationFixture(source, callback, extra = {}) {
+ fixture({
+ 'src/App.tsx': 'export default () =>