Context
Found during Titan-run grind phase 22 (/titan-grind --phase 22) while running the mandatory Step 2c codebase-wide duplicate scan on the newly-extracted computeCpmEdgeWeights[Directed/Undirected] helpers in src/graph/algorithms/leiden/partition.ts (commit 21db9a9). The scan surfaced that computeCpmEdgeWeights* duplicates the exact same directed/undirected branch-splitting formula as the pre-existing diffCPM in src/graph/algorithms/leiden/cpm.ts — which led to tracing who actually calls each path.
Finding
src/graph/algorithms/leiden/optimiser.ts:computeQualityGain (the only caller of CPM/modularity delta computation in the Leiden hot loop) calls the standalone module-level functions directly:
if (quality === 'cpm') {
return diffCPM(partition, partition.graph, v, c, gamma);
}
return diffModularity(partition, partition.graph, v, c, gamma);
It never calls partition.deltaCPM(...), partition.deltaModularityDirected(...), or partition.deltaModularityUndirected(...) — the Partition interface methods backed by computeDeltaCPM, computeDeltaModularityDirected, computeDeltaModularityUndirected in partition.ts.
Verified via repo-wide grep (not just codegraph) that these three interface methods, plus getCandidateCommunityCount, have zero callers anywhere in src/, tests/, or scripts:
$ grep -rn "\.deltaCPM(\|\.deltaModularityDirected(\|\.deltaModularityUndirected(\|\.getCandidateCommunityCount(" src/ tests/ --include="*.ts" | grep -v "partition.ts:"
(no output)
Every other Partition interface method (moveNodeToCommunity, compactCommunityIds, getCommunityMembers, getCommunityTotalSize, getCommunityNodeCount, getCandidateCommunityAt, getNeighborEdgeWeightToCommunity, getOutEdgeWeightToCommunity, getInEdgeWeightFromCommunity, accumulateNeighborCommunityEdgeWeights, resizeCommunities, initializeAggregates) has 1+ external callers — only these four are orphaned.
makePartition/Partition are not exported from the package's public API (src/index.ts), so this isn't unused-by-design public surface — it's purely internal dead code.
Why codegraph's own dead-code detector misses this
codegraph roles --role dead -T --file src/graph/algorithms/leiden/partition.ts --json does not flag computeDeltaCPM, computeDeltaModularityDirected, computeDeltaModularityUndirected, or the backing arrow functions as dead — because each is referenced as a value inside the object literal returned by the exported makePartition() factory (e.g. deltaCPM: (v, newC, gamma) => computeDeltaCPM(s, v, newC, gamma)). The detector treats "referenced as a property value in a returned object" as sufficient evidence of liveness, without tracing whether the resulting object's property is ever actually invoked by a consumer (partition.deltaCPM(...)). This is a distinct blind spot from #1723 (interface/type declarations) and #1769 (missed call-edge attribution to real callers) — here the bug runs the other direction: a false negative, undercounting dead code through object-literal-property indirection.
Impact
~80 lines of module code (computeDeltaCPM, computeDeltaModularityDirected, computeDeltaModularityUndirected, plus the phase-22-extracted computeCpmEdgeWeights/computeCpmEdgeWeightsDirected/computeCpmEdgeWeightsUndirected sub-helpers) exist purely to back four Partition interface methods that no code path invokes. computeDeltaCPM's logic is also a near-duplicate of cpm.ts's actively-used diffCPM (same directed/undirected formula, different data-access layer: raw PartitionState typed arrays vs. PartitionView getter interface).
Not fixed here because
- Predates phase 22 —
computeDeltaCPM/computeDeltaModularityDirected/computeDeltaModularityUndirected existed before this phase; phase 22 only decomposed their internals (behavior-preserving), it didn't introduce the unreachability.
- Two possible fixes with different risk profiles need dedicated investigation, not a drive-by:
- Remove the four dead
Partition interface methods + their backing implementations (verify nothing external/future depends on the interface shape).
- Wire
computeQualityGain to call partition.deltaCPM/partition.deltaModularityDirected/partition.deltaModularityUndirected instead of the standalone diffCPM/diffModularity functions, deduplicating the two parallel implementations — but this changes which code path executes in the Leiden optimization hot loop and needs careful behavioral-equivalence verification first (out of scope for a pure-adoption grind pass, which must not change control flow).
- Filed per project scope-discipline rule rather than silently left undocumented.
Context
Found during Titan-run grind phase 22 (
/titan-grind --phase 22) while running the mandatory Step 2c codebase-wide duplicate scan on the newly-extractedcomputeCpmEdgeWeights[Directed/Undirected]helpers insrc/graph/algorithms/leiden/partition.ts(commit 21db9a9). The scan surfaced thatcomputeCpmEdgeWeights*duplicates the exact same directed/undirected branch-splitting formula as the pre-existingdiffCPMinsrc/graph/algorithms/leiden/cpm.ts— which led to tracing who actually calls each path.Finding
src/graph/algorithms/leiden/optimiser.ts:computeQualityGain(the only caller of CPM/modularity delta computation in the Leiden hot loop) calls the standalone module-level functions directly:It never calls
partition.deltaCPM(...),partition.deltaModularityDirected(...), orpartition.deltaModularityUndirected(...)— thePartitioninterface methods backed bycomputeDeltaCPM,computeDeltaModularityDirected,computeDeltaModularityUndirectedinpartition.ts.Verified via repo-wide grep (not just codegraph) that these three interface methods, plus
getCandidateCommunityCount, have zero callers anywhere insrc/,tests/, or scripts:Every other
Partitioninterface method (moveNodeToCommunity,compactCommunityIds,getCommunityMembers,getCommunityTotalSize,getCommunityNodeCount,getCandidateCommunityAt,getNeighborEdgeWeightToCommunity,getOutEdgeWeightToCommunity,getInEdgeWeightFromCommunity,accumulateNeighborCommunityEdgeWeights,resizeCommunities,initializeAggregates) has 1+ external callers — only these four are orphaned.makePartition/Partitionare not exported from the package's public API (src/index.ts), so this isn't unused-by-design public surface — it's purely internal dead code.Why codegraph's own dead-code detector misses this
codegraph roles --role dead -T --file src/graph/algorithms/leiden/partition.ts --jsondoes not flagcomputeDeltaCPM,computeDeltaModularityDirected,computeDeltaModularityUndirected, or the backing arrow functions as dead — because each is referenced as a value inside the object literal returned by the exportedmakePartition()factory (e.g.deltaCPM: (v, newC, gamma) => computeDeltaCPM(s, v, newC, gamma)). The detector treats "referenced as a property value in a returned object" as sufficient evidence of liveness, without tracing whether the resulting object's property is ever actually invoked by a consumer (partition.deltaCPM(...)). This is a distinct blind spot from #1723 (interface/type declarations) and #1769 (missed call-edge attribution to real callers) — here the bug runs the other direction: a false negative, undercounting dead code through object-literal-property indirection.Impact
~80 lines of module code (
computeDeltaCPM,computeDeltaModularityDirected,computeDeltaModularityUndirected, plus the phase-22-extractedcomputeCpmEdgeWeights/computeCpmEdgeWeightsDirected/computeCpmEdgeWeightsUndirectedsub-helpers) exist purely to back four Partition interface methods that no code path invokes.computeDeltaCPM's logic is also a near-duplicate ofcpm.ts's actively-useddiffCPM(same directed/undirected formula, different data-access layer: rawPartitionStatetyped arrays vs.PartitionViewgetter interface).Not fixed here because
computeDeltaCPM/computeDeltaModularityDirected/computeDeltaModularityUndirectedexisted before this phase; phase 22 only decomposed their internals (behavior-preserving), it didn't introduce the unreachability.Partitioninterface methods + their backing implementations (verify nothing external/future depends on the interface shape).computeQualityGainto callpartition.deltaCPM/partition.deltaModularityDirected/partition.deltaModularityUndirectedinstead of the standalonediffCPM/diffModularityfunctions, deduplicating the two parallel implementations — but this changes which code path executes in the Leiden optimization hot loop and needs careful behavioral-equivalence verification first (out of scope for a pure-adoption grind pass, which must not change control flow).