fix(cli): keep automated worktree creation in background (#11445)
This commit is contained in:
parent
5e00a30e4e
commit
78b8a37aed
|
|
@ -143,12 +143,12 @@ ORCA worktree create --name task --setup skip --json
|
|||
ORCA worktree create --name task --run-hooks --json
|
||||
```
|
||||
|
||||
- `--agent <id>` launches that agent **in the first terminal** (Orca docs: *"`--agent` launches the selected agent in the first terminal"*); `--prompt <text>` sends initial work to it. Known ids include `claude`, `codex`, `omp`, `pi`, `grok`, and other installed TUI agents.
|
||||
- `--agent <id>` launches that agent **in the first terminal** (Orca docs: _"`--agent` launches the selected agent in the first terminal"_); `--prompt <text>` sends initial work to it. Known ids include `claude`, `codex`, `omp`, `pi`, `grok`, and other installed TUI agents.
|
||||
- **Prefer agent-first create for agent workers.** `orca worktree create --agent <id> --prompt "..."` puts the agent in the worktree's first terminal without adding a separate fallback shell for that worker. Repo setup or default-terminal settings may still add tabs or splits. Without configured default tabs, the bare-create fallback shell plus a later `terminal create --command <agent>` is an anti-pattern for ordinary agent worktrees — use `--agent` instead of “create worktree, then open agent.” Configured default tabs are intentional surfaces; never treat one as disposable without verifying that it is an unused shell.
|
||||
- After create, use exactly one agent handle: `startupTerminal.handle` from the create response when present, or the matching result from `orca terminal list --worktree id:<repoId>::<newWorktreePath> --json` (or `name:<displayName>`) when the response omits it. If a handle later returns `terminal_handle_stale`, re-list it; never dual-send to old and replacement handles.
|
||||
- `--setup run|skip|inherit` controls repo setup hooks. Default is `inherit`, which follows the repo's setup policy.
|
||||
- `--run-hooks` is a legacy alias for `--setup run`; it also reveals/activates the new worktree.
|
||||
- `--agent`, `--activate`, and `--run-hooks` reveal the new worktree. Plain create stays in the background.
|
||||
- `--activate` and `--run-hooks` reveal the new worktree. `--agent` alone stays in the background.
|
||||
- Let Orca choose setup terminal placement from repo settings, including tab vs split behavior. Do not manually create extra setup terminals when `--agent` already owns the first tab.
|
||||
- If an older installed CLI rejects `--agent`, `--prompt`, or `--setup`, create the worktree normally, then run `orca terminal create --worktree <selector> --command "<requested-agent>"` and `orca terminal send` if a prompt is needed. This can leave a fallback shell when no default tabs are configured; close it only after confirming it is unused.
|
||||
- `worktree create` creates a new checkout. For a fresh agent in the **current** checkout (no new worktree), use `orca terminal create --worktree active --command "codex" --json` — that path does not create a second worktree shell.
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -237,8 +237,7 @@ export const WORKTREE_HANDLERS: Record<string, CommandHandler> = {
|
|||
...linearIssueLink,
|
||||
comment: getOptionalStringFlag(flags, 'comment'),
|
||||
runHooks: flags.get('run-hooks') === true,
|
||||
activate:
|
||||
flags.get('activate') === true || flags.get('run-hooks') === true || Boolean(startupAgent),
|
||||
activate: flags.get('activate') === true || flags.get('run-hooks') === true,
|
||||
...(setupDecision ? { setupDecision } : {}),
|
||||
parentWorktree: explicitParentWorktree,
|
||||
...(explicitParentWorkspace ? { parentWorkspace: explicitParentWorkspace } : {}),
|
||||
|
|
|
|||
|
|
@ -2826,7 +2826,7 @@ describe('orca cli worktree awareness', () => {
|
|||
})
|
||||
})
|
||||
|
||||
it('passes agent prompt and setup policy through worktree.create', async () => {
|
||||
it('starts an agent worktree in the background unless activation is explicit', async () => {
|
||||
queueFixtures(
|
||||
callMock,
|
||||
worktreeListFixture([buildWorktree('/tmp/repo', 'main', 'abc', 'repo-1')]),
|
||||
|
|
@ -2864,7 +2864,7 @@ describe('orca cli worktree awareness', () => {
|
|||
linkedIssue: undefined,
|
||||
comment: undefined,
|
||||
runHooks: false,
|
||||
activate: true,
|
||||
activate: false,
|
||||
setupDecision: 'run',
|
||||
parentWorktree: undefined,
|
||||
cwdParentWorktree: 'id:repo-1::/tmp/repo',
|
||||
|
|
@ -2876,7 +2876,7 @@ describe('orca cli worktree awareness', () => {
|
|||
})
|
||||
})
|
||||
|
||||
it('infers the repo from the current worktree on worktree.create', async () => {
|
||||
it('infers the repo and honors explicit activation on worktree.create', async () => {
|
||||
queueFixtures(
|
||||
callMock,
|
||||
worktreeListFixture([buildWorktree('/tmp/repo', 'main', 'abc', 'repo-1')]),
|
||||
|
|
@ -2898,6 +2898,7 @@ describe('orca cli worktree awareness', () => {
|
|||
'codex',
|
||||
'--prompt',
|
||||
'hi',
|
||||
'--activate',
|
||||
'--json'
|
||||
],
|
||||
'/tmp/repo/src'
|
||||
|
|
|
|||
|
|
@ -211,20 +211,19 @@ describe('orchestration federation', () => {
|
|||
remote_worktree_id: 'repo::windows-worktree',
|
||||
remote_terminal_handle: 'term_windows_worker'
|
||||
})
|
||||
expect(workerDb.getRemoteDispatchAttachment(dispatch.id)).toMatchObject({
|
||||
const attachment = workerDb.getRemoteDispatchAttachment(dispatch.id)
|
||||
expect(attachment).toMatchObject({
|
||||
task_id: task.id,
|
||||
protocol_version: 2,
|
||||
state: 'ready',
|
||||
worktree_id: 'repo::windows-worktree',
|
||||
terminal_handle: 'term_windows_worker'
|
||||
})
|
||||
expect(JSON.parse(workerDb.getRemoteDispatchAttachment(dispatch.id)?.effects ?? '[]')).toEqual(
|
||||
expect.arrayContaining([
|
||||
expect.objectContaining({ kind: 'dispatch_input', state: 'accepted' })
|
||||
])
|
||||
)
|
||||
const fx = JSON.parse(attachment?.effects ?? '[]') as { kind?: string; state?: string }[]
|
||||
expect(fx.some((x) => x.kind === 'dispatch_input' && x.state === 'accepted')).toBe(true)
|
||||
expect(workerDb.listTasks()).toHaveLength(0)
|
||||
expect(vi.mocked(workerRuntime.createManagedWorktree).mock.calls[0]?.[0].activate).toBe(false)
|
||||
const create = vi.mocked(workerRuntime.createManagedWorktree).mock.calls[0]?.[0]
|
||||
expect([create.activate, create.runHooks]).toEqual([false, false])
|
||||
expect(workerRuntime.sendTerminalAgentPrompt).toHaveBeenCalledWith(
|
||||
'term_windows_worker',
|
||||
expect.stringContaining(`Your task ID is: ${task.id}`)
|
||||
|
|
|
|||
|
|
@ -119,7 +119,8 @@ export const ORCHESTRATION_FEDERATION_ATTACH_METHODS: RpcMethod[] = [
|
|||
baseBranch: params.baseBranch,
|
||||
displayName: params.displayName,
|
||||
comment: params.comment,
|
||||
runHooks: setupDecision === 'run',
|
||||
// setupDecision runs setup without the legacy runHooks activation side effect.
|
||||
runHooks: false,
|
||||
setupDecision,
|
||||
awaitTerminalProvisioning: true,
|
||||
observeSetupCompletion: true,
|
||||
|
|
|
|||
|
|
@ -125,7 +125,8 @@ export async function createWorkerWorktree(args: {
|
|||
baseBranch: params.baseBranch,
|
||||
displayName: params.displayName,
|
||||
comment: params.comment,
|
||||
runHooks: setupDecision === 'run',
|
||||
// setupDecision runs setup without the legacy runHooks activation side effect.
|
||||
runHooks: false,
|
||||
setupDecision,
|
||||
awaitTerminalProvisioning: true,
|
||||
observeSetupCompletion: true,
|
||||
|
|
|
|||
|
|
@ -256,7 +256,7 @@ describe('orchestration new-worktree workers', () => {
|
|||
const { result } = await startWorker({ setup })
|
||||
|
||||
expect(runtime.createManagedWorktree).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ setupDecision: setup, runHooks: setup === 'run' })
|
||||
expect.objectContaining({ setupDecision: setup, runHooks: false, activate: false })
|
||||
)
|
||||
expect(result).toMatchObject({
|
||||
state: 'ready',
|
||||
|
|
|
|||
|
|
@ -2458,9 +2458,10 @@ describe('orchestration RPC methods', () => {
|
|||
expect.objectContaining({
|
||||
repoSelector: 'repo',
|
||||
name: 'child-worker',
|
||||
runHooks: true,
|
||||
runHooks: false,
|
||||
setupDecision: 'run',
|
||||
startupAgent: 'codex',
|
||||
activate: false,
|
||||
lineage: expect.objectContaining({ parentWorktree: 'repo::parent', noParent: false })
|
||||
})
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in New Issue