Skip to content

[Graphite MQ] Draft PR GROUP:spec_e1a9c4 (PRs 34) - #46

Closed
graphite-app[bot] wants to merge 1 commit into
masterfrom
gtmq_spec_e1a9c4_1790965993749-75852b9f-b820-498f-9f8c-fdcba9754e98
Closed

graphite-app[bot] wants to merge 1 commit into
masterfrom
gtmq_spec_e1a9c4_1790965993749-75852b9f-b820-498f-9f8c-fdcba9754e98

Conversation

@graphite-app

@graphite-app graphite-app Bot commented Oct 2, 2026

Copy link
Copy Markdown

This draft PR was created by the Graphite merge queue.
Trunk will be fast forwarded to the HEAD of this PR when CI passes, and the original PRs will be closed.

The following PRs are included in this draft PR:

…ned (COR-14205) (#34)

## Summary
TOON is the default output in agent mode (`CLAUDECODE`, `CURSOR_AGENT`, …), so it is what every coding agent reads from `vf`. `output.Result` handed the SDK's Go values straight to `gotoon.Encode`, which walks them by reflection and gets the SDK's types wrong in four ways:

- **The key is the whole json tag.** `agent get` showed 42 distinct keys like `"instructions,omitzero"`.
- **Optional-nullable fields render as `null` even when set.** They are a `map[bool]*T` underneath, and gotoon turns a map with non-string keys into null. `agent get --include-instructions` returned 11,934 characters of instructions as JSON and `null` as TOON, so agents never saw the instructions.
- **Unions render as their Go wrapper** (`StableToolV2API: null`, `StableToolV2Function: {…}`) instead of the member the API returned.
- **`omitempty` and `omitzero` are ignored.** Every unset union member is printed, so `document list` came to 4.9 MB of TOON against 1.27 MB of JSON.

The `--include-headers` path already avoided all of this by encoding the JSON form. A shared `jsonValue` helper now does the same for plain TOON: marshal with the SDK's JSON rules, decode into plain maps and slices, then encode. TOON carries exactly what `--output-format json` does. JSON, YAML, table and pretty output are unchanged.

## Before and after
Measured live and read-only on a real project.

| | master | this PR |
|---|---|---|
| `agent get`: keys with tag options | 42 | 0 |
| `agent get --include-instructions`: instructions | `null` | present (11,934 chars) |
| `tool list --global`: shape | Go wrappers | the API's shape |
| `document list`: TOON size (JSON is 1.27 MB) | 4.9 MB | 1.4 MB |
| `document list`: run time | ~1.1 s | ~1.1 s |

## Test plan
- [x] `gofmt`, `go vet ./...` and `go test ./...` pass; `go.mod` is unchanged.
- [x] `internal/output/toon_test.go`: 4 Go tests on real SDK types. They cover plain keys, a set optional-nullable field, a flat union, and TOON equal to the JSON output re-encoded. All 4 fail on master and pass here.
- [x] `test/toon-output.test.ts`: 3 hermetic cases on the built binary. They run with a mock server, isolated HOME and agent mode. All 3 fail with master's binary and pass here.
- [x] Live before and after on a real project, as in the table.
- [ ] CI

The 4 vitest cases that already fail on master (`docs-command` ×2, `flag-errors`, `flag-raw-text`) still fail here and are unrelated.

Fixes COR-14205
@graphite-app graphite-app Bot closed this Oct 2, 2026
@graphite-app
graphite-app Bot deleted the gtmq_spec_e1a9c4_1790965993749-75852b9f-b820-498f-9f8c-fdcba9754e98 branch October 2, 2026 18:33
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