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.
8.8 KiB
Architecture & Integration
Generated 2026-06-14. How
agent_mei_panelwires together internally, to the Joule host, and to its 16 external deps. file:line against audited HEAD.
Component map
crates/zed/src/main.rs:770 agent_mei_panel::init(cx)
crates/zed/src/zed.rs:704 AgentMeiPanel::load(...) (initialize_panels)
│
init(cx) [agent_mei_panel.rs:84] AgentMeiPanel (struct :177) owns:
├─ control::init_control_server(cx) l0_cache: L0Cache (joule-code-cascade)
├─ observe_new<Workspace> → ToggleFocus l3_model: Option<Arc<L3Model>> (jouleclaw-runtime/loader)
└─ observe_new<Editor> → LocalFimDelegate cascade_gate: CascadeGate (cascade_gate.rs / joule-code-jcp)
hooks: HookRegistry (hooks.rs)
methodology: MethodologyTracker (methodology.rs)
session_mgr: SessionManager (sessions.rs)
energy_counter: EnergyCounter (jouleclaw-energy)
1. Cascade data flow
Entry submit_prompt (agent_mei_panel.rs:1600). Each tier guarded by authorize_tier(tier, intent); first to close wins.
submit_prompt :1600
├─ resolve_at_mentions → pending_context :1608
├─ ensure_ledger_loaded / ensure_l2_loaded :1618 (rehydrate L0/L2 across sessions)
├─ L0 authorize_tier(L0) → l0_cache.try_resolve :1628 hit → note_close(L0,0) → RETURN :1646
├─ L1 attempt_l1_deterministic :1834 parse_substitution; buffer.set_text → record_tier_edit(L1)
└─ attempt_l2_then_l3 :1673
├─ L2 embed (GGUF as encoder) → cosine ≥ threshold → replay prior edit → record_tier_edit(L2)
├─ L3 attempt_l3_then_l4 :1883
│ energy_before; document_symbols (LSP) on fg :1927
│ background: load_l3_model → codebase_index.search → format_symbol_context →
│ harness_prompt → l3_generate :1958
│ FILE blocks → apply_multi_file_edit; else parse_edit;
│ empty → send_to_l4; else review? stage_pending_edit : buffer.set_text + record_l3_edit
└─ L4 send_to_l4 :2462
authorize_tier(L4) DENY → "L4 denied by grant" RETURN ← no-phone-home seam
thread.send(ContentBlock) over ACP :2491
(close captured later via thread subscription — see §risks)
Edit review (stage_pending_edit:2178 → accept_pending_edit:2231 → apply_staged_now:2204): staging records a PendingEdit; buffers untouched until Accept (set_text + record_l3_edit). Reject just drops it. Control protocol exposes the same (accept/reject).
Energy (bracket_energy:2443): after − before from energy_uj_now; Estimator → measured_uj = None (honest). Counter from host_energy_counter:3850 — Apple IOReport (aarch64), NVML/RAPL (linux), else None.
Sealing (record_tier_edit:2542, the shared close path): bracket energy → build_coding_op → append_to_ledger:686 (hash-chained COSE_Sign1) → note_methodology_op → l0_cache.insert → record_review → note_close → index_for_l2 → attest_applied_edit:3039 (sandbox). Also folds the op into the active session via record_active_op:728.
L4 close is asymmetric: sealed not in send_to_l4 but in the thread subscription (:1123-1136) — on AcpThreadEvent, captured_op:3137 walks the thread's diffs into a CodingOp, then append_to_ledger + l0_cache.insert. (See risk #1.)
2. Joule integration seams
- Init:
main.rs:770agent_mei_panel::init(cx)(thezed.rs:5337init is inmod testonly — no production double-init). - Panel load:
zed.rs:704AgentMeiPanel::loadininitialize_panels, added viaadd_panel_when_readyalongside the other dock panels. - Joule APIs touched:
workspace::Workspace(panel host, actions,impl Panel);project::Project(agent_server_store,document_symbolsLSP,open_buffer, worktrees);agent_servers/acp_thread/agent-client-protocol(ACP connection + L4 send + diff subscription);editor::Editor(prompt + FIM provider);language::Buffer/multi_buffer(edit application);lsp(symbol context); macOSsandbox(Seatbelt for the agent'sruntool).
3. External dependency boundary (16 git deps, pinned 4132daa)
| Dep | Used by | Purpose | Status |
|---|---|---|---|
joule-code-cargo |
panel, methodology | CodingOp, Edit, Anchor, SignedOp |
Core |
joule-code-cascade |
panel, cascade_gate | L0Cache, Request, Stage |
Core |
joule-code-receipt |
panel | Energy, Provenance, Receipt |
Core |
joule-code-schema |
panel, gate, methodology, sessions | Tier, ContentId, ALG_ED25519 |
Core |
joule-code-jcp |
cascade_gate | JcpGate — tier auth + sealed receipts |
Core (gate) |
jcp-bridge |
tool_gate | LocalToolGate — per-tool-call auth |
Core (gate) |
joule-code-identity |
sessions, panel | Identity, ActorKind — did:key principals |
Used |
joule-code-spec |
methodology | cite, coverage, Clause, SignedSpec |
Used |
joule-code-review |
methodology, panel | two-stage review ledger | Used |
joule-code-release |
methodology | certify, ReleaseCertificate — ship door |
Used (via ship_summary) |
joule-code-joulecontract |
methodology | frame_check — out-of-frame edit gate |
Used |
joulecontract-schema |
methodology | Contract, Rigor |
Thin (inert frame contract only) |
jouleclaw-energy |
panel | EnergyCounter + IOReport/NVML/RAPL |
Core |
jouleclaw-runtime |
panel | generate, embed, cosine_similarity |
Core (L3) |
jouleclaw-loader-gguf |
panel | GGUF reader/tokenizer + safetensors Mellum | Core (L3) |
joule-code-conformance (dev) |
tests | verify_pack over C1–C4 vectors |
Test-only |
Flags: joule-code-release's discharge gate is hardcoded false (ship_summary:2985) — ship door un-passable; jcp-bridge/ToolGate only active under JOULE_CODE_AGENT_TOOLS; Mellum surface only via JOULE_CODE_L3_ENGINE=mellum.
4. Subsystem wiring
authorize_tier:2611is the single junction composing hooks (PreTool, deny-wins,:2623) + cascade_gate (JCP grant + lifetime ceiling,:2629). Every tier passes through it.record_tier_edit:2542is the close junction fanning into methodology, sessions, L0 cache, L2 index, reviews, sandbox attestation.control_dispatch:2261is the headless seam — the control server (control.rs:185) and MCP bridge (run_mcp_bridge) drive the same panel methods a human action would.- methodology ←
note_methodology_op:943signs+cites+frame-checks each op, exports to.joule/*.json. sessions ←ensure_session_mgrbuilds the manager withcascade_gate.grant(); worktrees back background sessions (active_session_worktree→ agent cwd). tool_gate ← passed as theauthorize_toolclosure intolocal_agent::run_agent_loop.
5. Integration risks / danglers
- L4 close depends on the thread subscription firing (
:1123-1136). If the subscription is dropped on reconnect (:1141) or no diff event fires, the L4 turn produces no ledger op and no L0 entry — a silently lost close (unlike synchronous L0–L3). (See FINDINGS P1.) - Release/ship door structurally un-passable —
contract_discharged = falsehardcoded (:2985); the full release certificate can't be reached (only merge-via-verifiedcan). - Session grant ↔ live gate is descriptor-only —
SessionGrantis sealed into the open receipt but not bound to the liveCascadeGate(sessions.rs:25-27); sessions with different declared grants are gated identically. - Heavy env-var gating — accountability is opt-in. Out of the box (no
JOULE_CODE_GRANT/_LIFETIME_UJ/_AGENT_TOOLS/JOULECLAW_L3_MODEL/_REVIEW_EDITS/_CONTROL_SOCK) the cascade runs ungated and L4-reachable — no-phone-home is a configuration, not a default. session_mgrsilently absent outside a git repo —ensure_session_mgrreturns early;record_active_opno-ops; closed ops hit the ledger but never fold into a session chain, with no surfaced warning.joulecontract-schemanear-vestigial — only builds an inert frame contract.- RAPL counter fragile by design — selected only if a read succeeds; normal Linux user →
None→ 0-J receipts that look honest but carry no measurement and no "unavailable" signal. - FIM provider attaches per-editor at
observe_newtime (set-once); editors opened before a model is configured stay no-op for the session.