diff --git a/.huskies/agents.toml b/.huskies/agents.toml index e865c240..cf739e70 100644 --- a/.huskies/agents.toml +++ b/.huskies/agents.toml @@ -253,35 +253,30 @@ When the auto-resolver fails, you have access to the merge worktree at `.story_k 6. Call the `run_tests` MCP tool to start tests, then poll `get_test_result` until complete 7. If it compiles, commit and re-trigger merge_agent_work -### Common conflict patterns in this project: +### Common conflict patterns: -**Story file rename/rename conflicts:** Both branches moved the story .md file to different pipeline directories. Resolution: `git rm` both sides — story files in `work/2_current/`, `work/3_qa/`, `work/4_merge/` are gitignored and don't need to be committed. - -**bot.rs tokio::select! conflicts:** Master has a `tokio::select!` loop in `handle_message()` that handles permission forwarding (story 275). Feature branches created before story 275 have a simpler direct `provider.chat_stream().await` call. Resolution: KEEP master's tokio::select! loop. Integrate only the feature's new logic (e.g. typing indicators, new callbacks) into the existing loop structure. Do NOT replace the loop with the old direct call. +**Story file rename/rename conflicts:** Both branches moved the story .md file to different pipeline directories. Resolution: `git rm` both sides — story files in pipeline directories are gitignored and don't need to be committed. **Duplicate functions/imports:** The auto-resolver keeps both sides, producing duplicates. Resolution: keep one copy (prefer master's version), delete the duplicate. **Formatting-only conflicts:** Both sides reformatted the same code differently. Resolution: pick either side (prefer master). -**IMPORTANT: After resolving ANY conflict or fixing ANY gate failure in the merge workspace, run `script/lint` (if it exists) or the project's formatter before recommitting.** The auto-resolver frequently produces code that compiles but fails formatting checks. Running the formatter after every fix prevents repeated gate failures. +**IMPORTANT: After resolving ANY conflict or fixing ANY gate failure in the merge workspace, use the `run_lint` MCP tool to check formatting, then `run_tests` to verify everything passes before recommitting.** The auto-resolver frequently produces code that compiles but fails formatting or linting checks. ## Fixing Gate Failures -If quality gates fail, attempt to fix issues yourself in the merge worktree. Use the run_tests MCP tool (then poll get_test_result) to verify — do not run script/test via Bash. +If quality gates fail, attempt to fix issues yourself in the merge workspace. Use the run_tests MCP tool to verify before recommitting. **Fix yourself (up to 3 attempts total):** -- Syntax errors (missing semicolons, brackets, commas) +- Syntax errors - Duplicate definitions from merge artifacts -- Simple type annotation errors -- Unused import warnings flagged by clippy -- Mismatched braces from bad conflict resolution -- Trivial formatting issues that block compilation or linting +- Unused import warnings +- Formatting issues that block linting **Report to human without attempting a fix:** - Logic errors or incorrect business logic - Missing function implementations - Architectural changes required -- Non-trivial refactoring needed **Max retry limit:** If gates still fail after 3 fix attempts, call report_merge_failure to record the failure, then stop immediately and report the full gate output to the human. @@ -292,4 +287,4 @@ If quality gates fail, attempt to fix issues yourself in the merge worktree. Use - Report conflict resolution outcomes clearly - Report gate failures with full output so the human can act if needed - The server automatically runs acceptance gates when your process exits""" -system_prompt = "You are the mergemaster agent. Your primary job is to merge feature branches to master. First try the merge_agent_work MCP tool. If the auto-resolver fails on complex conflicts, resolve them yourself in the merge worktree — you are an opus-class agent capable of understanding both sides of a conflict and producing correct merged code. Common patterns: keep master's tokio::select! permission loop in bot.rs, discard story file rename conflicts (gitignored), remove duplicate definitions. After resolving, verify compilation before re-triggering merge. CRITICAL: Never manually move story files or call accept_story. After 3 failed fix attempts, call report_merge_failure and stop." +system_prompt = "You are the mergemaster agent. Your primary job is to merge feature branches to master. First try the merge_agent_work MCP tool. If the auto-resolver fails on complex conflicts, resolve them yourself in the merge workspace. Common patterns: discard story file rename conflicts (gitignored), remove duplicate definitions/imports. After resolving, verify with run_tests MCP tool before re-triggering merge. CRITICAL: Never manually move story files or call accept_story. After 3 failed fix attempts, call report_merge_failure and stop." diff --git a/frontend/src/api/gateway.ts b/frontend/src/api/gateway.ts index 794a710f..6fdf3850 100644 --- a/frontend/src/api/gateway.ts +++ b/frontend/src/api/gateway.ts @@ -8,6 +8,18 @@ export interface JoinedAgent { label: string; address: string; registered_at: number; + /// Project this agent is assigned to, if any. + assigned_project?: string; +} + +export interface GatewayProject { + name: string; + url: string; +} + +export interface GatewayInfo { + active: string; + projects: GatewayProject[]; } export interface GenerateTokenResponse { @@ -61,4 +73,17 @@ export const gatewayApi = { method: "DELETE", }); }, + + /// Assign an agent to a project, or unassign it by passing null. + assignAgent(id: string, project: string | null): Promise { + return gatewayRequest(`/gateway/agents/${id}/assign`, { + method: "POST", + body: JSON.stringify({ project }), + }); + }, + + /// Get the list of registered projects from the gateway. + getGatewayInfo(): Promise { + return gatewayRequest("/api/gateway"); + }, }; diff --git a/frontend/src/components/GatewayPanel.tsx b/frontend/src/components/GatewayPanel.tsx index 41dc3564..6d08bdef 100644 --- a/frontend/src/components/GatewayPanel.tsx +++ b/frontend/src/components/GatewayPanel.tsx @@ -3,10 +3,10 @@ /// Provides: /// - An "Add Agent" button that generates a one-time join token. /// - Instructions for running a build agent with the token. -/// - A list of connected agents with per-agent "Remove" buttons. +/// - A list of connected agents with per-agent project assignment and "Remove" buttons. import * as React from "react"; -import { gatewayApi, type JoinedAgent } from "../api/gateway"; +import { gatewayApi, type JoinedAgent, type GatewayProject } from "../api/gateway"; const { useCallback, useEffect, useState } = React; @@ -90,12 +90,17 @@ function TokenDisplay({ token }: { token: string }) { function AgentRow({ agent, + projects, onRemove, + onAssign, }: { agent: JoinedAgent; + projects: GatewayProject[]; onRemove: (id: string) => void; + onAssign: (id: string, project: string | null) => void; }) { const registeredAt = new Date(agent.registered_at * 1000).toLocaleString(); + const isAssigned = Boolean(agent.assigned_project); return (
{agent.label}
@@ -129,6 +135,29 @@ function AgentRow({ Registered {registeredAt}
+