car-reason 0.24.1

Code reasoning engine for Common Agent Runtime — adaptive, graph-driven, learning
docs.rs failed to build car-reason-0.24.1
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
Visit the last successful build: car-reason-0.23.0

car-reason

Code reasoning engine for Common Agent Runtime. Adaptive, graph-driven, learning.

What it does

Instead of a hardcoded "diagnose → suggest → explain" pipeline, reasoning actions are skills in the memgine graph. The graph's spreading activation and success/failure tracking determine which actions to run, in what order, routed to which models. As outcomes accumulate, the routing improves without code changes.

Usage

use std::sync::{Arc, Mutex};
use car_reason::ReasoningSession;

let inference = Arc::new(car_inference::InferenceEngine::new(Default::default()));
let mut memgine = car_memgine::MemgineEngine::new(None);

// Seed the default reasoning skills
car_reason::skills::seed_defaults(&mut memgine);

let memgine = Arc::new(Mutex::new(memgine));
let session = ReasoningSession::new(memgine, inference);
let result = session.reason("fix the off-by-one error in parse_header").await?;

println!("Diagnosis: {}", result.diagnosis);
for s in &result.suggestions {
    println!("Fix: {}", s.suggested);
}
println!("Explanation: {}", result.explanation);

Where it fits

A higher-level capability over car-memgine + car-inference + car-ast. Used by the car CLI's diagnostic / fix slash commands and by .claude-plugin/agents/reason.md.

Inference handle abstraction (Parslee-ai/car#189)

ReasoningSession does not depend on the concrete InferenceEngine. It holds an Arc<dyn ReasoningInferenceHandle> — the narrow trait surface this crate exports in handle.rs.

The trait extends car_inference::InferenceHandle (which provides generate + embed) with three reasoning-specific methods:

Method Used for In-process impl Daemon impl
generate_tracked(req) Per-action InferenceResult (trace_id, model_used, latency_ms) InferenceEngine::generate_tracked daemon's infer JSON-RPC method
find_model_by_name(name) Tier-picker checks whether a candidate model is registered before naming it unified_registry.find_by_name cached models.list_unified snapshot
record_inferred_outcomes(action_results) Post-session learning loop (writes inferred outcomes for each action's trace) takes the engine's tracker write lock best-effort no-op (no outcomes.resolve_pending endpoint yet — follow-up)

This lets callers pick the inference backend at runtime:

// In-process (offline dev, tests, CI)
let inference: Arc<dyn ReasoningInferenceHandle> =
    Arc::new(car_inference::InferenceEngine::new(Default::default()));

// Daemon-routed (`car-server` running locally; shared hot weights + accumulated profiles)
let inference: Arc<dyn ReasoningInferenceHandle> =
    Arc::new(DaemonInferenceHandle::new("ws://127.0.0.1:9100/"));

cmd_reason in car-cli does the runtime selection — probes the daemon with a cheap models.list RPC and falls back to an embedded engine if unreachable. See car-rs/crates/car-cli/src/daemon_handle.rs for the daemon-side ReasoningInferenceHandle impl.

Why a new trait instead of growing InferenceHandle. InferenceHandle (added in #188 for memgine) is intentionally minimal — generate + embed — because memgine is reachable from many crates and a wide trait surface multiplies daemon-proxy work for every implementor. ReasoningInferenceHandle extends it with the three methods car-reason actually uses, keeping the lower-level trait clean while still letting daemon impls compose: DaemonInferenceHandle implements both, with one shared WebSocket connection.