{"record":{"id":"75bbc659f7052a54","repo":"stablyai/orca","slug":"resolved-values-differ-for-baseref-n-serial","errorCode":null,"errorMessage":"resolved values differ for ${baseRef}:\\n  serial     ${JSON.stringify(serial)}\\n  concurrent ${JSON.stringify(concurrent)}","messagePattern":"resolved values differ for (.+?):\\\\n  serial     (.+?)\\\\n  concurrent (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"config/scripts/branch-compare-head-benchmark.mjs","lineNumber":175,"sourceCode":"console.log('getBranchCompare head-of-chain reads, per call. Lower is better.')\nconsole.log(`iterations=${ITERATIONS} warmup=${WARMUP} rounds=${ROUNDS} (per-arm medians)`)\nconsole.log(\n  `${pad('base ref', 30)} ${pad('serial', 11)} ${pad('concurrent', 11)} ${pad('speedup', 9)}`\n)\n\n// A short remote label is the common case (Orca's base picker emits `origin/main`); the\n// already-qualified ref skips the probe entirely, so only the concurrency half applies.\nconst upstream = await git(['rev-parse', '--abbrev-ref', 'HEAD@{upstream}']).catch(() => null)\nconst baseRefs = ['origin/main', 'refs/remotes/origin/main', 'main']\nif (upstream && !baseRefs.includes(upstream)) {\n  baseRefs.push(upstream)\n}\n\nfor (const baseRef of baseRefs) {\n  const serial = await readSerial(baseRef)\n  const concurrent = await readConcurrent(baseRef)\n  if (JSON.stringify(serial) !== JSON.stringify(concurrent)) {\n    throw new Error(\n      `resolved values differ for ${baseRef}:\\n  serial     ${JSON.stringify(serial)}\\n  concurrent ${JSON.stringify(concurrent)}`\n    )\n  }\n  if (!serial.headOid) {\n    throw new Error(`fixture resolved no HEAD oid for ${baseRef}`)\n  }\n  const { serialMs, concurrentMs } = await measure(baseRef)\n  console.log(\n    `${pad(baseRef, 30)} ${pad(`${serialMs.toFixed(1)} ms`, 11)} ${pad(`${concurrentMs.toFixed(1)} ms`, 11)} ${pad(`${(serialMs / concurrentMs).toFixed(2)}x`, 9)}`\n  )\n}\n\nconsole.log(\n  '\\nThe already-qualified refs/... row skips the probe by design, so it only shows the\\nconcurrency half. This times the native/WSL head-of-chain reads, not the whole compare;\\nthe relay path has separate production-concurrency coverage.'\n)\n","sourceCodeStart":157,"sourceCodeEnd":191,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/config/scripts/branch-compare-head-benchmark.mjs#L157-L191","documentation":"Thrown by the branch-compare-head benchmark as a correctness guard: for each baseRef it runs readSerial (the pre-fix serial chain) and readConcurrent (the production concurrent reader readBranchCompareHead) and JSON.stringifies both. A mismatch means the production concurrent path resolves a different compareRef/resolvedBaseRef/headOid/baseOid than the serial reference, i.e. the optimization changed semantics — a real bug, not a benchmark maintenance issue.","triggerScenarios":"readBranchCompareHead in src/shared/git-branch-compare-head.ts was edited and now resolves refs differently; the probe-oid reuse optimization (reusableProbedOidByRef) returns the wrong oid for a refs/heads/* ref; the candidate-ordering in resolveBaseRef changed; an annotated-tag handling rule diverged between the two arms.","commonSituations":"A speed optimization to the head-of-chain reads changed which candidate wins; the serial path was updated but the concurrent path was not (or vice versa); remote-tracking refs that store annotated tags now resolve to a tag oid in one arm but a commit oid in the other.","solutions":["Inspect the printed JSON for both arms — the differing field (usually resolvedBaseRef or baseOid) identifies the bug location.","Diff readBranchCompareHead in src/shared/git-branch-compare-head.ts against the serial reference in the benchmark and reconcile the resolution rule.","For annotated-tag refs/remotes/* refs, confirm both arms dereference to the commit oid (^{commit}) consistently.","Add a unit test in the production test suite capturing this baseRef so the divergence cannot recur silently."],"exampleFix":"// before — concurrent arm reuses probe oid for refs/remotes/* (unsafe for annotated tags)\n// -> 'resolved values differ for origin/main:\\n  serial     {...}\\n  concurrent {...}'\n\n// after — only reuse probe oids for refs/heads/* (the optimization's invariant)\n// if (candidate.startsWith('refs/heads/')) {\n//   reusableProbedOidByRef.set(candidate, oid)\n// }","handlingStrategy":"validation","validationCode":"function assertArmsAgree(baseRef, serial, concurrent) {\n  if (JSON.stringify(serial) !== JSON.stringify(concurrent)) {\n    throw new Error(`Serial vs concurrent divergence on ${baseRef} — production readBranchCompareHead changed semantics.\\n  serial     ${JSON.stringify(serial)}\\n  concurrent ${JSON.stringify(concurrent)}`)\n  }\n}\n// call after both arms resolve, before timing","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When editing readBranchCompareHead, run this benchmark before merging — it will catch a semantic regression.","Keep the benchmark's readSerial as a deliberate reference; do not 'optimize' it to match the concurrent arm.","Add a unit test in src/shared/git-branch-compare-head.test.ts covering each baseRef shape so divergences surface in CI without the benchmark."],"tags":["benchmark","correctness-guard","git","branch-compare","regression"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}