{"record":{"id":"27d6b4b47b3cb2bd","repo":"santifer/career-ops","slug":"plugins-template-not-found","errorCode":null,"errorMessage":"plugins/_template/ not found","messagePattern":"plugins/_template/ not found","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"plugin-install.mjs","lineNumber":123,"sourceCode":" */\nexport function auditRegistryEntry(url, sha, expectId) {\n  let parsed;\n  try { parsed = parseRepoArg(url); } catch (e) { return [e.message]; }\n  if (expectId && parsed.id !== expectId) return [`repo \"${url}\" → id \"${parsed.id}\" but registry id is \"${expectId}\"`];\n  let dir;\n  try { dir = safeClone(parsed.url, sha); } catch (e) { return [e.message]; }\n  let result;\n  try { result = validateInstall(dir, parsed.id); }\n  catch (e) { rmSync(dir, { recursive: true, force: true }); return [e.message]; }\n  try { rmSync(result.dir || dir, { recursive: true, force: true }); } catch { /* best-effort */ }\n  return result.ok ? [] : result.problems;\n}\n\n/** Scaffold a new local plugin from plugins/_template/. */\nexport function scaffoldNew(root, name) {\n  if (!/^[a-z0-9][a-z0-9-]*$/.test(name)) throw new Error(`plugin name must match [a-z0-9-] (got \"${name}\")`);\n  const tpl = path.join(root, 'plugins', '_template');\n  if (!existsSync(tpl)) throw new Error('plugins/_template/ not found');\n  const dest = path.join(root, 'plugins.local', name);\n  if (existsSync(dest)) throw new Error(`plugins.local/${name} already exists`);\n  mkdirSync(path.join(root, 'plugins.local'), { recursive: true });\n  cpSync(tpl, dest, { recursive: true });\n  // Substitute {{NAME}} placeholders in shipped text files.\n  const sub = (p) => { if (existsSync(p)) writeFileSync(p, readFileSync(p, 'utf8').replaceAll('{{NAME}}', name), 'utf8'); };\n  for (const f of readdirSync(dest, { withFileTypes: true })) {\n    if (f.isFile()) sub(path.join(dest, f.name));\n  }\n  if (existsSync(path.join(dest, 'test'))) for (const f of readdirSync(path.join(dest, 'test'))) sub(path.join(dest, 'test', f));\n  return dest;\n}\n\n// ── CLI flags + help ────────────────────────────────────────────────\n//\n// This file is a library first: plugins.mjs owns the user-facing `new`/`add`\n// commands and calls the exports above. But docs/SCRIPTS.md lists `node\n// plugin-install.mjs` as a runnable command, so it is reachable directly — and","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/santifer/career-ops/blob/aac998c7ed7248ea853b720ceeb1fdbeb322fc5d/plugin-install.mjs#L105-L141","documentation":"scaffoldNew copies plugins/_template/ as the starting point for a new local plugin. If that template directory does not exist in the repo root provided, it throws before creating anything. The template ships with the system; its absence means an incomplete checkout or a deleted/renamed directory.","triggerScenarios":"Calling scaffoldNew(root, name) where path.join(root, 'plugins', '_template') fails existsSync — repo missing the plugins/_template directory.","commonSituations":"Running from a wrong working directory/root; a partial clone or sparse checkout that dropped plugins/; user deleted the template; an old system version before the template was added.","solutions":["Re-sync/re-clone the repo so plugins/_template/ exists (git checkout / reinstall the system files)","Verify you're passing the correct repo root to scaffoldNew, not a subdirectory","Recreate a minimal plugins/_template/ directory with a valid plugin manifest if intentionally customized"],"exampleFix":"// before: running from a shallow copy without the template\nawait scaffoldNew(process.cwd(), 'my-plugin');\n// Error: plugins/_template/ not found\n// after: restore the template from the repo\n// git checkout -- plugins/_template/   (or re-clone)\nawait scaffoldNew(repoRoot, 'my-plugin');","handlingStrategy":"validation","validationCode":"import { existsSync } from 'node:fs';\nif (!existsSync(path.join(root, 'plugins', '_template'))) throw new Error(`template missing at ${root}/plugins/_template — reinstall system files`);","typeGuard":"null","tryCatchPattern":"try { await scaffoldNew(root, name); } catch (e) { if (e.message === 'plugins/_template/ not found') { await restoreTemplate(root); return scaffoldNew(root, name); } throw e; }","preventionTips":["Verify repo integrity (git status / full clone) before scaffolding","Never delete or gitignore plugins/_template/","Pass the repository root, not a subdirectory, as root"],"tags":["plugins","filesystem","missing-template"],"backgroundTag":"file-not-found","analyzedSha":"aac998c7ed7248ea853b720ceeb1fdbeb322fc5d","analyzedAt":"2026-09-16T06:35:29.214Z","contentChangedAt":"2026-09-16T06:35:29.214Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}