Summary
Upgrading a multi-project machine to the flat-config/global-registry model (0.9.x) has a set of interlocking dead ends that cost us a full evening to escape. Each behavior is individually defensible; together they form a loop with no documented exit.
Environment: ao 0.9.5 (npm, node 22.21.0), macOS, tmux runtime, 3 projects with legacy wrapped configs (projects: key in each repo's agent-orchestrator.yaml), long-running daemon started weeks earlier.
The loop
ao project add <path> → refuses: 'Found old-format config … Run ao start in that project to migrate it'.
ao start in that project (daemon running) → 'AO is already running' — no migration. The migration path only executes on a cold start.
ao stop (from any cwd with a wrapped config, or none) → 'Error: No projects configured. Add a project to agent-orchestrator.yaml' — stop's preflight can't parse the same wrapped config the running daemon is happily using, so you cannot even stop cleanly to get the cold start. Escape is kill <pid> (SIGTERM honored, ~30s delayed).
- After killing: a cold
ao start in project B makes the singleton adopt B and silently drop project A from lifecycle polling — A's ao spawn then fails with 'the running AO instance is not polling project A', and nothing re-adds A short of manually editing the global registry AND flattening A's yaml.
- Extra confusion:
ao spawn's 'not polling project X' message says 'Run ao start X', but ao start <name> errors with 'not registered in the global config' for exactly the projects that need migrating — circular advice.
What actually works (for the docs, until fixed)
Rewrite each repo's yaml FLAT (no projects: wrapper; behavior fields only), write the identity entries (projectId/path/sessionPrefix/defaultBranch) into ~/.agent-orchestrator/config.yaml projects: by hand, then one cold ao start — supervisor then polls from the registry ('polling N project(s)').
Suggested fixes (any subset helps)
ao project add should just DO the migration (flatten + register) instead of refusing — it already knows both formats.
ao stop must not require a parseable project config to stop a daemon (it has running.json).
- A cold
ao start in one project should not drop other registered projects from supervision.
- Make the 'not polling X' error name the real remedy (register + restart), not a command that errors.
- An explicit
ao migrate command would make all of this one step.
🤖 Filed with Claude Code on behalf of @Tonedeath
Summary
Upgrading a multi-project machine to the flat-config/global-registry model (0.9.x) has a set of interlocking dead ends that cost us a full evening to escape. Each behavior is individually defensible; together they form a loop with no documented exit.
Environment: ao 0.9.5 (npm, node 22.21.0), macOS, tmux runtime, 3 projects with legacy wrapped configs (
projects:key in each repo's agent-orchestrator.yaml), long-running daemon started weeks earlier.The loop
ao project add <path>→ refuses: 'Found old-format config … Runao startin that project to migrate it'.ao startin that project (daemon running) → 'AO is already running' — no migration. The migration path only executes on a cold start.ao stop(from any cwd with a wrapped config, or none) → 'Error: No projects configured. Add a project to agent-orchestrator.yaml' — stop's preflight can't parse the same wrapped config the running daemon is happily using, so you cannot even stop cleanly to get the cold start. Escape iskill <pid>(SIGTERM honored, ~30s delayed).ao startin project B makes the singleton adopt B and silently drop project A from lifecycle polling — A'sao spawnthen fails with 'the running AO instance is not polling project A', and nothing re-adds A short of manually editing the global registry AND flattening A's yaml.ao spawn's 'not polling project X' message says 'Runao start X', butao start <name>errors with 'not registered in the global config' for exactly the projects that need migrating — circular advice.What actually works (for the docs, until fixed)
Rewrite each repo's yaml FLAT (no
projects:wrapper; behavior fields only), write the identity entries (projectId/path/sessionPrefix/defaultBranch) into~/.agent-orchestrator/config.yamlprojects:by hand, then one coldao start— supervisor then polls from the registry ('polling N project(s)').Suggested fixes (any subset helps)
ao project addshould just DO the migration (flatten + register) instead of refusing — it already knows both formats.ao stopmust not require a parseable project config to stop a daemon (it has running.json).ao startin one project should not drop other registered projects from supervision.ao migratecommand would make all of this one step.🤖 Filed with Claude Code on behalf of @Tonedeath