fix(formatters): surface every GraphResponse field in goon output

Summary

Audit follow-up to !1289 (merged). The encoder was silently dropping four pieces of GraphResponse data. This MR routes each one to the wire so a goon consumer has the same information a raw consumer does.

Field Before After
ColumnDescriptor.target / .property count / max (target and property dropped) count(count:v) / max(max:v.updated_at)
GroupColumnDescriptor.property (alias differs from property) severity_bucket(property) severity_bucket(property:severity)
GraphEdge.depth (variable-length traversals) sort key only, depth dropped from output User:1 --> Group:200 depth=2
Value::Null group / metric cell dropped — severity=null, count=5 rendered as count=5 bare null token preserves the dimension

The null rendering is unambiguous because the string "null" already gets quoted as "null" by the existing token-collision guard.

Test plan

  • 57 unit tests in goon::tests (6 new for the data-loss fixes)
  • 7 insta snapshots (two updated for the richer aggregation header)
  • 4 proptest invariants
  • 8 integration subtests against ClickHouse
cargo test -p formatters --tests --all-features
cargo test -p integration-tests --test containers goon_formatter
cargo clippy -p formatters --all-features --all-targets -- -D warnings

[skip goon-format-version-check]

Merge request reports

Loading