Skip to content

refactor: address warn-level complexity across features, visitors, presentation, and infrastructure#1593

Merged
carlos-alm merged 6 commits into
mainfrom
refactor/titan-warn-complexity
Jun 18, 2026
Merged

refactor: address warn-level complexity across features, visitors, presentation, and infrastructure#1593
carlos-alm merged 6 commits into
mainfrom
refactor/titan-warn-complexity

Conversation

@carlos-alm

Copy link
Copy Markdown
Contributor

Summary

Addresses warn-level complexity violations across 5 domains that cleared the FAIL threshold but remained above WARN thresholds. Grouped as a single PR since all are below-FAIL cleanup rather than structural decompositions.

  • presentation/viewer.tsrenderPlotHTML decomposed; MI improved
  • domain/wasm-worker-pool.tsdeserializeResult extracted
  • features/ (8 files: audit, boundaries, cfg, check, communities, sequence, snapshot, triage) — warn-level complexity addressed, empty catch in features/structure.ts fixed
  • ast-analysis/visitors/ (complexity-visitor, dataflow-visitor, visitor.ts) — visitor dispatch helpers extracted
  • infrastructure/registry.ts, update-check.tscheckForUpdates cyclomatic: 13→10
  • graph/algorithms/tarjan.ts — complexity addressed
  • graph/builders/dependency.ts — complexity addressed
  • shared/normalize.ts — complexity addressed

Titan Audit Context

Metrics Impact

  • 17 functions moved from warn to below-threshold
  • checkForUpdates cyclomatic: 13→10
  • Empty catch in features/structure.ts fixed (Rule II.10 violation resolved)

Test plan

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

@github-actions

github-actions Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Codegraph Impact Analysis

95 functions changed149 callers affected across 73 files

  • WalkState.visitors in src/ast-analysis/visitor.ts:156 (0 transitive callers)
  • WalkState.allFuncTypes in src/ast-analysis/visitor.ts:157 (0 transitive callers)
  • WalkState.nestingNodeTypes in src/ast-analysis/visitor.ts:158 (0 transitive callers)
  • WalkState.getFunctionName in src/ast-analysis/visitor.ts:159 (0 transitive callers)
  • WalkState.context in src/ast-analysis/visitor.ts:160 (0 transitive callers)
  • WalkState.scopeStack in src/ast-analysis/visitor.ts:161 (0 transitive callers)
  • WalkState.skipDepths in src/ast-analysis/visitor.ts:162 (0 transitive callers)
  • buildWalkState in src/ast-analysis/visitor.ts:166 (14 transitive callers)
  • walkNode in src/ast-analysis/visitor.ts:196 (14 transitive callers)
  • walkWithVisitors in src/ast-analysis/visitor.ts:257 (19 transitive callers)
  • computeEffectiveNesting in src/ast-analysis/visitors/complexity-visitor.ts:215 (1 transitive callers)
  • trackElseIfNestingAdjust in src/ast-analysis/visitors/complexity-visitor.ts:230 (1 transitive callers)
  • createComplexityVisitor in src/ast-analysis/visitors/complexity-visitor.ts:243 (9 transitive callers)
  • enterNode in src/ast-analysis/visitors/complexity-visitor.ts:302 (0 transitive callers)
  • unwrapArg in src/ast-analysis/visitors/dataflow-visitor.ts:291 (3 transitive callers)
  • resolveArgTrackedName in src/ast-analysis/visitors/dataflow-visitor.ts:305 (3 transitive callers)
  • handleCallExpr in src/ast-analysis/visitors/dataflow-visitor.ts:312 (2 transitive callers)
  • resolveMutationCallParts in src/ast-analysis/visitors/dataflow-visitor.ts:352 (3 transitive callers)
  • handleExprStmtMutation in src/ast-analysis/visitors/dataflow-visitor.ts:378 (2 transitive callers)
  • mapTransitiveCallers in src/db/repository/native-repository.ts:172 (3 transitive callers)

@greptile-apps

greptile-apps Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR addresses warn-level cyclomatic and cognitive complexity violations across five domains by extracting helper functions — no algorithmic or behavioral changes are introduced. All extractions are faithful lifts of existing inline logic into named private functions with matching doc comments.

  • ast-analysis/visitor.ts & visitors/: Walk state initialization (buildWalkState/walkNode), nesting computation (computeEffectiveNesting), and dataflow argument unwrapping (unwrapArg, resolveArgTrackedName, resolveMutationCallParts) are each isolated into single-responsibility helpers.
  • features/ (8 files): Inline logic in audit, boundaries, cfg, check, communities, sequence, snapshot, and triage is extracted into small, documented helpers; the CommunitiesDataOpts inline object type is promoted to a named interface.
  • infrastructure/ & presentation/ & graph/ & shared/: checkForUpdates cyclomatic reduced from 13→10 via resolveLatestVersion/collectResponseBody; renderPlotHTML decomposed into three section renderers; kindIcon switch replaced with a const lookup table.

Confidence Score: 5/5

Safe to merge — all changes are mechanical extractions of existing inline logic into named helpers with no algorithmic differences.

Every extraction was verified against the original: loop variable re-assignment in dataflow-visitor is correctly modelled by raw vs unwrapped; parseTreeForCfg returning undefined instead of null is handled by the falsy check in the caller; resolveLatestVersion returning a cached null version gracefully short-circuits rather than passing null to semverCompare; pruneConsentEntries mutates by reference just as the original inline loop did. No logic was changed, only reorganised.

No files require special attention.

Important Files Changed

Filename Overview
src/ast-analysis/visitor.ts Extracts buildWalkState and walkNode from walkWithVisitors; DFS logic and public API are preserved exactly.
src/ast-analysis/visitors/dataflow-visitor.ts Extracts unwrapArg, resolveArgTrackedName, resolveMutationCallParts; raw correctly maps to the post-wrapper-unwrap node used for expression in the original loop.
src/ast-analysis/visitors/complexity-visitor.ts Extracts computeEffectiveNesting and trackElseIfNestingAdjust; nesting-adjustment logic is equivalent to the inline original.
src/db/repository/native-repository.ts Hoists mapTransitiveCallers and mapFnDepsEntry from the inline raw.results.map callback; pure refactor with no behavioral change.
src/domain/wasm-worker-pool.ts Splits deserializeResult into deserializeCoreFields, deserializeBindingFields, deserializeMapFields; callAssignments correctly moved to binding section (simple array, not a Map).
src/features/audit.ts Extracts querySymbolEdges from enrichSymbol; three DB queries and test-file filtering are preserved verbatim.
src/features/boundaries.ts Extracts collectOuterModules; outer-layer filtering logic is equivalent to the original nested loop.
src/features/cfg.ts Extracts parseTreeForCfg; returns undefined on failure (vs null in original) but if (!tree) in the caller handles both correctly.
src/features/check.ts Extracts three diff-header predicates; evaluation order in the loop is preserved so --- /dev/null is still matched before the broader --- check.
src/features/communities.ts Extracts loadCommunityGraph and promotes inline opts object type to CommunitiesDataOpts; finally { close() } semantics preserved.
src/features/sequence.ts Extracts resolveCollisionAliases; depth-iteration and uniqueness logic are equivalent to the inline original.
src/features/snapshot.ts Extracts atomicPlaceFile; atomic linkSync/rename and EEXIST detection logic are preserved without change.
src/features/triage.ts Extracts resolveRiskConfig and ResolvedRiskConfig; weight merging order (DEFAULT_WEIGHTS → riskConfig.weights → opts.weights) is preserved.
src/graph/algorithms/tarjan.ts Comment-only change — adds explanatory inline comments to the SCC detection steps; no logic altered.
src/graph/builders/dependency.ts Extracts resolveCallEdges; explicit as Repository/as BetterSqlite3Database casts are added (the original lacked them, relying on implicit narrowing that TS does not provide through a boolean variable).
src/infrastructure/registry.ts Splits pruneRegistry into pruneRepoEntries and pruneConsentEntries; consent mutation-by-reference and consentChanged flag semantics are preserved.
src/infrastructure/update-check.ts Extracts collectResponseBody and resolveLatestVersion; cache-hit / stale-fetch branches are equivalent to the original; JSDoc updated per previous review thread.
src/presentation/viewer.ts Decomposes renderPlotHTML into renderViewerHead, renderViewerControls, renderViewerScript; HTML structure and escaping are identical to the original.
src/shared/normalize.ts Replaces switch statement in kindIcon with a const lookup table; default - case preserved via ?? '-'.

Reviews (3): Last reviewed commit: "chore: merge origin/main — resolve confi..." | Re-trigger Greptile

Comment on lines +122 to +126
/**
* Return the latest version from cache if fresh, or fetch it from the registry.
* Persists the result to the cache before returning.
* Returns null when the network fetch fails or the cache is corrupt.
*/

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 Misleading JSDoc: cache-hit path does not persist

The second bullet — "Persists the result to the cache before returning" — is inaccurate for the fresh-cache code path: when Date.now() - cache.lastCheckedAt < CACHE_TTL_MS, the function returns cache.latestVersion without calling saveCache. Persistence only happens on the stale/missing branch. The JSDoc should clarify that persistence is conditional on a network fetch, otherwise callers may assume every call refreshes the timestamp.

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 — updated the JSDoc to accurately describe conditional persistence: the cache is only written when a network fetch occurs (stale/missing cache path). When the cache is fresh, the value is returned directly without saving.

Comment on lines +145 to 151
function deserializeResult(ser: SerializedExtractorOutput | null): ExtractorOutput | null {
if (!ser) return null;
const out: ExtractorOutput = { ...deserializeCoreFields(ser) } as ExtractorOutput;
deserializeBindingFields(ser, out);
deserializeMapFields(ser, out);
return out;
}

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 Force-cast bypasses TypeScript exhaustiveness on ExtractorOutput

deserializeCoreFields returns Pick<ExtractorOutput, …> & Partial<Pick<ExtractorOutput, …>>, which intentionally omits the binding and Map fields. The spread-then-cast { ...deserializeCoreFields(ser) } as ExtractorOutput silences TypeScript for the gap between what the core helper returns and the full ExtractorOutput shape. If a new required field is added to ExtractorOutput and assigned in one of the three helpers but forgotten in another, the compiler will not catch the partial construction here.

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.

Added an inline comment explaining why the cast is safe and documenting the maintenance contract: all required ExtractorOutput fields are covered by deserializeCoreFields's Pick return type. The comment instructs future devs to update deserializeCoreFields's return type and body when adding new required fields to ExtractorOutput.

Keep main's improved CODEGRAPH_ENGINE validation (with explicit warn on
invalid values) and the updated engine JSDoc that documents partial wiring.
@carlos-alm

Copy link
Copy Markdown
Contributor Author

Addressed both Greptile P2 findings and resolved merge conflicts with main:

Conflicts resolved (src/infrastructure/config.ts, src/types.ts): Kept main's improved CODEGRAPH_ENGINE validation (explicit warn on invalid values) and the updated engine JSDoc documenting partial wiring (issue #1596).

Finding 1 (update-check.ts:126): Updated JSDoc to accurately state that persistence is conditional — the cache is only written when a network fetch occurs (stale/missing path). The cache-hit path returns directly without saving.

Finding 2 (wasm-worker-pool.ts:151): Added an inline comment documenting the maintenance contract for the force-cast: all required ExtractorOutput fields are covered by deserializeCoreFields's Pick return type, and the comment instructs future devs to keep deserializeCoreFields in sync when adding new required fields.

@carlos-alm

Copy link
Copy Markdown
Contributor Author

@greptileai

@carlos-alm carlos-alm merged commit 97261c3 into main Jun 18, 2026
30 checks passed
@carlos-alm carlos-alm deleted the refactor/titan-warn-complexity branch June 18, 2026 00:47
@github-actions github-actions Bot locked and limited conversation to collaborators Jun 18, 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