> ## Documentation Index
> Fetch the complete documentation index at: https://docs.qredence.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Architecture

> Qlaw on DSPy 3.3.0 in three tiers: typed lenses over a pydantic graph, one compilable ReasoningEngine module, and a ReActV2 chat agent with lenses as tools.

Qlaw's agents become **typed `dspy.Signature` + `dspy.Module` lenses** over a **pydantic graph state**. The user-driven loop (Selection → Lens Invocation → Expansion) becomes the `forward()` of a single **`ReasoningEngine`** module. The Co-Pilot and the Enrich researcher become **`dspy.ReActV2`** tool agents.

Because everything is a DSPy module, every layer is:

* **Optimizable** — via `MIPROv2`, `BootstrapFewShot`, or GEPA.
* **Evaluable** — via `dspy.Evaluate` with custom metrics.
* **`Refine`-validated** — deterministic reward functions retry until the contract passes.

## Three tiers

| Tier       | What                                                                                                                                                            | Where                              |
| ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- |
| 1 — Lenses | One optimizable module per agent: `SemanticInterpreter`, `Decomposer`, `OntologyArchitect`, `TrajectoryStrategist`, `Critic`, `GroundingEnricher`, `Explainer`. | `qlaw/lenses/`                     |
| 2 — Engine | `ReasoningEngine` + `ReasoningLoop` + `SeedFlow` — Selection → Routing → Invocation → Expansion → Critic gate.                                                  | `qlaw/engine.py`, `qlaw/router.py` |
| 3 — Chat   | Multi-turn `dspy.ReActV2` agent with lenses as tools (`run_lens`, `add_node`, `inspect_node`, `graph_stats`).                                                   | `qlaw/chat.py`                     |

## DSPy 3.3.0 primitives used

| Concern                  | DSPy primitive                                                                       |
| ------------------------ | ------------------------------------------------------------------------------------ |
| Task specification       | `dspy.Signature` (docstring = instructions; pydantic-typed fields = output contract) |
| Reasoning step           | `dspy.Predict`, `dspy.ChainOfThought`                                                |
| Tool-use loop            | `dspy.ReActV2` (native tool calling, reserved `submit`, parallel tool calls)         |
| Retry and validation     | `dspy.Refine` (3.x replacement for the removed `Assert` / `Suggest`)                 |
| Program composition      | `dspy.Module.forward()` — arbitrary Python control flow is the loop                  |
| Optimization             | `dspy.MIPROv2`, `dspy.BootstrapFewShot`, `dspy.Flex`                                 |
| Evaluation               | `dspy.Evaluate` plus custom metrics                                                  |
| Program-structure search | `dspy.Flex` (experimental)                                                           |

## Layer-to-DSPy mapping

| Qlaw layer (agent)                   | DSPy primitive                     | Signature                | Output contract                                                               |
| ------------------------------------ | ---------------------------------- | ------------------------ | ----------------------------------------------------------------------------- |
| **Inception** (Semantic Interpreter) | `ChainOfThought`                   | `SemanticInterpretation` | `root_type: Literal[PROBLEM, QUESTION, PLAN, PROJECT]`, `entities: list[str]` |
| **Deconstruct**                      | `ChainOfThought` + `Refine`        | `Decompose`              | `sub_nodes: list[SubNode]`, type ∈ {`COMPONENT`, `QUESTION`, `DATA`}          |
| **Ontology**                         | `ChainOfThought` + `Refine`        | `Ontology`               | `concepts: list[Concept]`, type == `CONCEPT`                                  |
| **Trajectories**                     | `ChainOfThought`                   | `Trajectories`           | `trajectories: list[Trajectory]`, type == `TRAJECTORY`                        |
| **Gap Analysis** (Critic)            | `ChainOfThought`                   | `GapAnalysis`            | `risks: list[Risk]`, type == `RISK`, `severity: Literal[low, med, high]`      |
| **Enrich** (Researcher)              | `ReActV2` + search tool            | `Enrich`                 | `intel: Intel{summary, sources, metrics}`                                     |
| **Explainer**                        | `Predict`                          | `Explain`                | `summary: str`                                                                |
| **Co-Pilot**                         | `ReActV2` + graph/lens tools       | `ChatAnswer`             | Tools: `run_lens`, `add_node`, `inspect_node`, `graph_stats`                  |
| **Seed flow**                        | Composition                        | —                        | `SemanticInterpreter → Decomposer`                                            |
| **The loop**                         | Python control flow in `forward()` | —                        | `GraphState → GraphState`                                                     |

## Domain model

The graph is the typed state that flows through every DSPy module. It has two hard rules:

1. **Expansion is deterministic and pure.** The LM never mutates the graph. It emits a `NodeBatch`, and `GraphState.apply()` does the wiring. The graph delta is ground truth a metric can check.
2. **The LM sees a distilled `NodeContext`, not raw state.** Lenses receive `node.label` and `node.description`. The Co-Pilot gets a graph summary.

The node taxonomy mirrors the frontend's `NodeType`: `ROOT`, `PROBLEM`, `QUESTION`, `PLAN`, `PROJECT`, `COMPONENT`, `TRAJECTORY`, `DATA`, `RISK`, `INSIGHT`, `CONCEPT`, `VISUALIZATION`. Lens output DTOs (`SubNode`, `Concept`, `Trajectory`, `Risk`, `Intel`) each pin a `Literal[NodeType.…]` so pydantic coercion enforces the contract at the boundary.

## Model configuration

**One model across all tiers** — `deepseek-v4-flash` via the OpenAI-compatible endpoint, configured once at startup.

| Model               | DSPy configuration                                                                    | Provider                   |
| ------------------- | ------------------------------------------------------------------------------------- | -------------------------- |
| `deepseek-v4-flash` | `dspy.LM("openai/" + OPENAI_MODEL, api_base=OPENAI_BASE_URL, api_key=OPENAI_API_KEY)` | OpenAI-compatible endpoint |

Set `model_type="chat"` if the endpoint requires it. Any OpenAI-compatible model id can be swapped in via `OPENAI_MODEL`.

## Design decisions

| Concern          | Current Qlaw (React app)                  | Fleet Reasoner (DSPy)                                                                      |
| ---------------- | ----------------------------------------- | ------------------------------------------------------------------------------------------ |
| Prompt per agent | Hand-written system prompt + JSON schema. | Typed `dspy.Signature`; docstring is instructions; pydantic coercion enforces types.       |
| Graph mutation   | Zustand store, `addNodesAndLinks`.        | `GraphState.apply()` — pure, deterministic, testable.                                      |
| Loop             | `App.tsx` click handlers.                 | `ReasoningEngine.forward()` Python control flow.                                           |
| Model selection  | Hardcoded per call.                       | One `dspy.LM` configured at startup (`config.py`); per-scope overrides via `dspy.context`. |
| Feedback         | None (Critic is a separate call).         | `Refine` retry plus critic gate feeding the loop.                                          |
| Improvement      | None.                                     | `MIPROv2` / `BootstrapFewShot` / `Flex` compile + `dspy.Evaluate`.                         |
| Tool loop        | Hand-rolled chat tool dispatch.           | `dspy.ReActV2` native tool calling.                                                        |
| UI contract      | `NodeType` / `QlawNode` JSON.             | Identical pydantic contract — the React app keeps its JSON shape via a thin adapter.       |
