Skip to content

refactor(presentation): extract shared rendering helpers in cfg and flow#1234

Merged
carlos-alm merged 4 commits into
mainfrom
refactor/titan-abstraction-presentation
May 27, 2026
Merged

refactor(presentation): extract shared rendering helpers in cfg and flow#1234
carlos-alm merged 4 commits into
mainfrom
refactor/titan-abstraction-presentation

Conversation

@carlos-alm

Copy link
Copy Markdown
Contributor

Summary

  • Extracts shared rendering helpers for cfg and flow presentation modules
  • Independent of all other Titan PRs

Commits

  • a132635: refactor(presentation): extract shared rendering helpers in cfg and flow

Context

Part of the Titan Paradigm cleanup pass (see .codegraph/titan/TITAN_REPORT.md). Merge order: this PR is #6 of 10 (mergeOrder position: 6).

Caveats

  • WASM grammars not available in dev worktree — CI will run full test matrix

Test plan

  • CI passes (lint, build, full test matrix)
  • Verify no new cycles introduced (codegraph stats)

@claude

claude Bot commented May 27, 2026

Copy link
Copy Markdown

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


PR Review Complete ✓

Reviewing PR #1234: refactor(presentation): extract shared rendering helpers in cfg and flow

Todo List:

  • Read and analyze changed files (cfg.ts and flow.ts)
  • Phase 1: Root cause analysis
  • Phase 2: Configuration change detection
  • Phase 3: Test integrity check
  • Phase 4: Code quality assessment
  • Phase 5: Backlog compliance evaluation
  • Provide final structured assessment

Root Cause Analysis

Problem Being Solved: This PR addresses technical debt by extracting inline rendering logic into dedicated helper functions. Both src/presentation/cfg.ts and src/presentation/flow.ts had complex inline logic scattered throughout their main export functions.

Why This Approach: The refactoring follows clean code principles by extracting functions like renderBlockLocation(), printCfgBlocks(), printCfgEdges(), printFlowHeader(), printFlowSteps(), etc. This improves readability and reusability while maintaining identical behavior.

Risk Assessment: Very Low - This is a pure extract-method refactoring with no behavioral changes. The public API signatures remain identical.

Configuration Changes Detection

No high-risk changes detected

  • No biome/linting rule modifications
  • No test timeouts or coverage threshold changes
  • No build configuration changes
  • No TypeScript strict mode modifications

Test Integrity

No test integrity concerns

  • No test files were modified (confirmed via git diff)
  • No test expectations were weakened or removed
  • No new test requirements introduced (pure refactoring)

Code Quality Assessment

High quality refactoring

Strengths:

  • Clean extraction: All helper functions have single responsibilities (renderBlockLocation, printCfgBlocks, printFlowHeader)
  • Proper TypeScript: Added proper type definitions (CfgData = ReturnType<typeof cfgData>, comprehensive interfaces)
  • Consistent naming: Functions follow clear naming patterns (print*, render*, tryRender*)
  • Zero behavior change: Unicode character fixes (\u26A0, \u2500) are cosmetic improvements only
  • Maintained error handling: All existing error conditions and console outputs preserved

Minor observations:

  • Consistent patterns: Both files follow identical refactoring patterns, suggesting systematic approach
  • Type safety: Addition of proper interfaces (FlowNode, FlowStep, FlowCycle, etc.) improves maintainability

Backlog Compliance

Zero-dep: ✅

No new runtime dependencies added. Pure refactoring using existing TypeScript/tree-sitter/SQLite infrastructure.

Foundation-aligned: ✅

Fully aligned with all FOUNDATION.md principles:

  • P1 (always-current): No impact on graph currency
  • P4 (zero-cost core): No performance impact, improves readability
  • P5 (embeddable-first): Maintains identical programmatic API
  • P8 (not an agent): Pure presentation layer refactoring

Problem-fit: 3/5

Indirectly addresses the core problem by improving code maintainability. While it doesn't directly reduce token waste or prevent hallucinated dependencies, cleaner presentation code makes the codebase easier for AI agents to understand and modify.

Breaking: No

Zero breaking changes. All function signatures, CLI outputs, and APIs remain identical.

Tier: 1 (Zero-dep ✓ + Foundation-aligned ✓)

Critical Concerns

None identified. This is exemplary refactoring work.

Final Recommendation

  • Rating: ⭐⭐⭐⭐☆ (4/5)
  • Action: APPROVE
  • Reasoning: High-quality extract-method refactoring that improves code organization with zero risk. The systematic approach across both files, proper TypeScript typing, and maintained functionality demonstrate careful engineering. This is exactly the kind of technical debt cleanup that keeps codebases healthy.

Minor recommendation: Consider this pattern as a model for similar presentation layer refactoring across other commands in the codebase.


@greptile-apps

greptile-apps Bot commented May 27, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This refactor extracts shared rendering helpers from cfg.ts and flow.ts into focused private functions, replacing inline logic with named helpers and replacing Unicode escape sequences with literal characters. The behavioral contract is preserved across both files.

  • cfg.ts: Introduces renderBlockLocation, printCfgBlocks, printCfgEdges, printCfgEntry, and tryRenderGraphFormat; the main cfg() function is now a concise orchestrator with no change to output.
  • flow.ts: Adds typed interfaces (FlowResult, FlowStep, FlowCycle, EntryPoint, FlowNode) replacing as any casts, and extracts runListEntryPoints, printFlowHeader, printFlowSteps, and printFlowCycles; printFlowSteps returns a boolean to guard the cycle-output block, correctly restoring the original leaf-node suppression behavior flagged in the prior review.

Confidence Score: 5/5

Safe to merge — this is a pure extraction refactor with no logic changes and no new dependencies.

Both files are straightforward extractions of inline logic into named helpers. The printFlowSteps boolean-return pattern correctly gates printFlowCycles so leaf-node output suppression is preserved. The typed interfaces in flow.ts remove the as-any casts without changing runtime behavior. No data paths are added, removed, or reordered.

No files require special attention.

Important Files Changed

Filename Overview
src/presentation/cfg.ts Extracts rendering helpers (renderBlockLocation, printCfgBlocks, printCfgEdges, printCfgEntry, tryRenderGraphFormat); replaces unicode escapes with literal characters; logic is functionally equivalent to the original
src/presentation/flow.ts Adds typed interfaces (FlowResult, FlowStep, FlowCycle, etc.) and extracts runListEntryPoints, printFlowHeader, printFlowSteps, printFlowCycles, isLeafNode; printFlowSteps returns boolean to guard cycle output, correctly restoring original leaf-node suppression behavior

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    subgraph cfg_ts["cfg.ts — cfg()"]
        C1[outputResult] -->|handled| CRET1[return]
        C1 -->|not handled| C2{data.warning?}
        C2 -->|yes| CRET2[return]
        C2 -->|no| C3{results empty?}
        C3 -->|yes| CRET3[return]
        C3 -->|no| C4[tryRenderGraphFormat]
        C4 -->|dot / mermaid| CRET4[return]
        C4 -->|text| C5[for each result: printCfgEntry]
        C5 --> C6[printCfgBlocks]
        C5 --> C7[printCfgEdges]
        C6 --> C8[renderBlockLocation]
    end

    subgraph flow_ts["flow.ts — flow()"]
        F0{opts.list?} -->|yes| F1[runListEntryPoints]
        F1 --> FRET0[return]
        F0 -->|no| F2{name?}
        F2 -->|no| FRET1[return]
        F2 -->|yes| F3[flowData]
        F3 --> F4[outputResult]
        F4 -->|handled| FRET2[return]
        F4 -->|not handled| F5{data.entry?}
        F5 -->|no| FRET3[return]
        F5 -->|yes| F6[printFlowHeader]
        F6 --> F7[printFlowSteps]
        F7 -->|isLeaf=true| FRET4[return — cycles suppressed]
        F7 -->|isLeaf=false| F8[printFlowCycles]
    end
Loading

Reviews (5): Last reviewed commit: "Merge branch 'main' into refactor/titan-..." | Re-trigger Greptile

Comment thread src/presentation/flow.ts Outdated
Comment on lines +93 to +105
function printFlowSteps(data: FlowResult): void {
if (data.steps.length === 0) {
console.log(' (leaf node — no callees)');
return;
}

for (const step of data.steps) {
console.log(` depth ${step.depth}:`);
for (const n of step.nodes) {
const isLeaf = data.leaves.some(
(l: { name: string; file: string }) => l.name === n.name && l.file === n.file,
);
const leafTag = isLeaf ? ' [leaf]' : '';
const leafTag = isLeafNode(n, data.leaves) ? ' [leaf]' : '';
console.log(` [${kindIcon(n.kind)}] ${n.name} ${n.file}:${n.line}${leafTag}`);
}
}
}

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.

P1 Early-return in printFlowSteps no longer suppresses cycle output

In the original flow(), the return inside the data.steps.length === 0 branch exited the entire outer function, so printFlowCycles was never reached for leaf nodes. After the refactor, printFlowSteps returns from itself, and flow() unconditionally calls printFlowCycles(data.cycles) afterward. If the back-end ever emits a non-empty cycles array for a node whose steps is empty (e.g. a directly self-recursive function where traversal stops at depth 0), the output will now include a "Cycles detected" block that the old code silently suppressed — a visible regression in CLI output.

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. printFlowSteps now returns boolean (true = leaf node, false = steps printed). flow() guards printFlowCycles behind if (!isLeaf), restoring the original behavior where a leaf node suppresses cycle output entirely. Commit: f7e884e

@github-actions

github-actions Bot commented May 27, 2026

Copy link
Copy Markdown
Contributor

Codegraph Impact Analysis

32 functions changed20 callers affected across 12 files

  • renderBlockLocation in src/presentation/cfg.ts:41 (3 transitive callers)
  • printCfgBlocks in src/presentation/cfg.ts:47 (10 transitive callers)
  • printCfgEdges in src/presentation/cfg.ts:56 (10 transitive callers)
  • printCfgEntry in src/presentation/cfg.ts:64 (12 transitive callers)
  • tryRenderGraphFormat in src/presentation/cfg.ts:72 (12 transitive callers)
  • cfg in src/presentation/cfg.ts:84 (14 transitive callers)
  • EntryPoint.kind in src/presentation/flow.ts:20 (0 transitive callers)
  • EntryPoint.name in src/presentation/flow.ts:21 (0 transitive callers)
  • EntryPoint.file in src/presentation/flow.ts:22 (0 transitive callers)
  • EntryPoint.line in src/presentation/flow.ts:23 (0 transitive callers)
  • FlowNode.kind in src/presentation/flow.ts:27 (0 transitive callers)
  • FlowNode.name in src/presentation/flow.ts:28 (0 transitive callers)
  • FlowNode.file in src/presentation/flow.ts:29 (0 transitive callers)
  • FlowNode.line in src/presentation/flow.ts:30 (0 transitive callers)
  • FlowStep.depth in src/presentation/flow.ts:34 (0 transitive callers)
  • FlowStep.nodes in src/presentation/flow.ts:35 (0 transitive callers)
  • FlowCycle.from in src/presentation/flow.ts:39 (0 transitive callers)
  • FlowCycle.to in src/presentation/flow.ts:40 (0 transitive callers)
  • FlowCycle.depth in src/presentation/flow.ts:41 (0 transitive callers)
  • FlowResult.entry in src/presentation/flow.ts:45 (0 transitive callers)

@carlos-alm

Copy link
Copy Markdown
Contributor Author

@greptileai

@carlos-alm carlos-alm merged commit 74c326b into main May 27, 2026
21 checks passed
@carlos-alm carlos-alm deleted the refactor/titan-abstraction-presentation branch May 27, 2026 23:58
@github-actions github-actions Bot locked and limited conversation to collaborators May 27, 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