Accepted. Superseded in part by ADR 0006 for execution, concurrency, and webhook response timing. Production uses pg-boss workers only. Bare thread replies without an @bot mention do not enqueue ask work. Durable admission limits for both triggers are defined in ADR 0031.
Contributors and reviewers need to ask ad hoc questions about PR code (for example, "what is this hook for?") and to follow up on inline findings ("why is this a P0?") without triggering a full review. Upstream qodo-pr-agent implements /ask as a single LLM call with the PR diff (or selected diff hunk for inline comments) embedded in the prompt.
This repo already runs reviews through a Pi-AI tool loop over a local PR workspace (ADR 0011, ADR 0023). Production ask execution uses pg-boss workers (ADR 0006).
-
Triggers β
/askslash command onissue_commentandpull_request_review_comment(createdonly), parsed on the first non-empty line like other commands; or an@-mention of the app bot login (and optional slug without[bot]) anywhere on those surfaces, subject to the same association allowlist as slash commands. Bare non-mention replies do not enqueue ask work. -
Tool-loop investigation β Ask runs call local workspace tools and Context7 doc lookup when needed. The model does not receive the full PR diff upfront. When the webhook includes a code anchor (inline review comment), path, line range, and
diff_hunkare injected into the user message as the starting point. -
Thread transcript β Before the LLM turn, the ask worker loads the containing comment thread (inline review comments grouped by root, or PR conversation thread when
in_reply_to_idis available) and injects it as untrustedthread_transcriptcontext. Fetch failures soft-degrade to question-only. A char cap keeps oversized threads bounded (root + newest tail). -
Separate ask lane β Ask runs enqueue on pg-boss
agent-work-askwith workerlocalConcurrencyfromASK_CONCURRENCY(default 1), not the review queue, so interactive Q&A does not share review worker slots. -
Split reply format (matches upstream UX):
- Inline review thread: plain answer only.
- PR conversation:
**Question:**/**Answer:**wrapper.
-
Explain-only β Ask runs do not change finding severity, dismiss findings, resolve threads, or edit review summaries.
-
Failure handling β One retry nudge, then text-only fallback, then an honest short failure reply if still stuck. The terminal hook treats only a completed
ask_replypublish record or a recovered comment id as a delivered answer. Anoutcome_unknownanswer mutation does not suppress the failure. An undelivered ask posts exactly one failure reply through theask:failure_replyoperation-intent key. -
Style β System prompt requires simple, humane prose with no em dashes and no AI-tell openers; enforcement is prompt-only (no post-processing).
- Ask runs may take longer than upstream's single-call
/askbut can trace symbols across the repo beyond the inline hunk and continue a natural conversation in-thread. - The webhook returns
200after durable intake and enqueue; the ask answer is posted asynchronously byROLE=worker. If intake exceeds the configured webhook response budget, the request returns503before GitHub reports a delivery timeout. CONTEXT.mdAsk run documents mention triggers and thread context.
- Production routing:
AgentWorkScheduler.submitSlashCommandβagent-work-askjob βrunAskRunin the worker (thread load inaskExecutor). - Mention detection:
parseBotMention+ webhook handlers.
Remove mention handling from webhookHandlers.ts, drop thread transcript loading from the ask executor, and revert ask prompt/user-content changes.