Skip to content

Add worktree-backed workspace lifecycle scripts - #24

Merged
trydis merged 24 commits into
mainfrom
worktree-scripts
Mar 15, 2026
Merged

Add worktree-backed workspace lifecycle scripts#24
trydis merged 24 commits into
mainfrom
worktree-scripts

Conversation

@trydis

@trydis trydis commented Mar 14, 2026

Copy link
Copy Markdown
Owner

Create and reuse per-workspace Git worktrees before launching Shellraiser
sessions, including Ghostty bootstrap for new worktrees. Add a matching
workspace-delete script that removes the Shellraiser workspace, linked
worktree, and branch with safety checks for dirty worktrees and unmerged
branches.

Extend AppleScript support with stable workspace root paths and direct
workspace deletion so scripts can target the correct workspace reliably.
Persist the workspace root directory in the model and add tests covering
backfill, stable root behavior, and scripted deletion.

Summary by CodeRabbit

  • New Features

    • Added a scripted "delete workspace" command and direct delete API.
    • Workspaces now expose and persist a stable root working directory for automation and scripted creation.
    • Workspace creation APIs accept an optional root working directory to stabilize scripted workspaces.
  • CLI / Scripts

    • Enhanced CLI tooling for worktree creation, deletion and bootstrapping with validation, prompts, and robust helpers.
  • Tests

    • Added tests for scripted deletion and root-working-directory behavior, including decoding/backfill scenarios.

@coderabbitai

coderabbitai Bot commented Mar 14, 2026

Copy link
Copy Markdown

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds workspace rootWorkingDirectory throughout models, persistence, workspace creation, and AppleScript snapshots; introduces an AppleScript "delete workspace" command and controller delete(workspace:) path; and adds new shell scripts and common utilities for worktree creation, bootstrap, and deletion workflows.

Changes

Cohort / File(s) Summary
AppleScript commands & scripting dictionary
Sources/Shellraiser/Infrastructure/AppleScript/ShellraiserScriptCommands.swift, Sources/Shellraiser/Infrastructure/AppleScript/ShellraiserScripting.xml
Adds WorkspaceTargetingScriptCommand helpers and DeleteWorkspaceScriptCommand; registers delete workspace and exposes rootWorkingDirectory property in the scripting dictionary.
Scripting controller
Sources/Shellraiser/Infrastructure/AppleScript/ShellraiserScriptingController.swift
Adds delete(workspace: ScriptableWorkspace) -> Bool to drive manager deletion from AppleScript.
Scriptable workspace exposure & manager AppleScript wiring
Sources/Shellraiser/Infrastructure/AppleScript/ScriptableTerminal.swift, Sources/Shellraiser/Infrastructure/AppleScript/WorkspaceManager+AppleScript.swift
Include rootWorkingDirectory in ScriptableWorkspace snapshots, compute/pass stable rootWorkingDirectory during scripted creation, and add deleteScriptWorkspace(id: UUID) -> Bool.
Workspace model & persistence
Sources/Shellraiser/Models/WorkspaceModel.swift
Adds rootWorkingDirectory property, CodingKeys, encoder/decoder (with backfill from pane tree), new initializer, and updated makeDefault behavior.
Workspace creation call-sites
Sources/Shellraiser/Services/Workspaces/WorkspaceCatalogManager.swift, Sources/Shellraiser/Services/Workspaces/WorkspaceManager+WorkspaceLifecycle.swift
Thread optional rootWorkingDirectory: String? through createWorkspace APIs into WorkspaceModel construction.
Workspace Manager lifecycle
Sources/Shellraiser/Infrastructure/AppleScript/WorkspaceManager+AppleScript.swift
Compute a stable rootWorkingDirectory for scripted creation flows and implement deletion primitive deleteScriptWorkspace.
Tests & test support
Tests/ShellraiserTests/AgentTypeAndWorkspaceModelTests.swift, Tests/ShellraiserTests/WorkspaceManagerAppleScriptTests.swift, Tests/ShellraiserTests/WorkspaceTestSupport.swift
Add tests for rootWorkingDirectory defaulting/backfill and scripted deletion; update test helpers to supply/derive rootWorkingDirectory.
Shell scripts: common helpers & workflows
scripts/workspace-shellraiser-common.sh, scripts/workspace-delete.sh, scripts/worktree-create.sh
Large new/modified scripting surface: robust repo/worktree/branch resolution, fail_with_message, prepare/bootstrap worktrees, deletion workflow, and helper utilities.
Script updates to use worktree root
scripts/workspace-claude+lazygit.sh, scripts/workspace-codex+lazygit.sh
Resolve and use worktree_root, branch_name, worktree_status; conditional bootstrap and invocation now use worktree_root.
Misc scripting tooling
scripts/...
New deletion orchestration script and related utilities; improved interactive prompts and slugification helpers.

Sequence Diagram(s)

sequenceDiagram
    actor AppleScriptCaller
    participant DeleteCmd as "DeleteWorkspaceScriptCommand"
    participant Controller as "ShellraiserScriptingController"
    participant Manager as "WorkspaceManager"
    participant Persistence as "Workspace Persistence"

    AppleScriptCaller->>DeleteCmd: performDefaultImplementation()
    DeleteCmd->>DeleteCmd: resolvedWorkspace()
    alt workspace resolved
        DeleteCmd->>Controller: delete(workspace:)
        Controller->>Manager: deleteScriptWorkspace(id:)
        Manager->>Persistence: remove workspace by id
        Persistence-->>Manager: success/failure
        Manager-->>Controller: Bool
        Controller-->>DeleteCmd: Bool
        alt deletion succeeded
            DeleteCmd-->>AppleScriptCaller: return nil (success)
        else deletion failed
            DeleteCmd->>AppleScriptCaller: set scriptErrorNumber & scriptErrorString
        end
    else workspace not resolved
        DeleteCmd-->>AppleScriptCaller: return workspace argument error
    end
Loading
sequenceDiagram
    actor User
    participant DeleteScript as "workspace-delete.sh"
    participant Common as "workspace-shellraiser-common.sh"
    participant Git as "Git"
    participant AppleScript as "Shellraiser AppleScript"

    User->>DeleteScript: invoke delete workflow
    DeleteScript->>Common: resolve repo, workspace, worktree info
    Common->>Git: query worktree & branch status
    Git-->>Common: worktree_root, branch_name, status
    DeleteScript->>Common: confirm_with_user? (if required)
    DeleteScript->>Common: delete_shellraiser_workspace_for_root(worktree_root)
    Common->>AppleScript: invoke DeleteWorkspaceScriptCommand for matching workspace
    AppleScript-->>Common: deletion result
    DeleteScript->>Git: remove worktree / delete branch (maybe force)
    DeleteScript-->>User: print summary of Shellraiser, worktree, branch statuses
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly matches the main change: adding worktree-backed workspace lifecycle scripts across AppleScript, model, and shell script components.
Docstring Coverage ✅ Passed Docstring coverage is 94.83% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch worktree-scripts
📝 Coding Plan
  • Generate coding plan for human review comments

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/workspace-claude`+lazygit.sh:
- Around line 13-16: prepare_workspace_worktree() currently hides whether the
worktree was just created so bootstrap_ghostty_for_worktree() is never called
for new worktrees; modify the launcher to use the status-bearing variant of
prepare_workspace_worktree (or otherwise capture its creation status) and, after
unpacking its return values (worktree_root and branch_name), call
bootstrap_ghostty_for_worktree "$worktree_root" only when the helper indicates
the worktree was newly created, then proceed to
run_shellraiser_workspace_with_commands "$worktree_root" "$workspace_name"
"claude" "lazygit".

In `@scripts/workspace-codex`+lazygit.sh:
- Around line 13-16: prepare_workspace_worktree no longer surfaces whether a
worktree was created, so bootstrap_ghostty_for_worktree never runs for
first-time worktrees; update the call to capture the creation status and invoke
the bootstrap when appropriate. Change the read to IFS=$'\t' read -r
worktree_root branch_name created_status < <(prepare_workspace_worktree
"$repo_root" "$workspace_name"), then after the null-checks add: if [[
"$created_status" == "created" ]]; then bootstrap_ghostty_for_worktree
"$worktree_root"; fi, keeping the subsequent call to
run_shellraiser_workspace_with_commands unchanged (references:
prepare_workspace_worktree, bootstrap_ghostty_for_worktree,
run_shellraiser_workspace_with_commands).

In `@scripts/workspace-delete.sh`:
- Around line 34-35: The guard currently only prevents deleting the primary repo
worktree; add an explicit check that the script is not being run from the
worktree being deleted by comparing the current working directory (PWD or
$(pwd)) to expected_worktree_path and invocation_repo_root and refuse early
using fail_with_message if they match; update the conditional around
expected_worktree_path/main_repo_root/invocation_repo_root (or add a separate
if) so the script exits before attempting to remove the worktree when the
invocation worktree is the target.

In `@scripts/workspace-shellraiser-common.sh`:
- Around line 447-459: The launcher currently always runs the AppleScript 'new
workspace named workspaceName with configuration config', which creates
duplicate Shellraiser workspaces and breaks
delete_shellraiser_workspace_for_root(); change the logic to first check for an
existing workspace whose initial working directory equals workspaceRoot (the
same attribute delete_shellraiser_workspace_for_root() uses) and if found
reuse/select that workspace instead of creating a new one, otherwise proceed to
create; alternatively, if reuse isn't possible implement an early failure with a
clear error when a matching workspace already exists so
delete_shellraiser_workspace_for_root() remains able to target the session.

In `@scripts/worktree-create.sh`:
- Around line 11-26: Replace the fragile use of $0 in the zsh branch that sets
shellraiser_script_path: detect zsh via ZSH_VERSION and ZSH_EVAL_CONTEXT as
already done, and when in zsh set shellraiser_script_path using the zsh-specific
current-file expansion (${(%):-%x}) so that shellraiser_script_sourced is
derived from a reliable sourced-file path; keep the existing bash behavior and
the rest of the script unchanged (symbols: shellraiser_script_path, ZSH_VERSION,
ZSH_EVAL_CONTEXT, shellraiser_script_sourced).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4943a40c-039a-4898-80cf-95d006034288

📥 Commits

Reviewing files that changed from the base of the PR and between 056d016 and 32f9ea5.

📒 Files selected for processing (16)
  • Sources/Shellraiser/Infrastructure/AppleScript/ScriptableTerminal.swift
  • Sources/Shellraiser/Infrastructure/AppleScript/ShellraiserScriptCommands.swift
  • Sources/Shellraiser/Infrastructure/AppleScript/ShellraiserScripting.xml
  • Sources/Shellraiser/Infrastructure/AppleScript/ShellraiserScriptingController.swift
  • Sources/Shellraiser/Infrastructure/AppleScript/WorkspaceManager+AppleScript.swift
  • Sources/Shellraiser/Models/WorkspaceModel.swift
  • Sources/Shellraiser/Services/Workspaces/WorkspaceCatalogManager.swift
  • Sources/Shellraiser/Services/Workspaces/WorkspaceManager+WorkspaceLifecycle.swift
  • Tests/ShellraiserTests/AgentTypeAndWorkspaceModelTests.swift
  • Tests/ShellraiserTests/WorkspaceManagerAppleScriptTests.swift
  • Tests/ShellraiserTests/WorkspaceTestSupport.swift
  • scripts/workspace-claude+lazygit.sh
  • scripts/workspace-codex+lazygit.sh
  • scripts/workspace-delete.sh
  • scripts/workspace-shellraiser-common.sh
  • scripts/worktree-create.sh

Comment thread scripts/workspace-claude+lazygit.sh Outdated
Comment thread scripts/workspace-codex+lazygit.sh Outdated
Comment thread scripts/workspace-delete.sh Outdated
Comment thread scripts/workspace-shellraiser-common.sh Outdated
Comment thread scripts/worktree-create.sh Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
scripts/workspace-shellraiser-common.sh (1)

60-61: ⚠️ Potential issue | 🟠 Major

Replace bash-only read -p usage in the shared prompt helpers.

The scripts/worktree-create.sh script detects and supports both bash and zsh (lines 3-22), then sources scripts/workspace-shellraiser-common.sh unconditionally. However, workspace-shellraiser-common.sh uses read -r -p for prompts, which is bash-specific. In zsh, read -p reads from the coprocess instead of displaying a prompt, causing interactive flows to fail.

Use portable prompt form instead:

💡 Portable prompt form
-        if ! read -r -p "Workspace name: " workspace_name; then
+        printf '%s' "Workspace name: " >&2
+        if ! read -r workspace_name; then
             fail_workspace_name_required
         fi
...
-        if ! read -r -p "Worktree name: " worktree_name; then
+        printf '%s' "Worktree name: " >&2
+        if ! read -r worktree_name; then
             fail_worktree_name_required
         fi
...
-    if ! read -r -p "$prompt_message [y/N] " response; then
+    printf '%s' "$prompt_message [y/N] " >&2
+    if ! read -r response; then
         return 1
     fi

Also applies to: lines 79-80, 312-313

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/workspace-shellraiser-common.sh` around lines 60 - 61, The prompt
uses bash-only read -r -p syntax (e.g., if ! read -r -p "Workspace name: "
workspace_name; then fail_workspace_name_required) which breaks in zsh; replace
each occurrence with the portable form: print the prompt with printf (e.g.,
printf '%s' "Workspace name: ") then call read -r workspace_name and keep the
same error handling (call fail_workspace_name_required on empty/failure). Update
the other similar occurrences (the prompts that set variables referenced in the
same file) the same way so all uses of read -r -p are replaced with printf +
read -r while preserving the existing variable names and failure functions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/workspace-shellraiser-common.sh`:
- Around line 221-225: The code derives worktree_path from the caller-provided
repo_root which makes paths dependent on linked worktrees; instead canonicalize
to the main repo root before computing the worktree path by calling
resolve_main_repo_root (or equivalent) and using that result when invoking
resolve_workspace_worktree_path and any subsequent logic that expects the main
repo root; update the local variable usage so branch_name is still from
slugify_workspace_name but worktree_path is computed with the canonical main
repo root returned by resolve_main_repo_root rather than the original repo_root.

In `@scripts/worktree-create.sh`:
- Around line 11-12: Add a narrow ShellCheck suppression for SC2296 around the
zsh-only expansion so the bash-shebang lint doesn't complain: locate the branch
that sets shellraiser_script_path using the zsh expansion ("${(%):-%x}") in the
if [[ -n "${ZSH_VERSION:-}" ]]; then block and add a single-line or immediately
preceding directive to disable SC2296 (e.g. a comment "# shellcheck
disable=SC2296") only for that line, keeping the suppression minimal and scoped
to that zsh-specific assignment.

---

Outside diff comments:
In `@scripts/workspace-shellraiser-common.sh`:
- Around line 60-61: The prompt uses bash-only read -r -p syntax (e.g., if !
read -r -p "Workspace name: " workspace_name; then fail_workspace_name_required)
which breaks in zsh; replace each occurrence with the portable form: print the
prompt with printf (e.g., printf '%s' "Workspace name: ") then call read -r
workspace_name and keep the same error handling (call
fail_workspace_name_required on empty/failure). Update the other similar
occurrences (the prompts that set variables referenced in the same file) the
same way so all uses of read -r -p are replaced with printf + read -r while
preserving the existing variable names and failure functions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1f1b8cb4-4ceb-4deb-a715-460d9e9def02

📥 Commits

Reviewing files that changed from the base of the PR and between 32f9ea5 and 8665cf7.

📒 Files selected for processing (5)
  • scripts/workspace-claude+lazygit.sh
  • scripts/workspace-codex+lazygit.sh
  • scripts/workspace-delete.sh
  • scripts/workspace-shellraiser-common.sh
  • scripts/worktree-create.sh
🚧 Files skipped from review as they are similar to previous changes (1)
  • scripts/workspace-claude+lazygit.sh

Comment thread scripts/workspace-shellraiser-common.sh Outdated
Comment thread scripts/worktree-create.sh

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/workspace-shellraiser-common.sh`:
- Around line 35-56: In both resolve_main_repo_root and
prepare_workspace_worktree_with_status, add an immediate "return 1" after every
call to fail_with_message so the function exits on error instead of continuing;
specifically update the fail_with_message occurrences inside
resolve_main_repo_root (the blocks that fail to resolve common_git_dir or
canonical repo root) and the five fail_with_message calls inside
prepare_workspace_worktree_with_status so each is followed by return 1 to ensure
the function halts and propagates failure.
- Around line 101-117: slugify_workspace_name currently returns slugs that can
be rejected by Git (e.g., containing ".." or ending with ".lock"); after
producing the initial $slug in slugify_workspace_name, validate it with git
check-ref-format --branch "$slug" and if it fails, sanitize further by
collapsing consecutive dots (replace '\.\.+' with '.'), remove any trailing
".lock" suffix and trim leading/trailing dots or dashes, then re-run git
check-ref-format --branch; if it still fails, call fail_with_message with a
clear error that the workspace name cannot be converted to a Git-safe slug.
Ensure you operate on the same local variables (slug, workspace_name) and
preserve the existing printf '%s\n' "$slug" return behavior when validation
passes.

In `@scripts/worktree-create.sh`:
- Around line 58-64: Summary: command substitutions for resolve_repo_root and
resolve_worktree_name (and the process substitution invoking
prepare_workspace_worktree_with_status) can swallow failures when script is
sourced; add explicit failure propagation. Edit the lines invoking
resolve_repo_root() and resolve_worktree_name() to append "|| return 1" after
each command substitution (the assignments to repo_root and worktree_name) and
also append "|| return 1" after the process substitution that reads from
prepare_workspace_worktree_with_status so that failures from resolve_repo_root,
resolve_worktree_name, or prepare_workspace_worktree_with_status immediately
return (rather than producing empty variables); keep references to the same
variable names repo_root, worktree_name, worktree_root, branch_name,
worktree_status and the existing fail_with_message call.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 79cfe564-b7fe-4fe8-bd1b-c39ab9aed581

📥 Commits

Reviewing files that changed from the base of the PR and between 8665cf7 and 27f3d34.

📒 Files selected for processing (2)
  • scripts/workspace-shellraiser-common.sh
  • scripts/worktree-create.sh

Comment thread scripts/workspace-shellraiser-common.sh
Comment thread scripts/workspace-shellraiser-common.sh
Comment thread scripts/worktree-create.sh Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/workspace-shellraiser-common.sh`:
- Around line 316-341: The function currently calls fail_with_message (which
only returns a non-zero status when the script is sourced) but then continues
execution; update the error paths to stop further work by adding an explicit
return 1 immediately after each fail_with_message invocation: specifically after
the submodule init failure (the block that runs git submodule update --init
--recursive against $worktree_root), after the check that [[ ! -d
"$ghostty_root" ]], after the command -v zig check, and after the zig build
failure block (the zig build invocation against $ghostty_root) so the function
exits early on each detected failure.
- Around line 254-259: The helper results are not checked so failures produce
empty variables and allow continuation; after assigning main_repo_root,
branch_name, and worktree_path (from resolve_main_repo_root,
slugify_workspace_name, resolve_workspace_worktree_path) verify each command
succeeded and abort (log error and exit/return non‑zero) if any is empty or the
helper returned non‑zero, and likewise check the return value of
ensure_local_branch_exists and abort on failure; update the logic around
repo_root/main_repo_root/branch_name/worktree_path and
ensure_local_branch_exists to propagate errors instead of silently continuing.
- Around line 396-407: The safety and error-return logic in the worktree removal
block is incorrect: when worktree_path == main_repo_root you must exit the
function immediately (add a return 1 after the fail_with_message) to prevent
removing the primary repo, and when invoking git -C "$repo_root" worktree remove
"$worktree_path" ensure the function only returns success if the command
actually succeeded (do not unconditionally return 0 after calling
fail_with_message on failure); change the flow around the git worktree remove
call so that on failure you call fail_with_message and return a non-zero status,
and only return 0 when the git command succeeds (referencing the existing
symbols fail_with_message, registered_worktree_exists, worktree_is_clean and the
git -C "$repo_root" worktree remove invocation).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7c4d17d8-b377-4559-bfef-688a27225ae6

📥 Commits

Reviewing files that changed from the base of the PR and between 27f3d34 and e96281e.

📒 Files selected for processing (2)
  • scripts/workspace-shellraiser-common.sh
  • scripts/worktree-create.sh
🚧 Files skipped from review as they are similar to previous changes (1)
  • scripts/worktree-create.sh

Comment thread scripts/workspace-shellraiser-common.sh Outdated
Comment thread scripts/workspace-shellraiser-common.sh
Comment thread scripts/workspace-shellraiser-common.sh

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
scripts/workspace-shellraiser-common.sh (1)

65-82: ⚠️ Potential issue | 🟠 Major

Write prompts to stderr and return error status explicitly.

Lines 71 and 91 write prompts to stdout, which are captured alongside the input value when these helpers are called with $(...) command substitution in scripts/worktree-create.sh and the launcher scripts. Additionally, both helpers fall through to their final printf even after the error handlers, converting a failed validation into exit status 0.

Add >&2 to prompt output and explicit return 1 after each error path:

Suggested fix
-        printf '%s' "Workspace name: "
+        printf '%s' "Workspace name: " >&2
         if ! read -r workspace_name; then
             fail_workspace_name_required
+            return 1
         fi
@@
     if [[ -z "${workspace_name//[[:space:]]/}" ]]; then
         fail_workspace_name_required
+        return 1
     fi
@@
-        printf '%s' "Worktree name: "
+        printf '%s' "Worktree name: " >&2
         if ! read -r worktree_name; then
             fail_worktree_name_required
+            return 1
         fi
@@
     if [[ -z "${worktree_name//[[:space:]]/}" ]]; then
         fail_worktree_name_required
+        return 1
     fi
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/workspace-shellraiser-common.sh` around lines 65 - 82, In
resolve_workspace_name(), change the prompt printf to write to stderr (add >&2)
so the "Workspace name: " prompt isn't captured by command substitution, and
after each error path (the read failure branch that calls
fail_workspace_name_required and the empty-name validation branch) ensure the
function returns a non-zero status (e.g., return 1) so it doesn't fall through
to the final printf; keep the final printf only for the success path. Reference:
resolve_workspace_name, the prompt printf and the two error branches that
currently call fail_workspace_name_required.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@scripts/workspace-shellraiser-common.sh`:
- Around line 315-321: The guard calling fail_with_message when IFS read from
prepare_workspace_worktree_with_status yields empty values doesn't stop
execution, so add an explicit non-zero exit after the failure: after the call to
fail_with_message in the branch that checks [[ -n "$worktree_path" && -n
"$branch_name" && -n "$worktree_status" ]], follow it with a return 1 (or exit 1
if this is a top-level script) so the function that uses
prepare_workspace_worktree_with_status, the read into
worktree_path/branch_name/worktree_status, and the subsequent printf won't
execute on error; ensure the change is made where those symbols appear
(prepare_workspace_worktree_with_status, fail_with_message, printf).
- Around line 492-496: The function currently calls fail_with_message
"Shellraiser workspace deletion failed for '$workspace_root'." but continues
execution and prints an unset $result; update the error branch to immediately
exit the function with a non-zero status by adding a return 1 (or equivalent)
right after the fail_with_message call so the subsequent printf '%s\n' "$result"
is not executed on failure; locate the block that contains fail_with_message and
the printf and insert the return 1 directly after the fail_with_message
invocation.

---

Outside diff comments:
In `@scripts/workspace-shellraiser-common.sh`:
- Around line 65-82: In resolve_workspace_name(), change the prompt printf to
write to stderr (add >&2) so the "Workspace name: " prompt isn't captured by
command substitution, and after each error path (the read failure branch that
calls fail_workspace_name_required and the empty-name validation branch) ensure
the function returns a non-zero status (e.g., return 1) so it doesn't fall
through to the final printf; keep the final printf only for the success path.
Reference: resolve_workspace_name, the prompt printf and the two error branches
that currently call fail_workspace_name_required.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9b90dcb0-5203-4ec8-94e4-2a8fc8792da0

📥 Commits

Reviewing files that changed from the base of the PR and between e96281e and b38ed2c.

📒 Files selected for processing (1)
  • scripts/workspace-shellraiser-common.sh

Comment thread scripts/workspace-shellraiser-common.sh
Comment thread scripts/workspace-shellraiser-common.sh
@trydis
trydis merged commit 254b0ce into main Mar 15, 2026
2 checks passed
@trydis
trydis deleted the worktree-scripts branch March 15, 2026 01:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant