pbakaus/impeccable · error · Error

surface brief requires a concrete project-relative primary…

Error message

surface brief requires a concrete project-relative primary target or URL

What it means

Thrown by writeSurfaceBrief when normalizeSurfaceTarget returns a falsy value for primaryTarget. A surface brief must name one concrete, project-relative file path or a URL that the brief documents; normalizeSurfaceTarget rejects anything it cannot anchor — values that are not strings, bare names that resolve to no existing project file, or paths that escape the project root. Related targets that fail normalization are silently filtered instead, but the primary target is mandatory.

Solutions

  1. Pass an existing project-relative path such as 'src/pages/index.astro' or a full URL.
  2. Create the target file first if it does not exist yet, then write the brief.
  3. Check the spelling of the primaryTarget option name in the call.
  4. Use resolveSurfaceTarget/normalizeSurfaceTarget on the value first to see why it fails to anchor.

Example fix

// before
writeSurfaceBrief({ projectRoot, primaryTarget: 'homepage' });   // no such file -> throws

// after
writeSurfaceBrief({ projectRoot, primaryTarget: 'src/pages/index.astro' });
writeSurfaceBrief({ projectRoot, primaryTarget: 'https://example.com/pricing' });
Defensive patterns

Strategy: validation

Validate before calling

import path from 'node:path';
function isAnchoredTarget(target, projectRoot) {
  if (typeof target !== 'string' || !target.trim()) return false;
  if (/^https?:\/\//.test(target)) return true;
  const abs = path.resolve(projectRoot, target);
  return abs.startsWith(path.resolve(projectRoot) + path.sep) && fs.existsSync(abs);
}
if (!isAnchoredTarget(primaryTarget, projectRoot)) throw new Error('primaryTarget must be an existing project-relative path or a URL');

Type guard

function isValidPrimaryTarget(t, projectRoot) {
  return typeof t === 'string' && t.trim().length > 0 &&
    (/^https?:\/\//.test(t) ||
      (path.resolve(projectRoot, t).startsWith(path.resolve(projectRoot) + path.sep) &&
       require('node:fs').existsSync(path.resolve(projectRoot, t))));
}

Prevention

When it happens

Trigger: Calling writeSurfaceBrief({ primaryTarget: undefined }) or with the key misspelled; passing a bare page name like 'home' that matches no project file; passing '../outside/index.html' which resolves outside projectRoot; passing an empty string.

Common situations: Agents writing briefs from a plan document where the target was described but never resolved to a real path; callers assuming any label works; typos in the prop name (target vs primaryTarget); target file not yet created.


AI-assisted analysis of pbakaus/impeccable@f88b2837a7 (2026-08-18). Data as JSON: /api/errors/1fd0b1d9b79cc909. Report an issue: GitHub.

Appendix: source

Thrown at skill/scripts/lib/surface-briefs.mjs:132

  const exactPath = surfaceBriefPathForTarget(normalized, { projectRoot });
  const exact = briefs.find((brief) => brief.path === exactPath && (!brief.targets.length || brief.targets.includes(normalized)));
  if (exact) return { brief: exact, candidates: briefs, reason: 'slug' };
  const mapped = briefs.filter((brief) => brief.targets.includes(normalized));
  return {
    brief: mapped.length === 1 ? mapped[0] : null,
    candidates: mapped.length > 1 ? mapped : briefs,
    reason: mapped.length === 1 ? 'mapping' : mapped.length > 1 ? 'ambiguous-target' : 'not-found',
  };
}

export function writeSurfaceBrief({
  projectRoot = process.cwd(),
  primaryTarget,
  relatedTargets = [],
  body,
}) {
  const normalizedPrimary = normalizeSurfaceTarget(primaryTarget, { projectRoot });
  if (!normalizedPrimary) throw new Error('surface brief requires a concrete project-relative primary target or URL');
  const normalizedRelated = [...new Set(relatedTargets
    .map((target) => normalizeSurfaceTarget(target, { projectRoot }))
    .filter((target) => target && target !== normalizedPrimary))];
  const slug = slugFromTarget(normalizedPrimary, { cwd: projectRoot });
  const filePath = surfaceBriefPathForTarget(normalizedPrimary, { projectRoot });
  fs.mkdirSync(path.dirname(filePath), { recursive: true });
  const frontmatter = [
    '---',
    `version: ${SURFACE_BRIEF_VERSION}`,
    `slug: ${JSON.stringify(slug)}`,
    `primary_target: ${JSON.stringify(normalizedPrimary)}`,
    `related_targets: ${JSON.stringify(normalizedRelated)}`,
    '---',
  ].join('\n');
  fs.writeFileSync(filePath, `${frontmatter}\n\n${String(body || '').trim()}\n`, 'utf-8');
  return filePath;
}

View on GitHub (pinned to f88b2837a7)