{"record":{"id":"03cf5014e388b118","repo":"Egonex-AI/Understand-Anything","slug":"symbol-baseline-does-not-match-the-incremental-pla","errorCode":null,"errorMessage":"Symbol baseline does not match the incremental plan","messagePattern":"Symbol baseline does not match the incremental plan","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"understand-anything-plugin/skills/understand/validate-incremental-symbols.mjs","lineNumber":296,"sourceCode":"    afterCount: current.nodes.length,\n    beforeSymbolCount: oldSymbols.length,\n    afterSymbolCount: newSymbols.length,\n    missing,\n    replacements,\n  };\n}\n\nexport function git(root, args) {\n  const result = spawnSync('git', args, { cwd: root, encoding: 'utf8', maxBuffer: 256 * 1024 * 1024 });\n  if (result.status !== 0) throw new Error(`git ${args[0]} failed: ${result.stderr || result.error || result.status}`);\n  return result.stdout;\n}\n\nexport function loadSymbolContext(projectRoot, intermediateDir) {\n  const plan = readJson(join(intermediateDir, 'incremental-plan.json'));\n  const baseline = readJson(join(intermediateDir, 'incremental-symbol-baseline.json'));\n  if (baseline.version !== 1 || baseline.baseCommit !== plan.baseCommit || baseline.headCommit !== plan.headCommit\n    || !Array.isArray(baseline.files)) throw new Error('Symbol baseline does not match the incremental plan');\n  const paths = baseline.files.map(file => file.filePath).sort();\n  if (JSON.stringify(paths) !== JSON.stringify([...plan.filesToReanalyze].sort())\n    || paths.some(path => !normalizePath(path) || (plan.deletedFiles ?? []).includes(path))\n    || new Set(paths).size !== paths.length) {\n    throw new Error('Symbol baseline file inventory does not match the incremental plan');\n  }\n  if (git(projectRoot, ['rev-parse', 'HEAD']).trim() !== plan.headCommit) {\n    throw new Error('HEAD changed since prepare; baseline not advanced');\n  }\n  // Check every analyzer input, even if all IDs survive and parsing is skipped.\n  // Git compares normalized contents, including repository clean/EOL rules.\n  if (paths.length) git(projectRoot, [\n    'diff', '--quiet', '--no-ext-diff', plan.headCommit, '--', ...paths.map(path => `:(literal)${path}`),\n  ]);\n  return { plan, baseline };\n}\n\nexport async function validateIncrementalSymbols(projectRoot, { graph, intermediateDir } = {}) {","sourceCodeStart":278,"sourceCodeEnd":314,"githubUrl":"https://github.com/Egonex-AI/Understand-Anything/blob/07edf82a04371b6f69779b067bdc8a1a8753a9db/understand-anything-plugin/skills/understand/validate-incremental-symbols.mjs#L278-L314","documentation":"`loadSymbolContext` loads `incremental-plan.json` and `incremental-symbol-baseline.json` from the intermediate directory and verifies they describe the same incremental run: baseline schema version 1, matching baseCommit/headCommit, and a files array. If any check fails it throws this error, because validating symbols against a baseline from a different plan would produce incorrect results.","triggerScenarios":"Calling `loadSymbolContext(projectRoot, intermediateDir)` when the baseline's `version` is not 1, its `baseCommit`/`headCommit` differ from the plan's, or `baseline.files` is not an array — typically stale or hand-edited intermediate files.","commonSituations":"A previous incremental run was interrupted halfway (plan written, baseline not); a newer tool version wrote an incompatible baseline; the intermediate directory mixes artifacts from two branches; files were edited manually or partially copied.","solutions":["Delete the stale intermediate artifacts (`incremental-plan.json`, `incremental-symbol-baseline.json`) and re-run the prepare step to regenerate them together.","Confirm both files come from the same run: their `baseCommit` and `headCommit` fields must be identical.","Check the tool version that produced the baseline — regenerate it if your validator expects version 1.","Ensure the whole `intermediate/` directory is cleaned between runs on different branches."],"exampleFix":"// before: stale mixed artifacts\nintermediate/incremental-plan.json           { \"baseCommit\": \"aaa\", \"headCommit\": \"bbb\" }\nintermediate/incremental-symbol-baseline.json { \"baseCommit\": \"xxx\", \"headCommit\": \"yyy\" }\n\n// after: regenerate both from one prepare run\nrm .ua/intermediate/incremental-plan.json .ua/intermediate/incremental-symbol-baseline.json\n# re-run /understand prepare so both files are written from the same plan","handlingStrategy":"validation","validationCode":"const plan = JSON.parse(readFileSync(join(dir,'incremental-plan.json'),'utf8'));\nconst baseline = JSON.parse(readFileSync(join(dir,'incremental-symbol-baseline.json'),'utf8'));\nconst compatible = baseline.version === 1 && baseline.baseCommit === plan.baseCommit\n  && baseline.headCommit === plan.headCommit && Array.isArray(baseline.files);\nif (!compatible) regeneratePlanAndBaseline();","typeGuard":"function isCompatibleBaseline(plan, baseline) {\n  return typeof baseline === 'object' && baseline !== null\n    && baseline.version === 1\n    && baseline.baseCommit === plan.baseCommit\n    && baseline.headCommit === plan.headCommit\n    && Array.isArray(baseline.files);\n}","tryCatchPattern":"try {\n  await validateIncrementalSymbols({ projectRoot, intermediateDir });\n} catch (err) {\n  if (err.message === 'Symbol baseline does not match the incremental plan') {\n    await rerunPrepareStep(); // regenerate both artifacts together\n  } else throw err;\n}","preventionTips":["Never edit incremental-plan.json or the baseline by hand.","Regenerate plan and baseline in the same prepare run; clean intermediate/ between runs.","Pin the validator and artifact-writer to the same schema version.","Don't reuse intermediate artifacts across branches."],"tags":["state-mismatch","incremental-analysis","json"],"backgroundTag":"schema-validation-failed","analyzedSha":"07edf82a04371b6f69779b067bdc8a1a8753a9db","analyzedAt":"2026-09-07T23:20:10.829Z","contentChangedAt":"2026-09-07T23:20:10.829Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}