# Grounded harness and continual learning

Sruja is a **CLI-first autonomous coding agent**. It owns the full
observe → act → verify → critique → replan loop (`sruja agent loop`), and
also works as a passive harness (lint, drift, evidence, MCP) from any editor
host. In both modes the **deterministic layer** (verify-task, drift, lint,
intent) is the **independent grader** — the actor never grades itself.

This guide explains how to combine both layers for **continual learning in token space**: the system improves through recorded outcomes and curated memory without retraining model weights.

---

## Why passive codegen decays

When a language model refactors or designs architecture from an isolated prompt, there is no built-in check against the real repository. The result is often structurally invalid DSL, relationships that contradict imports, or boundaries that ignore existing coupling. Over time, teams accumulate drift between `repo.sruja` and code.

A **grounded harness** shifts correctness from neural weights to a compiler: every proposal is linted, compared to scan evidence, and optionally blocked in CI before merge.

---

## Product boundary

See the [boundary table in HOST_AGENT_INTEGRATION.md](HOST_AGENT_INTEGRATION.md#boundary-table) for the full layer breakdown. In summary:

- **Sruja CLI (`agent loop`)** owns the autonomous loop (comprehend → plan → execute → critique → replan).
- **Sruja CLI + MCP** owns the deterministic grader (sync, lint, drift, intent, verify-task, focus, agent memory).
- **Your editor / CI** (optional) owns the interactive host loop using Sruja's passive gates and MCP tools.
- **Humans** own reviewed truth (repo.sruja, Decision Records, approved proposals).

See also [CONTEXT_ENGINEERING.md](CONTEXT_ENGINEERING.md) and [plans/LOOP_AGENT_PLAN.md](plans/LOOP_AGENT_PLAN.md).

---

## Report vs repository (correction table)

Some articles describe a monolithic `ContinualLearningAgent` with `facts`, `user_preferences`, and `learned_patterns` in memory, plus `reflect_and_learn()` and automatic skill generation. **That is a host pattern, not a single shipped binary in this repo.**

| Often described elsewhere | What Sruja ships today |
|---------------------------|-------------------------|
| `ContinualLearningAgent` / `TrajectoryTracker` / `reflect_and_learn()` | **Host workflow** (e.g. Cursor agent + `sruja-architecture` skill) consuming Sruja JSON |
| Memory buckets: facts, preferences, patterns | **`.sruja/agent_memory.json`** with `LearningEntry` objects (`context`, `hypothesis`, `outcome`, `guardrail_advice`, optional `hitl_kind`) |
| LLM supervisor rewrites system prompt | **Not shipped** — optional host step via `--enrich-cmd` on run artifacts |
| Auto-created skill `.md` files | **Not shipped** — install or author skills manually ([skills/README.md](../skills/README.md)) |
| `sruja agent run --autonomous` | **Shipped as `sruja agent loop`** — drives the full closed loop: comprehend → plan → execute → critique → replan |
| `sruja onboard` only | Prefer **`sruja inspect onboard`** for markdown briefings; see [README.md](../README.md) |

Team preferences and stable domain facts belong in **Decision Records** (`.sruja/decisions/`), **editor rules**, or **skills**—not in a separate memory schema inside `agent_memory.json`.

---

## Grounded harness: CLI commands

| Command | Role in the agentic loop |
|---------|---------------------------|
| `sruja lint <file> [--format json]` | Primary rejection gate for invalid or skill-violating DSL |
| `sruja fmt <file>` | Deterministic formatting for reviewable diffs |
| `sruja tree <file>` | Low-token structural map of elements |
| `sruja export json <file>` | Machine-readable graph for tools |
| `sruja sync -r .` | Refresh scan evidence (`.sruja/author_evidence.json`, `.sruja/context.json`) |
| `sruja drift -r . -a repo.sruja` | Fitness function: architecture vs implementation |
| `sruja intent check` | Code changes vs declared intent |
| `sruja discover --explain -r .` | Community detection (LPA) when no baseline exists |

**Lint loop (works well with local OSS models):**

1. Host proposes `.sruja` edits.
2. Run `sruja lint repo.sruja --format json`.
3. If errors exist, feed the JSON array back to the model: “Fix these lint errors.”
4. Repeat until clean, then run `sruja drift`.

Validation uses the WASM-first pipeline (editor extension and CLI share the same rules).

---

## Three lanes of truth

Authoring is split so models do not confuse evidence with reviewed architecture:

| Lane | Tool | Output | Trust |
|------|------|--------|-------|
| **Facts** | `sruja sync`, `sruja author evidence` | `.sruja/author_evidence.json`, `.sruja/context.json` | Citeable evidence |
| **Synthesis** | Skill / MCP; optional `sruja author propose --enrich-cmd` | `.sruja/proposals/<id>.json`, `repo.sruja.working` | Hypothesis until promoted |
| **Enforcement** | `sruja lint`, `sruja drift`, `sruja propose approve` | Pass/fail, violations | Machine-checkable |

Full detail: [plans/GROUNDED_ARCHITECTURE_AUTHORING_PLAN.md](plans/GROUNDED_ARCHITECTURE_AUTHORING_PLAN.md).

---

## Continual learning in token space (Act → Record → Reflect → Learn)

Weights are fixed; **experience** is stored in files and injected into the next prompt.

| Phase | Host (editor/CI) | Sruja harness |
|-------|------------------|---------------|
| **Act** | LLM proposes DSL or code scoped to a goal | `sruja focus`, MCP ladder, `sruja ai` / `ai-context` |
| **Record** | Save chat/run notes if needed | `agent plan` / `agent run`; `.sruja/agent/runs/<id>/facts_bundle.json` on apply; `.sruja/context_events.jsonl` on drift/intent/propose |
| **Reflect** | Optional: summarize `facts_bundle.json` via `--enrich-cmd` | `sruja agent curate` (suggest-only report) |
| **Learn** | Merge advice into team skill or rules | `sruja agent record` or MCP `sruja_record_learning`; `agent merge` / `agent update` |

### Agent memory schema (`LearningEntry`)

Example entry (fields may include optional `id`, `run_id`, `hitl_kind`, `evidence_refs`, retrieval counters):

```json
{
  "id": "learn-abc123",
  "timestamp": "2026-05-19T12:00:00Z",
  "context": "Promote payment boundary proposal",
  "hypothesis": "Split PaymentService container reduces drift violations",
  "outcome": "success",
  "guardrail_advice": "Always run drift after promoting proposals that touch PaymentService",
  "affected_elements": ["Shop.PaymentService"],
  "hitl_kind": "precedent",
  "evidence_refs": [".sruja/proposals/pay-001.json"]
}
```

`hitl_kind` values: `precedent`, `exception`, `correction`, `guardrail`.

CLI:

```bash
sruja agent record -r . \
  -c "Drift fix for Auth" \
  -H "Extract Auth as separate container" \
  -o success \
  -g "Run intent check when moving auth modules" \
  --hitl-kind precedent

sruja agent history -r . -f json
sruja agent curate -r .
```

Utility signals (`retrieval_count`, `task_success_after`) are documented in [AGENTS.md](../AGENTS.md#agentic-memory-utility-srujaagent_memoryjson).

### Closed-loop agent (`sruja agent loop`)

The primary autonomous path: Sruja owns the full cognition loop and runs until
a verifiable condition is met or a budget is exhausted.

```bash
# Autonomous loop: comprehend -> plan -> execute -> critique -> replan
sruja agent loop -r . --goal "Add a health check endpoint"

# With a loop manifest for defaults
cat > .sruja/loop.toml <<EOF
max_iterations = 3
tdd = true
review_every_change = true
shell_allowlist = ["cargo", "just", "npm"]
EOF
sruja agent loop -r . --goal "Fix the flaky test in auth.rs"
```

For interactive work, any editor host (Cursor, Claude Code, Cline, Windsurf)
can use Sruja's MCP tools and deterministic gates as a passive harness.
`agent run`, `agent plan`, and `agent apply` remain as headless/CI convenience
helpers for architecture-bounded validation and evidence authoring.

```bash
# 1. Plan (reviewable JSON)
sruja agent plan -r . --goal "Reduce drift on Shop.API" --file src/shop/api.rs --print

# 2. Human or CI reviews the plan file

# 3. Apply with verification
sruja agent apply -r . --plan docs/plans/run-xxx.json

# Or combined observe/plan/apply (Headless/CI only):
sruja agent run -r . --goal "..." --file path/to/file.rs --mode plan
sruja agent run -r . --goal "..." --file path/to/file.rs --mode apply
```

**MaTTS (parallel trajectories):** `sruja agent run ... --trajectories 3` runs sandboxed attempts (git worktrees when available) and distills guardrails by contrasting success vs failure—deterministic contrast, not an LLM judge.

Configure bounds in `.sruja/config.toml`:

```toml
[agent]
max_steps = 5
max_runtime_ms_per_step = 120000
auto_record_learnings = true
default_trajectories = 3

[integrations]
default_provider = "cmd"
cmd = "ollama run llama3"
timeout_ms = 15000
max_bytes = 20000
```

---

## Artifacts reference

| Path | Purpose |
|------|---------|
| `.sruja/agent_memory.json` | Curated learnings (`LearningEntry`) |
| `.sruja/context_events.jsonl` | Append-only lineage (drift, intent, proposal merge) |
| `.sruja/agent/runs/<run_id>/facts_bundle.json` | Replay bundle after agent apply verification |
| `.sruja/proposals/<id>.json` | Hypothesis architecture changes |
| `.sruja/author_evidence.json` | Scan-backed authoring evidence (prefer over raw `graph.json` for agents) |
| `.sruja/learned_facts.jsonl` | Hypotheses from `sruja learn` — **not** reviewed truth |

---

## Local and open-source inference (`--enrich-cmd`)

Sruja does not require proprietary APIs. Enrichment reads **grounded JSON from stdin** and expects **markdown on stdout**.

```bash
# One-off
sruja inspect onboard -r . -f markdown --enrich-cmd 'ollama run llama3'

sruja author propose -r . --enrich-cmd 'ollama run llama3'

sruja agent plan -r . --goal "..." --file src/lib.rs --enrich --enrich-cmd 'ollama run llama3'
```

Environment overrides (team or CI):

- `SRUJA_ENRICH_PROVIDER` — `cmd` (default) or `openai`
- `SRUJA_ENRICH_CMD` — command for `cmd` provider
- `SRUJA_ENRICH_MODEL`, `SRUJA_ENRICH_BASE_URL`, `SRUJA_ENRICH_API_KEY` — OpenAI-compatible local servers (vLLM, TGI)

Repo defaults: `.sruja/config.toml` `[integrations]` block (see [README.md](../README.md)).

---

## Daily operational loop

```bash
# 1. Refresh evidence
sruja sync -r .

# 2. Task briefing
sruja focus --file src/api/main.rs -r .

# 3. Synthesize (host or headless)
#    Skill/MCP default; optional:
sruja author propose -r . --enrich-cmd 'ollama run llama3'

# 4. Gates before promotion
sruja lint repo.sruja --format json
sruja drift -r . -a repo.sruja
sruja propose approve <id>   # when using proposals

# 5. CI envelope
sruja drift --ci -r .
```

Scaffold GitHub Actions: `sruja init --ci` (alias `sruja start --ci`).

---

## Systems thinking: flows, externals, blast radius

- Model **external systems** and scenarios in `.sruja` so agents see dependencies you do not control.
- Use **scenario / flow** syntax for data lineage (origin → transforms → destinations).
- Before large changes: `sruja focus --element-id <id>` or MCP impact/neighbor tools.
- Discovery without baseline: `sruja discover --explain -r .` (community detection + confidence hints).

---

## IDE and CI integration

- **VS Code / Cursor extension:** validation on save, diagram preview, “Copy Agent Guide”, architecture review commands.
- **MCP:** progressive disclosure (`sruja_list_architecture_index` → topology → elements → task context). Setup: [mcp_setup.md](mcp_setup.md). Catalog: [mcp_tools_reference.md](mcp_tools_reference.md).
- **CI:** fail PRs on `sruja drift --ci`; optional baseline with `sruja baseline`.

Host-side reflect playbook: [.cursor/commands/sruja-reflect-on-run.md](../.cursor/commands/sruja-reflect-on-run.md).

---

## What Sruja does not do

- Run indefinitely without bounds — `agent loop` is bounded by `max_iterations`, spend caps, and workspace-scoped file guards.
- Automatically rewrite its own system prompts or mint new skills from trajectories.
- Treat `learned_facts.jsonl` or LLM synthesis as reviewed architecture without promotion + lint + drift.

**Kill rule:** If a workflow cannot define intent → understand context → detect drift → review change, keep it out of primary automation.

---

## Advanced: extending the CLI (contributors only)

The CLI is a Rust workspace (`sruja-cli`). Teams may add validation subcommands via `clap` subcommands for org-specific compliance. This is **not** the default integration path for agent users—prefer MCP tools, config, and hooks.

---

## Further reading

- [CONTEXT_ENGINEERING.md](CONTEXT_ENGINEERING.md) — Context pipeline principles, Decision Records, and trace events
- [plans/GROUNDED_ARCHITECTURE_AUTHORING_PLAN.md](plans/GROUNDED_ARCHITECTURE_AUTHORING_PLAN.md) — Authoring lanes
- [GETTING_STARTED_SKILL.md](GETTING_STARTED_SKILL.md) — Install `sruja-architecture` skill
- Book: [Agentic AI course](../book/src/courses/agentic-ai/course-overview.md) — Module 4, Lesson 4 (grounded harness)

---

## Agentic Orchestration Patterns and Sruja

Industry writing on multi-agent systems often discusses **reflection**, **tool use**, **planning**, **multi-agent collaboration**, and topologies such as sequential pipelines, parallel fan-out, hierarchical coordinators, and evaluator–optimizer loops. This section maps those ideas to **what Sruja is today** (CLI-first autonomous agent, architecture-as-code, graph queries, MCP, drift and context engineering).

### MCP: tools and grounding, not peer-to-peer agents

Sruja exposes a **Model Context Protocol (MCP)** server so AI editors can call structured tools (summaries, neighbors, paths, focus briefings, context score, and related capabilities depending on version). That aligns with the common split:

- **MCP** answers: *What tools and grounded facts can this session use?*
- The **host** (Cursor, Claude Desktop, CI, or your own stack) can orchestrate multi-step reasoning via MCP, or use `sruja agent loop` to let Sruja own the loop directly.

### Shared state instead of stuffing the chat window

Patterns such as **tiered memory** and **context engineering** stress moving stable facts out of the model's volatile window. In Sruja terms:

- **Architecture graph** and `repo.sruja` (and federation artifacts where used) act as **semantic memory**: reviewed structure and relationships.
- **Drift** commands and linting align with **governance**: whether the model's picture matches enforced truth.
- **Ingested docs** under `.sruja/context/` (with links to elements) ground policy and decisions without pasting entire wikis into every prompt.

### Modeling orchestration in `.sruja` (not executing it)

You can **document** how *your* system orchestrates agents—supervisor, hierarchy, mesh, pipelines—using the DSL and relationships. You can also **execute** coding tasks via `sruja agent loop`, which drives the cognition loop against the real workspace.

### The 80 / 20 split in practice

A practical industry heuristic is **~80% deterministic orchestration**, **~20%** genuinely open-ended model judgment. Sruja's `agent loop` combines both: the **deterministic** layer (parse, validate, scan, query, score, lint) grades each iteration, while the **model** layer (comprehend, plan, execute, critique) does the open-ended work. The deterministic layer is the independent grader — the actor never grades itself.

### Observability as you add automation

If you add more **autonomous** steps (headless runs, hooks, or multi-bot flows), invest in **traceability**: which MCP tools ran, with what arguments, what graph version or git SHA was in scope, and what changed in `.sruja` or policy files. For the MCP server specifically, set **`SRUJA_MCP_LOG=1`** so each `tools/call` emits one JSON line on stderr (`tool`, `repo`, `ms`, `ok`, optional error), and use **`SRUJA_MCP_READONLY=1`** when the host must only call read/query tools (see [mcp_tools_reference.md](mcp_tools_reference.md)).
