Skip to content

feat: wire feedback modal and IPC wiring - #491

Merged
jeffscottward merged 33 commits into
RunMaestro:rcfrom
jeffscottward:symphony/issue-457-mm82lf08
Mar 26, 2026
Merged

feat: wire feedback modal and IPC wiring#491
jeffscottward merged 33 commits into
RunMaestro:rcfrom
jeffscottward:symphony/issue-457-mm82lf08

Conversation

@jeffscottward

@jeffscottward jeffscottward commented Mar 1, 2026

Copy link
Copy Markdown
Contributor

Closes #457
Closes #575

Implements feedback modal and IPC wiring updates (renderer modal flow, IPC wiring, and related preload/main handlers).

Summary by CodeRabbit

  • New Features

    • Send feedback to GitHub (bug report / feature / improvement) from the app.
    • Accessible via Quick Actions, About modal, and a new Feedback modal/view with session selection.
    • GitHub auth check with cached status, real-time char count/validation, and Ctrl/Cmd+Enter submit.
    • Renderer API exposed to check auth and submit feedback; successful submit can switch to the related session.
  • Documentation

    • Guidance added for converting feedback into a GitHub issue.
  • Tests

    • Added mock for a feedback-related icon.

@coderabbitai

coderabbitai Bot commented Mar 1, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a Send Feedback feature: IPC handlers (gh auth check + submit), preload bridge, feedback prompt template, renderer UI (FeedbackView/Modal), About/QuickActions integration, modal state/hooks, and global typings. (50 words)

Changes

Cohort / File(s) Summary
Main IPC / Backend
src/main/ipc/handlers/feedback.ts, src/main/ipc/handlers/index.ts
New IPC handlers feedback:check-gh-auth (cached gh auth status) and feedback:submit (validate, load prompt, inject feedback, forward to ProcessManager). Registered in handler init. Pay attention to ProcessManager availability and file reads.
Preload / Bridge
src/main/preload/feedback.ts, src/main/preload/index.ts
Adds Feedback API (checkGhAuth, submit) exposed to renderer via contextBridge and re-exported types.
Prompt template
src/prompts/feedback.md
New system prompt template that converts feedback into a structured GitHub issue and emits gh CLI commands.
Renderer — Views & Modals
src/renderer/components/FeedbackView.tsx, src/renderer/components/FeedbackModal.tsx, src/renderer/components/AboutModal.tsx, src/renderer/components/AppModals.tsx, src/renderer/components/.../AppInfoModals.tsx, src/renderer/components/.../AppUtilityModals.tsx, src/renderer/components/QuickActionsModal.tsx, src/renderer/App.tsx
Adds FeedbackView (auth gating, session selector, submit flow, Ctrl/Cmd+Enter), FeedbackModal wrapper, integrates feedback view into AboutModal and modal system, and adds Quick Action to open feedback. Check prop threading and modal priority/visibility changes.
Renderer — State, Hooks & Constants
src/renderer/stores/modalStore.ts, src/renderer/hooks/modal/useModalHandlers.ts, src/renderer/constants/modalPriorities.ts
Adds 'feedback' ModalId, feedbackModalOpen selector, setFeedbackModalOpen action, handlers to open/close feedback modal, and new modal priority FEEDBACK: 595.
Types / Globals
src/renderer/global.d.ts, src/main/preload/feedback.ts
Extends MaestroAPI and preload exports with feedback API types and response shapes.
Tests & Fixtures / Misc
src/__tests__/renderer/components/AboutModal.test.tsx, payload.XXXXXX.json, prompt.XXXXXX.txt, src/renderer/components/FilePreview.tsx, src/renderer/hooks/batch/useBatchProcessor.ts
Adds mock for MessageSquarePlus icon in tests; new payload/prompt files for CI/debugging; minor formatting tweaks in unrelated renderer files. Review test mock alignment with new UI icon.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Renderer as Feedback View
    participant Preload as Preload (ipcRenderer)
    participant Main as Main Process (IPC)
    participant Agent as Agent Process
    participant GHCli as GitHub CLI
    participant GitHub as GitHub API

    User->>Renderer: open feedback form
    Renderer->>Preload: invoke checkGhAuth()
    Preload->>Main: ipc invoke feedback:check-gh-auth
    Main->>GHCli: run `gh auth status` (cache consulted)
    GHCli-->>Main: auth status
    Main-->>Preload: { authenticated, message? }
    Preload-->>Renderer: auth result

    alt authenticated
        User->>Renderer: select agent + write feedback + submit
        Renderer->>Preload: invoke feedback:submit {sessionId, feedbackText}
        Preload->>Main: ipc invoke feedback:submit
        Main->>Agent: send prompt (feedback injected) via ProcessManager
        Agent->>GHCli: run `gh issue create ...`
        GHCli->>GitHub: create issue
        GitHub-->>GHCli: issue URL
        Agent-->>Main: report output (issue URL / success)
        Main-->>Preload: { success }
        Preload-->>Renderer: { success }
        Renderer->>User: switch to agent, close modal
    else not authenticated
        Renderer->>User: show auth message, disable form
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 53.85% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Out of Scope Changes check ❓ Inconclusive Minor formatting adjustments in FilePreview.tsx and useBatchProcessor.ts appear unrelated to feedback feature requirements and lack clear justification in the changeset summary. Clarify the purpose of formatting-only changes in FilePreview.tsx and useBatchProcessor.ts, or consider removing them as they fall outside the feedback feature scope.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: wire feedback modal and IPC wiring' accurately summarizes the main changes: wiring the feedback modal UI and integrating IPC handlers for gh auth and feedback submission.
Linked Issues check ✅ Passed The PR successfully implements all coding requirements from issue #457: IPC handlers for gh auth/submission, preload bridge, FeedbackView component, AboutModal integration with view toggle, FeedbackModal wrapper, Command Palette entry, and modal priorities configuration.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (2)
src/main/preload/feedback.ts (1)

48-49: ProcessManager.write() safely writes to stdin without shell interpolation; remove unwarranted security concern.

The handler correctly forwards raw sessionId/feedbackText across the renderer→main privilege boundary. However, verification shows the concern about shell-interpolation is unfounded: ProcessManager.write() directly writes to process.ptyProcess.write(data) or process.childProcess.stdin.write(data), with no command execution or string interpolation. The feedbackText is substituted into a template via String.replace() and written as stdin data—an inherently safe pattern.

That said, the handler lacks explicit input validation (e.g., bounds checks on feedbackText, verification that sessionId exists). Consider adding defensive validation for code robustness, though the current stdin-write design mitigates injection risk.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/preload/feedback.ts` around lines 48 - 49, The reviewer flagged a
shell-interpolation risk that doesn't exist because ProcessManager.write writes
directly to process.ptyProcess.write / process.childProcess.stdin.write; remove
or update any comment/handler logic that asserts a shell-injection risk and
instead add defensive input validation in the feedback submit handler (submit in
src/main/preload/feedback.ts) and upstream where the handler resolves sessionId:
enforce a reasonable max length for feedbackText, reject empty strings, and
verify sessionId maps to an existing session before invoking the IPC; keep
ProcessManager.write unchanged since it performs raw stdin writes (no
interpolation).
src/renderer/components/AppModals.tsx (1)

1802-1805: Consider unifying feedback modal open-state sourcing.

At Line 2147 the component self-sources modal booleans from useModalStore, but feedbackModalOpen remains prop-driven (Line 2222). This mixed ownership can drift over time; prefer store-sourcing here too for consistency and lower wiring overhead.

Also applies to: 2222-2225, 2477-2481

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/renderer/components/AppModals.tsx` around lines 1802 - 1805, The feedback
modal open-state should be sourced from the same store as the other modals
instead of a prop: in the AppModals component replace usage of the prop
feedbackModalOpen and its local handlers with the modal boolean from
useModalStore (the same selector used for other modals) and call the store's
close action when closing the modal; update references to onCloseFeedbackModal
(and any prop-driven state at the prop list) to use the store close function so
all modal booleans (including feedback) are consistently read/written from
useModalStore.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/main/ipc/handlers/feedback.ts`:
- Around line 114-128: The IPC feedback handler (the async callback that takes
sessionId and feedbackText and calls getProcessManager(),
fs.readFile(getPromptPath()), and processManager.write) must validate inputs at
the main-process boundary: ensure sessionId and feedbackText are strings,
non-empty, and within reasonable length limits (e.g., max length for
feedbackText), and reject or return { success: false, error: '...' } for invalid
inputs; additionally trim/sanitize feedbackText (strip dangerous control chars
or excessive newlines) before using promptTemplate.replace and before calling
processManager.write(sessionId, ...). Implement these checks at the top of that
handler (before getPromptPath()/fs.readFile/processManager.write) and return
clear error messages for each validation failure.

In `@src/renderer/components/AboutModal.tsx`:
- Around line 137-144: In AboutModal, the icon-only back and feedback buttons
(the button that calls setView('about') and the other icon button around
ArrowLeft/feedback icon) rely only on title; update both Button elements to
include explicit type="button" and an appropriate aria-label (e.g.,
aria-label="Back to About" for the setView('about') button and aria-label="Send
feedback" for the feedback button) so screen readers and default button behavior
are handled correctly; the relevant symbols to edit are the button elements that
render ArrowLeft and the feedback icon inside the AboutModal component.

In `@src/renderer/components/FeedbackView.tsx`:
- Around line 164-167: Update the FeedbackView component to associate labels
with their form controls and use “agent” in user-facing text: change the visible
label text from "Target Agent Session" to "Target Agent" and ensure the <label>
elements for the related <select> elements include htmlFor attributes that match
the corresponding select id (do the same for the other label at the second
occurrence). Keep the code-level types/names using the Session interface intact
(no renaming in code), only modify the displayed string and add the htmlFor/id
pairing so screen readers have a programmatic association.
- Around line 156-170: The form wrapper currently only applies 'opacity-40
pointer-events-none' when authState.authenticated is false, which blocks mouse
clicks but still allows keyboard focus; update the interactive controls (e.g.,
the <select> bound to selectedSessionId via setSelectedSessionId, the
inputs/textareas around lines referenced, and any submit controls using
isSubmittingDisabled) to also set the disabled prop when authState.authenticated
is false (or compute a single boolean like isAuthDisabled =
!authState.authenticated || isSubmittingDisabled and pass it to disabled on
select, inputs, textarea and buttons) so keyboard interaction is prevented
consistently across the form elements.
- Around line 113-116: The current branch that checks result.success overwrites
any backend-provided error with a fixed message; update the failure path in
FeedbackView (the block that checks result.success) to surface the backend error
instead: if result.success is false, call setSubmitError using the backend
message (e.g., result.error or result.message) and only fall back to the
existing "selected agent..." string when no backend message exists, then call
setSubmitting(false) and return; locate the logic referencing result.success,
setSubmitError, and setSubmitting and replace the hardcoded message with the
conditional use of the backend-provided error.

---

Nitpick comments:
In `@src/main/preload/feedback.ts`:
- Around line 48-49: The reviewer flagged a shell-interpolation risk that
doesn't exist because ProcessManager.write writes directly to
process.ptyProcess.write / process.childProcess.stdin.write; remove or update
any comment/handler logic that asserts a shell-injection risk and instead add
defensive input validation in the feedback submit handler (submit in
src/main/preload/feedback.ts) and upstream where the handler resolves sessionId:
enforce a reasonable max length for feedbackText, reject empty strings, and
verify sessionId maps to an existing session before invoking the IPC; keep
ProcessManager.write unchanged since it performs raw stdin writes (no
interpolation).

In `@src/renderer/components/AppModals.tsx`:
- Around line 1802-1805: The feedback modal open-state should be sourced from
the same store as the other modals instead of a prop: in the AppModals component
replace usage of the prop feedbackModalOpen and its local handlers with the
modal boolean from useModalStore (the same selector used for other modals) and
call the store's close action when closing the modal; update references to
onCloseFeedbackModal (and any prop-driven state at the prop list) to use the
store close function so all modal booleans (including feedback) are consistently
read/written from useModalStore.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bfebc19 and 0c67650.

📒 Files selected for processing (15)
  • src/main/ipc/handlers/feedback.ts
  • src/main/ipc/handlers/index.ts
  • src/main/preload/feedback.ts
  • src/main/preload/index.ts
  • src/prompts/feedback.md
  • src/renderer/App.tsx
  • src/renderer/components/AboutModal.tsx
  • src/renderer/components/AppModals.tsx
  • src/renderer/components/FeedbackModal.tsx
  • src/renderer/components/FeedbackView.tsx
  • src/renderer/components/QuickActionsModal.tsx
  • src/renderer/constants/modalPriorities.ts
  • src/renderer/global.d.ts
  • src/renderer/hooks/modal/useModalHandlers.ts
  • src/renderer/stores/modalStore.ts

Comment thread src/main/ipc/handlers/feedback.ts Outdated
Comment thread src/renderer/components/AboutModal.tsx
Comment thread src/renderer/components/FeedbackView.tsx
Comment thread src/renderer/components/FeedbackView.tsx Outdated
Comment thread src/renderer/components/FeedbackView.tsx Outdated
@greptile-apps

greptile-apps Bot commented Mar 1, 2026

Copy link
Copy Markdown

Greptile Summary

This PR implements a feedback submission system that allows users to report bugs and suggest features directly from within Maestro. The feedback flow integrates with GitHub CLI to automatically create issues in the RunMaestro/Maestro repository.

Key changes:

  • New IPC handlers for GitHub CLI authentication check and feedback submission
  • FeedbackModal and FeedbackView components with session selector and text input
  • Feedback accessible from About modal and Quick Actions menu (Cmd/Ctrl+K)
  • Agent receives structured prompt from feedback.md template that guides GitHub issue creation
  • Modal state management with priority 595

Implementation notes:

  • Feedback is sent by writing the templated prompt to a selected agent session via processManager.write()
  • GitHub CLI (gh) must be installed and authenticated for feedback submission
  • The agent receives instructions to classify feedback, format it as a GitHub issue, create the "Maestro-feedback" label, and post the issue
  • Users are automatically switched to the selected agent after successful submission

Issue found:

  • The isRunningSession() filter excludes 'idle' sessions, which prevents users from sending feedback to ready agents that aren't actively processing

Confidence Score: 4/5

  • Safe to merge with one logic issue to fix
  • The implementation follows established patterns for IPC handlers, modal management, and preload APIs. The architecture is clean with proper separation between main/renderer processes. However, the isRunningSession() filter excludes idle sessions which will limit when users can send feedback.
  • src/renderer/components/FeedbackView.tsx - fix the isRunningSession() logic to include idle sessions

Important Files Changed

Filename Overview
src/main/ipc/handlers/feedback.ts New IPC handler for checking GitHub CLI auth and submitting feedback via processManager.write()
src/main/preload/feedback.ts Preload API exposing feedback.checkGhAuth and feedback.submit to renderer
src/prompts/feedback.md Template prompt instructing agent to create GitHub issue with gh CLI, includes label creation step
src/renderer/components/FeedbackView.tsx Feedback form component with session selector; filters running sessions but excludes 'idle' state
src/renderer/components/AboutModal.tsx Adds feedback view toggle with back navigation; integrates FeedbackView into About modal

Sequence Diagram

sequenceDiagram
    participant User
    participant FeedbackView
    participant IPC
    participant Main Process
    participant ProcessManager
    participant Agent
    participant GitHub CLI

    User->>FeedbackView: Opens feedback modal
    FeedbackView->>IPC: feedback.checkGhAuth()
    IPC->>Main Process: feedback:check-gh-auth
    Main Process->>GitHub CLI: gh auth status
    GitHub CLI-->>Main Process: exit code 0 (authenticated)
    Main Process-->>IPC: {authenticated: true}
    IPC-->>FeedbackView: Auth success
    
    User->>FeedbackView: Enters feedback text
    User->>FeedbackView: Selects target agent
    User->>FeedbackView: Clicks "Send Feedback"
    
    FeedbackView->>IPC: feedback.submit(sessionId, text)
    IPC->>Main Process: feedback:submit
    Main Process->>Main Process: Load feedback.md template
    Main Process->>Main Process: Replace {{FEEDBACK}} placeholder
    Main Process->>ProcessManager: write(sessionId, prompt)
    ProcessManager->>Agent: Writes prompt to agent process
    
    Agent->>Agent: Classifies feedback
    Agent->>Agent: Formats GitHub issue
    Agent->>GitHub CLI: gh label create "Maestro-feedback"
    Agent->>GitHub CLI: gh issue create
    GitHub CLI-->>Agent: Issue URL
    Agent-->>User: Returns issue URL
    
    Main Process-->>IPC: {success: true}
    IPC-->>FeedbackView: Success
    FeedbackView->>User: Switches to agent session
Loading

Last reviewed commit: 0c67650

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

15 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment thread src/renderer/components/FeedbackView.tsx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/renderer/components/AboutModal.tsx`:
- Around line 177-202: The three icon-only buttons in AboutModal (the Globe
button that renders <Globe>, the Discord button with the SVG, and the
Documentation button that renders <BookOpen>) are missing type="button" and
aria-label attributes; update each of those button elements to include
type="button" and a descriptive aria-label (e.g., "Visit runmaestro.ai", "Join
our Discord", "Documentation") to match the existing Feedback/Close buttons and
improve accessibility and consistency.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0c67650 and 36e922e.

📒 Files selected for processing (3)
  • src/main/ipc/handlers/feedback.ts
  • src/renderer/components/AboutModal.tsx
  • src/renderer/components/FeedbackView.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/renderer/components/FeedbackView.tsx
  • src/main/ipc/handlers/feedback.ts

Comment thread src/renderer/components/AboutModal.tsx Outdated
@jeffscottward
jeffscottward force-pushed the symphony/issue-457-mm82lf08 branch from 36e922e to 4805547 Compare March 1, 2026 21:03

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/renderer/components/AboutModal.tsx (1)

122-134: ⚠️ Potential issue | 🟠 Major

Fix Escape flow short-circuit so feedback view can always go back to About.

Line 124 currently returns early whenever badgeEscapeHandlerRef.current exists, even if the handler did not consume Escape. This can prevent the new feedback Escape behavior on Line 128 from running.

🔧 Proposed fix
 	const handleEscape = useCallback(() => {
 		// If badge overlay is open, close it first
-		if (badgeEscapeHandlerRef.current) {
-			badgeEscapeHandlerRef.current();
+		if (badgeEscapeHandlerRef.current?.()) {
 			return;
 		}
 		if (view === 'feedback') {
 			setView('about');
 			return;
 		}
 		// Otherwise close the modal
 		onCloseRef.current();
 	}, [view]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/renderer/components/AboutModal.tsx` around lines 122 - 134, The Escape
flow currently always returns if badgeEscapeHandlerRef.current exists,
preventing the feedback->about transition in handleEscape; change the call so
you invoke badgeEscapeHandlerRef.current() and only return when that call
indicates it consumed the event (e.g., returns true); otherwise fall through to
the existing view check (if view === 'feedback' then setView('about')) and
finally call onCloseRef.current(). Update handleEscape to use the boolean result
of badgeEscapeHandlerRef.current() and, if relying on a new return contract,
ensure other code that sets badgeEscapeHandlerRef provides a boolean return
value.
♻️ Duplicate comments (1)
src/renderer/components/AboutModal.tsx (1)

177-202: ⚠️ Potential issue | 🟡 Minor

Add explicit button semantics on icon-only external-link controls.

Line 177, Line 185, and Line 195 are icon-only <button> elements missing type="button" and aria-label, which hurts accessibility and consistency with nearby controls.

♿ Proposed patch
 					<button
+						type="button"
 						onClick={() => window.maestro.shell.openExternal('https://runmaestro.ai')}
 						className="p-1 rounded hover:bg-white/10 transition-colors"
 						title="Visit runmaestro.ai"
+						aria-label="Visit runmaestro.ai"
 						style={{ color: theme.colors.accent }}
 					>
 						<Globe className="w-4 h-4" />
 					</button>
 					<button
+						type="button"
 						onClick={() => window.maestro.shell.openExternal('https://runmaestro.ai/discord')}
 						className="p-1 rounded hover:bg-white/10 transition-colors"
 						title="Join our Discord"
+						aria-label="Join our Discord"
 						style={{ color: theme.colors.accent }}
 					>
@@
 					<button
+						type="button"
 						onClick={() => window.maestro.shell.openExternal('https://docs.runmaestro.ai/')}
 						className="p-1 rounded hover:bg-white/10 transition-colors"
 						title="Documentation"
+						aria-label="Documentation"
 						style={{ color: theme.colors.accent }}
 					>
 						<BookOpen className="w-4 h-4" />
 					</button>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/renderer/components/AboutModal.tsx` around lines 177 - 202, The three
icon-only buttons in AboutModal that call
window.maestro.shell.openExternal('https://runmaestro.ai'),
window.maestro.shell.openExternal('https://runmaestro.ai/discord'), and
window.maestro.shell.openExternal('https://docs.runmaestro.ai/') should include
explicit button semantics: add type="button" and a descriptive aria-label for
each (e.g., "Visit runmaestro.ai", "Join our Discord", "Open documentation") to
the button elements that render the <Globe />, the Discord SVG, and <BookOpen />
so they are accessible and consistent with other controls.
🧹 Nitpick comments (1)
src/main/preload/feedback.ts (1)

44-50: Type createFeedbackApi return as FeedbackApi to prevent API drift.

This keeps the preload bridge contract enforced at compile time if methods are changed later.

♻️ Proposed patch
-export function createFeedbackApi() {
+export function createFeedbackApi(): FeedbackApi {
 	return {
 		checkGhAuth: (): Promise<FeedbackAuthResponse> => ipcRenderer.invoke('feedback:check-gh-auth'),

 		submit: (sessionId: string, feedbackText: string): Promise<FeedbackSubmitResponse> =>
 			ipcRenderer.invoke('feedback:submit', { sessionId, feedbackText }),
 	};
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/preload/feedback.ts` around lines 44 - 50, The createFeedbackApi
function currently returns an inferred object type which can drift; explicitly
annotate its return type as FeedbackApi by changing the signature to export
function createFeedbackApi(): FeedbackApi { … } and ensure the returned object
implements the FeedbackApi interface (i.e., includes checkGhAuth and submit with
the correct signatures) so the preload bridge contract is enforced at compile
time.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/renderer/components/AboutModal.tsx`:
- Around line 122-134: The Escape flow currently always returns if
badgeEscapeHandlerRef.current exists, preventing the feedback->about transition
in handleEscape; change the call so you invoke badgeEscapeHandlerRef.current()
and only return when that call indicates it consumed the event (e.g., returns
true); otherwise fall through to the existing view check (if view === 'feedback'
then setView('about')) and finally call onCloseRef.current(). Update
handleEscape to use the boolean result of badgeEscapeHandlerRef.current() and,
if relying on a new return contract, ensure other code that sets
badgeEscapeHandlerRef provides a boolean return value.

---

Duplicate comments:
In `@src/renderer/components/AboutModal.tsx`:
- Around line 177-202: The three icon-only buttons in AboutModal that call
window.maestro.shell.openExternal('https://runmaestro.ai'),
window.maestro.shell.openExternal('https://runmaestro.ai/discord'), and
window.maestro.shell.openExternal('https://docs.runmaestro.ai/') should include
explicit button semantics: add type="button" and a descriptive aria-label for
each (e.g., "Visit runmaestro.ai", "Join our Discord", "Open documentation") to
the button elements that render the <Globe />, the Discord SVG, and <BookOpen />
so they are accessible and consistent with other controls.

---

Nitpick comments:
In `@src/main/preload/feedback.ts`:
- Around line 44-50: The createFeedbackApi function currently returns an
inferred object type which can drift; explicitly annotate its return type as
FeedbackApi by changing the signature to export function createFeedbackApi():
FeedbackApi { … } and ensure the returned object implements the FeedbackApi
interface (i.e., includes checkGhAuth and submit with the correct signatures) so
the preload bridge contract is enforced at compile time.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 36e922e and 4805547.

📒 Files selected for processing (15)
  • src/main/ipc/handlers/feedback.ts
  • src/main/ipc/handlers/index.ts
  • src/main/preload/feedback.ts
  • src/main/preload/index.ts
  • src/prompts/feedback.md
  • src/renderer/App.tsx
  • src/renderer/components/AboutModal.tsx
  • src/renderer/components/AppModals.tsx
  • src/renderer/components/FeedbackModal.tsx
  • src/renderer/components/FeedbackView.tsx
  • src/renderer/components/QuickActionsModal.tsx
  • src/renderer/constants/modalPriorities.ts
  • src/renderer/global.d.ts
  • src/renderer/hooks/modal/useModalHandlers.ts
  • src/renderer/stores/modalStore.ts
🚧 Files skipped from review as they are similar to previous changes (8)
  • src/renderer/components/FeedbackModal.tsx
  • src/renderer/components/QuickActionsModal.tsx
  • src/renderer/App.tsx
  • src/renderer/stores/modalStore.ts
  • src/renderer/constants/modalPriorities.ts
  • src/prompts/feedback.md
  • src/renderer/components/FeedbackView.tsx
  • src/main/preload/index.ts

jeffscottward pushed a commit to jeffscottward/Maestro that referenced this pull request Mar 3, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@prompt.XXXXXX.txt`:
- Around line 1-17: Remove the accidental agent prompt/debug artifact file
(prompt.XXXXXX.txt) from the PR: delete the file or revert its addition so only
product code changes remain, ensuring no references to the file remain in the
branch or imports; commit the deletion under the same PR branch to clear the
unrelated CI/debug payload content that caused the failing checks.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4805547 and b051a06.

📒 Files selected for processing (3)
  • payload.XXXXXX.json
  • prompt.XXXXXX.txt
  • src/__tests__/renderer/components/AboutModal.test.tsx
✅ Files skipped from review due to trivial changes (1)
  • payload.XXXXXX.json

Comment thread prompt.XXXXXX.txt Outdated
jeffscottward pushed a commit to jeffscottward/Maestro that referenced this pull request Mar 3, 2026
jeffscottward pushed a commit to jeffscottward/Maestro that referenced this pull request Mar 3, 2026
jeffscottward and others added 16 commits March 13, 2026 19:11
- Add input validation at IPC boundary (sessionId, feedbackText length/empty checks)
- Add type="button" and aria-label to AboutModal icon-only buttons
- Surface backend error messages instead of hardcoded string in FeedbackView
- Add isFormDisabled to properly disable form controls when auth is missing
- Associate labels with form controls via htmlFor/id pairings
- Change "Target Agent Session" to "Target Agent" in user-facing text
- Include idle state in isRunningSession so ready agents can receive feedback

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@jeffscottward
jeffscottward force-pushed the symphony/issue-457-mm82lf08 branch from b0b90b3 to 070ebf1 Compare March 13, 2026 23:42
@jeffscottward

Copy link
Copy Markdown
Contributor Author

Successful end-to-end Maestro feedback flow with text submission and inline screenshot rendering.

Valid issue from the UI flow:

  1. Feedback button visible in the Maestro shell:
    Step 1 - feedback button

  2. Feedback modal opened:
    Step 2 - feedback modal

  3. Screenshot attached in the feedback flow:
    Step 3 - attachment added

  4. Submit clicked from the modal:
    Step 4 - submit clicked

  5. Resulting GitHub issue page with the image rendered inline:
    Step 5 - created issue with inline screenshot

@jeffscottward

Copy link
Copy Markdown
Contributor Author

Copy pasting the report that my local AI Building this feature sent to me in email


Completed

Validation

  • npm run build:prompts
  • npm run lint
  • npx prettier --check on changed files
  • npx eslint --no-warn-ignored src/main/ipc/handlers/feedback.ts src/main/preload/feedback.ts src/renderer/components/FeedbackView.tsx
  • npx vitest run src/tests/main/preload/feedback.test.ts src/tests/main/ipc/handlers/feedback.test.ts src/tests/renderer/components/FeedbackView.test.tsx
  • CodeRabbit check on PR feat: wire feedback modal and IPC wiring #491 is passing and the PR review decision is APPROVED on head 455f0f7.
  • Greptile has not posted a fresh review on the latest push, but there are no new actionable bot comments visible from this machine.

Links

Not completed / blockers

  • The new issue forms are committed on the PR branch, but they will not be live on RunMaestro/Maestro's default branch until PR feat: wire feedback modal and IPC wiring #491 merges.
  • I did not modify the older local screenshot artifacts or the untracked feedback E2E script/node_modules in the worktree; they were pre-existing and left untouched.

@jeffscottward
jeffscottward changed the base branch from main to rc March 26, 2026 04:00
# Conflicts:
#	docs/releases.md
#	src/__tests__/renderer/components/SessionList.test.tsx
#	src/renderer/components/AboutModal.tsx
#	src/renderer/components/AppModals.tsx
#	src/renderer/components/SessionList/SessionList.tsx
@jeffscottward
jeffscottward merged commit 19d8e99 into RunMaestro:rc Mar 26, 2026
3 checks passed
@jeffscottward
jeffscottward deleted the symphony/issue-457-mm82lf08 branch May 11, 2026 20:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature: add structured bug report issue form Send Feedback: in-app issue creation via agent

1 participant