Context
apps/loopover-miner-ui/src/lib/chat-portfolio-queue-actions.ts already ships a complete, tested,
end-to-end portfolio release/requeue chat pipeline: handlePortfolioQueueChatCommand (line 246)
resolves free text via resolvePortfolioQueueChatAction, matches it against a live queue item,
registers the chat action, dispatches it through the shared dispatchChatAction chokepoint-gated
layer, and formats the outcome as a ChatMessage. apps/loopover-miner-ui/src/components/chat/governor-action-result.tsx
similarly ships a ready-to-render GovernorChatActionResult component for inline action outcomes.
Both were built and merged as part of issues #6520/#6838 (portfolio) and #6521 (governor), which
closed as done.
None of this is actually reachable from the live chat surface. apps/loopover-miner-ui/src/components/chat/conversation.tsx
(ChatConversation, the component chat-rail.tsx mounts) has exactly one code path in handleSubmit:
it always calls streamChatImpl (defaulting to streamChat → POST /api/chat) and never calls
handlePortfolioQueueChatCommand or any other action handler. The component's own header comment
(conversation.tsx:16) states this explicitly: "it never touches an action endpoint (portfolio
release/requeue, governor pause/resume) — that surface is a separate, later, flag-gated issue."
A repo-wide search confirms handlePortfolioQueueChatCommand and GovernorChatActionResult are
imported nowhere outside their own module and their own test files.
Net effect: typing "release owner/repo" (or "requeue owner/repo #12") into the chat rail today is
always answered by the read-only grounding backend as an ordinary question — it can never actually
release or requeue a queue item, even though the entire pipeline for doing so, including its own
params validator, chokepoint gating, and result-formatting, is fully built and unit-tested.
Requirements
- In
ChatConversation's submit path, attempt to resolve the operator's message as a portfolio-queue
action via resolvePortfolioQueueChatAction (from apps/loopover-miner-ui/src/lib/chat-portfolio-queue-resolve.ts)
before falling back to the read-only streamChat path.
- When the message resolves to a portfolio action, call
handlePortfolioQueueChatCommand and append
its returned message(s) to the conversation instead of opening a streamChat request.
- When the message does not resolve to a portfolio action, fall through to the existing
streamChat
behavior unchanged — this must not narrow or change ordinary Q&A behavior in any way.
- The composer must disable for the duration of the action dispatch, exactly as it already does for a
streamChat round-trip, so a second submission cannot race an in-flight action.
- No new HTTP route, no new fetch call, and no change to
handlePortfolioQueueChatCommand,
resolvePortfolioQueueChatAction, or the underlying /api/portfolio-queue/{release,requeue} routes —
this issue is wiring only, reusing the existing, already-tested pipeline exactly as built.
Deliverables
Test Coverage Requirements
apps/** is listed under ignore: in codecov.yml, so this app is not gated by Codecov's 99% patch
check — but the local npm run test:coverage invariant bar still applies, and a regression test is
required: one test asserting a "release owner/repo"-shaped message dispatches through
handlePortfolioQueueChatCommand (not streamChat), and one asserting an ordinary question still
reaches streamChat unchanged. Since this is a visual/interactive change to the chat rail, a
before/after screenshot (or short clip) of a resolved action's outcome appearing inline in the
conversation is required per this repo's UI-PR convention.
Links & Resources
Epic: #6504. apps/loopover-miner-ui/src/components/chat/conversation.tsx,
apps/loopover-miner-ui/src/lib/chat-portfolio-queue-actions.ts (handlePortfolioQueueChatCommand,
line 246), apps/loopover-miner-ui/src/lib/chat-portfolio-queue-resolve.ts. Closed issues that built
the now-unreachable pipeline: #6520, #6838.
Context
apps/loopover-miner-ui/src/lib/chat-portfolio-queue-actions.tsalready ships a complete, tested,end-to-end portfolio release/requeue chat pipeline:
handlePortfolioQueueChatCommand(line 246)resolves free text via
resolvePortfolioQueueChatAction, matches it against a live queue item,registers the chat action, dispatches it through the shared
dispatchChatActionchokepoint-gatedlayer, and formats the outcome as a
ChatMessage.apps/loopover-miner-ui/src/components/chat/governor-action-result.tsxsimilarly ships a ready-to-render
GovernorChatActionResultcomponent for inline action outcomes.Both were built and merged as part of issues #6520/#6838 (portfolio) and #6521 (governor), which
closed as done.
None of this is actually reachable from the live chat surface.
apps/loopover-miner-ui/src/components/chat/conversation.tsx(
ChatConversation, the componentchat-rail.tsxmounts) has exactly one code path inhandleSubmit:it always calls
streamChatImpl(defaulting tostreamChat→POST /api/chat) and never callshandlePortfolioQueueChatCommandor any other action handler. The component's own header comment(conversation.tsx:16) states this explicitly: "it never touches an action endpoint (portfolio
release/requeue, governor pause/resume) — that surface is a separate, later, flag-gated issue."
A repo-wide search confirms
handlePortfolioQueueChatCommandandGovernorChatActionResultareimported nowhere outside their own module and their own test files.
Net effect: typing "release owner/repo" (or "requeue owner/repo #12") into the chat rail today is
always answered by the read-only grounding backend as an ordinary question — it can never actually
release or requeue a queue item, even though the entire pipeline for doing so, including its own
params validator, chokepoint gating, and result-formatting, is fully built and unit-tested.
Requirements
ChatConversation's submit path, attempt to resolve the operator's message as a portfolio-queueaction via
resolvePortfolioQueueChatAction(fromapps/loopover-miner-ui/src/lib/chat-portfolio-queue-resolve.ts)before falling back to the read-only
streamChatpath.handlePortfolioQueueChatCommandand appendits returned message(s) to the conversation instead of opening a
streamChatrequest.streamChatbehavior unchanged — this must not narrow or change ordinary Q&A behavior in any way.
streamChatround-trip, so a second submission cannot race an in-flight action.handlePortfolioQueueChatCommand,resolvePortfolioQueueChatAction, or the underlying/api/portfolio-queue/{release,requeue}routes —this issue is wiring only, reusing the existing, already-tested pipeline exactly as built.
Deliverables
ChatConversation.handleSubmittries portfolio-action resolution before the read-only stream pathstreamChatexactly as today (regression coverage for this)Test Coverage Requirements
apps/**is listed underignore:incodecov.yml, so this app is not gated by Codecov's 99% patchcheck — but the local
npm run test:coverageinvariant bar still applies, and a regression test isrequired: one test asserting a "release owner/repo"-shaped message dispatches through
handlePortfolioQueueChatCommand(notstreamChat), and one asserting an ordinary question stillreaches
streamChatunchanged. Since this is a visual/interactive change to the chat rail, abefore/after screenshot (or short clip) of a resolved action's outcome appearing inline in the
conversation is required per this repo's UI-PR convention.
Links & Resources
Epic: #6504.
apps/loopover-miner-ui/src/components/chat/conversation.tsx,apps/loopover-miner-ui/src/lib/chat-portfolio-queue-actions.ts(handlePortfolioQueueChatCommand,line 246),
apps/loopover-miner-ui/src/lib/chat-portfolio-queue-resolve.ts. Closed issues that builtthe now-unreachable pipeline: #6520, #6838.