Skip to content

refactor: adopt dead helpers identified by Titan grind#1793

Merged
carlos-alm merged 41 commits into
mainfrom
refactor/titan-grind-adoptions
Jul 5, 2026
Merged

refactor: adopt dead helpers identified by Titan grind#1793
carlos-alm merged 41 commits into
mainfrom
refactor/titan-grind-adoptions

Conversation

@carlos-alm

Copy link
Copy Markdown
Contributor

Summary

Adopt dead helpers identified by the Titan GRIND phase — wiring previously-extracted-but-unused helpers into real call sites, and promoting/deduping a few forge-phase helpers that turned out to have further adoption opportunities:

  • Adopt fget/iget from typed-array-helpers.ts in cpm.ts/modularity.ts (leiden).
  • Wire db.busyTimeoutMs and community.capacityGrowthFactor config constants through their real call sites (db/connection, builder pipeline, watcher, communities, leiden).
  • Adopt resolveMethodDefinitionName across 3 duplicate call sites in extractors/javascript.ts.
  • Dedupe forge phase-11 call-resolution helpers (unwrapTypeEntry, resolveSameClassQualifiedMethod) across build-edges.ts/incremental.ts.
  • Extract markExportedSymbols, dedupe a batch UPDATE in builder helpers.
  • Promote timeMedian/median/round1 into a shared scripts/lib/bench-timing.ts, deduping the same logic across 3 benchmark scripts.

Titan Audit Context

Changes

  • src/graph/algorithms/leiden/{cpm,modularity}.ts
  • src/db/connection.ts, src/domain/graph/builder/{pipeline,watcher}..., src/domain/graph/builder/stages/{native-db-lifecycle,native-orchestrator}.ts, src/features/communities.ts, src/graph/algorithms/leiden/{optimiser,partition}.ts, src/graph/algorithms/louvain.ts, src/infrastructure/config.ts, src/types.ts
  • src/extractors/javascript.ts
  • src/domain/graph/builder/{call-resolver,incremental}.ts, src/domain/graph/builder/stages/build-edges.ts, src/domain/graph/resolver/strategy.ts
  • src/domain/graph/builder/{helpers,stages/insert-nodes,stages/native-orchestrator}.ts
  • scripts/{benchmark,incremental-benchmark,query-benchmark,token-benchmark}.ts, new scripts/lib/bench-timing.ts

Metrics Impact

The Titan GRIND phase triaged 24 candidate dead-symbol targets: 6 were genuinely adoptable (this PR), 3 were promoted/deduped further (also this PR), and the remaining 15 were confirmed false positives caused by known codegraph role-classifier bugs (documented in generated/titan/ report and filed as GitHub issues).

Test plan

  • CI passes (lint + build + tests)
  • codegraph check --cycles --boundaries passes
  • No new functions above complexity thresholds

carlos-alm added 30 commits July 2, 2026 03:37
…docs check acknowledged)

Impact: 1 functions changed, 2 affected
…n algorithm files

docs check acknowledged: internal helper extraction only, no user-facing
feature/language/architecture-table changes.

Impact: 10 functions changed, 27 affected
…n readFileSafe

readFileSafe's Atomics.wait busy-block froze the entire Node.js event loop
(all I/O and timer callbacks) for up to 100ms per retry on the watch-mode
hot path. Extracts journal.ts's existing sleepSync busy-spin helper into
src/shared/sleep.ts so both readFileSafe and journal.ts's lock-retry loop
share one implementation instead of duplicating it.

docs check acknowledged: internal bug fix, no feature/language/architecture
table changes warranted in README.md, CLAUDE.md, or ROADMAP.md.

Impact: 2 functions changed, 31 affected
…complexity.ts

Impact: 14 functions changed, 10 affected
Registers resolveSecrets' execFileSync timeout/maxBuffer in
DEFAULTS.llm (apiKeyCommandTimeoutMs, apiKeyCommandMaxBufferBytes) and
wires resolveSecrets to read them from config instead of hardcoding.
Also adds three purely-additive @reserved DEFAULTS entries for
constants hardcoded elsewhere in the codebase (build.
largeCodebaseFileThreshold, db.busyTimeoutMs, community.
capacityGrowthFactor) so their consumer files can be wired to them in
follow-up commits.

docs check acknowledged — no new feature/language/architecture change;
docs/guides/configuration.md (the actual config reference) is already
updated in this commit.

Impact: 5 functions changed, 87 affected
…presentation/plot.ts

Impact: 4 functions changed, 3 affected
…l/runContextCollectorWalk

Pure extract-method decomposition of the three highest-complexity functions in
extractors/javascript.ts (Titan phase 10, sync.json commit message shortened to
fit the 100-char commitlint header limit). No extraction logic, node-type
handling, or edge-case behavior changed -- verified byte-identical
resolution-benchmark precision/recall across all 34 fixture languages and
byte-identical codegraph query/where output for 3 real non-fixture files
before/after. No Rust files touched, so native/WASM parity is unaffected by
construction.

docs check acknowledged: internal-only refactor, no new languages/commands/
architecture; README.md, CLAUDE.md, and ROADMAP.md are unaffected.

Impact: 20 functions changed, 15 affected
…ative in build-edges.ts

docs check acknowledged: pure internal extract-method refactor, no new
features, commands, languages, or architecture changes — README/CLAUDE/ROADMAP
do not need updates.

Impact: 20 functions changed, 15 affected
…or in native-orchestrator.ts

Pure extract-class decomposition of the DECOMPOSE-flagged worst offender in
Titan phase 12 (halstead.bugs 1.17). tryNativeOrchestrator's native-DB
lifecycle steps (open/build/backfill/handoff/close) are now owned by a
NativeOrchestrationSession class; tryNativeOrchestrator becomes a thin
sequencer of session method calls. No dispatch logic, fallback conditions, or
error handling changed -- verified via full test suite (200/200 files,
3330/3330 tests), byte-identical resolution-benchmark output across all 34
fixture languages, and byte-identical native-engine DB dumps (full build +
incremental early-exit) on tests/fixtures/sample-project before/after.

tryNativeOrchestrator: cognitive 35->24, cyclomatic 34->25, halstead.bugs
1.17->0.83, mi 49.7->54.1.

docs check acknowledged: pure internal extract-class refactor, no new
features, commands, languages, or architecture changes -- README/CLAUDE/
ROADMAP do not need updates.

Impact: 9 functions changed, 6 affected

Impact: 9 functions changed, 6 affected
…tor in remote.ts

Extract-method refactor only, no behavior change. embedRemote's per-batch
body is split into executeRemoteEmbeddingRequest (build request body,
fetch-with-timeout, map network/timeout/status failures to EngineError)
and mapRemoteEmbeddingResponse (shape-check, index-sort, embedding-field
check, cross-batch dimension-consistency check, Float32Array conversion),
with the outer loop calling both in the same order as before. Drops
embedRemote from cognitive=36/halstead.bugs=1.10 (DECOMPOSE-flagged worst
offender in GAUNTLET) to cognitive=6/bugs=0.38; both new helpers are well
within thresholds (cognitive 11 and 9, bugs 0.38 and 0.33).

Deliberately does not fix the gauntlet's secondary finding that
response.json() sits outside error handling (a malformed body throws a
raw SyntaxError instead of EngineError) -- that's a behavior change,
out of scope for this pure decomposition. Filed as #1745.

docs check acknowledged: internal refactor only, no CLI/feature/language/
architecture surface changed -- README/CLAUDE.md/ROADMAP untouched by design.

Impact: 3 functions changed, 10 affected
…dedupe consent glob-matching

applyExcludeTestsShorthand mutated merged.query in place, which was still
a live reference to the shared DEFAULTS.query singleton whenever no config
layer had already overridden `query`. In long-running processes (e.g.
`codegraph mcp --multi-repo`) this permanently leaked one repo's
excludeTests setting into every subsequent loadConfig() call for any other
repo. loadConfig now deep-clones DEFAULTS before merging so no layer can
ever write onto a live DEFAULTS reference, and DEFAULTS itself is now
deep-frozen so any future regression of this kind throws immediately
instead of silently corrupting shared state. applyExcludeTestsShorthand
was also hardened to copy-on-write its `query` key directly.

Also dedupes the appliesTo-glob-matching logic (previously copy-pasted
between resolveConsent and promptForConsentIfNeeded) into a shared
matchesAppliesTo helper.

No user-facing behavior, CLI surface, or language support changed —
docs check acknowledged.

Fixes #1725

Impact: 6 functions changed, 140 affected
…pe engine resolution

openReadonlyWithNative opened the better-sqlite3 handle before resolving
the engine, and engine resolution calls loadConfig(), which can throw
(e.g. ConfigError from resolveSecrets on a malformed llm.apiKeyCommand).
If that throw happened, the already-open DB handle was never closed --
a real leak on the hot path used by dataflow/hotspots/stats commands.

Fix: resolve the engine (and thus loadConfig) before opening the DB,
mirroring openRepo's existing, correct ordering. Extracted the shared
engine-resolution logic (customDbPath > rootDir > loadConfig priority
chain) into resolveDbEngine(), used by both openRepo and
openReadonlyWithNative so the two call sites can't drift again.

Added tests/unit/openReadonlyWithNative-leak.test.ts: tracks every
better-sqlite3 Database instantiation and asserts zero occur when
loadConfig throws. Verified this test fails against the pre-fix
ordering (it recorded a leaked instance) and passes against the fix.

docs check acknowledged: internal bug fix + dedup, no CLI surface,
language support, or documented architecture/design decision changed.

Impact: 3 functions changed, 38 affected
…ne and cli/commands/info.ts

Converts 13 comment-only/silent catch blocks in pipeline.ts, native-orchestrator.ts,
detect-changes.ts, helpers.ts, and info.ts from `catch { /* comment */ }` to
`catch (e) { debug(...) }`, using the existing infrastructure/logger.ts debug()
utility. Purely additive observability -- no control-flow changes, no change to
what errors are swallowed vs rethrown.

docs check acknowledged: internal logging-only change, no new feature/language/
architecture/command surface to document in README/CLAUDE.md/ROADMAP.md.

Impact: 13 functions changed, 17 affected
…(docs check acknowledged)

Impact: 4 functions changed, 4 affected
…nfig (docs check acknowledged)

Impact: 6 functions changed, 12 affected
…docs check acknowledged)

Impact: 6 functions changed, 22 affected
…owledged)

Decompose gauntlet-flagged FAIL-level complexity in points-to.ts,
strategy.ts, and ts-resolver.ts via pure extract-method refactoring.
No resolution-behavior change (verified byte-for-byte identical
resolution-benchmark output across all 34 fixture languages).

Impact: 41 functions changed, 32 affected
…ut of domain layer

Impact: 1 functions changed, 8 affected
…aliasing, leiden complexity)

model.ts: merge() aliased NodeAttrs/EdgeAttrs objects by reference instead
of cloning, unlike subgraph()/filterEdges()/clone() which all defensively
copy with { ...attrs }. A caller merging graph B into graph A could
silently leak mutations across graphs via the shared attrs object. No
production caller exists today (verified via fn-impact: 0 callers besides
the test), so this was a latent defect, not a demonstrated one -- now
fixed to match the file's established convention.

leiden/partition.ts + leiden/adapter.ts: decomposed the remaining
cognitive/cyclomatic-exceeding functions left after phase 3's shared
aggregate/typed-array helper extraction (commit 0f9bbe6), following the
same directed/undirected-branch-splitting pattern gauntlet recommended:
- moveNode (cognitive 16->2, cyclomatic 13->3): split into
  applyMoveStrengthTotals + applyMoveInternalEdgeWeightDelta[Directed/Undirected]
- buildSortedCommunityIds (cognitive 17->3): extracted compareBySizeDesc/
  compareByPreserveMap comparators
- computeDeltaCPM (cognitive 17->4): extracted computeCpmEdgeWeights[Directed/Undirected]
- makeGraphAdapter (cognitive 27->3): extracted resolveAdapterOptions,
  buildNodeIndex, computeNodeSizes, makeForEachNeighbor
- populateUndirectedEdges (cognitive 28->0): extracted
  aggregateUndirectedPairs/recordUndirectedPairWeight, emitUndirectedPairs,
  applyUndirectedSelfLoops

Pure behavior-preserving decomposition -- no algorithm changes. Verified:
full test suite (201/201 files, 3336 tests), leiden-specific suite
(22/22), graph suite (177/177 incl. merge()), typecheck, and lint all
green. Community-detection output on the leiden-specific directories is
byte-identical before/after (confirmed via codegraph communities --drift
split-candidates, controlling for the known #1734 run-to-run noise).

docs check acknowledged: internal refactor + bug fix only, no user-facing
feature/language/architecture-table changes.

Impact: 28 functions changed, 31 affected
…ck acknowledged)

Extract getExceededMetrics as the single source of truth for which
manifesto thresholds a row exceeds, shared by mapComplexityRow and
exceedsAnyThreshold — cuts mapComplexityRow's cyclomatic complexity
from 23 (fail) to 10 and removes the duplicated 4-branch check.
Replace the hardcoded default-threshold object with DEFAULTS.manifesto.rules
(config.ts is already the source of truth for these values). Decompose
complexityData/computeComplexitySummary (resolveComplexityQueryOptions,
buildComplexityResult, queryComplexityRows, fetchAllComplexityMetrics,
summarizeComplexityMetrics, average) to bring halstead.effort for every
function in the file under the 15000 fail threshold. Pure decomposition,
zero behavior change — verified via clean rebuild + full test suite.

Widen tests/integration/complexity.test.ts's config.js mock to preserve
real exports via importOriginal (it previously replaced the whole module,
which broke once this file started importing DEFAULTS).

Impact: 24 functions changed, 8 affected
…wledged)

Wire computeCoChanges/analyzeCoChanges's minSupport/maxFilesPerCommit/since
fallback literals through DEFAULTS.coChange instead of re-declaring the
same magic numbers in two places (extended the same fix to minJaccard in
coChangeData/coChangeTopData/coChangeForFiles for consistency). Decompose
computeCoChanges' three passes (per-file counts, pair generation, Jaccard
filtering) into named helpers (updateFileCommitCounts, updatePairCounts,
buildCoChangeResults), plus scanGitHistory, analyzeCoChanges, coChangeData,
coChangeTopData, and coChangeForFiles — bringing halstead.effort for every
one of the 26 functions in the file under the 15000 fail threshold (worst
was computeCoChanges at 65249.68). Fix the loadLastAnalyzedSha/loadKnownFiles
silent catches to log via debug(), matching scanGitHistory's existing
error-visibility pattern. Pure decomposition + config wiring, zero behavior
change — verified via clean rebuild + full test suite (including the
real git-history integration tests in cochange.test.ts).

Impact: 23 functions changed, 15 affected
… acknowledged)

This was the run's worst gauntlet offender (halstead.bugs 1.585 on
branchCompareData). Pure decomposition per the gauntlet recommendation:
extract git-ref validation (validateBranchCompareRefs), dual-worktree +
dual-buildGraph setup (setupCompareWorktrees), and output-shape cleanup
(shapeBranchCompareSymbolLists) out of branchCompareData; unify
attachImpactToSymbols/attachImpactToChanged into one generic
attachImpact(symbols, resolveId, dbPath, maxDepth, noTests) parameterized
by id-resolution strategy.

Extended the same treatment to the file's other named-FAIL functions
(loadSymbolsFromDb: halstead.effort 123718.05->12326.18, bugs 0.9546->0.2182;
branchCompareMermaid: cyclomatic 22->6) and to pre-existing effort-fails
gauntlet's summary didn't name explicitly (loadCallersFromDb, compareSymbols)
-- consistent with this phase's cochange.ts/complexity-query.ts fixes, where
the file-level FAIL verdict covers every function over threshold, not just
the 2-3 worst examples cited in the audit detail text.

Zero behavior change: both exported functions (branchCompareData,
branchCompareMermaid) keep byte-identical signatures; every extraction
preserves exact call order, error-handling scope (the try/catch/finally
around worktree creation is untouched), and the existing mutate-in-place
impact-attachment pattern. Verified via tests/integration/branch-compare.test.ts,
which exercises real git worktrees + buildGraph + DB comparison end-to-end
(not mocked), plus the full suite, both before and after each incremental
edit.

Impact: 44 functions changed, 15 affected
…ck acknowledged)

Impact: 48 functions changed, 9 affected
…nowledged)

Decomposes the highest-complexity functions across 7 independent
single-language extractor files (sync.json phase 26): r, dart, groovy,
csharp, elixir, scala, julia. Pure behavior-preserving decomposition —
no extraction-logic changes. Resolution benchmark precision/recall/
TP/FP/FN confirmed byte-for-byte identical to baseline for all 7
languages.

Impact: 22 functions changed, 29 affected
…/printBuildMetadata

docs check acknowledged — pure internal decomposition of CLI output
logic, no new features/languages/architecture changes; README/CLAUDE/
ROADMAP do not need updates.

Impact: 5 functions changed, 2 affected
Impact: 2 functions changed, 3 affected
Split loader-hooks.mjs's instrumentSource (cognitive 34, cyclomatic 22)
into single-purpose matcher/tracker helpers. Extract the duplicated
line-scanning loop shared by native-tracer.sh's trace_rust/trace_swift/
trace_dart/trace_zig into a parameterized inject_trace_calls plus small
maybe_close_context/maybe_close_finally_scope/maybe_inject_declaration/
instrument_one_file helpers, and rename the LANG variable to TRACE_LANG
so it no longer clobbers the POSIX locale env var inherited by every
spawned compiler toolchain. Log lua-tracer.lua's swallowed pcall error
to stderr so a genuine fixture failure is visible instead of looking
like a silent successful trace.

Impact: 17 functions changed, 11 affected
…ing (docs check acknowledged)

Impact: 12 functions changed, 36 affected
…and modularity.ts

Forge phase 3 extracted fget/iget/u8get/taAdd into typed-array-helpers.ts
from adapter.ts/index.ts/partition.ts, but two sibling leiden files —
cpm.ts and modularity.ts — carried byte-for-byte identical private copies
of fget/iget (down to the "see adapter.ts for rationale" comment) that
were never migrated to the shared module. Codebase-wide grep/symbol scans
found no other duplicates of this pattern outside the leiden directory.

Both functions were unexported, file-local helpers with zero external
callers (codegraph exports confirms neither appears in either file's
export list), so replacing the private declarations with an import from
the shared module is a pure dedup with no behavioral change.

docs check acknowledged: internal helper adoption within an already-vendored
algorithm module, no user-facing feature/language/architecture-table changes.
…actor

Forge phase 7 (8fed8bc) added these as reserved DEFAULTS entries but left
their consumers on hardcoded literals.

db.busyTimeoutMs: openDb and openReadonlyOrFail in src/db/connection.ts now
take an optional busyTimeoutMs parameter defaulting to DEFAULTS.db.busyTimeoutMs.
Build and watch call sites that already hold a resolved config (pipeline,
native orchestrator, native-db-lifecycle, watcher, openRepo and
openReadonlyWithNative via the renamed resolveDbSettings helper) pass the
user-configured value through explicitly. This partially addresses issue 1749,
whose busy-locked regex dedup half remains open; remaining read-only query
call sites and the Rust connection.rs mirror are tracked in issue 1763.

community.capacityGrowthFactor is threaded through the existing maxLevels
and refinementTheta plumbing, from communitiesData through
louvainCommunities and detectClusters into makePartition, so
ensureCommCapacity in src/graph/algorithms/leiden/partition.ts reads the
configured value instead of a hardcoded 1.5 growth multiplier. It is
ignored by the native Rust Louvain path, consistent with the other options.

largeCodebaseFileThreshold, the third reserved entry from phase 7, was
already wired by a later forge commit and needed no action.

docs check acknowledged: internal config wiring only, already documented
in docs/guides/configuration.md by forge phase 7.

Impact: 31 functions changed, 171 affected
…icate sites

handleMethodCapture, handleMethodDef, and extractObjectLiteralFunctions each
inlined the identical computed_property_name unwrap-and-strip-quotes logic
that forge phase 10 already extracted into resolveMethodDefinitionName for
pushMethodDefContext. Consolidate onto the shared helper; no behavior change.

docs check acknowledged: internal-only duplicate-code consolidation, no new
languages/commands/architecture; README.md, CLAUDE.md, and ROADMAP.md are
unaffected.

Impact: 3 functions changed, 11 affected
Phase 11 decomposed build-edges.ts's resolveFallbackTargets into 15 named
helpers. The codebase-wide duplicate scan on those new helpers surfaced two
pre-existing duplicates the decomposition didn't catch (both predate phase 11
temporally, so the consolidation opportunities weren't nameable until now):

- resolveReflectionKeyExprFallback and resolveDefinePropertyAccessorFallback
  each inlined the same string/{type} typeMap-entry unwrap ternary that
  strategy.ts's unwrapTypeEntry already implements (extracted one commit
  after phase 11, in forge phase 20). Promoted unwrapTypeEntry to an export
  and wired both call sites to it.
- build-edges.ts's newly-named resolveSameClassQualifiedMethod was
  byte-identical to incremental.ts's pre-existing resolveThisSameClassTarget
  (incremental.ts's own docstring already noted it mirrors "the full-build
  counterpart"). Moved the shared implementation into call-resolver.ts --
  the module whose stated purpose is holding call-resolution logic shared
  between build-edges.ts and incremental.ts exactly once -- and wired both
  consumers to it.

Zero behavior change: all replaced logic was verified byte-identical before
relocating. Resolution benchmark (206/206) and full suite (3340 tests) pass
identically before/after.

Two follow-on divergences the scan also surfaced between the full-build and
incremental resolution paths (not fixed here -- would change behavior, not
just relocate it): incremental.ts has no same-class bare-call fallback
(#1765), and the Object.defineProperty same-file fallback's kind-filter
differs between the two paths (#1766).

docs check acknowledged: pure internal dedup/extract-method refactor, no
new features, commands, languages, or architecture changes -- README/CLAUDE/
ROADMAP do not need updates.

Impact: 5 functions changed, 20 affected
…docs check acknowledged)

insertDefinitionsAndExports (insert-nodes.ts) and insertBackfilledNodes
(native-orchestrator.ts) duplicated the exact same chunked-UPDATE loop for
marking exported symbols -- the latter's own comment even said "mirrors
insertDefinitionsAndExports". Extract markExportedSymbols(db, exportKeys) in
builder/helpers.ts, built on the existing getOrCreateBatchStmt/runBatchInsert
primitives from the batch-insert dedupe, and wire both call sites to it.

Impact: 4 functions changed, 20 affected
…-timing lib

Forge phase 28 extracted timeMedian in token-benchmark.ts, already wired
within that file. The codebase-wide duplicate scan found median()/round1()
duplicated verbatim across query-benchmark.ts, incremental-benchmark.ts
(twice), and benchmark.ts, plus the "loop N times, time each run, median()"
pattern repeated 8 more times across those files.

Promotes median/round1/timeMedian into scripts/lib/bench-timing.ts
(matching the existing bench-config.ts/fork-engine.ts shared-module
pattern) and wires median/round1 into all 4 scripts. Adopts timeMedian at
the 3 call sites that were already unconditionally async with no new
async boundary (incremental-benchmark.ts fullBuildMs/noopRebuildMs worker,
benchmark.ts noopRebuildMs worker).

Left 5 remaining duplicate sites unconverted since adopting timeMedian
there requires making currently-synchronous functions async, which is a
control-flow change rather than a mechanical adoption -- tracked in #1774.

Impact: 4 functions changed, 14 affected
@greptile-apps

greptile-apps Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adopts dead helpers identified during the Titan GRIND phase: wiring previously extracted-but-unused utilities into their real call sites and deduplicating recurring patterns across the codebase.

  • Config constants wired end-to-end: busyTimeoutMs now flows from DEFAULTS through openDb/openReadonlyOrFail default parameters and is forwarded explicitly by every build/watch call site that already holds a resolved config; capacityGrowthFactor is threaded from communitiesData all the way to ensureCommCapacity in the Leiden partition.
  • Structural deduplication: resolveSameClassQualifiedMethod, markExportedSymbols, unwrapTypeEntry, resolveMethodDefinitionName, fget/iget, and the bench-timing trio (median/round1/timeMedian) each had two-to-five byte-for-byte duplicates removed; the shared versions are functionally identical, chunk sizes and control-flow (return vs continue) preserved.
  • Previous-review follow-up addressed: DEFAULT_CAPACITY_GROWTH_FACTOR is now exported from partition.ts and imported by optimiser.ts, closing the three-copy drift risk called out in the prior thread.

Confidence Score: 5/5

A clean adoption PR; every shared helper is functionally identical to the duplicates it replaces, and config values that were previously hardcoded are now forwarded from the already-resolved config objects that all call sites hold.

All deduplication is purely mechanical — chunk sizes, control flow, and default values are preserved exactly. The busyTimeoutMs wiring is consistent across every openDb call site that holds a resolved config, and the remaining ad-hoc callers fall back to the same 5000 ms default as before. No behavioral changes were introduced.

src/presentation/audit.ts has a double-cast that may warrant a follow-up type fix, but it does not affect runtime behavior.

Important Files Changed

Filename Overview
scripts/lib/bench-timing.ts New shared module extracting median/round1/timeMedian from duplicate copies across four benchmark scripts; well-typed, empty-array guard added to median, runs parameter is now mandatory.
src/db/connection.ts Threads busyTimeoutMs through openDb/openReadonlyOrFail defaults and resolveDbSettings; loadConfig is now always invoked inside resolveDbSettings regardless of whether engineOpt is provided, which is intentional to also fetch busyTimeoutMs.
src/domain/graph/builder/helpers.ts Extracts markExportedSymbols using a module-level WeakMap cache (same BATCH_CHUNK=500 as the old per-call EXPORT_CHUNK=500 constants), correctly deduping the chunked UPDATE loop.
src/domain/graph/builder/call-resolver.ts Extracts resolveSameClassQualifiedMethod as an exported function; logic is identical to the private duplicates removed from build-edges.ts and incremental.ts.
src/graph/algorithms/leiden/partition.ts Exports DEFAULT_CAPACITY_GROWTH_FACTOR (resolving the previous-review's three-copy concern), adds capacityGrowthFactor to PartitionState and MakePartitionOptions, wires through ensureCommCapacity.
src/graph/algorithms/leiden/optimiser.ts Imports DEFAULT_CAPACITY_GROWTH_FACTOR from partition.ts (previous-review addressed), adds capacityGrowthFactor to LeidenOptions/NormalizedOptions, passes it through to makePartition at both call sites.
src/extractors/javascript.ts Replaces three identical computed_property_name inline blocks with calls to the file-local resolveMethodDefinitionName; control flow (return vs continue) is preserved correctly at each call site.
src/presentation/audit.ts Adds an as-unknown-as cast to satisfy outputResult's parameter type; the double escape hints at a structural type mismatch between AuditResult and Record<string, unknown> that may deserve a proper fix.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["communitiesData()\nsrc/features/communities.ts"] -->|capacityGrowthFactor| B["louvainCommunities()\nsrc/graph/algorithms/louvain.ts"]
    B -->|JS path| C["louvainJS() → detectClusters()"]
    C --> D["runLouvainUndirectedModularity()\noptimiser.ts"]
    D -->|capacityGrowthFactor| E["makePartition()\npartition.ts"]
    E --> F["ensureCommCapacity()\nuses s.capacityGrowthFactor"]
    B -->|native path| G["native Rust louvain\n⚠ ignores capacityGrowthFactor"]

    H["DEFAULTS.db.busyTimeoutMs\nconfig.ts"] -->|default param| I["openDb() / openReadonlyOrFail()\nconnection.ts"]
    J["resolveDbSettings()\nconnection.ts"] -->|busyTimeoutMs| I
    I --> K["pipeline.ts / watcher.ts\nnative-orchestrator.ts\nnative-db-lifecycle.ts"]

    P["resolveSameClassQualifiedMethod()\ncall-resolver.ts (exported)"] --> Q["build-edges.ts\nresolveFallbackTargets"]
    P --> R["incremental.ts\napplyThisReceiverFallbacks"]

    S["markExportedSymbols()\nhelpers.ts (exported)"] --> T["insert-nodes.ts\ninsertDefinitionsAndExports"]
    S --> U["native-orchestrator.ts\ninsertBackfilledNodes"]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A["communitiesData()\nsrc/features/communities.ts"] -->|capacityGrowthFactor| B["louvainCommunities()\nsrc/graph/algorithms/louvain.ts"]
    B -->|JS path| C["louvainJS() → detectClusters()"]
    C --> D["runLouvainUndirectedModularity()\noptimiser.ts"]
    D -->|capacityGrowthFactor| E["makePartition()\npartition.ts"]
    E --> F["ensureCommCapacity()\nuses s.capacityGrowthFactor"]
    B -->|native path| G["native Rust louvain\n⚠ ignores capacityGrowthFactor"]

    H["DEFAULTS.db.busyTimeoutMs\nconfig.ts"] -->|default param| I["openDb() / openReadonlyOrFail()\nconnection.ts"]
    J["resolveDbSettings()\nconnection.ts"] -->|busyTimeoutMs| I
    I --> K["pipeline.ts / watcher.ts\nnative-orchestrator.ts\nnative-db-lifecycle.ts"]

    P["resolveSameClassQualifiedMethod()\ncall-resolver.ts (exported)"] --> Q["build-edges.ts\nresolveFallbackTargets"]
    P --> R["incremental.ts\napplyThisReceiverFallbacks"]

    S["markExportedSymbols()\nhelpers.ts (exported)"] --> T["insert-nodes.ts\ninsertDefinitionsAndExports"]
    S --> U["native-orchestrator.ts\ninsertBackfilledNodes"]
Loading

Reviews (5): Last reviewed commit: "fix: import performance explicitly in be..." | Re-trigger Greptile

// via .codegraphrc.json. Callers (e.g. louvain.ts) can pass overrides through options.
const DEFAULT_MAX_LEVELS: number = 50;
const DEFAULT_MAX_LOCAL_PASSES: number = 20;
const DEFAULT_CAPACITY_GROWTH_FACTOR: number = 1.5;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Three copies of the same 1.5 default now exist independently: DEFAULT_CAPACITY_GROWTH_FACTOR here, DEFAULT_CAPACITY_GROWTH_FACTOR in partition.ts, and DEFAULTS.community.capacityGrowthFactor in config.ts. The value in optimiser.ts normalises the option before it reaches makePartition, but partition.ts also keeps its own copy as a last-resort fallback for callers that skip the optimiser layer. If the tuning value ever changes, all three sites must be updated atomically — any miss silently produces mismatched growth behaviour depending on which code path ran. Importing the constant from one canonical location would close that gap.

Suggested change
const DEFAULT_CAPACITY_GROWTH_FACTOR: number = 1.5;
import { DEFAULT_CAPACITY_GROWTH_FACTOR } from './partition.js';

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Claude Code

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed — exported DEFAULT_CAPACITY_GROWTH_FACTOR from partition.ts and imported it in optimiser.ts instead of keeping an independent literal. The third copy (DEFAULTS.community.capacityGrowthFactor in config.ts) is intentionally kept separate — it follows the same established pattern as DEFAULT_MAX_LEVELS/DEFAULT_MAX_LOCAL_PASSES in this file (module-level fallback mirrored from the user-facing config default, documented via comment), so no further action needed there.

@github-actions

github-actions Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Codegraph Impact Analysis

48 functions changed231 callers affected across 114 files

  • median in scripts/lib/bench-timing.ts:25 (13 transitive callers)
  • round1 in scripts/lib/bench-timing.ts:35 (10 transitive callers)
  • timeMedian in scripts/lib/bench-timing.ts:45 (5 transitive callers)
  • runPerfBenchmarks in scripts/token-benchmark.ts:262 (2 transitive callers)
  • openDb in src/db/connection.ts:161 (21 transitive callers)
  • openReadonlyOrFail in src/db/connection.ts:333 (126 transitive callers)
  • ResolvedDbSettings.engine in src/db/connection.ts:360 (0 transitive callers)
  • ResolvedDbSettings.busyTimeoutMs in src/db/connection.ts:361 (0 transitive callers)
  • resolveDbSettings in src/db/connection.ts:374 (24 transitive callers)
  • openRepo in src/db/connection.ts:427 (28 transitive callers)
  • openReadonlyWithNative in src/db/connection.ts:482 (8 transitive callers)
  • resolveSameClassQualifiedMethod in src/domain/graph/builder/call-resolver.ts:48 (8 transitive callers)
  • getExportStmt in src/domain/graph/builder/helpers.ts:453 (15 transitive callers)
  • markExportedSymbols in src/domain/graph/builder/helpers.ts:470 (7 transitive callers)
  • applyThisReceiverFallbacks in src/domain/graph/builder/incremental.ts:600 (5 transitive callers)
  • setupPipeline in src/domain/graph/builder/pipeline.ts:173 (4 transitive callers)
  • runPipelineStages in src/domain/graph/builder/pipeline.ts:277 (4 transitive callers)
  • resolveReflectionKeyExprFallback in src/domain/graph/builder/stages/build-edges.ts:1137 (3 transitive callers)
  • resolveDefinePropertyAccessorFallback in src/domain/graph/builder/stages/build-edges.ts:1182 (3 transitive callers)
  • insertDefinitionsAndExports in src/domain/graph/builder/stages/insert-nodes.ts:258 (3 transitive callers)

…ledged)

optimiser.ts kept its own copy of the 1.5 fallback instead of importing
partition.ts's constant, so the two could silently drift apart. Export
it from partition.ts and import it in optimiser.ts. Addresses Greptile
review feedback on #1793.
@carlos-alm

Copy link
Copy Markdown
Contributor Author

Addressed Greptile's review feedback: exported DEFAULT_CAPACITY_GROWTH_FACTOR from partition.ts and imported it in optimiser.ts (commit da0c267) instead of keeping an independently-drifting literal. See inline reply for details on why the third copy in config.ts is intentionally kept separate.

@carlos-alm

Copy link
Copy Markdown
Contributor Author

@greptileai

Base automatically changed from refactor/titan-warning-improvements to fix/titan-quality-fixes-ast-presentation-cli July 5, 2026 02:26
Base automatically changed from fix/titan-quality-fixes-ast-presentation-cli to main July 5, 2026 07:23
docs check acknowledged — merge conflict resolution only, no new
features/languages/architecture changes; README/CLAUDE/ROADMAP do not
need updates.

Impact: 11 functions changed, 31 affected
Every other benchmark script imports performance from node:perf_hooks;
bench-timing.ts relied on the global instead. Flagged by Greptile's
review summary.

docs check acknowledged — one-line import fix, no new
features/languages/architecture changes; README/CLAUDE/ROADMAP do not
need updates.
@carlos-alm

Copy link
Copy Markdown
Contributor Author

Addressed the remaining item from Greptile's review summary: added the missing import { performance } from 'node:perf_hooks'; in scripts/lib/bench-timing.ts — every other benchmark script imports it explicitly rather than relying on the global.

@carlos-alm

Copy link
Copy Markdown
Contributor Author

@greptileai

@carlos-alm carlos-alm merged commit a3629f1 into main Jul 5, 2026
15 checks passed
@carlos-alm carlos-alm deleted the refactor/titan-grind-adoptions branch July 5, 2026 17:03
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 5, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant