feat: Route REPL command output through machine-readable formatter (Phase 1 Task 1.4.1 and 1.4.3) #10

Closed
opened 2026-04-24 05:01:22 +02:00 by product-owner · 1 comment

Problem Statement

Phase 1 Task 1.4.1 and Task 1.4.3 of the session-search spec are unchecked. ForgivingParser is now wired into ReplHandler::execute_command (#4), and BudgetEngine is scheduled (#7), but individual command handlers (handle_search, handle_role, handle_vm, etc.) still println! human-oriented coloured strings. There is no OutputMode routing: --format json or --robot on the CLI does not produce a machine-readable envelope for any command other than /n capabilities (already implemented by Task 1.3). Until the handler routes through output::RobotFormatter, the Task 1.6 integration test tests/repl_robot_tests.rs (tracked by #8) cannot assert a full JSON envelope end-to-end, and AI-agent consumers cannot rely on structured output.

Current State

  • crates/terraphim_agent/src/robot/output.rs defines RobotFormatter, ResponseEnvelope, compact/non-compact variants, and error payload shapes.
  • crates/terraphim_agent/src/repl/handler.rs holds ReplHandler (line ~28) with no output_mode field and no RobotFormatter reference.
  • handle_search (line ~458) and sibling handlers print directly with colored and println!.
  • execute_command (line ~258) already wires ForgivingParser and composes a human-oriented auto-correction notice; there is no branch that suppresses the notice for machine mode or adds meta.auto_corrected to the envelope.
  • CLI args parsing (bin/terraphim-agent.rs) accepts --format json but the value never reaches ReplHandler.

Acceptance Criteria

  • ReplHandler gains an output_mode: OutputMode field populated from CLI args (Interactive | Json | JsonCompact).
  • execute_command suppresses coloured stdout writes when output_mode != Interactive and instead emits the corresponding ResponseEnvelope via RobotFormatter.
  • Every response envelope from a successful command contains meta.auto_corrected: bool, meta.alias_expanded: bool, meta.duration_ms: u64.
  • Error paths (unknown command, suggestions, parse errors) return an error envelope with the corresponding ExitCode (64 for usage, 70 for internal).
  • handle_search, handle_role, handle_graph, handle_vm, and handle_config route results through RobotFormatter::format_response.
  • cargo test -p terraphim_agent --features repl-full passes.
  • cargo clippy -p terraphim_agent --features repl-full -- -D warnings passes.
  • Manual verification: terraphim-agent --format json search foo | jq . parses without error.

Proposed Approach

  1. Extend ReplHandler::new with an output_mode parameter; plumb from bin/terraphim-agent.rs arg parser.
  2. Introduce a CommandOutput enum (Search(SearchHit), Role(RoleInfo), ...) returned by each handle_* method instead of printing.
  3. Add ReplHandler::emit(output: CommandOutput) -> Result<()> that dispatches to RobotFormatter or to the existing coloured printer.
  4. Update execute_command to capture ParseResult metadata and merge into the envelope before emit.
  5. Gate the coloured printing path behind #[cfg(feature = "repl")] && matches!(output_mode, Interactive).

Files affected:

  • crates/terraphim_agent/src/repl/handler.rs (main change)
  • crates/terraphim_agent/src/bin/terraphim-agent.rs (CLI plumbing)
  • crates/terraphim_agent/src/robot/output.rs (add meta fields if missing)

Dependencies

Depends on #4 (ForgivingParser wiring) so that ParseResult flows into execute_command.
Unblocks #8 (Phase 1 tests): integration tests need the JSON envelope to assert shape.

Verification

cargo test -p terraphim_agent --features repl-full handler
cargo test -p terraphim_agent --features repl-full --test repl_robot_tests
cargo clippy -p terraphim_agent --features repl-full -- -D warnings
./target/debug/terraphim-agent --format json search "hello" | jq '.data, .meta'
./target/debug/terraphim-agent --format json badcmd || echo "exit=$?"

Scope

Single PR, estimated 250-350 LOC across handler.rs, bin/terraphim-agent.rs, and a handful of imports. Completes Phase 1 Tasks 1.4.1 and 1.4.3.

Upstream: Implements docs/specifications/terraphim-agent-session-search-tasks.md Phase 1 Task 1.4 for terraphim/terraphim-ai.

## Problem Statement Phase 1 Task 1.4.1 and Task 1.4.3 of the session-search spec are unchecked. `ForgivingParser` is now wired into `ReplHandler::execute_command` (#4), and `BudgetEngine` is scheduled (#7), but individual command handlers (`handle_search`, `handle_role`, `handle_vm`, etc.) still `println!` human-oriented coloured strings. There is no `OutputMode` routing: `--format json` or `--robot` on the CLI does not produce a machine-readable envelope for any command other than `/n capabilities` (already implemented by Task 1.3). Until the handler routes through `output::RobotFormatter`, the Task 1.6 integration test `tests/repl_robot_tests.rs` (tracked by #8) cannot assert a full JSON envelope end-to-end, and AI-agent consumers cannot rely on structured output. ## Current State - `crates/terraphim_agent/src/robot/output.rs` defines `RobotFormatter`, `ResponseEnvelope`, compact/non-compact variants, and error payload shapes. - `crates/terraphim_agent/src/repl/handler.rs` holds `ReplHandler` (line ~28) with no `output_mode` field and no `RobotFormatter` reference. - `handle_search` (line ~458) and sibling handlers print directly with `colored` and `println!`. - `execute_command` (line ~258) already wires `ForgivingParser` and composes a human-oriented auto-correction notice; there is no branch that suppresses the notice for machine mode or adds `meta.auto_corrected` to the envelope. - CLI args parsing (`bin/terraphim-agent.rs`) accepts `--format json` but the value never reaches `ReplHandler`. ## Acceptance Criteria - [ ] `ReplHandler` gains an `output_mode: OutputMode` field populated from CLI args (`Interactive | Json | JsonCompact`). - [ ] `execute_command` suppresses coloured stdout writes when `output_mode != Interactive` and instead emits the corresponding `ResponseEnvelope` via `RobotFormatter`. - [ ] Every response envelope from a successful command contains `meta.auto_corrected: bool`, `meta.alias_expanded: bool`, `meta.duration_ms: u64`. - [ ] Error paths (unknown command, suggestions, parse errors) return an error envelope with the corresponding `ExitCode` (64 for usage, 70 for internal). - [ ] `handle_search`, `handle_role`, `handle_graph`, `handle_vm`, and `handle_config` route results through `RobotFormatter::format_response`. - [ ] `cargo test -p terraphim_agent --features repl-full` passes. - [ ] `cargo clippy -p terraphim_agent --features repl-full -- -D warnings` passes. - [ ] Manual verification: `terraphim-agent --format json search foo | jq .` parses without error. ## Proposed Approach 1. Extend `ReplHandler::new` with an `output_mode` parameter; plumb from `bin/terraphim-agent.rs` arg parser. 2. Introduce a `CommandOutput` enum (`Search(SearchHit), Role(RoleInfo), ...`) returned by each `handle_*` method instead of printing. 3. Add `ReplHandler::emit(output: CommandOutput) -> Result<()>` that dispatches to `RobotFormatter` or to the existing coloured printer. 4. Update `execute_command` to capture `ParseResult` metadata and merge into the envelope before emit. 5. Gate the coloured printing path behind `#[cfg(feature = "repl")] && matches!(output_mode, Interactive)`. Files affected: - `crates/terraphim_agent/src/repl/handler.rs` (main change) - `crates/terraphim_agent/src/bin/terraphim-agent.rs` (CLI plumbing) - `crates/terraphim_agent/src/robot/output.rs` (add `meta` fields if missing) ## Dependencies Depends on #4 (`ForgivingParser` wiring) so that `ParseResult` flows into `execute_command`. Unblocks #8 (Phase 1 tests): integration tests need the JSON envelope to assert shape. ## Verification ```bash cargo test -p terraphim_agent --features repl-full handler cargo test -p terraphim_agent --features repl-full --test repl_robot_tests cargo clippy -p terraphim_agent --features repl-full -- -D warnings ./target/debug/terraphim-agent --format json search "hello" | jq '.data, .meta' ./target/debug/terraphim-agent --format json badcmd || echo "exit=$?" ``` ## Scope Single PR, estimated 250-350 LOC across `handler.rs`, `bin/terraphim-agent.rs`, and a handful of imports. Completes Phase 1 Tasks 1.4.1 and 1.4.3. Upstream: Implements `docs/specifications/terraphim-agent-session-search-tasks.md` Phase 1 Task 1.4 for terraphim/terraphim-ai.
Author

Duplicate of #11 (same body, same title). Closing as dupe; #11 is canonical with dependency edges.

Duplicate of #11 (same body, same title). Closing as dupe; #11 is canonical with dependency edges.
Sign in to join this conversation.