feat: add robot subcommand surface for capabilities schemas examples (f3.1 f3.2 f3.3 task 1.3.4) #36

Open
opened 2026-04-25 08:02:02 +02:00 by product-owner · 0 comments

Problem Statement

Specification terraphim-agent-session-search-spec.md sections F3.1 Capabilities Endpoint, F3.2 Schema Documentation, and F3.3 Examples Endpoint mandate three CLI surfaces:

terraphim-agent robot capabilities         # F3.1: feature flags + index status
terraphim-agent robot schemas [command]    # F3.2: argument/flag schemas
terraphim-agent robot examples [command]   # F3.3: runnable examples

The implementation tasks (terraphim-agent-session-search-tasks.md, Task 1.3.4) mark these subcommands [x] complete, but a clap-level grep on crates/terraphim_agent/src/main.rs for Robot|Schemas|Capabilities|Examples as Subcommand variants returns zero hits. The SelfDocumentation Rust API methods do exist (pub fn capabilities(), pub fn all_schemas(), pub fn examples() at crates/terraphim_agent/src/robot/docs.rs:25, :65, :70) but they are unreachable from the CLI -- and the entire pub mod docs is wrapped in #[allow(dead_code)] (robot/mod.rs:9).

Existing related issues -- #11 (Route REPL output through machine-readable formatter, Task 1.4.1+1.4.3), #30 (populate ExampleDoc.output for examples endpoint), and #32 (live index_status in capabilities response) -- handle the output formatter and response data, but none add the actual robot subcommand surface that exposes those structures over the binary CLI. This is the missing wiring layer between the existing Rust API and the documented user-facing contract.

Without this, AI agents cannot self-discover terraphim-agent's command surface, schemas, or runnable examples, blocking the entire MCP-style robot capabilities/robot schemas integration story that motivates Phase 1.

Acceptance Criteria

  • Add Command::Robot { sub: RobotSub } variant to the existing Command enum in crates/terraphim_agent/src/main.rs:699.
  • Add RobotSub enum with three variants:
    • Capabilities -- no args; emits the result of SelfDocumentation::capabilities_data().
    • Schemas { command: Option<String> } -- single command name selects one schema, no arg returns all_schemas().
    • Examples { command: Option<String> } -- same shape as Schemas but returns ExampleDoc[].
  • All three subcommands route output through the existing RobotFormatter (robot/output.rs), honouring the global --format flag (lines 689-690), so --format json|jsonl|minimal|table all work.
  • In --robot mode (line 686-687) output is the standard RobotResponse<T> envelope from robot/schema.rs, including meta.command, meta.elapsed_ms, and the new meta.exit_code slot.
  • terraphim-agent robot capabilities --format json | jq .features.session_search returns a boolean.
  • terraphim-agent robot schemas search returns the search command's CommandDoc JSON.
  • terraphim-agent robot examples search returns at least one runnable ExampleDoc.
  • Unknown command for schemas/examples exits with ExitCode::ErrorNotFound (4) and includes a RobotError listing valid commands.
  • Drop the #[allow(dead_code)] on pub mod docs in robot/mod.rs:9.
  • Add crates/terraphim_agent/tests/robot_subcommand.rs exercising each subcommand via assert_cmd with both --format json and default output.
  • cargo test -p terraphim_agent passes.
  • cargo clippy -p terraphim_agent -- -D warnings passes.

Proposed Approach

  1. Define RobotSub next to existing Command enum (around line 698) using clap::Subcommand derive, identical pattern to RolesSub/ConfigSub.
  2. Match Command::Robot { sub } in the existing dispatch and call into a thin handle_robot(sub, &cli) -> Result<ExitCode> function in a new crates/terraphim_agent/src/robot/cli.rs module.
  3. handle_robot instantiates SelfDocumentation::new() (already a stateless builder), dispatches to capabilities_data()/all_schemas()/examples(), wraps the result in RobotResponse, and serialises through RobotFormatter::format(&response, cli.format).
  4. For interactive REPL parity (Task 1.4.4), add the same dispatch behind the repl feature gate in crates/terraphim_agent/src/repl/ so /robot capabilities works inside the REPL too -- but this is a stretch goal and can be deferred to a follow-up if it pushes the diff above 500 LOC.

Affected crates: terraphim_agent only.

Affected files:

  • crates/terraphim_agent/src/main.rs (add RobotSub, dispatch arm)
  • crates/terraphim_agent/src/robot/mod.rs (drop dead-code attr; export new submodule)
  • New: crates/terraphim_agent/src/robot/cli.rs (handle_robot)
  • New: crates/terraphim_agent/tests/robot_subcommand.rs

Dependencies

Soft-pairs with #30 (ExampleDoc.output) and #32 (live index_status) -- both populate response data; this issue exposes the response surface. Can land independently because the response types already exist with empty/static defaults.

Pairs naturally with #35 (ExitCode wiring) for the meta.exit_code field but does not strictly block on it.

Verification

cargo test -p terraphim_agent --test robot_subcommand
cargo build -p terraphim_agent
./target/debug/terraphim-agent robot capabilities --format json | jq .name
./target/debug/terraphim-agent robot schemas search --format json | jq .arguments
./target/debug/terraphim-agent robot examples search --format json | jq '.[0].command'
./target/debug/terraphim-agent robot schemas not-a-real-command; echo "exit=$?"  # expect 4
cargo clippy -p terraphim_agent -- -D warnings

Scope

Single PR, ~350-450 LOC. New cli.rs module is a thin dispatcher (~120 LOC), enum additions are mechanical, tests carry the rest. No external crate or workspace dependency changes.

## Problem Statement Specification `terraphim-agent-session-search-spec.md` sections **F3.1 Capabilities Endpoint**, **F3.2 Schema Documentation**, and **F3.3 Examples Endpoint** mandate three CLI surfaces: ``` terraphim-agent robot capabilities # F3.1: feature flags + index status terraphim-agent robot schemas [command] # F3.2: argument/flag schemas terraphim-agent robot examples [command] # F3.3: runnable examples ``` The implementation tasks (terraphim-agent-session-search-tasks.md, Task 1.3.4) mark these subcommands `[x]` complete, but a clap-level grep on `crates/terraphim_agent/src/main.rs` for `Robot|Schemas|Capabilities|Examples` as `Subcommand` variants returns zero hits. The `SelfDocumentation` Rust API methods *do* exist (`pub fn capabilities()`, `pub fn all_schemas()`, `pub fn examples()` at `crates/terraphim_agent/src/robot/docs.rs:25`, `:65`, `:70`) but they are unreachable from the CLI -- and the entire `pub mod docs` is wrapped in `#[allow(dead_code)]` (`robot/mod.rs:9`). Existing related issues -- #11 (Route REPL output through machine-readable formatter, Task 1.4.1+1.4.3), #30 (populate ExampleDoc.output for examples endpoint), and #32 (live index_status in capabilities response) -- handle the *output formatter* and *response data*, but none add the actual `robot` subcommand surface that exposes those structures over the binary CLI. This is the missing wiring layer between the existing Rust API and the documented user-facing contract. Without this, AI agents cannot self-discover terraphim-agent's command surface, schemas, or runnable examples, blocking the entire MCP-style `robot capabilities`/`robot schemas` integration story that motivates Phase 1. ## Acceptance Criteria - [ ] Add `Command::Robot { sub: RobotSub }` variant to the existing `Command` enum in `crates/terraphim_agent/src/main.rs:699`. - [ ] Add `RobotSub` enum with three variants: - `Capabilities` -- no args; emits the result of `SelfDocumentation::capabilities_data()`. - `Schemas { command: Option<String> }` -- single command name selects one schema, no arg returns `all_schemas()`. - `Examples { command: Option<String> }` -- same shape as `Schemas` but returns `ExampleDoc[]`. - [ ] All three subcommands route output through the existing `RobotFormatter` (`robot/output.rs`), honouring the global `--format` flag (lines 689-690), so `--format json|jsonl|minimal|table` all work. - [ ] In `--robot` mode (line 686-687) output is the standard `RobotResponse<T>` envelope from `robot/schema.rs`, including `meta.command`, `meta.elapsed_ms`, and the new `meta.exit_code` slot. - [ ] `terraphim-agent robot capabilities --format json | jq .features.session_search` returns a boolean. - [ ] `terraphim-agent robot schemas search` returns the search command's `CommandDoc` JSON. - [ ] `terraphim-agent robot examples search` returns at least one runnable `ExampleDoc`. - [ ] Unknown command for `schemas`/`examples` exits with `ExitCode::ErrorNotFound` (4) and includes a `RobotError` listing valid commands. - [ ] Drop the `#[allow(dead_code)]` on `pub mod docs` in `robot/mod.rs:9`. - [ ] Add `crates/terraphim_agent/tests/robot_subcommand.rs` exercising each subcommand via `assert_cmd` with both `--format json` and default output. - [ ] `cargo test -p terraphim_agent` passes. - [ ] `cargo clippy -p terraphim_agent -- -D warnings` passes. ## Proposed Approach 1. Define `RobotSub` next to existing `Command` enum (around line 698) using `clap::Subcommand` derive, identical pattern to `RolesSub`/`ConfigSub`. 2. Match `Command::Robot { sub }` in the existing dispatch and call into a thin `handle_robot(sub, &cli) -> Result<ExitCode>` function in a new `crates/terraphim_agent/src/robot/cli.rs` module. 3. `handle_robot` instantiates `SelfDocumentation::new()` (already a stateless builder), dispatches to `capabilities_data()`/`all_schemas()`/`examples()`, wraps the result in `RobotResponse`, and serialises through `RobotFormatter::format(&response, cli.format)`. 4. For interactive REPL parity (Task 1.4.4), add the same dispatch behind the `repl` feature gate in `crates/terraphim_agent/src/repl/` so `/robot capabilities` works inside the REPL too -- but this is a stretch goal and can be deferred to a follow-up if it pushes the diff above 500 LOC. Affected crates: `terraphim_agent` only. Affected files: - `crates/terraphim_agent/src/main.rs` (add `RobotSub`, dispatch arm) - `crates/terraphim_agent/src/robot/mod.rs` (drop dead-code attr; export new submodule) - New: `crates/terraphim_agent/src/robot/cli.rs` (handle_robot) - New: `crates/terraphim_agent/tests/robot_subcommand.rs` ## Dependencies Soft-pairs with #30 (ExampleDoc.output) and #32 (live index_status) -- both populate response *data*; this issue exposes the response *surface*. Can land independently because the response types already exist with empty/static defaults. Pairs naturally with #35 (ExitCode wiring) for the `meta.exit_code` field but does not strictly block on it. ## Verification ```bash cargo test -p terraphim_agent --test robot_subcommand cargo build -p terraphim_agent ./target/debug/terraphim-agent robot capabilities --format json | jq .name ./target/debug/terraphim-agent robot schemas search --format json | jq .arguments ./target/debug/terraphim-agent robot examples search --format json | jq '.[0].command' ./target/debug/terraphim-agent robot schemas not-a-real-command; echo "exit=$?" # expect 4 cargo clippy -p terraphim_agent -- -D warnings ``` ## Scope Single PR, ~350-450 LOC. New `cli.rs` module is a thin dispatcher (~120 LOC), enum additions are mechanical, tests carry the rest. No external crate or workspace dependency changes.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Reference: terraphim/agent-tasks#36