Commit Graph

766 Commits

Author SHA1 Message Date
dave 26f9f3f7fc huskies: merge 729_story_store_story_name_as_a_crdt_field_separate_from_the_story_id 2026-04-27 19:09:56 +00:00
dave 4aadf4aa47 huskies: merge 684_refactor_decompose_server_src_http_agents_rs_1249_lines 2026-04-27 18:49:53 +00:00
dave 4b64bc614f huskies: merge 726_story_notify_chat_transports_when_oauth_account_swaps_or_all_accounts_are_exhausted 2026-04-27 18:44:47 +00:00
dave 80661fa622 huskies: merge 727_story_ed25519_node_identity_keypair_generation_persistence_and_identity_endpoint 2026-04-27 18:37:58 +00:00
dave b008235d0d huskies: merge 683_refactor_decompose_server_src_agents_pool_start_mod_rs_1329_lines 2026-04-27 18:26:31 +00:00
dave 646dc490b8 huskies: merge 720_refactor_add_mesh_status_mcp_tool_read_only_peer_mesh_diagnostics 2026-04-27 18:18:51 +00:00
dave c6bc6f07f7 huskies: merge 725_story_auto_swap_oauth_account_on_rate_limit 2026-04-27 18:12:57 +00:00
dave 272a592a4d huskies: merge 735_story_attach_statuseventbuffer_to_each_agent_session_scoped_per_project_reset_on_restart 2026-04-27 18:06:11 +00:00
dave d654f55981 huskies: merge 682_refactor_decompose_server_src_agents_merge_squash_rs_1346_lines 2026-04-27 17:58:04 +00:00
dave 101f616346 huskies: merge 719_refactor_stale_merge_job_lock_recovery_on_new_merge_attempts 2026-04-27 17:46:49 +00:00
dave 1ecb4dad55 huskies: merge 724_story_per_account_oauth_credential_storage_with_login_pool 2026-04-27 17:40:53 +00:00
dave ed8646f0d9 huskies: merge 681_refactor_decompose_server_src_agents_pool_pipeline_advance_mod_rs_1509_lines 2026-04-27 17:35:17 +00:00
dave 875096b3ec huskies: merge 718_refactor_stale_agent_claims_time_out_claim_ttl_with_displacement 2026-04-27 17:26:51 +00:00
dave fce7e16811 huskies: merge 716_story_statuseventbuffer_bounded_per_instance_buffer_over_services_status_broadcaster 2026-04-27 17:03:12 +00:00
dave 4a0f57478c huskies: merge 671_refactor_migrate_pipeline_state_consumers_from_string_comparisons_to_typed_pipelinestage_enum 2026-04-27 16:39:39 +00:00
dave 39a9766d7d huskies: merge 677_refactor_reject_promotion_to_current_coder_of_work_items_with_junk_only_acceptance_criteria 2026-04-27 16:30:35 +00:00
dave 6a582d73b6 huskies: merge 675_bug_mergemaster_silently_exits_when_feature_branch_has_zero_commits_ahead_of_master 2026-04-27 14:43:54 +00:00
dave ea872fa01c huskies: merge 676_bug_apply_and_persist_silently_drops_ops_when_persist_channel_send_fails 2026-04-27 14:38:11 +00:00
dave cbb0a50729 huskies: merge 649_story_migrate_whatsapp_transport_to_status_broadcaster 2026-04-27 14:19:19 +00:00
dave 6c8043d866 huskies: merge 648_story_migrate_discord_transport_to_status_broadcaster 2026-04-27 14:01:32 +00:00
dave 9040d18f50 huskies: merge 664_story_crdt_lamport_clock_inner_seq_must_resume_from_max_own_author_seq_1_instead_of_resetting_to_1_on_restart_phase_c 2026-04-27 12:30:44 +00:00
dave 25603bb8cb huskies: merge 669_story_migrate_slack_transport_to_status_broadcaster 2026-04-27 11:57:06 +00:00
dave 5da29c3d91 huskies: merge 668_bug_pipeline_advances_coder_work_to_merge_when_gates_passed_false 2026-04-27 11:39:11 +00:00
dave 65d2fb210c huskies: merge 655_bug_matrix_bot_spawns_its_own_timerstore_instead_of_using_shared_appcontext_timer_store 2026-04-27 11:32:51 +00:00
dave ac85cfce5d huskies: merge 652_story_pass_resume_session_id_on_agent_respawn_so_new_sessions_inherit_prior_reasoning 2026-04-27 11:27:50 +00:00
dave 144f07f412 huskies: merge 644_story_chat_transport_consumers_slack_discord_whatsapp_matrix_for_the_unified_status_broadcaster 2026-04-27 11:22:52 +00:00
dave 75533225e4 fix: commit minor fmt residue blocking mergemaster cherry-picks
Master had 8 uncommitted single-line whitespace changes (blank-line trimming
in test mod headers, etc.) left over from a previous mergemaster cargo-fmt
run that didn't get committed. Each subsequent merge attempt hit:

  cherry-pick failed: 'Your local changes to the following files would be
  overwritten by merge. Please commit your changes or stash them.'

So merges had been silently un-mergeable for the last several rounds —
mergemaster correctly reported the issue but had no way to fix master's
own state from inside the merge_workspace.

Files affected (all whitespace-only):
- chat/transport/matrix/bot/messages/{handle_message,on_room_message}.rs
- chat/transport/slack/commands/{llm,mod}.rs
- http/mcp/agent_tools/worktree.rs
- http/workflow/story_ops/{create,criterion,update}.rs

cargo clippy --all-targets -- -D warnings: clean
cargo fmt --all --check: clean
2636 tests pass.
2026-04-27 11:17:31 +00:00
dave 7408cc5b4b fix(crdt_snapshot): per-thread SNAPSHOT_STATE in cfg(test) instead of shared static (bug 669)
Replaces the test-time GLOBAL_STATE_LOCK approach (which was just disguised
single-threading) with proper test isolation: each test thread gets its own
SnapshotState via a thread_local!.

Pattern matches crdt_state::CRDT_STATE_TL — production keeps the global
OnceLock; tests get a per-thread OnceLock that's accessed through a
snapshot_state() helper. The unsafe `&*ptr` cast to 'static is safe because
the thread_local lives as long as the spawning test thread.

The race: latest_snapshot_available_after_compaction captured at_seq from a
freshly-generated snapshot, then asserted it equalled SNAPSHOT_STATE's
latest.at_seq. With shared SNAPSHOT_STATE, another test thread's
apply_compaction could overwrite latest_snapshot between capture and read.
Per-thread state eliminates the race at its source.

ALL_OPS / VECTOR_CLOCK stay shared — the tests don't assert on absolute
counts, only on (this-thread's at_seq) == (this-thread's latest.at_seq).

5 consecutive default-parallel `cargo test --bin huskies` runs all green
at 2636/2636.
2026-04-27 02:49:53 +00:00
dave fc71c22305 Revert "fix(crdt_snapshot): serialise tests that share global SNAPSHOT_STATE / ALL_OPS / VECTOR_CLOCK (bug 669)"
This reverts commit 8e608feec1.
2026-04-27 02:45:01 +00:00
dave 8e608feec1 fix(crdt_snapshot): serialise tests that share global SNAPSHOT_STATE / ALL_OPS / VECTOR_CLOCK (bug 669)
The crdt_snapshot tests share three global statics:
- SNAPSHOT_STATE (latest_snapshot, pending_acks, pending_at_seq) — coordination state
- crdt_state::ALL_OPS / VECTOR_CLOCK — op journal + vector clock

Only the per-thread CRDT is thread-local (init_for_test); these other globals
are shared across test threads. Under default cargo test parallelism, two tests
running concurrently interleave their op writes and snapshot generation, so
assertions like assert_eq!(at_seq, 4) fail with at_seq=5 (the other thread's
ops snuck in).

Add a module-level GLOBAL_STATE_LOCK that all 17 affected tests grab at the
top. unwrap_or_else(|e| e.into_inner()) handles the case where a prior test
panicked while holding the lock (poisoned).

Fixes bug 669 — these two tests were the silent killer behind every agent's
script/test failure (see also bug 668, which advanced agents to merge despite
gates_passed=false; that compounded this by sending failing-tests worktrees
to mergemaster).

All 2636 tests now pass under default parallel execution (no --test-threads=1
needed).

Closes #669.
2026-04-27 02:43:49 +00:00
dave 404fd396f5 refactor: split chat/transport/whatsapp/commands.rs (837) into mod + llm
The 837-line commands.rs is split:

- llm.rs: handle_llm_message (LLM turn for non-command messages, ~195 lines)
- mod.rs: handle_incoming_message + tests (~660 lines)

Tests stay co-located with handle_incoming_message in mod.rs. All 2636 tests pass; clippy clean.
2026-04-27 02:37:22 +00:00
dave 1f02de8cd0 refactor: split chat/transport/slack/commands.rs (875) into mod + llm
The 875-line commands.rs is split:

- llm.rs: handle_llm_message (LLM turn for non-command messages, ~190 lines)
- mod.rs: SlackSlashCommandPayload + slash_command_to_bot_keyword + handle_incoming_message + tests (~700 lines)

Tests stay co-located with handle_incoming_message in mod.rs. All 2636 tests pass; clippy clean.
2026-04-27 02:32:11 +00:00
dave d07728f22b refactor: split chat/transport/matrix/bot/messages.rs (912) into mod + on_room_message + handle_message
The 912-line messages.rs is split:

- on_room_message.rs: incoming Matrix event dispatch (~600 lines)
- handle_message.rs: LLM turn + reply streaming (~265 lines)
- mod.rs: format_user_prompt + tests (~70 lines)

Tests stay co-located with format_user_prompt in mod.rs.

All 2636 tests pass; clippy clean.
2026-04-27 02:21:54 +00:00
dave adf936be07 refactor: split http/workflow/story_ops.rs (1256) into create + criterion + update
The 1256-line story_ops.rs is split:

- create.rs: create_story_file + tests (~232 lines)
- criterion.rs: check/add/remove/edit_criterion_in_file + tests (~525 lines)
- update.rs: update_story_in_file + yaml helpers + tests (~640 lines)
- mod.rs: re-exports (~12 lines)

Workflow helpers (read_story_content, write_story_content, slugify_name, etc.)
bumped from pub(super) to pub(crate) since they're now consumed across nested
sub-modules and from http/mcp/story_tools/.

Tests stay co-located. All 2636 tests pass; clippy clean.
2026-04-27 02:13:31 +00:00
dave 34a399b838 refactor: split http/mcp/shell_tools.rs (1144) into mod + exec + script
The 1144-line shell_tools.rs is split:

- exec.rs: validate_working_dir + tool_run_command + handle_run_command_sse
  + their tests (~550 lines)
- script.rs: tool_run_tests + tool_get_test_result + tool_run_build +
  tool_run_lint + helpers + their tests (~610 lines)
- mod.rs: re-exports (~12 lines)

Tests stay co-located. All 2636 tests pass; clippy clean.
2026-04-27 02:04:04 +00:00
dave 928d613190 refactor: split http/mcp/agent_tools.rs (1094) into mod + worktree
The 1094-line agent_tools.rs is split:

- worktree.rs: tool_create/list/remove_worktree, tool_get_editor_command,
  get_worktree_commits + their tests (~190 lines)
- mod.rs: agent lifecycle tools (start/stop/list/output/config/wait/
  remaining_turns_and_budget/read_coverage helper) + their tests

Tests stay co-located. All 2636 tests pass; clippy clean.
2026-04-27 01:57:46 +00:00
dave a8ead9cd10 refactor: split http/mcp/diagnostics.rs (861) into mod + permission + usage
The 861-line diagnostics.rs is split:

- permission.rs: tool_prompt_permission + helpers + their tests (584 lines)
- usage.rs: tool_get_token_usage + tests (122 lines)
- mod.rs: server_logs, rebuild, version, loc_file, dump_crdt, move_story + tests (185 lines)

Tests stay co-located. The bigger sub-modules (permission at 584 with tests
mostly under 800; usage at 122) are well within the 800-line guide.

Also added #[allow(unused_imports)] to two now-pedantic re-exports in
service/diagnostics/mod.rs that the split made flag.

All 2636 tests pass; clippy clean.
2026-04-27 01:51:36 +00:00
dave c600b94f4e chore: remove dangling orphan files accidentally added in b340aa97
server/src/agents/pool/lifecycle.rs and server/src/chat/transport/matrix/notifications.rs were untracked leftovers from an abandoned WIP stash that 'git add -A' picked up. Neither is declared as a mod anywhere — they're dangling code that doesn't get compiled but pollutes the tree.
2026-04-27 01:32:38 +00:00
dave b340aa97b0 fix: clean up clippy warnings + cargo fmt across post-refactor surface
The 13-file refactor pass (commits db00a5d4 through eca15b4e) introduced
~89 clippy errors and 38 cargo fmt issues — every agent in every worktree
hit them on script/test, burning their turn budget on cleanup before doing
real story work. This is the silent kill behind 644, 652, 655, 664, 667
all hitting watchdog limits this round.

Changes:
- cargo fmt --all across 37 files (formatting normalisation only)
- #![allow(unused_imports, dead_code)] on 24 split modules where the
  python-script splitter imported liberally to be safe; tighter cleanup
  per-import will happen as agents touch each module
- Removed truly-dead re-exports (cleanup_merge_workspace, slog_warn from
  http/mcp/mod.rs, CliArgs/print_help from main.rs)
- Prefixed _auth_msg in crdt_sync/server.rs (handshake helper return is
  bound but not consumed)
- Converted dangling /// doc block in crdt_sync/mod.rs to //! so it
  attaches to the module
- Removed empty lines after doc comments in 4 spots (clippy lint)

All 2636 tests pass; clippy --all-targets -- -D warnings clean.
2026-04-27 01:32:08 +00:00
dave 06035f20ad fix: restore #[tokio::main] on main(), #[cfg(unix)] on platform tests, #[allow] on run_pty_session/AuthListenerResult
The biggest miss is #[tokio::main] — without it, async fn main() doesn't compile,
and the binary in every worktree fails 'cargo check'. Agents in those worktrees
burn their turn budgets trying to fix the build before they can do real work, then
get killed by the watchdog. That's why all three in-flight stories failed.

Other restored attributes:
- #[cfg(unix)] on 4 tests in merge/squash and scaffold (skip on non-Unix)
- #[allow(dead_code)] on AuthListenerResult test enum
- #[allow(clippy::too_many_arguments)] on run_pty_session

Same root cause as the earlier #[test] attribute losses: my line ranges started
at the fn line, missing the leading attribute on the previous line.
2026-04-26 23:38:17 +00:00
dave eca15b4ee7 refactor: split agents/pool/start.rs into mod.rs + validation.rs + spawn.rs
The 1630-line start.rs is split into a sub-module directory:

- validation.rs: validate_agent_stage + read_front_matter_agent helpers (69 lines)
- spawn.rs: run_agent_spawn — the background async work that was inlined as
  a tokio::spawn closure body inside start_agent (359 lines)
- mod.rs: AgentPool::start_agent orchestrator + tests (1062 lines)

Stage validation and front-matter agent reading are pre-lock pure helpers that
naturally extract.  The spawn closure body becomes a free async fn that takes
the previously-cloned values as parameters; rebound to the original _clone /
_owned names at the top of the body so the actual work code is a verbatim copy.

No behaviour change. All 23 start tests pass; full suite green.
2026-04-26 22:12:04 +00:00
dave 40f1794d41 fix: restore #[test] attributes on parse_no_args, peer_receives_op_encoded_via_wire_codec, keepalive_constants_are_correct
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).
2026-04-26 22:04:12 +00:00
dave 0d805313d6 fix: restore #[test] and #[should_panic] attributes on panics_on_duplicate_agent_names
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.
2026-04-26 22:01:06 +00:00
dave 0e09a1ed4b refactor: extract auth handshake from crdt_sync/server.rs into handshake.rs
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.
2026-04-26 21:49:46 +00:00
dave db00a5d4b5 refactor: split main.rs by extracting CLI parsing into cli.rs
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.
2026-04-26 21:41:39 +00:00
dave a86448f6a6 refactor: split chat/transport/matrix/config.rs into mod.rs + loading.rs
The 1260-line config.rs is split into:

- mod.rs: BotConfig struct + small impl + default helpers + tests (1047 lines)
- loading.rs: BotConfig::load + save_ambient_rooms (223 lines)

Tests stay co-located.

No behaviour change. All 41 matrix::config tests pass; full suite green.
2026-04-26 21:37:39 +00:00
dave ca72f36c78 refactor: split agents/pool/pipeline/advance.rs into mod.rs + helpers.rs
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.
2026-04-26 21:35:04 +00:00
dave 5aedf94512 refactor: split pipeline_state.rs into 4 sub-modules with co-located tests
The 1411-line pipeline_state.rs is split into:

- mod.rs: types, transition(), execution_transition(), labels + transition tests (885 lines)
- events.rs: TransitionFired, EventBus, TransitionSubscriber + event-bus tests (114 lines)
- projection.rs: ProjectionError, TryFrom<&PipelineItemView>, read_typed + projection tests (379 lines)
- subscribers.rs: 5 concrete TransitionSubscriber stubs (95 lines)

Tests stay co-located.

No behaviour change. All 42 pipeline_state tests pass; full suite green.
2026-04-26 21:30:55 +00:00
dave f1e42710b5 refactor: split llm/providers/claude_code.rs into mod.rs + parse.rs + events.rs
The 1427-line claude_code.rs is split into:

- parse.rs: parse_assistant_message + parse_tool_results + tests (332 lines)
- events.rs: process_json_event + handle_stream_event + tests (749 lines)
- mod.rs: doc, types (ClaudeCodeResult, ClaudeCodeProvider), chat_stream, run_pty_session (395 lines)

Tests stay co-located.

No behaviour change. All 44 claude_code tests pass; full suite green.
2026-04-26 21:22:08 +00:00
dave ce94dd0af4 refactor: split agents/merge.rs into mod.rs + squash.rs + conflicts.rs
The 1772-line merge.rs is split into:

- conflicts.rs: try_resolve_conflicts + resolve_simple_conflicts + tests (351 lines)
- squash.rs: run_squash_merge orchestrator + cleanup + run_merge_quality_gates + tests (1306 lines)
- mod.rs: doc, types (MergeJobStatus, MergeJob, MergeReport, SquashMergeResult), re-exports (52 lines)

Tests stay co-located.

No behaviour change. All 20 merge tests pass; full suite green
(2635 tests with --test-threads=1).
2026-04-26 21:15:06 +00:00