pbakaus/impeccable · error
surface brief path requires a concrete target
Error message
surface brief path requires a concrete target
What it means
Thrown by main() in surface-brief.mjs when the 'path' subcommand is invoked without a concrete target argument. surfaceBriefPathForTarget(target, ...) returns a falsy value when target is empty/undefined (it cannot derive a brief filename without one), and the CLI refuses to guess. The 'list' subcommand intentionally needs no target; 'path', 'read', and 'write' do.
Source
Thrown at skill/scripts/surface-brief.mjs:27
surfaceBriefPathForTarget,
writeSurfaceBrief,
} from './lib/surface-briefs.mjs';
function summary(brief, projectRoot) {
return {
slug: brief.slug,
path: path.relative(projectRoot, brief.path).split(path.sep).join('/'),
primaryTarget: brief.primaryTarget,
relatedTargets: brief.relatedTargets,
};
}
function main(argv) {
const [command, target, bodyFile, ...relatedTargets] = argv;
const projectRoot = resolveProjectRoot(process.cwd(), target ? { targetPath: target } : {});
if (command === 'path') {
const filePath = surfaceBriefPathForTarget(target, { projectRoot });
if (!filePath) throw new Error('surface brief path requires a concrete target');
process.stdout.write(`${path.relative(process.cwd(), filePath) || filePath}\n`);
return;
}
if (command === 'list') {
process.stdout.write(`${JSON.stringify(listSurfaceBriefs(projectRoot).map((brief) => summary(brief, projectRoot)), null, 2)}\n`);
return;
}
if (command === 'read') {
const result = resolveSurfaceBrief(projectRoot, target || null);
if (result.brief) {
process.stdout.write(result.brief.text);
return;
}
if (result.candidates.length) process.stderr.write(`${JSON.stringify(result.candidates.map((brief) => summary(brief, projectRoot)), null, 2)}\n`);
process.exit(2);
}
if (command === 'write') {
if (!target || !bodyFile) throw new Error('usage: surface-brief.mjs write <primary-target> <body-file>');View on GitHub (pinned to d14711ae3d)
Solutions
- Pass a target identifier: 'surface-brief.mjs path src/components/Header.jsx'.
- If you wanted to enumerate existing briefs instead, use 'surface-brief.mjs list'.
- Ensure wrapper scripts pass a non-empty target variable.
Example fix
# before node surface-brief.mjs path # after node surface-brief.mjs path src/components/Header.jsx
Defensive patterns
Strategy: validation
Validate before calling
if (command === 'path' && (!target || target === '')) {
throw new Error('path subcommand requires a target argument');
} Prevention
- Wrap the CLI in a shell function that requires the target for 'path/read/write'.
- Print the usage line to stderr before throwing so users see the fix inline.
- Prefer 'list' when enumerating; require 'path' only when materializing a filename.
When it happens
Trigger: The script is run as 'surface-brief.mjs path' (no target), or 'surface-brief.mjs path ""' (empty target). The destructuring at the top sets target = argv[1]; if absent it is undefined and surfaceBriefPathForTarget returns null.
Common situations: User runs the path subcommand to discover where a brief would live but forgets to name the target; a wrapper script passes an unset variable as the target; confusion with 'list' which needs no target.
Related errors
- --target requires a path value (use --target <path> or --tar
- usage: surface-brief.mjs write <primary-target> <body-file>
- usage: surface-brief.mjs <path|list|read|write> [target] [bo
- Unknown ignore-rule flag: ${arg}
- Pass a rule id, e.g. ${IMPECCABLE_COMMAND} hooks ignore-rule
AI-assisted analysis of pbakaus/impeccable@d14711ae3d (2026-08-13).
Data as JSON: /api/errors/51f8dbffcdbd1159.
Report an issue: GitHub.