From 05d1c2fceab8158f4a81615a36b64644610997f7 Mon Sep 17 00:00:00 2001 From: Andrew Lee Date: Sun, 14 Jun 2026 20:57:12 -0700 Subject: [PATCH] docs: document and guard the operational --json shapes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AGENT.md described abort/undo/repair only as "small { ... } objects, see st help " — but st help renders commandInfo (name/summary/ usage/aliases/flags), which carries none of the result keys, so the redirect pointed agents at the wrong shape. The emitted keys (aborted, undone, label, restored, repaired, fixes) appeared in no drift-guard. Document the three fixed shapes explicitly and extend TestAgentDoc- DocumentsEmittedKeys to drive abort (over a real paused rebase), undo, and repair so every key they emit is pinned to AGENT.md, matching the guard already covering status/checkout/validate/log/navigation. --- cmd/commands_json_test.go | 18 +++++++++++++++--- docs/AGENT.md | 7 ++++++- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/cmd/commands_json_test.go b/cmd/commands_json_test.go index ecc0ae3..28425e4 100644 --- a/cmd/commands_json_test.go +++ b/cmd/commands_json_test.go @@ -753,11 +753,13 @@ func collectJSONKeys(v any, into map[string]bool) { } } -// TestAgentDocDocumentsEmittedKeys runs the read/navigation commands that emit -// anonymous inline structs (status, checkout, validate, navigation, log) — which +// TestAgentDocDocumentsEmittedKeys runs the read/navigation commands and the +// operational commands (abort/undo/repair) that emit anonymous inline structs +// (status, checkout, validate, navigation, log, abort, undo, repair) — which // reflection cannot reach by name — and asserts every JSON key they actually // emit is documented in AGENT.md. The fixture surfaces status's omitempty keys -// (parent, needsRestack) by running on a tracked branch with a parent and child. +// (parent, needsRestack) by running on a tracked branch with a parent and child, +// and drives a real paused rebase so abort has something to abort. func TestAgentDocDocumentsEmittedKeys(t *testing.T) { doc := agentDoc(t) newRepo(t) @@ -807,6 +809,16 @@ func TestAgentDocDocumentsEmittedKeys(t *testing.T) { t.Fatal("expected a conflict restacking conf-b onto the amended conf-a") } collect("status --json (conflict)", func() error { return runStatus([]string{"--json"}) }) + // The paused rebase is still in progress; aborting it surfaces abort's keys. + collect("abort --json", func() error { return runAbort([]string{"--json"}) }) + + // repair on a consistent stack and undo of the last mutation surface the + // remaining operational keys (repaired/fixes, undone/label/restored). + newRepo(t) + mustInit(t) + mustCreate(t, "op-a", "a.txt", "a\n", "add a") + collect("repair --json", func() error { return runRepair([]string{"--json"}) }) + collect("undo --json", func() error { return runUndo([]string{"--json"}) }) for k := range keys { if !documentsKey(doc, k) { diff --git a/docs/AGENT.md b/docs/AGENT.md index 4fe14cd..911e65b 100644 --- a/docs/AGENT.md +++ b/docs/AGENT.md @@ -82,7 +82,12 @@ message. - **`init --json`** — one shape for both outcomes: `{ "trunk", "initialized": bool, "alreadyInitialized": bool }` (a fresh init sets `initialized`; an already-initialized repo sets `alreadyInitialized`). -- **operational** (`abort`, `undo`, `repair`) — small `{ ... }` objects, see `st help `. +- **operational** — each emits a small fixed object: + - `abort --json` → `{ "aborted": true, "summary" }`. + - `undo --json` → `{ "undone": true, "label", "restored": [] }` (`label` names the + reverted command; `restored` lists branches whose tips were moved back). + - `repair --json` → `{ "repaired": bool, "fixes": [] }` (`repaired` is true when + `fixes` is non-empty; both are present on every run). ## Idempotency & safety