[codex] Propose workspace open agent context#1054
Conversation
|
Caution Review failedPull request was closed or merged during review Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (7)
📝 WalkthroughWalkthroughAdds a new workspace-open capability: CLI surface and command, per-workspace preferred-opener state, opener discovery/validation, open-surface sync (AGENTS.md, .code-workspace, .gitignore), launcher construction/spawn, and tests covering interactive and non‑interactive flows. ChangesWorkspace Open Feature
Sequence DiagramsequenceDiagram
participant User as User
participant CLI as CLI Handler
participant Select as Workspace Selection
participant State as State Reader
participant Sync as Open Surface
participant Opener as Opener Resolver
participant Launcher as Process Launcher
participant Process as Editor/Agent
User->>CLI: runs `openspec workspace open [name] --agent/--editor`
CLI->>Select: selectWorkspaceForCommand(...)
Select-->>CLI: SelectedWorkspace
CLI->>State: readWorkspaceOpenState(selected)
State->>Sync: resolveWorkspaceOpenLinks(sharedState, localState)
Sync-->>State: { links, skipped }
State-->>CLI: WorkspaceOpenState (incl. codeWorkspacePath)
CLI->>Opener: resolveWorkspaceOpenOpener(localState, options)
Opener-->>CLI: PreferredOpener (stored / explicit / prompt result)
CLI->>CLI: buildWorkspaceOpenCommandForState(opener, state)
CLI->>Opener: assertWorkspaceOpenerAvailable(opener, codeWorkspacePath)
CLI->>Launcher: launchWorkspaceOpenCommand(command)
Launcher->>Process: spawn(executable, args, {cwd, shell})
Process-->>Launcher: exit / error
Launcher-->>CLI: success / WorkspaceCliError
CLI-->>User: status or error
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
e7e7458 to
159b38f
Compare
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@openspec/changes/workspace-open-agent-context/specs/workspace-foundation/spec.md`:
- Around line 11-19: Update the two scenarios so they explicitly mark the
commands as non-interactive by adding the --no-interactive flag; change the
example commands 'openspec workspace setup --opener codex' to 'openspec
workspace setup --opener codex --no-interactive' and 'openspec workspace setup'
to 'openspec workspace setup --no-interactive', and ensure the scenario text
still refers to “non-interactive” flow to avoid ambiguity between interactive
defaults and explicit non-interactive behavior.
In `@openspec/changes/workspace-open-agent-context/specs/workspace-open/spec.md`:
- Around line 76-109: The spec lacks an explicit rule for the conflicting flags
`--agent` and `--editor` on the command `openspec workspace open`; add a short
requirement and scenario under "Opener Resolution" that declares this
combination invalid and mandates a fail-fast behavior with a clear conflict
error (e.g. "Cannot specify both --agent and --editor; choose one"), update any
resolution precedence bullets to reference this conflict, and include a test
scenario describing the GIVEN (both flags present), WHEN (user runs the
command), and THEN (command fails immediately with the specified error message).
In `@openspec/changes/workspace-open-agent-context/tasks.md`:
- Line 83: Update the checklist command to the documented runnable form so
contributors can run it without a global install: replace the checklist entry
string "openspec validate workspace-open-agent-context --strict" with "node
bin/openspec.js validate workspace-open-agent-context --strict" (or include both
variants) in the tasks.md checklist so the validation step matches the PR
objective and is reproducible.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: d4a9eb17-a905-4145-9c7a-e7fbf492266d
📒 Files selected for processing (5)
openspec/changes/workspace-open-agent-context/design.mdopenspec/changes/workspace-open-agent-context/proposal.mdopenspec/changes/workspace-open-agent-context/specs/workspace-foundation/spec.mdopenspec/changes/workspace-open-agent-context/specs/workspace-open/spec.mdopenspec/changes/workspace-open-agent-context/tasks.md
There was a problem hiding this comment.
Actionable comments posted: 4
♻️ Duplicate comments (1)
openspec/changes/workspace-open-agent-context/specs/workspace-open/spec.md (1)
76-109:⚠️ Potential issue | 🟠 Major | ⚡ Quick winStill missing a scenario for conflicting
--agentand--editoroverrides.The
Opener Resolutionrequirement enumerates each override individually but does not specify behavior when both--agent <tool>and--editorare passed in the same invocation. Without an explicit rule, the implementation contract is ambiguous (which override wins, is it a fail-fast, etc.). Add a scenario codifying fail-fast behavior so tests/implementation can rely on it.📝 Suggested addition
#### Scenario: Failing when no opener is stored in non-interactive mode - **GIVEN** the workspace has no stored preferred opener - **AND** the terminal is non-interactive - **WHEN** the user runs `openspec workspace open` using default opener resolution - **THEN** OpenSpec SHALL fail with a clear message - **AND** it SHALL ask the user to pass `--agent <tool>` or `--editor` + +#### Scenario: Conflicting opener overrides +- **WHEN** the user runs `openspec workspace open --agent <tool> --editor` +- **THEN** OpenSpec SHALL fail with a clear conflict error naming both flags +- **AND** it SHALL not launch any opener🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@openspec/changes/workspace-open-agent-context/specs/workspace-open/spec.md` around lines 76 - 109, Add a new Scenario under "Requirement: Opener Resolution" that covers conflicting overrides for `openspec workspace open` when both `--agent <tool>` and `--editor` are provided; specify that OpenSpec SHALL fail fast with a clear error message explaining the conflict and instructing the user to pass only one of `--agent <tool>` or `--editor`, and that no stored preference is changed. Reference the command and flags (`openspec workspace open`, `--agent`, `--editor`) so tests and implementations know to treat simultaneous `--agent` and `--editor` as an error case.
🧹 Nitpick comments (1)
src/core/completions/command-registry.ts (1)
177-181: ⚡ Quick winProvide
values:arrays for enum-like flags to improve shell completions.
--opener(setup) and--agent(open) accept a fixed set of identifiers that the description spells out, but the registry entries omitvalues:. Other enum-like flags in this file (--type,--scope) declarevalues:so completion scripts can suggest them. Add the same here for parity and a better UX in zsh/bash/fish completions.♻️ Suggested change
{ name: 'opener', description: 'Preferred opener: codex, claude, github-copilot, or editor', takesValue: true, + values: ['codex', 'claude', 'github-copilot', 'editor'], },{ name: 'agent', description: 'Use an agent for this session: codex, claude, or github-copilot', takesValue: true, + values: ['codex', 'claude', 'github-copilot'], },Also applies to: 277-281
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/core/completions/command-registry.ts` around lines 177 - 181, Add explicit values arrays for the enum-like flags so shell completions can suggest options: update the command registry entries for the flags named 'opener' (in the setup command) and 'agent' (in the open command) to include a values: array with the allowed identifiers (e.g., "codex", "claude", "github-copilot", "editor"); keep the existing name, description, and takesValue: true properties and only add the values field to both flag objects to match how '--type' and '--scope' are declared.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/commands/workspace.ts`:
- Around line 434-436: The interactive branch currently calls
promptPreferredOpener without filtering out unavailable launchers, which can
lead to a dead-end prompt; update the branch that checks
resolveNoInteractive/options and isInteractive(options) to first call
listWorkspaceOpenerChoices() and filter for available choices (the same
availability criteria used by assertWorkspaceOpenerAvailable()), then if the
filtered list is empty throw a targeted error (e.g., a clear "no available
openers" error) instead of prompting, otherwise call promptPreferredOpener with
only the available choices so the prompt never offers unlaunchable options.
In `@src/commands/workspace/open.ts`:
- Around line 115-124: The returned launch command uses the stale
state.codeWorkspacePath even after resolveWorkspaceOpenLinks recomputes
openLinks.links/skipped, so regenerate the maintained .code-workspace from
openLinks.links before returning; specifically, after calling
resolveWorkspaceOpenLinks and before buildWorkspaceOpenLaunchCommand, write an
updated workspace file (based on openLinks.links.map(link => link.path)) to
state.codeWorkspacePath (or the maintained workspace writer function) so the
editor/GitHub Copilot open uses the refreshed folders and skipped entries are
reflected.
In `@src/commands/workspace/operations.ts`:
- Around line 636-639: The code writes shared/local state files before calling
syncWorkspaceOpenSurface(), which creates a new failure point that can leave
workspace files stale; change the order so
syncWorkspaceOpenSurface(selected.root, updatedSharedState, updatedLocalState)
is invoked and completes successfully before calling
writeWorkspaceSharedState(selected.root, updatedSharedState),
writeWorkspaceLocalState(selected.root, updatedLocalState), and then
recordSelectedWorkspaceAfterMutation(selected); apply the same reorder to the
other occurrence around the functions at lines 674-676 so the open-surface
refresh succeeds before persisting the link state.
In `@test/commands/workspace-open.test.ts`:
- Around line 74-111: The spawn call inside launchWorkspaceOpenCommand does not
pass a shell option, which breaks execution of Windows .cmd wrappers; update the
call that invokes spawnCommand (the spot that creates the child process in
launchWorkspaceOpenCommand) to include shell: true in the options object along
with cwd and stdio (i.e., pass { cwd: command.cwd, stdio: 'inherit', shell: true
}) so Windows PATH-wrapped executables like code/codex run correctly.
---
Duplicate comments:
In `@openspec/changes/workspace-open-agent-context/specs/workspace-open/spec.md`:
- Around line 76-109: Add a new Scenario under "Requirement: Opener Resolution"
that covers conflicting overrides for `openspec workspace open` when both
`--agent <tool>` and `--editor` are provided; specify that OpenSpec SHALL fail
fast with a clear error message explaining the conflict and instructing the user
to pass only one of `--agent <tool>` or `--editor`, and that no stored
preference is changed. Reference the command and flags (`openspec workspace
open`, `--agent`, `--editor`) so tests and implementations know to treat
simultaneous `--agent` and `--editor` as an error case.
---
Nitpick comments:
In `@src/core/completions/command-registry.ts`:
- Around line 177-181: Add explicit values arrays for the enum-like flags so
shell completions can suggest options: update the command registry entries for
the flags named 'opener' (in the setup command) and 'agent' (in the open
command) to include a values: array with the allowed identifiers (e.g., "codex",
"claude", "github-copilot", "editor"); keep the existing name, description, and
takesValue: true properties and only add the values field to both flag objects
to match how '--type' and '--scope' are declared.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: a99a0674-fb14-4d58-8ea0-4c3b24ef43c9
📒 Files selected for processing (21)
docs/cli.mddocs/concepts.mdopenspec/changes/workspace-open-agent-context/design.mdopenspec/changes/workspace-open-agent-context/proposal.mdopenspec/changes/workspace-open-agent-context/specs/workspace-foundation/spec.mdopenspec/changes/workspace-open-agent-context/specs/workspace-open/spec.mdopenspec/changes/workspace-open-agent-context/tasks.mdsrc/commands/workspace.tssrc/commands/workspace/open.tssrc/commands/workspace/operations.tssrc/commands/workspace/selection.tssrc/commands/workspace/types.tssrc/core/completions/command-registry.tssrc/core/workspace/foundation.tssrc/core/workspace/index.tssrc/core/workspace/open-surface.tssrc/core/workspace/openers.tstest/commands/workspace-open.test.tstest/commands/workspace.interactive.test.tstest/commands/workspace.test.tstest/core/workspace/foundation.test.ts
| await writeWorkspaceSharedState(selected.root, updatedSharedState); | ||
| await writeWorkspaceLocalState(selected.root, updatedLocalState); | ||
| await syncWorkspaceOpenSurface(selected.root, updatedSharedState, updatedLocalState); | ||
| await recordSelectedWorkspaceAfterMutation(selected); |
There was a problem hiding this comment.
Avoid committing link state before the open-surface refresh succeeds.
syncWorkspaceOpenSurface() now adds another failure point after the shared/local state files are already written. If that refresh throws, the command returns an error even though the link change has already been persisted, which leaves AGENTS.md / <workspace>.code-workspace stale and the workspace partially updated.
Also applies to: 674-676
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/commands/workspace/operations.ts` around lines 636 - 639, The code writes
shared/local state files before calling syncWorkspaceOpenSurface(), which
creates a new failure point that can leave workspace files stale; change the
order so syncWorkspaceOpenSurface(selected.root, updatedSharedState,
updatedLocalState) is invoked and completes successfully before calling
writeWorkspaceSharedState(selected.root, updatedSharedState),
writeWorkspaceLocalState(selected.root, updatedLocalState), and then
recordSelectedWorkspaceAfterMutation(selected); apply the same reorder to the
other occurrence around the functions at lines 674-676 so the open-surface
refresh succeeds before persisting the link state.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/commands/workspace/open.ts`:
- Around line 138-175: The current spawn logic uses shell: platform === 'win32'
which concatenates args on Windows and causes argument-splitting (affecting
command.args and command.executable); change to use cross-spawn (import spawn
from 'cross-spawn') and invoke spawn(command.executable, command.args, { cwd:
command.cwd, stdio: 'inherit', shell: false }) so cross-spawn resolves Windows
shims and preserves args, and only set shell: true conditionally when the
resolved executable name endsWith('.cmd') || endsWith('.bat') (so .cmd/.bat keep
shell while normal .exe/.ps1 calls do not); keep existing error handling
(child.on('error', ...) and child.on('close', ...)) and still throw
WorkspaceCliError with asErrorMessage on failure.
In `@src/core/workspace/open-surface.ts`:
- Around line 95-99: The workspace root entry in the folders array is emitting a
synthetic name; update the root folder object in open-surface.ts (the folders
constant) to omit the name property and only emit { path: '.' } for the
coordination root so the workspace JSON conforms to the new spec and VS Code
shows the correct label.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: e1d87a21-2b4f-40eb-8ea0-a2f6bd18522e
📒 Files selected for processing (12)
docs/cli.mddocs/concepts.mdopenspec/changes/workspace-open-agent-context/specs/workspace-foundation/spec.mdopenspec/changes/workspace-open-agent-context/specs/workspace-open/spec.mdopenspec/changes/workspace-open-agent-context/tasks.mdsrc/commands/workspace.tssrc/commands/workspace/open.tssrc/core/completions/command-registry.tssrc/core/workspace/open-surface.tstest/commands/workspace-open.test.tstest/commands/workspace.interactive.test.tstest/commands/workspace.test.ts
…agent-context # Conflicts: # test/commands/workspace.test.ts
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@test/core/workspace/foundation.test.ts`:
- Around line 462-473: The test calls buildWorkspaceCodeWorkspaceContent with
only links but the exported signature in open-surface.ts is
buildWorkspaceCodeWorkspaceContent(workspaceName, workspaceRoot, links); update
the test to pass the missing workspaceName and workspaceRoot parameters (e.g., a
stable name and root string) before the links array when invoking
buildWorkspaceCodeWorkspaceContent in foundation.test.ts so the call matches the
implementation's parameters.
- Around line 496-497: Replace the blanket '*.code-workspace' ignore in the test
setup/assertions with a scoped entry for the maintained workspace file (e.g.
`${workspaceName}.code-workspace`) by updating the fs.writeFileSync call and any
assertions that expect the synced .gitignore; specifically change places that
write or assert '*.code-workspace' (see uses of fs.writeFileSync and
workspaceRoot in this test and the similar block at 533-535) to instead assert
the scoped `<workspaceName>.code-workspace` entry, and add an assertion that if
the repo originally contained the wildcard entry OpenSpec either removes or
rewrites it to the scoped entry during sync (use sharedState or the test helper
that performs the sync to verify the rewrite/removal).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: e9235e98-c27a-4ae4-9f09-f8056e155be7
📒 Files selected for processing (9)
openspec/changes/archive/2026-05-06-workspace-open-agent-context/design.mdopenspec/changes/archive/2026-05-06-workspace-open-agent-context/proposal.mdopenspec/changes/archive/2026-05-06-workspace-open-agent-context/specs/workspace-foundation/spec.mdopenspec/changes/archive/2026-05-06-workspace-open-agent-context/specs/workspace-open/spec.mdopenspec/changes/archive/2026-05-06-workspace-open-agent-context/tasks.mdopenspec/specs/workspace-foundation/spec.mdopenspec/specs/workspace-open/spec.mdsrc/core/workspace/open-surface.tstest/core/workspace/foundation.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- src/core/workspace/open-surface.ts
| it('builds VS Code workspace content with stable root and linked paths', () => { | ||
| const content = buildWorkspaceCodeWorkspaceContent([ | ||
| { | ||
| name: 'api', | ||
| path: '/repos/api', | ||
| }, | ||
| { | ||
| name: 'windows', | ||
| path: 'D:\\repos\\web', | ||
| }, | ||
| ]); | ||
| const payload = JSON.parse(content); |
There was a problem hiding this comment.
Match the new buildWorkspaceCodeWorkspaceContent signature.
Line 463 calls this helper with only the links array, but src/core/workspace/open-surface.ts:92-107 exports it as buildWorkspaceCodeWorkspaceContent(workspaceName, workspaceRoot, links). As written, this test will not type-check against the implementation.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@test/core/workspace/foundation.test.ts` around lines 462 - 473, The test
calls buildWorkspaceCodeWorkspaceContent with only links but the exported
signature in open-surface.ts is
buildWorkspaceCodeWorkspaceContent(workspaceName, workspaceRoot, links); update
the test to pass the missing workspaceName and workspaceRoot parameters (e.g., a
stable name and root string) before the links array when invoking
buildWorkspaceCodeWorkspaceContent in foundation.test.ts so the call matches the
implementation's parameters.
| fs.writeFileSync(path.join(workspaceRoot, '.gitignore'), '*.code-workspace\n'); | ||
| const sharedState = { |
There was a problem hiding this comment.
Don’t lock in the old blanket *.code-workspace ignore.
This expectation preserves *.code-workspace in the synced .gitignore, which contradicts the new requirement that only the maintained <workspace-name>.code-workspace entry is ignored so user-authored workspace files stay trackable. Please assert the scoped entry instead, and if OpenSpec owns the wildcard line, verify sync removes or rewrites it.
Also applies to: 533-535
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@test/core/workspace/foundation.test.ts` around lines 496 - 497, Replace the
blanket '*.code-workspace' ignore in the test setup/assertions with a scoped
entry for the maintained workspace file (e.g. `${workspaceName}.code-workspace`)
by updating the fs.writeFileSync call and any assertions that expect the synced
.gitignore; specifically change places that write or assert '*.code-workspace'
(see uses of fs.writeFileSync and workspaceRoot in this test and the similar
block at 533-535) to instead assert the scoped `<workspaceName>.code-workspace`
entry, and add an assertion that if the repo originally contained the wildcard
entry OpenSpec either removes or rewrites it to the scoped entry during sync
(use sharedState or the test helper that performs the sync to verify the
rewrite/removal).
alfred-openspec
left a comment
There was a problem hiding this comment.
Reviewed the diff and validated locally. CI is green.
Summary
workspace-open-agent-contextOpenSpec proposal artifacts.workspace-opencapability for opening a workspace through a preferred agent or VS Code editor.Validation
node bin/openspec.js validate workspace-open-agent-context --strictSummary by CodeRabbit
New Features
workspace opento launch a workspace in a preferred agent or VS Code; supports agent/editor overrides, interactive picker, and auto-select when only one workspace is known.--openeroption forworkspace setupand interactive opener selection to persist a preferred opener.Documentation
Tests