Skip to content

Phase 3: Custom recommendation scripts (Rhai + declarative YAML) #143

@Kadajett

Description

@Kadajett

Overview

Enable users to write custom recommendation rules using Rhai scripts or declarative YAML patterns. Rules live in .semfora/rules/ and have access to semfora's index data.

Depends on: #141 (Phase 2)
Parent research: #135

Implementation

1. Add Rhai dependency

In Cargo.toml:

rhai = { version = "1.19", features = ["sync"] }

Rhai is pure Rust, adds ~1MB to binary, sandboxed by default. No filesystem/network access from scripts.

2. Create src/suggest/plugins/mod.rs — Plugin loader

pub struct PluginLoader {
    rhai_engine: rhai::Engine,
}

impl PluginLoader {
    pub fn load_rules_dir(dir: &Path) -> Vec<Box<dyn SuggestRule>> {
        // Scan .semfora/rules/ for .rhai and .yaml files
        // Parse each into a SuggestRule implementation
    }
}

3. Create src/suggest/plugins/rhai_runtime.rs

  • Register custom Rhai types: Symbol, Call, Module (read-only views of index data)
  • Expose query functions: symbols_in_module(name), callers_of(hash), calls_from(hash)
  • Script returns array of recommendation objects

Example Rhai script (.semfora/rules/api-error-handling.rhai):

// Flag API functions without error handling
let results = [];
for sym in symbols_in_module("src.api") {
    let has_error = false;
    for call in sym.calls {
        if call.name.contains("catch") || call.name.contains("error") || call.in_try {
            has_error = true;
            break;
        }
    }
    if !has_error {
        results.push(#{
            id: "api-error-handling",
            title: `${sym.name} has no error handling`,
            confidence: 0.9,
            severity: "warning",
            symbols: [sym.ref],
        });
    }
}
results

4. Create src/suggest/plugins/schema.rs — Declarative YAML rules

Simple pattern-matching rules without scripting:

id: api-error-handling
category: custom
severity: warning
match:
  module_pattern: "src/api/**"
  min_calls: 1
  missing_calls: ["catch", "try", "error"]
message: "Function {symbol} in {module} has no error handling"
confidence: 0.8

Support match conditions: module_pattern, name_pattern, min_complexity, min_calls, missing_calls, has_decorator, is_exported, is_async.

5. Configuration

In semfora.toml:

[suggest.plugins]
rules_dir = ".semfora/rules"    # default
enabled = true

6. Documentation

Create .semfora/rules/README.md template explaining:

  • Available Rhai functions and types
  • YAML schema reference
  • Example rules for common patterns

Testing

  • Test Rhai script loading and execution
  • Test YAML declarative rule parsing
  • Test that malicious Rhai scripts can't access filesystem
  • Test error handling for invalid scripts
  • Integration test with sample rules directory

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions