agent-joule/dev-docs/MODULES.md
David Charlot 7a59f0ffc5 agent-mei: rename agent_joule panel/theme/workflows to agent-mei, MEI fleet wiring and honest-energy receipts
Brings over the uncommitted agent-mei work (Mac checkout, Sep 22) plus box
follow-ups (Oct 17: agent_mei action namespace in keymap/zed.rs, MEI_BRIDGE.md,
RENAME_AGENT_MEI.md, unmetered receipts report 0 uJ). joule_core, JOULE_CODE_*
and JouleDB names unchanged. *.bak.* scratch files excluded.
2026-10-27 12:59:12 -04:00

84 lines
9.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Function Breakdown & Codebase Review — `agent_mei_panel`
> Generated 2026-06-14. Per-file inventory of the bolt-on crate. file:line references are against the audited HEAD.
## 1. Crate overview
`agent_mei_panel` is the bolt-on that turns this Joule fork into an **energy-metered, federated, no-phone-home coding editor**. It adds a dock panel (`AgentMeiPanel`) that drives first-party login-based vendor agents (Claude Code / Gemini / Codex) over ACP — the vendor's own CLI owns its login and tokens; the panel never handles a key — and wraps every request in a five-tier **cascade** (L0 cache → L1 deterministic → L2 semantic retrieval → L3 on-device GGUF model → L4 remote agent) that closes at the cheapest tier that can, metering host energy and sealing JCR-1 signed receipts at each close. Three entry points: **`init(cx)`** (`agent_mei_panel.rs:84`) starts the control server, registers actions, attaches the on-device FIM provider to every file editor; the **`AgentMeiPanel`** view/struct (`:177`); and the **control protocol** (`control.rs`), a CDP-style JSON protocol whose methods land in **`control_dispatch`** (`:2261`).
## 2. Per-file breakdown
### `agent_mei_panel.rs` (5335 LOC) — panel, cascade, control dispatch
**Lifecycle & view:** `init` `:84`, `new` `:557`, `load` `:1080`, `Render::render` `:4208` (~500 lines: status, connect buttons, prompt, cascade/grant/methodology/session/hooks summaries, edit-review list, pending-edit Accept/Reject diff, agent step log), `impl Panel` `:4713`.
**Cascade tiers:** `submit_prompt` `:1600` (entry: resolve `@`-mentions, run cascade), `attempt_l1_deterministic` `:1834` (L1 exact substitution), `attempt_l2_then_l3` `:1673` (L2 embed+replay), `index_for_l2` `:1777`, `attempt_l3_then_l4` `:1883` (L3 model gen+apply), `send_to_l4` `:2462` (L4 ACP forward).
**Edit application & review:** `apply_multi_file_edit` `:2022`, `record_multi_edit` `:2100`, `stage_pending_edit` `:2178`, `apply_staged_now` `:2204`, `accept_pending_edit` `:2231`, `reject_pending_edit` `:2246`, `revert_edit` `:1002`, `record_review` `:986`, `line_diff` `:465`, `diff_stat` `:502`.
**Local-agent / index / prediction:** `run_local_agent` `:1370` (drives `local_agent::run_agent_loop` off-thread), `index_codebase` `:1181`, `predict_here` `:1269`.
**Sessions glue:** `ensure_session_mgr` `:2656`, `spawn_session` `:2699`, `delegate_session` `:2735`, `close_session` `:2777`, `verify_session` `:2799`, `merge_session` `:2839`, `set_active_session` `:2899`, `record_active_op` `:2883`, `active_session_worktree` `:2872`.
**Energy, receipts, ledger:** `host_energy` `:3196`, `energy_uj_now` `:3213`, `bracket_energy` `:2443`, `append_to_ledger` `:686`, `ensure_ledger_loaded` `:642`, `seal_op_receipt` `:738`, `ledger_receipt` `:751`, `verify_entry_seal` `:772`, `ensure_l2_loaded` `:790`, `append_l2_record` `:828`, `record_tier_edit` `:2542`, `record_l3_edit` `:2510`, `note_close` `:2602`, `authorize_tier` `:2611`, `life_spent_uj` `:2637`, `local_life_exhausted` `:2643`, `captured_op` `:3137`, `session_receipt` `:3107`.
**Control & attestation:** `control_dispatch` `:2261` (ping/state/submit/run_agent/accept/reject/open/save/buffer/revert/spawn_session/session_worktree/connect_agent), `control_state` `:2409`, `attest_unit` `:548`, `attest_in_sandbox` `:1025`, `attest_applied_edit` `:3039`.
**Agent connection:** `connect_agent` `:1096`, `do_connect` `:1155` (resolve `CustomAgentServer`, open ACP rooted in the active session worktree).
**L3 model (free fns):** `l3_engine` `:377`, `load_l3_model` `:3393`, `load_mellum_backend` `:3416`, `l3_generate` `:3540`, `l3_generate_fim` `:3560`, `l3_embed` `:3583`, `mellum_generate` `:3497`, `l3_sampling` `:3465`, `build_coding_op` `:3237`, `harness_prompt` `:3789`, `parse_edit` `:3830`, `parse_substitution` `:3273`, `resolve_at_mentions` `:3701`, `format_symbol_context` `:3619`, `format_codebase_context` `:4172`, `session_identity` `:3994`, `build_hook_registry` `:3983`.
### `control.rs` (732) — control protocol over Unix socket / TCP / MCP
`init_control_server` `:185`, `dispatch_foreground` `:276`, `serve_conn`/`process_line` `:340`/`:419` (token-aware), Unix/TCP accept loops, `list_peers` `:93` / `relay_command` `:138` / `register_self` `:61` (fleet), `run_client` `:473` / `run_client_tcp` `:506`, `mcp_tool_specs` `:533` / `handle_tool_call` / `run_mcp_bridge` `:673` (stdio MCP server). Types: `ControlCommand`, `ControlInstance` (gpui Global).
### `methodology.rs` (993) — spec-driven traceability
`MethodologyTracker` `:78`: `adopt`/`adopt_from_file` (verify-before-take signed spec), `cite_op`, `record_op`, `review`, `set_frame`/`check_op_in_frame` (fail-closed footprint gate), `coverage`, `ship_request`/`ship_summary`/`certify_release` (four-gate release cert), `amortization_line`. `SpecFile`, `RunSteering`+`RunCheckpoint`+`RunAmendment` (mid-run steering, monotonic only-narrowing budget).
### `sessions.rs` (855) — accountable worktree-isolated sessions
GPUI-free. `SessionManager` `:271`: `open`/`open_child` (attenuated delegation), `record_op`, `mark_verified`, `merge` (refuses unverified), `close`, `delegated_energy_uj`. `Session` (a `did:key` principal, worktree, branch, grant, status, chain): `verify_chain` `:249`. `SessionGrant::attenuate` `:101` (delegate only what you hold). `SealedEvent` (hash-chained, parent-signed).
### `local_agent.rs` (706) — on-device ReAct tool loop
`run_agent_loop` `:159` (prompt→generate→parse→gate→execute, fix-to-green verify before `finish`), `parse_tool_call`, `is_allowed_command` (allowlist), tools read/grep/list. `AgentStep`, `AgentTrace`.
### `codebase_index.rs` (433) — on-device repo-RAG
`CodebaseIndex::build` `:173` (incremental, reuses unchanged vectors), `search` `:69`, `find_symbol` `:101` (pure-text def ranking), `chunk_file`, `cosine`.
### `edit_blocks.rs` (356) — search/replace edit format
`parse_edit_blocks`, `apply_body`/`apply_edit`/`apply_patch` (exact → trailing-whitespace-tolerant → `SearchNotFound`, errors loudly naming the file). `EditBlock`/`Edit`/`Patch`/`ApplyError`.
### `hooks.rs` (284) — deny-capable lifecycle gates
`Hook` trait, `HookRegistry` (`with_reference_hooks`, `gate` deny-wins, `fire`). Reference gates `RefuseUnverifiedMerge` (PreMerge), `JouleCeiling` (PreTool budget). `LifecyclePoint`, `HookContext`, `Denied`.
### `mcp_client.rs` (230) — synchronous MCP stdio client
`McpClient::connect`/`list_tools`/`call_tool`, `parse_mcp_invocation`. Pure std + serde_json.
### `edit_prediction_local.rs` (216) — Cursor-Tab via on-device FIM
`LocalFimEditPredictionDelegate` (debounced off-thread infill, ghost-text), `CurrentCompletion::interpolate`.
### `cascade_gate.rs` (207) — JCP gate over L0–L4
`CascadeGate::from_env`/`authorize`/`l4_granted`/`grant`. Omit `l4` ⇒ remote agent structurally unreachable.
### `sandbox_bridge.rs` (202) — federate execution to `sandbox-mcp`
`attested_build` (S0–S7 attested build receipt, RATS EAT per step). `AttestedStep`/`AttestedBuild`/`UnitSpec`.
### `fim_local.rs` (182) — pure FIM engine
`FimFormat` (StarCoder/DeepseekCoder/CodeLlama), `fim_prompt`, `predict_infill`, `windows_around`, `clean_completion`.
### `tool_gate.rs` (136) — JCP gate over local-agent tools
`ToolGate::from_env`/`authorize` per tool call (read_file/grep/list_files/run/edit_file/mcp) against a grant + budget.
## 3. Key types
- **`AgentMeiPanel`** `:177` — central view. Field groups: connection (`session`, `prompt_editor`, `status`, `workspace`, `project`); energy (`energy_counter`, `energy_baseline`, `local_energy_uj`); cascade (`l0_cache`, `l2_index`, `l3_model`, `tier_closes:[u32;5]`, `codebase_index`); gating/accountability (`cascade_gate`, `hooks`, `methodology`, `session_key`, `session_mgr`, `active_session`); ledger (`ledger_ops`, `ledger_energy_uj`, `ledger_head`, `ledger_seq`, `ledger_intact`); review (`reviews`, `pending_edit`, `agent_steps`, `pending_context`, `last_intent`).
- **`L3Engine`** — `Runtime` (from-scratch GGUF) | `Mellum` (in-process safetensors). **`L3Backend`** — `Runtime(GgufModel,Vocab)` | `Mellum(Box<MellumModel>,BpeTokenizer,u32)`.
- **`StagedFile`** `{path, old, new, buffer}`, **`PendingEdit`** `{files, energy_before, single_path}`, **`LedgerEntry`** `{seq, prev, intent, energy_uj, op, seal}`.
## 4. Codebase review
**Architecture.** A clean spine: GPUI-free pure substrate modules + one GPUI orchestrator. Dependency-injection-by-closure (`run_agent_loop`, `CodebaseIndex::build`'s `embed`/`progress`, `predict_infill`'s `generate`) keeps heavy/model/IO parts out of the testable cores. The cascade is the central design; JCR-1 sealing + the hash-chained ledger are real with round-trip + tamper tests.
**The one debt: `agent_mei_panel.rs` at 5,335 LOC** — ~half the crate, 5× the next file, mixing seven concerns (render, cascade, L3 inference, ledger, energy, control dispatch, ~480 lines of inline tests). Recommended splits (all GPUI-free, move cleanly):
- **L3 model loading + generation** (`load_l3_model`/`l3_generate`/`mellum_generate`/`l3_sampling`/`harness_prompt`/`parse_edit`/`build_coding_op`, ~`:3237`–`:3600`) → `l3_model.rs`.
- **The persistent ledger** (`LedgerEntry`, `append_to_ledger`, `ensure_ledger_loaded`, `seal_op_receipt`, `verify_entry_seal`, ~`:329`–`:790`) → `ledger.rs` (a sibling of `sessions.rs` — both hash-chained sealed logs).
**Consistency notes:** two near-identical MCP stdio clients (`mcp_client::McpClient`, `sandbox_bridge::Mcp`); doc comments are unusually rich (occasionally essay-length). Adheres well to the repo's Rust guidelines (`let Some(..) else`, `?`, bounded indexing, `.detach()`/`.log_err()` on tasks) — except the load-bearing `let _ =` discards noted in [FINDINGS.md](FINDINGS.md).