Skip to content

fix(annotate): offer Approve with a note in every gated session that delivers it - #1728

Merged
backnotprop merged 2 commits into
mainfrom
fix/annotate-approve-with-note
Oct 6, 2026
Merged

backnotprop merged 2 commits into
mainfrom
fix/annotate-approve-with-note

Conversation

@backnotprop

Copy link
Copy Markdown
Owner

What the owner saw

A gated annotate session (often an HTML plan from the visual-explainer skill, which runs plannotator annotate <file> --gate) showed Approve and Request changes…, but no Approve with a note….

The item shows only when /api/plan sends approvalNotesSupported: true. The Bun CLI set that only for --gate --json. Every Claude Code path launches plain --gate, so all of them got false:

  • the mod's plannotator tool with gate: true
  • /plannotator-annotate x --gate
  • a taken-over plannotator annotate x --gate Bash run
  • the classic skill bang line

HTML is not the cause. Markdown, raw-HTML and live-app surfaces build the header from the same buildDecisionSpec input. The only HTML-specific header option is dismissOnIframeFocus.

In a non-gated session (no --gate), the header shows Done and Send a note…. That is intended: the maintainer ruled that "Done with a note…" and "Request changes…" collapse into one composer, because both used the same /api/feedback transport.

Fix

  • supportsAnnotateApprovalNotes is now gate && !hook. --json is no longer required.
  • In plaintext mode, an approval that carries a note prints the configured approvedWithNotes prompt, with the File: / Folder: / URL: / Files: context. This matches what review plaintext already does. A bare approval still prints The user approved. byte for byte, and before this change plaintext could never carry a note.
  • The Claude Code mod needs no change. Its result file already sends approved-with-notes as a turn (noop: false).
  • --hook stays off, because the hook protocol carries no message on approval.
  • The skill and command templates (Claude, Gemini, Copilot, core annotate) now recognize the "Approved with Notes" message. The docs and AGENTS.md are updated.

Per-host advert (gated sessions)

Launch path Advert before Advert after How the note reaches the agent
CLI annotate --gate --json (also strict --require-approval / --result-file) true true JSON feedback / strict record feedback
CLI annotate --gate (plain; classic skill, visual-explainer, Codex/Gemini/Copilot/Vibe/Kiro skills) false true approved-with-notes prompt on stdout
Claude Code mod: tool gate: true, /plannotator-annotate x --gate, taken-over Bash false true result file → approved-with-notes plugin turn
CLI annotate-last / copilot-last --gate (plain or json) json only true same as above
CLI --gate --hook false false dropped (hook has no approve message)
OpenCode CLI bridge (annotate … --json --gate), opencode-annotate-last true true bridge composes approved-with-notes
OpenCode embedded commands true with session unchanged commands.ts
Amp / Droid (always --json) true when gated true plugin composes approved-with-notes
Pi (tool / slash) true unchanged index.ts approved-with-notes
Non-gated annotate (any host) n/a n/a no approve channel; "Send a note…" (feedback)

Proposal, not implemented: non-gated "Done with a note"

A note in a non-gated session already reaches the agent as feedback through "Send a note…". The maintainer collapsed the old "Done with a note…" / "Request changes…" pair because both posted the same /api/feedback. Only the framing differed: approvalFraming in buildCompleteAnnotateFeedback.

Bringing back a positive-note item would mean adding that framing back to the empty-state menu. That reverses the ruling, so I left it for the owner to decide.

Tests

  • annotate-output.test.ts
    • checks the predicate
    • plaintext approve-with-note uses the configured prompt and context
    • a whitespace-only note falls back to the bare marker
    • every startAnnotateServer call site sets approvalNotesSupported
  • annotate-host-result.test.ts runs the real process the way the mod launches it (page.html --gate with the result file):
    • /api/plan advertises the item on an HTML surface
    • the note reaches stdout and the host record
    • a bare approval keeps the marker and stays a no-op
    • --hook keeps the advert off

The UI code is unchanged, so no DOM tests were added.

Results: bun test apps/hook apps/skills apps/opencode-plugin apps/amp-plugin (883 pass), bun run typecheck, build:review + build:hook, and a Bun bundle of the CLI all pass.

…delivers it

The annotate header hid "Approve with a note…" / "Approve with notes" unless
the CLI ran with --gate --json. The Claude Code mod (plannotator tool gate:true,
/plannotator-annotate x --gate, taken-over Bash runs) and the classic skill launch
plain --gate, so a gated review there (markdown or HTML) had no way to approve
with a note, even though the mod's result file already delivers an
approved-with-notes turn.

- supportsAnnotateApprovalNotes is now gate && !hook.
- Plaintext approval with a note prints the configured approvedWithNotes prompt
  (with the File/Folder/URL/Files context); a bare approval still prints
  "The user approved." byte for byte. --hook stays off (no message on approve).
- Skill/command templates recognize the Approved with Notes message; docs updated.
- Docs: the plannotator skill's plaintext contract and AGENTS.md
  "Strict direct annotate results" name the one plaintext change (an
  approval with a note prints the approved-with-notes message).
- Mod legacyResult recognizes the default "# Approved with Notes" heading
  on annotate surfaces, so a launch with no result.json is still delivered
  as "Approved with notes" rather than as feedback.
- annotateContextLine (host-result.ts) is the one File:/Folder:/URL:/Files:
  helper for both the result file and plaintext stdout; parity test.
- The call-site scan requires supportsAnnotateApprovalNotes( at every
  startAnnotateServer site except opencode-annotate-last.
@backnotprop
backnotprop merged commit bf307e2 into main Oct 6, 2026
28 checks passed
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