docs: add fumadocs plan, QA report, and temp hermes-ao config
This commit is contained in:
parent
af8887d4ff
commit
f8d03f1ab7
|
|
@ -0,0 +1,9 @@
|
|||
port: 3999
|
||||
defaults:
|
||||
runtime: process
|
||||
agent: hermes
|
||||
workspace: worktree
|
||||
projects:
|
||||
ao:
|
||||
path: /home/hermes/agent-orchestrator
|
||||
defaultBranch: main
|
||||
|
|
@ -0,0 +1,337 @@
|
|||
# Agent Orchestrator /docs Plan — Strategy + Execution (All-Rounded)
|
||||
|
||||
Status: Approved planning artifact for implementation handoff
|
||||
Owner: Agent Orchestrator team
|
||||
Scope: Build complete user-facing docs at `/docs` inside `packages/web` now; migrate to `website/` later
|
||||
|
||||
---
|
||||
|
||||
## 0) Why this document exists
|
||||
|
||||
You asked for two things at once:
|
||||
1. Rich strategic context (so implementers make good decisions), and
|
||||
2. A one-shot coding brief (so they actually ship, not over-plan).
|
||||
|
||||
This document combines both. It is intentionally opinionated and execution-focused.
|
||||
|
||||
---
|
||||
|
||||
## 1) Product context and decision record
|
||||
|
||||
### Problem
|
||||
Agent Orchestrator has strong feature docs, but no coherent user-facing docs experience. New users currently piece things together from README + scattered files.
|
||||
|
||||
### Goal
|
||||
Ship a complete, high-clarity documentation experience that answers:
|
||||
- What is AO?
|
||||
- What can I do with AO?
|
||||
- How do I do it right now?
|
||||
|
||||
### Confirmed staging decision
|
||||
- Phase 1 (now): implement docs at `/docs` in `packages/web`.
|
||||
- Phase 2 (later, after approval): copy/migrate docs module into root `website/` app.
|
||||
|
||||
### Why this is the correct strategy
|
||||
1. Fastest path to real user value.
|
||||
2. Lower risk than architecture move + docs rewrite simultaneously.
|
||||
3. Lets us validate IA/content before migration.
|
||||
4. Keeps later move mostly mechanical if boundaries are clean.
|
||||
|
||||
---
|
||||
|
||||
## 2) Inputs and constraints already validated
|
||||
|
||||
- Issue reference: #1133 (user-facing docs requirement).
|
||||
- PR #1047 was useful as process/style input, but not merged on main.
|
||||
- AO visual source of truth:
|
||||
- `DESIGN.md`
|
||||
- `packages/web/src/app/globals.css`
|
||||
- Current docs source material to mine:
|
||||
- `README.md`
|
||||
- `SETUP.md`
|
||||
- `docs/CLI.md`
|
||||
- `TROUBLESHOOTING.md`
|
||||
- `ARCHITECTURE.md`
|
||||
- `agent-orchestrator.yaml.example`
|
||||
- selected user-relevant pieces of `docs/DEVELOPMENT.md`
|
||||
|
||||
---
|
||||
|
||||
## 3) Non-negotiable principles
|
||||
|
||||
1. User-first docs, not contributor diary.
|
||||
2. Complete workflows, not fragmented reference dumps.
|
||||
3. AO visual identity must remain consistent.
|
||||
4. No placeholder pages in core journey.
|
||||
5. Implementation must be portable to `website/`.
|
||||
6. No breaking dashboard behavior.
|
||||
|
||||
---
|
||||
|
||||
## 4) Information architecture (Diátaxis)
|
||||
|
||||
### Tutorials (learning-oriented)
|
||||
- First run from zero
|
||||
- End-to-end issue -> PR flow
|
||||
- Running multiple agents in parallel
|
||||
|
||||
### How-to guides (task-oriented)
|
||||
- Configure GitHub issue workflow
|
||||
- Configure Linear workflow
|
||||
- Handle CI failures
|
||||
- Handle review comments
|
||||
- Add/operate multiple projects
|
||||
- Remote access setup (incl. practical caveats)
|
||||
- Recover stuck/orphan sessions
|
||||
|
||||
### Reference (lookup-oriented)
|
||||
- CLI reference
|
||||
- Config reference
|
||||
- Plugin slot matrix
|
||||
- Runtime behavior and status model
|
||||
- Ports/env vars/endpoints references
|
||||
|
||||
### Explanation (understanding-oriented)
|
||||
- Why orchestration beats single-agent terminal loops
|
||||
- AO lifecycle model
|
||||
- Reactions and escalation semantics
|
||||
- Plugin architecture reasoning
|
||||
|
||||
---
|
||||
|
||||
## 5) Required sitemap for Phase 1
|
||||
|
||||
- `/docs`
|
||||
- `/docs/getting-started`
|
||||
- `/docs/installation`
|
||||
- `/docs/quickstart/first-run`
|
||||
- `/docs/workflows/parallel-issues`
|
||||
- `/docs/workflows/ci-recovery`
|
||||
- `/docs/workflows/review-loop`
|
||||
- `/docs/workflows/multi-project`
|
||||
- `/docs/configuration/overview`
|
||||
- `/docs/configuration/projects`
|
||||
- `/docs/configuration/reactions`
|
||||
- `/docs/configuration/remote-access`
|
||||
- `/docs/cli`
|
||||
- `/docs/plugins`
|
||||
- `/docs/troubleshooting`
|
||||
- `/docs/faq`
|
||||
- `/docs/changelog`
|
||||
- `/docs/migration`
|
||||
|
||||
No core page above may be empty/placeholder.
|
||||
|
||||
---
|
||||
|
||||
## 6) UX + visual design requirements
|
||||
|
||||
### Must align with AO style
|
||||
- warm dark palette
|
||||
- dense but readable docs layout
|
||||
- subtle borders and restrained depth
|
||||
- Geist-like prose + JetBrains Mono for commands/code
|
||||
- low-drama motion
|
||||
|
||||
### Must avoid
|
||||
- cinematic/marketing-heavy visuals
|
||||
- decorative effects that hurt reading
|
||||
- detached design language that looks like another product
|
||||
|
||||
### Token anchor (dark mode)
|
||||
Use AO tokens rather than hardcoded one-offs:
|
||||
- `--color-bg-base: #121110`
|
||||
- `--color-bg-surface: #1a1918`
|
||||
- `--color-bg-elevated: #222120`
|
||||
- `--color-text-primary: #f0ece8`
|
||||
- `--color-text-secondary: #a8a29e`
|
||||
- `--color-accent: #8b9cf7`
|
||||
- `--color-accent-amber: #f97316`
|
||||
- `--color-border-default: rgba(255,240,220,0.13)`
|
||||
|
||||
---
|
||||
|
||||
## 7) Fumadocs feature set to implement now
|
||||
|
||||
1. TOC + heading anchors
|
||||
2. Full-text search (+ keyboard shortcut hint)
|
||||
3. Syntax highlighted code blocks (Shiki), copy button, code groups
|
||||
4. Callouts/admonitions: info, success, warning, danger
|
||||
5. Sidebar from page tree
|
||||
6. Last-updated metadata + edit links
|
||||
7. Prev/next page navigation
|
||||
8. Theme handling consistent with AO
|
||||
9. Lightweight feedback mechanism per page
|
||||
10. LLM-friendly output path if compatible in stack
|
||||
|
||||
OpenAPI docs integration:
|
||||
- Include only if dependency compatibility is clean in Phase 1.
|
||||
- Otherwise explicitly mark as Phase 2 extension.
|
||||
|
||||
---
|
||||
|
||||
## 8) Dependency and compatibility strategy (critical)
|
||||
|
||||
Because `packages/web` is on Next 15, do not casually install latest Fumadocs variants that force Next 16.
|
||||
|
||||
Use Next-15-compatible baseline:
|
||||
- `fumadocs-core@15.0.0`
|
||||
- `fumadocs-ui@15.0.0`
|
||||
- `fumadocs-mdx@14.2.x`
|
||||
|
||||
Rules:
|
||||
- Do NOT upgrade `packages/web` to Next 16 in this task.
|
||||
- Do NOT adopt incompatible Fumadocs UI/Core versions.
|
||||
- Any deviation must be justified with passing build/test proof.
|
||||
|
||||
---
|
||||
|
||||
## 9) Content migration strategy
|
||||
|
||||
### Source-to-target approach
|
||||
Build a migration map from existing docs to new pages:
|
||||
- source file
|
||||
- target page
|
||||
- keep/rewrite/drop decision
|
||||
- missing gaps to author fresh
|
||||
|
||||
### Content rules
|
||||
1. No copy-paste dumps from source docs.
|
||||
2. Rewrite for user outcomes and task success.
|
||||
3. One canonical home per concept.
|
||||
4. Link advanced/internal docs instead of duplicating internals.
|
||||
|
||||
### Required depth standard per major page
|
||||
Each page must include:
|
||||
1. Purpose
|
||||
2. Prerequisites
|
||||
3. Exact steps/commands
|
||||
4. Expected result
|
||||
5. Failure modes + fixes
|
||||
6. Next steps links
|
||||
|
||||
If this 6-part shape is missing, the page is not done.
|
||||
|
||||
---
|
||||
|
||||
## 10) Implementation architecture (Phase 1 in packages/web)
|
||||
|
||||
### Route and layout
|
||||
- Add docs route tree under `packages/web/src/app/docs`.
|
||||
- Add docs layout with:
|
||||
- top nav
|
||||
- left sidebar
|
||||
- right TOC on desktop
|
||||
- mobile-safe nav
|
||||
|
||||
### Integration with dashboard
|
||||
- Add visible dashboard -> docs entry point.
|
||||
- Add docs -> dashboard CTA.
|
||||
|
||||
### Content source
|
||||
- Keep one docs content root (recommended `packages/web/content/docs/**`).
|
||||
- Keep page tree config explicit and portable.
|
||||
|
||||
### Portability for future migration
|
||||
- Keep docs-specific components isolated (e.g. `src/components/docs/*`).
|
||||
- Avoid dependencies on dashboard runtime internals.
|
||||
- Keep docs config/content decoupled from app-specific state.
|
||||
|
||||
---
|
||||
|
||||
## 11) Testing and QA plan
|
||||
|
||||
### Minimum automated tests
|
||||
- docs home render
|
||||
- representative docs leaf page render
|
||||
- sidebar/nav path behavior
|
||||
- mobile render sanity (no crash)
|
||||
|
||||
### Manual QA checklist
|
||||
- Search returns expected pages
|
||||
- TOC anchors jump correctly
|
||||
- Code copy works
|
||||
- Internal links have no dead ends
|
||||
- Keyboard navigation works
|
||||
- Mobile readability and nav work
|
||||
- Contrast/accessibility smoke checks pass
|
||||
|
||||
### Validation commands (must run)
|
||||
- `pnpm --filter @aoagents/ao-web typecheck`
|
||||
- `pnpm --filter @aoagents/ao-web test`
|
||||
- plus route smoke run in dev for `/docs`
|
||||
|
||||
---
|
||||
|
||||
## 12) Risks and mitigations
|
||||
|
||||
1) Docs/dashboard coupling becomes messy
|
||||
- Mitigation: strict module boundaries from day one.
|
||||
|
||||
2) Big doc set, weak onboarding flow
|
||||
- Mitigation: quickstart-first, path-driven docs home.
|
||||
|
||||
3) Stale commands/config snippets
|
||||
- Mitigation: command verification pass before merge.
|
||||
|
||||
4) Pretty UI, weak utility
|
||||
- Mitigation: enforce 6-part depth standard per page.
|
||||
|
||||
5) Dependency incompatibility with Fumadocs
|
||||
- Mitigation: pin compatible versions and verify early.
|
||||
|
||||
---
|
||||
|
||||
## 13) Definition of done
|
||||
|
||||
### User success
|
||||
- New user understands AO in <5 minutes.
|
||||
- New user can complete first run from docs alone.
|
||||
|
||||
### Content completeness
|
||||
- All required sitemap pages exist and are fully written.
|
||||
- Core workflows and troubleshooting are actionable.
|
||||
|
||||
### Technical completeness
|
||||
- Docs route is stable, searchable, navigable.
|
||||
- No obvious runtime errors on docs pages.
|
||||
- Typecheck and tests pass.
|
||||
|
||||
### Design completeness
|
||||
- UI looks like AO product family, not a random template.
|
||||
|
||||
---
|
||||
|
||||
## 14) One-shot coding agent execution brief (copy-paste)
|
||||
|
||||
Implement this in one PR. Do not return a planning-only PR.
|
||||
|
||||
Build complete user docs in `packages/web` at `/docs` using Fumadocs with:
|
||||
- docs route + layout + nav + sidebar + toc + search
|
||||
- AO-aligned theming and typography
|
||||
- full content for required sitemap pages
|
||||
- dashboard/docs cross-links
|
||||
- tests + validation evidence
|
||||
|
||||
Hard constraints:
|
||||
- stay in `packages/web`
|
||||
- no dashboard regressions
|
||||
- no placeholders in core docs pages
|
||||
- keep migration portability to `website/`
|
||||
- use Next-15-compatible Fumadocs versions
|
||||
|
||||
PR must include:
|
||||
1. implemented routes/components/content structure
|
||||
2. dependency versions + compatibility reasoning
|
||||
3. final sitemap
|
||||
4. source docs used for migration
|
||||
5. commands run + test results
|
||||
6. follow-up notes for `website/` migration
|
||||
|
||||
---
|
||||
|
||||
## 15) Final recommendation
|
||||
|
||||
Ship `/docs` in `packages/web` now, with clean boundaries and portable docs modules. Then migrate to `website/` as a controlled second step after content and UX are validated.
|
||||
|
||||
This is the fastest path that still preserves long-term architecture quality.
|
||||
|
|
@ -0,0 +1,790 @@
|
|||
# Agent Orchestrator — Windows QA Report
|
||||
|
||||
**Date:** 2026-04-12
|
||||
**Platform:** Windows 11 (10.0.26200)
|
||||
**Branch:** `feat/windows-platform-adapter`
|
||||
**Duration:** ~60 minutes
|
||||
**Framework:** Next.js 15 + CLI (Node.js 22)
|
||||
**Pages/Features Tested:** 40+
|
||||
|
||||
---
|
||||
|
||||
## Health Score: 48/100
|
||||
|
||||
| Category | Score | Weight | Weighted |
|
||||
|----------|-------|--------|----------|
|
||||
| Functional | 35 | 20% | 7.0 |
|
||||
| Console | 100 | 15% | 15.0 |
|
||||
| UX | 55 | 15% | 8.25 |
|
||||
| Accessibility | 80 | 15% | 12.0 |
|
||||
| Links | 100 | 10% | 10.0 |
|
||||
| Visual | 75 | 10% | 7.5 |
|
||||
| Performance | 80 | 10% | 8.0 |
|
||||
| Content | 90 | 5% | 4.5 |
|
||||
| **TOTAL** | | | **~48** |
|
||||
|
||||
---
|
||||
|
||||
## Top 9 Things to Fix
|
||||
|
||||
1. **Codex agent dies on every Windows spawn** (ISSUE-001) — `shellEscape(binary)` produces a quoted absolute path that PowerShell parses as a string literal. Affects every agent using `shellEscape(binary)` first.
|
||||
2. **Web API can't spawn or send messages to sessions on Windows** (ISSUE-003) — `Runtime plugin 'process' not found`. Dashboard plugin registry is missing process runtime.
|
||||
3. **Missing `windowsHide: true` everywhere** (ISSUE-017) — root cause of the popup-window-on-kill regression. Zero occurrences of `windowsHide` in the entire codebase. Four call sites in `platform.ts`. One-line fix per call site.
|
||||
4. **`ao session kill` doesn't delete the session branch** (ISSUE-021) — leaves dead branches in git, blocks re-spawning an issue with the same name. CLI error is truncated so users see "Failed to create worktree" without the real reason.
|
||||
5. **Stale git worktree blocks spawn after force-cleanup** (ISSUE-018) — after file locks prevent cleanup, `ao spawn` fails silently with "missing but already registered worktree". Needs self-healing `git worktree prune`.
|
||||
6. **`ao stop` leaves orphaned agent processes and worktrees** (ISSUE-004) — confirmed 11 zombie node processes accumulated across 2 test cycles (4 from ~10h ago, 6 from ~5h ago). Processes never cleaned up.
|
||||
7. **Spawn race condition — sessions briefly show `exited` / `null` activity immediately after spawn** (ISSUE-019) — dashboard flickers to "dead" for 5-10 seconds during healthy startup.
|
||||
8. **`ao batch-spawn` is non-atomic** (ISSUE-023) — on interrupt leaves partial state (worktree, branch, metadata). No rollback on error.
|
||||
9. **`ao open` is dead code on Windows** (ISSUE-006) — hardcoded to tmux, always "No sessions to open".
|
||||
|
||||
---
|
||||
|
||||
## Critical Issues
|
||||
|
||||
### ISSUE-001: Codex agent fails to launch — PowerShell parser error
|
||||
**Severity:** Critical
|
||||
**Category:** Functional
|
||||
|
||||
**Repro:**
|
||||
```bash
|
||||
ao spawn "test codex" --agent codex
|
||||
```
|
||||
|
||||
**Result:** Process spawned, immediately died. `ao session attach <id>` shows:
|
||||
```
|
||||
ParserError:
|
||||
Line |
|
||||
1 | 'codex' -c check_for_update_on_startup=false --dangerously-bypass-app …
|
||||
| ~~
|
||||
| Unexpected token '-c' in expression or statement.
|
||||
```
|
||||
|
||||
**Root cause:** In `packages/plugins/agent-codex/src/index.ts`, `getLaunchCommand` builds the command as:
|
||||
```ts
|
||||
const parts: string[] = [shellEscape(binary)];
|
||||
appendNoUpdateCheckFlag(parts); // pushes "-c", "check_for_update_on_startup=false"
|
||||
// ...
|
||||
return parts.join(" ");
|
||||
```
|
||||
|
||||
`shellEscape("codex")` on Windows returns `'codex'`. PowerShell parses `'codex' -c ...` as a string literal followed by `-c` token, not as a command. To execute a quoted command in PowerShell you must use the call operator `&`.
|
||||
|
||||
**Fix:** On Windows, prefix the launch command with `& ` when the first argument is quoted, OR avoid quoting bare command names that don't need it.
|
||||
|
||||
**Affects:** codex (confirmed), likely cursor and any future agent using `shellEscape(binary)` first.
|
||||
|
||||
**Note:** claude-code does NOT have this bug because it uses unquoted `claude` (relies on PATH).
|
||||
|
||||
---
|
||||
|
||||
### ISSUE-002: `resolveCodexBinary` returns the wrong file on Windows
|
||||
**Severity:** High
|
||||
**Category:** Functional
|
||||
|
||||
**Repro:**
|
||||
1. `which codex` in Git Bash returns `/c/Users/priya/AppData/Roaming/npm/codex` (no extension)
|
||||
2. Codex uses this path in `resolveCodexBinary`
|
||||
3. PowerShell can't execute extensionless `codex` (it's a bash wrapper script)
|
||||
|
||||
**Expected:** On Windows, prefer `codex.cmd`, `codex.exe`, or `codex.ps1` (in that order). The npm npm wrapper at `%APPDATA%/npm/` always installs three variants:
|
||||
- `codex` (bash wrapper for WSL/Cygwin/Git Bash) ← currently picked
|
||||
- `codex.cmd` (cmd.exe wrapper) ← should be picked
|
||||
- `codex.ps1` (PowerShell wrapper)
|
||||
|
||||
**Fix:** In `resolveCodexBinary()`, when on Windows, append `.cmd` to candidates and check for `.cmd`/`.exe`/`.ps1` versions first.
|
||||
|
||||
---
|
||||
|
||||
### ISSUE-003: Web API can't access process runtime — dashboard spawn/send broken
|
||||
**Severity:** Critical
|
||||
**Category:** Functional
|
||||
|
||||
**Repro:**
|
||||
```
|
||||
$ curl -X POST -H "Content-Type: application/json" \
|
||||
-d '{"projectId":"...","issueId":"test"}' \
|
||||
http://localhost:3000/api/spawn
|
||||
{"error":"Runtime plugin 'process' not found"}
|
||||
|
||||
$ curl -X POST -H "Content-Type: application/json" \
|
||||
-d '{"message":"test"}' \
|
||||
http://localhost:3000/api/sessions/fwpa-1/send
|
||||
{"error":"No runtime plugin for session fwpa-1"}
|
||||
|
||||
$ curl -X POST -H "Content-Type: application/json" \
|
||||
-d '{"projectId":"..."}' \
|
||||
http://localhost:3000/api/orchestrators
|
||||
{"error":"Runtime plugin 'process' not found"}
|
||||
```
|
||||
|
||||
**What works:** `POST /api/sessions/[id]/kill` succeeds (probably because lifecycle manager has cached runtime instances).
|
||||
|
||||
**Root cause:** The Next.js server process loads a different plugin registry than the CLI. Default in CLI is `runtime: process` but the web server doesn't seem to have the process runtime plugin registered.
|
||||
|
||||
**Impact:** Users cannot spawn sessions from the dashboard, cannot send messages from the dashboard via the API, and cannot start orchestrator sessions from the dashboard.
|
||||
|
||||
**Note:** The dashboard's terminal input (xterm.js → WebSocket → named pipe) DOES work — that path bypasses the runtime plugin lookup. But the React UI's "Send" buttons that hit these REST endpoints will all fail.
|
||||
|
||||
---
|
||||
|
||||
### ISSUE-004: `ao stop` leaves agent processes and worktrees behind
|
||||
**Severity:** High
|
||||
**Category:** Functional
|
||||
|
||||
**Repro:**
|
||||
1. `ao start --no-orchestrator`
|
||||
2. `ao spawn "test"`
|
||||
3. `ao stop`
|
||||
4. Check: `cat ~/.agent-orchestrator/.../sessions/` — fwpa-1 metadata still present
|
||||
5. Check: `ls ~/.worktrees/...` — worktree directory still present
|
||||
6. Check: `Get-Process pwsh,node` — 13+ leftover processes from the AO session
|
||||
|
||||
**Expected:** `ao stop` should:
|
||||
1. Kill all agent processes for the project
|
||||
2. Remove session metadata
|
||||
3. Clean up worktrees
|
||||
4. OR document clearly that `ao stop` only stops orchestrator and users must `ao session kill` first
|
||||
|
||||
**Current behavior:** Only kills the orchestrator/dashboard/lifecycle worker. Agents become orphaned, worktrees pile up.
|
||||
|
||||
---
|
||||
|
||||
### ISSUE-005: `ao stop` and `ao session kill` trigger popup window requiring Enter press
|
||||
**Severity:** High
|
||||
**Category:** Functional (Regression — user confirmed, twice now)
|
||||
|
||||
**Repro:**
|
||||
1. `ao start` (with orchestrator enabled)
|
||||
2. `ao spawn test-session`
|
||||
3. `ao session kill test-session` → pops a terminal window, user must press Enter
|
||||
4. `ao stop` → same behavior
|
||||
|
||||
**Root cause (identified):** `packages/core/src/platform.ts:91` calls `execFileAsync("taskkill", args)` **without `windowsHide: true`**. On Windows, when Node.js spawns a child process (via `child_process.spawn`/`execFile`) without `windowsHide: true`, and the parent process doesn't own a console (or is being wrapped by npx/bash), Windows creates a new console window for the child. For `taskkill` this window briefly flashes or — in some cases — persists waiting for Enter.
|
||||
|
||||
**Evidence:**
|
||||
```bash
|
||||
$ grep -rn "windowsHide" packages/
|
||||
(no results)
|
||||
```
|
||||
Not a single place in the entire codebase passes `windowsHide: true` to any spawn/exec call. This is the likely cause of console window pops on several commands that kill processes on Windows.
|
||||
|
||||
**Also affected:** `findPidByPort` calls `execFileAsync("netstat", ["-ano"])` without `windowsHide: true` at platform.ts:116, which runs during `ao start` port detection.
|
||||
|
||||
**Fix:** Add `{ windowsHide: true }` to every `execFileAsync`/`spawn`/`execFile` call that targets Windows binaries. Minimal fix:
|
||||
```ts
|
||||
await execFileAsync("taskkill", args, { windowsHide: true });
|
||||
await execFileAsync("netstat", ["-ano"], { windowsHide: true });
|
||||
```
|
||||
|
||||
**Calls:** `killProcessTree` is invoked on every session kill, `ao stop`, PTY host teardown, and worktree cleanup — so this popup affects many commands.
|
||||
|
||||
---
|
||||
|
||||
### ISSUE-006: `ao open` broken — hardcoded to tmux
|
||||
**Severity:** Critical
|
||||
**Category:** Functional
|
||||
|
||||
**Root cause:** `packages/cli/src/commands/open.ts:27` calls `getTmuxSessions()` which returns empty on Windows. Line 43 looks up sessions against tmux output, not the session manager. Result: always "No sessions to open" even with active sessions.
|
||||
|
||||
**Fix:** On Windows with `runtime: process`, query the session manager directly. Could open the dashboard URL or attach via named pipe.
|
||||
|
||||
---
|
||||
|
||||
### ISSUE-007: `ao doctor` crashes without `AO_BASH_PATH`
|
||||
**Severity:** High
|
||||
**Category:** Functional / DX
|
||||
|
||||
**Repro:** Run `npx ao doctor` with no env var set on Windows.
|
||||
|
||||
**Output:** `Cannot run repo scripts on Windows without bash. Set AO_BASH_PATH to a bash executable (e.g. C:\Program Files\Git\bin\bash.exe).`
|
||||
|
||||
**Expected:** Auto-detect Git Bash at common paths, OR skip script-dependent checks gracefully.
|
||||
|
||||
With `AO_BASH_PATH=C:/Program Files/Git/bin/bash.exe` set, doctor works correctly: 12 PASS, 2 WARN, 1 FAIL.
|
||||
|
||||
---
|
||||
|
||||
### ISSUE-008: Activity state shows `null` instead of `exited` when agent dies
|
||||
**Severity:** Medium
|
||||
**Category:** Functional
|
||||
|
||||
**Repro:**
|
||||
1. Spawn a session that dies on launch (e.g., `ao spawn x --agent codex` due to ISSUE-001)
|
||||
2. Wait 30 seconds for next lifecycle poll
|
||||
3. `curl /api/sessions` shows `"activity": null` instead of `"activity": "exited"`
|
||||
4. `ao status` (CLI) shows `exited` correctly
|
||||
|
||||
**Inconsistency:** CLI and Web API give different activity values for the same session. The lifecycle manager and CLI use different code paths.
|
||||
|
||||
**Impact:** Dashboard shows session as "working" with no activity dot, even though the process is dead.
|
||||
|
||||
---
|
||||
|
||||
### ISSUE-009: Worktree directory not cleaned after session kill
|
||||
**Severity:** Medium
|
||||
**Category:** Functional
|
||||
|
||||
**Repro:**
|
||||
1. Spawn session: `ao spawn "test"` → creates worktree at `~/.worktrees/.../fwpa-N`
|
||||
2. Kill session: `ao session kill fwpa-N`
|
||||
3. Check: `git worktree list` shows worktree de-registered (correct)
|
||||
4. Check: `ls ~/.worktrees/...` → directory still has 16+ files
|
||||
|
||||
**Root cause:** Windows file locks prevent `git worktree remove` from deleting the directory. fwpa-1 cleans correctly, fwpa-2 doesn't — non-deterministic.
|
||||
|
||||
**Fix:** Retry directory cleanup with delay, OR queue deferred cleanup on next `ao start`.
|
||||
|
||||
---
|
||||
|
||||
### ISSUE-010: Session stuck at `spawning` when lifecycle worker dies
|
||||
**Severity:** Medium
|
||||
**Category:** Functional
|
||||
|
||||
**Repro:**
|
||||
1. `ao start --no-dashboard --no-orchestrator`
|
||||
2. `ao spawn "test"`
|
||||
3. Wait 1+ minutes
|
||||
4. `ao status` shows `spawning` indefinitely
|
||||
|
||||
**Root cause:** The lifecycle runs in-process inside `ao start` (via `ensureLifecycleWorker` in `lifecycle-service.ts`). If `ao start` crashes or the terminal running it is closed, the polling loop dies and no state transitions happen. The dashboard process alone does not have its own lifecycle loop — it depends entirely on `ao start` staying alive.
|
||||
|
||||
---
|
||||
|
||||
### ISSUE-011: Codex/Aider sessions hidden from dashboard UI when activity is null
|
||||
**Severity:** Medium (actually visible — UI does show them)
|
||||
**Category:** UX
|
||||
|
||||
When ISSUE-008 occurs (`activity: null`), dashboard fleet header shows "4 FLEET, 2 ACTIVE" but the Working column actually does include the dead-process sessions. The "ACTIVE" count is misleading because it counts only sessions with non-null activity.
|
||||
|
||||
---
|
||||
|
||||
### ISSUE-012: xterm.js terminal rows clip ~3 characters per line on Windows
|
||||
**Severity:** Medium
|
||||
**Category:** Visual (Windows-specific)
|
||||
|
||||
**Repro (confirmed in browse at 1366x768):**
|
||||
1. Navigate to `/sessions/[id]` with an active session that has content
|
||||
2. Inspect `.xterm-row` children of `.xterm-rows`
|
||||
|
||||
**Measurement:**
|
||||
- `.xterm-rows` container: `clientWidth: 1098, scrollWidth: 1098` (no overflow at container level)
|
||||
- **12 of 30 `.xterm-row` children with content (`textLen: 144`)** have `clientWidth: 1098, scrollWidth: 1123` — **25px overflow each**
|
||||
- Empty rows do not overflow
|
||||
|
||||
**Root cause:** xterm.js calculates column count = floor(1098 / 7.625) = 144 chars. But Windows font rendering uses ~7.80px per char due to ClearType hinting. Accumulated error: (7.80 - 7.625) × 144 = **25.2px per row**.
|
||||
|
||||
**Impact:** Every line with content that fills the terminal width gets its rightmost ~3 characters clipped on Windows. The container has `overflow: hidden` so there's no visible scrollbar, but the content is silently truncated. On macOS the font metrics match, so no clipping occurs.
|
||||
|
||||
**Fix options:**
|
||||
1. Use xterm.js's canvas/webgl renderer instead of DOM renderer on Windows (better pixel precision)
|
||||
2. Force `letterSpacing: 0` and explicitly set `fontWidth` from direct measurement
|
||||
3. Reduce column count on Windows by 2-3 chars as a safety margin
|
||||
4. Upgrade xterm.js if a newer version has better Windows font metric handling
|
||||
|
||||
---
|
||||
|
||||
### ISSUE-013: Kanban board horizontal scroll at narrow widths
|
||||
**Severity:** Low
|
||||
**Category:** Visual
|
||||
|
||||
The kanban board (`packages/web/src/app/globals.css:1839`) uses 5 columns of `min-width: 260px` + 8px gaps = **1332px minimum**. Below ~1388px viewport (after `dashboard-main` padding), the kanban board scrolls horizontally. On Windows with 17px native scrollbars (vs 0px overlay on macOS), this scrollbar is more visually obvious.
|
||||
|
||||
**Fix options:** Reduce column min-width, use horizontal scroll snap, or make columns stack on narrow viewports.
|
||||
|
||||
---
|
||||
|
||||
### ISSUE-014: POST /api/spawn rejects valid CLI issue IDs
|
||||
**Severity:** Low
|
||||
**Category:** Functional / Inconsistency
|
||||
|
||||
**Repro:**
|
||||
```
|
||||
POST /api/spawn body: {"issueId": "test issue"}
|
||||
→ {"error":"issueId must match [a-zA-Z0-9_-]+"}
|
||||
```
|
||||
|
||||
But CLI accepts: `ao spawn "test issue"` works fine.
|
||||
|
||||
**Inconsistency:** Web API has stricter validation than CLI for the same field.
|
||||
|
||||
---
|
||||
|
||||
### ISSUE-015: Desktop notifications are a silent no-op on Windows
|
||||
**Severity:** Low
|
||||
|
||||
`packages/plugins/notifier-desktop/src/index.ts:61-86` only supports macOS and Linux. Windows logs a warning and resolves silently.
|
||||
|
||||
---
|
||||
|
||||
### ISSUE-016: Noisy notifier warnings on every CLI command
|
||||
**Severity:** Low
|
||||
**Category:** UX
|
||||
|
||||
Every `ao` command prints 4 warning lines about unconfigured notifiers (`discord`, `openclaw`, `slack`, `webhook`) even though the generated config has `notifiers: []`. The plugins are loaded despite not being requested.
|
||||
|
||||
---
|
||||
|
||||
### ISSUE-017: Missing `windowsHide: true` on every spawn/exec call in the codebase
|
||||
**Severity:** High (umbrella root cause for ISSUE-005 and more)
|
||||
**Category:** Functional / Windows DX
|
||||
|
||||
**Evidence:** `grep -rn "windowsHide" packages/` returns **zero matches**. Not a single spawn/execFile/execFileSync call in the entire codebase passes `windowsHide: true`.
|
||||
|
||||
**Affected call sites identified:**
|
||||
|
||||
| File:line | Command | Frequency | Impact |
|
||||
|-----------|---------|-----------|--------|
|
||||
| `packages/core/src/platform.ts:34` | `execFileSync("pwsh", ["-Version"])` | Every AO command startup | Console flash on every `ao <command>` |
|
||||
| `packages/core/src/platform.ts:42` | `execFileSync("powershell.exe", ["-Command", "echo ok"])` | Fallback in shell detection | Console flash |
|
||||
| `packages/core/src/platform.ts:91` | `execFileAsync("taskkill", args)` | Every session kill, ao stop, worktree cleanup | **Popup window requiring Enter press (ISSUE-005)** |
|
||||
| `packages/core/src/platform.ts:116` | `execFileAsync("netstat", ["-ano"])` | Port discovery during ao start | Console flash |
|
||||
|
||||
**Fix:** Add `{ windowsHide: true }` to every call. One-line fix per location:
|
||||
```ts
|
||||
await execFileAsync("taskkill", args, { windowsHide: true });
|
||||
await execFileAsync("netstat", ["-ano"], { windowsHide: true });
|
||||
execFileSync("pwsh", ["-Version"], { timeout: 5000, stdio: "ignore", windowsHide: true });
|
||||
```
|
||||
|
||||
This is the root cause of ISSUE-005 (`ao stop` / `ao session kill` popup) and likely also causes brief console flashes on every AO command.
|
||||
|
||||
---
|
||||
|
||||
### ISSUE-018: Stale git worktree registry blocks spawn after force-cleanup
|
||||
**Severity:** High
|
||||
**Category:** Functional (Windows-specific consequence of ISSUE-009)
|
||||
|
||||
**Repro:**
|
||||
1. `ao spawn test1` → creates worktree at `~/.worktrees/.../fwpa-3`
|
||||
2. `ao session kill fwpa-3` → git worktree remove fails due to file locks (ISSUE-009)
|
||||
3. User force-deletes the directory via PowerShell
|
||||
4. `ao spawn test2` → fails silently with:
|
||||
```
|
||||
fatal: 'C:/Users/priya/.worktrees/.../fwpa-3' is a missing but already registered worktree;
|
||||
use 'add -f' to override, or 'prune' or 'remove' to clear
|
||||
```
|
||||
|
||||
**Impact:**
|
||||
- CLI spawn appears to succeed but session is NOT created (silent error, no exit code change)
|
||||
- `ao status` shows no sessions (so no way to tell the spawn failed)
|
||||
- User must manually run `git worktree prune` to unblock further spawns
|
||||
|
||||
**Root cause:** When `session kill` fails to remove the worktree directory (Windows file locks), git's worktree registry keeps the stale entry. The next spawn attempts to create a worktree with the same incrementing name and collides with the stale entry.
|
||||
|
||||
**Fix:**
|
||||
1. Before every `ao spawn`, run `git worktree prune` to clean stale entries
|
||||
2. Or detect "missing but already registered" errors and auto-prune + retry
|
||||
3. Or use `git worktree add -f` to force overwrite
|
||||
4. Propagate worktree creation errors to the user — currently silent
|
||||
|
||||
---
|
||||
|
||||
### ISSUE-019: Spawn race condition — session briefly reports `activity: "exited"` immediately after spawn
|
||||
**Severity:** Medium
|
||||
**Category:** Functional
|
||||
|
||||
**Repro (via SSE stream):**
|
||||
1. Spawn a session: `ao spawn test --agent claude-code`
|
||||
2. Capture SSE events from `/api/events`
|
||||
3. Observe timeline:
|
||||
```
|
||||
T+0s: {"sessions":[]} ← before spawn
|
||||
T+5s: {"id":"fwpa-2","status":"spawning","activity":"exited"} ← WRONG
|
||||
T+10s: {"id":"fwpa-2","status":"spawning","activity":"idle"} ← eventually correct
|
||||
```
|
||||
|
||||
**Impact:** For the first 5-10 seconds of a session's life, the dashboard shows `activity: exited` — making users think the session died when it's actually still starting up. This is also visible in the 4-concurrent-session test where codex/aider showed `null` activity (race between spawn and process detection) and the dashboard display was inconsistent.
|
||||
|
||||
**Root cause:** Lifecycle polling runs before the agent process is actually visible to `isProcessRunning`, or before `getActivityState` finds the agent's native JSONL file. The first poll returns `exited` or `null`.
|
||||
|
||||
**Fix:** On initial spawn, skip activity detection for the first N polls, or return a `spawning` / `pending` activity state instead of `exited` / `null` until a grace period has elapsed.
|
||||
|
||||
---
|
||||
|
||||
### ISSUE-021: `ao session kill` does not delete the session branch
|
||||
**Severity:** High
|
||||
**Category:** Functional
|
||||
|
||||
**Repro:**
|
||||
1. `ao spawn test-branch-name` → creates worktree + branch `feat/test-branch-name`
|
||||
2. `ao session kill <id>` → removes worktree and session metadata
|
||||
3. Check: `git branch | grep test-branch-name` → branch still exists
|
||||
4. `ao spawn test-branch-name` again → **fails** with `fatal: a branch named 'feat/test-branch-name' already exists`
|
||||
|
||||
**Impact:**
|
||||
- Cannot re-spawn an issue with the same name after killing its session
|
||||
- CLI error message is truncated — shows "Failed to create worktree" but hides the underlying `fatal: a branch named 'feat/...' already exists`
|
||||
- Users see silent/unclear spawn failures
|
||||
- Accumulating dead branches in git
|
||||
|
||||
**Confirmed affected branches from this test session:**
|
||||
```
|
||||
feat/concurrent-test-1
|
||||
feat/concurrent-test-2-codex
|
||||
feat/concurrent-test-3-aider
|
||||
feat/concurrent-test-4-opencode
|
||||
feat/dashboard-update-test
|
||||
feat/horizontal-scroll-test
|
||||
feat/retry-test
|
||||
feat/sse-test-dont-edit-files
|
||||
feat/test-dashboard-display
|
||||
feat/test-no-edit
|
||||
feat/test-windows-session-handling
|
||||
```
|
||||
All 11 branches survived `ao session kill` — none were deleted.
|
||||
|
||||
**Fix:** After removing the worktree in `session.destroy()`, also run `git branch -D <branch>` to delete the local branch. Or stash it for recovery (e.g. rename to `archived/<branch>-<timestamp>`). Also: propagate the full git error message through to the CLI output so users can diagnose failures.
|
||||
|
||||
---
|
||||
|
||||
### ISSUE-024: Malformed/invalid YAML reported as "No config found"
|
||||
**Severity:** Medium
|
||||
**Category:** UX / DX
|
||||
|
||||
**Repro:**
|
||||
1. Create a malformed `agent-orchestrator.yaml` (bad indentation, missing colon, etc.)
|
||||
2. Run `ao status`
|
||||
3. Output: `No config found. Run \`ao init\` first.` — but the file exists!
|
||||
|
||||
**Tested variants that all report "No config found":**
|
||||
- Malformed YAML syntax (missing colon, bad indent)
|
||||
- Schema-invalid fields (`port: "not-a-number"`, `runtime: nonexistent-runtime`)
|
||||
- Empty `projects: {}`
|
||||
|
||||
**Root cause:** `packages/cli/src/commands/status.ts:274` uses a bare `catch {}` that swallows all exceptions — `ConfigNotFoundError`, `YAMLParseError`, `ZodError`, etc. All get reported as "No config found".
|
||||
|
||||
**Fix:**
|
||||
```ts
|
||||
catch (err) {
|
||||
if (err instanceof ConfigNotFoundError) {
|
||||
console.log(chalk.yellow("No config found. Run `ao init` first."));
|
||||
} else {
|
||||
console.error(chalk.red(`Config is invalid: ${(err as Error).message}`));
|
||||
process.exit(1);
|
||||
}
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Applies to every command that calls `loadConfig()` in a try/catch.
|
||||
|
||||
---
|
||||
|
||||
### ISSUE-026: `ao start` auto-open races the orchestrator session creation
|
||||
**Severity:** Medium
|
||||
**Category:** UX / Race Condition (user confirmed twice)
|
||||
|
||||
**Repro:**
|
||||
1. `ao start` (with orchestrator enabled)
|
||||
2. Browser tab auto-opens at `http://localhost:3000/sessions/fwpa-orchestrator-1`
|
||||
3. Page shows "Session not found"
|
||||
4. Wait a few seconds and reload → session appears correctly
|
||||
|
||||
**Timing analysis:**
|
||||
Flow in `start.ts`:
|
||||
- Line 982: `startDashboard(...)` — Next.js starts (port 3000 accepts ~1s later)
|
||||
- Line 997: `ensureLifecycleWorker(...)` — lifecycle worker starts
|
||||
- Line 1069: `await sm.spawnOrchestrator(...)` — orchestrator session created + written to disk
|
||||
- Line 1139: `void waitForPortAndOpen(port, url, signal)` — browser opens as soon as port 3000 responds
|
||||
|
||||
**Race:** Even though `sm.spawnOrchestrator` is awaited before `waitForPortAndOpen`, the dashboard's API/SSE may not have picked up the new session file yet when the browser navigates. The CLI writes the session file → dashboard reads it on next API request → but between "CLI finishes writing" and "browser finishes navigating + React hits API", there's a gap where `/api/sessions/<id>` returns 404.
|
||||
|
||||
**Dashboard UX:** When the React page hits a 404 on initial load, it shows "Session not found" instead of retrying a few times or subscribing to SSE to wait for the session to appear. The page doesn't re-render when the session eventually shows up via SSE.
|
||||
|
||||
**Fix options:**
|
||||
1. Before calling `waitForPortAndOpen`, actively probe `GET /api/sessions/<id>` and wait for it to return 200.
|
||||
2. On the dashboard session page, subscribe to SSE updates before showing "not found" — if the session appears within N seconds of page load, navigate to it.
|
||||
3. Add a small retry/loading state to the session detail page — poll for up to 5 seconds before showing the not-found UI.
|
||||
|
||||
**User confirmed:** This happens reproducibly on Windows at least with the current build.
|
||||
|
||||
---
|
||||
|
||||
### ISSUE-025: Symlink fallback on Windows copies entire directory trees
|
||||
**Severity:** Medium
|
||||
**Category:** Functional / Performance
|
||||
|
||||
**Location:** `packages/plugins/workspace-worktree/src/index.ts:355-360`
|
||||
|
||||
**Code:**
|
||||
```ts
|
||||
try {
|
||||
symlinkSync(sourcePath, targetPath);
|
||||
} catch (err) {
|
||||
if (isWindows()) {
|
||||
// Symlinks require admin/Developer Mode on Windows — fall back to copy
|
||||
fs.cpSync(sourcePath, targetPath, { recursive: true });
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Impact on Windows:**
|
||||
1. **Performance disaster:** If a user configures `symlinks: [node_modules]`, every spawned worktree does a full recursive copy of `node_modules` (often 500MB-5GB). Spawn time goes from seconds to minutes.
|
||||
2. **Disk space:** N worktrees × size(node_modules) of disk usage instead of near-zero via symlinks.
|
||||
3. **File lock contamination:** The copy creates duplicate files that Windows file handles can hold onto, worsening ISSUE-009 (worktree cleanup failures). Every worker has its own copy of `node_modules` which get loaded into memory by Node processes, blocking later cleanup.
|
||||
4. **Stale copies:** The copy is a point-in-time snapshot. If `node_modules` updates in the main repo, the worktree copies don't reflect it — agents may work with outdated dependencies.
|
||||
|
||||
**Fix options:**
|
||||
1. Use Windows directory junctions (`mklink /J`) — works without admin for directories on NTFS. Not the same as symlinks but close enough for most use cases.
|
||||
2. Document that `symlinks` requires Developer Mode on Windows; skip the fallback when it's not possible and warn clearly.
|
||||
3. For `node_modules` specifically, use hardlinks via `fs.link` per file (not possible for directories but works for files).
|
||||
|
||||
Currently not triggering because the test config has no `symlinks:` entries, but it's a landmine for any user who adds them.
|
||||
|
||||
---
|
||||
|
||||
### ISSUE-023: `ao batch-spawn` is non-atomic — partial state on interrupt
|
||||
**Severity:** Medium
|
||||
**Category:** Functional
|
||||
|
||||
**Repro:**
|
||||
1. `ao batch-spawn invalid-1 invalid-2`
|
||||
2. The command appears to hang after printing "Project: ...", "Issues: invalid-1, invalid-2" and the notifier warnings
|
||||
3. Kill it via timeout/Ctrl+C
|
||||
4. Check state: **worktree for `invalid-1` already created on disk**, branch `feat/invalid-1` exists, session metadata file written
|
||||
|
||||
**Observed:**
|
||||
- `C:/Users/priya/.worktrees/.../fwpa-4` exists after interrupted batch-spawn
|
||||
- `feat/invalid-1` branch exists
|
||||
- Session metadata file `~/.agent-orchestrator/.../sessions/fwpa-4` exists
|
||||
- Second issue (`invalid-2`) was not attempted
|
||||
|
||||
**Impact:** Batch spawn appears to create resources sequentially without a transaction wrapper. If interrupted (Ctrl+C, timeout, or network error on issue #N), you get N-1 successful sessions plus the one being created — but no rollback. Worktrees, branches, and session metadata are left in partial state.
|
||||
|
||||
**Fix:** Either batch-spawn in parallel with a "cleanup on error" guard, or register each session atomically and finalize after all succeed.
|
||||
|
||||
**Additional observation:** Without GitHub issue tracking configured, `batch-spawn` should probably reject non-numeric/non-tracker-ID inputs upfront. Currently it accepts arbitrary strings.
|
||||
|
||||
---
|
||||
|
||||
### ISSUE-022: `ao start --no-dashboard` leaves stale `running.json` with dead PID
|
||||
**Severity:** Medium
|
||||
**Category:** Functional
|
||||
|
||||
**Repro:**
|
||||
1. `ao start --no-dashboard --no-orchestrator`
|
||||
2. After startup completes: `cat ~/.agent-orchestrator/running.json` shows a PID
|
||||
3. `Get-Process -Id <that PID>` returns DEAD
|
||||
|
||||
**Note on root cause (updated):** The lifecycle now runs in-process inside `ao start` — the PID written to `running.json` is the `ao start` process itself, which is correct. The dead-PID observation from original testing was likely caused by a process wrapper (npx, bash shim) exiting while the real Node child was recorded. The structural concern remains: if `ao start` exits for any reason (crash, user closes terminal), `running.json` will have a stale PID and `ao status` / `ao spawn` will incorrectly believe the lifecycle is running.
|
||||
|
||||
**Tested:** Confirmed with PID 34544 after `ao start --no-dashboard --no-orchestrator` — running.json listed the PID but PowerShell showed it dead.
|
||||
|
||||
**Related to ISSUE-010** (lifecycle stops when `ao start` exits).
|
||||
|
||||
---
|
||||
|
||||
### ISSUE-020: `ao start` auto-opens `/sessions/undefined` when no orchestrator
|
||||
**Severity:** Medium
|
||||
**Category:** Functional / UX
|
||||
|
||||
**Repro:**
|
||||
1. `ao start --no-orchestrator`
|
||||
2. Dashboard starts, browser auto-opens
|
||||
3. Tab opens at `http://localhost:3000/sessions/undefined` → "Session not found" page
|
||||
|
||||
**Root cause:** `packages/cli/src/commands/start.ts:1138`:
|
||||
```ts
|
||||
const orchestratorUrl = hasExistingOrchestrators
|
||||
? `http://localhost:${port}/orchestrators?project=${projectId}`
|
||||
: `http://localhost:${port}/sessions/${selectedOrchestratorId ?? sessionId}`;
|
||||
```
|
||||
When `--no-orchestrator` is passed, `selectedOrchestratorId` and `sessionId` are both `undefined`, so the template renders `.../sessions/undefined`.
|
||||
|
||||
**Fix:** When both IDs are undefined, fall back to `http://localhost:${port}/` (main dashboard).
|
||||
|
||||
**Also:** After `ao stop` kills a session, any stale browser tab pointing to that session's URL shows "Session not found" on reload. The page UX is OK (clear message + "Back to dashboard" link), but adding a brief note like "This session was killed/archived. Start a new one?" would be friendlier.
|
||||
|
||||
---
|
||||
|
||||
### ISSUE-027: `ao start` must stay as a foreground terminal — no Windows daemon story
|
||||
**Severity:** Medium
|
||||
**Category:** UX / Windows-specific
|
||||
|
||||
**Observation:** The lifecycle polling loop runs in-process inside `ao start` (see `lifecycle-service.ts`). This means the terminal window running `ao start` must remain open for the entire duration of a session. Closing the window, logging off, or killing the terminal kills the lifecycle loop — PTY host processes keep running (agents remain alive) but no state transitions fire, no CI reactions happen, no notifications go out.
|
||||
|
||||
On Linux/Mac users work around this with `nohup ao start &`, `tmux`, or `screen`. On Windows none of these are standard — there is no built-in equivalent for detaching a Node.js process from its console.
|
||||
|
||||
**Impact:**
|
||||
- Users doing overnight runs must leave a terminal window open
|
||||
- Remote desktop / SSH sessions die on disconnect, taking the lifecycle with them
|
||||
- No way to recover a running lifecycle without restarting `ao start` (which re-polls fresh)
|
||||
|
||||
**Contrast with Linux/Mac:** The lifecycle has always been in-process, but `ao start` on Unix can be backgrounded cleanly. On Windows this is non-trivial.
|
||||
|
||||
**Possible fixes:**
|
||||
1. Document that users should run `ao start` in Windows Terminal or a persistent PowerShell window
|
||||
2. Add a `--detach` flag that uses `node-windows` or `node-service` to register `ao start` as a Windows Service
|
||||
3. Wrap with a `.vbs` launcher that calls `wscript.exe` to start the process without a console window (common Windows pattern)
|
||||
|
||||
---
|
||||
|
||||
## Communication Test (orchestrator-worker simulation)
|
||||
|
||||
I tested the orchestrator-worker communication path manually:
|
||||
|
||||
| Step | Result |
|
||||
|------|--------|
|
||||
| `ao spawn` to create worker (claude-code) | PASS |
|
||||
| `ao send <id> "<message>"` to deliver text | PASS — "Message sent and processing" |
|
||||
| Agent receives and acts on message | PASS — agent processed the request |
|
||||
| Activity transitions: spawning → working → ready → idle | PASS — observed via `ao status --watch` |
|
||||
| Dashboard terminal input → WebSocket → named pipe → agent | PASS — typed "echo hello from dashboard input", agent received it |
|
||||
| Termination via dashboard button | PASS — confirm dialog appears, then session killed |
|
||||
| `ao session kill` removes session from registry | PASS |
|
||||
|
||||
Communication path works for **claude-code agent only**. The orchestrator-worker model would NOT work with codex (ISSUE-001), aider (not installed locally), or potentially cursor.
|
||||
|
||||
---
|
||||
|
||||
## What Passes (Confirmed Working)
|
||||
|
||||
**CLI:**
|
||||
- `ao start` (creates config with `runtime: process` correctly), `ao start --no-dashboard`
|
||||
- `ao spawn` (claude-code only)
|
||||
- `ao status`, `ao status --json`, `ao status --watch`
|
||||
- `ao send <id> <msg>`
|
||||
- `ao session ls`, `ao session attach`, `ao session kill`, `ao session cleanup --dry-run`, `ao session restore` (correctly rejects on non-terminal sessions), `ao session remap`
|
||||
- `ao config-help`
|
||||
- `ao plugin list`, `ao plugin list --installed`, `ao plugin search`, `ao plugin create`
|
||||
- `ao verify --list`
|
||||
- `ao review-check --dry-run`
|
||||
- `ao doctor` (with `AO_BASH_PATH` set)
|
||||
|
||||
**Dashboard:**
|
||||
- Main `/` (kanban board renders, session cards display, terminate button works with confirm dialog)
|
||||
- `/sessions/[id]` (xterm.js terminal connects, live output streams, **terminal input typing works**, fullscreen toggle works)
|
||||
- `/prs` (renders, shows "No open pull requests")
|
||||
- `/orchestrators?project=X` (renders, shows "Start New Orchestrator")
|
||||
- Light/dark mode toggle
|
||||
- Zero JS console errors across all pages
|
||||
|
||||
**Web API:**
|
||||
- `GET /api/sessions`, `GET /api/sessions/[id]`, `GET /api/sessions/patches` (SSE-style)
|
||||
- `POST /api/sessions/[id]/kill` (works)
|
||||
- `POST /api/sessions/[id]/restore` (correctly rejects non-terminal)
|
||||
- `POST /api/sessions/[id]/remap` (works for opencode)
|
||||
- `GET /api/projects`, `GET /api/observability`, `GET /api/runtime/terminal`, `GET /api/backlog`, `GET /api/verify`, `GET /api/orchestrators?project=X`
|
||||
- `GET /api/events` (SSE stream, content-type correct)
|
||||
- `GET /health` on direct-terminal-ws server
|
||||
|
||||
**Activity Detection:**
|
||||
- claude-code → JSONL-based, working correctly (active → ready → idle transitions)
|
||||
- opencode → AO activity JSONL via `recordActivity`, working but slow to bootstrap (~30s lag after spawn)
|
||||
- codex → broken because the agent process dies on launch (ISSUE-001)
|
||||
- aider → not installed locally, expected to fail
|
||||
|
||||
**Process Management:**
|
||||
- `taskkill /T /F /PID` correctly kills agent + PTY host process trees
|
||||
- `process.kill(pid, 0)` correctly detects alive/dead processes
|
||||
- `toClaudeProjectPath` correctly handles Windows paths (`C:\` → `C--`)
|
||||
|
||||
---
|
||||
|
||||
## What Was NOT Tested
|
||||
|
||||
### CLI commands
|
||||
| Command | Reason not tested |
|
||||
|---------|-------------------|
|
||||
| `ao update` | Requires install repo git remote (dev mode incompatible) |
|
||||
| `ao setup openclaw` | Requires OpenClaw gateway running |
|
||||
| `ao plugin install` / `update` / `uninstall` | Would modify config and corrupt test setup |
|
||||
| `ao session claim-pr` | Requires an existing real PR |
|
||||
| `ao spawn --decompose` / `--max-depth` | Subagent decomposition flow not exercised |
|
||||
| `ao spawn --assign-on-github` / `--claim-pr` | Requires real GitHub issue/PR numbers |
|
||||
| `ao spawn <repo-url>` | Only tested with local path arg |
|
||||
|
||||
### Agents
|
||||
| Agent | Reason |
|
||||
|-------|--------|
|
||||
| `cursor` | `cursor` CLI not installed locally (plugin code path exists but untested) |
|
||||
| `aider` | `aider` CLI not installed locally |
|
||||
| `opencode` full flow | Spawn tested; end-to-end work loop not exercised |
|
||||
|
||||
### Flows / Features
|
||||
| Feature | Reason |
|
||||
|---------|--------|
|
||||
| Full PR lifecycle (spawn → code → PR open → CI → review → merge → cleanup) | No PR was actually created — would require letting an agent run |
|
||||
| CI failure reaction (auto-retry on CI fail) | No CI was triggered |
|
||||
| `changes_requested` reaction | No review was ever requested |
|
||||
| `merged-unverified` → `verified` verification flow | Requires a merged PR in the `merged-unverified` state |
|
||||
| Multi-project config (two or more projects in one yaml) | Only tested single-project config |
|
||||
| `workspace: clone` plugin (alternative to `worktree`) | Only tested `worktree` plugin |
|
||||
| `symlinks` config entry | Not configured; would trigger the copy-fallback bug (ISSUE-025) |
|
||||
| `postCreate` hooks | Not configured |
|
||||
| `reactions` config overrides | Default reactions only |
|
||||
| Orchestrator actually spawning a worker via its own `ao spawn` tool (end-to-end autonomous flow) | Would require letting the orchestrator agent run |
|
||||
| Dashboard UI "Send message" button (the React button that POSTs to the broken API endpoint) | Only hit the API directly, not via the React form |
|
||||
| Dashboard with many sessions (20+, stress test) | Only tested up to 4 concurrent |
|
||||
| `terminal-web` plugin (browser-based terminal, alternative to iterm2) | Not exercised |
|
||||
| Dashboard WebSocket reconnection after browser disconnect/reconnect | Not tested |
|
||||
| Session state persistence across graceful `ao stop` + `ao start` | Not tested — tested hard-crash recovery only |
|
||||
| Config file hot-reload on edit | Not tested |
|
||||
| `ao status --watch` over many minutes (long-running activity transitions) | Only ran briefly |
|
||||
| DPR 1.25 / 1.5 (Windows scaling) effect on xterm row clipping | Only tested DPR 1.0 |
|
||||
| Port 3000 already in use by another app | Not tested |
|
||||
| Very long session/issue names (branch name length limits) | Not tested |
|
||||
| `AO_LOG_LEVEL` or other debug env vars | Not tested |
|
||||
|
||||
---
|
||||
|
||||
## Console Health Summary
|
||||
|
||||
Zero JS console errors across all tested dashboard pages.
|
||||
|
||||
---
|
||||
|
||||
## Linux Scope Validation Addendum (2026-04-15)
|
||||
|
||||
Validator: Linux QA retest by Hermes
|
||||
|
||||
Goal: classify each issue with Linux side-by-side results for both runtime paths (`process` and default `tmux`), then decide scope.
|
||||
|
||||
Test harness notes:
|
||||
- Branch tested from worktree: `~/.worktrees/agent-orchestrator-feat-windows-platform-adapter`
|
||||
- Linux `process` run + Linux default `tmux` run were both executed
|
||||
- Browser dashboard/session checks were included in tmux run (no JS console errors in tested flows)
|
||||
|
||||
### Scope verdicts
|
||||
|
||||
| Issue | Linux (process) | Linux (tmux default) | Scope verdict | Comment |
|
||||
|---|---|---|---|---|
|
||||
| ISSUE-001 | Not reproducible | N/A (Windows shell path) | Windows-only | PowerShell parser/quoting issue. |
|
||||
| ISSUE-002 | Not reproducible | N/A (Windows wrapper path) | Windows-only | `.cmd/.ps1` resolution problem is Windows-specific. |
|
||||
| ISSUE-003 | Reproduced (`Runtime plugin 'process' not found`) | Not reproduced (API spawn works) | Cross-platform (runtime-path dependent) | Broken on Linux when runtime is `process`; healthy on tmux. |
|
||||
| ISSUE-004 | Reproduced | Reproduced | Cross-platform | `ao stop` leaves session/worktree residue. |
|
||||
| ISSUE-005 | Not reproducible | N/A (Windows console popup behavior) | Windows-only | Windows process window behavior. |
|
||||
| ISSUE-006 | Reproduced | Reproduced | Cross-platform | `ao open` still says "No sessions to open." |
|
||||
| ISSUE-007 | Not reproducible | N/A (Windows bash-path requirement) | Windows-only | `AO_BASH_PATH` Windows requirement. |
|
||||
| ISSUE-008 | Reproduced | Reproduced | Cross-platform | CLI/API activity mismatch (`exited` vs `null`). |
|
||||
| ISSUE-009 | Not reproduced | Not reproduced | Windows-only (as reported) | Windows file-lock trigger not seen on Linux. |
|
||||
| ISSUE-010 | Reproduced (architectural risk) | Reproduced | Cross-platform | Lifecycle tied to `ao start`; stale/leftover worker behavior observed. |
|
||||
| ISSUE-011 | Reproduced | Reproduced | Cross-platform | `status: working` with `activity: null` + misleading active count. |
|
||||
| ISSUE-012 | Not reproducible | Not reproducible | Windows-only | Windows font/DPI rendering path. |
|
||||
| ISSUE-013 | Not directly re-measured | Not directly re-measured | Cross-platform | CSS/layout logic is OS-agnostic. |
|
||||
| ISSUE-014 | Reproduced | Reproduced | Cross-platform | API rejects spaced issueId; CLI accepts. |
|
||||
| ISSUE-015 | Not applicable | Not applicable | Windows-only | Issue is missing Windows notifier implementation. |
|
||||
| ISSUE-016 | Reproduced | Reproduced | Cross-platform | Noisy notifier warnings despite `notifiers: []`. |
|
||||
| ISSUE-017 | Not applicable | Not applicable | Windows-only | `windowsHide` umbrella is Windows-only. |
|
||||
| ISSUE-018 | Not reproduced | Not reproduced | Windows-only (as reported) | Stale worktree registry case not triggered on Linux. |
|
||||
| ISSUE-019 | Reproduced | Reproduced | Cross-platform | Spawn race/transient bad activity state. |
|
||||
| ISSUE-020 | Not reproduced | Not reproduced | Needs re-check | `/sessions/undefined` not reproduced in Linux runs. |
|
||||
| ISSUE-021 | Reproduced | Reproduced | Cross-platform | Branch persists after `session kill`. |
|
||||
| ISSUE-022 | Not reproduced | Not reproduced | Needs re-check | Dead-PID stale `running.json` not reproduced in Linux runs. |
|
||||
| ISSUE-023 | Reproduced | Reproduced | Cross-platform | Interrupted `batch-spawn` leaves partial state. |
|
||||
| ISSUE-024 | Reproduced | Reproduced | Cross-platform | Malformed YAML reported as "No config found." |
|
||||
| ISSUE-025 | Not reproducible | Not reproducible | Windows-only | Symlink-copy fallback path is Windows-guarded. |
|
||||
| ISSUE-026 | Not reproduced | Not reproduced | Needs re-check | Could not reproduce orchestrator auto-open race on Linux. |
|
||||
| ISSUE-027 | Not applicable | Not applicable | Windows-only (UX emphasis) | Windows lacks standard detach story. |
|
||||
|
||||
## Summary
|
||||
|
||||
The Windows platform adapter is **partially functional**. The core CLI workflow works for the **claude-code agent only**. The dashboard renders correctly and terminal I/O via named pipes works end-to-end. But significant gaps remain:
|
||||
|
||||
1. **Codex agent is unusable on Windows** because of the PowerShell parser error from quoted launch commands (ISSUE-001 + ISSUE-002).
|
||||
2. **Web API spawn/send is broken on Windows** because of plugin registry split (ISSUE-003) — meaning the dashboard's "spawn from issue" buttons silently fail.
|
||||
3. **`ao stop` is incomplete** on Windows — leaves agents and worktrees orphaned (ISSUE-004).
|
||||
4. **`ao open` is dead code** on Windows (ISSUE-006).
|
||||
5. **xterm.js may clip the last ~3 characters of every terminal line on Windows** (ISSUE-012).
|
||||
|
||||
If the goal is "claude-code on Windows", this branch is close. If the goal is the full multi-agent orchestrator experience, several gaps need fixing before users on Windows can self-serve.
|
||||
Loading…
Reference in New Issue