{"record":{"id":"2dc03053e6a0dca5","repo":"affaan-m/ECC","slug":"retrospective-invalid-capsule","errorCode":"retrospective.invalid_capsule","errorMessage":"capsule at input index ${index} failed verification","messagePattern":"capsule at input index (.+?) failed verification","errorType":"error_code","errorClass":"RetrospectiveError","httpStatus":null,"severity":"error","filePath":"scripts/lib/eval-harness/retrospective.js","lineNumber":29,"sourceCode":"const MAX_INPUTS = 100;\nconst SOURCE_FIELDS = ['entry_count', 'root_hash', 'journal_sha256', 'projection_hash'];\n\nclass RetrospectiveError extends Error {\n  constructor(code, message, inputIndex) {\n    super(message);\n    this.name = 'RetrospectiveError';\n    this.code = code;\n    if (inputIndex !== undefined) this.input_index = inputIndex;\n  }\n}\n\nfunction readProjection(dir, index) {\n  try {\n    return capsule.project(dir);\n  } catch {\n    // Reader errors can contain private paths or journal content. No partial\n    // report or unchecked diagnostic content crosses the report boundary.\n    throw new RetrospectiveError('retrospective.invalid_capsule', `capsule at input index ${index} failed verification`, index);\n  }\n}\n\nconst compare = (a, b) => a < b ? -1 : a > b ? 1 : 0;\nconst identity = projection => JSON.stringify([projection.run_id, projection.capsule_id]);\n\nfunction summarizeGroup(harnessVersion, projections) {\n  const total = keys => Object.fromEntries(keys.map(key => [key, 0]));\n  const byLineage = total(LINEAGES);\n  const byEffect = total(EFFECT_CLASSES);\n  for (const projection of projections) {\n    for (const key of LINEAGES) byLineage[key] += projection.by_lineage[key];\n    for (const key of EFFECT_CLASSES) byEffect[key] += projection.by_effect_class[key];\n  }\n  return {\n    harness_version: harnessVersion,\n    capsule_count: projections.length,\n    entry_count: projections.reduce((sum, item) => sum + item.entry_count, 0),","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/affaan-m/ECC/blob/8321021c54d670126ce3b2969d5deb880b4b0c2a/scripts/lib/eval-harness/retrospective.js#L11-L47","documentation":"readProjection verifies each capsule directory before including it in a retrospective report. When capsule.project(dir) fails — meaning the capsule's journal fails integrity, digest, or structural verification — the error is replaced by a sanitized RetrospectiveError carrying only the input index. Raw reader errors are deliberately swallowed because they can contain private paths or journal content that must not cross the report boundary.","triggerScenarios":"Passing a directory to groupCapsules that is not a valid capsule (missing journal, corrupted hash chain, tampered artifacts, or a non-capsule path). The failing input is identified by its zero-based index in the dirs array.","commonSituations":"Pointing the tool at an ordinary project directory instead of a capsule snapshot; a capsule truncated by an interrupted copy or sync; editing capsule files by hand so link digests no longer verify; version drift where the capsule format differs from what this harness version projects.","solutions":["Regenerate the failing capsule snapshot and re-run the retrospective","Verify the directory is a complete capsule produced by this harness version (check journal and digests)","Re-copy the capsule directory in full if it was truncated during transfer","Confirm you passed the directory itself, not a parent or a file path"],"exampleFix":"// before\nnode scripts/eval-harness.js capsule group ./random-dir ./capsule-b\n// after (regenerate the invalid capsule first)\nnode scripts/eval-harness.js capsule group ./.claude/capsules/run-123 ./capsule-b","handlingStrategy":"try-catch","validationCode":"// pre-check: capsule dir contains a journal before grouping\nif (!fs.existsSync(path.join(dir, 'journal.jsonl'))) throw new Error(`${dir} is not a capsule`);","typeGuard":"const looksLikeCapsule = (dir) => typeof dir === 'string' && fs.existsSync(dir) && fs.statSync(dir).isDirectory() && fs.existsSync(path.join(dir, 'journal.jsonl'));","tryCatchPattern":"try { report = groupCapsules(dirs); } catch (e) { if (e.code === 'retrospective.invalid_capsule') console.error(`capsule #${e.index} failed verification — regenerate it`); throw e; }","preventionTips":["Never hand-edit capsule files; regenerate snapshots instead","Copy capsule directories completely (verify file counts/digests after transfer)","Pin the harness version used to produce and to read capsules","Only pass directories produced by eval-harness capsule recording to groupCapsules"],"tags":["capsule","verification","retrospective"],"backgroundTag":"checksum-mismatch","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"}