Skip to content

refactor: adopt dead helpers across codebase#895

Merged
carlos-alm merged 6 commits intomainfrom
feat/adopt-dead-helpers
Apr 8, 2026
Merged

refactor: adopt dead helpers across codebase#895
carlos-alm merged 6 commits intomainfrom
feat/adopt-dead-helpers

Conversation

@carlos-alm
Copy link
Copy Markdown
Contributor

@carlos-alm carlos-alm commented Apr 8, 2026

Summary

Code adoptions (28 files, -30 net lines)

  • Adopt named_child_text across 27 sites in 11 Rust extractors — replaces node.child_by_field_name("X").map(|n| node_text(&n, source)) boilerplate
  • Migrate cpp.rs from hand-rolled find_cpp_parent_class to existing find_enclosing_type_name helper (-14 lines)
  • Add toSymbolRef utility in shared/normalize.ts, adopt at 15 inline { name, kind, file, line } mapping sites across 7 files
  • Wire ParseError in parser.tsdoLoadLanguage now throws structured PARSE_FAILED errors with file and cause instead of bare re-throws
  • Wire BoundaryError in boundaries.ts — invalid config and DB failures now throw instead of silently returning empty results; callers (manifesto.ts, diff-impact.ts) handle gracefully
  • Add --modules/--threshold flags to codegraph structure command, wiring existing but unused moduleBoundariesData + formatModuleBoundaries
  • Wire batchQuery in CLI batch command, removing duplicated multi-batch routing logic
  • Route detect-changes pending analysis path through unified runAnalyses engine instead of separate buildCFGData/buildDataflowEdges calls

New /titan-grind skill (Phase 4.5)

  • Add .claude/skills/titan-grind/SKILL.md — closes the adoption loop that forge leaves open. After forge extracts helpers, grind finds the dead ones, classifies them (adopt/re-export/promote/false-positive/remove), wires them into consumers, and gates on dead-symbol delta
  • Update .claude/skills/titan-run/SKILL.md — pipeline is now recon → gauntlet → sync → forge → grind → close. Added Step 4.5 with grind loop, V16-V19 validations, --start-from grind support, and forge artifact pre-validation

Why

Titan runs (v3.3.1–v3.8.0) extracted helpers that were never consumed, inflating dead symbols from 8,259 → 11,647 across three runs. This PR does the manual adoption work and adds the /titan-grind phase so future runs close the loop automatically.

Test plan

  • All 36 unit test files pass (975 tests)
  • All 31 integration test files pass (564 tests)
  • boundaries.test.ts updated for new BoundaryError throw behavior (32/32 pass)
  • TypeScript build passes (tsc)
  • Lint passes (0 new warnings)
  • Verify codegraph structure --modules produces expected output on a real repo
  • Verify codegraph batch still works for both single and multi-batch targets
  • CI green on all platforms
  • Run /titan-grind --dry-run on a post-forge branch to validate the skill

Wire up extracted helpers from Titan runs that existed but were never
consumed, reducing boilerplate and improving error specificity.

- Adopt named_child_text across 27 sites in 11 Rust extractors
- Migrate cpp.rs from hand-rolled find_cpp_parent_class to find_enclosing_type_name
- Add toSymbolRef helper in shared/normalize.ts, adopt at 15 mapping sites
- Wire ParseError in parser.ts for structured PARSE_FAILED error codes
- Wire BoundaryError in boundaries.ts to distinguish config/DB failures from clean results
- Add --modules/--threshold flags to codegraph structure command
- Wire batchQuery in CLI batch command, removing duplicated routing logic
- Route detect-changes pending analysis through unified runAnalyses engine
@claude
Copy link
Copy Markdown

claude bot commented Apr 8, 2026

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


Code Review Analysis

Reviewing PR #895: "refactor: adopt dead helpers across codebase"

Todo List:

  • Read CLAUDE.md and understand repository structure
  • Phase 1: Root Cause Analysis - Understand what problem this PR solves
  • Phase 2: Configuration Change Detection - Check for high-risk changes
  • Phase 3: Test Integrity - Verify no test weakening
  • Phase 4: Code Quality - Review implementation details
  • Phase 5: Backlog Compliance - Rate against BACKLOG.md criteria
  • Provide final assessment and recommendation

Root Cause Analysis

Problem Being Solved: This PR addresses code quality debt by adopting previously unused helper functions across the codebase. The helpers (named_child_text, find_enclosing_type_name, toSymbolRef, batchQuery, etc.) were created in previous versions (v3.3.1–v3.8.0) but never wired up to their intended consumers, inflating the dead symbol count.

Why This Approach: The approach is well-justified - rather than removing the helpers, the PR completes their adoption, reducing code duplication and standardizing patterns across extractors. This follows the principle of DRY (Don't Repeat Yourself) and improves maintainability.

Risk Assessment: LOW RISK - The changes are primarily mechanical refactoring that replaces inline boilerplate with existing tested helpers. The error-throwing changes (ParseError, BoundaryError) improve error handling robustness.

Backlog Compliance

  • Zero-dep: ✓ — No new runtime dependencies added
  • Foundation-aligned: ✓ — Fully complies with core principles; improves code quality without breaking API contracts
  • Problem-fit: 4 — Improves maintainability and reduces technical debt, which aids AI agent code comprehension and reduces hallucinated dependencies
  • Breaking: No — All changes are internal refactoring; external API remains unchanged
  • Tier: 1 (zero-dep ✓ + foundation-aligned ✓)

Phase 2: Configuration Changes ✓

No high-risk configuration changes detected:

  • No linting rules disabled or relaxed
  • No test timeouts increased or coverage thresholds lowered
  • No build configuration or module resolution modified
  • No TypeScript strict mode flags disabled
  • All changed files are source code, not configuration

Phase 3: Test Integrity ✓

Tests are strengthened, not weakened:

  • Only one test file modified (boundaries.test.ts)
  • Change replaces expect(() => ...).not.toThrow() with expect(() => ...).toThrow(/Invalid boundary configuration/)
  • This strengthens test assertions by verifying the new BoundaryError throwing behavior
  • Test count remains identical (975 unit + 564 integration = 1539 tests total)
  • All existing tests pass according to PR description

Phase 4: Code Quality ✓

Rust Extractor Changes (crates/codegraph-core/src/extractors/*.rs):

  • ✅ Excellent: Adopts named_child_text helper across 27 sites, replacing node.child_by_field_name("X").map(|n| node_text(&n, source)) boilerplate
  • ✅ Good cleanup: cpp.rs migrates from custom find_cpp_parent_class to existing find_enclosing_type_name (-14 lines)
  • ✅ Consistent pattern: All extractors now use the same helper for getting child field text

TypeScript Utilities (src/shared/normalize.ts):

  • ✅ Good addition: New toSymbolRef utility adopted at 15 sites, standardizing { name, kind, file, line } object creation
  • ✅ Single responsibility: Function has clear, focused purpose with good type safety

Error Handling Improvements:

  • ✅ Robust: ParseError now throws structured errors with file and cause instead of bare re-throws (parser.ts:972722625ce)
  • ✅ Proper boundaries: BoundaryError now throws on invalid config instead of silently returning empty results (boundaries.ts:c792a284)
  • ✅ Graceful handling: Callers (manifesto.ts, diff-impact.ts) handle the new errors appropriately

CLI Enhancements:

  • ✅ Feature completion: codegraph structure gains --modules/--threshold flags, wiring existing but unused functionality
  • ✅ DRY improvement: codegraph batch uses existing batchQuery function instead of duplicated routing logic

Potential Issues: None identified

  • No security concerns (no command injection, SQL injection, or secret exposure)
  • No performance regressions (changes are mechanical substitutions)
  • No breaking changes to public APIs

Critical Concerns

None. This is a well-executed technical debt cleanup.

Final Recommendation

  • Rating: ⭐⭐⭐⭐☆ (4/5)
  • Action: APPROVE
  • Reasoning: High-quality refactoring that reduces technical debt, improves code consistency, and strengthens error handling. The mechanical nature of most changes minimizes risk, while the structured approach (28 files changed systematically) demonstrates careful execution. The single test file change actually strengthens assertions. This is exactly the type of maintenance work that keeps codebases healthy.

Minor suggestions for future PRs:

  1. Consider breaking large refactoring PRs (28 files) into smaller logical chunks for easier review
  2. The PR title could be more specific: "refactor: adopt dead helpers" → "refactor: wire up unused tree-sitter and utility helpers"

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 8, 2026

Greptile Summary

This PR completes the adoption of previously-dead helpers across the codebase: named_child_text in 11 Rust extractors, toSymbolRef at 15 TypeScript mapping sites, find_enclosing_type_name replacing the hand-rolled find_cpp_parent_class, and structural wiring for ParseError, BoundaryError, batchQuery, --modules/--threshold flags, and the runAnalyses engine path in detect-changes. The previously-flagged status: 'pass' issue in manifesto.ts is fixed to status: 'warn'.

Confidence Score: 5/5

Safe to merge — all changes are mechanical dead-helper adoption with no behavioral regressions; the only open finding is a P2 range check suggestion.

All 28 changed files are refactors of existing, previously-dead helpers. The previously-flagged status: 'pass' issue is resolved. The callers exception in dependencies.ts is correctly documented. Tests pass (975 unit + 564 integration). The single remaining comment is a non-blocking P2 input-validation suggestion.

src/cli/commands/structure.ts — minor threshold range validation gap (P2)

Vulnerabilities

No security concerns identified. The changes are purely refactoring and dead-helper adoption with no new external inputs, credential handling, or untrusted data paths introduced.

Important Files Changed

Filename Overview
src/shared/normalize.ts Adds toSymbolRef utility — a simple 4-field picker that replaces inline object literals at 15 call sites. Clean addition with no risk.
src/cli/commands/batch.ts Removes the local isMultiBatch type guard and MultiBatchItem interface in favor of the equivalent logic already present in batchQuery; routing is identical.
src/cli/commands/structure.ts Wires --modules/--threshold flags calling the pre-existing moduleBoundariesData/formatModuleBoundaries; NaN is checked but threshold range [0,1] is not validated.
src/features/boundaries.ts Changes silent debug+return to throw BoundaryError for invalid config and DB failures; callers updated accordingly with try/catch surfacing warn status.
src/features/manifesto.ts Wraps evaluateBoundaries in try/catch and reports status: 'warn' on error (previously 'pass'), fixing the previously-flagged silent-pass issue.
src/domain/graph/builder/stages/detect-changes.ts Replaces two separate conditional imports with a single runAnalyses call using explicit flags; behavior is equivalent.
src/domain/parser.ts Wraps bare re-throw in a structured ParseError with file and cause for required-parser failures; non-required parsers still warn-and-skip.
src/domain/analysis/dependencies.ts Adopts toSymbolRef for callees/candidates; deliberately skips it for callers (extra viaHierarchy field) — correctly commented.
crates/codegraph-core/src/extractors/cpp.rs Removes hand-rolled find_cpp_parent_class (14 lines) and replaces its single call site with find_enclosing_type_name; semantically identical.
crates/codegraph-core/src/extractors/helpers.rs find_enclosing_type_name and extract_constructor_name/extract_call_name now use named_child_text internally; logic is equivalent.
tests/unit/boundaries.test.ts Test updated to expect BoundaryError throw instead of empty-result return on invalid config; correctly reflects the new behavior.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    subgraph Rust ["Rust extractors (11 files)"]
        R1["named_child_text\nreplaces child_by_field_name boilerplate\n(27 sites)"]
        R2["find_enclosing_type_name\nreplaces find_cpp_parent_class\n(cpp.rs)"]
    end
    subgraph TS ["TypeScript domain/features"]
        T1["toSymbolRef\nreplaces inline {name,kind,file,line}\n(15 sites, 7 files)"]
        T2["ParseError structured throw\n(parser.ts doLoadLanguage)"]
        T3["BoundaryError throw\n(boundaries.ts)"]
        T4["try/catch → status: warn\n(manifesto.ts)"]
        T5["batchQuery\nreplaces isMultiBatch + dual-path\n(batch.ts)"]
        T6["runAnalyses\nreplaces buildCFGData + buildDataflowEdges\n(detect-changes.ts)"]
        T7["--modules / --threshold\nwires moduleBoundariesData\n(structure.ts)"]
    end
    T3 -->|"throws"| T4
    T1 --> normalize["shared/normalize.ts"]
    R1 --> helpers["helpers.rs"]
    R2 --> helpers
Loading

Reviews (2): Last reviewed commit: "fix: address review feedback on dead hel..." | Re-trigger Greptile

Comment on lines +423 to +432
} catch (e: unknown) {
debug(`boundary check failed: ${(e as Error).message}`);
ruleResults.push({
name: 'boundaries',
level: 'graph',
status: 'pass',
thresholds: effectiveThresholds,
violationCount: 0,
});
return;
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 Invalid config silently reports pass

When evaluateBoundaries throws a BoundaryError because the boundary config is invalid (e.g. empty modules, unknown rule target), this catch block pushes status: 'pass' — the user's CI gate will green-light a run that never actually checked boundaries. A 'warn' status (or a re-thrown error when the cause is a config error rather than a DB error) would surface the misconfiguration without breaking unrelated checks.

Suggested change
} catch (e: unknown) {
debug(`boundary check failed: ${(e as Error).message}`);
ruleResults.push({
name: 'boundaries',
level: 'graph',
status: 'pass',
thresholds: effectiveThresholds,
violationCount: 0,
});
return;
} catch (e: unknown) {
debug(`boundary check failed: ${(e as Error).message}`);
ruleResults.push({
name: 'boundaries',
level: 'graph',
status: 'warn',
thresholds: effectiveThresholds,
violationCount: 0,
});
return;
}

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 in d6e25a6 -- the catch block now reports status: 'warn' instead of 'pass', so invalid boundary configs surface in the manifesto output rather than silently passing.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 8, 2026

Codegraph Impact Analysis

40 functions changed110 callers affected across 48 files

  • match_c_node in crates/codegraph-core/src/extractors/c.rs:175 (0 transitive callers)
  • handle_cpp_function_definition in crates/codegraph-core/src/extractors/cpp.rs:200 (1 transitive callers)
  • handle_cpp_call_expression in crates/codegraph-core/src/extractors/cpp.rs:336 (1 transitive callers)
  • handle_invocation_expr in crates/codegraph-core/src/extractors/csharp.rs:210 (1 transitive callers)
  • handle_call_expr in crates/codegraph-core/src/extractors/go.rs:197 (1 transitive callers)
  • find_enclosing_type_name in crates/codegraph-core/src/extractors/helpers.rs:74 (27 transitive callers)
  • extract_constructor_name in crates/codegraph-core/src/extractors/helpers.rs:540 (5 transitive callers)
  • extract_call_name in crates/codegraph-core/src/extractors/helpers.rs:599 (5 transitive callers)
  • handle_method_invocation in crates/codegraph-core/src/extractors/java.rs:265 (1 transitive callers)
  • extract_new_expr_type_name in crates/codegraph-core/src/extractors/javascript.rs:41 (1 transitive callers)
  • extract_call_info in crates/codegraph-core/src/extractors/javascript.rs:868 (3 transitive callers)
  • handle_member_call in crates/codegraph-core/src/extractors/php.rs:256 (1 transitive callers)
  • handle_scoped_call in crates/codegraph-core/src/extractors/php.rs:269 (1 transitive callers)
  • handle_call in crates/codegraph-core/src/extractors/python.rs:114 (1 transitive callers)
  • extract_python_parameters in crates/codegraph-core/src/extractors/python.rs:197 (2 transitive callers)
  • extract_python_type_name in crates/codegraph-core/src/extractors/python.rs:309 (1 transitive callers)
  • handle_call in crates/codegraph-core/src/extractors/ruby.rs:113 (1 transitive callers)
  • find_current_impl in crates/codegraph-core/src/extractors/rust_lang.rs:20 (2 transitive callers)
  • handle_call_expr in crates/codegraph-core/src/extractors/rust_lang.rs:183 (1 transitive callers)
  • extract_rust_use_path in crates/codegraph-core/src/extractors/rust_lang.rs:306 (2 transitive callers)

- manifesto.ts: report 'warn' instead of 'pass' when boundary check throws
- structure.ts: validate --threshold flag rejects non-numeric input
- dependencies.ts: clarify intentional skip of toSymbolRef for callers
@carlos-alm
Copy link
Copy Markdown
Contributor Author

Addressed all three Greptile findings in d6e25a6:

  1. manifesto.ts pass-on-error (P2 inline): Changed status: 'pass' to status: 'warn' in the boundary check catch block so invalid configs are surfaced.

  2. structure.ts --threshold NaN (P2 out-of-diff): Added a Number.isNaN guard after parseFloat — now exits with an error message if the value is non-numeric.

  3. dependencies.ts callers asymmetry (P2 out-of-diff): Added a comment explaining the intentional skip of toSymbolRef for callers (they include the extra viaHierarchy field).

@carlos-alm
Copy link
Copy Markdown
Contributor Author

@greptileai

Forge extracts helpers but never completes the adoption loop — dead
symbol count inflates with every run. Grind closes the gap by finding
dead helpers from forge, classifying them (adopt/re-export/promote/
false-positive/remove), wiring them into consumers, and gating on a
non-positive dead-symbol delta.

Pipeline is now: recon → gauntlet → sync → forge → grind → close
- Track currentTarget, processedTargets, failedTargets in state for
  mid-run resume after interruption
- Persist grind classifications to grind-targets.ndjson (append-only)
  so re-runs skip already-analyzed targets
- Write titan-state.json after every target, not just at phase end
- Add interrupted-mid-target recovery logic in edge cases
- Use codegraph audit/context/fn-impact/where/query/ast before edits
- Add codegraph diff-impact --staged before commits
- Add codegraph build after edits to keep graph current
- Add --target flag for retrying individual failures
@carlos-alm carlos-alm merged commit 3cb4260 into main Apr 8, 2026
18 of 19 checks passed
@carlos-alm carlos-alm deleted the feat/adopt-dead-helpers branch April 8, 2026 04:16
@github-actions github-actions bot locked and limited conversation to collaborators Apr 8, 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