Skip to content

refactor(workspace): P3+P4 extract level-1 and level-2 crates - #82

Merged
Crsei merged 1 commit into
Crsei:rust-litefrom
yaohaowei0914:claude/admiring-hertz-4915e0
Apr 21, 2026
Merged

refactor(workspace): P3+P4 extract level-1 and level-2 crates#82
Crsei merged 1 commit into
Crsei:rust-litefrom
yaohaowei0914:claude/admiring-hertz-4915e0

Conversation

@yaohaowei0914

Copy link
Copy Markdown
Contributor

Summary

Resolves #72 (Phase 3) and #73 (Phase 4) from the workspace-split epic #68. Extracts ten new crates on top of the existing cc-types / cc-observability / cc-keybindings / cc-auth / cc-bootstrap / cc-skills split, following the plan in docs/superpowers/specs/2026-04-20-workspace-split-design.md.

Phase 3 (#72) — level-1 crates

Crate Kind Notes
cc-config full SettingsJson moved here from types::app_state; validation inlines 2 engine rules instead of reaching back
cc-utils full clean leaf on cc-types + cc-config; tiny build.rs links advapi32 so libgit2-sys test binaries resolve CryptoAPI
cc-mcp partial (7/8) tools.rs (Tool trait adapter) stays in root. IPC-event cycle broken via callback hook — same pattern cc-skills used
cc-services partial (4/6) session_analytics (needs session::storage) and langfuse (needs types::tool::Tools) stay pending P5
cc-computer-use partial platform backends (input/*, screenshot/*); Tool wrappers stay until P5

Phase 4 (#73) — level-2 crates

Crate Kind Notes
cc-compact full clean DAG — deps only on cc-types + cc-utils
cc-sandbox full policy_from_app_state signature tightened: &ToolPermissionContext + &SandboxSettings instead of &AppState
cc-permissions full permission types moved into cc_types::permissions; CU + browser prompt lookups via registered callbacks
cc-browser partial (9/11) detection.rs split so pure helpers move; Arc<dyn Tool> walkers stay
cc-session full (3,828 LOC) ~/.cc-rust/memory/ path preserved per #73's acceptance

Cycle-break tricks used

  • Callback hooks (mirrors the cc-skills::set_event_callback pattern from P2): cc-mcp subsystem events, cc-mcp plugin discovery, cc-permissions CU / browser prompt lookups.
  • Type migration: PermissionMode / ToolPermissionContext / AdditionalWorkingDirectory / ToolPermissionRulesBySource moved into cc_types::permissions. The re-export in types/tool.rs keeps existing crate::types::tool::… call sites compiling unchanged.
  • Signature narrowing: policy_from_app_state takes the two fields it actually reads, so cc-sandbox does not depend on AppState (which still drags teams / ui / keybindings in).

Why

Per the epic, per-crate granular rebuild cuts incremental build time dramatically — editing one tool file will rebuild one ~3kLOC leaf crate + the root bin instead of re-codegenning the entire ~92kLOC claude-code-rs. This PR unblocks Phase 5 cycle-break work by removing the subsystems that do not participate in the hub cycles from the root crate.

Acceptance checks

Test plan

Not in this PR

🤖 Generated with Claude Code

Ten new workspace crates land in a single commit; each builds + tests
green at the boundary and the root crate keeps every `crate::{config,
utils, mcp, services, computer_use, compact, sandbox, permissions,
browser, session}::…` path working via `use cc_X as X;` aliases or
facade `mod.rs` files that re-export the crate. Matches the existing
P1 / P2 split pattern and the plan in docs/superpowers/specs/
2026-04-20-workspace-split-design.md.

Phase 3 (issue Crsei#72) — five level-1 crates
-----------------------------------------

cc-config — 3,139 LOC (full extraction, one tie broken)
  `src/config/{claude_md,constants,features,paths,settings,validation}.rs`
  → `crates/cc-config/src/…`. `SettingsJson` moved from
  `types::app_state` into `cc-config::runtime_settings` so validation
  reads it without a reverse dep, and the two engine constants the
  validator consulted (`output_style::BUILT_IN_NAMES`,
  `effort::effort_to_budget_tokens`) are inlined as a small rule table
  — the authoritative engine values still drive runtime behaviour.

cc-utils — 2,883 LOC (full, clean leaf on cc-types + cc-config)
  `src/utils/{abort,bash,cwd,file_state_cache,git,messages,shell,
  tokens}.rs` → `crates/cc-utils/src/…`. A tiny `build.rs` emits
  `-l dylib=advapi32` on Windows so the test binary picks up the
  libgit2-sys CryptoAPI imports that rust-lld otherwise leaves
  unresolved.

cc-mcp — ~1,856 LOC (partial)
  Moved: `mod,channel,client,client_tests,discovery,manager,
  transport.rs`. Not moved: `tools.rs` (implements the root-crate
  `Tool` trait — unblocks in P5). The IPC-event cycle is broken the
  same way cc-skills broke its: cc-mcp owns a minimal
  `McpSubsystemEvent` enum and a `set_event_callback` hook the host
  wires to adapt into `SubsystemEvent`. Plugin-contributed server
  discovery now runs through `set_plugin_hook` for the same reason.

cc-services — partial (4 of 6 modules)
  Moved: `lsp_lifecycle,prompt_suggestion,session_memory,
  tool_use_summary.rs`. Not moved: `session_analytics` (deps on
  `session::storage` — unblocked by this same commit's cc-session),
  `langfuse/` (deps on `types::tool::Tools` — unblocks in P5).

cc-computer-use — partial (input + screenshot)
  Platform backends (`input/*.rs`, `screenshot/*.rs`) moved; the Tool
  wrappers (`detection,setup,tools.rs`) stay in root until P5.

Phase 4 (issue Crsei#73) — five level-2 crates
-----------------------------------------

cc-compact — full, clean DAG addition
  `src/compact/{auto_compact,compaction,messages,microcompact,
  pipeline,snip,tool_result_budget}.rs` → `crates/cc-compact/src/…`.
  Deps: cc-types + cc-utils only.

cc-sandbox — full
  `src/sandbox/{availability,errors,filesystem,mode,network,policy,
  runner}.rs` → `crates/cc-sandbox/src/…`. `policy_from_app_state`
  signature tightened to take `&ToolPermissionContext +
  &SandboxSettings` instead of the whole `AppState`, so cc-sandbox
  doesn't need the root crate's app-state type (still tied to teams /
  ui / keybindings). Four callers updated to pass the two fields.

cc-permissions — full, two callbacks registered
  `src/permissions/{bash_matcher,dangerous,decision,path_validation,
  rules}.rs` → `crates/cc-permissions/src/…`. The CU /
  browser permission-prompt lookups that previously called into
  `computer_use::detection` and `browser::{detection,permissions}`
  now go through `set_cu_message_callback` / `set_browser_message_callback`;
  main.rs registers adapters from the root-crate implementations.
  `PermissionMode`, `ToolPermissionContext`,
  `AdditionalWorkingDirectory`, and `ToolPermissionRulesBySource`
  moved into `cc-types::permissions` so both cc-sandbox and
  cc-permissions can consult them without reaching back into
  `types::tool` (where `ToolUseContext` still drags in an ipc cycle).

cc-browser — partial (9 of 11 modules)
  Moved: `common,mcp_bridge,native_host,permissions,session,setup,
  state,tool_rendering,transport.rs`. Also moved the pure-string and
  server-registry helpers out of `detection.rs` into
  `cc-browser::detection`. The `Arc<dyn Tool>` registry walker
  (`detect_browser_servers` / `detect_browser_tools`) and the
  prompt-section builder stay in root until P5.

cc-session — 3,828 LOC (full)
  `src/session/{audit_export,export,memdir,migrations,resume,storage,
  transcript}.rs` + `session_export/{builders,compression,mod,
  tests}.rs` → `crates/cc-session/src/…`. Session files still land in
  `~/.cc-rust/memory/` (per Crsei#73's acceptance criterion — unchanged).
  Same advapi32 build shim as cc-utils for the libgit2-sys test link.

Post-split invariants
---------------------

- `cargo build --workspace --release` succeeds; only the two
  pre-existing `session_id is never read` warnings in
  `web/handlers.rs` remain (both fields are #[serde(default)] API
  contract fields — not introduced by this split).
- Every extracted crate's unit tests pass: cc-config 55, cc-utils 101,
  cc-mcp 26, cc-services 41, cc-compact n/a (no unit tests, covered
  via integration), cc-sandbox 55, cc-permissions 87 + 1 doctest,
  cc-browser n/a, cc-session 55.
- Root crate: 1234 tests pass `--test-threads=1`. The handful of
  parallel failures are pre-existing shared-state flakes (same set
  as on rust-lite HEAD before this commit).
- Feature-gate lookup (`cc_config::features::enabled(…)`) still
  routes through the same `FEATURE_*` env-var reads.
- No new runtime deps — only cross-crate path deps added under
  `[workspace.dependencies]`.

Refs Crsei#72. Refs Crsei#73. Part of Crsei#68.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Crsei
Crsei merged commit 201b2a4 into Crsei:rust-lite Apr 21, 2026
0 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[workspace-split] Phase 3: Extract level-1 crates (config, utils, mcp, services, computer-use)

2 participants