TUI decomposition is blocked on crate::config: 118 of 128 modules form one component (727,748 lines)
- Dominant language
- Rust
- Stars
- 41k
- Forks
- 3.6k
- Avg merge
- 13h 59m
- Merged PRs (30d)
- 299
Description
## Where the decomposition actually stands
Three modules left `crates/tui` in 0.9.13 — `localization` (7,087 lines, `ddc38548d`), `palette` (5,850) and `command_safety` into the existing `execpolicy` crate (2,951) (`063f914f2`). The crate went **973,442 → ~957,700 lines**.
Those were chosen because a dependency census that excluded doc comments and `#[cfg(test)]` blocks showed them at or near zero real coupling. `localization`'s single `crate::` reference turned out to be a sentence inside a doc comment.
## The blocker, found by attempting the next one
`remote_control` (8,828 lines) was scored as a zero-dependency leaf and **is not**. It has 12 real production edges, including a grouped `use crate::{…}` that a naive `crate::[a-z]` census misses entirely. Worse, it forms a genuine two-node cycle with the UI:
```
crates/tui/src/tui/views/mod.rs:1168 crate::remote_control::view_is_approval_for_gate(view.as_ref(), gate)
crates/tui/src/remote_control.rs:3139 view: &dyn crate::tui::views::ModalView,
```
A crate cannot contain half a cycle, so no manifest arrangement makes that build.
Its transitive closure is **118 of 128 top-level modules — 727,748 production lines in 689 non-test files**. The hub is `crate::config`: the TUI's *own* 13,304-line `config.rs` (`pub struct Config` at `:2817`), which is **not** a re-export of `codewhale-config`. Even `crate::utils` is inside the component, because `utils.rs:740,859` call `crate::config::effective_home_dir()`.
**Breaking `crate::config` out of the UI crate is the prerequisite for essentially every remaining extraction.** Until it moves, most modules are one component.
## Why this matters, in measured terms
C00 measured warmed one-line edits: a **provider edit at 30.31s / 8,714 MB RSS**, a **renderer edit at 46.62s / 8,947 MB**, against **0.92s / 269 MB** for the same shape of edit in a small crate. `docs/BUILD_PERFORMANCE.md:18` puts a cold `cargo build -p codewhale-tui` at 94s, of which the crate itself is 70s and the critical path.
## The target, stated plainly
`crates/tui` should contain `tui/` — the ~266k lines of actual UI. Everything else belongs to the crate that already owns its name. The striking part is that those crates **already exist and are nearly empty**:
| Concern | Real crate | Shadow inside `tui` |
| -- | --: | --: |
| `tools` | 1,311 | **154,135** |
| `core` | 5,593 | **58,621** |
| `mcp` | 4,569 | 13,097 |
| `hooks` | 1,598 | 7,542 |
There is 117× more tool code inside the UI crate than in the crate named `tools`.
## Proposed order
1. **`crate::config` out of the UI crate** — the prerequisite. Likely merges into `codewhale-config`, which already exists at 46,768 lines.
2. Re-run the closure analysis afterwards; most of the 118-module component should fragment.
3. Then the large blocks by real coupling: `plugins`+`skills` (mutually coupled, move together), `mcp` (into the existing crate, not a new one), `runtime_api` (zero inbound), `fleet`, `client`.
4. `tools` (154k) and `core` (59k) last — they are the mass, and both have existing near-empty owners.
## Rules learned the hard way
- **Run extractions strictly one at a time.** Each rewrites consumers crate-wide; two in parallel destroyed each other's work in this session.
- Check whether a `crate::` hit is code before trusting a census — comments and test blocks inflated every early estimate.
- Move code, do not rewrite it. Moved tests passing unchanged is the proof an extraction is correct.
- No re-export shims: `docs/design/TUI_DECONSTRUCTION.md:176,185-186` forbids leaving one with deferred consumers.
Contributor guide
Research direction
Read docs/design/TUI_DECONSTRUCTION.md:176,185-186 and inspect crates/tui/src/config.rs, especially Config at :2817, alongside the existing codewhale-config crate. Start by mapping the production dependencies and then run the closure analysis after considering the config extraction. Done means the config component is moved without re-export shims and the moved tests pass unchanged.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- build-system, cli
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100