{"record":{"id":"870db6f7ba6cf27a","repo":"affaan-m/ECC","slug":"capsule-bad-lineage","errorCode":"capsule.bad_lineage","errorMessage":"unknown lineage ${lineage}","messagePattern":"unknown lineage (.+?)","errorType":"error_code","errorClass":"CapsuleError","httpStatus":null,"severity":"error","filePath":"scripts/lib/eval-harness/capsule.js","lineNumber":183,"sourceCode":"    const capsule = new Capsule(resolved, state.meta, options);\n    if (state.entries.length > 0) {\n      const last = state.entries[state.entries.length - 1];\n      capsule.lastHash = last.entry_hash;\n      capsule.nextSeq = last.seq + 1;\n    }\n    return capsule;\n  }\n\n  /**\n   * Serialize cooperating appenders and validate current disk state under lock.\n   * A partial I/O failure is preserved for diagnosis, never silently rolled back.\n   */\n  append(lineage, kind, payload = {}, options = {}) {\n    return withAppendLock(this.dir, () => {\n      const state = readCapsule(this.dir);\n      if (!state.ok) throw new CapsuleError(state.code, state.reason, { failed_at: state.failed_at });\n      if (!envelope.LINEAGES.includes(lineage)) {\n        throw new CapsuleError('capsule.bad_lineage', `unknown lineage ${lineage}`);\n      }\n      const effectClass = options.effect_class || 'SE0';\n      const { payload: clean, dropped, findings, errors: payloadErrors } = envelope.redactPayload(payload, options);\n      if (payloadErrors.length > 0) {\n        throw new CapsuleError('capsule.payload_invalid', payloadErrors.join('; '));\n      }\n      if (findings.length > 0) {\n        throw new CapsuleError('capsule.secret_canary', `payload tripped secret canary ${findings[0].canary} at ${findings[0].path}`, { findings });\n      }\n      if (dropped.length > 0 && options.strict !== false) {\n        throw new CapsuleError('capsule.payload_denied', `payload keys not allowlisted: ${dropped.join(', ')}`, { dropped });\n      }\n      const body = {\n        schema: envelope.SCHEMA_VERSION,\n        run_id: state.meta.run_id,\n        capsule_id: state.meta.capsule_id,\n        seq: state.entries.length,\n        ts: nowIso(this.clock),","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/eval-harness/capsule.js#L165-L201","documentation":"append() validates its lineage argument against envelope.LINEAGES (the five documented lineages, e.g. capsule/fix/feat/task families). Any lineage string not in that allowlist is rejected with code 'capsule.bad_lineage'. Lineages are a closed enum because the projection groups entries by lineage.","triggerScenarios":"Calling append() with a misspelled lineage ('Fix', 'fixes', 'bugfix'), a dynamic/interpolated lineage value, or a lineage from an older/newer schema version that this library build does not recognize.","commonSituations":"Typo in the lineage name; wrapping lineage in a variable whose value came from CLI args or config; refactoring that renamed a lineage without updating all append() call sites.","solutions":["Check the exact spelling of the lineage argument against the values in envelope.LINEAGES (import or log them).","Use one of the documented lineages verbatim (lowercase, exact string).","If a genuinely new lineage is needed, add it to LINEAGES in the envelope module and update projection consumers — do not pass arbitrary strings.","Guard call sites that compute lineage dynamically with a check against LINEAGES before calling append()."],"exampleFix":"// before\nawait capsule.append('Fix', 'note', { msg }); // throws capsule.bad_lineage\n\n// after\nif (!envelope.LINEAGES.includes('fix')) throw new Error('unsupported lineage');\nawait capsule.append('fix', 'note', { msg });","handlingStrategy":"validation","validationCode":"import { LINEAGES } from './envelope.js';\nif (!LINEAGES.includes(lineage)) throw new Error(`lineage must be one of: ${LINEAGES.join(', ')}`);","typeGuard":"function isValidLineage(lineage) {\n  return typeof lineage === 'string' && envelope.LINEAGES.includes(lineage);\n}","tryCatchPattern":"try {\n  await capsule.append(lineage, kind, payload);\n} catch (e) {\n  if (e instanceof CapsuleError && e.code === 'capsule.bad_lineage') {\n    throw new Error(`${e.message}; valid lineages: ${envelope.LINEAGES.join(', ')}`);\n  }\n  throw e;\n}","preventionTips":["Import lineage names from envelope.LINEAGES instead of inlining strings.","Wrap append() in a small helper that validates lineage once.","Add a unit test per call site asserting the lineage constant is in LINEAGES.","Never derive lineage from raw user/CLI input without allowlist checking."],"tags":["argument-validation","enum"],"backgroundTag":"invalid-enum-value","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"}