Blocked on next major version bump. Filing now so the prose promise in crates/cli/src/output_envelope.rs:1083-1086 and docs/backwards-compatibility.md:23 exists as a tracked issue rather than only as inline commentary that risks evaporating.
Today
FallowOutput is #[serde(untagged)] so consumers must variant-narrow by checking unique-field presence (e.g. summary.total_issues for check, health_score for health, etc.). This is documented in docs/backwards-compatibility.md and works correctly today, but every consumer pays the field-presence-test tax on every payload.
Plan
- Add
#[serde(tag = "kind")] to FallowOutput, switching to internally-tagged untagged-fallback semantics so payloads carry a unique top-level kind: "<command>" field.
- Ship one minor cycle with a
--legacy-envelope opt-out flag that re-emits the untagged form for consumers that need a deprecation grace period.
- Remove
--legacy-envelope in N+1.
Impact
- AI agents and MCP consumers get O(1) variant narrowing.
- Schema-validating clients can drop their unique-field-presence rules.
- This is a wire-shape change so it must bump
schema_version and ride the next major bump.
Acceptance
FallowOutput carries #[serde(tag = "kind")] in crates/cli/src/output_envelope.rs.
docs/backwards-compatibility.md documents the new discriminator and the --legacy-envelope deprecation timeline.
CodeClimateOutput stays an untagged sibling (the array shape cannot carry an internal tag); discriminate against it via root-level "is it an array" first.
- The inline doc comment on
FallowOutput is updated to reflect the new shape.
Refs #384 (this completes the typed-root work that #391 started).
Blocked on next major version bump. Filing now so the prose promise in
crates/cli/src/output_envelope.rs:1083-1086anddocs/backwards-compatibility.md:23exists as a tracked issue rather than only as inline commentary that risks evaporating.Today
FallowOutputis#[serde(untagged)]so consumers must variant-narrow by checking unique-field presence (e.g.summary.total_issuesfor check,health_scorefor health, etc.). This is documented indocs/backwards-compatibility.mdand works correctly today, but every consumer pays the field-presence-test tax on every payload.Plan
#[serde(tag = "kind")]toFallowOutput, switching to internally-tagged untagged-fallback semantics so payloads carry a unique top-levelkind: "<command>"field.--legacy-envelopeopt-out flag that re-emits the untagged form for consumers that need a deprecation grace period.--legacy-envelopein N+1.Impact
schema_versionand ride the next major bump.Acceptance
FallowOutputcarries#[serde(tag = "kind")]incrates/cli/src/output_envelope.rs.docs/backwards-compatibility.mddocuments the new discriminator and the--legacy-envelopedeprecation timeline.CodeClimateOutputstays an untagged sibling (the array shape cannot carry an internal tag); discriminate against it via root-level "is it an array" first.FallowOutputis updated to reflect the new shape.Refs #384 (this completes the typed-root work that #391 started).