diff --git a/.cta.json b/.cta.json index 838f6b9f..ef8caf2c 100644 --- a/.cta.json +++ b/.cta.json @@ -1,5 +1,5 @@ { - "projectName": "clawsuite", + "projectName": "hermes", "mode": "file-router", "typescript": true, "tailwind": true, diff --git a/.env.example b/.env.example index 9b3acf2f..a0c79c6f 100644 --- a/.env.example +++ b/.env.example @@ -1,6 +1,6 @@ -# ClawSuite → OpenClaw Gateway Connection +# Hermes Workspace → Hermes Gateway Connection # -# The ClawSuite server connects to the OpenClaw Gateway via WebSocket. +# The Hermes Workspace server connects to the Hermes Gateway via WebSocket. # Keep secrets here (never exposed to the browser). # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ @@ -11,7 +11,7 @@ # - Local gateway (default): ws://127.0.0.1:18789 # - Remote gateway: wss://your-gateway.example.com # - Docker: ws://host.docker.internal:18789 (to reach host machine) -CLAWDBOT_GATEWAY_URL=ws://127.0.0.1:18789 +HERMES_GATEWAY_URL=ws://127.0.0.1:18789 # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ # AUTHENTICATION (Choose one method) @@ -20,22 +20,22 @@ CLAWDBOT_GATEWAY_URL=ws://127.0.0.1:18789 # Gateway Token (Recommended) # How to find your token: # 1. Run: openclaw config get gateway.auth.token -# 2. Or check OpenClaw settings UI +# 2. Or check Hermes settings UI # Format: clw_abc123def456... (64+ characters) -CLAWDBOT_GATEWAY_TOKEN= +HERMES_GATEWAY_TOKEN= # Gateway Password (Alternative to token) # Only use if your gateway is configured for password auth -# CLAWDBOT_GATEWAY_PASSWORD= +# HERMES_GATEWAY_PASSWORD= # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ # CLAWSUITE ACCESS CONTROL (Optional) # ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ -# Password-protect ClawSuite web interface +# Password-protect Hermes Workspace web interface # Leave empty for no authentication (default for local use) # Set this for production deployments -# CLAWSUITE_PASSWORD= +# HERMES_PASSWORD= # Allow access from non-localhost addresses # Comma-separated list of hostnames/IPs @@ -44,4 +44,4 @@ CLAWDBOT_GATEWAY_TOKEN= # - Tailscale: my-server.tail1234.ts.net # - LAN: 192.168.1.50 # - Subnet: 192.168.1.0/24 -# CLAWSUITE_ALLOWED_HOSTS= +# HERMES_ALLOWED_HOSTS= diff --git a/.workspace-source b/.workspace-source new file mode 100644 index 00000000..416f9176 --- /dev/null +++ b/.workspace-source @@ -0,0 +1 @@ +/Users/aurora/.openclaw/workspace/hermes-workspace/clawsuite diff --git a/AGENTS.md b/AGENTS.md index 33abf6a8..1a34ca67 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,100 +1,276 @@ -# AGENTS.md — ClawSuite Codebase Guide - -## Stack -- **Framework:** TanStack Start (React, file-based routing) -- **Language:** TypeScript (strict) — `npx tsc --noEmit` must pass with 0 errors -- **Styling:** Tailwind CSS with custom design tokens -- **State:** Zustand stores + TanStack Query -- **Icons:** `@hugeicons/react` + `@hugeicons/core-free-icons` -- **Animation:** `motion/react` (AnimatePresence, motion.div) -- **Package manager:** npm (NOT pnpm) - -## Key Paths +# ClawSuite Agent Roster +_Canonical agent definitions. Aurora reads this before every Codex spawn._ + +--- + +## How Aurora Uses This File + +Before spawning any Codex agent for ClawSuite work, Aurora: +1. Picks the right agent by task type (see routing table below) +2. Loads that agent's full system prompt from this file +3. Injects live context (recent git log, relevant file list, branch state) +4. Spawns with: `codex --yolo exec "AGENT_PROMPT\n\n---\n\nTASK: "` + +**Always use the same named agent for the same task type.** This builds consistent patterns and better outputs over time. + +--- + +## Routing Table + +| Task keywords | Agent | +|--------------|-------| +| ui, react, screen, component, layout, design, theme, tailwind, css, style | `aurora-coder` | +| api, route, endpoint, db, database, schema, migration, daemon, server, express, tracker | `aurora-daemon` | +| review, qa, verify, test, check, audit, regression | `aurora-qa` | +| plan, decompose, spec, roadmap, architect | `aurora-planner` | +| electron, ipc, main process, preload | `aurora-electron` | +| anything else | `aurora-coder` (default) | + +--- + +## aurora-coder — Frontend Specialist + +**Role:** React/TypeScript UI work. Owns all workspace screens and components. +**Model:** codex / gpt-5.4 +**Spawn:** Always `--yolo` in `/Users/aurora/.openclaw/workspace/clawsuite` + +``` +IDENTITY: aurora-coder +ROLE: Frontend implementation specialist for ClawSuite + +STACK: +- React + TanStack Router + TanStack Query +- Tailwind CSS — use ONLY these tokens: + - Backgrounds: bg-surface (#f9fafb), bg-white, bg-primary-50, bg-primary-100 + - Text: text-primary-900 (body), text-primary-600 (muted), text-primary-500 (placeholder) + - Borders: border-primary-200, border-primary-300 + - Accent: accent-500 (highlight/CTA only) + - NEVER use dark classes (bg-primary-800/900/950, text-primary-100) in workspace screens +- HugeIcons: import from @hugeicons/core-free-icons, render with HugeiconsIcon from @hugeicons/react +- Animations: motion/react ONLY — never framer-motion +- Toast: import { toast } from '@/components/ui/toast' +- Button: import { Button } from '@/components/ui/button' + +FILE OWNERSHIP (only touch these unless explicitly told otherwise): +- src/screens/workspace/ +- src/screens/agents/ +- src/screens/review/ +- src/screens/runs/ +- src/screens/skills/ +- src/screens/teams/ +- src/screens/projects/ +- src/components/ui/ +- src/hooks/ + +STANDARD PAGE WRAPPER (every workspace screen must use this): +
+
+ +STANDARD HEADER CARD: +
+ +DATA FETCHING: +- Always use useQuery/useMutation from @tanstack/react-query +- Daemon URL: http://localhost:3099 +- Use workspaceRequestJson() from @/lib/workspace-checkpoints for daemon calls +- Always handle isPending + isError states + +MANDATORY BEFORE COMMIT: +1. Run: npx tsc --noEmit (from clawsuite/ root) — zero errors required +2. Verify no dark color tokens in modified files +3. git add only the files you changed, commit with clear message +``` + +--- + +## aurora-daemon — Backend Specialist + +**Role:** Express + SQLite workspace daemon. Owns all server-side logic. +**Model:** codex / gpt-5.4 +**Spawn:** Always `--yolo` in `/Users/aurora/.openclaw/workspace/clawsuite` + +``` +IDENTITY: aurora-daemon +ROLE: Backend implementation specialist for ClawSuite workspace daemon + +STACK: +- Express + better-sqlite3 in workspace-daemon/src/ +- TypeScript strict mode + +ARCHITECTURE RULES (non-negotiable): +1. ALL DB writes go through Tracker class methods — never raw db.prepare() from routes +2. All routes export createXxxRouter(tracker, orchestrator?) factory functions +3. Register new routers in workspace-daemon/src/server.ts +4. Emit emitSse() on every meaningful state change so frontend stays live +5. New columns = new ensureXxxColumn() migration in workspace-daemon/src/db/index.ts +6. Always add migration AND update schema.sql for fresh installs + +FILE OWNERSHIP: +- workspace-daemon/src/routes/ +- workspace-daemon/src/tracker.ts +- workspace-daemon/src/db/ +- workspace-daemon/src/orchestrator.ts +- workspace-daemon/src/adapters/ +- workspace-daemon/src/types.ts + +ERROR RESPONSE PATTERN: +- 400 bad input: res.status(400).json({ error: "field is required" }) +- 404 not found: res.status(404).json({ error: "Resource not found" }) +- 500 server error: res.status(500).json({ error: "Internal error" }) +- Never throw, always return JSON error + +INPUT VALIDATION: +- Validate required fields before any DB operation +- Never trust req.body types — always cast + check + +MANDATORY BEFORE COMMIT: +1. Run: npx tsc --noEmit (from workspace-daemon/ dir) — zero errors required +2. Verify new routes are registered in server.ts +3. Verify tracker method is used, not raw SQL from route +4. git add only daemon files, commit with feat(daemon): prefix ``` -src/routes/ — File-based routes (pages + API endpoints) -src/routes/api/ — API routes (TanStack Start server handlers) -src/components/ — Shared UI components -src/screens/ — Full-page screen components -src/hooks/ — React hooks -src/stores/ — Zustand stores -src/lib/ — Utilities -src/server/ — Server-only code (auth, gateway RPC, rate limiting) -public/ — Static assets (logos, icons) + +--- + +## aurora-qa — Review Specialist + +**Role:** Code review, regression detection, verification. +**Model:** codex / gpt-5.4 (or claude for deeper analysis) +**Spawn:** Always `--yolo` in `/Users/aurora/.openclaw/workspace/clawsuite` + ``` +IDENTITY: aurora-qa +ROLE: Code reviewer and verifier for ClawSuite -## Design Tokens (always use these, never raw colors) +YOUR JOB: Review diffs and verify correctness. You are the last line of defense before merge. + +REVIEW CHECKLIST (apply to every diff): +1. TypeScript: type errors? Check return types, function signatures, generic constraints +2. React: missing useEffect deps? Infinite render risk? Missing key props on lists? +3. API: new routes have input validation? Error responses are consistent JSON? +4. DB: new columns have migration? SQL uses prepared statements (no string interpolation)? +5. Design system: new UI uses correct light-theme tokens? No dark classes in workspace screens? +6. SSE: new state changes emit via emitSse()? Frontend query keys match? +7. Regressions: does change touch shared code (tracker.ts, types.ts, workspace-layout.tsx)? + If yes, list every consumer that could be affected. + +OUTPUT FORMAT: +Always end with a structured summary: +- VERDICT: APPROVED / NEEDS_CHANGES / BLOCKED +- ISSUES: bullet list (empty if approved) +- RISK_LEVEL: LOW / MEDIUM / HIGH + +MANDATORY: +Run npx tsc --noEmit from both clawsuite/ and workspace-daemon/ before giving verdict. +Report exact error count and any errors found. ``` -bg-primary-950/900/800/700 — dark backgrounds (darkest to lighter) -text-primary-100/200/300/400 — text (lightest to dimmer) -border-primary-800/700 — borders -bg-accent-500/400 — orange CTA (hover: accent-400) -text-accent-300/400/500 — orange text + +--- + +## aurora-planner — Decomposition Specialist + +**Role:** Break goals into concrete implementation tasks. +**Model:** codex / gpt-5.4 +**Spawn:** Always `--yolo` in `/Users/aurora/.openclaw/workspace/clawsuite` + +``` +IDENTITY: aurora-planner +ROLE: Task decomposition and planning specialist for ClawSuite + +YOUR JOB: Given a goal, produce a structured implementation plan that aurora-coder and aurora-daemon can execute without ambiguity. + +OUTPUT FORMAT (always JSON array): +[ + { + "name": "short imperative task name", + "agent": "aurora-coder | aurora-daemon | aurora-qa", + "files": ["exact/file/paths/to/touch"], + "description": "specific enough that the agent can act without asking questions", + "depends_on": ["other task name if blocked"], + "estimated_minutes": 30, + "verification": "how to verify this is done correctly" + } +] + +RULES: +- Max 8 tasks per plan +- Each task must be independently executable (no ambiguous deps) +- description must include: what to change, where, and how to verify +- files must be exact paths relative to clawsuite/ +- Always include a final aurora-qa review task +- Return ONLY the JSON array — no prose, no markdown fences ``` -## Component Patterns - -### API Routes -```ts -import { createFileRoute } from '@tanstack/react-router' -import { json } from '@tanstack/react-start' -import { isAuthenticated } from '../../server/auth-middleware' -import { requireJsonContentType } from '../../server/rate-limit' - -export const Route = createFileRoute('/api/my-endpoint')({ - server: { - handlers: { - GET: async ({ request }) => { - if (!isAuthenticated(request)) return json({ ok: false, error: 'Unauthorized' }, { status: 401 }) - // ... - return json({ ok: true, data }) - }, - POST: async ({ request }) => { - if (!isAuthenticated(request)) return json({ ok: false, error: 'Unauthorized' }, { status: 401 }) - const csrfCheck = requireJsonContentType(request) - if (csrfCheck) return csrfCheck - const body = await request.json() - return json({ ok: true }) - }, - }, - }, -}) +--- + +## aurora-electron — Electron Specialist + +**Role:** Electron main process, IPC, preload bridge, native integrations. +**Model:** codex / gpt-5.4 +**Spawn:** Always `--yolo` in `/Users/aurora/.openclaw/workspace/clawsuite` + ``` +IDENTITY: aurora-electron +ROLE: Electron main process specialist for ClawSuite + +STACK: +- Electron in clawsuite/electron/ +- electron/main.ts + electron/main.cjs (compiled output) +- electron/preload.ts — exposes safe IPC bridge to renderer +- IPC handlers: ipcMain.handle("namespace:action", async (event, ...args) => {}) +- IPC callers: window.electronBridge?.namespace?.action() -### Dynamic API Routes -File: `src/routes/api/items.$id.action.ts` -Route: `createFileRoute('/api/items/$id/action')` -Access: `params.id` - -### UI Components -- Always use `HugeiconsIcon` from `@hugeicons/react` for icons -- Wrap transitions in `AnimatePresence` from `motion/react` -- Use `cn()` from `@/lib/utils` for conditional classNames -- Path alias `@/` maps to `src/` - -### Gateway RPC -```ts -import { gatewayRpc } from '../../server/gateway' -await gatewayRpc('sessions.delete', { key: sessionKey }) +FILE OWNERSHIP: +- electron/main.ts +- electron/main.cjs +- electron/preload.ts + +RULES: +- Never expose Node APIs directly to renderer — always go through preload bridge +- All IPC handlers must have try/catch and return { ok: boolean, error?: string } +- Daemon management: check port 3099 before spawning, don't double-spawn +- Use ipcMain.handle (not ipcMain.on) for request/response patterns + +MANDATORY BEFORE COMMIT: +Run npx tsc --noEmit from clawsuite/. Zero errors. ``` -## Rules -- **Never push to GitHub** — PRs only, Eric reviews before merge -- **Always run `npx tsc --noEmit`** before finishing — 0 errors required -- **No pnpm** — use npm -- **No new dependencies** without asking — check if existing packages cover it first -- **Mobile-first** — all UI must work on small screens -- **Dark theme only** — use primary-* tokens, never hardcode colors -- **POST endpoints** must have `requireJsonContentType` CSRF check -- **All endpoints** must have `isAuthenticated` check - -## Common Imports -```ts -import { cn } from '@/lib/utils' -import { HugeiconsIcon } from '@hugeicons/react' -import { SomeIcon } from '@hugeicons/core-free-icons' -import { motion, AnimatePresence } from 'motion/react' -import { useQuery, useMutation } from '@tanstack/react-query' +--- + +## How Aurora Spawns These Agents + +### Template (copy-paste for each spawn) + +```bash +# 1. Get agent prompt +AGENT_PROMPT=$(cat clawsuite/AGENTS.md | awk '/^## aurora-AGENTNAME/,/^---/' | grep -A1000 '^\`\`\`' | grep -B1000 '^\`\`\`$' | grep -v '^\`\`\`') + +# 2. Inject live context +GIT_LOG=$(cd clawsuite && git log --oneline -5) +BRANCH=$(cd clawsuite && git branch --show-current) + +# 3. Spawn with full context +codex --yolo exec "## Agent Identity +$AGENT_PROMPT + +## Current branch: $BRANCH +## Recent commits: +$GIT_LOG + +--- + +## Task +" ``` -## Current Branch: main -Latest commit: f7d4ff9 — mobile setup wizard, paste fix, CLI kill fix +### Shorthand rules for Aurora +- UI task → spawn `aurora-coder` prompt +- API/daemon task → spawn `aurora-daemon` prompt +- After any multi-file change → spawn `aurora-qa` prompt to review +- New feature with unclear scope → spawn `aurora-planner` first to get task list + +### Never do +- Inline ad-hoc prompts without identity/context +- Mix UI and daemon work in same agent spawn +- Skip tsc verification step +- Spawn without specifying workdir as `clawsuite/` diff --git a/ARCHITECTURE-V2.md b/ARCHITECTURE-V2.md new file mode 100644 index 00000000..0c2d4720 --- /dev/null +++ b/ARCHITECTURE-V2.md @@ -0,0 +1,1002 @@ +# ClawSuite Architecture V2 + +**Author:** Aurora (Lead Architect) +**Date:** 2026-03-10 +**Status:** Implementation-Ready + +--- + +## Executive Summary + +This document upgrades ClawSuite from fire-and-forget PTY Codex spawns to first-class OpenClaw session management. The key architectural shift: **every agent run becomes an OpenClaw session**, visible in the hub, steerable mid-run, with context persistence across follow-ups. + +Current state: Working E2E flow with PTY Codex, smart agent routing, SSE live updates. +Target state: ACP sessions for Codex/Claude, subagent sessions for aurora-qa/orchestrator, auto-QA pipeline, mission creation UI. + +--- + +## 1. OpenClaw Integration Architecture + +### 1.1 Session Type Decision Tree + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ WHICH SESSION TYPE? │ +├─────────────────────────────────────────────────────────────────────────┤ +│ │ +│ Is this a file-writing coding task? │ +│ YES → Does it need context persistence across follow-ups? │ +│ YES → ACP Session (acpx codex -s ) │ +│ NO → PTY Codex exec (fire-and-forget, legacy mode) │ +│ │ +│ Is this a review, research, or multi-tool task? │ +│ YES → Subagent Session (sessions_spawn runtime:"subagent") │ +│ Tools: read, write, exec, browser, web_search, memory │ +│ │ +│ Is this an orchestration/coordination task? │ +│ YES → Subagent Session (aurora-orchestrator role) │ +│ │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +### 1.2 When to Use Each Type + +| Use Case | Session Type | Why | +|----------|-------------|-----| +| UI implementation (aurora-coder) | ACP Session | Context persists for revisions | +| Backend implementation (aurora-daemon) | ACP Session | Context persists for revisions | +| Code review (aurora-qa) | Subagent Session | Needs browser, tsc, diff analysis | +| Task decomposition (aurora-planner) | Subagent Session | Reads files, searches codebase | +| Follow-up fix after rejection | ACP Session (same session) | Retains original context | +| New task, fresh context | ACP Session (new session) | Clean slate | + +### 1.3 ACP Session Naming Convention + +``` +Pattern: cs--- + +Examples: +- cs-coder-clawsuite-a1b2c3d4 +- cs-daemon-clawsuite-e5f6g7h8 +- cs-qa-clawsuite-i9j0k1l2 + +Where: +- cs = ClawSuite prefix +- agent = coder|daemon|qa|planner|electron +- project = project slug (lowercase, alphanumeric) +- task_run_id_short = first 8 chars of task_run.id +``` + +### 1.4 Session Lifecycle Per Project + +``` +Task Created (status: pending) + │ + ▼ +Task Ready (status: ready, dependencies met) + │ + ▼ +Session Started ─────────────────────────────────────────┐ +│ POST http://127.0.0.1:3333/sessions/spawn │ +│ { │ +│ runtime: "acp", │ +│ label: "cs-coder-clawsuite-a1b2c3d4", │ +│ agent: { model: "gpt-5.4" }, │ +│ prompt: "\n---\n", │ +│ cwd: "/path/to/worktree" │ +│ } │ +└────────────────────────────────────────────────────────┘ + │ + ▼ +Session Running (SSE stream to daemon, events to UI) + │ + ├── On agent message delta → store in run_events + ├── On token usage → update task_run metrics + ├── On turn/completed → trigger checkpoint creation + │ + ▼ +Checkpoint Created (status: awaiting_review) + │ + ├── aurora-qa auto-runs (subagent session) + │ + ▼ +Review Complete + │ + ├── Approved → session killed, worktree merged + ├── Rejected → session persists for follow-up + └── Revision requested → new turn in SAME session +``` + +### 1.5 Upgrading OpenClawAdapter + +**Current:** Posts to `/sessions/spawn`, reads SSE, no session ID tracking. + +**Target:** Full session lifecycle management with ID persistence. + +```typescript +// workspace-daemon/src/adapters/openclaw.ts + +interface OpenClawSessionResponse { + sessionId: string; // Store in task_run.session_id + status: 'running' | 'completed' | 'failed'; +} + +interface OpenClawSpawnRequest { + runtime: 'acp' | 'subagent'; + label: string; // Our session naming convention + agent: { + id: string; + name: string; + model: string; + }; + prompt: string; + cwd?: string; + channel?: string; // For completion notifications +} + +export class OpenClawAdapter implements AgentAdapter { + readonly type = "openclaw"; + + async execute(request: AgentExecutionRequest, context: AgentAdapterContext): Promise { + const sessionLabel = this.buildSessionLabel(request); + + const spawnPayload: OpenClawSpawnRequest = { + runtime: this.resolveRuntime(request.agent), // 'acp' for codex/claude, 'subagent' for qa + label: sessionLabel, + agent: { + id: request.agent.id, + name: request.agent.name, + model: request.agent.model, + }, + prompt: this.buildContextualPrompt(request), + cwd: request.workspacePath, + }; + + const response = await fetch(`${this.baseUrl}/sessions/spawn`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(spawnPayload), + signal: context.signal, + }); + + // Extract session ID from first SSE event or response header + const sessionId = response.headers.get('X-Session-Id'); + if (sessionId) { + context.onEvent({ type: 'session_started', sessionId, label: sessionLabel }); + } + + // ... rest of SSE handling ... + } + + private resolveRuntime(agent: AgentRecord): 'acp' | 'subagent' { + // QA and Planner need full tool access (browser, search, memory) + if (agent.id === 'aurora-qa' || agent.id === 'aurora-planner') { + return 'subagent'; + } + // Coders use ACP for context persistence + return 'acp'; + } + + private buildSessionLabel(request: AgentExecutionRequest): string { + const agentSlug = request.agent.id.replace('aurora-', ''); + const projectSlug = request.projectName.toLowerCase().replace(/[^a-z0-9]/g, ''); + const runIdShort = request.taskRunId.slice(0, 8); + return `cs-${agentSlug}-${projectSlug}-${runIdShort}`; + } +} +``` + +### 1.6 Completion Notifications + +Three options, in order of preference: + +1. **SSE (current)** — Daemon already streams SSE, UI already polls. Keep this. + +2. **System Events (for Aurora)** — Already implemented in `checkpoint-builder.ts`: + ```typescript + execFile('openclaw', ['system', 'event', '--text', message, '--mode', 'now']); + ``` + +3. **Webhooks (for external integrations)** — Future: daemon exposes `/webhooks/checkpoint-ready`. + +**Recommendation:** Keep SSE for UI, keep system events for Aurora notifications. Add webhook endpoint only when external integrations require it. + +--- + +## 2. Subagent Session Design + +### 2.1 Agent Definitions + +| Agent | Runtime | Model | Tools | Create | Reuse | Kill | +|-------|---------|-------|-------|--------|-------|------| +| aurora-coder | acp | gpt-5.4 | read, write, exec | New task | Same task revisions | On approve/reject | +| aurora-daemon | acp | gpt-5.4 | read, write, exec | New task | Same task revisions | On approve/reject | +| aurora-qa | subagent | claude-sonnet-4-6 | read, exec, browser, web_search | Per checkpoint | Never (stateless) | On result | +| aurora-planner | subagent | gpt-5.4 | read, exec, web_search | Per decompose | Never (stateless) | On result | +| aurora-orchestrator | subagent | claude-sonnet-4-6 | read, exec, sessions_list, sessions_steer | Per project | Per project | On project complete | + +### 2.2 Session Naming Convention + +``` +Pattern: cs--- + +aurora-coder: cs-coder-- +aurora-daemon: cs-daemon-- +aurora-qa: cs-qa- +aurora-planner: cs-planner- +aurora-orchestrator: cs-orch- +``` + +### 2.3 Tool Requirements by Role + +**aurora-coder / aurora-daemon (ACP sessions):** +```yaml +tools: + - read: Full file access in worktree + - write: Full file access in worktree + - exec: git, npm, npx tsc, etc. +constraints: + - cwd locked to worktree path + - No browser, no web_search (focused on implementation) +``` + +**aurora-qa (Subagent session):** +```yaml +tools: + - read: Full file access (worktree + main repo) + - exec: git diff, npx tsc, npm test + - browser: Screenshot diffs (optional, future) + - web_search: Look up deprecation warnings, API docs +prompt_suffix: | + Return JSON: { approved: boolean, issues: string[], confidence: number, riskLevel: string } +``` + +**aurora-planner (Subagent session):** +```yaml +tools: + - read: Full file access (understand codebase structure) + - exec: tree, find, grep (codebase exploration) + - web_search: Research libraries, patterns +prompt_suffix: | + Return JSON array of tasks with: name, description, agent, files, depends_on, estimated_minutes +``` + +**aurora-orchestrator (Subagent session):** +```yaml +tools: + - read: Project spec, agent status + - exec: git status, daemon health checks + - sessions_list: Monitor active coding sessions + - sessions_steer: Intervene on stuck/failing sessions +lifecycle: + - Created when project starts + - Runs continuously, polling for stuck tasks + - Killed when project marked complete +``` + +--- + +## 3. Auto-QA Pipeline + +### 3.1 Trigger Flow + +``` +Checkpoint Created + │ + ├── checkpoint_builder.ts calls notifyCheckpointReady() + │ + ▼ +Orchestrator Receives Event + │ + ├── orchestrator.ts onCheckpointCreated(checkpointId) + │ + ▼ +QA Session Spawned + │ + ├── sessions_spawn runtime:"subagent" + │ label: cs-qa- + │ prompt: QA_SYSTEM_PROMPT + checkpoint_diff + verification_results + │ + ▼ +QA Analysis Runs + │ + ├── tsc --noEmit (already captured in verification) + ├── git diff analysis + ├── Regression risk assessment + │ + ▼ +QA Result Returned + │ + ├── JSON: { approved, issues[], confidence, riskLevel } + │ + ▼ +Result Stored in checkpoint.qa_result + │ + ├── If approved && confidence >= 0.9 && riskLevel === 'low': + │ └── Auto-approve checkpoint (no human review) + ├── Else: + │ └── Queue for human review with QA report attached +``` + +### 3.2 QA Result Schema + +```typescript +// workspace-daemon/src/types.ts + +interface QAResult { + approved: boolean; + issues: QAIssue[]; + confidence: number; // 0.0 - 1.0 + riskLevel: 'low' | 'medium' | 'high' | 'critical'; + summary: string; + checkedAt: string; // ISO timestamp + sessionId: string | null; // QA session ID for traceability +} + +interface QAIssue { + severity: 'error' | 'warning' | 'info'; + category: 'typescript' | 'react' | 'api' | 'design' | 'regression' | 'security'; + file: string | null; + line: number | null; + message: string; + suggestion: string | null; +} +``` + +### 3.3 Files to Modify + +**workspace-daemon/src/orchestrator.ts:** +```typescript +// Add after checkpoint creation in dispatchTask() +private async triggerAutoQA(checkpointId: string, taskRun: TaskRun): Promise { + const checkpoint = this.tracker.getCheckpointDetail(checkpointId); + if (!checkpoint) return; + + // Build QA prompt with diff, verification results, and context + const qaPrompt = this.buildQAPrompt(checkpoint); + + // Spawn QA subagent + const qaResult = await this.spawnQASession(checkpointId, qaPrompt); + + // Store result + this.tracker.updateCheckpointQAResult(checkpointId, qaResult); + + // Auto-approve if confidence is high + if (qaResult.approved && qaResult.confidence >= 0.9 && qaResult.riskLevel === 'low') { + this.tracker.approveCheckpoint(checkpointId, 'Auto-approved by QA', checkpoint.commit_hash); + } +} +``` + +**workspace-daemon/src/tracker.ts:** +```typescript +// Add method +updateCheckpointQAResult(checkpointId: string, result: QAResult): void { + const stmt = this.db.prepare(` + UPDATE checkpoints SET qa_result = ? WHERE id = ? + `); + stmt.run(JSON.stringify(result), checkpointId); + this.emitSse({ type: 'checkpoint.qa_complete', checkpointId, result }); +} +``` + +**workspace-daemon/src/checkpoint-builder.ts:** +```typescript +// Modify buildCheckpoint to return without auto-approve notification +// Let orchestrator handle the auto-QA flow + +export async function buildCheckpoint(...): Promise { + // ... existing logic ... + + // Remove notifyCheckpointReady() call here + // Orchestrator will trigger QA, which will notify if needed + + return checkpoint; +} +``` + +**workspace-daemon/src/routes/checkpoints.ts:** +```typescript +// Add QA result to detail response +router.get("/:id", async (req, res) => { + const detail = await buildCheckpointDetail(tracker, req.params.id); + if (!detail) { + res.status(404).json({ error: "Checkpoint not found" }); + return; + } + + // Parse QA result if present + const qaResult = detail.checkpoint.qa_result + ? JSON.parse(detail.checkpoint.qa_result) + : null; + + res.json({ + ...detail, + qa_result: qaResult, + }); +}); +``` + +**workspace-daemon/src/db/index.ts:** +```typescript +// Add migration +function ensureQAResultColumn(db: Database.Database): void { + const columns = db.pragma('table_info(checkpoints)') as { name: string }[]; + if (!columns.some(col => col.name === 'qa_result')) { + db.exec('ALTER TABLE checkpoints ADD COLUMN qa_result TEXT'); + } +} +``` + +--- + +## 4. Mission Creation UI Architecture + +### 4.1 Component Tree + +``` + + │ + ├── + │ ├── + │ └── ◄── NEW + │ ├── Name input + │ ├── Path picker (native dialog via IPC) + │ ├── Spec textarea + │ └── Settings (auto_approve, max_concurrent) + │ + ├── + │ ├── + │ ├── + │ └── ◄── NEW + │ ├── Mission name input + │ ├── Goal description textarea + │ ├── Decompose button → calls /api/decompose + │ ├── ◄── NEW + │ │ ├── Reorderable task cards + │ │ ├── Agent badge per task (editable) + │ │ ├── Estimated time display + │ │ └── Dependency arrows + │ ├── Execution mode: sequential | parallel + │ └── Start Mission button +``` + +### 4.2 New Project Modal + +**File:** `src/screens/projects/new-project-modal.tsx` + +```typescript +interface NewProjectModalProps { + isOpen: boolean; + onClose: () => void; + onCreated: (project: Project) => void; +} + +export function NewProjectModal({ isOpen, onClose, onCreated }: NewProjectModalProps) { + const [name, setName] = useState(''); + const [path, setPath] = useState(''); + const [spec, setSpec] = useState(''); + const [autoApprove, setAutoApprove] = useState(false); + const [maxConcurrent, setMaxConcurrent] = useState(2); + + const createMutation = useMutation({ + mutationFn: async () => { + const res = await workspaceRequestJson('/projects', { + method: 'POST', + body: JSON.stringify({ name, path, spec, auto_approve: autoApprove, max_concurrent: maxConcurrent }), + }); + return res as Project; + }, + onSuccess: (project) => { + onCreated(project); + onClose(); + }, + }); + + const handlePickPath = async () => { + // IPC to Electron for native folder picker + const result = await window.electronBridge?.dialog?.showOpenDialog({ + properties: ['openDirectory'], + }); + if (result?.filePaths?.[0]) { + setPath(result.filePaths[0]); + } + }; + + return ( + + + + New Project + +
+ setName(e.target.value)} /> +
+ setPath(e.target.value)} className="flex-1" /> + +
+