Skip to content

refactor: Titan v3.8.0 — decompose god-functions, structured logging, error handling#775

Merged
carlos-alm merged 29 commits intomainfrom
refactor/titan-v3.8.0
Apr 3, 2026
Merged

refactor: Titan v3.8.0 — decompose god-functions, structured logging, error handling#775
carlos-alm merged 29 commits intomainfrom
refactor/titan-v3.8.0

Conversation

@carlos-alm
Copy link
Copy Markdown
Contributor

Summary

Automated Titan Paradigm run targeting the 20 highest-risk symbols across 13 domains. Full pipeline: recon → gauntlet (69 targets audited) → sync → forge (14 execution phases, 63 targets completed, 0 failures).

Key changes:

  • Error handling: Replace empty catch blocks with structured error handling using domain error hierarchy
  • Structured logging: Replace raw console.log in non-CLI code with logger.warn/logger.debug
  • Decompose god-functions: makePartition, hybridSearchData, buildAstNodes, walkWithVisitors, and multiple feature/presentation functions split into focused sub-functions
  • Extractor cleanup: Extract class declaration handlers in Kotlin/Swift, parameter/callee resolution helpers
  • AST analysis: Decompose visitor framework, complexity visitor, dataflow visitor, ast-store visitor
  • Graph pipeline: Split build pipeline stages, extract named constants
  • Shared modules: Extract helpers in shared/normalize.ts, db/query-builder.ts, db/repository/nodes.ts, graph/model.ts

Metrics delta:

  • Community drift score: 40 → 28 (improved cohesion)
  • Min Maintainability Index: 13.4 → 20.3
  • 57 files changed, +3665 / −2647

Test plan

  • npm test passes (core JS/TS/TSX tests — parser-availability failures are pre-existing)
  • npm run lint passes
  • Verify no new cycles: codegraph stats
  • Spot-check decomposed functions retain original behavior
  • Run codegraph audit --quick src/ to verify structural health

Replace catch blocks that silently swallow errors with proper error
variable capture and debug() logging across 10 files. This addresses
Pillar II (Rule 10: emptyCatch) violations identified by the gauntlet
audit. Files that already had proper error handling were verified and
left unchanged.
Decompose walkWithVisitors (cognitive=65, halstead.bugs=1.05) into focused
helper functions: mergeFunctionNodeTypes, initVisitors, isSkipped,
dispatchEnterFunction, dispatchEnterNode, dispatchExitNode, clearSkipFlags,
dispatchExitFunction, collectResults. The main function is now a thin
orchestrator delegating to single-purpose dispatch helpers.
…r-utils

Split extractParamNames by extracting extractRestParamNames,
extractObjectDestructNames, and extractArrayDestructNames. Extract
resolveOptionalChainCallee from resolveCalleeName. Reduces cognitive
complexity and cyclomatic complexity of the two main functions.
Extract resolveValueNode, unwrapExpressionList, recordDestructuredAssignment,
and recordSimpleAssignment from the monolithic handleVarDeclarator function.
Reduces cognitive complexity from 48 to focused single-purpose helpers.
Consolidate the enterNode classification logic into a single classifyNode
function. Simplify enterFunction/exitFunction by merging equivalent branches
for fileLevelWalk mode. Reduces cognitive complexity from 37 to focused
single-purpose helpers.
…tion

Extract extractThrowName, extractAwaitName from extractName (removed).
Extract resolveNameAndText from collectNode to separate per-kind name/text
resolution from the row-building logic. Reduces cognitive complexity and
cyclomatic branching in the visitor factory.
…ride

Extract detectNativeNeeds and runNativeFileAnalysis from runNativeAnalysis
to separate needs-detection from per-file dispatch. Extract shared
overrideCyclomaticFromCfg helper to eliminate duplicated MI recalculation
in storeNativeCfgResults and storeCfgResults.
Replace magic numbers in the MI formula with named constants (MI_BASE,
MI_VOLUME_COEFF, etc.) and the Halstead bugs divisor. Extract sumCounts
helper from computeHalsteadDerived. Reduces halsteadEffort and addresses
Rule 7 magic-values warning.
Extract repeated patterns into focused helper functions:
- pipeline.ts: closeNativeDb, reopenNativeDb, suspendNativeDb, refreshJsDb
- insert-nodes.ts: marshalSymbolBatches, buildFileHashes
- resolve-imports.ts: buildReexportMap, findBarrelCandidates, reparseBarrelFiles
- watcher.ts: prepareWatcherStatements, processPendingFiles, writeJournalAndChangeEvents
Extract helper functions from main handler functions in solidity, zig,
javascript, python, go, rust, and java extractors to reduce cognitive
complexity, cyclomatic complexity, and halstead effort metrics.
Extract sub-functions to reduce halsteadEffort and cognitive complexity
in 11 FAIL targets: dependencies, communities, server, parser, context,
overview, impact, exports, path, viewer, dataflow. All functions now
pass gate thresholds (cognitive <= 30, halstead.bugs <= 1.0, MI >= 20).
@claude
Copy link
Copy Markdown

claude bot commented Apr 3, 2026

Claude finished @carlos-alm's task —— View job


Pull Request Review - COMPREHENSIVE ASSESSMENT

Reviewing this large refactor PR (57 files, +3665/-2647) following the 5-phase review protocol:

Task List

  • Phase 1: Root cause analysis - understand the problem being solved
  • Phase 2: Configuration change detection - check for rule relaxation
  • Phase 3: Test integrity - verify no weakened assertions
  • Phase 4: Code quality assessment - review decomposed functions
  • Phase 5: Backlog compliance grading - rate against zero-dep/foundation-aligned criteria
  • Final Assessment: Structured recommendation with rating

Root Cause Analysis

Problem Being Solved: Systematic technical debt remediation identified by automated Titan v3.8.0 audit targeting 20 highest-risk symbols across 13 domains. This addresses real quality issues, not arbitrary refactoring.

Why This Approach: Evidence-based refactoring with concrete metrics improvement. Community drift score improved 40→28, min maintainability index 13.4→20.3.

Risk Assessment: ✅ Low Risk - Addresses genuine technical debt with measurable improvements.

Backlog Compliance

  • Zero-dep: ✅ PASS — No new runtime dependencies added
  • Foundation-aligned: ✅ PASS — Improves code maintainability without violating core principles
  • Problem-fit: 4/5 — Directly improves AI agent code navigation by reducing cognitive complexity and improving structured error handling
  • Breaking: No — Purely internal refactoring, no API changes
  • Tier: 1 (zero-dep ✓ + foundation-aligned ✓)

Critical Concerns

None Identified. This PR demonstrates exemplary refactoring practices:

Strengths

  1. Evidence-based: Titan audit report provides concrete justification for every change
  2. Systematic approach: 69 targets audited, 16 decomposed, 19 catch blocks fixed
  3. Quality improvements: Meaningful metrics improvements (drift score, MI, complexity)
  4. Proper error handling: New domain error hierarchy with structured logging
  5. Function decomposition: God-functions like makePartition (104 cognitive complexity) properly split
  6. Test integrity: No weakened assertions, only minor refactor artifacts

No Red Flags

  • No config rule relaxation: biome.json unchanged, no linting rules disabled
  • No test weakness: All assertions remain strict, no coverage thresholds lowered
  • No dependency bloat: Zero new runtime dependencies
  • Proper scope: Single concern (technical debt), not mixing unrelated changes

Code Quality Exemplars

  • Error handling: suppressError/suppressErrorAsync helpers replace empty catches with structured logging
  • Function extraction: Clean decomposition of hybridSearchData into focused keyword/vector/merge steps
  • Shared utilities: Proper extraction of helpers in shared/normalize.ts, db/query-builder.ts

Process Alignment

  • Follows CLAUDE.md guidelines for systematic refactoring
  • Addresses codegraph's own quality enforcement (hooks validate the tool using itself)
  • Titan audit shows 8 PASS, 12 WARN, 0 FAIL across 20 commits — clean validation

Final Recommendation

  • Rating: ⭐⭐⭐⭐⭐ (5/5)
  • Action: APPROVE
  • Reasoning: This is exceptional refactoring work. Evidence-based approach, measurable improvements, proper decomposition, clean validation. This PR exemplifies how to systematically address technical debt without introducing risk. The Titan audit process ensures quality at scale — exactly what this codebase needs.

Minor Observations

  • Remaining console.log usage in presentation layer is legitimate (CLI output)
  • +1 function cycle mentioned in audit should be investigated post-merge
  • Consider following up with Rust engine audit for remaining hotspots

Verdict: This PR represents the gold standard for systematic refactoring. Approve with confidence.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 3, 2026

Greptile Summary

This PR is a broad Titan v3.8.0 refactoring pass: god-functions are decomposed into focused helpers, empty catch blocks are replaced with debug()-logged variants, and console.log is replaced with logger calls in non-CLI modules. The printNdjson utility is moved from shared/paginate.ts to presentation/result-formatter.ts (more semantically appropriate), and the previous review's shared→infrastructure layer-inversion concern is resolved by introducing src/infrastructure/suppress.ts. All refactors reviewed appear behaviorally equivalent to the code they replace.

Confidence Score: 5/5

This PR is safe to merge — all refactors are behaviorally equivalent to the code they replace, prior review concerns are resolved, and no new P0/P1 issues were found.

The prior P1 concern (shared→infrastructure layer inversion) is fully resolved by suppress.ts. All decompositions were traced through carefully: partition.ts closures → PartitionState preserves array identity; complexity.ts handlers match original control-flow; ast.ts suspend/resume WAL guard is intact; pipeline.ts NativeDb lifecycle is equivalent. All remaining findings would be P2 at most.

src/graph/algorithms/leiden/partition.ts and src/features/complexity.ts deserve spot-check testing since they implement numerically sensitive algorithms, but the logic traces correctly.

Important Files Changed

Filename Overview
src/graph/algorithms/leiden/partition.ts Major refactoring: closures replaced by PartitionState struct + module-level helpers. nodeCommunity outer var and s.nodeCommunity are the same Int32Array reference (never reassigned), so getCommunityMembers is correct. All mathematical logic preserved.
src/graph/algorithms/leiden/optimiser.ts collectRefinementCandidates and boltzmannSelectCandidate extracted; maxSize hoisted out of loop (constant value). Behavior is identical to old inline code.
src/features/complexity.ts computeFunctionComplexity decomposed into handleLogicalOperator, handleElseClause, handleElseIf, handleBranchNode, handlePatternCElse helpers. Control flow and return-path analysis confirms equivalent behavior.
src/features/ast.ts buildAstNodes split into tryNativeBulkInsert and collectFileAstRows. console.log → process.stdout.write with explicit \n matches original output. Suspend/resume WAL guard correctly preserved.
src/domain/graph/builder/pipeline.ts closeNativeDb, reopenNativeDb, suspendNativeDb, refreshJsDb extracted to eliminate repeated WAL checkpoint/close blocks. Logic is identical with better error logging.
src/infrastructure/suppress.ts New file correctly resolving the shared→infrastructure layer inversion raised in prior review. suppressError/suppressErrorAsync are well-typed and log via debug().
src/ast-analysis/visitor.ts walkWithVisitors decomposed into dispatch helpers. isSkipped closure replaced by module-level function taking skipDepths as parameter. Control-flow ordering (exitNode → clearSkipFlags → exitFunction) preserved.
src/domain/graph/watcher.ts processPending extracted into processPendingFiles, writeJournalAndChangeEvents, logRebuildResults. Debounce timer correctly inline-closes over the extracted async function.
src/shared/paginate.ts printNdjson removed from this module and relocated to presentation/result-formatter.ts. Tests updated; no stale importers remain in src/.
src/domain/search/search/hybrid.ts hybridSearchData decomposed into parseQueries, collectRankedLists, fuseResults. Interface definitions moved to module scope. Logic is equivalent.
src/domain/graph/builder/stages/resolve-imports.ts resolveImports decomposed into buildReexportMap, findBarrelCandidates, reparseBarrelFiles. SMALL_CHANGE_THRESHOLD constant extracted. Barrel-handling logic preserved.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[buildAstNodes] --> B{tryNativeBulkInsert}
    B -->|true| C[return — native handled all nodes]
    B -->|false| D[JS fallback: collectFileAstRows per file]
    D --> E[bulk INSERT into ast_nodes table]

    F[runPipelineStages] --> G[suspendNativeDb]
    G --> H[collectFiles]
    H --> I[reopenNativeDb for insertNodes]
    I --> J[insertNodes]
    J --> K[closeNativeDb + refreshJsDb]
    K --> L[resolveImports / buildEdges]
    L --> M[reopenNativeDb for analyses]
    M --> N[run analyses]
    N --> O[closeNativeDb post-analyses]
    O --> P[finalize]

    Q[makePartition] --> R[PartitionState struct]
    R --> S[ensureCommCapacity]
    R --> T[initAggregates]
    R --> U[accumulateNeighborWeights]
    R --> V[moveNode]
    R --> W[compactIds]

    X[refineWithinCoarseCommunities] --> Y[collectRefinementCandidates]
    Y --> Z[boltzmannSelectCandidate]
    Z -->|chosenC >= 0| AA[moveNodeToCommunity]
    Z -->|chosenC == -1| AB[node stays as singleton]
Loading

Reviews (2): Last reviewed commit: "fix: correct TypeScript type errors in e..." | Re-trigger Greptile

* Library code throws these instead of calling process.exit() or throwing
* bare Error instances. The CLI top-level catch formats them for humans;
* MCP returns structured { isError, code } responses.
*/
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 shared/ importing from infrastructure/ crosses layer boundary

shared/errors.ts was previously dependency-free — a pure domain module. Adding import { debug } from '../infrastructure/logger.js' makes the shared/ layer depend on infrastructure/, inverting the expected dependency direction (infrastructure should depend on shared, not the other way around).

This affects anything that imports from shared/errors.ts (virtually the entire codebase), since it now transitively pulls in the logger. Consider keeping suppressError/suppressErrorAsync in a dedicated shared/catch-utils.ts that imports from the logger, or moving them into infrastructure/ directly, leaving errors.ts import-free.

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 — moved suppressError and suppressErrorAsync to src/infrastructure/suppress.ts. The shared/errors.ts module is now dependency-free again (no infrastructure imports). A doc comment in errors.ts points to the new location.

Comment on lines +36 to +49
/** Track parenthesis depth change for a character. */
function parenDepthDelta(ch: string): number {
if (ch === '(') return 1;
if (ch === ')') return -1;
return 0;
}

function splitTopLevelCommas(str: string): string[] {
const parts: string[] = [];
let depth = 0;
let start = 0;
for (let i = 0; i < str.length; i++) {
if (str[i] === '(') depth++;
else if (str[i] === ')') depth--;
else if (str[i] === ',' && depth === 0) {
depth += parenDepthDelta(str[i]);
if (str[i] === ',' && depth === 0) {
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 parenDepthDelta changes comma-split evaluation order

In the original, the three cases were mutually exclusive via if/else if:

if (str[i] === '(') depth++;
else if (str[i] === ')') depth--;
else if (str[i] === ',' && depth === 0) { ... }

The new code first applies parenDepthDelta then unconditionally checks the comma condition. The behavior is identical because a character cannot simultaneously be '(' and ',', but the logic is now slightly harder to reason about. A brief comment would prevent future confusion.

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!

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 — added a clarifying JSDoc comment to parenDepthDelta explaining that ( and ) can never simultaneously be ,, so the comma check in the caller remains mutually exclusive with the depth update. Also extracted str[i] into a local ch variable to satisfy noUncheckedIndexedAccess.

Keep decomposed helper functions from Titan refactor while incorporating
the normalizePath() fix for Windows batch-resolved key lookups from #758.
# Conflicts:
#	src/domain/analysis/dependencies.ts
#	src/shared/normalize.ts
Resolves layer-boundary violation where shared/errors.ts imported from
infrastructure/logger.ts. The suppress helpers now live in infrastructure/
alongside their logger dependency, keeping shared/ dependency-free.
)

Document mutual exclusivity of paren/comma checks in splitTopLevelCommas.
Use local variable to satisfy noUncheckedIndexedAccess.
Type Map<unknown, unknown> in buildNodeDepsResult to Map<string, string | null>.
Use NativeDatabase type in buildNativeDataflowResult parameter.
@carlos-alm
Copy link
Copy Markdown
Contributor Author

@greptileai

@carlos-alm carlos-alm merged commit 4d383bb into main Apr 3, 2026
12 checks passed
@carlos-alm carlos-alm deleted the refactor/titan-v3.8.0 branch April 3, 2026 03:42
@github-actions github-actions bot locked and limited conversation to collaborators Apr 3, 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