From eb9c843b6eb8dd6e6b5959a60bb7866648bd0570 Mon Sep 17 00:00:00 2001 From: Madhura68 Date: Sun, 3 May 2026 01:11:12 +0200 Subject: [PATCH] docs(adr): add 0007-claude-question-channel-design --- .../0007-claude-question-channel-design.md | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 docs/adr/0007-claude-question-channel-design.md diff --git a/docs/adr/0007-claude-question-channel-design.md b/docs/adr/0007-claude-question-channel-design.md new file mode 100644 index 0000000..5e77f7c --- /dev/null +++ b/docs/adr/0007-claude-question-channel-design.md @@ -0,0 +1,64 @@ +--- +status: accepted +date: 2026-05-03 +decision-makers: [janpetervisser] +--- + +# ADR-0007: Agent ↔ user question channel via persistent table + LISTEN/NOTIFY + +## Context and Problem Statement + +When Claude Code is executing a task and needs human input, it must be able to pause, post a question, and receive an answer — potentially across separate sessions. The app must notify an active user that a question is waiting. How should this async communication channel be designed? + +## Decision Drivers + +- Questions must survive agent session restarts (persistent, not in-memory). +- The app user needs a real-time notification without polling from the client. +- The infrastructure already includes PostgreSQL with LISTEN/NOTIFY (used for M8 realtime updates). +- Answers must be readable by the agent in a future session without the original connection. + +## Considered Options + +- **Synchronous polling only** — agent polls an endpoint every N seconds. +- **Push via SSE without persistence** — agent opens SSE connection, user pushes answer over it. +- **Persistent `claude_questions` table + PostgreSQL LISTEN/NOTIFY** + +## Decision Outcome + +Chosen option: **Persistent table + LISTEN/NOTIFY**, because it is the only option that survives session restarts on both ends and reuses existing infrastructure. + +### Consequences + +- Good, because questions survive agent and user session restarts. +- Good, because reuses the `scrum4me_changes` LISTEN/NOTIFY channel already in place. +- Good, because any product member with access can answer, not just the original session. +- Bad, because adds a `claude_questions` table and trigger to the schema. +- Bad, because LISTEN/NOTIFY requires a persistent DB connection (`DIRECT_URL` env var). + +### Confirmation + +`docs/patterns/claude-question-channel.md` documents the full implementation. MCP tools: `ask_user_question`, `get_question_answer`, `list_open_questions`, `cancel_question`. + +## Pros and Cons of the Options + +### Synchronous polling only + +- Good, because simple — no extra infrastructure. +- Bad, because agent blocks a CPU slot while polling; question lost if agent restarts. +- Bad, because no real-time notification to the user. + +### Push via SSE without persistence + +- Good, because low latency. +- Bad, because agent-side SSE connection is fragile across restarts. +- Bad, because no persistence — if the user isn't connected at the moment the question is posted, it is lost. + +### Persistent table + LISTEN/NOTIFY + +- Good, because fully durable. +- Good, because real-time notification to the user reuses existing M8 infrastructure. +- Neutral, because requires `DIRECT_URL` for a persistent PostgreSQL connection (already required for M8). + +## More Information + +See `docs/plans/M11-claude-questions.md` and `docs/patterns/claude-question-channel.md`.