Same root cause as 0d805313: when extracting a test that's the FIRST inside its
mod block, the slicer started at the fn line and missed the leading #[test]
attribute on the previous line. Test count now matches pre-split count (2636).
Lost in commit db00a5d4 when extracting tests from main.rs into cli.rs;
the line range used for the panics_on_duplicate_agent_names test in main.rs
started at the fn signature instead of the attribute line.
The 1680-line server.rs is split:
- handshake.rs: perform_auth_handshake helper + close_with_auth_failed + auth tests
+ start_auth_listener / close_listener_auth_failed test helpers + AuthListenerResult enum
- server.rs: crdt_sync_handler (now invokes perform_auth_handshake) + wait_for_sync_text
+ broadcast/e2e/keepalive tests
Auth handshake (Steps 1-3 of the WebSocket handshake) is a self-contained sequence
that takes &mut SplitSink + &mut SplitStream and returns Option<AuthMessage>. The
caller observes None to mean the connection has already been closed with the
appropriate close code.
No behaviour change. All 63 crdt_sync tests pass; full suite green.
The 1258-line main.rs is split into:
- main.rs: mod declarations, async fn main + panics_on_duplicate_agent_names test (894 lines)
- cli.rs: CliArgs struct, parse_cli_args, print_help, resolve_path_arg + their tests (372 lines)
main.rs cannot itself become a directory (binary crate must have main.rs at the
crate root); cli.rs is a sibling module.
No behaviour change. All cli tests pass; full suite green.
The 1353-line advance.rs is split into:
- mod.rs: impl AgentPool with run_pipeline_advance + start_mergemaster_or_block + tests (1244 lines)
- helpers.rs: spawn_pipeline_advance, resolve_qa_mode_from_store, write_review_hold_to_store, should_block_story (128 lines)
Tests stay co-located with run_pipeline_advance which they exercise.
No behaviour change. All 10 advance tests pass; full suite green.
The 1864-line story_tools.rs is split into:
- story.rs: story creation/lifecycle/management (903 lines incl. tests)
- criteria.rs: acceptance-criteria tools (534 lines)
- bug.rs: bug item tools (318 lines)
- spike.rs: spike item tools (120 lines)
- refactor.rs: refactor item tools (60 lines)
- mod.rs: re-exports (25 lines)
Tests stay co-located with the code they exercise; setup_git_repo_in and
setup_story_for_update test helpers are duplicated into the modules that need
them rather than centralised, since they are tiny and test-only.
No behaviour change. All 60 story_tools tests pass; full suite green
(2635 tests with --test-threads=1).
The 1882-line mod.rs is split into:
- tools_list.rs: handle_tools_list — the static schema for every MCP tool (1172 lines)
- dispatch.rs: handle_tools_call — the tool-name → *_tools router (157 lines)
- mod.rs: doc, sub-mod decls, JsonRpc structs, Poem handlers, handle_initialize (586 lines)
Tests stay co-located with the code they exercise.
No behaviour change. All 267 http::mcp tests pass; full suite green
(2635 tests with --test-threads=1).
The 2045-line scaffold.rs is split into a sub-module directory:
- templates.rs: STORY_KIT_* and DEFAULT_* template constants (161 lines)
- detect.rs: detect_components_toml + detect_script_{build,lint,test} + tests (989 lines)
- helpers.rs: write_*_if_missing, generate_project_toml, gitignore helpers (166 lines)
- mod.rs: scaffold_story_kit orchestrator + scaffold tests (756 lines)
include_str! paths in templates.rs are adjusted (one extra ../) for the deeper
nesting. Tests stay co-located with the code they exercise per Rust convention.
No behaviour change. All 77 scaffold tests pass; full suite green
(2635 tests with --test-threads=1).
Five files in server/src/ exceeded 1500 lines, with 50–75% of the line
count being inline `#[cfg(test)] mod tests { ... }` blocks. Agents
working on these files have to navigate huge buffers via Read calls,
costing turn budget that could go toward actual work.
Pattern: convert `foo.rs` to `foo/mod.rs` + `foo/tests.rs`.
Rust resolves `mod foo;` to either form, so no parent-module changes
needed.
Before / after (production-code lines, what an agent has to navigate
when editing the module):
crdt_sync.rs: 3672 → 1003 (mod.rs) + 2667 (tests.rs)
crdt_state.rs: 2122 → 1263 (mod.rs) + 854 (tests.rs)
io/fs/scaffold.rs: 2045 → 702 (mod.rs) + 1342 (tests.rs)
http/mcp/mod.rs: 1882 → 1410 (mod.rs) + 472 (tests.rs)
http/mcp/story_tools.rs: 1864 → 725 (mod.rs) + 1137 (tests.rs)
Side change: scaffold/mod.rs's include_str! paths got an extra `../`
because the file moved one directory deeper.
Tests: full `cargo test` suite passes (2635 passed, 0 failed).
Formatting: cargo fmt --check clean.
Motivation: today's agent thrashing on 644 / 650 / 652 was partly due to
cumulative-counting (now fixed by 650) but also genuinely due to file
size — sonnet's 50-turn budget barely covers reading these files plus
making the change. Smaller production-code files mean more turn budget
left for the actual work.
Committed straight to master because this is an enabling refactor for
agent autonomy work; running it through the normal pipeline would
require an agent that has to navigate the very files it's about to
split, defeating the purpose.