{"record":{"id":"756099127382e3ef","repo":"affaan-m/ECC","slug":"missing-provenance-metadata-for-skilldir","errorCode":null,"errorMessage":"Missing provenance metadata for ${skillDir}","messagePattern":"Missing provenance metadata for (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/lib/skill-evolution/provenance.js","lineNumber":147,"sourceCode":"    errors,\n  };\n}\n\nfunction assertValidProvenance(record) {\n  const validation = validateProvenance(record);\n  if (!validation.valid) {\n    throw new Error(`Invalid provenance metadata: ${validation.errors.join('; ')}`);\n  }\n}\n\nfunction readProvenance(skillPath, options = {}) {\n  const skillDir = normalizeSkillDir(skillPath);\n  const provenancePath = getProvenancePath(skillDir);\n  const provenanceRequired = options.required === true || requiresProvenance(skillDir, options);\n\n  if (!fs.existsSync(provenancePath)) {\n    if (provenanceRequired) {\n      throw new Error(`Missing provenance metadata for ${skillDir}`);\n    }\n\n    return null;\n  }\n\n  const record = JSON.parse(fs.readFileSync(provenancePath, 'utf8'));\n  assertValidProvenance(record);\n  return record;\n}\n\nfunction writeProvenance(skillPath, record, options = {}) {\n  const skillDir = normalizeSkillDir(skillPath);\n\n  if (!requiresProvenance(skillDir, options)) {\n    throw new Error(`Provenance metadata is only required for learned or imported skills: ${skillDir}`);\n  }\n\n  assertValidProvenance(record);","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/skill-evolution/provenance.js#L129-L165","documentation":"readProvenance reads the provenance metadata file for a skill directory. If the file does not exist, it returns null when provenance is optional, but throws when provenance is required — either because the caller passed { required: true } or because requiresProvenance() determined the skill directory must carry provenance metadata.","triggerScenarios":"readProvenance(dir, { required: true }) on a skill dir with no provenance file; calling plain readProvenance(dir) on a skill that requiresProvenance() flags (e.g. a third-party/unverified skill lacking metadata); pointing skillPath at a directory that is a different skill than intended, one without a provenance file.","commonSituations":"Onboarding old skills into a repo that now enforces provenance; vendored/community skills copied in without their metadata file; .gitignore or packaging rules stripping the provenance file during install; running the check from the wrong working directory so the resolved path points at an empty skill.","solutions":["Generate/restore the provenance metadata file for the skill (use the library's provenance tooling or writeProvenance with a valid record).","If provenance is genuinely optional for this skill, call readProvenance(dir) without required: true and handle the null return.","Verify skillPath resolves to the intended skill directory; fix the path if it points elsewhere.","Ensure the provenance file is included in version control/packaging so installs do not drop it."],"exampleFix":"// before\nconst record = readProvenance(skillDir, { required: true }); // throws if missing\n\n// after\nconst record = readProvenance(skillDir) ?? writeProvenance(skillDir, buildProvenance(skillDir));","handlingStrategy":"try-catch","validationCode":"const provenancePath = getProvenancePath(normalizeSkillDir(dir));\nif (required && !fs.existsSync(provenancePath)) {\n  throw new Error(`Run provenance init for ${dir} first`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  const record = readProvenance(skillDir, { required: true });\n} catch (err) {\n  if (err.message.startsWith('Missing provenance metadata')) {\n    const record = createProvenanceFor(skillDir);\n    writeProvenance(skillDir, record);\n  } else throw err;\n}","preventionTips":["Initialize provenance metadata whenever a skill is added, vendored, or copied.","Ensure provenance files are committed and included in packaging (not gitignored).","Prefer the optional call (returns null) when your workflow tolerates missing metadata, and branch on null explicitly."],"tags":["provenance","missing-metadata","file-not-found"],"backgroundTag":"file-not-found","analyzedSha":"8321021c54d670126ce3b2969d5deb880b4b0c2a","analyzedAt":"2026-09-16T10:08:13.343Z","contentChangedAt":"2026-09-16T10:08:13.343Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}