Skip to content

Phase 1: Core suggest engine + --suggest flag + built-in rules #139

@Kadajett

Description

@Kadajett

Overview

Implement the core recommendations engine as src/suggest/ module with the --suggest global CLI flag and all 6 built-in recommendation types.

Parent research: #135

Implementation Steps

1. Create src/suggest/types.rs

Define core types:

pub struct Recommendation {
    pub id: String,
    pub category: Category,
    pub severity: Severity,
    pub confidence: f64,      // 0.0 - 1.0
    pub title: String,
    pub description: String,
    pub symbols: Vec<SymbolRef>,  // from src/duplicate/mod.rs
    pub suggestion: Option<String>,
}

pub enum Category {
    CombineFunctions,
    Naming,
    Complexity,
    DeadCode,
    ModuleOrganization,
    TypeNarrowing,
    Custom(String),
}

pub enum Severity { Info, Warning, Error }

2. Create src/suggest/mod.rs — Engine orchestrator

pub struct SuggestEngine {
    rules: Vec<Box<dyn SuggestRule>>,
}

pub struct SuggestContext<'a> {
    pub symbols: &'a [FunctionSignature],
    pub call_edges: &'a [(String, String)],
    pub duplicates: &'a [DuplicateGroup],
    pub modules: &'a [ModuleInfo],
    pub scope: &'a SuggestScope,
}

pub trait SuggestRule: Send + Sync {
    fn id(&self) -> &str;
    fn category(&self) -> Category;
    fn evaluate(&self, ctx: &SuggestContext) -> Vec<Recommendation>;
}

impl SuggestEngine {
    pub fn new() -> Self { /* register all built-in rules */ }
    pub fn run(&self, ctx: &SuggestContext) -> Vec<Recommendation> { /* run all rules, sort by confidence */ }
}

3. Implement 6 built-in rules in src/suggest/rules/

Each as a separate file implementing SuggestRule:

  • combine.rs — Wraps DuplicateDetector results. Confidence = similarity score. Only suggest when similarity > 0.7 AND functions share call graph nodes.
  • dead_code.rs — Walk call graph to find symbols with 0 callers. Skip framework entry points (SymbolInfo.framework_entry_point). Confidence: 1.0 for zero callers + not exported; 0.7 for zero callers + exported.
  • complexity.rs — Flag functions with >5 control flow constructs or >10 calls. Suggest split points based on call clustering. Confidence proportional to complexity score.
  • naming.rs — Compare symbol name tokens against actual behavior (calls made, return type). Flag when name suggests one thing but implementation does another. Lower confidence (0.4-0.7) since naming is subjective.
  • module_org.rs — For each function, count intra-module vs cross-module calls. If >70% of calls go to a different module, suggest moving. Confidence = cross-module ratio.
  • type_narrow.rs — Find any/Object/generic types in arguments where the function body only uses specific methods. Confidence: 1.0 for clear narrowing; 0.5 for heuristic.

4. Add --suggest global flag to CLI

In src/cli.rs, add to Cli struct:

#[arg(long, global = true)]
pub suggest: bool,

In src/commands/mod.rs, add to CommandContext:

pub suggest: bool,

5. Integrate with existing commands

In commands that support suggestions (validate, analyze, query overview):

  • After main output, if ctx.suggest is true, load index data, build SuggestContext, run engine
  • Append recommendations to output in appropriate format

6. Output formatting

  • text: Section header \n--- Suggestions ---\n followed by formatted recommendations
  • toon: Append suggestions[N]: block with confidence, id, title, description
  • json: Add "suggestions": [...] array to the response object

7. MCP integration

Add optional suggest: bool parameter to relevant MCP tools (validate, get_overview). When true, include recommendations in response.

Testing

  • Unit tests for each rule with known-good/known-bad symbol data
  • Integration test: semfora-engine validate --duplicates --suggest on test fixtures
  • Test that --suggest produces no output change when no recommendations apply
  • Test all 3 output formats

Performance Target

--suggest should add <50ms to any command on a 50K-function repo. All data comes from the already-loaded index.

Files to create/modify

  • Create: src/suggest/mod.rs, src/suggest/types.rs, src/suggest/rules/*.rs
  • Modify: src/cli.rs (add flag), src/commands/mod.rs (add to context), src/commands/validate.rs, src/commands/analyze.rs (integrate suggest), src/main.rs (wire up), src/mcp_server/helpers.rs (add to MCP tools)
  • Tests: tests/suggest/ directory with unit + integration tests

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions