* feat: support multiple concurrent orchestrators with isolated worktrees
- Each orchestrator session gets a numbered ID ({prefix}-orchestrator-N)
and an isolated git worktree, replacing the single shared orchestrator
- reserveNextOrchestratorIdentity atomically reserves the next available
number and detects conflicting project prefix configurations early
- isOrchestratorSession / isOrchestratorSessionName accept optional
allSessionPrefixes for cross-project false-positive prevention
- getProjectPause and resolveGlobalPause track the longest active pause
across all concurrent orchestrators instead of returning the first found
- cleanupWorktreeAndMetadata helper used consistently on all failure paths
including post-launch; system prompt file included in cleanup
- pollBacklog, status.ts, ProjectSidebar, sessions page, global-pause,
project-utils, serialize, and sessions API route all pass
allSessionPrefixes to isOrchestratorSession
- Web sessions/[id]/page.tsx fetches project prefix map and passes it
through prefixByProjectRef to avoid stale closure in fetchProjectSessions
* fix: seed sseAttentionLevels from fresh sessions on full refresh
When scheduleRefresh dispatches a reset action, derive sseAttentionLevels
from the freshly fetched sessions using getAttentionLevel. This clears
phantom entries for removed sessions and seeds correct levels for new
sessions, preventing stale favicon color and attention counts until the
next SSE snapshot.
* fix: merge duplicate @/lib/types imports into single import statement
Combining the separate import type and value import from @/lib/types
into one import to satisfy the no-duplicate-imports lint rule.
Update all usages of project.tracker.plugin and project.scm.plugin
to use optional chaining since the plugin field is now optional
when package or path fields are specified.
Files updated:
- CLI: doctor.ts, status.ts, verify.ts
- Web: issues/route.ts, verify/route.ts, scm-webhooks.ts,
serialize.ts, services.ts
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The --interval flag is only relevant when --watch is enabled.
Previously, passing `--interval 0` without `--watch` threw an error,
whereas `--interval 5` was silently ignored. Now, invalid intervals
are ignored when `--watch` is omitted, ensuring consistent behavior.
Also adds a test case to prevent regression.
Cover the following previously-uncovered lines in status.ts:
- 65-69: maybeClearScreen() isTTY branch
- 255-256: maybeClearScreen() call on watch refresh (refreshing=true)
- 262-266: loadConfig() throw → fallback to tmux session discovery
- 269-271: unknown --project flag → process.exit(1)
- 388, 390-396, 398: tracker block (registry.get, listIssues, error catch)
- 402-405: unverified issues warning banner
- 424-436: setInterval guard skips render when already in progress
Also hoists mockGetPluginRegistry as a vi.fn() so individual tests
can override the plugin registry returned by getPluginRegistry.
In dev mode, `npx next dev` only starts Next.js without the terminal
WebSocket servers. Detect monorepo by checking for `server/` dir and
use `pnpm run dev` which runs both via concurrently.
- Rollback plugin config on setup failure so a half-configured
notifier is never left enabled (non-transactional install fix)
- Use atomic temp+rename for health summary writes to prevent
corruption under concurrent notifications
- Scope credential injection to only when OpenClaw notifier is
configured, avoiding ambient secret exposure to unrelated projects
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Wrap statSync in try/catch in resolveLocalPluginEntrypoint so
permission-denied errors return null instead of crashing
- Add 30s AbortSignal timeout to refreshMarketplaceCatalog fetch
to prevent indefinite hangs on slow networks
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Export isPluginModule, normalizeImportedPluginModule,
resolvePackageExportsEntry, and resolveLocalPluginEntrypoint from
@composio/ao-core and import them in the CLI instead of maintaining
independent copies that have already diverged.
Removes ~70 lines of duplicated code from plugin-marketplace.ts.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
createRequire resolves relative to the compiled dist/lib/ directory
where the JSON file doesn't exist. Use readFileSync with a path
resolved from the package root (../../src/assets/) which works from
both src/lib/ and dist/lib/.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Uses diff-cover to check that newly added or modified lines in PRs
have at least 80% test coverage, without requiring the entire
codebase to meet the threshold.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Import attributes aren't supported with module: "Node16". Switch to
createRequire for the plugin-registry.json import and copy assets
to dist during build.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add `with { type: "json" }` to the plugin-registry.json import to
satisfy Node.js 20's ERR_IMPORT_ASSERTION_TYPE_MISSING requirement.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Node.js v20 requires `with { type: "json" }` for JSON module imports.
This fixes the ERR_IMPORT_ASSERTION_TYPE_MISSING error in the onboarding
integration test.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove unused `resolve` import from plugin.ts
- Use strict equality (`!== null && !== undefined`) instead of `!=` in start.ts
- Attach `cause` to re-thrown errors in plugin install/update rollback
- Fix forbidden `import()` type annotation in plugin test
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Export runSetupAction from setup.ts (fixes TS2459 build error)
- Use rollbackErr as cause in re-thrown errors (preserve-caught-error)
- Remove import() type annotation from test mock (consistent-type-imports)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove unused `resolve` import from node:path
- Add `{ cause: err }` to re-thrown errors (preserve-caught-error rule)
- Fix import() type annotation in plugin test (consistent-type-imports)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add top-level "default" key fallback in CLI's resolvePackageExportsEntry
to match core's plugin-registry.ts (fixes local plugin resolution for
packages using exports: { "default": "./dist/index.js" })
- Remove dead exports: MARKETPLACE_PLUGIN_CATALOG, printPluginList,
getAgentFromRegistry, resolveInstalledPluginSpecifier
- Fix incomplete string escaping in plugin scaffold (backslash/newline)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>