feat: json parameters with declared schemas + CLI representation overrides (COD-411) - #3
Conversation
…rides (COD-411) Add generic parameter capabilities so consumers can express non-scalar inputs without inference: - type: json parameters (body-only) with an explicitly declared JSON Schema subtree embedded verbatim into generated MCP tool inputSchemas - cli: representation overrides: kebab-case flag rename, multiple: true (repeatable Vec<String> flag with ArgAction::Append), and companion CLI-only repeatable flags (e.g. --attach-mime) emitted as Option<Vec<String>> fields excluded from HTTP/MCP - validation: json params require schema + body location; schema is json-only; cli: blocks only on CLI-generating operations; json params on CLI ops must declare a cli: block (no inferred shape); multiple is json-only; flag/field collisions rejected across params + companions - parameters_json() maps CLI shape back to wire names; companions ride as sibling keys - definitions not using the feature generate byte-identical output (guarded by fixture test) Dogfood: examples/notes annotate_note carries an attachments-style closed inline/stored union end-to-end — repeatable --attach + --attach-mime CLI parsing, MCP schema embedding, HTTP union validation with 400 on malformed unions. 43/43 tests, all five gates green.
…validation, required multiple flags (COD-411) - Companion flags now emit their declared flag verbatim instead of letting clap derive from the field name - Collision validation registers EVERY CLI-visible parameter (default shape included), so explicit flags/fields cannot collide with derived defaults; path parameters cannot carry cli: blocks - cli: without flag: emits plain #[arg(long)] — clap derives kebab from the field, same as default shape; no snake_case long names - required: true + multiple: true now emits required = true on the clap attribute, so requiredness holds on the CLI surface too - MCP schema merge policy documented: schema-level description wins; parameter description fills in only when absent - 6 new regression tests for every panel finding; 49/49 green, all five gates clean, codegen check + write-twice determinism verified
🤖 Automated Review PanelDual-model review ran before this PR was opened. Round 1 findings were fixed in 1a2c238 with regression tests added for each. GPT-5.5 (openai/gpt-5.5) — Round 1 verdict: BLOCK → resolved
Gemini 3 Flash (google/gemini-3-flash-preview) — Round 1 verdict: BLOCK → resolved
Round 2 statusAll four findings fixed with regression tests; 49/49 tests green; build/clippy/fmt/codegen-check + write-twice determinism all clean. Note for Shiv: none of the round-1 suggestions were style nits — all were real correctness gaps the panel caught pre-merge. The |
Auto-Merge Gate ApprovalConfidence: 0.92 — threshold 0.80. Merging as squash. GoalCOD-411 "hydra: json parameters with declared schemas + CLI representation overrides". Verified against the Linear ticket description, deliverables, constraints, and verification criteria — all satisfied. Rationale
Checks observed (all green, independently verified)
Scope limits respected
Confidence rationale basis: PR body, COD-411 Linear issue, full diff vs main, green checks, resolved review panel. Not merged on vibes. |
Summary
Adds generic, explicitly-declared parameter capabilities to hydra so consumers (iris) can express non-scalar inputs without inference. Unblocks COD-406 (IRIS-11 PR3) which needs
send_messageto accept a closed inline/stored attachment union.Closes COD-411.
What lands
type: jsonparameters with declared schemasschema:)Value; runtime validatescli:representation overridesflag:— kebab-case rename for any non-path parametermultiple: true— repeatableOption<Vec<String>>flag withArgAction::Append(json params only);required: true+multiple: trueemitsrequired = trueso requiredness holds on CLIcompanions:— CLI-only repeatable string flags (explicitflag/field/description), excluded from HTTP/MCP, riding as sibling keys inparameters_json()Validation (generation-time, per hydra law)
cli:blocks only on CLI-generating operations; json params on CLI ops must declarecli:(no inferred shape)cli:blocks (positional contract preserved)Dogfood (examples/notes)
annotate_notecarries an attachments-style closed inline/stored union end-to-end: repeatable--attach+--attach-mimeCLI parsing, MCP schema embedding, HTTP union validation (400 on malformed unions).Verification
All five gates green locally:
cargo build --all-targets— 0 errorscargo test --all-targets— 49/49 passedcargo clippy --all-targets -- -D warnings— 0 errorscargo fmt --all -- --check— cleanhydra-codegen check— artifacts current; write-twice determinism verified (identical md5s)Definitions not using the feature generate byte-identical output (fixture test guards this). Additive-only: consumers pinned on tags (iris v0.1.1, rite v0.1.1) unaffected.
Review panel
Dual-model review ran before opening. Round 1 flagged 4 findings (companion flag ignored in emission, collision validation missing default-shaped params, snake_case long names from
cli:withoutflag, required+multiple weakening requiredness) — all fixed in 1a2c238 with regression tests. Full reviews posted as PR comment.Follow-up
v0.2.0after merge → iris PR pins the tag and adopts (COD-406 T8–T10)load_api_definition+ defaults)