{"record":{"id":"eb01edc734d40f23","repo":"affaan-m/ECC","slug":"provenance-metadata-is-only-required-for-learned-o","errorCode":null,"errorMessage":"Provenance metadata is only required for learned or imported skills: ${skillDir}","messagePattern":"Provenance metadata is only required for learned or imported skills: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"scripts/lib/skill-evolution/provenance.js","lineNumber":162,"sourceCode":"\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);\n\n  const provenancePath = getProvenancePath(skillDir);\n  ensureDir(skillDir);\n  fs.writeFileSync(provenancePath, `${JSON.stringify(record, null, 2)}\\n`, 'utf8');\n\n  return {\n    path: provenancePath,\n    record: { ...record },\n  };\n}\n\nmodule.exports = {\n  PROVENANCE_FILE_NAME,\n  SKILL_TYPES,\n  classifySkillPath,","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/scripts/lib/skill-evolution/provenance.js#L144-L180","documentation":"Thrown by writeProvenance when requiresProvenance(skillDir, options) returns false — i.e. the path classifies as curated (under the repo's skills/) or unknown (outside all known roots). The module intentionally refuses to write provenance metadata where it is not required, to keep curated skills clean.","triggerScenarios":"writeProvenance('/repo/skills/foo', record) (curated path); writeProvenance('/tmp/random', record) (unknown path); a learned skill whose path is misclassified as curated because repoRoot/homeDir options point at the wrong place.","commonSituations":"Trying to attach provenance to a curated ECC skill; wrong repoRoot so a learned path resolves under the repo skills/ tree; CI running with a different HOME so ~/.claude/skills/learned maps elsewhere.","solutions":["Only call writeProvenance on learned or imported skill directories (under ~/.claude/skills/learned or /imported).","Pre-check with requiresProvenance(dir, options) before writing.","Verify repoRoot and homeDir options resolve to the real repo/home so classifySkillPath returns the expected type."],"exampleFix":"// before\nwriteProvenance(path.join(repoRoot, 'skills', 'foo'), record);\n// throws: Provenance metadata is only required for learned or imported skills\n\n// after\nif (requiresProvenance(dir)) {\n  writeProvenance(dir, record);\n}","handlingStrategy":"validation","validationCode":"const { requiresProvenance } = require('./provenance');\nfunction safeWriteProvenance(dir, record, options = {}) {\n  if (!requiresProvenance(dir, options)) {\n    return null; // not required here, skip gracefully\n  }\n  return writeProvenance(dir, record, options);\n}","typeGuard":"function shouldWriteProvenance(dir, options = {}) {\n  return requiresProvenance(dir, options);\n}","tryCatchPattern":"try {\n  writeProvenance(dir, record);\n} catch (err) {\n  if (/only required for learned or imported/.test(err.message)) return null;\n  throw err;\n}","preventionTips":["Pre-check requiresProvenance() before writeProvenance().","Verify repoRoot and homeDir options point at the real locations so classification is correct in CI.","Reserve provenance for learned/imported skills; leave curated skills unattributed."],"tags":["provenance","write-guard","skill-classification"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}