story-kit: merge 247_story_human_qa_gate_with_rejection_flow

This commit is contained in:
Dave
2026-03-18 15:45:45 +00:00
parent 1faacd7812
commit 9352443555
11 changed files with 557 additions and 26 deletions

View File

@@ -33,6 +33,8 @@ export interface PipelineStageItem {
error: string | null;
merge_failure: string | null;
agent: AgentAssignment | null;
review_hold: boolean | null;
manual_qa: boolean | null;
}
export interface PipelineState {
@@ -312,8 +314,42 @@ export const api = {
baseUrl,
);
},
/** Approve a story in QA, moving it to merge. */
approveQa(storyId: string) {
return callMcpTool("approve_qa", { story_id: storyId });
},
/** Reject a story in QA, moving it back to current with notes. */
rejectQa(storyId: string, notes: string) {
return callMcpTool("reject_qa", { story_id: storyId, notes });
},
/** Launch the QA app for a story's worktree. */
launchQaApp(storyId: string) {
return callMcpTool("launch_qa_app", { story_id: storyId });
},
};
async function callMcpTool(
toolName: string,
args: Record<string, unknown>,
): Promise<string> {
const res = await fetch("/mcp", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "tools/call",
params: { name: toolName, arguments: args },
}),
});
const json = await res.json();
if (json.error) {
throw new Error(json.error.message);
}
const text = json.result?.content?.[0]?.text ?? "";
return text;
}
export class ChatWebSocket {
private static sharedSocket: WebSocket | null = null;
private static refCount = 0;