{"record":{"id":"4f25f18506e3a106","repo":"Egonex-AI/Understand-Anything","slug":"current-edge-candidates-do-not-match-the-increment-4f25f1","errorCode":null,"errorMessage":"Current edge candidates do not match the incremental plan","messagePattern":"Current edge candidates do not match the incremental plan","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"understand-anything-plugin/skills/understand/validate-incremental-symbols.mjs","lineNumber":382,"sourceCode":"        } catch (error) {\n          baseEvidence = { status: 'failed' };\n          headEvidence = { status: 'failed' };\n          report.errors.push(`${previous.filePath}: ${error.message}`);\n        }\n      }\n      const result = compareFileSymbols(previous, current, baseEvidence, headEvidence);\n      report.files.push(result);\n      if (result.missing.some(node => node.status !== 'deleted')) report.unresolvedFiles.push(previous.filePath);\n    }\n    report.ok = report.errors.length === 0 && report.unresolvedFiles.length === 0;\n    if (report.ok) {\n      const retryPath = join(intermediateDir, 'incremental-symbol-retry.json');\n      const retry = existsSync(retryPath) ? readJson(retryPath) : null;\n      const candidatePath = join(intermediateDir, 'incremental-edge-candidates.json');\n      const currentCandidates = existsSync(candidatePath) ? readJson(candidatePath) : null;\n      if (currentCandidates && (currentCandidates.baseCommit !== plan.baseCommit\n        || currentCandidates.headCommit !== plan.headCommit || !Array.isArray(currentCandidates.edges))) {\n        throw new Error('Current edge candidates do not match the incremental plan');\n      }\n      const hasRetry = retry?.baseCommit === plan.baseCommit && retry.headCommit === plan.headCommit\n        && Array.isArray(retry.inboundEdgeCandidates);\n      if (hasRetry && !Array.isArray(retry.currentFiles)) throw new Error('Retry endpoint descriptors are missing');\n      const candidates = [\n        ...(currentCandidates?.edges ?? []).map(edge => ({ edge, saved: false })),\n        ...(hasRetry ? retry.inboundEdgeCandidates : []).map(edge => ({ edge, saved: true })),\n      ];\n      if (candidates.length || hasRetry) {\n        const ids = new Set(graph.nodes.map(node => node.id));\n        const replacements = new Map(report.files.flatMap(file => file.replacements)\n          .map(({ oldId, newId }) => [oldId, newId]));\n        const deleted = new Set(report.files.flatMap(file => file.missing.map(node => node.id)));\n        const baselineBindings = new Map(baseline.files.flatMap(file => file.nodes.filter(symbolKind))\n          .map(node => [node.id, deleted.has(node.id) ? null : replacements.get(node.id) ?? node.id]));\n        const currentBindings = new Map();\n        // These descriptors belong to the initial CURRENT analysis, not the\n        // old published graph. Both sides therefore map against HEAD source.","sourceCodeStart":364,"sourceCodeEnd":400,"githubUrl":"https://github.com/Egonex-AI/Understand-Anything/blob/07edf82a04371b6f69779b067bdc8a1a8753a9db/understand-anything-plugin/skills/understand/validate-incremental-symbols.mjs#L364-L400","documentation":"During validation, `validateIncrementalSymbols` reads the optional `incremental-edge-candidates.json` and requires it to match the current plan: identical `baseCommit`, identical `headCommit`, and an `edges` array. A candidates file recorded for a different commit range is stale, so it throws rather than mixing edge candidates across runs.","triggerScenarios":"Calling `validateIncrementalSymbols` when a leftover `incremental-edge-candidates.json` was written by a run with a different baseCommit/headCommit than `incremental-plan.json`, or when the file exists but its `edges` field is not an array.","commonSituations":"Re-running validation after new commits without regenerating edge candidates; rebase amended the head commit so the recorded headCommit no longer matches; a partially written candidates file lost its edges array; reusing an intermediate directory across branches.","solutions":["Delete the stale `incremental-edge-candidates.json` (and retry file) and re-run the pipeline step that regenerates it for the current plan.","Confirm the candidates file's `baseCommit`/`headCommit` equal the plan's (`jq '.baseCommit,.headCommit' incremental-edge-candidates.json`).","If edges were lost, re-run edge candidate extraction so `edges` is a populated array.","Clean the whole intermediate directory when switching branches or after a rebase."],"exampleFix":"// before: stale candidates from a previous head\nincremental-plan.json:             { headCommit: \"def456\" }\nincremental-edge-candidates.json:  { headCommit: \"abc123\", edges: [...] }\n\n// after: regenerate for the current plan\nrm .ua/intermediate/incremental-edge-candidates.json .ua/intermediate/incremental-symbol-retry.json\n# re-run edge candidate extraction at headCommit def456","handlingStrategy":"validation","validationCode":"const plan = JSON.parse(readFileSync(join(dir,'incremental-plan.json'),'utf8'));\nconst cPath = join(dir,'incremental-edge-candidates.json');\nif (existsSync(cPath)) {\n  const c = JSON.parse(readFileSync(cPath,'utf8'));\n  const ok = c.baseCommit === plan.baseCommit && c.headCommit === plan.headCommit\n    && Array.isArray(c.edges);\n  if (!ok) { unlinkSync(cPath); await regenerateEdgeCandidates(); }\n}","typeGuard":"function candidatesMatchPlan(plan, c) {\n  return c != null && c.baseCommit === plan.baseCommit\n    && c.headCommit === plan.headCommit && Array.isArray(c.edges);\n}","tryCatchPattern":"try {\n  await validateIncrementalSymbols({ projectRoot, intermediateDir });\n} catch (err) {\n  if (err.message === 'Current edge candidates do not match the incremental plan') {\n    rmSync(join(intermediateDir, 'incremental-edge-candidates.json'));\n    await rerunPrepareAndEdgeExtraction();\n  } else throw err;\n}","preventionTips":["Regenerate edge candidates whenever the plan's commits change (rebase, new commits).","Clean intermediate/ when switching branches.","Compare baseCommit/headCommit of all intermediate files before validating.","Write candidates files atomically to avoid missing edges arrays."],"tags":["stale-state","incremental-analysis","graph-edges"],"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-14T00:17:10.932Z"}