Adds docs/CROSS_PLATFORM.md as the canonical reference for cross-platform
development: the "Golden Rule" (no raw process.platform === "win32" — use
isWindows() and the helpers in platform.ts), a full inventory of every
platform helper (platform.ts, path-equality, windows-pty-registry,
pty-client, sweepWindowsPtyHosts, validateSessionId, resolvePipePath,
setupPathWrapperWorkspace, activity-state helpers, AO_SHELL/AO_BASH_PATH),
the EPERM-vs-ESRCH gotcha when probing processes, PowerShell-vs-bash
differences, IPv6 localhost stalls, agent-plugin specifics, and a 10-point
pre-merge checklist.
Updates internal docs (CLAUDE.md, AGENTS.md, docs/ARCHITECTURE.md,
docs/DEVELOPMENT.md, CONTRIBUTING.md, .github/copilot-instructions.md,
.cursor/BUGBOT.md, packages/core/README.md, packages/plugins/runtime-tmux/
README.md, packages/core/src/prompts/orchestrator.md, ARCHITECTURE.md) to
remove tmux-only / POSIX-only claims, point at the new doc, and (in
docs/ARCHITECTURE.md) describe the Windows runtime architecture: pty-host
helper, named-pipe protocol, registry, sweep, mux WS Windows branch.
Updates user-facing docs (README.md, SETUP.md, docs/CLI.md) to split
prerequisites by OS (no tmux on Windows), reflect that ao doctor and
ao update work on Windows, and note that power.preventIdleSleep is a
no-op on Linux and Windows.
Updates the agent-orchestrator skill (skills/agent-orchestrator/SKILL.md
and references/config.md) so it advertises Windows support, drops tmux
from the required-bins list, and gives the right Windows guidance for the
"spawn tmux ENOENT" error.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: add zsh completion for ao (#1371)
Add a generated zsh completion command and dynamic completion backend so ao can tab-complete projects and session IDs without relying on jq or brittle text parsing. Document standard zsh and Oh My Zsh install paths, and cover the new flow with CLI tests.
* fix(cli): address copilot completion review feedback for PR 1374
* fix completion and harden local workflow parsing
* Update packages/cli/src/lib/completion.ts
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* fix completion regressions and agent-ci review feedback
---------
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* feat(cli): filter terminated sessions from ao session ls / ao status by default
Closes#1310. Terminated sessions (killed/terminated/done/merged/errored/cleanup,
plus lifecycle-driven terminal states) are now hidden from `ao session ls` and
`ao status` by default. A dim footer reports how many were hidden and how to
surface them. Pass `--include-terminated` to restore the full list.
JSON output wraps into `{ data: [...], meta: { hiddenTerminatedCount } }` on
both commands so text and machine-readable views tell the same story. This is a
breaking change for script consumers of `--json`; `--include-terminated` is the
escape hatch.
Orthogonal to `-a, --all` (orchestrator visibility, unchanged). Restore of
terminated sessions by id is unaffected — that path goes through `sm.get`, not
`sm.list`.
Docs (`SETUP.md`, `docs/CLI.md`) updated to match. Tests cover both the legacy
status branch and the canonical lifecycle branch of `isTerminalSession`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(cli): drop unused `lc` param in lifecycle-alive test case
ESLint's no-unused-vars rejects unprefixed unused args. The "alive — should
remain visible" branch of the new lifecycle-driven filter test in
`session.test.ts` took `lc` but never touched it. Switch to `()`. Matches the
equivalent case in `status.test.ts`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(core): preserve pr.state=merged when legacy metadata lacks pr= URL
Review blocker on PR #1340: a metadata file with `status=merged` but no `pr=`
URL was still showing as active in `ao session ls` / `ao status` by default.
Root cause: `synthesizePRState()` in lifecycle-state.ts short-circuited to
`{ state: "none" }` whenever no PR URL was present, ignoring the fact that the
legacy `status` column already encodes terminal truth. Once lifecycle was
synthesized as `session.state="idle"` + `pr.state="none"`, `deriveLegacyStatus`
returned `"idle"` and `isTerminalSession()` (lifecycle branch) returned false.
The new CLI filter then let the session through.
Fix: when legacy `status === "merged"` and no URL is available, synthesize
`pr.state="merged", reason="merged"` with `number: null, url: null`. The
terminal signal survives the flat-metadata → canonical-lifecycle round trip.
Also:
- Export `sessionFromMetadata` from the core barrel. CLI tests and external
consumers need it to round-trip metadata through the canonical lifecycle.
- Update CLI `buildSessionsFromDir` helpers to route through `sessionFromMetadata`
so mocked `sm.list()` reflects production reconstruction (the old shortcut
bypassed synthesis entirely and was the reason the bug slipped past the
original test suite).
- Add regression tests: one at the core level (`parseCanonicalLifecycle` for
merged-without-URL) and one integration-style test per CLI command asserting
the reviewer's exact repro produces the expected filtered output.
- One pre-existing test expectation updated: when metadata has `status=working`
and `pr=<url>`, the reconstructed status is `pr_open`, not `working`. That's
what production `sm.list()` has always returned; the test was previously
hiding behind the reconstruction shortcut.
Changeset bumped to include ao-core (patch).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* test(cli): route review-check helper through sessionFromMetadata
Last remaining test-fidelity shortcut flagged by codex on PR #1340. The
`buildSessionsFromDir` helper in review-check.test.ts fabricated Session
objects by hand, bypassing the canonical lifecycle reconstruction that
production `sm.list()` runs. Doesn't affect review-check's actual behavior
(which reads `session.metadata["pr"]` directly), but aligns this test with
the equivalent helpers in session.test.ts and status.test.ts so future
lifecycle changes don't silently skip this surface.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The README should sell the experience, not list CLI flags. Humans
interact with `ao start` and the dashboard — the CLI is primarily
used by the orchestrator agent internally.
- Move full CLI reference to docs/CLI.md with clear sections:
"commands humans use" vs "commands the orchestrator agent uses"
- Rewrite README to focus on install → start → done flow
- Remove CLI and Maintenance sections from README
- Simplify "How It Works" to describe the system, not CLI commands
- Add CLI Reference to Documentation table
- Collapse source install into <details> to reduce noise
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>