Severity
High for maintainability — runtime crate has the same god-crate shape as kernel, and at 77k LOC dwarfs the kernel.
Location
crates/librefang-runtime/src/agent_loop.rs — 10,403 lines
crates/librefang-runtime/src/tool_runner.rs — 9,789 lines
crates/librefang-runtime/src/context_engine.rs — 5,116 lines
crates/librefang-runtime/src/plugin_manager.rs — 4,341 lines
crates/librefang-runtime/src/session_repair.rs — 2,837 lines
crates/librefang-runtime/src/model_catalog.rs — 2,758 lines
librefang-runtime total: 67 files, 77,313 LOC
- Inconsistent split with siblings:
librefang-runtime-mcp/src/lib.rs — 3,581 lines (a single-file crate)
librefang-runtime-oauth/src/lib.rs — ~3 lines (re-export shell)
librefang-runtime-wasm/src/lib.rs — ~3 lines (re-export shell)
Finding
The runtime split is incoherent:
- MCP, OAuth, WASM each get their own crate. OAuth and WASM crates contain ~3 lines of re-exports — pure overhead.
- Meanwhile, audit, media, apply_patch, docker sandbox, browser automation, prompt injection guards, auth_cooldown, command_lane all live as massive in-tree modules of
librefang-runtime.
The result: a dependency graph with two oversized nodes (kernel ≈ 50k LOC, runtime ≈ 77k LOC) and a constellation of tiny shell crates around them. This is monorepo cosmetics, not modularity.
librefang-extensions (395 LOC) was apparently intended as the extension boundary, but the actual extension surface — Docker sandbox, browser, audit, media — is hard-wired into runtime. Plugins cannot be separately versioned, separately compiled, or selectively enabled at build time.
Suggested split (Phase 1 — extract from runtime)
Promote the following to standalone crates so they can be turned off, swapped, or developed in isolation:
| New crate |
Source modules |
Approx LOC |
librefang-runtime-audit |
audit/, audit-related parts of agent_loop |
~2k |
librefang-runtime-sandbox-docker |
docker_sandbox.rs |
~1.5k |
librefang-runtime-browser |
browser/ tool subsystem |
~3k |
librefang-runtime-media |
media/ subsystem |
~2k |
librefang-runtime-apply-patch |
apply_patch tool |
~1k |
Internal split for the remaining librefang-runtime core:
| Module |
Responsibility |
agent_loop/dispatch.rs |
top-level message → result |
agent_loop/tool_call.rs |
tool invocation envelope |
agent_loop/streaming.rs |
provider streaming aggregation |
tool_runner/registry.rs |
tool registration |
tool_runner/<tool_name>.rs |
one file per tool (currently all in tool_runner.rs) |
Phase 2 — collapse useless shell crates
Move the contents of librefang-runtime-oauth and librefang-runtime-wasm (sub-100-LOC re-export shells) back into librefang-runtime as modules. Crate count is not a quality metric.
Why now
- Compile times: a one-line change to
tool_runner.rs rebuilds 9,789 lines of dependent code in librefang-runtime.
- Tool isolation: an audit/security review of "what can a tool plugin do" requires reading agent_loop + tool_runner together, ~20k LOC of intertwined code.
- Selective build features: production deployments may not need browser automation or Docker sandbox, but currently can't compile them out.
Acceptance criteria
Related
- Companion issue:
kernel/mod.rs is also a god-file (17,943 LOC). These two should be tackled in coordination since they share the KernelHandle boundary.
Severity
High for maintainability — runtime crate has the same god-crate shape as kernel, and at 77k LOC dwarfs the kernel.
Location
crates/librefang-runtime/src/agent_loop.rs— 10,403 linescrates/librefang-runtime/src/tool_runner.rs— 9,789 linescrates/librefang-runtime/src/context_engine.rs— 5,116 linescrates/librefang-runtime/src/plugin_manager.rs— 4,341 linescrates/librefang-runtime/src/session_repair.rs— 2,837 linescrates/librefang-runtime/src/model_catalog.rs— 2,758 lineslibrefang-runtimetotal: 67 files, 77,313 LOClibrefang-runtime-mcp/src/lib.rs— 3,581 lines (a single-file crate)librefang-runtime-oauth/src/lib.rs— ~3 lines (re-export shell)librefang-runtime-wasm/src/lib.rs— ~3 lines (re-export shell)Finding
The runtime split is incoherent:
librefang-runtime.The result: a dependency graph with two oversized nodes (
kernel≈ 50k LOC,runtime≈ 77k LOC) and a constellation of tiny shell crates around them. This is monorepo cosmetics, not modularity.librefang-extensions(395 LOC) was apparently intended as the extension boundary, but the actual extension surface — Docker sandbox, browser, audit, media — is hard-wired into runtime. Plugins cannot be separately versioned, separately compiled, or selectively enabled at build time.Suggested split (Phase 1 — extract from runtime)
Promote the following to standalone crates so they can be turned off, swapped, or developed in isolation:
librefang-runtime-auditlibrefang-runtime-sandbox-dockerlibrefang-runtime-browserlibrefang-runtime-medialibrefang-runtime-apply-patchInternal split for the remaining
librefang-runtimecore:agent_loop/dispatch.rsagent_loop/tool_call.rsagent_loop/streaming.rstool_runner/registry.rstool_runner/<tool_name>.rsPhase 2 — collapse useless shell crates
Move the contents of
librefang-runtime-oauthandlibrefang-runtime-wasm(sub-100-LOC re-export shells) back intolibrefang-runtimeas modules. Crate count is not a quality metric.Why now
tool_runner.rsrebuilds 9,789 lines of dependent code inlibrefang-runtime.Acceptance criteria
librefang-runtime/src/exceeds 2,000 LOCcargo build -p librefang-runtime --no-default-featuresexcludes browser/docker/media without compile errorstool_runner/Related
kernel/mod.rsis also a god-file (17,943 LOC). These two should be tackled in coordination since they share theKernelHandleboundary.