mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-20 18:16:30 +03:00
feat(detector): deprecate --fast (now a no-op, full scan always)
Since the jsdom removal the static HTML/CSS analysis is fast (~4ms/file) and covers every rule, so the regex-only `--fast` path only loses coverage (it ran ~10 of 41 rules) for no real speed win. It's a foot-gun: a `--fast` scan can read "clean" because most rules silently don't run. Deprecate gracefully rather than hard-remove: the flag is still accepted (so existing CI scripts don't break) but ignored, with a one-line stderr notice, and the full scan always runs. Dropped from --help and the example. Removed the `--fast` suggestion from the many-files warning and from critique.md's scan guidance. Ships to users via a CLI release (npm) and rides the next skill release in the bundled detector. Tests updated to assert the deprecation behavior. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
772aa73aa3
commit
f7f2bfc800
@@ -58,12 +58,12 @@ Run the bundled detector and browser visualization evidence. Assessment B is man
|
|||||||
|
|
||||||
CLI scan:
|
CLI scan:
|
||||||
```bash
|
```bash
|
||||||
node .agents/skills/impeccable/scripts/detect.mjs --json [--fast] [target]
|
node .agents/skills/impeccable/scripts/detect.mjs --json [target]
|
||||||
```
|
```
|
||||||
|
|
||||||
- Pass markup files/directories as `[target]`; do not pass CSS-only files.
|
- Pass markup files/directories as `[target]`; do not pass CSS-only files.
|
||||||
- For URLs, skip CLI scan and use browser visualization.
|
- For URLs, skip CLI scan and use browser visualization.
|
||||||
- For 200+ scannable files, use `--fast`; for 500+, narrow scope or ask.
|
- For very large trees (500+ scannable files), narrow scope or ask.
|
||||||
- Exit code 0 = clean; 2 = findings.
|
- Exit code 0 = clean; 2 = findings.
|
||||||
- If the detector entrypoint is missing or fails to load, report deterministic scan unavailable and continue with browser/manual review.
|
- If the detector entrypoint is missing or fails to load, report deterministic scan unavailable and continue with browser/manual review.
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,6 @@ function printUsage() {
|
|||||||
Scan files or URLs for UI anti-patterns and design quality issues.
|
Scan files or URLs for UI anti-patterns and design quality issues.
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--fast Regex-only mode (skip static HTML/CSS analysis, faster but misses linked stylesheets)
|
|
||||||
--json Output results as JSON
|
--json Output results as JSON
|
||||||
--gpt Also report GPT-specific provider tells (off by default)
|
--gpt Also report GPT-specific provider tells (off by default)
|
||||||
--gemini Also report Gemini-specific provider tells (off by default)
|
--gemini Also report Gemini-specific provider tells (off by default)
|
||||||
@@ -89,13 +88,12 @@ Detection modes:
|
|||||||
HTML files Static HTML/CSS analysis (default, catches linked CSS)
|
HTML files Static HTML/CSS analysis (default, catches linked CSS)
|
||||||
Non-HTML files Regex pattern matching (CSS, JSX, TSX, etc.)
|
Non-HTML files Regex pattern matching (CSS, JSX, TSX, etc.)
|
||||||
URLs Puppeteer full browser rendering (auto-detected)
|
URLs Puppeteer full browser rendering (auto-detected)
|
||||||
--fast Forces regex for all files
|
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
impeccable detect src/
|
impeccable detect src/
|
||||||
impeccable detect index.html
|
impeccable detect index.html
|
||||||
impeccable detect https://example.com
|
impeccable detect https://example.com
|
||||||
impeccable detect --fast --json .`);
|
impeccable detect --json .`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function detectCli() {
|
async function detectCli() {
|
||||||
@@ -107,7 +105,15 @@ async function detectCli() {
|
|||||||
if (args[0] === 'detect') args = args.slice(1);
|
if (args[0] === 'detect') args = args.slice(1);
|
||||||
const jsonMode = args.includes('--json');
|
const jsonMode = args.includes('--json');
|
||||||
const helpMode = args.includes('--help');
|
const helpMode = args.includes('--help');
|
||||||
const fastMode = args.includes('--fast');
|
// --fast (regex-only) is deprecated: since the jsdom removal, the static
|
||||||
|
// HTML/CSS analysis is fast and covers every rule, so the regex-only path
|
||||||
|
// only loses coverage for no real speed win. Accept the flag for back-compat
|
||||||
|
// but ignore it and run the full scan.
|
||||||
|
if (args.includes('--fast')) {
|
||||||
|
process.stderr.write(
|
||||||
|
'Note: --fast is deprecated and ignored. The full scan is fast now and runs every rule.\n',
|
||||||
|
);
|
||||||
|
}
|
||||||
const providers = [];
|
const providers = [];
|
||||||
if (args.includes('--gpt')) providers.push('gpt');
|
if (args.includes('--gpt')) providers.push('gpt');
|
||||||
if (args.includes('--gemini')) providers.push('gemini');
|
if (args.includes('--gemini')) providers.push('gemini');
|
||||||
@@ -177,7 +183,7 @@ async function detectCli() {
|
|||||||
process.stderr.write(
|
process.stderr.write(
|
||||||
`\nFound ${files.length} files (${htmlCount} HTML) in ${target}.\n` +
|
`\nFound ${files.length} files (${htmlCount} HTML) in ${target}.\n` +
|
||||||
`Scanning may take a while${htmlCount > 10 ? ' (static HTML/CSS processes each HTML file individually)' : ''}.\n` +
|
`Scanning may take a while${htmlCount > 10 ? ' (static HTML/CSS processes each HTML file individually)' : ''}.\n` +
|
||||||
`Use --fast to skip static HTML/CSS analysis, or target a specific subdirectory.\n`
|
`Target a specific subdirectory to narrow scope.\n`
|
||||||
);
|
);
|
||||||
const ok = await confirm('Continue?');
|
const ok = await confirm('Continue?');
|
||||||
if (!ok) { process.stderr.write('Aborted.\n'); process.exit(0); }
|
if (!ok) { process.stderr.write('Aborted.\n'); process.exit(0); }
|
||||||
@@ -197,7 +203,7 @@ async function detectCli() {
|
|||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
const ext = path.extname(file).toLowerCase();
|
const ext = path.extname(file).toLowerCase();
|
||||||
let fileFindings;
|
let fileFindings;
|
||||||
if (!fastMode && HTML_EXTENSIONS.has(ext)) {
|
if (HTML_EXTENSIONS.has(ext)) {
|
||||||
fileFindings = await detectHtml(file, scanOptions);
|
fileFindings = await detectHtml(file, scanOptions);
|
||||||
} else {
|
} else {
|
||||||
fileFindings = detectText(fs.readFileSync(file, 'utf-8'), file, scanOptions);
|
fileFindings = detectText(fs.readFileSync(file, 'utf-8'), file, scanOptions);
|
||||||
@@ -214,7 +220,7 @@ async function detectCli() {
|
|||||||
}
|
}
|
||||||
} else if (stat.isFile()) {
|
} else if (stat.isFile()) {
|
||||||
const ext = path.extname(resolved).toLowerCase();
|
const ext = path.extname(resolved).toLowerCase();
|
||||||
if (!fastMode && HTML_EXTENSIONS.has(ext)) {
|
if (HTML_EXTENSIONS.has(ext)) {
|
||||||
allFindings.push(...await detectHtml(resolved, scanOptions));
|
allFindings.push(...await detectHtml(resolved, scanOptions));
|
||||||
} else {
|
} else {
|
||||||
allFindings.push(...detectText(fs.readFileSync(resolved, 'utf-8'), resolved, scanOptions));
|
allFindings.push(...detectText(fs.readFileSync(resolved, 'utf-8'), resolved, scanOptions));
|
||||||
|
|||||||
@@ -50,12 +50,12 @@ Run the bundled detector and browser visualization evidence. Assessment B is man
|
|||||||
|
|
||||||
CLI scan:
|
CLI scan:
|
||||||
```bash
|
```bash
|
||||||
node .claude/skills/impeccable/scripts/detect.mjs --json [--fast] [target]
|
node .claude/skills/impeccable/scripts/detect.mjs --json [target]
|
||||||
```
|
```
|
||||||
|
|
||||||
- Pass markup files/directories as `[target]`; do not pass CSS-only files.
|
- Pass markup files/directories as `[target]`; do not pass CSS-only files.
|
||||||
- For URLs, skip CLI scan and use browser visualization.
|
- For URLs, skip CLI scan and use browser visualization.
|
||||||
- For 200+ scannable files, use `--fast`; for 500+, narrow scope or ask.
|
- For very large trees (500+ scannable files), narrow scope or ask.
|
||||||
- Exit code 0 = clean; 2 = findings.
|
- Exit code 0 = clean; 2 = findings.
|
||||||
- If the detector entrypoint is missing or fails to load, report deterministic scan unavailable and continue with browser/manual review.
|
- If the detector entrypoint is missing or fails to load, report deterministic scan unavailable and continue with browser/manual review.
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,6 @@ function printUsage() {
|
|||||||
Scan files or URLs for UI anti-patterns and design quality issues.
|
Scan files or URLs for UI anti-patterns and design quality issues.
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--fast Regex-only mode (skip static HTML/CSS analysis, faster but misses linked stylesheets)
|
|
||||||
--json Output results as JSON
|
--json Output results as JSON
|
||||||
--gpt Also report GPT-specific provider tells (off by default)
|
--gpt Also report GPT-specific provider tells (off by default)
|
||||||
--gemini Also report Gemini-specific provider tells (off by default)
|
--gemini Also report Gemini-specific provider tells (off by default)
|
||||||
@@ -89,13 +88,12 @@ Detection modes:
|
|||||||
HTML files Static HTML/CSS analysis (default, catches linked CSS)
|
HTML files Static HTML/CSS analysis (default, catches linked CSS)
|
||||||
Non-HTML files Regex pattern matching (CSS, JSX, TSX, etc.)
|
Non-HTML files Regex pattern matching (CSS, JSX, TSX, etc.)
|
||||||
URLs Puppeteer full browser rendering (auto-detected)
|
URLs Puppeteer full browser rendering (auto-detected)
|
||||||
--fast Forces regex for all files
|
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
impeccable detect src/
|
impeccable detect src/
|
||||||
impeccable detect index.html
|
impeccable detect index.html
|
||||||
impeccable detect https://example.com
|
impeccable detect https://example.com
|
||||||
impeccable detect --fast --json .`);
|
impeccable detect --json .`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function detectCli() {
|
async function detectCli() {
|
||||||
@@ -107,7 +105,15 @@ async function detectCli() {
|
|||||||
if (args[0] === 'detect') args = args.slice(1);
|
if (args[0] === 'detect') args = args.slice(1);
|
||||||
const jsonMode = args.includes('--json');
|
const jsonMode = args.includes('--json');
|
||||||
const helpMode = args.includes('--help');
|
const helpMode = args.includes('--help');
|
||||||
const fastMode = args.includes('--fast');
|
// --fast (regex-only) is deprecated: since the jsdom removal, the static
|
||||||
|
// HTML/CSS analysis is fast and covers every rule, so the regex-only path
|
||||||
|
// only loses coverage for no real speed win. Accept the flag for back-compat
|
||||||
|
// but ignore it and run the full scan.
|
||||||
|
if (args.includes('--fast')) {
|
||||||
|
process.stderr.write(
|
||||||
|
'Note: --fast is deprecated and ignored. The full scan is fast now and runs every rule.\n',
|
||||||
|
);
|
||||||
|
}
|
||||||
const providers = [];
|
const providers = [];
|
||||||
if (args.includes('--gpt')) providers.push('gpt');
|
if (args.includes('--gpt')) providers.push('gpt');
|
||||||
if (args.includes('--gemini')) providers.push('gemini');
|
if (args.includes('--gemini')) providers.push('gemini');
|
||||||
@@ -177,7 +183,7 @@ async function detectCli() {
|
|||||||
process.stderr.write(
|
process.stderr.write(
|
||||||
`\nFound ${files.length} files (${htmlCount} HTML) in ${target}.\n` +
|
`\nFound ${files.length} files (${htmlCount} HTML) in ${target}.\n` +
|
||||||
`Scanning may take a while${htmlCount > 10 ? ' (static HTML/CSS processes each HTML file individually)' : ''}.\n` +
|
`Scanning may take a while${htmlCount > 10 ? ' (static HTML/CSS processes each HTML file individually)' : ''}.\n` +
|
||||||
`Use --fast to skip static HTML/CSS analysis, or target a specific subdirectory.\n`
|
`Target a specific subdirectory to narrow scope.\n`
|
||||||
);
|
);
|
||||||
const ok = await confirm('Continue?');
|
const ok = await confirm('Continue?');
|
||||||
if (!ok) { process.stderr.write('Aborted.\n'); process.exit(0); }
|
if (!ok) { process.stderr.write('Aborted.\n'); process.exit(0); }
|
||||||
@@ -197,7 +203,7 @@ async function detectCli() {
|
|||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
const ext = path.extname(file).toLowerCase();
|
const ext = path.extname(file).toLowerCase();
|
||||||
let fileFindings;
|
let fileFindings;
|
||||||
if (!fastMode && HTML_EXTENSIONS.has(ext)) {
|
if (HTML_EXTENSIONS.has(ext)) {
|
||||||
fileFindings = await detectHtml(file, scanOptions);
|
fileFindings = await detectHtml(file, scanOptions);
|
||||||
} else {
|
} else {
|
||||||
fileFindings = detectText(fs.readFileSync(file, 'utf-8'), file, scanOptions);
|
fileFindings = detectText(fs.readFileSync(file, 'utf-8'), file, scanOptions);
|
||||||
@@ -214,7 +220,7 @@ async function detectCli() {
|
|||||||
}
|
}
|
||||||
} else if (stat.isFile()) {
|
} else if (stat.isFile()) {
|
||||||
const ext = path.extname(resolved).toLowerCase();
|
const ext = path.extname(resolved).toLowerCase();
|
||||||
if (!fastMode && HTML_EXTENSIONS.has(ext)) {
|
if (HTML_EXTENSIONS.has(ext)) {
|
||||||
allFindings.push(...await detectHtml(resolved, scanOptions));
|
allFindings.push(...await detectHtml(resolved, scanOptions));
|
||||||
} else {
|
} else {
|
||||||
allFindings.push(...detectText(fs.readFileSync(resolved, 'utf-8'), resolved, scanOptions));
|
allFindings.push(...detectText(fs.readFileSync(resolved, 'utf-8'), resolved, scanOptions));
|
||||||
|
|||||||
@@ -50,12 +50,12 @@ Run the bundled detector and browser visualization evidence. Assessment B is man
|
|||||||
|
|
||||||
CLI scan:
|
CLI scan:
|
||||||
```bash
|
```bash
|
||||||
node .cursor/skills/impeccable/scripts/detect.mjs --json [--fast] [target]
|
node .cursor/skills/impeccable/scripts/detect.mjs --json [target]
|
||||||
```
|
```
|
||||||
|
|
||||||
- Pass markup files/directories as `[target]`; do not pass CSS-only files.
|
- Pass markup files/directories as `[target]`; do not pass CSS-only files.
|
||||||
- For URLs, skip CLI scan and use browser visualization.
|
- For URLs, skip CLI scan and use browser visualization.
|
||||||
- For 200+ scannable files, use `--fast`; for 500+, narrow scope or ask.
|
- For very large trees (500+ scannable files), narrow scope or ask.
|
||||||
- Exit code 0 = clean; 2 = findings.
|
- Exit code 0 = clean; 2 = findings.
|
||||||
- If the detector entrypoint is missing or fails to load, report deterministic scan unavailable and continue with browser/manual review.
|
- If the detector entrypoint is missing or fails to load, report deterministic scan unavailable and continue with browser/manual review.
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,6 @@ function printUsage() {
|
|||||||
Scan files or URLs for UI anti-patterns and design quality issues.
|
Scan files or URLs for UI anti-patterns and design quality issues.
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--fast Regex-only mode (skip static HTML/CSS analysis, faster but misses linked stylesheets)
|
|
||||||
--json Output results as JSON
|
--json Output results as JSON
|
||||||
--gpt Also report GPT-specific provider tells (off by default)
|
--gpt Also report GPT-specific provider tells (off by default)
|
||||||
--gemini Also report Gemini-specific provider tells (off by default)
|
--gemini Also report Gemini-specific provider tells (off by default)
|
||||||
@@ -89,13 +88,12 @@ Detection modes:
|
|||||||
HTML files Static HTML/CSS analysis (default, catches linked CSS)
|
HTML files Static HTML/CSS analysis (default, catches linked CSS)
|
||||||
Non-HTML files Regex pattern matching (CSS, JSX, TSX, etc.)
|
Non-HTML files Regex pattern matching (CSS, JSX, TSX, etc.)
|
||||||
URLs Puppeteer full browser rendering (auto-detected)
|
URLs Puppeteer full browser rendering (auto-detected)
|
||||||
--fast Forces regex for all files
|
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
impeccable detect src/
|
impeccable detect src/
|
||||||
impeccable detect index.html
|
impeccable detect index.html
|
||||||
impeccable detect https://example.com
|
impeccable detect https://example.com
|
||||||
impeccable detect --fast --json .`);
|
impeccable detect --json .`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function detectCli() {
|
async function detectCli() {
|
||||||
@@ -107,7 +105,15 @@ async function detectCli() {
|
|||||||
if (args[0] === 'detect') args = args.slice(1);
|
if (args[0] === 'detect') args = args.slice(1);
|
||||||
const jsonMode = args.includes('--json');
|
const jsonMode = args.includes('--json');
|
||||||
const helpMode = args.includes('--help');
|
const helpMode = args.includes('--help');
|
||||||
const fastMode = args.includes('--fast');
|
// --fast (regex-only) is deprecated: since the jsdom removal, the static
|
||||||
|
// HTML/CSS analysis is fast and covers every rule, so the regex-only path
|
||||||
|
// only loses coverage for no real speed win. Accept the flag for back-compat
|
||||||
|
// but ignore it and run the full scan.
|
||||||
|
if (args.includes('--fast')) {
|
||||||
|
process.stderr.write(
|
||||||
|
'Note: --fast is deprecated and ignored. The full scan is fast now and runs every rule.\n',
|
||||||
|
);
|
||||||
|
}
|
||||||
const providers = [];
|
const providers = [];
|
||||||
if (args.includes('--gpt')) providers.push('gpt');
|
if (args.includes('--gpt')) providers.push('gpt');
|
||||||
if (args.includes('--gemini')) providers.push('gemini');
|
if (args.includes('--gemini')) providers.push('gemini');
|
||||||
@@ -177,7 +183,7 @@ async function detectCli() {
|
|||||||
process.stderr.write(
|
process.stderr.write(
|
||||||
`\nFound ${files.length} files (${htmlCount} HTML) in ${target}.\n` +
|
`\nFound ${files.length} files (${htmlCount} HTML) in ${target}.\n` +
|
||||||
`Scanning may take a while${htmlCount > 10 ? ' (static HTML/CSS processes each HTML file individually)' : ''}.\n` +
|
`Scanning may take a while${htmlCount > 10 ? ' (static HTML/CSS processes each HTML file individually)' : ''}.\n` +
|
||||||
`Use --fast to skip static HTML/CSS analysis, or target a specific subdirectory.\n`
|
`Target a specific subdirectory to narrow scope.\n`
|
||||||
);
|
);
|
||||||
const ok = await confirm('Continue?');
|
const ok = await confirm('Continue?');
|
||||||
if (!ok) { process.stderr.write('Aborted.\n'); process.exit(0); }
|
if (!ok) { process.stderr.write('Aborted.\n'); process.exit(0); }
|
||||||
@@ -197,7 +203,7 @@ async function detectCli() {
|
|||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
const ext = path.extname(file).toLowerCase();
|
const ext = path.extname(file).toLowerCase();
|
||||||
let fileFindings;
|
let fileFindings;
|
||||||
if (!fastMode && HTML_EXTENSIONS.has(ext)) {
|
if (HTML_EXTENSIONS.has(ext)) {
|
||||||
fileFindings = await detectHtml(file, scanOptions);
|
fileFindings = await detectHtml(file, scanOptions);
|
||||||
} else {
|
} else {
|
||||||
fileFindings = detectText(fs.readFileSync(file, 'utf-8'), file, scanOptions);
|
fileFindings = detectText(fs.readFileSync(file, 'utf-8'), file, scanOptions);
|
||||||
@@ -214,7 +220,7 @@ async function detectCli() {
|
|||||||
}
|
}
|
||||||
} else if (stat.isFile()) {
|
} else if (stat.isFile()) {
|
||||||
const ext = path.extname(resolved).toLowerCase();
|
const ext = path.extname(resolved).toLowerCase();
|
||||||
if (!fastMode && HTML_EXTENSIONS.has(ext)) {
|
if (HTML_EXTENSIONS.has(ext)) {
|
||||||
allFindings.push(...await detectHtml(resolved, scanOptions));
|
allFindings.push(...await detectHtml(resolved, scanOptions));
|
||||||
} else {
|
} else {
|
||||||
allFindings.push(...detectText(fs.readFileSync(resolved, 'utf-8'), resolved, scanOptions));
|
allFindings.push(...detectText(fs.readFileSync(resolved, 'utf-8'), resolved, scanOptions));
|
||||||
|
|||||||
@@ -50,12 +50,12 @@ Run the bundled detector and browser visualization evidence. Assessment B is man
|
|||||||
|
|
||||||
CLI scan:
|
CLI scan:
|
||||||
```bash
|
```bash
|
||||||
node .gemini/skills/impeccable/scripts/detect.mjs --json [--fast] [target]
|
node .gemini/skills/impeccable/scripts/detect.mjs --json [target]
|
||||||
```
|
```
|
||||||
|
|
||||||
- Pass markup files/directories as `[target]`; do not pass CSS-only files.
|
- Pass markup files/directories as `[target]`; do not pass CSS-only files.
|
||||||
- For URLs, skip CLI scan and use browser visualization.
|
- For URLs, skip CLI scan and use browser visualization.
|
||||||
- For 200+ scannable files, use `--fast`; for 500+, narrow scope or ask.
|
- For very large trees (500+ scannable files), narrow scope or ask.
|
||||||
- Exit code 0 = clean; 2 = findings.
|
- Exit code 0 = clean; 2 = findings.
|
||||||
- If the detector entrypoint is missing or fails to load, report deterministic scan unavailable and continue with browser/manual review.
|
- If the detector entrypoint is missing or fails to load, report deterministic scan unavailable and continue with browser/manual review.
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,6 @@ function printUsage() {
|
|||||||
Scan files or URLs for UI anti-patterns and design quality issues.
|
Scan files or URLs for UI anti-patterns and design quality issues.
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--fast Regex-only mode (skip static HTML/CSS analysis, faster but misses linked stylesheets)
|
|
||||||
--json Output results as JSON
|
--json Output results as JSON
|
||||||
--gpt Also report GPT-specific provider tells (off by default)
|
--gpt Also report GPT-specific provider tells (off by default)
|
||||||
--gemini Also report Gemini-specific provider tells (off by default)
|
--gemini Also report Gemini-specific provider tells (off by default)
|
||||||
@@ -89,13 +88,12 @@ Detection modes:
|
|||||||
HTML files Static HTML/CSS analysis (default, catches linked CSS)
|
HTML files Static HTML/CSS analysis (default, catches linked CSS)
|
||||||
Non-HTML files Regex pattern matching (CSS, JSX, TSX, etc.)
|
Non-HTML files Regex pattern matching (CSS, JSX, TSX, etc.)
|
||||||
URLs Puppeteer full browser rendering (auto-detected)
|
URLs Puppeteer full browser rendering (auto-detected)
|
||||||
--fast Forces regex for all files
|
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
impeccable detect src/
|
impeccable detect src/
|
||||||
impeccable detect index.html
|
impeccable detect index.html
|
||||||
impeccable detect https://example.com
|
impeccable detect https://example.com
|
||||||
impeccable detect --fast --json .`);
|
impeccable detect --json .`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function detectCli() {
|
async function detectCli() {
|
||||||
@@ -107,7 +105,15 @@ async function detectCli() {
|
|||||||
if (args[0] === 'detect') args = args.slice(1);
|
if (args[0] === 'detect') args = args.slice(1);
|
||||||
const jsonMode = args.includes('--json');
|
const jsonMode = args.includes('--json');
|
||||||
const helpMode = args.includes('--help');
|
const helpMode = args.includes('--help');
|
||||||
const fastMode = args.includes('--fast');
|
// --fast (regex-only) is deprecated: since the jsdom removal, the static
|
||||||
|
// HTML/CSS analysis is fast and covers every rule, so the regex-only path
|
||||||
|
// only loses coverage for no real speed win. Accept the flag for back-compat
|
||||||
|
// but ignore it and run the full scan.
|
||||||
|
if (args.includes('--fast')) {
|
||||||
|
process.stderr.write(
|
||||||
|
'Note: --fast is deprecated and ignored. The full scan is fast now and runs every rule.\n',
|
||||||
|
);
|
||||||
|
}
|
||||||
const providers = [];
|
const providers = [];
|
||||||
if (args.includes('--gpt')) providers.push('gpt');
|
if (args.includes('--gpt')) providers.push('gpt');
|
||||||
if (args.includes('--gemini')) providers.push('gemini');
|
if (args.includes('--gemini')) providers.push('gemini');
|
||||||
@@ -177,7 +183,7 @@ async function detectCli() {
|
|||||||
process.stderr.write(
|
process.stderr.write(
|
||||||
`\nFound ${files.length} files (${htmlCount} HTML) in ${target}.\n` +
|
`\nFound ${files.length} files (${htmlCount} HTML) in ${target}.\n` +
|
||||||
`Scanning may take a while${htmlCount > 10 ? ' (static HTML/CSS processes each HTML file individually)' : ''}.\n` +
|
`Scanning may take a while${htmlCount > 10 ? ' (static HTML/CSS processes each HTML file individually)' : ''}.\n` +
|
||||||
`Use --fast to skip static HTML/CSS analysis, or target a specific subdirectory.\n`
|
`Target a specific subdirectory to narrow scope.\n`
|
||||||
);
|
);
|
||||||
const ok = await confirm('Continue?');
|
const ok = await confirm('Continue?');
|
||||||
if (!ok) { process.stderr.write('Aborted.\n'); process.exit(0); }
|
if (!ok) { process.stderr.write('Aborted.\n'); process.exit(0); }
|
||||||
@@ -197,7 +203,7 @@ async function detectCli() {
|
|||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
const ext = path.extname(file).toLowerCase();
|
const ext = path.extname(file).toLowerCase();
|
||||||
let fileFindings;
|
let fileFindings;
|
||||||
if (!fastMode && HTML_EXTENSIONS.has(ext)) {
|
if (HTML_EXTENSIONS.has(ext)) {
|
||||||
fileFindings = await detectHtml(file, scanOptions);
|
fileFindings = await detectHtml(file, scanOptions);
|
||||||
} else {
|
} else {
|
||||||
fileFindings = detectText(fs.readFileSync(file, 'utf-8'), file, scanOptions);
|
fileFindings = detectText(fs.readFileSync(file, 'utf-8'), file, scanOptions);
|
||||||
@@ -214,7 +220,7 @@ async function detectCli() {
|
|||||||
}
|
}
|
||||||
} else if (stat.isFile()) {
|
} else if (stat.isFile()) {
|
||||||
const ext = path.extname(resolved).toLowerCase();
|
const ext = path.extname(resolved).toLowerCase();
|
||||||
if (!fastMode && HTML_EXTENSIONS.has(ext)) {
|
if (HTML_EXTENSIONS.has(ext)) {
|
||||||
allFindings.push(...await detectHtml(resolved, scanOptions));
|
allFindings.push(...await detectHtml(resolved, scanOptions));
|
||||||
} else {
|
} else {
|
||||||
allFindings.push(...detectText(fs.readFileSync(resolved, 'utf-8'), resolved, scanOptions));
|
allFindings.push(...detectText(fs.readFileSync(resolved, 'utf-8'), resolved, scanOptions));
|
||||||
|
|||||||
@@ -50,12 +50,12 @@ Run the bundled detector and browser visualization evidence. Assessment B is man
|
|||||||
|
|
||||||
CLI scan:
|
CLI scan:
|
||||||
```bash
|
```bash
|
||||||
node .github/skills/impeccable/scripts/detect.mjs --json [--fast] [target]
|
node .github/skills/impeccable/scripts/detect.mjs --json [target]
|
||||||
```
|
```
|
||||||
|
|
||||||
- Pass markup files/directories as `[target]`; do not pass CSS-only files.
|
- Pass markup files/directories as `[target]`; do not pass CSS-only files.
|
||||||
- For URLs, skip CLI scan and use browser visualization.
|
- For URLs, skip CLI scan and use browser visualization.
|
||||||
- For 200+ scannable files, use `--fast`; for 500+, narrow scope or ask.
|
- For very large trees (500+ scannable files), narrow scope or ask.
|
||||||
- Exit code 0 = clean; 2 = findings.
|
- Exit code 0 = clean; 2 = findings.
|
||||||
- If the detector entrypoint is missing or fails to load, report deterministic scan unavailable and continue with browser/manual review.
|
- If the detector entrypoint is missing or fails to load, report deterministic scan unavailable and continue with browser/manual review.
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,6 @@ function printUsage() {
|
|||||||
Scan files or URLs for UI anti-patterns and design quality issues.
|
Scan files or URLs for UI anti-patterns and design quality issues.
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--fast Regex-only mode (skip static HTML/CSS analysis, faster but misses linked stylesheets)
|
|
||||||
--json Output results as JSON
|
--json Output results as JSON
|
||||||
--gpt Also report GPT-specific provider tells (off by default)
|
--gpt Also report GPT-specific provider tells (off by default)
|
||||||
--gemini Also report Gemini-specific provider tells (off by default)
|
--gemini Also report Gemini-specific provider tells (off by default)
|
||||||
@@ -89,13 +88,12 @@ Detection modes:
|
|||||||
HTML files Static HTML/CSS analysis (default, catches linked CSS)
|
HTML files Static HTML/CSS analysis (default, catches linked CSS)
|
||||||
Non-HTML files Regex pattern matching (CSS, JSX, TSX, etc.)
|
Non-HTML files Regex pattern matching (CSS, JSX, TSX, etc.)
|
||||||
URLs Puppeteer full browser rendering (auto-detected)
|
URLs Puppeteer full browser rendering (auto-detected)
|
||||||
--fast Forces regex for all files
|
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
impeccable detect src/
|
impeccable detect src/
|
||||||
impeccable detect index.html
|
impeccable detect index.html
|
||||||
impeccable detect https://example.com
|
impeccable detect https://example.com
|
||||||
impeccable detect --fast --json .`);
|
impeccable detect --json .`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function detectCli() {
|
async function detectCli() {
|
||||||
@@ -107,7 +105,15 @@ async function detectCli() {
|
|||||||
if (args[0] === 'detect') args = args.slice(1);
|
if (args[0] === 'detect') args = args.slice(1);
|
||||||
const jsonMode = args.includes('--json');
|
const jsonMode = args.includes('--json');
|
||||||
const helpMode = args.includes('--help');
|
const helpMode = args.includes('--help');
|
||||||
const fastMode = args.includes('--fast');
|
// --fast (regex-only) is deprecated: since the jsdom removal, the static
|
||||||
|
// HTML/CSS analysis is fast and covers every rule, so the regex-only path
|
||||||
|
// only loses coverage for no real speed win. Accept the flag for back-compat
|
||||||
|
// but ignore it and run the full scan.
|
||||||
|
if (args.includes('--fast')) {
|
||||||
|
process.stderr.write(
|
||||||
|
'Note: --fast is deprecated and ignored. The full scan is fast now and runs every rule.\n',
|
||||||
|
);
|
||||||
|
}
|
||||||
const providers = [];
|
const providers = [];
|
||||||
if (args.includes('--gpt')) providers.push('gpt');
|
if (args.includes('--gpt')) providers.push('gpt');
|
||||||
if (args.includes('--gemini')) providers.push('gemini');
|
if (args.includes('--gemini')) providers.push('gemini');
|
||||||
@@ -177,7 +183,7 @@ async function detectCli() {
|
|||||||
process.stderr.write(
|
process.stderr.write(
|
||||||
`\nFound ${files.length} files (${htmlCount} HTML) in ${target}.\n` +
|
`\nFound ${files.length} files (${htmlCount} HTML) in ${target}.\n` +
|
||||||
`Scanning may take a while${htmlCount > 10 ? ' (static HTML/CSS processes each HTML file individually)' : ''}.\n` +
|
`Scanning may take a while${htmlCount > 10 ? ' (static HTML/CSS processes each HTML file individually)' : ''}.\n` +
|
||||||
`Use --fast to skip static HTML/CSS analysis, or target a specific subdirectory.\n`
|
`Target a specific subdirectory to narrow scope.\n`
|
||||||
);
|
);
|
||||||
const ok = await confirm('Continue?');
|
const ok = await confirm('Continue?');
|
||||||
if (!ok) { process.stderr.write('Aborted.\n'); process.exit(0); }
|
if (!ok) { process.stderr.write('Aborted.\n'); process.exit(0); }
|
||||||
@@ -197,7 +203,7 @@ async function detectCli() {
|
|||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
const ext = path.extname(file).toLowerCase();
|
const ext = path.extname(file).toLowerCase();
|
||||||
let fileFindings;
|
let fileFindings;
|
||||||
if (!fastMode && HTML_EXTENSIONS.has(ext)) {
|
if (HTML_EXTENSIONS.has(ext)) {
|
||||||
fileFindings = await detectHtml(file, scanOptions);
|
fileFindings = await detectHtml(file, scanOptions);
|
||||||
} else {
|
} else {
|
||||||
fileFindings = detectText(fs.readFileSync(file, 'utf-8'), file, scanOptions);
|
fileFindings = detectText(fs.readFileSync(file, 'utf-8'), file, scanOptions);
|
||||||
@@ -214,7 +220,7 @@ async function detectCli() {
|
|||||||
}
|
}
|
||||||
} else if (stat.isFile()) {
|
} else if (stat.isFile()) {
|
||||||
const ext = path.extname(resolved).toLowerCase();
|
const ext = path.extname(resolved).toLowerCase();
|
||||||
if (!fastMode && HTML_EXTENSIONS.has(ext)) {
|
if (HTML_EXTENSIONS.has(ext)) {
|
||||||
allFindings.push(...await detectHtml(resolved, scanOptions));
|
allFindings.push(...await detectHtml(resolved, scanOptions));
|
||||||
} else {
|
} else {
|
||||||
allFindings.push(...detectText(fs.readFileSync(resolved, 'utf-8'), resolved, scanOptions));
|
allFindings.push(...detectText(fs.readFileSync(resolved, 'utf-8'), resolved, scanOptions));
|
||||||
|
|||||||
@@ -50,12 +50,12 @@ Run the bundled detector and browser visualization evidence. Assessment B is man
|
|||||||
|
|
||||||
CLI scan:
|
CLI scan:
|
||||||
```bash
|
```bash
|
||||||
node .kiro/skills/impeccable/scripts/detect.mjs --json [--fast] [target]
|
node .kiro/skills/impeccable/scripts/detect.mjs --json [target]
|
||||||
```
|
```
|
||||||
|
|
||||||
- Pass markup files/directories as `[target]`; do not pass CSS-only files.
|
- Pass markup files/directories as `[target]`; do not pass CSS-only files.
|
||||||
- For URLs, skip CLI scan and use browser visualization.
|
- For URLs, skip CLI scan and use browser visualization.
|
||||||
- For 200+ scannable files, use `--fast`; for 500+, narrow scope or ask.
|
- For very large trees (500+ scannable files), narrow scope or ask.
|
||||||
- Exit code 0 = clean; 2 = findings.
|
- Exit code 0 = clean; 2 = findings.
|
||||||
- If the detector entrypoint is missing or fails to load, report deterministic scan unavailable and continue with browser/manual review.
|
- If the detector entrypoint is missing or fails to load, report deterministic scan unavailable and continue with browser/manual review.
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,6 @@ function printUsage() {
|
|||||||
Scan files or URLs for UI anti-patterns and design quality issues.
|
Scan files or URLs for UI anti-patterns and design quality issues.
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--fast Regex-only mode (skip static HTML/CSS analysis, faster but misses linked stylesheets)
|
|
||||||
--json Output results as JSON
|
--json Output results as JSON
|
||||||
--gpt Also report GPT-specific provider tells (off by default)
|
--gpt Also report GPT-specific provider tells (off by default)
|
||||||
--gemini Also report Gemini-specific provider tells (off by default)
|
--gemini Also report Gemini-specific provider tells (off by default)
|
||||||
@@ -89,13 +88,12 @@ Detection modes:
|
|||||||
HTML files Static HTML/CSS analysis (default, catches linked CSS)
|
HTML files Static HTML/CSS analysis (default, catches linked CSS)
|
||||||
Non-HTML files Regex pattern matching (CSS, JSX, TSX, etc.)
|
Non-HTML files Regex pattern matching (CSS, JSX, TSX, etc.)
|
||||||
URLs Puppeteer full browser rendering (auto-detected)
|
URLs Puppeteer full browser rendering (auto-detected)
|
||||||
--fast Forces regex for all files
|
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
impeccable detect src/
|
impeccable detect src/
|
||||||
impeccable detect index.html
|
impeccable detect index.html
|
||||||
impeccable detect https://example.com
|
impeccable detect https://example.com
|
||||||
impeccable detect --fast --json .`);
|
impeccable detect --json .`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function detectCli() {
|
async function detectCli() {
|
||||||
@@ -107,7 +105,15 @@ async function detectCli() {
|
|||||||
if (args[0] === 'detect') args = args.slice(1);
|
if (args[0] === 'detect') args = args.slice(1);
|
||||||
const jsonMode = args.includes('--json');
|
const jsonMode = args.includes('--json');
|
||||||
const helpMode = args.includes('--help');
|
const helpMode = args.includes('--help');
|
||||||
const fastMode = args.includes('--fast');
|
// --fast (regex-only) is deprecated: since the jsdom removal, the static
|
||||||
|
// HTML/CSS analysis is fast and covers every rule, so the regex-only path
|
||||||
|
// only loses coverage for no real speed win. Accept the flag for back-compat
|
||||||
|
// but ignore it and run the full scan.
|
||||||
|
if (args.includes('--fast')) {
|
||||||
|
process.stderr.write(
|
||||||
|
'Note: --fast is deprecated and ignored. The full scan is fast now and runs every rule.\n',
|
||||||
|
);
|
||||||
|
}
|
||||||
const providers = [];
|
const providers = [];
|
||||||
if (args.includes('--gpt')) providers.push('gpt');
|
if (args.includes('--gpt')) providers.push('gpt');
|
||||||
if (args.includes('--gemini')) providers.push('gemini');
|
if (args.includes('--gemini')) providers.push('gemini');
|
||||||
@@ -177,7 +183,7 @@ async function detectCli() {
|
|||||||
process.stderr.write(
|
process.stderr.write(
|
||||||
`\nFound ${files.length} files (${htmlCount} HTML) in ${target}.\n` +
|
`\nFound ${files.length} files (${htmlCount} HTML) in ${target}.\n` +
|
||||||
`Scanning may take a while${htmlCount > 10 ? ' (static HTML/CSS processes each HTML file individually)' : ''}.\n` +
|
`Scanning may take a while${htmlCount > 10 ? ' (static HTML/CSS processes each HTML file individually)' : ''}.\n` +
|
||||||
`Use --fast to skip static HTML/CSS analysis, or target a specific subdirectory.\n`
|
`Target a specific subdirectory to narrow scope.\n`
|
||||||
);
|
);
|
||||||
const ok = await confirm('Continue?');
|
const ok = await confirm('Continue?');
|
||||||
if (!ok) { process.stderr.write('Aborted.\n'); process.exit(0); }
|
if (!ok) { process.stderr.write('Aborted.\n'); process.exit(0); }
|
||||||
@@ -197,7 +203,7 @@ async function detectCli() {
|
|||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
const ext = path.extname(file).toLowerCase();
|
const ext = path.extname(file).toLowerCase();
|
||||||
let fileFindings;
|
let fileFindings;
|
||||||
if (!fastMode && HTML_EXTENSIONS.has(ext)) {
|
if (HTML_EXTENSIONS.has(ext)) {
|
||||||
fileFindings = await detectHtml(file, scanOptions);
|
fileFindings = await detectHtml(file, scanOptions);
|
||||||
} else {
|
} else {
|
||||||
fileFindings = detectText(fs.readFileSync(file, 'utf-8'), file, scanOptions);
|
fileFindings = detectText(fs.readFileSync(file, 'utf-8'), file, scanOptions);
|
||||||
@@ -214,7 +220,7 @@ async function detectCli() {
|
|||||||
}
|
}
|
||||||
} else if (stat.isFile()) {
|
} else if (stat.isFile()) {
|
||||||
const ext = path.extname(resolved).toLowerCase();
|
const ext = path.extname(resolved).toLowerCase();
|
||||||
if (!fastMode && HTML_EXTENSIONS.has(ext)) {
|
if (HTML_EXTENSIONS.has(ext)) {
|
||||||
allFindings.push(...await detectHtml(resolved, scanOptions));
|
allFindings.push(...await detectHtml(resolved, scanOptions));
|
||||||
} else {
|
} else {
|
||||||
allFindings.push(...detectText(fs.readFileSync(resolved, 'utf-8'), resolved, scanOptions));
|
allFindings.push(...detectText(fs.readFileSync(resolved, 'utf-8'), resolved, scanOptions));
|
||||||
|
|||||||
@@ -50,12 +50,12 @@ Run the bundled detector and browser visualization evidence. Assessment B is man
|
|||||||
|
|
||||||
CLI scan:
|
CLI scan:
|
||||||
```bash
|
```bash
|
||||||
node .opencode/skills/impeccable/scripts/detect.mjs --json [--fast] [target]
|
node .opencode/skills/impeccable/scripts/detect.mjs --json [target]
|
||||||
```
|
```
|
||||||
|
|
||||||
- Pass markup files/directories as `[target]`; do not pass CSS-only files.
|
- Pass markup files/directories as `[target]`; do not pass CSS-only files.
|
||||||
- For URLs, skip CLI scan and use browser visualization.
|
- For URLs, skip CLI scan and use browser visualization.
|
||||||
- For 200+ scannable files, use `--fast`; for 500+, narrow scope or ask.
|
- For very large trees (500+ scannable files), narrow scope or ask.
|
||||||
- Exit code 0 = clean; 2 = findings.
|
- Exit code 0 = clean; 2 = findings.
|
||||||
- If the detector entrypoint is missing or fails to load, report deterministic scan unavailable and continue with browser/manual review.
|
- If the detector entrypoint is missing or fails to load, report deterministic scan unavailable and continue with browser/manual review.
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,6 @@ function printUsage() {
|
|||||||
Scan files or URLs for UI anti-patterns and design quality issues.
|
Scan files or URLs for UI anti-patterns and design quality issues.
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--fast Regex-only mode (skip static HTML/CSS analysis, faster but misses linked stylesheets)
|
|
||||||
--json Output results as JSON
|
--json Output results as JSON
|
||||||
--gpt Also report GPT-specific provider tells (off by default)
|
--gpt Also report GPT-specific provider tells (off by default)
|
||||||
--gemini Also report Gemini-specific provider tells (off by default)
|
--gemini Also report Gemini-specific provider tells (off by default)
|
||||||
@@ -89,13 +88,12 @@ Detection modes:
|
|||||||
HTML files Static HTML/CSS analysis (default, catches linked CSS)
|
HTML files Static HTML/CSS analysis (default, catches linked CSS)
|
||||||
Non-HTML files Regex pattern matching (CSS, JSX, TSX, etc.)
|
Non-HTML files Regex pattern matching (CSS, JSX, TSX, etc.)
|
||||||
URLs Puppeteer full browser rendering (auto-detected)
|
URLs Puppeteer full browser rendering (auto-detected)
|
||||||
--fast Forces regex for all files
|
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
impeccable detect src/
|
impeccable detect src/
|
||||||
impeccable detect index.html
|
impeccable detect index.html
|
||||||
impeccable detect https://example.com
|
impeccable detect https://example.com
|
||||||
impeccable detect --fast --json .`);
|
impeccable detect --json .`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function detectCli() {
|
async function detectCli() {
|
||||||
@@ -107,7 +105,15 @@ async function detectCli() {
|
|||||||
if (args[0] === 'detect') args = args.slice(1);
|
if (args[0] === 'detect') args = args.slice(1);
|
||||||
const jsonMode = args.includes('--json');
|
const jsonMode = args.includes('--json');
|
||||||
const helpMode = args.includes('--help');
|
const helpMode = args.includes('--help');
|
||||||
const fastMode = args.includes('--fast');
|
// --fast (regex-only) is deprecated: since the jsdom removal, the static
|
||||||
|
// HTML/CSS analysis is fast and covers every rule, so the regex-only path
|
||||||
|
// only loses coverage for no real speed win. Accept the flag for back-compat
|
||||||
|
// but ignore it and run the full scan.
|
||||||
|
if (args.includes('--fast')) {
|
||||||
|
process.stderr.write(
|
||||||
|
'Note: --fast is deprecated and ignored. The full scan is fast now and runs every rule.\n',
|
||||||
|
);
|
||||||
|
}
|
||||||
const providers = [];
|
const providers = [];
|
||||||
if (args.includes('--gpt')) providers.push('gpt');
|
if (args.includes('--gpt')) providers.push('gpt');
|
||||||
if (args.includes('--gemini')) providers.push('gemini');
|
if (args.includes('--gemini')) providers.push('gemini');
|
||||||
@@ -177,7 +183,7 @@ async function detectCli() {
|
|||||||
process.stderr.write(
|
process.stderr.write(
|
||||||
`\nFound ${files.length} files (${htmlCount} HTML) in ${target}.\n` +
|
`\nFound ${files.length} files (${htmlCount} HTML) in ${target}.\n` +
|
||||||
`Scanning may take a while${htmlCount > 10 ? ' (static HTML/CSS processes each HTML file individually)' : ''}.\n` +
|
`Scanning may take a while${htmlCount > 10 ? ' (static HTML/CSS processes each HTML file individually)' : ''}.\n` +
|
||||||
`Use --fast to skip static HTML/CSS analysis, or target a specific subdirectory.\n`
|
`Target a specific subdirectory to narrow scope.\n`
|
||||||
);
|
);
|
||||||
const ok = await confirm('Continue?');
|
const ok = await confirm('Continue?');
|
||||||
if (!ok) { process.stderr.write('Aborted.\n'); process.exit(0); }
|
if (!ok) { process.stderr.write('Aborted.\n'); process.exit(0); }
|
||||||
@@ -197,7 +203,7 @@ async function detectCli() {
|
|||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
const ext = path.extname(file).toLowerCase();
|
const ext = path.extname(file).toLowerCase();
|
||||||
let fileFindings;
|
let fileFindings;
|
||||||
if (!fastMode && HTML_EXTENSIONS.has(ext)) {
|
if (HTML_EXTENSIONS.has(ext)) {
|
||||||
fileFindings = await detectHtml(file, scanOptions);
|
fileFindings = await detectHtml(file, scanOptions);
|
||||||
} else {
|
} else {
|
||||||
fileFindings = detectText(fs.readFileSync(file, 'utf-8'), file, scanOptions);
|
fileFindings = detectText(fs.readFileSync(file, 'utf-8'), file, scanOptions);
|
||||||
@@ -214,7 +220,7 @@ async function detectCli() {
|
|||||||
}
|
}
|
||||||
} else if (stat.isFile()) {
|
} else if (stat.isFile()) {
|
||||||
const ext = path.extname(resolved).toLowerCase();
|
const ext = path.extname(resolved).toLowerCase();
|
||||||
if (!fastMode && HTML_EXTENSIONS.has(ext)) {
|
if (HTML_EXTENSIONS.has(ext)) {
|
||||||
allFindings.push(...await detectHtml(resolved, scanOptions));
|
allFindings.push(...await detectHtml(resolved, scanOptions));
|
||||||
} else {
|
} else {
|
||||||
allFindings.push(...detectText(fs.readFileSync(resolved, 'utf-8'), resolved, scanOptions));
|
allFindings.push(...detectText(fs.readFileSync(resolved, 'utf-8'), resolved, scanOptions));
|
||||||
|
|||||||
@@ -50,12 +50,12 @@ Run the bundled detector and browser visualization evidence. Assessment B is man
|
|||||||
|
|
||||||
CLI scan:
|
CLI scan:
|
||||||
```bash
|
```bash
|
||||||
node .pi/skills/impeccable/scripts/detect.mjs --json [--fast] [target]
|
node .pi/skills/impeccable/scripts/detect.mjs --json [target]
|
||||||
```
|
```
|
||||||
|
|
||||||
- Pass markup files/directories as `[target]`; do not pass CSS-only files.
|
- Pass markup files/directories as `[target]`; do not pass CSS-only files.
|
||||||
- For URLs, skip CLI scan and use browser visualization.
|
- For URLs, skip CLI scan and use browser visualization.
|
||||||
- For 200+ scannable files, use `--fast`; for 500+, narrow scope or ask.
|
- For very large trees (500+ scannable files), narrow scope or ask.
|
||||||
- Exit code 0 = clean; 2 = findings.
|
- Exit code 0 = clean; 2 = findings.
|
||||||
- If the detector entrypoint is missing or fails to load, report deterministic scan unavailable and continue with browser/manual review.
|
- If the detector entrypoint is missing or fails to load, report deterministic scan unavailable and continue with browser/manual review.
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,6 @@ function printUsage() {
|
|||||||
Scan files or URLs for UI anti-patterns and design quality issues.
|
Scan files or URLs for UI anti-patterns and design quality issues.
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--fast Regex-only mode (skip static HTML/CSS analysis, faster but misses linked stylesheets)
|
|
||||||
--json Output results as JSON
|
--json Output results as JSON
|
||||||
--gpt Also report GPT-specific provider tells (off by default)
|
--gpt Also report GPT-specific provider tells (off by default)
|
||||||
--gemini Also report Gemini-specific provider tells (off by default)
|
--gemini Also report Gemini-specific provider tells (off by default)
|
||||||
@@ -89,13 +88,12 @@ Detection modes:
|
|||||||
HTML files Static HTML/CSS analysis (default, catches linked CSS)
|
HTML files Static HTML/CSS analysis (default, catches linked CSS)
|
||||||
Non-HTML files Regex pattern matching (CSS, JSX, TSX, etc.)
|
Non-HTML files Regex pattern matching (CSS, JSX, TSX, etc.)
|
||||||
URLs Puppeteer full browser rendering (auto-detected)
|
URLs Puppeteer full browser rendering (auto-detected)
|
||||||
--fast Forces regex for all files
|
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
impeccable detect src/
|
impeccable detect src/
|
||||||
impeccable detect index.html
|
impeccable detect index.html
|
||||||
impeccable detect https://example.com
|
impeccable detect https://example.com
|
||||||
impeccable detect --fast --json .`);
|
impeccable detect --json .`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function detectCli() {
|
async function detectCli() {
|
||||||
@@ -107,7 +105,15 @@ async function detectCli() {
|
|||||||
if (args[0] === 'detect') args = args.slice(1);
|
if (args[0] === 'detect') args = args.slice(1);
|
||||||
const jsonMode = args.includes('--json');
|
const jsonMode = args.includes('--json');
|
||||||
const helpMode = args.includes('--help');
|
const helpMode = args.includes('--help');
|
||||||
const fastMode = args.includes('--fast');
|
// --fast (regex-only) is deprecated: since the jsdom removal, the static
|
||||||
|
// HTML/CSS analysis is fast and covers every rule, so the regex-only path
|
||||||
|
// only loses coverage for no real speed win. Accept the flag for back-compat
|
||||||
|
// but ignore it and run the full scan.
|
||||||
|
if (args.includes('--fast')) {
|
||||||
|
process.stderr.write(
|
||||||
|
'Note: --fast is deprecated and ignored. The full scan is fast now and runs every rule.\n',
|
||||||
|
);
|
||||||
|
}
|
||||||
const providers = [];
|
const providers = [];
|
||||||
if (args.includes('--gpt')) providers.push('gpt');
|
if (args.includes('--gpt')) providers.push('gpt');
|
||||||
if (args.includes('--gemini')) providers.push('gemini');
|
if (args.includes('--gemini')) providers.push('gemini');
|
||||||
@@ -177,7 +183,7 @@ async function detectCli() {
|
|||||||
process.stderr.write(
|
process.stderr.write(
|
||||||
`\nFound ${files.length} files (${htmlCount} HTML) in ${target}.\n` +
|
`\nFound ${files.length} files (${htmlCount} HTML) in ${target}.\n` +
|
||||||
`Scanning may take a while${htmlCount > 10 ? ' (static HTML/CSS processes each HTML file individually)' : ''}.\n` +
|
`Scanning may take a while${htmlCount > 10 ? ' (static HTML/CSS processes each HTML file individually)' : ''}.\n` +
|
||||||
`Use --fast to skip static HTML/CSS analysis, or target a specific subdirectory.\n`
|
`Target a specific subdirectory to narrow scope.\n`
|
||||||
);
|
);
|
||||||
const ok = await confirm('Continue?');
|
const ok = await confirm('Continue?');
|
||||||
if (!ok) { process.stderr.write('Aborted.\n'); process.exit(0); }
|
if (!ok) { process.stderr.write('Aborted.\n'); process.exit(0); }
|
||||||
@@ -197,7 +203,7 @@ async function detectCli() {
|
|||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
const ext = path.extname(file).toLowerCase();
|
const ext = path.extname(file).toLowerCase();
|
||||||
let fileFindings;
|
let fileFindings;
|
||||||
if (!fastMode && HTML_EXTENSIONS.has(ext)) {
|
if (HTML_EXTENSIONS.has(ext)) {
|
||||||
fileFindings = await detectHtml(file, scanOptions);
|
fileFindings = await detectHtml(file, scanOptions);
|
||||||
} else {
|
} else {
|
||||||
fileFindings = detectText(fs.readFileSync(file, 'utf-8'), file, scanOptions);
|
fileFindings = detectText(fs.readFileSync(file, 'utf-8'), file, scanOptions);
|
||||||
@@ -214,7 +220,7 @@ async function detectCli() {
|
|||||||
}
|
}
|
||||||
} else if (stat.isFile()) {
|
} else if (stat.isFile()) {
|
||||||
const ext = path.extname(resolved).toLowerCase();
|
const ext = path.extname(resolved).toLowerCase();
|
||||||
if (!fastMode && HTML_EXTENSIONS.has(ext)) {
|
if (HTML_EXTENSIONS.has(ext)) {
|
||||||
allFindings.push(...await detectHtml(resolved, scanOptions));
|
allFindings.push(...await detectHtml(resolved, scanOptions));
|
||||||
} else {
|
} else {
|
||||||
allFindings.push(...detectText(fs.readFileSync(resolved, 'utf-8'), resolved, scanOptions));
|
allFindings.push(...detectText(fs.readFileSync(resolved, 'utf-8'), resolved, scanOptions));
|
||||||
|
|||||||
@@ -50,12 +50,12 @@ Run the bundled detector and browser visualization evidence. Assessment B is man
|
|||||||
|
|
||||||
CLI scan:
|
CLI scan:
|
||||||
```bash
|
```bash
|
||||||
node .qoder/skills/impeccable/scripts/detect.mjs --json [--fast] [target]
|
node .qoder/skills/impeccable/scripts/detect.mjs --json [target]
|
||||||
```
|
```
|
||||||
|
|
||||||
- Pass markup files/directories as `[target]`; do not pass CSS-only files.
|
- Pass markup files/directories as `[target]`; do not pass CSS-only files.
|
||||||
- For URLs, skip CLI scan and use browser visualization.
|
- For URLs, skip CLI scan and use browser visualization.
|
||||||
- For 200+ scannable files, use `--fast`; for 500+, narrow scope or ask.
|
- For very large trees (500+ scannable files), narrow scope or ask.
|
||||||
- Exit code 0 = clean; 2 = findings.
|
- Exit code 0 = clean; 2 = findings.
|
||||||
- If the detector entrypoint is missing or fails to load, report deterministic scan unavailable and continue with browser/manual review.
|
- If the detector entrypoint is missing or fails to load, report deterministic scan unavailable and continue with browser/manual review.
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,6 @@ function printUsage() {
|
|||||||
Scan files or URLs for UI anti-patterns and design quality issues.
|
Scan files or URLs for UI anti-patterns and design quality issues.
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--fast Regex-only mode (skip static HTML/CSS analysis, faster but misses linked stylesheets)
|
|
||||||
--json Output results as JSON
|
--json Output results as JSON
|
||||||
--gpt Also report GPT-specific provider tells (off by default)
|
--gpt Also report GPT-specific provider tells (off by default)
|
||||||
--gemini Also report Gemini-specific provider tells (off by default)
|
--gemini Also report Gemini-specific provider tells (off by default)
|
||||||
@@ -89,13 +88,12 @@ Detection modes:
|
|||||||
HTML files Static HTML/CSS analysis (default, catches linked CSS)
|
HTML files Static HTML/CSS analysis (default, catches linked CSS)
|
||||||
Non-HTML files Regex pattern matching (CSS, JSX, TSX, etc.)
|
Non-HTML files Regex pattern matching (CSS, JSX, TSX, etc.)
|
||||||
URLs Puppeteer full browser rendering (auto-detected)
|
URLs Puppeteer full browser rendering (auto-detected)
|
||||||
--fast Forces regex for all files
|
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
impeccable detect src/
|
impeccable detect src/
|
||||||
impeccable detect index.html
|
impeccable detect index.html
|
||||||
impeccable detect https://example.com
|
impeccable detect https://example.com
|
||||||
impeccable detect --fast --json .`);
|
impeccable detect --json .`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function detectCli() {
|
async function detectCli() {
|
||||||
@@ -107,7 +105,15 @@ async function detectCli() {
|
|||||||
if (args[0] === 'detect') args = args.slice(1);
|
if (args[0] === 'detect') args = args.slice(1);
|
||||||
const jsonMode = args.includes('--json');
|
const jsonMode = args.includes('--json');
|
||||||
const helpMode = args.includes('--help');
|
const helpMode = args.includes('--help');
|
||||||
const fastMode = args.includes('--fast');
|
// --fast (regex-only) is deprecated: since the jsdom removal, the static
|
||||||
|
// HTML/CSS analysis is fast and covers every rule, so the regex-only path
|
||||||
|
// only loses coverage for no real speed win. Accept the flag for back-compat
|
||||||
|
// but ignore it and run the full scan.
|
||||||
|
if (args.includes('--fast')) {
|
||||||
|
process.stderr.write(
|
||||||
|
'Note: --fast is deprecated and ignored. The full scan is fast now and runs every rule.\n',
|
||||||
|
);
|
||||||
|
}
|
||||||
const providers = [];
|
const providers = [];
|
||||||
if (args.includes('--gpt')) providers.push('gpt');
|
if (args.includes('--gpt')) providers.push('gpt');
|
||||||
if (args.includes('--gemini')) providers.push('gemini');
|
if (args.includes('--gemini')) providers.push('gemini');
|
||||||
@@ -177,7 +183,7 @@ async function detectCli() {
|
|||||||
process.stderr.write(
|
process.stderr.write(
|
||||||
`\nFound ${files.length} files (${htmlCount} HTML) in ${target}.\n` +
|
`\nFound ${files.length} files (${htmlCount} HTML) in ${target}.\n` +
|
||||||
`Scanning may take a while${htmlCount > 10 ? ' (static HTML/CSS processes each HTML file individually)' : ''}.\n` +
|
`Scanning may take a while${htmlCount > 10 ? ' (static HTML/CSS processes each HTML file individually)' : ''}.\n` +
|
||||||
`Use --fast to skip static HTML/CSS analysis, or target a specific subdirectory.\n`
|
`Target a specific subdirectory to narrow scope.\n`
|
||||||
);
|
);
|
||||||
const ok = await confirm('Continue?');
|
const ok = await confirm('Continue?');
|
||||||
if (!ok) { process.stderr.write('Aborted.\n'); process.exit(0); }
|
if (!ok) { process.stderr.write('Aborted.\n'); process.exit(0); }
|
||||||
@@ -197,7 +203,7 @@ async function detectCli() {
|
|||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
const ext = path.extname(file).toLowerCase();
|
const ext = path.extname(file).toLowerCase();
|
||||||
let fileFindings;
|
let fileFindings;
|
||||||
if (!fastMode && HTML_EXTENSIONS.has(ext)) {
|
if (HTML_EXTENSIONS.has(ext)) {
|
||||||
fileFindings = await detectHtml(file, scanOptions);
|
fileFindings = await detectHtml(file, scanOptions);
|
||||||
} else {
|
} else {
|
||||||
fileFindings = detectText(fs.readFileSync(file, 'utf-8'), file, scanOptions);
|
fileFindings = detectText(fs.readFileSync(file, 'utf-8'), file, scanOptions);
|
||||||
@@ -214,7 +220,7 @@ async function detectCli() {
|
|||||||
}
|
}
|
||||||
} else if (stat.isFile()) {
|
} else if (stat.isFile()) {
|
||||||
const ext = path.extname(resolved).toLowerCase();
|
const ext = path.extname(resolved).toLowerCase();
|
||||||
if (!fastMode && HTML_EXTENSIONS.has(ext)) {
|
if (HTML_EXTENSIONS.has(ext)) {
|
||||||
allFindings.push(...await detectHtml(resolved, scanOptions));
|
allFindings.push(...await detectHtml(resolved, scanOptions));
|
||||||
} else {
|
} else {
|
||||||
allFindings.push(...detectText(fs.readFileSync(resolved, 'utf-8'), resolved, scanOptions));
|
allFindings.push(...detectText(fs.readFileSync(resolved, 'utf-8'), resolved, scanOptions));
|
||||||
|
|||||||
@@ -50,12 +50,12 @@ Run the bundled detector and browser visualization evidence. Assessment B is man
|
|||||||
|
|
||||||
CLI scan:
|
CLI scan:
|
||||||
```bash
|
```bash
|
||||||
node .rovodev/skills/impeccable/scripts/detect.mjs --json [--fast] [target]
|
node .rovodev/skills/impeccable/scripts/detect.mjs --json [target]
|
||||||
```
|
```
|
||||||
|
|
||||||
- Pass markup files/directories as `[target]`; do not pass CSS-only files.
|
- Pass markup files/directories as `[target]`; do not pass CSS-only files.
|
||||||
- For URLs, skip CLI scan and use browser visualization.
|
- For URLs, skip CLI scan and use browser visualization.
|
||||||
- For 200+ scannable files, use `--fast`; for 500+, narrow scope or ask.
|
- For very large trees (500+ scannable files), narrow scope or ask.
|
||||||
- Exit code 0 = clean; 2 = findings.
|
- Exit code 0 = clean; 2 = findings.
|
||||||
- If the detector entrypoint is missing or fails to load, report deterministic scan unavailable and continue with browser/manual review.
|
- If the detector entrypoint is missing or fails to load, report deterministic scan unavailable and continue with browser/manual review.
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,6 @@ function printUsage() {
|
|||||||
Scan files or URLs for UI anti-patterns and design quality issues.
|
Scan files or URLs for UI anti-patterns and design quality issues.
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--fast Regex-only mode (skip static HTML/CSS analysis, faster but misses linked stylesheets)
|
|
||||||
--json Output results as JSON
|
--json Output results as JSON
|
||||||
--gpt Also report GPT-specific provider tells (off by default)
|
--gpt Also report GPT-specific provider tells (off by default)
|
||||||
--gemini Also report Gemini-specific provider tells (off by default)
|
--gemini Also report Gemini-specific provider tells (off by default)
|
||||||
@@ -89,13 +88,12 @@ Detection modes:
|
|||||||
HTML files Static HTML/CSS analysis (default, catches linked CSS)
|
HTML files Static HTML/CSS analysis (default, catches linked CSS)
|
||||||
Non-HTML files Regex pattern matching (CSS, JSX, TSX, etc.)
|
Non-HTML files Regex pattern matching (CSS, JSX, TSX, etc.)
|
||||||
URLs Puppeteer full browser rendering (auto-detected)
|
URLs Puppeteer full browser rendering (auto-detected)
|
||||||
--fast Forces regex for all files
|
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
impeccable detect src/
|
impeccable detect src/
|
||||||
impeccable detect index.html
|
impeccable detect index.html
|
||||||
impeccable detect https://example.com
|
impeccable detect https://example.com
|
||||||
impeccable detect --fast --json .`);
|
impeccable detect --json .`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function detectCli() {
|
async function detectCli() {
|
||||||
@@ -107,7 +105,15 @@ async function detectCli() {
|
|||||||
if (args[0] === 'detect') args = args.slice(1);
|
if (args[0] === 'detect') args = args.slice(1);
|
||||||
const jsonMode = args.includes('--json');
|
const jsonMode = args.includes('--json');
|
||||||
const helpMode = args.includes('--help');
|
const helpMode = args.includes('--help');
|
||||||
const fastMode = args.includes('--fast');
|
// --fast (regex-only) is deprecated: since the jsdom removal, the static
|
||||||
|
// HTML/CSS analysis is fast and covers every rule, so the regex-only path
|
||||||
|
// only loses coverage for no real speed win. Accept the flag for back-compat
|
||||||
|
// but ignore it and run the full scan.
|
||||||
|
if (args.includes('--fast')) {
|
||||||
|
process.stderr.write(
|
||||||
|
'Note: --fast is deprecated and ignored. The full scan is fast now and runs every rule.\n',
|
||||||
|
);
|
||||||
|
}
|
||||||
const providers = [];
|
const providers = [];
|
||||||
if (args.includes('--gpt')) providers.push('gpt');
|
if (args.includes('--gpt')) providers.push('gpt');
|
||||||
if (args.includes('--gemini')) providers.push('gemini');
|
if (args.includes('--gemini')) providers.push('gemini');
|
||||||
@@ -177,7 +183,7 @@ async function detectCli() {
|
|||||||
process.stderr.write(
|
process.stderr.write(
|
||||||
`\nFound ${files.length} files (${htmlCount} HTML) in ${target}.\n` +
|
`\nFound ${files.length} files (${htmlCount} HTML) in ${target}.\n` +
|
||||||
`Scanning may take a while${htmlCount > 10 ? ' (static HTML/CSS processes each HTML file individually)' : ''}.\n` +
|
`Scanning may take a while${htmlCount > 10 ? ' (static HTML/CSS processes each HTML file individually)' : ''}.\n` +
|
||||||
`Use --fast to skip static HTML/CSS analysis, or target a specific subdirectory.\n`
|
`Target a specific subdirectory to narrow scope.\n`
|
||||||
);
|
);
|
||||||
const ok = await confirm('Continue?');
|
const ok = await confirm('Continue?');
|
||||||
if (!ok) { process.stderr.write('Aborted.\n'); process.exit(0); }
|
if (!ok) { process.stderr.write('Aborted.\n'); process.exit(0); }
|
||||||
@@ -197,7 +203,7 @@ async function detectCli() {
|
|||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
const ext = path.extname(file).toLowerCase();
|
const ext = path.extname(file).toLowerCase();
|
||||||
let fileFindings;
|
let fileFindings;
|
||||||
if (!fastMode && HTML_EXTENSIONS.has(ext)) {
|
if (HTML_EXTENSIONS.has(ext)) {
|
||||||
fileFindings = await detectHtml(file, scanOptions);
|
fileFindings = await detectHtml(file, scanOptions);
|
||||||
} else {
|
} else {
|
||||||
fileFindings = detectText(fs.readFileSync(file, 'utf-8'), file, scanOptions);
|
fileFindings = detectText(fs.readFileSync(file, 'utf-8'), file, scanOptions);
|
||||||
@@ -214,7 +220,7 @@ async function detectCli() {
|
|||||||
}
|
}
|
||||||
} else if (stat.isFile()) {
|
} else if (stat.isFile()) {
|
||||||
const ext = path.extname(resolved).toLowerCase();
|
const ext = path.extname(resolved).toLowerCase();
|
||||||
if (!fastMode && HTML_EXTENSIONS.has(ext)) {
|
if (HTML_EXTENSIONS.has(ext)) {
|
||||||
allFindings.push(...await detectHtml(resolved, scanOptions));
|
allFindings.push(...await detectHtml(resolved, scanOptions));
|
||||||
} else {
|
} else {
|
||||||
allFindings.push(...detectText(fs.readFileSync(resolved, 'utf-8'), resolved, scanOptions));
|
allFindings.push(...detectText(fs.readFileSync(resolved, 'utf-8'), resolved, scanOptions));
|
||||||
|
|||||||
@@ -50,12 +50,12 @@ Run the bundled detector and browser visualization evidence. Assessment B is man
|
|||||||
|
|
||||||
CLI scan:
|
CLI scan:
|
||||||
```bash
|
```bash
|
||||||
node .trae-cn/skills/impeccable/scripts/detect.mjs --json [--fast] [target]
|
node .trae-cn/skills/impeccable/scripts/detect.mjs --json [target]
|
||||||
```
|
```
|
||||||
|
|
||||||
- Pass markup files/directories as `[target]`; do not pass CSS-only files.
|
- Pass markup files/directories as `[target]`; do not pass CSS-only files.
|
||||||
- For URLs, skip CLI scan and use browser visualization.
|
- For URLs, skip CLI scan and use browser visualization.
|
||||||
- For 200+ scannable files, use `--fast`; for 500+, narrow scope or ask.
|
- For very large trees (500+ scannable files), narrow scope or ask.
|
||||||
- Exit code 0 = clean; 2 = findings.
|
- Exit code 0 = clean; 2 = findings.
|
||||||
- If the detector entrypoint is missing or fails to load, report deterministic scan unavailable and continue with browser/manual review.
|
- If the detector entrypoint is missing or fails to load, report deterministic scan unavailable and continue with browser/manual review.
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,6 @@ function printUsage() {
|
|||||||
Scan files or URLs for UI anti-patterns and design quality issues.
|
Scan files or URLs for UI anti-patterns and design quality issues.
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--fast Regex-only mode (skip static HTML/CSS analysis, faster but misses linked stylesheets)
|
|
||||||
--json Output results as JSON
|
--json Output results as JSON
|
||||||
--gpt Also report GPT-specific provider tells (off by default)
|
--gpt Also report GPT-specific provider tells (off by default)
|
||||||
--gemini Also report Gemini-specific provider tells (off by default)
|
--gemini Also report Gemini-specific provider tells (off by default)
|
||||||
@@ -89,13 +88,12 @@ Detection modes:
|
|||||||
HTML files Static HTML/CSS analysis (default, catches linked CSS)
|
HTML files Static HTML/CSS analysis (default, catches linked CSS)
|
||||||
Non-HTML files Regex pattern matching (CSS, JSX, TSX, etc.)
|
Non-HTML files Regex pattern matching (CSS, JSX, TSX, etc.)
|
||||||
URLs Puppeteer full browser rendering (auto-detected)
|
URLs Puppeteer full browser rendering (auto-detected)
|
||||||
--fast Forces regex for all files
|
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
impeccable detect src/
|
impeccable detect src/
|
||||||
impeccable detect index.html
|
impeccable detect index.html
|
||||||
impeccable detect https://example.com
|
impeccable detect https://example.com
|
||||||
impeccable detect --fast --json .`);
|
impeccable detect --json .`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function detectCli() {
|
async function detectCli() {
|
||||||
@@ -107,7 +105,15 @@ async function detectCli() {
|
|||||||
if (args[0] === 'detect') args = args.slice(1);
|
if (args[0] === 'detect') args = args.slice(1);
|
||||||
const jsonMode = args.includes('--json');
|
const jsonMode = args.includes('--json');
|
||||||
const helpMode = args.includes('--help');
|
const helpMode = args.includes('--help');
|
||||||
const fastMode = args.includes('--fast');
|
// --fast (regex-only) is deprecated: since the jsdom removal, the static
|
||||||
|
// HTML/CSS analysis is fast and covers every rule, so the regex-only path
|
||||||
|
// only loses coverage for no real speed win. Accept the flag for back-compat
|
||||||
|
// but ignore it and run the full scan.
|
||||||
|
if (args.includes('--fast')) {
|
||||||
|
process.stderr.write(
|
||||||
|
'Note: --fast is deprecated and ignored. The full scan is fast now and runs every rule.\n',
|
||||||
|
);
|
||||||
|
}
|
||||||
const providers = [];
|
const providers = [];
|
||||||
if (args.includes('--gpt')) providers.push('gpt');
|
if (args.includes('--gpt')) providers.push('gpt');
|
||||||
if (args.includes('--gemini')) providers.push('gemini');
|
if (args.includes('--gemini')) providers.push('gemini');
|
||||||
@@ -177,7 +183,7 @@ async function detectCli() {
|
|||||||
process.stderr.write(
|
process.stderr.write(
|
||||||
`\nFound ${files.length} files (${htmlCount} HTML) in ${target}.\n` +
|
`\nFound ${files.length} files (${htmlCount} HTML) in ${target}.\n` +
|
||||||
`Scanning may take a while${htmlCount > 10 ? ' (static HTML/CSS processes each HTML file individually)' : ''}.\n` +
|
`Scanning may take a while${htmlCount > 10 ? ' (static HTML/CSS processes each HTML file individually)' : ''}.\n` +
|
||||||
`Use --fast to skip static HTML/CSS analysis, or target a specific subdirectory.\n`
|
`Target a specific subdirectory to narrow scope.\n`
|
||||||
);
|
);
|
||||||
const ok = await confirm('Continue?');
|
const ok = await confirm('Continue?');
|
||||||
if (!ok) { process.stderr.write('Aborted.\n'); process.exit(0); }
|
if (!ok) { process.stderr.write('Aborted.\n'); process.exit(0); }
|
||||||
@@ -197,7 +203,7 @@ async function detectCli() {
|
|||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
const ext = path.extname(file).toLowerCase();
|
const ext = path.extname(file).toLowerCase();
|
||||||
let fileFindings;
|
let fileFindings;
|
||||||
if (!fastMode && HTML_EXTENSIONS.has(ext)) {
|
if (HTML_EXTENSIONS.has(ext)) {
|
||||||
fileFindings = await detectHtml(file, scanOptions);
|
fileFindings = await detectHtml(file, scanOptions);
|
||||||
} else {
|
} else {
|
||||||
fileFindings = detectText(fs.readFileSync(file, 'utf-8'), file, scanOptions);
|
fileFindings = detectText(fs.readFileSync(file, 'utf-8'), file, scanOptions);
|
||||||
@@ -214,7 +220,7 @@ async function detectCli() {
|
|||||||
}
|
}
|
||||||
} else if (stat.isFile()) {
|
} else if (stat.isFile()) {
|
||||||
const ext = path.extname(resolved).toLowerCase();
|
const ext = path.extname(resolved).toLowerCase();
|
||||||
if (!fastMode && HTML_EXTENSIONS.has(ext)) {
|
if (HTML_EXTENSIONS.has(ext)) {
|
||||||
allFindings.push(...await detectHtml(resolved, scanOptions));
|
allFindings.push(...await detectHtml(resolved, scanOptions));
|
||||||
} else {
|
} else {
|
||||||
allFindings.push(...detectText(fs.readFileSync(resolved, 'utf-8'), resolved, scanOptions));
|
allFindings.push(...detectText(fs.readFileSync(resolved, 'utf-8'), resolved, scanOptions));
|
||||||
|
|||||||
@@ -50,12 +50,12 @@ Run the bundled detector and browser visualization evidence. Assessment B is man
|
|||||||
|
|
||||||
CLI scan:
|
CLI scan:
|
||||||
```bash
|
```bash
|
||||||
node .trae/skills/impeccable/scripts/detect.mjs --json [--fast] [target]
|
node .trae/skills/impeccable/scripts/detect.mjs --json [target]
|
||||||
```
|
```
|
||||||
|
|
||||||
- Pass markup files/directories as `[target]`; do not pass CSS-only files.
|
- Pass markup files/directories as `[target]`; do not pass CSS-only files.
|
||||||
- For URLs, skip CLI scan and use browser visualization.
|
- For URLs, skip CLI scan and use browser visualization.
|
||||||
- For 200+ scannable files, use `--fast`; for 500+, narrow scope or ask.
|
- For very large trees (500+ scannable files), narrow scope or ask.
|
||||||
- Exit code 0 = clean; 2 = findings.
|
- Exit code 0 = clean; 2 = findings.
|
||||||
- If the detector entrypoint is missing or fails to load, report deterministic scan unavailable and continue with browser/manual review.
|
- If the detector entrypoint is missing or fails to load, report deterministic scan unavailable and continue with browser/manual review.
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,6 @@ function printUsage() {
|
|||||||
Scan files or URLs for UI anti-patterns and design quality issues.
|
Scan files or URLs for UI anti-patterns and design quality issues.
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--fast Regex-only mode (skip static HTML/CSS analysis, faster but misses linked stylesheets)
|
|
||||||
--json Output results as JSON
|
--json Output results as JSON
|
||||||
--gpt Also report GPT-specific provider tells (off by default)
|
--gpt Also report GPT-specific provider tells (off by default)
|
||||||
--gemini Also report Gemini-specific provider tells (off by default)
|
--gemini Also report Gemini-specific provider tells (off by default)
|
||||||
@@ -89,13 +88,12 @@ Detection modes:
|
|||||||
HTML files Static HTML/CSS analysis (default, catches linked CSS)
|
HTML files Static HTML/CSS analysis (default, catches linked CSS)
|
||||||
Non-HTML files Regex pattern matching (CSS, JSX, TSX, etc.)
|
Non-HTML files Regex pattern matching (CSS, JSX, TSX, etc.)
|
||||||
URLs Puppeteer full browser rendering (auto-detected)
|
URLs Puppeteer full browser rendering (auto-detected)
|
||||||
--fast Forces regex for all files
|
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
impeccable detect src/
|
impeccable detect src/
|
||||||
impeccable detect index.html
|
impeccable detect index.html
|
||||||
impeccable detect https://example.com
|
impeccable detect https://example.com
|
||||||
impeccable detect --fast --json .`);
|
impeccable detect --json .`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function detectCli() {
|
async function detectCli() {
|
||||||
@@ -107,7 +105,15 @@ async function detectCli() {
|
|||||||
if (args[0] === 'detect') args = args.slice(1);
|
if (args[0] === 'detect') args = args.slice(1);
|
||||||
const jsonMode = args.includes('--json');
|
const jsonMode = args.includes('--json');
|
||||||
const helpMode = args.includes('--help');
|
const helpMode = args.includes('--help');
|
||||||
const fastMode = args.includes('--fast');
|
// --fast (regex-only) is deprecated: since the jsdom removal, the static
|
||||||
|
// HTML/CSS analysis is fast and covers every rule, so the regex-only path
|
||||||
|
// only loses coverage for no real speed win. Accept the flag for back-compat
|
||||||
|
// but ignore it and run the full scan.
|
||||||
|
if (args.includes('--fast')) {
|
||||||
|
process.stderr.write(
|
||||||
|
'Note: --fast is deprecated and ignored. The full scan is fast now and runs every rule.\n',
|
||||||
|
);
|
||||||
|
}
|
||||||
const providers = [];
|
const providers = [];
|
||||||
if (args.includes('--gpt')) providers.push('gpt');
|
if (args.includes('--gpt')) providers.push('gpt');
|
||||||
if (args.includes('--gemini')) providers.push('gemini');
|
if (args.includes('--gemini')) providers.push('gemini');
|
||||||
@@ -177,7 +183,7 @@ async function detectCli() {
|
|||||||
process.stderr.write(
|
process.stderr.write(
|
||||||
`\nFound ${files.length} files (${htmlCount} HTML) in ${target}.\n` +
|
`\nFound ${files.length} files (${htmlCount} HTML) in ${target}.\n` +
|
||||||
`Scanning may take a while${htmlCount > 10 ? ' (static HTML/CSS processes each HTML file individually)' : ''}.\n` +
|
`Scanning may take a while${htmlCount > 10 ? ' (static HTML/CSS processes each HTML file individually)' : ''}.\n` +
|
||||||
`Use --fast to skip static HTML/CSS analysis, or target a specific subdirectory.\n`
|
`Target a specific subdirectory to narrow scope.\n`
|
||||||
);
|
);
|
||||||
const ok = await confirm('Continue?');
|
const ok = await confirm('Continue?');
|
||||||
if (!ok) { process.stderr.write('Aborted.\n'); process.exit(0); }
|
if (!ok) { process.stderr.write('Aborted.\n'); process.exit(0); }
|
||||||
@@ -197,7 +203,7 @@ async function detectCli() {
|
|||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
const ext = path.extname(file).toLowerCase();
|
const ext = path.extname(file).toLowerCase();
|
||||||
let fileFindings;
|
let fileFindings;
|
||||||
if (!fastMode && HTML_EXTENSIONS.has(ext)) {
|
if (HTML_EXTENSIONS.has(ext)) {
|
||||||
fileFindings = await detectHtml(file, scanOptions);
|
fileFindings = await detectHtml(file, scanOptions);
|
||||||
} else {
|
} else {
|
||||||
fileFindings = detectText(fs.readFileSync(file, 'utf-8'), file, scanOptions);
|
fileFindings = detectText(fs.readFileSync(file, 'utf-8'), file, scanOptions);
|
||||||
@@ -214,7 +220,7 @@ async function detectCli() {
|
|||||||
}
|
}
|
||||||
} else if (stat.isFile()) {
|
} else if (stat.isFile()) {
|
||||||
const ext = path.extname(resolved).toLowerCase();
|
const ext = path.extname(resolved).toLowerCase();
|
||||||
if (!fastMode && HTML_EXTENSIONS.has(ext)) {
|
if (HTML_EXTENSIONS.has(ext)) {
|
||||||
allFindings.push(...await detectHtml(resolved, scanOptions));
|
allFindings.push(...await detectHtml(resolved, scanOptions));
|
||||||
} else {
|
} else {
|
||||||
allFindings.push(...detectText(fs.readFileSync(resolved, 'utf-8'), resolved, scanOptions));
|
allFindings.push(...detectText(fs.readFileSync(resolved, 'utf-8'), resolved, scanOptions));
|
||||||
|
|||||||
+13
-7
@@ -79,7 +79,6 @@ function printUsage() {
|
|||||||
Scan files or URLs for UI anti-patterns and design quality issues.
|
Scan files or URLs for UI anti-patterns and design quality issues.
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--fast Regex-only mode (skip static HTML/CSS analysis, faster but misses linked stylesheets)
|
|
||||||
--json Output results as JSON
|
--json Output results as JSON
|
||||||
--gpt Also report GPT-specific provider tells (off by default)
|
--gpt Also report GPT-specific provider tells (off by default)
|
||||||
--gemini Also report Gemini-specific provider tells (off by default)
|
--gemini Also report Gemini-specific provider tells (off by default)
|
||||||
@@ -89,13 +88,12 @@ Detection modes:
|
|||||||
HTML files Static HTML/CSS analysis (default, catches linked CSS)
|
HTML files Static HTML/CSS analysis (default, catches linked CSS)
|
||||||
Non-HTML files Regex pattern matching (CSS, JSX, TSX, etc.)
|
Non-HTML files Regex pattern matching (CSS, JSX, TSX, etc.)
|
||||||
URLs Puppeteer full browser rendering (auto-detected)
|
URLs Puppeteer full browser rendering (auto-detected)
|
||||||
--fast Forces regex for all files
|
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
impeccable detect src/
|
impeccable detect src/
|
||||||
impeccable detect index.html
|
impeccable detect index.html
|
||||||
impeccable detect https://example.com
|
impeccable detect https://example.com
|
||||||
impeccable detect --fast --json .`);
|
impeccable detect --json .`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function detectCli() {
|
async function detectCli() {
|
||||||
@@ -107,7 +105,15 @@ async function detectCli() {
|
|||||||
if (args[0] === 'detect') args = args.slice(1);
|
if (args[0] === 'detect') args = args.slice(1);
|
||||||
const jsonMode = args.includes('--json');
|
const jsonMode = args.includes('--json');
|
||||||
const helpMode = args.includes('--help');
|
const helpMode = args.includes('--help');
|
||||||
const fastMode = args.includes('--fast');
|
// --fast (regex-only) is deprecated: since the jsdom removal, the static
|
||||||
|
// HTML/CSS analysis is fast and covers every rule, so the regex-only path
|
||||||
|
// only loses coverage for no real speed win. Accept the flag for back-compat
|
||||||
|
// but ignore it and run the full scan.
|
||||||
|
if (args.includes('--fast')) {
|
||||||
|
process.stderr.write(
|
||||||
|
'Note: --fast is deprecated and ignored. The full scan is fast now and runs every rule.\n',
|
||||||
|
);
|
||||||
|
}
|
||||||
const providers = [];
|
const providers = [];
|
||||||
if (args.includes('--gpt')) providers.push('gpt');
|
if (args.includes('--gpt')) providers.push('gpt');
|
||||||
if (args.includes('--gemini')) providers.push('gemini');
|
if (args.includes('--gemini')) providers.push('gemini');
|
||||||
@@ -177,7 +183,7 @@ async function detectCli() {
|
|||||||
process.stderr.write(
|
process.stderr.write(
|
||||||
`\nFound ${files.length} files (${htmlCount} HTML) in ${target}.\n` +
|
`\nFound ${files.length} files (${htmlCount} HTML) in ${target}.\n` +
|
||||||
`Scanning may take a while${htmlCount > 10 ? ' (static HTML/CSS processes each HTML file individually)' : ''}.\n` +
|
`Scanning may take a while${htmlCount > 10 ? ' (static HTML/CSS processes each HTML file individually)' : ''}.\n` +
|
||||||
`Use --fast to skip static HTML/CSS analysis, or target a specific subdirectory.\n`
|
`Target a specific subdirectory to narrow scope.\n`
|
||||||
);
|
);
|
||||||
const ok = await confirm('Continue?');
|
const ok = await confirm('Continue?');
|
||||||
if (!ok) { process.stderr.write('Aborted.\n'); process.exit(0); }
|
if (!ok) { process.stderr.write('Aborted.\n'); process.exit(0); }
|
||||||
@@ -197,7 +203,7 @@ async function detectCli() {
|
|||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
const ext = path.extname(file).toLowerCase();
|
const ext = path.extname(file).toLowerCase();
|
||||||
let fileFindings;
|
let fileFindings;
|
||||||
if (!fastMode && HTML_EXTENSIONS.has(ext)) {
|
if (HTML_EXTENSIONS.has(ext)) {
|
||||||
fileFindings = await detectHtml(file, scanOptions);
|
fileFindings = await detectHtml(file, scanOptions);
|
||||||
} else {
|
} else {
|
||||||
fileFindings = detectText(fs.readFileSync(file, 'utf-8'), file, scanOptions);
|
fileFindings = detectText(fs.readFileSync(file, 'utf-8'), file, scanOptions);
|
||||||
@@ -214,7 +220,7 @@ async function detectCli() {
|
|||||||
}
|
}
|
||||||
} else if (stat.isFile()) {
|
} else if (stat.isFile()) {
|
||||||
const ext = path.extname(resolved).toLowerCase();
|
const ext = path.extname(resolved).toLowerCase();
|
||||||
if (!fastMode && HTML_EXTENSIONS.has(ext)) {
|
if (HTML_EXTENSIONS.has(ext)) {
|
||||||
allFindings.push(...await detectHtml(resolved, scanOptions));
|
allFindings.push(...await detectHtml(resolved, scanOptions));
|
||||||
} else {
|
} else {
|
||||||
allFindings.push(...detectText(fs.readFileSync(resolved, 'utf-8'), resolved, scanOptions));
|
allFindings.push(...detectText(fs.readFileSync(resolved, 'utf-8'), resolved, scanOptions));
|
||||||
|
|||||||
@@ -50,12 +50,12 @@ Run the bundled detector and browser visualization evidence. Assessment B is man
|
|||||||
|
|
||||||
CLI scan:
|
CLI scan:
|
||||||
```bash
|
```bash
|
||||||
node .claude/skills/impeccable/scripts/detect.mjs --json [--fast] [target]
|
node .claude/skills/impeccable/scripts/detect.mjs --json [target]
|
||||||
```
|
```
|
||||||
|
|
||||||
- Pass markup files/directories as `[target]`; do not pass CSS-only files.
|
- Pass markup files/directories as `[target]`; do not pass CSS-only files.
|
||||||
- For URLs, skip CLI scan and use browser visualization.
|
- For URLs, skip CLI scan and use browser visualization.
|
||||||
- For 200+ scannable files, use `--fast`; for 500+, narrow scope or ask.
|
- For very large trees (500+ scannable files), narrow scope or ask.
|
||||||
- Exit code 0 = clean; 2 = findings.
|
- Exit code 0 = clean; 2 = findings.
|
||||||
- If the detector entrypoint is missing or fails to load, report deterministic scan unavailable and continue with browser/manual review.
|
- If the detector entrypoint is missing or fails to load, report deterministic scan unavailable and continue with browser/manual review.
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,6 @@ function printUsage() {
|
|||||||
Scan files or URLs for UI anti-patterns and design quality issues.
|
Scan files or URLs for UI anti-patterns and design quality issues.
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
--fast Regex-only mode (skip static HTML/CSS analysis, faster but misses linked stylesheets)
|
|
||||||
--json Output results as JSON
|
--json Output results as JSON
|
||||||
--gpt Also report GPT-specific provider tells (off by default)
|
--gpt Also report GPT-specific provider tells (off by default)
|
||||||
--gemini Also report Gemini-specific provider tells (off by default)
|
--gemini Also report Gemini-specific provider tells (off by default)
|
||||||
@@ -89,13 +88,12 @@ Detection modes:
|
|||||||
HTML files Static HTML/CSS analysis (default, catches linked CSS)
|
HTML files Static HTML/CSS analysis (default, catches linked CSS)
|
||||||
Non-HTML files Regex pattern matching (CSS, JSX, TSX, etc.)
|
Non-HTML files Regex pattern matching (CSS, JSX, TSX, etc.)
|
||||||
URLs Puppeteer full browser rendering (auto-detected)
|
URLs Puppeteer full browser rendering (auto-detected)
|
||||||
--fast Forces regex for all files
|
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
impeccable detect src/
|
impeccable detect src/
|
||||||
impeccable detect index.html
|
impeccable detect index.html
|
||||||
impeccable detect https://example.com
|
impeccable detect https://example.com
|
||||||
impeccable detect --fast --json .`);
|
impeccable detect --json .`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function detectCli() {
|
async function detectCli() {
|
||||||
@@ -107,7 +105,15 @@ async function detectCli() {
|
|||||||
if (args[0] === 'detect') args = args.slice(1);
|
if (args[0] === 'detect') args = args.slice(1);
|
||||||
const jsonMode = args.includes('--json');
|
const jsonMode = args.includes('--json');
|
||||||
const helpMode = args.includes('--help');
|
const helpMode = args.includes('--help');
|
||||||
const fastMode = args.includes('--fast');
|
// --fast (regex-only) is deprecated: since the jsdom removal, the static
|
||||||
|
// HTML/CSS analysis is fast and covers every rule, so the regex-only path
|
||||||
|
// only loses coverage for no real speed win. Accept the flag for back-compat
|
||||||
|
// but ignore it and run the full scan.
|
||||||
|
if (args.includes('--fast')) {
|
||||||
|
process.stderr.write(
|
||||||
|
'Note: --fast is deprecated and ignored. The full scan is fast now and runs every rule.\n',
|
||||||
|
);
|
||||||
|
}
|
||||||
const providers = [];
|
const providers = [];
|
||||||
if (args.includes('--gpt')) providers.push('gpt');
|
if (args.includes('--gpt')) providers.push('gpt');
|
||||||
if (args.includes('--gemini')) providers.push('gemini');
|
if (args.includes('--gemini')) providers.push('gemini');
|
||||||
@@ -177,7 +183,7 @@ async function detectCli() {
|
|||||||
process.stderr.write(
|
process.stderr.write(
|
||||||
`\nFound ${files.length} files (${htmlCount} HTML) in ${target}.\n` +
|
`\nFound ${files.length} files (${htmlCount} HTML) in ${target}.\n` +
|
||||||
`Scanning may take a while${htmlCount > 10 ? ' (static HTML/CSS processes each HTML file individually)' : ''}.\n` +
|
`Scanning may take a while${htmlCount > 10 ? ' (static HTML/CSS processes each HTML file individually)' : ''}.\n` +
|
||||||
`Use --fast to skip static HTML/CSS analysis, or target a specific subdirectory.\n`
|
`Target a specific subdirectory to narrow scope.\n`
|
||||||
);
|
);
|
||||||
const ok = await confirm('Continue?');
|
const ok = await confirm('Continue?');
|
||||||
if (!ok) { process.stderr.write('Aborted.\n'); process.exit(0); }
|
if (!ok) { process.stderr.write('Aborted.\n'); process.exit(0); }
|
||||||
@@ -197,7 +203,7 @@ async function detectCli() {
|
|||||||
for (const file of files) {
|
for (const file of files) {
|
||||||
const ext = path.extname(file).toLowerCase();
|
const ext = path.extname(file).toLowerCase();
|
||||||
let fileFindings;
|
let fileFindings;
|
||||||
if (!fastMode && HTML_EXTENSIONS.has(ext)) {
|
if (HTML_EXTENSIONS.has(ext)) {
|
||||||
fileFindings = await detectHtml(file, scanOptions);
|
fileFindings = await detectHtml(file, scanOptions);
|
||||||
} else {
|
} else {
|
||||||
fileFindings = detectText(fs.readFileSync(file, 'utf-8'), file, scanOptions);
|
fileFindings = detectText(fs.readFileSync(file, 'utf-8'), file, scanOptions);
|
||||||
@@ -214,7 +220,7 @@ async function detectCli() {
|
|||||||
}
|
}
|
||||||
} else if (stat.isFile()) {
|
} else if (stat.isFile()) {
|
||||||
const ext = path.extname(resolved).toLowerCase();
|
const ext = path.extname(resolved).toLowerCase();
|
||||||
if (!fastMode && HTML_EXTENSIONS.has(ext)) {
|
if (HTML_EXTENSIONS.has(ext)) {
|
||||||
allFindings.push(...await detectHtml(resolved, scanOptions));
|
allFindings.push(...await detectHtml(resolved, scanOptions));
|
||||||
} else {
|
} else {
|
||||||
allFindings.push(...detectText(fs.readFileSync(resolved, 'utf-8'), resolved, scanOptions));
|
allFindings.push(...detectText(fs.readFileSync(resolved, 'utf-8'), resolved, scanOptions));
|
||||||
|
|||||||
@@ -60,12 +60,12 @@ Run the bundled detector and browser visualization evidence. Assessment B is man
|
|||||||
|
|
||||||
CLI scan:
|
CLI scan:
|
||||||
```bash
|
```bash
|
||||||
node {{scripts_path}}/detect.mjs --json [--fast] [target]
|
node {{scripts_path}}/detect.mjs --json [target]
|
||||||
```
|
```
|
||||||
|
|
||||||
- Pass markup files/directories as `[target]`; do not pass CSS-only files.
|
- Pass markup files/directories as `[target]`; do not pass CSS-only files.
|
||||||
- For URLs, skip CLI scan and use browser visualization.
|
- For URLs, skip CLI scan and use browser visualization.
|
||||||
- For 200+ scannable files, use `--fast`; for 500+, narrow scope or ask.
|
- For very large trees (500+ scannable files), narrow scope or ask.
|
||||||
- Exit code 0 = clean; 2 = findings.
|
- Exit code 0 = clean; 2 = findings.
|
||||||
- If the detector entrypoint is missing or fails to load, report deterministic scan unavailable and continue with browser/manual review.
|
- If the detector entrypoint is missing or fails to load, report deterministic scan unavailable and continue with browser/manual review.
|
||||||
|
|
||||||
|
|||||||
@@ -720,9 +720,10 @@ describe('CLI', () => {
|
|||||||
expect(JSON.parse(stdout.trim())).toEqual([]);
|
expect(JSON.parse(stdout.trim())).toEqual([]);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('--fast mode works', () => {
|
test('--fast is accepted but deprecated (no-op, full scan still runs)', () => {
|
||||||
const { code } = run('--fast', path.join(FIXTURES, 'should-flag.html'));
|
const { code, stderr } = run('--fast', path.join(FIXTURES, 'should-flag.html'));
|
||||||
expect(code).toBe(2);
|
expect(code).toBe(2); // still flags the planted anti-patterns via the full scan
|
||||||
|
expect(stderr).toContain('--fast is deprecated');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('linked stylesheet detected (static HTML/CSS default)', () => {
|
test('linked stylesheet detected (static HTML/CSS default)', () => {
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ describe('skill detector bundle', () => {
|
|||||||
test('critique references the bundled detector command', () => {
|
test('critique references the bundled detector command', () => {
|
||||||
const critique = fs.readFileSync(path.join(ROOT, 'skill/reference/critique.md'), 'utf-8');
|
const critique = fs.readFileSync(path.join(ROOT, 'skill/reference/critique.md'), 'utf-8');
|
||||||
|
|
||||||
expect(critique).toContain('node {{scripts_path}}/detect.mjs --json [--fast] [target]');
|
expect(critique).toContain('node {{scripts_path}}/detect.mjs --json [target]');
|
||||||
expect(critique).not.toContain('npx impeccable detect');
|
expect(critique).not.toContain('npx impeccable detect');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user