{"record":{"id":"1fd0b1d9b79cc909","repo":"pbakaus/impeccable","slug":"surface-brief-requires-a-concrete-project-relative","errorCode":null,"errorMessage":"surface brief requires a concrete project-relative primary target or URL","messagePattern":"surface brief requires a concrete project-relative primary target or URL","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"skill/scripts/lib/surface-briefs.mjs","lineNumber":132,"sourceCode":"  const exactPath = surfaceBriefPathForTarget(normalized, { projectRoot });\n  const exact = briefs.find((brief) => brief.path === exactPath && (!brief.targets.length || brief.targets.includes(normalized)));\n  if (exact) return { brief: exact, candidates: briefs, reason: 'slug' };\n  const mapped = briefs.filter((brief) => brief.targets.includes(normalized));\n  return {\n    brief: mapped.length === 1 ? mapped[0] : null,\n    candidates: mapped.length > 1 ? mapped : briefs,\n    reason: mapped.length === 1 ? 'mapping' : mapped.length > 1 ? 'ambiguous-target' : 'not-found',\n  };\n}\n\nexport function writeSurfaceBrief({\n  projectRoot = process.cwd(),\n  primaryTarget,\n  relatedTargets = [],\n  body,\n}) {\n  const normalizedPrimary = normalizeSurfaceTarget(primaryTarget, { projectRoot });\n  if (!normalizedPrimary) throw new Error('surface brief requires a concrete project-relative primary target or URL');\n  const normalizedRelated = [...new Set(relatedTargets\n    .map((target) => normalizeSurfaceTarget(target, { projectRoot }))\n    .filter((target) => target && target !== normalizedPrimary))];\n  const slug = slugFromTarget(normalizedPrimary, { cwd: projectRoot });\n  const filePath = surfaceBriefPathForTarget(normalizedPrimary, { projectRoot });\n  fs.mkdirSync(path.dirname(filePath), { recursive: true });\n  const frontmatter = [\n    '---',\n    `version: ${SURFACE_BRIEF_VERSION}`,\n    `slug: ${JSON.stringify(slug)}`,\n    `primary_target: ${JSON.stringify(normalizedPrimary)}`,\n    `related_targets: ${JSON.stringify(normalizedRelated)}`,\n    '---',\n  ].join('\\n');\n  fs.writeFileSync(filePath, `${frontmatter}\\n\\n${String(body || '').trim()}\\n`, 'utf-8');\n  return filePath;\n}\n","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/pbakaus/impeccable/blob/f88b2837a7d7c3182e46307bbbb091a1ed547571/skill/scripts/lib/surface-briefs.mjs#L114-L150","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pass an existing project-relative path such as 'src/pages/index.astro' or a full URL.","Create the target file first if it does not exist yet, then write the brief.","Check the spelling of the primaryTarget option name in the call.","Use resolveSurfaceTarget/normalizeSurfaceTarget on the value first to see why it fails to anchor."],"exampleFix":"// before\nwriteSurfaceBrief({ projectRoot, primaryTarget: 'homepage' });   // no such file -> throws\n\n// after\nwriteSurfaceBrief({ projectRoot, primaryTarget: 'src/pages/index.astro' });\nwriteSurfaceBrief({ projectRoot, primaryTarget: 'https://example.com/pricing' });","handlingStrategy":"validation","validationCode":"import path from 'node:path';\nfunction isAnchoredTarget(target, projectRoot) {\n  if (typeof target !== 'string' || !target.trim()) return false;\n  if (/^https?:\\/\\//.test(target)) return true;\n  const abs = path.resolve(projectRoot, target);\n  return abs.startsWith(path.resolve(projectRoot) + path.sep) && fs.existsSync(abs);\n}\nif (!isAnchoredTarget(primaryTarget, projectRoot)) throw new Error('primaryTarget must be an existing project-relative path or a URL');","typeGuard":"function isValidPrimaryTarget(t, projectRoot) {\n  return typeof t === 'string' && t.trim().length > 0 &&\n    (/^https?:\\/\\//.test(t) ||\n      (path.resolve(projectRoot, t).startsWith(path.resolve(projectRoot) + path.sep) &&\n       require('node:fs').existsSync(path.resolve(projectRoot, t))));\n}","tryCatchPattern":null,"preventionTips":["Always pass a path that exists on disk under the project root, or an absolute http(s) URL.","Create the target file before writing its brief.","Spell the option exactly primaryTarget; relatedTargets are optional and normalized loosely, the primary is not."],"tags":["surface-brief","target-validation","path-resolution"],"backgroundTag":"invalid-target-path","analyzedSha":"f88b2837a7d7c3182e46307bbbb091a1ed547571","analyzedAt":"2026-08-18T04:58:36.608Z","contentChangedAt":"2026-08-18T04:58:36.608Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}