diff options
| -rw-r--r-- | makima/frontend/src/components/directives/TaskSlideOutPanel.tsx | 12 | ||||
| -rw-r--r-- | makima/frontend/src/components/mesh/WorktreeFilesPanel.tsx | 2 | ||||
| -rw-r--r-- | makima/frontend/src/lib/api.ts | 7 | ||||
| -rw-r--r-- | makima/frontend/tsconfig.tsbuildinfo | 2 | ||||
| -rw-r--r-- | makima/src/daemon/skills/directive.md | 7 | ||||
| -rw-r--r-- | makima/src/orchestration/directive.rs | 16 |
6 files changed, 38 insertions, 8 deletions
diff --git a/makima/frontend/src/components/directives/TaskSlideOutPanel.tsx b/makima/frontend/src/components/directives/TaskSlideOutPanel.tsx index 176728c..f803f90 100644 --- a/makima/frontend/src/components/directives/TaskSlideOutPanel.tsx +++ b/makima/frontend/src/components/directives/TaskSlideOutPanel.tsx @@ -25,6 +25,8 @@ export function TaskSlideOutPanel({ const [showDiff, setShowDiff] = useState(false); const [diffContent, setDiffContent] = useState<string>(""); const [diffLoading, setDiffLoading] = useState(false); + const [selectedFileDiff, setSelectedFileDiff] = useState<string | null>(null); + const [selectedFilePath, setSelectedFilePath] = useState<string | null>(null); // Escape key handler useEffect(() => { @@ -254,10 +256,12 @@ export function TaskSlideOutPanel({ )} </div> - {/* Worktree Changes section (~40% height) */} - <div className="flex-[2] min-h-0 overflow-y-auto"> - {taskId && <WorktreeFilesPanel taskId={taskId} onFileClick={handleFileClick} />} - </div> + {/* Worktree Changes section (~40% height) */} + <div className="flex-[2] min-h-0 overflow-y-auto"> + {taskId && <WorktreeFilesPanel taskId={taskId} onFileClick={handleFileClick} />} + </div> + </> + )} </div> </div> diff --git a/makima/frontend/src/components/mesh/WorktreeFilesPanel.tsx b/makima/frontend/src/components/mesh/WorktreeFilesPanel.tsx index bb3361d..500fb6a 100644 --- a/makima/frontend/src/components/mesh/WorktreeFilesPanel.tsx +++ b/makima/frontend/src/components/mesh/WorktreeFilesPanel.tsx @@ -154,7 +154,7 @@ export function WorktreeFilesPanel({ taskId, onFileClick }: WorktreeFilesPanelPr return ( <div key={file.path} - className={`flex items-center gap-2 px-3 py-1.5 ${onFileClick ? 'cursor-pointer hover:bg-[rgba(117,170,252,0.08)]' : 'hover:bg-[rgba(117,170,252,0.03)]'}`} + className={`flex items-center gap-2 px-3 py-1.5 ${isClickable ? 'cursor-pointer hover:bg-[rgba(117,170,252,0.08)]' : 'hover:bg-[rgba(117,170,252,0.03)]'}`} onClick={() => onFileClick?.(file.path)} > {/* Status badge */} diff --git a/makima/frontend/src/lib/api.ts b/makima/frontend/src/lib/api.ts index dd981ed..48e0faa 100644 --- a/makima/frontend/src/lib/api.ts +++ b/makima/frontend/src/lib/api.ts @@ -3089,6 +3089,13 @@ export async function getTaskDiff(taskId: string): Promise<{ taskId: string; suc return res.json(); } +/** Get the diff for a specific file in a task's worktree (falls back to full task diff filtered client-side) */ +export async function getWorktreeDiff(taskId: string, _filePath?: string): Promise<{ diff: string }> { + const result = await getTaskDiff(taskId); + // Return the full diff - per-file filtering can be done client-side if needed + return { diff: result.diff || "" }; +} + /** Commit changes in a task's worktree */ export async function commitWorktree(taskId: string, message?: string): Promise<{ taskId: string; success: boolean; commitSha: string | null; error: string | null }> { const res = await authFetch(`${API_BASE}/api/v1/mesh/tasks/${taskId}/worktree-commit`, { diff --git a/makima/frontend/tsconfig.tsbuildinfo b/makima/frontend/tsconfig.tsbuildinfo index 031f180..7a057d5 100644 --- a/makima/frontend/tsconfig.tsbuildinfo +++ b/makima/frontend/tsconfig.tsbuildinfo @@ -1 +1 @@ -{"root":["./src/main.tsx","./src/vite-env.d.ts","./src/components/gridoverlay.tsx","./src/components/japanesehovertext.tsx","./src/components/logo.tsx","./src/components/masthead.tsx","./src/components/navstrip.tsx","./src/components/phaseconfirmationnotification.tsx","./src/components/protectedroute.tsx","./src/components/questionimages.tsx","./src/components/rewritelink.tsx","./src/components/simplemarkdown.tsx","./src/components/supervisorquestionnotification.tsx","./src/components/charts/chartrenderer.tsx","./src/components/contracts/commandmodepanel.tsx","./src/components/contracts/contractcliinput.tsx","./src/components/contracts/contractcontextmenu.tsx","./src/components/contracts/contractdetail.tsx","./src/components/contracts/contractlist.tsx","./src/components/contracts/phasebadge.tsx","./src/components/contracts/phaseconfirmationmodal.tsx","./src/components/contracts/phasedeliverablespanel.tsx","./src/components/contracts/phasehint.tsx","./src/components/contracts/phaseprogressbar.tsx","./src/components/contracts/quickactionbuttons.tsx","./src/components/contracts/repositorypanel.tsx","./src/components/contracts/taskderivationpreview.tsx","./src/components/directives/doglist.tsx","./src/components/directives/directivecontextmenu.tsx","./src/components/directives/directivedag.tsx","./src/components/directives/directivedetail.tsx","./src/components/directives/directivelist.tsx","./src/components/directives/directivelogstream.tsx","./src/components/directives/orchestratorstepnode.tsx","./src/components/directives/stepnode.tsx","./src/components/directives/taskslideoutpanel.tsx","./src/components/files/bodyrenderer.tsx","./src/components/files/cliinput.tsx","./src/components/files/conflictnotification.tsx","./src/components/files/elementcontextmenu.tsx","./src/components/files/filedetail.tsx","./src/components/files/filelist.tsx","./src/components/files/reposyncindicator.tsx","./src/components/files/updatenotification.tsx","./src/components/files/versionhistorydropdown.tsx","./src/components/history/checkpointcard.tsx","./src/components/history/checkpointlist.tsx","./src/components/history/conversationmessage.tsx","./src/components/history/conversationview.tsx","./src/components/history/historyfilters.tsx","./src/components/history/resumecontrols.tsx","./src/components/history/timelineeventcard.tsx","./src/components/history/timelinelist.tsx","./src/components/history/index.ts","./src/components/listen/contractpickermodal.tsx","./src/components/listen/controlpanel.tsx","./src/components/listen/discusscontractmodal.tsx","./src/components/listen/speakerpanel.tsx","./src/components/listen/transcriptanalysispanel.tsx","./src/components/listen/transcriptpanel.tsx","./src/components/mesh/branchtaskmodal.tsx","./src/components/mesh/contractcompletequestion.tsx","./src/components/mesh/directoryinput.tsx","./src/components/mesh/gitactionspanel.tsx","./src/components/mesh/inlinesubtaskeditor.tsx","./src/components/mesh/mergeconflictresolver.tsx","./src/components/mesh/overlaydiffviewer.tsx","./src/components/mesh/prpreview.tsx","./src/components/mesh/patcheslistpanel.tsx","./src/components/mesh/subtasktree.tsx","./src/components/mesh/taskdetail.tsx","./src/components/mesh/tasklist.tsx","./src/components/mesh/taskoutput.tsx","./src/components/mesh/tasktree.tsx","./src/components/mesh/unifiedmeshchatinput.tsx","./src/components/mesh/worktreefilespanel.tsx","./src/components/orders/ordercontextmenu.tsx","./src/components/orders/orderdetail.tsx","./src/components/orders/orderlist.tsx","./src/contexts/authcontext.tsx","./src/contexts/supervisorquestionscontext.tsx","./src/hooks/usecontracts.ts","./src/hooks/usedirectives.ts","./src/hooks/usedogs.ts","./src/hooks/usefilesubscription.ts","./src/hooks/usefiles.ts","./src/hooks/usemeshchathistory.ts","./src/hooks/usemicrophone.ts","./src/hooks/usemultitasksubscription.ts","./src/hooks/useorders.ts","./src/hooks/usespeakwebsocket.ts","./src/hooks/usetasksubscription.ts","./src/hooks/usetasks.ts","./src/hooks/usetextscramble.ts","./src/hooks/useversionhistory.ts","./src/hooks/usewebsocket.ts","./src/lib/api.ts","./src/lib/listenapi.ts","./src/lib/markdown.ts","./src/lib/supabase.ts","./src/routes/_index.tsx","./src/routes/contract-file.tsx","./src/routes/contracts.tsx","./src/routes/daemons.tsx","./src/routes/directives.tsx","./src/routes/files.tsx","./src/routes/history.tsx","./src/routes/listen.tsx","./src/routes/login.tsx","./src/routes/mesh.tsx","./src/routes/orders.tsx","./src/routes/settings.tsx","./src/routes/speak.tsx","./src/types/messages.ts"],"errors":true,"version":"5.9.3"}
\ No newline at end of file +{"root":["./src/main.tsx","./src/vite-env.d.ts","./src/components/gridoverlay.tsx","./src/components/japanesehovertext.tsx","./src/components/logo.tsx","./src/components/masthead.tsx","./src/components/navstrip.tsx","./src/components/phaseconfirmationnotification.tsx","./src/components/protectedroute.tsx","./src/components/questionimages.tsx","./src/components/rewritelink.tsx","./src/components/simplemarkdown.tsx","./src/components/supervisorquestionnotification.tsx","./src/components/charts/chartrenderer.tsx","./src/components/contracts/commandmodepanel.tsx","./src/components/contracts/contractcliinput.tsx","./src/components/contracts/contractcontextmenu.tsx","./src/components/contracts/contractdetail.tsx","./src/components/contracts/contractlist.tsx","./src/components/contracts/phasebadge.tsx","./src/components/contracts/phaseconfirmationmodal.tsx","./src/components/contracts/phasedeliverablespanel.tsx","./src/components/contracts/phasehint.tsx","./src/components/contracts/phaseprogressbar.tsx","./src/components/contracts/quickactionbuttons.tsx","./src/components/contracts/repositorypanel.tsx","./src/components/contracts/taskderivationpreview.tsx","./src/components/directives/doglist.tsx","./src/components/directives/directivecontextmenu.tsx","./src/components/directives/directivedag.tsx","./src/components/directives/directivedetail.tsx","./src/components/directives/directivelist.tsx","./src/components/directives/directivelogstream.tsx","./src/components/directives/orchestratorstepnode.tsx","./src/components/directives/stepnode.tsx","./src/components/directives/taskslideoutpanel.tsx","./src/components/files/bodyrenderer.tsx","./src/components/files/cliinput.tsx","./src/components/files/conflictnotification.tsx","./src/components/files/elementcontextmenu.tsx","./src/components/files/filedetail.tsx","./src/components/files/filelist.tsx","./src/components/files/reposyncindicator.tsx","./src/components/files/updatenotification.tsx","./src/components/files/versionhistorydropdown.tsx","./src/components/history/checkpointcard.tsx","./src/components/history/checkpointlist.tsx","./src/components/history/conversationmessage.tsx","./src/components/history/conversationview.tsx","./src/components/history/historyfilters.tsx","./src/components/history/resumecontrols.tsx","./src/components/history/timelineeventcard.tsx","./src/components/history/timelinelist.tsx","./src/components/history/index.ts","./src/components/listen/contractpickermodal.tsx","./src/components/listen/controlpanel.tsx","./src/components/listen/discusscontractmodal.tsx","./src/components/listen/speakerpanel.tsx","./src/components/listen/transcriptanalysispanel.tsx","./src/components/listen/transcriptpanel.tsx","./src/components/mesh/branchtaskmodal.tsx","./src/components/mesh/contractcompletequestion.tsx","./src/components/mesh/directoryinput.tsx","./src/components/mesh/gitactionspanel.tsx","./src/components/mesh/inlinesubtaskeditor.tsx","./src/components/mesh/mergeconflictresolver.tsx","./src/components/mesh/overlaydiffviewer.tsx","./src/components/mesh/prpreview.tsx","./src/components/mesh/patcheslistpanel.tsx","./src/components/mesh/subtasktree.tsx","./src/components/mesh/taskdetail.tsx","./src/components/mesh/tasklist.tsx","./src/components/mesh/taskoutput.tsx","./src/components/mesh/tasktree.tsx","./src/components/mesh/unifiedmeshchatinput.tsx","./src/components/mesh/worktreefilespanel.tsx","./src/components/orders/ordercontextmenu.tsx","./src/components/orders/orderdetail.tsx","./src/components/orders/orderlist.tsx","./src/contexts/authcontext.tsx","./src/contexts/supervisorquestionscontext.tsx","./src/hooks/usecontracts.ts","./src/hooks/usedirectives.ts","./src/hooks/usedogs.ts","./src/hooks/usefilesubscription.ts","./src/hooks/usefiles.ts","./src/hooks/usemeshchathistory.ts","./src/hooks/usemicrophone.ts","./src/hooks/usemultitasksubscription.ts","./src/hooks/useorders.ts","./src/hooks/usespeakwebsocket.ts","./src/hooks/usetasksubscription.ts","./src/hooks/usetasks.ts","./src/hooks/usetextscramble.ts","./src/hooks/useversionhistory.ts","./src/hooks/usewebsocket.ts","./src/lib/api.ts","./src/lib/listenapi.ts","./src/lib/markdown.ts","./src/lib/supabase.ts","./src/routes/_index.tsx","./src/routes/contract-file.tsx","./src/routes/contracts.tsx","./src/routes/daemons.tsx","./src/routes/directives.tsx","./src/routes/files.tsx","./src/routes/history.tsx","./src/routes/listen.tsx","./src/routes/login.tsx","./src/routes/mesh.tsx","./src/routes/orders.tsx","./src/routes/settings.tsx","./src/routes/speak.tsx","./src/types/messages.ts"],"version":"5.9.3"}
\ No newline at end of file diff --git a/makima/src/daemon/skills/directive.md b/makima/src/daemon/skills/directive.md index 83b998a..b02a32a 100644 --- a/makima/src/daemon/skills/directive.md +++ b/makima/src/daemon/skills/directive.md @@ -125,13 +125,18 @@ makima directive ask "Does this UI look correct?" \ --phaseguard ``` +**Visual feedback workflow (with images):** +```bash +# Take a screenshot or reference a design mockup, then ask for feedback +makima directive ask "Does this UI layout match the design spec?" --images "screenshot.png,mockup.png" --choices "Looks good,Needs changes" --phaseguard +``` + Or use the helper script for a one-liner: ```bash tools/visual-feedback.sh http://localhost:5173 "Does this look correct?" --choices "Looks good,Needs changes" ``` For full documentation on viewport sizes, mobile screenshots, multi-page reviews, and dev server setup, see the **visual_feedback** skill. - ### Create an Order (Future Work) ```bash makima directive create-order --title "Order title" --order-type spike diff --git a/makima/src/orchestration/directive.rs b/makima/src/orchestration/directive.rs index 1e025c8..78b30ce 100644 --- a/makima/src/orchestration/directive.rs +++ b/makima/src/orchestration/directive.rs @@ -211,7 +211,11 @@ impl DirectiveOrchestrator { When done, the system will automatically mark this step as completed.\n\ If you cannot complete the task, report the failure clearly.\n\n\ If you need clarification or encounter a decision that requires user input, you can ask:\n\ - \x20 makima directive ask \"Your question\" --phaseguard{manual_mode_appendix}", + \x20 makima directive ask \"Your question\" --phaseguard\n\n\ + VISUAL FEEDBACK: If this step involves frontend/UI changes, you can take screenshots and ask for user review:\n\ + \x20 npx playwright screenshot --browser chromium <url> screenshot.png\n\ + \x20 makima directive ask \"Does this look correct?\" --images \"screenshot.png\" --phaseguard\n\ + Node.js and Playwright with Chromium are pre-installed in the environment.{manual_mode_appendix}", directive_title = step.directive_title, step_name = step.step_name, description = step.step_description.as_deref().unwrap_or("(none)"), @@ -1652,6 +1656,16 @@ When to create orders: Do NOT create orders for: - Work that should be a step in the current plan - Tasks that are part of the current goal + +VISUAL FEEDBACK FOR FRONTEND CHANGES: +Tasks can take screenshots of web applications and ask users for visual feedback: +1. Start the dev server in the worktree background +2. Use `npx playwright screenshot --browser chromium <url> screenshot.png` to capture the UI +3. Use `makima directive ask "Review the UI" --images "screenshot.png" --phaseguard` to show the user +4. Node.js and Playwright with Chromium are pre-installed in the daemon environment + +For steps involving frontend/UI changes, include instructions in the taskPlan to take screenshots and ask +for visual confirmation before completing the step. This ensures the user can see and approve visual changes. "#, title = directive.title, goal = directive.goal, |
