refactor: route command JSON output through PrintJSON helper

Summary

  • Migrate all 21 remaining inline json.Marshal / json.NewEncoder + manual stdout-write call sites to IOStreams.PrintJSON. The helper was added in ba8e90ef to fix the nil slice → null serialization bug, but only about half the commands adopted it; the rest kept marshaling inline. After this MR, every command's JSON output flows through one path.
  • Add a forbidigo golangci-lint rule that bans json.Marshal, json.MarshalIndent, and json.NewEncoder outside the helper, so this drift can't re-accumulate.
  • Annotate 10 legitimate non-stdout call sites (HTTP request bodies, on-disk caches, the git credential helper protocol, git/stacked.go storage, and PrintJSON itself) with //nolint:forbidigo plus a one-line reason.

Behavior change

Output for commands that previously pretty-printed JSON is now compact (single-line). The affected commands are variable export, mr note list, token create, cluster agent get-token, and workitems list. The bytes are semantically identical JSON, so any consumer (jq, scripts, parsers) behaves the same; only human-eyeballing the raw output changes. This brings them in line with every other command, which was already compact.

Test plan

  • go test ./... passes locally (verified)
  • golangci-lint run ./... reports 0 issues locally (verified)
  • Spot-check a migrated command in JSON mode: e.g. + "glab mr list -F json | jq '.[0].iid'" + produces a sensible result
  • Spot-check a non-stdout + "json.Marshal" + site (e.g. + "glab api projects/" + ) still functions — those paths build HTTP request bodies, not user output
Edited by Kai Armstrong

Merge request reports

Loading