feat: bidirectional AI conversation, context persistence, and approve-with-notes#317
Conversation
…rove-with-notes Phase 1 - Approve with Comments: - Replace 'Annotations Won't Be Sent' warning with 'Approve with Notes' flow - Pass user annotations through as implementation notes on approve (Claude Code) - Add planApproveWithNotesFeedback() shared template Phase 2 - Context Persistence: - Track review sessions across deny/revise cycles with session IDs - Persist iterations to ~/.plannotator/sessions/ with Q&A history - Enhanced planDenyFeedback() includes previous iteration context - Add Review History sidebar tab showing iteration timeline - Plan metadata embedding (session ID, questions) via HTML comments Phase 3 - Bidirectional AI Conversation: - AI can embed clarification questions in plans via structured metadata - WebSocket support in plan server for real-time question updates - ClarificationPanel UI with 5 question types (pick_one, pick_many, confirm, ask_text, show_options) - Question answers flow back to AI through approve/deny feedback - CLARIFICATION_QUESTIONS_PROMPT teaches AI the question format Inspired by github.com/vtemian/octto branch-based Q&A patterns.
|
Big feature, thanks. Was thinking about this myself. Ill review shortly. |
Question
I dont think this is actually supported by the claude hook though, or did they update it? |
|
| Field | Description |
|---|---|
behavior |
"allow" grants the permission, "deny" denies it |
updatedInput |
For "allow" only |
updatedPermissions |
For "allow" only |
message |
For "deny" only: tells Claude why the permission was denied |
interrupt |
For "deny" only |
So the current code in apps/hook/server/index.ts that does:
decision: {
behavior: "allow",
message: planApproveWithNotesFeedback(result.feedback) // ← silently ignored by Claude Code
}...will have the message silently discarded. The plan proceeds but the user's annotations/notes are lost.
The OpenCode plugin is fine
The OpenCode plugin (apps/opencode-plugin/index.ts) uses a tool-based approach (submit_plan tool) where the return string is the feedback — so approve-with-notes already works correctly there.
Possible fixes for Claude Code
-
"Deny-as-approve" pattern: When user selects "Approve with Notes", actually send
behavior: "deny"with a softer message like "Plan approved with minor notes — proceed with implementation, incorporating these suggestions...". The AI sees it as a deny but the tone guides it to continue rather than fully re-plan. -
PostToolUse hook: Send
allow, then use a separatePostToolUsehook onExitPlanModeto inject notes as context. More complex but semantically correct. -
Skip for Claude Code: Only support approve-with-notes for OpenCode. For Claude Code, revert to the original warning dialog behavior.
The rest of the PR (Phase 2: Context Persistence, Phase 3: Bidirectional Conversation) is unaffected by this issue since those features use the deny path for feedback delivery.
Summary
This PR addresses two major user complaints and adds three interconnected features inspired by Octto's branch-based Q&A patterns:
Approve with Notes — Users can now add annotations AND approve the plan in one step. No more forced choice between "approve silently" or "deny with feedback."
Context Persistence — Review sessions now survive across deny/revise cycles. Previous iterations' feedback, questions, and answers are accumulated and fed back to the AI with each revision.
Bidirectional AI Conversation — The AI can now embed clarification questions in plans that appear as interactive question cards in the review UI. Users answer visually; responses flow back through the approve/deny feedback loop.
Changes
Phase 1: Approve with Notes (smallest change, immediate value)
packages/shared/feedback-templates.ts: NewplanApproveWithNotesFeedback()templateapps/hook/server/index.ts: Pass user annotations through asmessagefield in theallowdecision (Claude Code)packages/editor/App.tsx: Replace "Annotations Won't Be Sent" warning with "Approve with Notes" confirmation dialog; always show full-green Approve buttonPhase 2: Context Persistence
packages/shared/questions.ts(NEW): Types forReviewIteration,ReviewSession,ClarificationQuestion,QuestionAnswer; plan metadata parsing (extractSessionId,extractQuestions,stripPlanMetadata)packages/server/review-session.ts(NEW): Session persistence to~/.plannotator/sessions/, with auto-cleanup of sessions older than 7 dayspackages/shared/feedback-templates.ts: EnhancedplanDenyFeedback()now includes accumulated iteration history and Q&A contextapps/hook/server/index.ts&apps/opencode-plugin/index.ts: Session tracking (extract/generate ID, load previous iterations, record after decision)packages/server/index.ts: NewGET /api/sessionendpoint for UI to fetch session statepackages/ui/components/sidebar/ReviewHistory.tsx(NEW): Review History sidebar tab with iteration timeline, expandable feedback summaries, and Q&A displaypackages/ui/components/sidebar/SidebarContainer.tsx&SidebarTabs.tsx: History tab integrationpackages/ui/hooks/useSidebar.ts: Added"history"toSidebarTabtypePhase 3: Bidirectional AI Conversation
packages/server/questions.ts(NEW): Question session management with waiters, answer submission, and state trackingpackages/server/index.ts: WebSocket support via Bun's native WS,POST /api/answersandGET /api/questionsendpoints, answers included in decision resolutionpackages/shared/prompts.ts(NEW):CLARIFICATION_QUESTIONS_PROMPTteaching AI the question embedding formatpackages/ui/components/ClarificationPanel.tsx(NEW): Modal panel with 5 question types (pick_one,pick_many,confirm,ask_text,show_options), badge with pulse animation, answered/unanswered statespackages/editor/App.tsx: WebSocket connection for real-time question updates, answer submission handler, ClarificationBadge in header, panel overlayHow It Works
AI Embeds Questions in Plans
Session Continuity
When a plan is denied, the feedback includes:
<!-- plannotator:session ID -->in the next submissionQuestion Types
pick_onepick_manyconfirmask_textshow_optionsFiles Changed
packages/shared/questions.tspackages/shared/prompts.tspackages/shared/feedback-templates.tspackages/server/index.tspackages/server/questions.tspackages/server/review-session.tspackages/editor/App.tsxpackages/ui/components/ClarificationPanel.tsxpackages/ui/components/sidebar/ReviewHistory.tsxpackages/ui/components/sidebar/SidebarContainer.tsxpackages/ui/components/sidebar/SidebarTabs.tsxpackages/ui/hooks/useSidebar.tsapps/hook/server/index.tsapps/opencode-plugin/index.ts14 files changed, ~2000 lines added