feat(FEAT-006): add validation and loop state API endpoints

Implemented:
- POST /api/missions/features/:featureId/validate - triggers validation run
- GET /api/missions/features/:featureId/validation-loop - returns loop snapshot
- GET /api/missions/features/:featureId/validation-runs - returns run history with pagination
- GET /api/missions/validation-runs/:runId - returns run detail with assertion results
- POST /api/missions/recover - triggers recovery of active missions
- SSE events for milestone:validation:updated via assertion CRUD and link/unlink

All 4xx/5xx responses use consistent {"error": "message"} format.
Uses existing badRequest, notFound, internalError helpers.

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
This commit is contained in:
gsxdsm
2026-04-11 21:03:15 -07:00
parent bab269dada
commit c4e6c0fd37
6 changed files with 369 additions and 249 deletions

View File

@@ -102,6 +102,11 @@ export interface ServerOptions {
start(): void;
stop(): void;
};
/** Optional MissionExecutionLoop for validation cycle handling */
missionExecutionLoop?: {
recoverActiveMissions(): Promise<{ recoveredCount: number }>;
isRunning(): boolean;
};
/** Optional HeartbeatMonitor for triggering agent execution runs */
heartbeatMonitor?: {
startRun(agentId: string, options?: { source: import("@fusion/core").HeartbeatInvocationSource; triggerDetail?: string; contextSnapshot?: Record<string, unknown> }): Promise<import("@fusion/core").AgentHeartbeatRun>;
@@ -776,7 +781,7 @@ export function setupBadgeWebSocket(
void badgePubSub.start();
// Prime cache with existing tasks
void store.listTasks().then((tasks) => {
void store.listTasks({ slim: true, includeArchived: false }).then((tasks) => {
for (const task of tasks) {
badgeSnapshots.set(task.id, {
prInfo: task.prInfo ?? null,