* feat: resolve @prompt_name saved-prompt references in workflow step prompts
Workflow step prompts, the GitHub review-watch task prompt, and the CI
auto-fix prompt now resolve "@name" references to saved custom prompts
(Settings > Prompts) at invocation time, appending the referenced
content as hidden context while keeping the mention visible - matching
how chat messages and message_task already resolve @mentions. Editing
a saved prompt now propagates to every workflow step that references
it without needing to update each step individually.
Adds a Monaco "@" completion provider to the step-prompt and
review-watch editors, alongside the existing "{{placeholder}}"
provider.
* fix: address PR review findings on prompt-reference expansion
- Make AppendReferenceExpansions idempotent: a prompt that already
contains a previously-appended expansion block is returned unchanged,
since the block's own "### @name" headers would otherwise be
re-scanned as fresh mentions on a second call.
- Skip "@name" expansion entirely for CLI-passthrough sessions: their
prompts are written raw to a PTY with no <kandev-system> stripping,
so the hidden block would otherwise leak into the terminal verbatim.
* fix: fail safe on passthrough lookup error in startTask
A session-lookup error while resolving isPassthrough for the Kandev
MCP wrap and prompt-reference expansion previously defaulted to
false (non-passthrough), risking a hidden <kandev-system> block
leaking into a real passthrough session's PTY on a transient error.
Extracted resolveIsPassthroughForLaunch, which now fails safe by
defaulting to true (skip injection) and logs a warning.
* fix: scope expansion idempotency marker to system blocks
The idempotency guard added in a prior commit checked for the
expansion marker anywhere in the prompt, which could falsely
suppress a legitimate first-time expansion if caller-controlled
text happened to contain that literal phrase. Add
sysprompt.HasSystemMarker, mirroring the existing HasKandevContext
pattern, so the marker is only recognized inside a formatter-
produced <kandev-system> block. Also strengthens a passthrough test
assertion that didn't actually distinguish the snapshot path from
the fail-safe default.
* fix: match exact expansion-block prefix in idempotency guard
The prior scoping fix accepted the marker anywhere inside any
<kandev-system> block, which could still false-positive against an
unrelated system block (e.g. a plan-mode prefix or MCP context
wrap) that happens to mention the marker phrase without it being
the block's own content. Check for the exact literal prefix this
package's formatter produces instead: the opening tag immediately
followed by the marker, with nothing in between.
---------
Co-authored-by: Kandev Agent <agent@kandev.dev>
* feat: press Enter on a dialog to run its semantic action
* fix: harden dialog Enter-to-confirm from review feedback
* fix: refine dialog Enter guards and fix prettier CI
* fix: coalesce ci auto-fix queue rounds
* fix: centralize ci auto-fix round cap
* fix: keep ci auto-fix state fresh
* fix: refine ci auto-fix round status
* fix: handle ci auto-fix exhaustion edge cases
* fix: reduce ci auto-fix dispatch complexity
* fix: refresh pending ci auto-fix before direct prompt
* fix: harden ci auto-fix queue replacement
---------
Co-authored-by: root <root@kandev.ts.net>
* feat(web): surface PR mergeability + conflict state in the CI popover
The CI hover popover showed checks/reviews but nothing about mergeability, so an
unmergeable PR silently dropped its merge button with no reason. Add a mergeability
row that reuses the detail panel's conflict banner + "Resolve conflicts" agent prompt
for dirty PRs, a "Behind base" chip, and a branch-protection note explaining why a
blocked PR is gated. Replace the compact merge split-button+dropdown with an inline
primary + "or <method>" buttons so the menu's detached portal no longer closes the
hover popover.
* feat(web): reflect PR mergeability in status colors and badges
The PR status pill, badge, and chat-input CI chip derived their colour from
checks/reviews only, so a conflicted or blocked PR still read as a green "all good"
check. Map dirty -> red, behind -> amber, and branch-protection blocked -> amber across
getPRStatusColor, the PRStatusIcon badge, and the chip glyph, so the indicators agree
with the popover. Blocked stays sky/in-progress while a requested review is still
outstanding (that's the awaiting-review gate, not a hard block).
* refactor(web): remove dead merge-menu keep-open plumbing
The compact merge control was redesigned to inline buttons (no dropdown portal),
which already fixes the hover popover closing. That leaves the keepOpen ref /
setKeepOpen / onMergeMenuOpenChange / onMenuOpenChange chain threaded through
usePopoverInteractions, PRCIPopover, and PRMergeButton unreachable: the popover
always renders PRMergeButton with compact, and the only DropdownMenu lives in the
non-compact detail-panel path that never passes the callback. Drop the unused
scaffolding (flagged by OpenCode + greptile).
* fix(web): keep CI popover quiet for blocked PRs only awaiting review
PRMergeabilityRow rendered "Blocked by branch protection" for any blocked PR,
including one blocked solely because a requested reviewer hasn't responded. That
contradicted the chip/pill/badge, which deliberately read that case as the calm
"awaiting review" state. Skip the note (render nothing) when isPRAwaitingReview is
true, and narrow blockedReason so an empty checks_state no longer falsely claims a
required status check failed. Flagged by Claude (blocker) and greptile.
* refactor(web): rename mergeability-notice compact prop to popover
The `compact` prop made the chip/text larger (to match the popover's text-xs rows)
while ConflictBanner's `compact` tightened padding — so "compact" rendered bigger,
which reads as inverted. Rename it to `popover` (the variant rendered inside the CI
hover popover) and document that the chip intentionally matches the popover rows.
No visual change. Flagged by cubic.
* fix(web): show default cursor on disabled compact merge alternates
The compact "or <method>" alternates kept cursor-pointer while disabled (during the
~1s merging state); add disabled:cursor-default to match the primary button. Flagged
by OpenCode.
* feat(web): tabbed multi-PR CI popover for topbar button and chat status chip
* test(e2e): cover multi-PR CI popover tabs, chip aggregate, and dropdown
* fix(web): address multi-PR popover review feedback
- suppress hover popover while the PR dropdown is open (no stacked overlays)
- repo-scope tab testids so same-number PRs on different repos stay unique
- guard non-array taskPRs store value in PRStatusChip (same as PRTaskIcon)
- add tablist/tab/aria-selected semantics to the popover tabs
* fix(web): warm default PR only, skip terminal PRs, add tabpanel ARIA
- chip background-sync warms pickDefaultPR (the tab the popover opens), not list head
- PRFeedbackWarmer skips merged/closed PRs (no wasted fetches in topbar path)
- tabpanel role + aria-controls/labelledby wire tabs to the panel
* fix(web): complete ARIA tabs keyboard model in multi-PR popover
- roving tabindex: only the active tab in the page tab order
- ArrowLeft/ArrowRight move selection + focus within the tablist (wrapping)
- stable useId-scoped tabpanel id so every tab's aria-controls resolves
- document topbar-only scoping of prCheckGroup e2e helpers
* refactor(web): skip duplicate rank call for first PR in pickDefaultPR