Skip to content

fix: address code review findings for task/58-handoff-context-fields #708

@AlexMikhalev

Description

@AlexMikhalev

Code Review Findings — task/58-handoff-context-fields

21 commits, ~8700 lines across 57 files. Reviewed by rust-code-reviewer and rust-developer agents.


Critical (Must Fix Before Merge)

C-1: Two failing tests assert wrong agents_run count

  • Location: lib.rs:976, orchestrator_tests.rs:146
  • Problem: Tests assert agents_run == 0 but default_groups() spawns 5 non-visual agents
  • Fix: Create SwarmConfig with groups: vec![] for test isolation, or fix assertions

C-2: Path traversal via unsanitized agent name in file path

  • Location: lib.rs:322
  • Problem: to_agent used directly in .handoff-{}.json path — ../ escapes working_dir
  • Fix: Validate agent name rejects /, \, .. before path construction

C-3: Blocking std::process::Command in async context

  • Location: scope.rs:244-250, 279-295
  • Problem: WorktreeManager::create_worktree and remove_worktree use blocking I/O in async callers
  • Fix: Convert to tokio::process::Command (already used in compound.rs)

C-4: Agent failure silently treated as pass

  • Location: compound.rs:461-467
  • Problem: Fallback pass: true when agent produces no parseable JSON output
  • Fix: Change fallback to pass: false

Important (Should Fix)

I-1: Result collection loop exits on 1s gap

  • Location: compound.rs:222-249
  • Problem: 1s inner timeout exits loop even if agents are still running
  • Fix: Use tokio::time::timeout_at(collect_deadline, rx.recv()) pattern

I-2: CostTracker mixed atomics (low risk)

  • Location: cost_tracker.rs:58-99
  • Problem: AtomicU64 spend with plain u8/i32 reset fields
  • Status: Mitigated — CostTracker is single-owner, no concurrent access possible. Could simplify atomics to Cell<u64>.

I-3: ProcedureStore::new is #[cfg(test)] only

  • Location: procedure.rs:49-64
  • Problem: No production constructor — type unusable outside tests
  • Fix: Remove #[cfg(test)] gate or #[cfg(test)] the entire struct

I-4: Blocking std::fs in async fns

  • Location: procedure.rs:88-282
  • Problem: save(), load_all(), find_by_title(), etc. use std::fs in async fn
  • Fix: Remove async from signatures (they don't actually await) or switch to tokio::fs

I-5: #[allow(dead_code)] without justification

  • Location: procedure.rs:49,55, compound.rs:114
  • Problem: Violates project rule "never use #[allow(dead_code)]"
  • Fix: Remove dead code or wire it into production

I-6: u64 TTL cast to i64 overflow

  • Location: handoff.rs:160
  • Fix: let ttl = i64::try_from(ttl_secs).unwrap_or(i64::MAX);

I-7: from_agent/to_agent parameter mismatch with context fields

  • Location: lib.rs:294-351
  • Fix: Validate context.from_agent == from_agent && context.to_agent == to_agent

I-8: ScopeReservation::overlaps false positives

  • Location: scope.rs:49-54
  • Problem: "src/" incorrectly overlaps "src-backup/"
  • Fix: Add path-separator-aware prefix check. Low priority (non-exclusive mode bypasses it).

I-9: substitute_env silently ignores $VAR syntax

  • Location: config.rs:362-375
  • Fix: Remove misleading doc claim or implement $VAR handling

I-10: expect in Default impl (keep as-is)

  • Location: persona.rs:195
  • Status: Justified — compile-time embedded template, invariant is sound

I-11: which command not portable

  • Location: spawner/config.rs:206
  • Fix: Use which crate or command -v fallback

I-12: Sleep-based test timing

  • Location: spawner/lib.rs:618-825
  • Fix: Replace sleeps with tokio::time::timeout + polling on broadcast receiver

Suggestions

# Issue Location
S-1 Unnecessary .clone() in findings collection compound.rs:258
S-2 has_visual_changes rebuilds patterns Vec every call compound.rs:472
S-3 index_path() returns &PathBuf not &Path mcp_tool_index.rs:244
S-4 CostSnapshot.verdict uses Debug format cost_tracker.rs:186
S-5 extract_review_output only handles single-line JSON fences compound.rs
S-6 Wall-clock ordering in test_buffer_latest_for_agent handoff.rs:568
S-7 PersonaRegistry::persona_names allocates Vec persona.rs:93
S-8 McpToolIndex::search clones thesaurus N times mcp_tool_index.rs:149

Fix Groupings (recommended order)

Group 1: Compound review workflow (C-1, C-4, I-1)

Files: compound.rs, lib.rs tests, orchestrator_tests.rs

Group 2: Handoff path safety (C-2, I-6, I-7)

Files: handoff.rs, lib.rs

Group 3: WorktreeManager async (C-3)

Files: scope.rs, compound.rs call sites

Group 4: Dead code cleanup (I-5)

Files: compound.rs (remove scope_registry), procedure.rs

Group 5: ProcedureStore cleanup (I-3, I-4)

File: procedure.rs

Group 6: Independent low-priority (I-8, I-9, I-11, I-12, S-1 through S-8)

Checklist

[ ] cargo fmt --check clean
[ ] cargo clippy --all-targets clean
[ ] All #[allow(...)] have justification or removed
[ ] All tests pass
[ ] No blocking I/O in async context
[ ] No path traversal vectors
[ ] No silent failure masking

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions