Skip to content

refactor: resolve three architecture issues after #456 and #458#459

Merged
carlos-alm merged 11 commits intomainfrom
refactor/arch-cleanup
Mar 16, 2026
Merged

refactor: resolve three architecture issues after #456 and #458#459
carlos-alm merged 11 commits intomainfrom
refactor/arch-cleanup

Conversation

@carlos-alm
Copy link
Contributor

Summary

Resolves three structural issues left over after the src/ reorganization in #456 and #458:

  • commands/presentation/: Moved 16 CLI formatter files from src/commands/ into src/presentation/ where they belong as presentation concerns. The src/commands/ directory is deleted entirely. Updated all 15 dynamic imports in src/cli/commands/.
  • queries-cli.js split: Split the 866-LOC presentation/queries-cli.js into 5 thematic modules under presentation/queries-cli/: path.js, overview.js, inspect.js, impact.js, exports.js. A barrel queries-cli.js re-exports everything for backward compatibility — zero import changes needed in consumers.
  • Viewer naming collision: Renamed features/viewer.jsfeatures/graph-enrichment.js to disambiguate from presentation/viewer.js (HTML renderer). Fixed a broken import in cli/commands/plot.js that referenced the deleted src/viewer.js.
  • Fixed wrong relative import in presentation/query.js (../presentation/./)
  • Updated CLAUDE.md architecture table

Test plan

  • npm test — 1862 tests pass (104 files, 6 skipped)
  • npx biome check src/ tests/ — 0 lint issues
  • ls src/commands/ — directory does not exist
  • Only cli.js and index.js at src/ root

* refactor: reorganize src/ into domain/, features/, presentation/ layers

Move source files into a domain-driven directory structure:
- src/domain/ — core graph building, queries, analysis, search (embeddings)
- src/features/ — composable feature modules (audit, check, complexity, etc.)
- src/presentation/ — CLI formatting and output rendering
- src/db/ — database layer (db.js → db/index.js)

All 199 files updated with corrected import paths.
1858 tests pass, 0 cycles, all manifesto rules green.

Impact: 22 functions changed, 5 affected

* docs: update CLAUDE.md architecture table for new directory structure

Update file paths in the architecture table to reflect the domain/,
features/, presentation/, db/ reorganization. Addresses Greptile review.

* refactor: move remaining flat src/ files into subdirectories

Move 12 remaining files out of flat src/ so only cli.js and index.js
remain as entry points:
- config, logger, native, registry, update-check → infrastructure/
- constants, errors, kinds, paginate → shared/
- parser → domain/
- journal, change-journal → domain/graph/

Update all import paths across src/ and tests/.
Update CLAUDE.md architecture table to match.

Impact: 9 functions changed, 17 affected

* style: fix import ordering after file moves
- Rename features/viewer.js → features/graph-enrichment.js to resolve
  naming collision with presentation/viewer.js (Issue 3)
- Move 16 CLI formatter files from commands/ → presentation/ where they
  belong as presentation concerns, delete commands/ directory (Issue 1)
- Split 866-LOC presentation/queries-cli.js into thematic modules:
  path.js, overview.js, inspect.js, impact.js, exports.js (Issue 2)
- Fix broken import in cli/commands/plot.js (was referencing deleted
  src/viewer.js, now correctly points to features/graph-enrichment.js)
- Fix wrong relative import in presentation/query.js
- Update CLAUDE.md architecture table to reflect new structure

Impact: 29 functions changed, 1 affected
@claude
Copy link

claude bot commented Mar 16, 2026

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


PR Review Complete

Reviewing PR #459: refactor: resolve three architecture issues after #456 and #458

Root Cause Analysis

Problem Being Solved: This PR addresses legitimate architectural inconsistencies left over from recent src/ reorganization (#456, #458):

  1. Misplaced CLI formatters: 16 files in src/commands/ were presentation concerns that should live in src/presentation/ per the layered architecture
  2. Monolithic queries-cli.js: 866-line file violated single responsibility principle and made the codebase harder to navigate
  3. Naming collision: Two viewer.js files created ambiguous imports and broken references

Why This Approach: The solution is systematic and minimal:

  • Moves files to their correct architectural layer without changing functionality
  • Splits large file by logical concerns with backward-compatible barrel export (866 LOC → 5 focused modules: 46+198+334+197+58 lines)
  • Uses clear, descriptive names to eliminate ambiguity
  • Updates all import paths consistently across 15 CLI command files

Risk Assessment: ⚠️ LOW RISK - Pure refactoring with no functional changes.

Backlog Compliance

  • Zero-dep: ✓ — no new runtime dependencies, builds on existing tree-sitter/SQLite/AST infrastructure
  • Foundation-aligned: ✓ — fully compliant with FOUNDATION.md principles; maintains embeddable-first design (P5), preserves always-current graph pipeline (P1), purely structural refactoring aligns with core architecture
  • Problem-fit: 2 — organizational improvement but doesn't directly address the core problem of AI agents wasting tokens on codebase orientation
  • Breaking: No — backward-compatible barrel exports maintain all existing import paths
  • Tier: 1 (zero-dep ✓ + foundation-aligned ✓)

Critical Concerns

None. This is exemplary refactoring work:

Phase 2 - Configuration: No risky changes (Biome rules, test thresholds, build config all unchanged)
Phase 3 - Test Integrity: Only import path updates, no weakened assertions or skipped tests
Phase 4 - Code Quality: Clean separation of concerns, consistent naming, proper layered architecture
Phase 5 - Compliance: Tier 1 feature, non-breaking, foundation-aligned

The split follows clear thematic boundaries:

  • path.js (58 LOC) - symbolPath queries
  • overview.js (197 LOC) - stats, moduleMap, roles
  • inspect.js (334 LOC) - where, queryName, context, children, explain
  • impact.js (198 LOC) - fileDeps, fnDeps, impactAnalysis, fnImpact, diffImpact
  • exports.js (46 LOC) - fileExports

Final Recommendation

  • Rating: ⭐⭐⭐⭐☆ (4/5)
  • Action: APPROVE
  • Reasoning: High-quality architectural cleanup that resolves real inconsistencies from previous PRs. Maintains backward compatibility, follows established patterns, and improves code organization without changing functionality. The only reason this isn't 5/5 is that it's organizational rather than feature work — but it's exactly the kind of foundational cleanup that enables future development.

- Rename features/viewer.js → features/graph-enrichment.js to resolve
  naming collision with presentation/viewer.js (Issue 3)
- Move 16 CLI formatter files from commands/ → presentation/ where they
  belong as presentation concerns, delete commands/ directory (Issue 1)
- Split 866-LOC presentation/queries-cli.js into thematic modules:
  path.js, overview.js, inspect.js, impact.js, exports.js (Issue 2)
- Fix broken import in cli/commands/plot.js (was referencing deleted
  src/viewer.js, now correctly points to features/graph-enrichment.js)
- Fix wrong relative import in presentation/query.js
- Update CLAUDE.md architecture table to reflect new structure

Impact: 54 functions changed, 19 affected
@carlos-alm carlos-alm force-pushed the refactor/arch-cleanup branch from ab9a309 to 8f184fe Compare March 16, 2026 09:18
@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 16, 2026

Greptile Summary

This PR completes a three-part architectural cleanup after the src/ reorganisation in #456 and #458, correctly moving 16 CLI formatter files from the now-deleted src/commands/ into src/presentation/, splitting the 866-line queries-cli.js monolith into five focused sub-modules with a backward-compatible barrel, renaming features/viewer.jsfeatures/graph-enrichment.js to resolve a naming collision, and fixing three broken dynamic imports (co-change, communitySummaryForStats, plot).

  • All 15 dynamic imports in src/cli/commands/ have been updated to point at src/presentation/ — no stale ../../commands/ references remain.
  • The queries-cli/ sub-module split is clean: the barrel queries-cli.js re-exports exactly the same 15 symbols as before, so all existing consumers are unaffected.
  • Follow-up fixes for co-change (feature-layer path) and communitySummaryForStats (wrong directory traversal) are correctly applied and confirmed in the diff.
  • src/presentation/query.js is still present at HEAD despite commit 8d77596 ("refactor: remove dead presentation/query.js barrel file") being part of this branch. The file has zero importers and carries a stale comment referencing the deleted src/commands/ path. It appears the deletion was lost during one of the two origin/main merge commits on the branch and should be reinstated before merge.

Confidence Score: 4/5

  • Safe to merge once the lingering src/presentation/query.js dead-code file is confirmed deleted; all functional changes are correct.
  • All import paths are verified correct, 1862 tests pass, biome reports zero lint issues, and the three previously-flagged runtime bugs are fixed. The only outstanding item is src/presentation/query.js being present despite an in-branch commit that intended to delete it — it carries zero importers and a stale doc comment, making it dead code that could confuse future contributors but does not affect runtime behaviour.
  • src/presentation/query.js — should be absent per commit 8d77596 but is still present at HEAD; verify and delete before merging.

Important Files Changed

Filename Overview
src/presentation/queries-cli.js Correctly reduced from 866-line monolith to a clean 27-line backward-compatible barrel re-exporting all 15 functions from ./queries-cli/index.js.
src/presentation/query.js File appears to be dead code (zero importers); intended to be deleted per commit 8d77596 in this branch, but it is still present at HEAD — likely re-introduced by a merge. Stale comment still references the deleted src/commands/ path.
src/presentation/queries-cli/overview.js Dynamic import of communitySummaryForStats was corrected to ../../features/communities.js in a follow-up commit; community stats section is now functional.
src/cli/commands/co-change.js Both broken imports fixed in HEAD (506c30f): feature layer now correctly points to ../../features/cochange.js, formatter to ../../presentation/cochange.js.
src/cli/commands/plot.js Fixed the broken ../../viewer.js import; now correctly imports generatePlotHTML and loadPlotConfig from ../../features/graph-enrichment.js.
src/features/graph-enrichment.js Pure rename of features/viewer.js with no content changes; disambiguates from presentation/viewer.js (HTML renderer). All consumers updated correctly.
src/presentation/queries-cli/index.js Clean barrel that correctly re-exports all 15 functions from the 5 thematic sub-modules; matches the export list in queries-cli.js exactly.
tests/graph/viewer.test.js Test import correctly updated from features/viewer.js to features/graph-enrichment.js to match the rename.
CLAUDE.md Architecture table updated accurately to reflect the new presentation/ layout, queries-cli/ split, and the features/graph-enrichment.js entry.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    subgraph CLI ["src/cli/commands/"]
        A[audit.js]
        B[batch.js]
        C[co-change.js]
        D[plot.js]
        E[check.js / triage.js / ...]
    end

    subgraph PRES ["src/presentation/"]
        F[audit.js / batch.js / cochange.js / ...]
        G[queries-cli.js\n barrel re-export]
        subgraph QC ["queries-cli/"]
            H[path.js]
            I[overview.js]
            J[inspect.js]
            K[impact.js]
            L[exports.js]
            M[index.js]
        end
    end

    subgraph FEAT ["src/features/"]
        N[cochange.js]
        O[graph-enrichment.js\n renamed from viewer.js]
        P[communities.js]
    end

    subgraph DOM ["src/domain/"]
        Q[queries.js]
    end

    A -->|static import| F
    C -->|dynamic import| N
    C -->|dynamic import| F
    D -->|dynamic import| O
    E -->|dynamic import| F

    G --> M
    M --> H & I & J & K & L

    I -->|async import| P
    H & I & J & K & L --> Q

    O -->|imports| PRES
Loading

Last reviewed commit: 506c30f

Comment on lines +1 to +4
/**
* Re-export all query CLI wrappers from queries-cli.js.
* This barrel file provides the standard src/commands/ import path.
*/
Copy link
Contributor

Choose a reason for hiding this comment

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

Stale comment and potential dead code

The comment on line 3 still references src/commands/ which no longer exists:

Suggested change
/**
* Re-export all query CLI wrappers from queries-cli.js.
* This barrel file provides the standard src/commands/ import path.
*/
/**
* Re-export all query CLI wrappers from queries-cli.js.
* This barrel file provides a secondary import path for backward compat.
*/

Additionally, query.js is an exact duplicate of the barrel in queries-cli.js — both re-export the same 15 functions from ./queries-cli/index.js. I confirmed that nothing in the codebase imports presentation/query.js. If there are no external consumers (e.g. the programmatic API), this file could be removed entirely to avoid maintaining two identical barrels.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch — confirmed zero importers. Removed presentation/query.js entirely in 8108e1c rather than just updating the comment.

This file was a duplicate of queries-cli.js with zero importers.
Removes the maintenance burden of keeping two identical barrels in sync.

Addresses Greptile review feedback on #459.

docs check acknowledged
carlos-alm added a commit that referenced this pull request Mar 16, 2026
This file was a duplicate of queries-cli.js with zero importers.
Removes the maintenance burden of keeping two identical barrels in sync.

Addresses Greptile review feedback on #459.

docs check acknowledged
@carlos-alm
Copy link
Contributor Author

@greptileai

Comment on lines +10 to +11
const { communitySummaryForStats } = await import('../communities.js');
data.communities = communitySummaryForStats(customDbPath, { noTests: opts.noTests });
Copy link
Contributor

Choose a reason for hiding this comment

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

Wrong import path for communitySummaryForStats

communitySummaryForStats lives in src/features/communities.js (confirmed by the export at line 160 there and its integration test), but this import resolves to src/presentation/communities.js, which only exports communities. At runtime, communitySummaryForStats will be undefined; calling it immediately throws a TypeError, which the catch block silently swallows. As a result, the community summary section is never populated in codegraph stats output — the feature is silently broken.

The correct path from src/presentation/queries-cli/overview.js to the features layer is:

Suggested change
const { communitySummaryForStats } = await import('../communities.js');
data.communities = communitySummaryForStats(customDbPath, { noTests: opts.noTests });
const { communitySummaryForStats } = await import('../../features/communities.js');
data.communities = communitySummaryForStats(customDbPath, { noTests: opts.noTests });

Note: the misleading comment /* graphology may not be available */ was originally written to guard against an optional peer dependency, but the real guard here is the wrong path. Fixing the path will let the import succeed when features/communities.js is present (it always is), and the catch can remain as a safety net for any genuine runtime failures.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in the latest push — corrected the dynamic import path from ../communities.js to ../../features/communities.js so communitySummaryForStats resolves correctly.

@carlos-alm
Copy link
Contributor Author

@greptileai

@@ -20,7 +20,7 @@ export const command = {
],
async execute([file], opts, ctx) {
const { analyzeCoChanges, coChangeData, coChangeTopData } = await import('../../cochange.js');
Copy link
Contributor

Choose a reason for hiding this comment

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

Broken dynamic import — resolves to non-existent file

'../../cochange.js' from src/cli/commands/co-change.js resolves to src/cochange.js, which does not exist in the repository. The actual functions analyzeCoChanges, coChangeData, and coChangeTopData are exported from src/features/cochange.js. This import will throw a ERR_MODULE_NOT_FOUND at runtime whenever the co-change command is invoked.

This is a pre-existing bug, but since this file is being touched in this PR to update the formatter import on the very next line, it's the right moment to fix the data-layer path too:

Suggested change
const { analyzeCoChanges, coChangeData, coChangeTopData } = await import('../../cochange.js');
const { analyzeCoChanges, coChangeData, coChangeTopData } = await import('../../features/cochange.js');

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed — corrected the dynamic import from \ to .

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 506c30f — corrected the dynamic import path from ../../cochange.js to ../../features/cochange.js.

@carlos-alm carlos-alm force-pushed the refactor/arch-cleanup branch from 67b7735 to 43ff32e Compare March 16, 2026 10:16
# Conflicts:
#	src/cli/commands/batch.js

Impact: 1 functions changed, 0 affected
Impact: 1 functions changed, 0 affected
@carlos-alm
Copy link
Contributor Author

@greptileai

@carlos-alm carlos-alm merged commit 6c2d7fa into main Mar 16, 2026
13 checks passed
@carlos-alm carlos-alm deleted the refactor/arch-cleanup branch March 16, 2026 10:41
@github-actions github-actions bot locked and limited conversation to collaborators Mar 16, 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