feat: case-insensitive flags and --flag=value separators (F2.3) #31

Open
opened 2026-04-25 06:02:47 +02:00 by root · 0 comments
Owner

Problem Statement

Spec F2.3 (terraphim-agent-session-search-spec.md, lines 186-194) requires three argument-flexibility behaviours that are explicitly missing from the forgiving parser:

  1. Case-insensitive flags: --Format json should be treated as --format json.
  2. Flag-value separators: --format=json should be treated as --format json.
  3. Boolean flag variations: --verbose, -v, --verbose=true should all yield verbose=true.

Verification (no matches today):

rg "to_ascii_lowercase|case_insensitive|--Format" crates/terraphim_agent/src/forgiving/  -> 0 matches
rg "split_once\\('='\\)|split('=')" crates/terraphim_agent/src/forgiving/                -> 0 matches

User-facing failure mode for AI agents (G2 goal: "Zero parse failures from typos"): an LLM that emits terraphim-agent --Format=json search "query" (Title-cased flag plus = separator -- common variations across model families) hits an "unknown flag" error. The forgiving parser corrects sub-command typos but not flag-name casing or value separators, leaving F2.3 the only un-implemented bullet of the F2 (Forgiving CLI) feature.

Acceptance Criteria

  • terraphim-agent --Format json search "x" and terraphim-agent --format=JSON search "x" both produce the same parsed result as terraphim-agent --format json search "x".
  • terraphim-agent search "x" -V and terraphim-agent search "x" --verbose=true both set the verbose flag.
  • Robot-mode meta exposes flag_normalisations: Vec<{from: String, to: String}> so AI consumers can detect that normalisation occurred (mirrors the existing auto_corrected pattern in F2.1).
  • ForgivingParser::normalise_flag(&str) -> (String, Option<String>) is added with unit tests covering: --Format, --format=json, -V, --verbose=true, --verbose=false, --verbose=TRUE, mixed-case --MAX-tokens=100.
  • cargo test -p terraphim_agent --lib forgiving passes.
  • cargo clippy -p terraphim_agent -- -D warnings passes.

Proposed Approach

  1. Add pub fn normalise_flag(raw: &str) -> (String, Option<String>) in crates/terraphim_agent/src/forgiving/parser.rs that:
    • Splits on the first = to separate name and value.
    • Lower-cases the leading --name portion only (values keep their case so quoted strings survive).
    • Maps short forms (-V, -v) via the existing FlagDoc.short field on CommandDoc -- look up the canonical long form rather than hard-coding.
  2. Boolean values: when the canonical flag is declared as flag_type == "bool" in FlagDoc, parse the value with bool::from_str against an ascii-lowercased copy.
  3. Wire the normalisation through ForgivingParser::parse() so the existing ParseResult variants surface the change. Add a new field normalisations: Vec<(String, String)> to ParseResult::Exact and ParseResult::Corrected.
  4. In the robot-mode response builder, when normalisations are non-empty, include them under meta.flag_normalisations. Keep field absent when empty (#[serde(skip_serializing_if = "Vec::is_empty")]).
  5. Update the REPL handler to log auto-normalisations in interactive mode, mirroring the F2.1 auto-correct UX.

Affected crates: terraphim_agent only.
Key files: forgiving/parser.rs, forgiving/mod.rs, robot/schema.rs (meta struct), repl/handler.rs (interactive surface).

Dependencies

Soft-blocked by #4 (Wire ForgivingParser into REPL command dispatch) for the REPL surface, but the parser-level work and unit tests can land independently. Mark this issue blocked-by #4 to sequence the REPL wiring after #4 lands.

Verification

cargo test -p terraphim_agent --lib forgiving::parser::tests::normalise_flag
cargo test -p terraphim_agent --lib forgiving
cargo clippy -p terraphim_agent -- -D warnings
./target/debug/terraphim-agent --Format=JSON search "test" --robot | jq '.meta.flag_normalisations'
# expected: [{"from":"--Format=JSON","to":"--format json"}]

Scope

Single-PR change. Estimated 250-350 lines (parser + tests + meta-field wiring). All logic lives in terraphim_agent; no cross-crate work.

## Problem Statement Spec F2.3 (terraphim-agent-session-search-spec.md, lines 186-194) requires three argument-flexibility behaviours that are explicitly missing from the forgiving parser: 1. Case-insensitive flags: `--Format json` should be treated as `--format json`. 2. Flag-value separators: `--format=json` should be treated as `--format json`. 3. Boolean flag variations: `--verbose`, `-v`, `--verbose=true` should all yield `verbose=true`. Verification (no matches today): ``` rg "to_ascii_lowercase|case_insensitive|--Format" crates/terraphim_agent/src/forgiving/ -> 0 matches rg "split_once\\('='\\)|split('=')" crates/terraphim_agent/src/forgiving/ -> 0 matches ``` User-facing failure mode for AI agents (G2 goal: "Zero parse failures from typos"): an LLM that emits `terraphim-agent --Format=json search "query"` (Title-cased flag plus `=` separator -- common variations across model families) hits an "unknown flag" error. The forgiving parser corrects sub-command typos but not flag-name casing or value separators, leaving F2.3 the only un-implemented bullet of the F2 (Forgiving CLI) feature. ## Acceptance Criteria - [ ] `terraphim-agent --Format json search "x"` and `terraphim-agent --format=JSON search "x"` both produce the same parsed result as `terraphim-agent --format json search "x"`. - [ ] `terraphim-agent search "x" -V` and `terraphim-agent search "x" --verbose=true` both set the verbose flag. - [ ] Robot-mode `meta` exposes `flag_normalisations: Vec<{from: String, to: String}>` so AI consumers can detect that normalisation occurred (mirrors the existing `auto_corrected` pattern in F2.1). - [ ] `ForgivingParser::normalise_flag(&str) -> (String, Option<String>)` is added with unit tests covering: `--Format`, `--format=json`, `-V`, `--verbose=true`, `--verbose=false`, `--verbose=TRUE`, mixed-case `--MAX-tokens=100`. - [ ] `cargo test -p terraphim_agent --lib forgiving` passes. - [ ] `cargo clippy -p terraphim_agent -- -D warnings` passes. ## Proposed Approach 1. Add `pub fn normalise_flag(raw: &str) -> (String, Option<String>)` in `crates/terraphim_agent/src/forgiving/parser.rs` that: - Splits on the first `=` to separate name and value. - Lower-cases the leading `--name` portion only (values keep their case so quoted strings survive). - Maps short forms (`-V`, `-v`) via the existing `FlagDoc.short` field on `CommandDoc` -- look up the canonical long form rather than hard-coding. 2. Boolean values: when the canonical flag is declared as `flag_type == "bool"` in `FlagDoc`, parse the value with `bool::from_str` against an ascii-lowercased copy. 3. Wire the normalisation through `ForgivingParser::parse()` so the existing `ParseResult` variants surface the change. Add a new field `normalisations: Vec<(String, String)>` to `ParseResult::Exact` and `ParseResult::Corrected`. 4. In the robot-mode response builder, when normalisations are non-empty, include them under `meta.flag_normalisations`. Keep field absent when empty (`#[serde(skip_serializing_if = "Vec::is_empty")]`). 5. Update the REPL handler to log auto-normalisations in interactive mode, mirroring the F2.1 auto-correct UX. Affected crates: `terraphim_agent` only. Key files: `forgiving/parser.rs`, `forgiving/mod.rs`, `robot/schema.rs` (meta struct), `repl/handler.rs` (interactive surface). ## Dependencies Soft-blocked by #4 (Wire ForgivingParser into REPL command dispatch) for the REPL surface, but the parser-level work and unit tests can land independently. Mark this issue blocked-by #4 to sequence the REPL wiring after #4 lands. ## Verification ```bash cargo test -p terraphim_agent --lib forgiving::parser::tests::normalise_flag cargo test -p terraphim_agent --lib forgiving cargo clippy -p terraphim_agent -- -D warnings ./target/debug/terraphim-agent --Format=JSON search "test" --robot | jq '.meta.flag_normalisations' # expected: [{"from":"--Format=JSON","to":"--format json"}] ``` ## Scope Single-PR change. Estimated 250-350 lines (parser + tests + meta-field wiring). All logic lives in `terraphim_agent`; no cross-crate work.
root added a new dependency 2026-04-25 06:02:59 +02:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Reference: terraphim/agent-tasks#31