backnotprop / backnotprop/plannotator

Claude Code: plan annotations are silently dropped when the plan is approved (approve path never sends feedback to the agent)

Open
#1,359 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
8.7k
Forks
649
Avg merge
11h 12m
Merged PRs (30d)
109

Description

## Summary

When reviewing a plan in the annotation UI for Claude Code, any annotations added before clicking **Approve** are silently dropped — the agent never sees them. Annotations only reach the agent when the plan is **denied**. The Gemini CLI approve path already forwards feedback via `systemMessage`; the Claude Code approve path does not.

## Environment

- plannotator 0.27.4 (also present in the 0.27.3 source I checked)
- Claude Code on WSL2, PermissionRequest hook on ExitPlanMode

## Steps to reproduce

1. Enter plan mode in Claude Code, have the agent submit a plan (ExitPlanMode).
2. The plannotator review page opens. Add one or more line annotations.
3. Click **Approve** (with annotations still present).
4. The plan is approved and execution continues.

## Actual behavior

The agent receives only the allow decision. None of the annotations are delivered into the conversation — the agent never learns the feedback existed. The annotations are written to `/.annotations.md`, but nothing surfaces them to the agent.

## Expected behavior

On approve, forward the collected feedback to the agent (e.g. as `systemMessage`), mirroring the Gemini CLI path.

## Root cause

`server/index.ts` (0.27.4):

- **Gemini approve path (line 2249)** — feedback IS forwarded:
```ts
console.log(result.feedback ? JSON.stringify({ systemMessage: result.feedback }) : "{}");
```

- **Claude Code approve path (lines 2263–2292)** — outputs `hookSpecificOutput` with `decision.behavior: "allow"` (+ `updatedInput` / `updatedPermissions`) but never includes `result.feedback`. Only the deny branch of the Claude Code path includes feedback (as `decision.message`).

## Suggested fix

In the Claude Code approve branch, attach the feedback, e.g.:

```ts
console.log(
JSON.stringify({
hookSpecificOutput: {
hookEventName: "PermissionRequest",
systemMessage: result.feedback || undefined,
decision: { /* existing allow output */ },
},
})
);
```

The current UX makes "annotate + approve" (notes for the agent to keep in mind while executing) indistinguishable from "plain approve", which reads as data loss rather than intent.

## Workaround

Deny the plan to have feedback delivered, or manually paste the contents of `.annotations.md` into the conversation.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.