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

  1. Pass a target identifier: 'surface-brief.mjs path src/components/Header.jsx'.
  2. If you wanted to enumerate existing briefs instead, use 'surface-brief.mjs list'.
  3. 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

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


AI-assisted analysis of pbakaus/impeccable@d14711ae3d (2026-08-13). Data as JSON: /api/errors/51f8dbffcdbd1159. Report an issue: GitHub.