Skip to content

feat(gen): split ,omitempty policy by request/response direction#6

Merged
ysyneu merged 1 commit into
mainfrom
feat/omitempty-request-response-split
Jun 2, 2026
Merged

feat(gen): split ,omitempty policy by request/response direction#6
ysyneu merged 1 commit into
mainfrom
feat/omitempty-request-response-split

Conversation

@ysyneu
Copy link
Copy Markdown
Collaborator

@ysyneu ysyneu commented Jun 2, 2026

What

Makes the generator's ,omitempty decision direction-aware:

  • Request structs KEEP ,omitempty — with the existing nullable→pointer rewrite, a nil pointer is omitted while &false/&0 is still sent (tri-state filters / partial-update-to-zero), and a non-nullable zero is genuinely "unset".
  • Response structs DROP ,omitempty — the API returns the field and the CLI re-serializes the decoded struct (--json/--toon). With ,omitempty, a false/0/[]/{} state field the help advertises as present (e.g. rule.enabled=false on a disabled rule) gets silently swallowed, so an agent doing --json | jq '.enabled' sees null instead of false.

Why

Surfaced by the fduty CLI agent-eval: agents reverse-engineering missing keys from omitted zero-valued response fields. For an agent-facing SDK, response fidelity beats wire-minimalism; requests stay lean.

Implementation

The generator already classifies direction (inReq := g.reqGoNames[name] || g.reqSynth[name], already driving the int64-timestamp and nullable-pointer rules). This just threads the same flag into the struct-tag emit. The toon tag is retained on both sides (snake_case keys unchanged — no toon-key regression).

Verification

  • go generate ./...: 27 services, 254 operations, 473 schemas.
  • go build / go vet / go test ./... (round-trip type guard) all green.
  • Spot-check: ListIncidentsRequest (request) keeps acker_ids,omitempty; IncidentInfo (response) renders account_id / ack_time with no ,omitempty.

No spec change. Untagged — no release; CLI/MCP pick it up on their next go get bump.

Request structs KEEP ,omitempty: combined with the nullable→pointer
rewrite, a nil pointer is omitted while &false/&0 is still sent
(tri-state), and a non-nullable zero is genuinely "unset".

Response structs DROP ,omitempty: the API returns the field and the CLI
re-serializes the decoded struct (--json/--toon), so ,omitempty would
silently swallow false/0/[]/{} state fields the help advertises as
present (e.g. rule.enabled=false on a disabled rule). An agent reading a
response field would get a missing key instead of the real value.

The generator already classifies direction (inReq via reqGoNames/
reqSynth, used for the int64-timestamp and nullable-pointer rules); this
just threads the same flag into the struct-tag emit. toon tag retained
on both sides (snake_case keys unchanged). Regenerated models_gen.go;
build + round-trip test green. No spec change, untagged (no release).
@ysyneu ysyneu merged commit 3500a74 into main Jun 2, 2026
4 checks passed
@ysyneu ysyneu deleted the feat/omitempty-request-response-split branch June 2, 2026 04:01
ysyneu added a commit that referenced this pull request Jun 2, 2026
…68) (#7)

Re-vendored openapi/ from flashduty-docs main after #68 removed the 6
dead /channel/notify/rule/* endpoints (backend routes deleted 2023-08,
absent from the pgy registry). Regenerated: operations 254→248, the 6
ChannelNotifyRule* SDK methods drop from channels.go. No model change
(they referenced only shared schemas); the #6 omitempty split is intact.
Untagged — no release.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant