{"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":"Error","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/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/skill-evolution/provenance.js#L144-L180","documentation":"writeProvenance() in the skill-evolution library persists a provenance metadata record next to a skill directory. Before writing, it checks requiresProvenance(); if the skill is not classified as learned or imported (e.g. it is a built-in/manual skill), provenance is considered meaningless and the function refuses with this error. This is an unsupported-operation guard: provenance tracking only applies to skills whose origin came from learning or import.","triggerScenarios":"Calling writeProvenance(skillPath, record) where the resolved skillDir maps to a skill whose type/origin (per requiresProvenance) is not 'learned' or 'imported' — e.g. a stock/bundled skill — and no options override that classification.","commonSituations":"Automating skill bookkeeping across a whole skills/ directory and accidentally running provenance writes for built-in skills; calling the API after refactoring skill metadata so the type field no longer reads 'learned'/'imported'; copy-pasting a provenance-writing script from an import workflow onto a manually authored skill.","solutions":["Only call writeProvenance for skills classified as learned or imported; check requiresProvenance(skillDir, options) first.","Pass options that correctly mark the skill as learned/imported if it genuinely is one (e.g. the origin/type option the function reads).","Fix the skill's metadata (type/origin fields) if it was misclassified as a non-learned skill.","Skip provenance writing for built-in/manual skills in your automation script instead of forcing it."],"exampleFix":"// before\nawait writeProvenance('/skills/built-in/linting', record);\n\n// after\nif (requiresProvenance(normalizeSkillDir('/skills/built-in/linting'), { origin: 'learned' })) {\n  await writeProvenance('/skills/built-in/linting', record, { origin: 'learned' });\n}","handlingStrategy":"validation","validationCode":"import { requiresProvenance, normalizeSkillDir } from './scripts/lib/skill-evolution/provenance.js';\n\nfunction canWriteProvenance(skillPath, options = {}) {\n  const skillDir = normalizeSkillDir(skillPath);\n  return requiresProvenance(skillDir, options);\n}\n\nif (!canWriteProvenance(skillPath, options)) {\n  throw new Error(`skip provenance write: ${skillPath} is not a learned/imported skill`);\n}","typeGuard":"function isProvenanceEligible(skill) {\n  return skill != null && (skill.type === 'learned' || skill.type === 'imported');\n}","tryCatchPattern":"try {\n  await writeProvenance(skillPath, record, options);\n} catch (err) {\n  if (err.message.startsWith('Provenance metadata is only required')) {\n    console.warn(`Skipping provenance for non-learned skill: ${skillPath}`);\n    return; // treat as no-op for built-in/manual skills\n  }\n  throw err;\n}","preventionTips":["Filter your skill list to learned/imported skills before any provenance write loop.","Keep skill type/origin metadata consistent so requiresProvenance classifies correctly.","Wrap provenance writes in a skip-and-log helper for ineligible skills."],"tags":["skill-evolution","provenance","unsupported-operation"],"backgroundTag":"unsupported-operation","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"}