feat: case-insensitive flags and --flag=value separators (F2.3) #31
Notifications
Due Date
No due date set.
Depends on
#4 feat: Wire ForgivingParser into REPL command dispatch
terraphim/agent-tasks
Reference: terraphim/agent-tasks#31
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
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:
--Format jsonshould be treated as--format json.--format=jsonshould be treated as--format json.--verbose,-v,--verbose=trueshould all yieldverbose=true.Verification (no matches today):
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"andterraphim-agent --format=JSON search "x"both produce the same parsed result asterraphim-agent --format json search "x".terraphim-agent search "x" -Vandterraphim-agent search "x" --verbose=trueboth set the verbose flag.metaexposesflag_normalisations: Vec<{from: String, to: String}>so AI consumers can detect that normalisation occurred (mirrors the existingauto_correctedpattern 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 forgivingpasses.cargo clippy -p terraphim_agent -- -D warningspasses.Proposed Approach
pub fn normalise_flag(raw: &str) -> (String, Option<String>)incrates/terraphim_agent/src/forgiving/parser.rsthat:=to separate name and value.--nameportion only (values keep their case so quoted strings survive).-V,-v) via the existingFlagDoc.shortfield onCommandDoc-- look up the canonical long form rather than hard-coding.flag_type == "bool"inFlagDoc, parse the value withbool::from_stragainst an ascii-lowercased copy.ForgivingParser::parse()so the existingParseResultvariants surface the change. Add a new fieldnormalisations: Vec<(String, String)>toParseResult::ExactandParseResult::Corrected.meta.flag_normalisations. Keep field absent when empty (#[serde(skip_serializing_if = "Vec::is_empty")]).Affected crates:
terraphim_agentonly.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
Scope
Single-PR change. Estimated 250-350 lines (parser + tests + meta-field wiring). All logic lives in
terraphim_agent; no cross-crate work.