Skip to content

Add shareable orchestration templates (cmux orchestration): package format, store, trust-gated runs - #8032

Closed
austinywang wants to merge 13 commits into
mainfrom
feat-orchestration-templates
Closed

austinywang wants to merge 13 commits into
mainfrom
feat-orchestration-templates

Conversation

@austinywang

@austinywang austinywang commented Jul 14, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Adds the shareable orchestration template layer: a packaged, versioned format that captures a whole way of running fleets of coding agents (prompts, workspace shapes, agent commands, provisioning style), so one user can share their setup as a git repo and another can install and run it. This is the template/packaging layer described in the Fleet plan (related: #7361); it is deliberately independent of the fleet engine skeleton in #7374 (no dependency on Packages/macOS/CmuxFleet, no file overlap beyond the shared CI package list / workspace registration lines) and exposes clean seams (OrchestrationRunPlan, per-task agent command + prompt + cwd + caps) the engine can consume later.

What's included

Packages/macOS/CmuxOrchestration (new pure SwiftPM package, Swift 6, dependency-free, 75 tests):

  • orchestration.json manifest model with versioned schemaVersion, actionable parse errors, and unknown-key detection.
  • Parameters (install-time interview: string/int/bool/path/choice/agent, defaults, typed coercion). Resolved values live per-install in ~/.cmuxterm/orchestrations/<name>/install.json, never inside the template.
  • Substrates: worktree (git worktree per task), clone-pool (v1: fresh clone per task), script (template-supplied provision script — the SSH/cloud escape hatch).
  • Validator: referenced-file existence, path traversal rejection, placeholder resolvability, script executable bits, duplicate ids, secret-material scan (error severity), layout JSON parse.
  • Store: install/list/info/remove/update over seam protocols (OrchestrationFileSystem, OrchestrationGitClient, OrchestrationProcessRunner) with in-memory fakes — the CmuxControlSocket testing shape. Update keeps parameter answers, drops stale keys, and resets trust confirmation.
  • {{placeholder}} rendering (strict: unknown placeholders fail at validate/plan time), shell quoting, run planner (branch/directory naming, prompt file, CMUX_ORCHESTRATION* env, minCmuxVersion gate), provisioner, init scaffold.

orchestration.* v2 socket domain (CmuxControlSocket + app):

  • orchestration.list / orchestration.info / orchestration.plan / orchestration.run, following the coordinator seam pattern (ControlOrchestrationContext + fakes + 8 coordinator tests).
  • App side: TerminalController+ControlOrchestrationContext plans via the package and enforces the trust gate; OrchestrationRunController provisions sequentially off the main actor, then creates workspaces unfocused, grouped in the sidebar, with the agent command delivered as typed terminal input (initialTerminalInput, or the layout's setup command when the template ships a layout). Completion/failure lands as a cmux notification (strings localized en/ja).

cmux orchestration CLI namespace (CLI/CMUXCLI+Orchestration*.swift):

  • init, validate, install, list, info, remove, update, configure run locally (no socket needed) with an interactive parameter interview; plan/run go through the socket. run prints the full plan (workspaces, agent commands, scripts, substrate) before executing.
  • CLI/cmux.swift may not grow (900-line hard cap), so the option-parsing helpers were extracted verbatim into CMUXCLI+OptionParsing.swift; net −60 lines. No budget TSV changes.

Trust model (enforced in code):

  • Install/update never execute template code — files are cloned/copied and parsed only, and invalid templates never reach the store.
  • The first run of a template (and every run after an update) requires explicit confirmation of the scripts, agent commands, and substrate; --yes skips the prompt; the socket method errors with needs_confirmation until confirmed.
  • Validation rejects secret material in templates; agent commands run with the user's own auth.
  • All run-path workspace creation is focus-false.

Example + docs: Examples/Orchestrations/issue-fleet is a real worktree-substrate template that package tests validate and plan on every CI run (the format's living fixture); docs/orchestrations.md documents the format, placeholders, trust model, CLI, socket API, and storage; docs/cli-contract.md gains the namespace row and a no-socket help probe.

Scope cuts (explicit)

  • Steps execution: manifests support the linear steps chain (parsed, validated, tested), but v1 run executes the first step only and says so in the plan notes. Full chain execution + success-condition supervision (pr-exists, hook-event, exit-code) belongs to the fleet engine.
  • Clone-pool reuse/reset: v1 provisions a fresh clone per task; pool reuse belongs to the engine.
  • instructions/ fragments: validated and documented, not yet auto-applied to workspaces.
  • Interview UX: plain readLine prompts (TTY only); non-TTY installs print the configure command instead.

Testing

  • swift test — CmuxOrchestration: 75 tests, 11 suites, all passing (manifest, validator, store, planner, provisioner, placeholders, scaffold, example fixture).
  • swift test — CmuxControlSocket: 234 tests passing including the new orchestration coordinator suite.
  • Guards run locally: swift_file_length_budget.py (merge-base mode, green), check-workspace-package-groups.py, check-package-resolved-policy.py, check-pbxproj.sh, lint-pbxproj-test-wiring.sh.
  • Localization audit: the only new user-facing UI strings are the three run-completion notification strings, added to Resources/Localizable.xcstrings for en and ja. CLI stdout is exempt per existing convention; no web/docs message catalogs are affected. App-target build is validated by CI (no local xcodebuild per task constraints).

Related: #7361

🤖 Generated with Claude Code


Summary by cubic

Adds shareable orchestration templates: a versioned package + CLI to install, plan, and trust‑gated run fleets of coding agents that provision task workspaces and type agent commands for you. Trust uses a fingerprint over command/substrate metadata and executable template content digests (prompts/layout/scripts); symlink and secret scans walk the whole tree safely.

  • New Features

    • CmuxOrchestration package: orchestration.json schema (parameters, steps, agents, substrates), strict validator (rejects symlinks; whole‑tree secret scan in OrchestrationValidatorScans.swift), placeholder rendering, local store at ~/.cmuxterm/orchestrations (install/list/info/remove/update), run planner + provisioner for worktree, clone-pool, and script; {{prompt_file}} is shell‑quoted.
    • orchestration.list/info/plan/run in CmuxControlSocket; plan returns a trust fingerprint (SHA‑256 over substrate, agent commands, template version, and digests of executable template files). The app enforces a first‑run/update trust gate that must echo this fingerprint; workspaces are created unfocused and grouped; localized run notifications.
    • CLI cmux orchestration: init/validate/install/list/info/remove/update/configure run locally; plan/run via socket and print the full plan; --yes confirms trust non‑interactively and includes the fingerprint. Option parsing helpers moved to CMUXCLI+OptionParsing.swift.
    • Example + docs: Examples/Orchestrations/issue-fleet and docs/orchestrations.md; CI builds CmuxOrchestration; app target declares a product dependency on CmuxOrchestration.
    • API cleanup: manifest parsing is OrchestrationManifest.parse(...) with ParseOutput; parameter override coercion is manifest.coerceParameterOverrides(...); OrchestrationWellKnownParameter uses string‑raw cases; OrchestrationPlaceholders is an instantiable value type.
  • Migration

    • Try it: cmux orchestration install Examples/Orchestrations/issue-fleet then cmux orchestration run issue-fleet --task "Do X" --task "Do Y".
    • Confirm the trust summary on first run (or pass --yes); the confirmation includes the plan’s fingerprint, which covers commands, substrate, and executable template content. update preserves answers and requires reconfirmation.
    • --param k=v overrides install parameters; templates with symlinks are rejected by validate/install. Related: Fleet: built-in agent orchestration loop (workspace per task, board, supervision) #7361

Written for commit 253d246. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features
    • Added the cmux orchestration command suite for template lifecycle: init/validate/install/update/configure/list/info/remove plus plan/run (local and socket-backed).
    • Supports task files, --param overrides, agent selection, dry-run, JSON output, interactive parameter interview, and trust-confirmation (with fingerprint binding).
    • Provisions workspaces via git worktrees, git clones, or template scripts.
    • Includes the issue-fleet orchestration example.
  • Documentation
    • Added orchestration format/CLI/trust documentation and example guides.
  • Tests
    • Expanded orchestration, validation, provisioning, store, and control-socket coverage; CI now also runs CmuxOrchestration SwiftPM tests.

austinywang and others added 6 commits July 13, 2026 16:47
…n planner

Pure SwiftPM package for shareable orchestration templates: versioned
orchestration.json manifest (parameters, substrate, agents, linear steps),
template directory validation with error/warning findings, install store
under ~/.cmuxterm/orchestrations (install/list/info/remove/update over
seam protocols with in-memory fakes), placeholder rendering, run planning
(worktree, clone-pool, script substrates), and an init scaffold.

Related: #7361

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New ControlOrchestrationContext seam + coordinator handler in
CmuxControlSocket (orchestration.list/info/plan/run) with fakes and
coordinator tests. App-side: TerminalController conformance plans runs via
CmuxOrchestration and enforces the trust gate (needs_confirmation until the
user confirms scripts/agent commands/substrate); OrchestrationRunController
provisions workspaces off-main (worktree/clone/script) and creates grouped,
unfocused workspaces with the agent command as typed terminal input.

Related: #7361

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Store verbs (init/validate/install/list/info/remove/update/configure) run
locally against ~/.cmuxterm/orchestrations with an interactive parameter
interview, so they work without a running app; plan/run go through the v2
orchestration.* socket methods. run shows the plan (workspaces, agent
commands, scripts, substrate) and enforces the first-run trust
confirmation; --yes skips the prompt. Contract doc gains the namespace row
and a no-socket help probe.

Related: #7361

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The example is the format's living test fixture: CmuxOrchestration package
tests validate it and plan a worktree run from it on every CI run.

Related: #7361

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
CLI/cmux.swift is over the 900-line hard cap and may not grow; moving
parseOption/parseRepeatedOption/optionValue/hasFlag verbatim offsets the
orchestration namespace's dispatch/help additions (net -60 lines).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 14, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Canceled Canceled Jul 14, 2026 7:06am
cmux-staging Building Building Preview, Comment Jul 14, 2026 7:06am

@coderabbitai

coderabbitai Bot commented Jul 14, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds the CmuxOrchestration Swift package and integrates manifest validation, template storage, run planning, workspace provisioning, trust confirmation, socket APIs, application execution, CLI commands, an example template, documentation, and CI coverage.

Changes

Orchestration platform

Layer / File(s) Summary
Manifest, templates, and validation
Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Model/*, .../Template/*, .../Validation/*
Defines orchestration manifests, parameters, agents, steps, substrates, placeholders, validation findings, version parsing, path checks, symlink detection, and secret scanning.
Storage, planning, and provisioning
Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Store/*, .../Run/*, .../Seams/*, .../Scaffold/*
Adds install/update/query APIs, filesystem/Git/process seams, scaffolding, parameter resolution, workspace plans, trust fingerprints, and worktree/clone/script provisioning.
Socket and application integration
Packages/macOS/CmuxControlSocket/Sources/.../Orchestration/*, Sources/TerminalController+ControlOrchestrationContext.swift, Sources/OrchestrationRunController.swift
Adds orchestration DTOs and request dispatch, plan/run resolution, trust gating, workspace attachment, layout application, and completion notifications.

CLI and supporting integration

Layer / File(s) Summary
CLI routing and commands
CLI/CMUXCLI+OptionParsing.swift, CLI/CMUXCLI+Orchestration*.swift, CLI/cmux.swift
Adds shared option parsing, local template-management commands, socket-backed plan/run commands, help output, JSON modes, trust prompts, and command routing.
Examples, documentation, and build wiring
Examples/Orchestrations/issue-fleet/*, docs/*, cmux.xcodeproj/project.pbxproj, Resources/Localizable.xcstrings, .github/workflows/ci.yml
Adds the issue-fleet template, orchestration documentation, localized run messages, Xcode package/source wiring, and CI execution for the new package tests.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant ControlCommandCoordinator
  participant TerminalController
  participant OrchestrationRunPlanner
  participant OrchestrationRunController
  participant TabManager
  CLI->>ControlCommandCoordinator: Send orchestration.plan or orchestration.run
  ControlCommandCoordinator->>TerminalController: Dispatch orchestration request
  TerminalController->>OrchestrationRunPlanner: Build and validate run plan
  TerminalController->>OrchestrationRunController: Start confirmed plan
  OrchestrationRunController->>TabManager: Provision and attach workspaces
Loading

Suggested reviewers: lawrencecchen, azooz2003-bit, 0xjord4n

🚥 Pre-merge checks | ✅ 4 | ❌ 21

❌ Failed checks (1 warning, 20 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.39% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Cmux Swift Actor Isolation ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux Swift Blocking Runtime ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux Browser Automation Off-Main ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux Expensive Synchronous Load ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux Cache Substitution Correctness ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux No Hacky Sleeps ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux Algorithmic Complexity ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux Swift Concurrency ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux Swift @Concurrent ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux Swift Package Boundaries ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux Swiftpm Lockfiles ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux Swift Logging ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux User-Facing Error Privacy ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux Full Internationalization ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux Swiftui State Layout ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux Architecture Rethink ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux Swift Auxiliary Window Close Shortcuts ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux Source Artifacts ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux No Test Or Debug Seam In Production Source ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Cmux No Ambient Global State ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: shareable orchestration templates with packaging, storage, and trust-gated runs.
Description check ✅ Passed The description is mostly complete: it has a detailed Summary and Testing section and covers scope, tradeoffs, and related docs.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat-orchestration-templates

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.

❤️ Share

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

@greptile-apps

greptile-apps Bot commented Jul 14, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds shareable orchestration templates and trust-gated fleet execution. The main changes are:

  • A dependency-free Swift package for manifests, validation, storage, planning, and provisioning.
  • Local CLI commands for template lifecycle and socket commands for planning and running.
  • App integration for sequential provisioning, workspace grouping, and terminal command delivery.
  • Trust fingerprints, deep symlink checks, secret scanning, documentation, and an example template.

Confidence Score: 5/5

No additional blocking issue qualifies for this review round.

  • The latest fixes cover the previously reported deep symlink, executable-content fingerprint, shell quoting, and app dependency problems.
  • No separate production failure requiring another comment was established.

Important Files Changed

Filename Overview
Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Run/OrchestrationRunPlan.swift Defines run-plan data and hashes executable template material for confirmation.
Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Validation/OrchestrationValidatorScans.swift Adds unbounded template traversal for symlink and secret detection.
CLI/CMUXCLI+OrchestrationRun.swift Adds socket-backed plan, confirmation, and run commands.
cmux.xcodeproj/project.pbxproj Wires the orchestration package product into the app and CLI targets.

Reviews (7): Last reviewed commit: "Merge remote-tracking branch 'origin/mai..." | Re-trigger Greptile

Comment on lines +111 to +112
params["confirm_trust"] = true
let runPayload = try client.sendV2(method: "orchestration.run", params: params)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 security Confirmation Can Approve New Revision

The user confirms the earlier orchestration.plan response, but orchestration.run replans by name and receives only confirm_trust = true. If the template is updated between those calls, the newly installed scripts and commands can be marked trusted and executed even though they were not shown. Bind confirmation to the displayed template commit or plan ID and reject a revision mismatch.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in dd75e89: orchestration.plan now returns a trust_fingerprint (SHA-256 over substrate kind, script paths, agent command templates, and template version). The CLI echoes it back as confirm_fingerprint, and the app rejects a first-run confirmation whose fingerprint doesn't match the freshly replanned trust material, so a template that changed between review and confirmation can no longer be silently approved.

Comment on lines +296 to +303
}
if !fileSystem.fileExists(atPath: join(templateDirectory, reference.path)) {
findings.append(.init(
severity: .error,
code: "missing-file",
message: "\(reference.role) file '\(reference.path)' does not exist in the template",
path: reference.path
))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 security Symlinks Escape Template Root

The path check rejects lexical traversal, but fileExists follows symlinks without proving that the resolved file stays below templateDirectory. A template can reference a relative prompt or provision script whose symlink resolves outside the package; planning then reads that local file into an agent prompt, or provisioning executes a different file than the reviewed package path. Canonicalize each referenced path and reject any result outside the canonical template root.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in dd75e89: validation now walks the template and errors on any symbolic link (symlink finding), so a symlinked prompt/script can't resolve outside the template root. Install/update validate before anything reaches the store, so symlinked templates are rejected outright. Covered by rejectsSymlinksAnywhereInTemplate.

}

let promptFile = Self.promptFileRelativePath
values["prompt"] = OrchestrationPlaceholders.shellQuoted(renderedPrompt)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Prompt File Path Is Unquoted

The rendered prompt is shell-quoted, but prompt_file is inserted as a raw path. When the installation or workspace root contains spaces or shell metacharacters, an agent command such as agent --prompt-file {{prompt_file}} receives split or altered arguments when typed into the terminal. Provide a shell-safe value for this command placeholder.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in dd75e89: {{prompt_file}} is now shell-quoted the same way as {{prompt}}. (Today the value is a constant relative path with no metacharacters, but quoting keeps agent commands safe if the location ever changes.)

C617000000000000000000A3 /* CmuxGit in Frameworks */,
799F1BEF876006EEB8CD1035 /* CMUXMobileCore in Frameworks */,
E3B7A30000000000000000D3 /* CmuxNotifications in Frameworks */,
C0FFEE0000000000000000A3 /* CmuxOrchestration in Frameworks */,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 App Target Omits Product Dependency

The app target compiles new sources that import CmuxOrchestration and links its product in the Frameworks phase, but its packageProductDependencies list does not include that product while the CLI target does. On a clean app-target resolution this can leave the module undeclared and fail compilation with No such module CmuxOrchestration. Add the product dependency to the main cmux target.

Rule Used: Flag SwiftPM package, Xcode project, .gitignore, w... (source)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in dd75e89: the app target's packageProductDependencies now lists CmuxOrchestration explicitly (the Frameworks-phase-only shape mirrored CmuxControlSocket's existing wiring, but the explicit entry is more robust on clean resolution).

austinywang and others added 2 commits July 13, 2026 19:05
package-conventions-lint forbids all-static public namespace types:
manifest parsing moves onto OrchestrationManifest (parse/ParseOutput),
parameter override coercion becomes manifest.coerceParameterOverrides,
OrchestrationWellKnownParameter gains real String-raw cases, and
OrchestrationPlaceholders becomes an instantiable value.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ile, app product dependency

- orchestration.plan returns a trust_fingerprint (SHA-256 of substrate,
  scripts, agent commands, template version); a first-run confirmation must
  echo it back, so a template that changes between review and confirmation
  is rejected (TOCTOU).
- Validation rejects symbolic links anywhere in a template; a symlinked
  prompt or script could resolve outside the template root and leak its
  target into rendered prompts.
- {{prompt_file}} is now shell-quoted like {{prompt}}.
- The app target's packageProductDependencies now lists CmuxOrchestration
  explicitly instead of relying on the Frameworks phase alone.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cursor

cursor Bot commented Jul 14, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

Comment on lines +135 to +149
private func symlinkPaths(under root: String, prefix: String = "", depth: Int = 0) -> [String] {
guard depth < 6, let entries = try? fileSystem.contentsOfDirectory(atPath: root) else { return [] }
var results: [String] = []
for entry in entries.sorted() {
if entry == ".git" { continue }
let absolute = join(root, entry)
let relative = prefix.isEmpty ? entry : "\(prefix)/\(entry)"
if fileSystem.isSymbolicLink(atPath: absolute) {
results.append(relative)
} else if fileSystem.directoryExists(atPath: absolute) {
results.append(contentsOf: symlinkPaths(under: absolute, prefix: relative, depth: depth + 1))
}
}
return results
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 security Scan all nested paths

The symlink scan stops after six directory levels. A manifest can reference a valid relative prompt or provision script below that depth, such as a/b/c/d/e/f/g/run.sh, but a symlink there is never checked. Planning and provisioning then follow the symlink, so an external file can still be read or executed. Remove the fixed depth limit so every referenced template path remains inside the template boundary.

Suggested change
private func symlinkPaths(under root: String, prefix: String = "", depth: Int = 0) -> [String] {
guard depth < 6, let entries = try? fileSystem.contentsOfDirectory(atPath: root) else { return [] }
var results: [String] = []
for entry in entries.sorted() {
if entry == ".git" { continue }
let absolute = join(root, entry)
let relative = prefix.isEmpty ? entry : "\(prefix)/\(entry)"
if fileSystem.isSymbolicLink(atPath: absolute) {
results.append(relative)
} else if fileSystem.directoryExists(atPath: absolute) {
results.append(contentsOf: symlinkPaths(under: absolute, prefix: relative, depth: depth + 1))
}
}
return results
}
private func symlinkPaths(under root: String, prefix: String = "") -> [String] {
guard let entries = try? fileSystem.contentsOfDirectory(atPath: root) else { return [] }
var results: [String] = []
for entry in entries.sorted() {
if entry == ".git" { continue }
let absolute = join(root, entry)
let relative = prefix.isEmpty ? entry : "\(prefix)/\(entry)"
if fileSystem.isSymbolicLink(atPath: absolute) {
results.append(relative)
} else if fileSystem.directoryExists(atPath: absolute) {
results.append(contentsOf: symlinkPaths(under: absolute, prefix: relative))
}
}
return results
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 49873fa: the symlink walk (and the secret sweep) no longer cap at six levels. A symlinked directory is flagged before descent, so recursion stays bounded by the template's real directory depth with no cycle risk.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 49873fa/52cfccdb18: the symlink and secret scans no longer cap at six directory levels. A symlinked directory is flagged before descent (never recursed into), so recursion is bounded by the template's real directory depth and arbitrarily deep symlinks are caught.

…shold

The symlink check pushed OrchestrationValidator.swift to 506 lines; the
whole-tree scans (symlink rejection, secret sweep) move verbatim to
OrchestrationValidatorScans.swift.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment on lines +163 to +168
self.workspaceRoot = workspaceRoot
self.templateVersion = templateVersion
}

/// Stable digest of the trust-relevant material (substrate, scripts,
/// agent commands, template version). A client that showed the user a

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 security Fingerprint omits executable content

The fingerprint covers script paths and raw agent command templates, but not prompt or layout contents. If an update changes a prompt without changing the manifest version or command template, the fingerprint from the displayed plan still matches the replanned run. The rendered terminal command can then contain instructions the user did not review. Include content digests for every template file that affects provisioning or terminal input, including prompts and layouts.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 49873fa: the fingerprint (now v2) includes a contentDigest over the prompt template, layout JSON, and substrate script bytes, so a content-only edit between plan and confirmation invalidates the pending confirmation even when paths, commands, and version are unchanged. Covered by trustFingerprintTracksPromptContent.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 49873fa/52cfccdb18: the trust fingerprint now includes a content digest over the selected prompt template, the layout JSON, and every substrate script's bytes. A content-only edit (same paths, commands, and version) between plan and confirmation now changes the fingerprint and the run is rejected with a re-plan message. Covered by the fingerprint test's prompt-edit assertion.

…rprint

- The template walks (symlink rejection, secret sweep) no longer cap at six
  directory levels; symlinked directories are flagged before descent, so
  recursion is bounded by the template's real depth.
- The trust fingerprint now includes a digest of the executable template
  contents (prompt, layout, substrate script bytes), so a content-only edit
  between plan and confirmation invalidates the pending confirmation even
  when paths, commands, and version are unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cursor

cursor Bot commented Jul 14, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

…print

- The symlink and secret scans no longer stop at six directory levels; a
  symlinked directory is flagged before descent, so recursion is bounded
  by the template's real depth and deep symlinks can't slip past.
- The trust fingerprint now includes a digest of the executable template
  contents (selected prompt, layout JSON, substrate script bytes), so a
  content-only edit between plan and confirmation is rejected even when
  paths, agent commands, and version are unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cursor

cursor Bot commented Jul 14, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@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: 39

🤖 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 `@CLI/cmux.swift`:
- Around line 15806-15807: Update the generic usage() help text’s top-level
Commands list to include orchestration, matching the existing
Self.orchestrationHelpText() dispatch and its placement among related commands.
Ensure plain cmux --help and cmux help expose the new command without changing
the orchestration subcommand help.
- Around line 3255-3261: Add "orchestration" to Self.topLevelCommandNames in
CommandSuggestions so shouldOpenAsPathArgument() recognizes it as a top-level
command even when a matching filesystem path exists. Preserve the existing local
orchestration routing in runOrchestrationLocalNamespace and command-first
dispatch behavior.

In `@CLI/CMUXCLI`+OptionParsing.swift:
- Around line 74-76: Update hasFlag to inspect only arguments before the
standalone "--" terminator, so flags appearing afterward are treated as
forwarded arguments rather than cmux options. Preserve existing exact flag
matching for pre-terminator arguments and return false when the requested flag
occurs only after "--".

In `@CLI/CMUXCLI`+Orchestration.swift:
- Around line 348-358: Update the parameter persistence and reload flow in
configure around store.setResolvedParameters and store.installed(named:) to
propagate failures as CLIError instead of discarding them or returning silently.
Preserve the existing success path and ensure “parameters saved” is only
reported after both required store operations succeed.

In `@CLI/CMUXCLI`+OrchestrationRun.swift:
- Around line 89-104: Update the orchestration run flow around
effectiveJSONOutput so non-dry JSON runs emit only the machine-readable JSON
payload on stdout. Suppress printOrchestrationPlan and interactive
trust-confirmation output in JSON mode, and require --yes when trust is not
already confirmed; users must review the plan separately via plan --json.

In `@cmux.xcodeproj/project.pbxproj`:
- Line 5714: Commit or update the Xcode SwiftPM lockfile at the workspace’s
shared SwiftPM location to include the resolved CmuxOrchestration package
dependency introduced by the XCLocalSwiftPackageReference entry. Ensure
Package.resolved records the complete, reproducible dependency resolution for
standalone Xcode builds.

In `@docs/orchestrations.md`:
- Line 34: Update the fenced code blocks in docs/orchestrations.md at lines
34-34 and 179-179 with the text language identifier, and at line 148-148 with
the bash language identifier; no other content changes are needed.

In
`@Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/Orchestration/ControlCommandCoordinator`+Orchestration.swift:
- Around line 135-138: Update the string-task handling in the orchestration
command coordinator to return an invalid_params error when the trimmed title is
empty, rather than continuing and silently omitting that task. Preserve trimming
and task creation for nonblank strings, and ensure mixed inputs fail the entire
request consistently with empty object titles.

In
`@Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/Orchestration/ControlOrchestrationContext.swift`:
- Line 2: Mark the transport DTOs ControlOrchestrationSummary,
ControlOrchestrationTaskInput, and ControlOrchestrationRunInputs as nonisolated
while preserving their immutable Sendable value-model definitions.

In
`@Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Model/OrchestrationManifest.swift`:
- Around line 179-221: Replace hard-coded user-facing diagnostics with
structured, localizable errors: in
Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Model/OrchestrationManifest.swift
lines 179-221, update the manifest parsing and describe logic to return
structured parse errors without raw debugDescription; in
OrchestrationParameter.swift lines 132-152, use stable reason codes and
arguments; in OrchestrationStep.swift lines 52-107 and
OrchestrationSubstrate.swift lines 52-57, structure invalid-policy and
invalid-kind diagnostics; in OrchestrationValidator.swift lines 60-405 and
OrchestrationValidatorScans.swift lines 68-72, localize findings before
presentation; add complete matching keys and translations for every locale in
Resources/Localizable.xcstrings.

In
`@Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Model/OrchestrationStep.swift`:
- Around line 100-116: Update OrchestrationStep.init(from:) in the .retry
decoding branch to validate the decoded attempts value as non-negative before
constructing retry(attempts:). Preserve the default value of 1 when attempts is
absent, and throw a suitable DecodingError for negative values.

In
`@Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Model/OrchestrationVersion.swift`:
- Around line 10-18: Update OrchestrationVersion’s major, minor, and patch
storage and initializer validation so every component is non-negative and cannot
be mutated into an invalid value after initialization. Preserve the existing
default values and ensure invalid inputs are rejected using the project’s
established invariant-enforcement approach.

In
`@Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Run/OrchestrationParameterResolution.swift`:
- Around line 11-14: Localize all user-facing orchestration errors using the
project’s localized APIs and add matching complete catalog entries: update the
unknown-parameter reason in
Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Run/OrchestrationParameterResolution.swift
lines 11-14, the unresolved-placeholder error in
Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Template/OrchestrationPlaceholders.swift
lines 65-67, and the invalid-name and existing-file errors in
Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Scaffold/OrchestrationScaffold.swift
lines 29-37. Preserve each error’s existing meaning while exposing localized
text or structured reasons for boundary localization.

In
`@Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Run/OrchestrationProvisioner.swift`:
- Around line 76-84: Sanitize provisioning failures at the
OrchestrationProvisioner boundary by replacing raw launch errors, exit codes,
and stderr with safe product-level messages while retaining redacted details
only for internal diagnostics. Update
Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Run/OrchestrationProvisioner.swift
lines 76-84 accordingly; update
Packages/macOS/CmuxOrchestration/Tests/CmuxOrchestrationTests/OrchestrationProvisionerTests.swift
lines 105-121 to assert the sanitized public error instead of raw stderr.
- Around line 41-43: The orchestration-facing messages are hard-coded and must
use localization. In OrchestrationProvisioner.swift lines 41-43, localize every
provisioning error with stable catalog keys; in OrchestrationRunPlanner.swift
lines 82-94, localize every planning error and note, including interpolated
values, and add matching translated catalog entries for all new keys.

In
`@Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Run/OrchestrationRunPlan.swift`:
- Around line 184-195: Use one canonical, unambiguous encoding for all
trust-hash inputs. In OrchestrationRunPlan.fingerprint, include workspaceRoot
and replace delimiter-only concatenation with explicit-length encoding or
canonical Codable serialization for every field and array element. In
OrchestrationRunPlanner’s hashing flow, apply the same encoding to prompt,
layout, and script path/content records; keep both sites consistent so distinct
inputs cannot produce the same material.
- Around line 173-177: Update sha256Hex to avoid per-byte String(format:)
conversion: use a cached hexadecimal lookup table and a preallocated UTF-8
buffer, writing two hex characters for each digest byte before constructing the
final String.

In
`@Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Run/OrchestrationRunPlanner.swift`:
- Around line 96-101: Update the agent resolution flow in
OrchestrationRunPlanner to consider every authoritative source: explicit
request.agentID, the resolved agent parameter, the first step’s agent, then
manifest.prompt’s default agent. Apply one consistent precedence path when
selecting the agent used for execution, preserving the existing first-step
behavior, and add coverage using distinct agents to verify the precedence.
- Around line 129-142: Update parameterValues construction in the orchestration
run planner to overwrite the well-known repoRoot and workspaceRoot entries with
the resolved absolute repoRoot and workspaceRoot values after copying the raw
parameters. Preserve all other parameter values unchanged so prompts and
commands receive the same paths used for provisioning.
- Around line 122-127: Update the concurrency handling in the orchestration run
planner so zero or negative values are rejected rather than bypassing the task
cap. Validate the .int concurrency parameter before planning tasks, using the
existing error-reporting mechanism, while preserving the current prefix limiting
behavior for positive values.

In
`@Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Scaffold/OrchestrationScaffold.swift`:
- Around line 33-46: Update the scaffold generation flow around
Self.files(name:) to first build the complete list of destination paths and
verify that none already exists, including orchestration.json, README.md,
WORKFLOW.md, and nested prompt files. Throw OrchestrationManifestError before
creating directories or writing any files when a destination conflicts, then
reuse the validated plan for directory creation and writes.

In
`@Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Seams/OrchestrationGitClient.swift`:
- Around line 8-12: Update DefaultOrchestrationGitClient.runGit so stdout and
stderr are consumed concurrently rather than sequentially, preventing either
pipe from blocking when its buffer fills. Preserve the existing command
execution, exit-status handling, and captured output behavior.

In
`@Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Seams/OrchestrationProcessRunner.swift`:
- Around line 21-27: Update OrchestrationProcessRunner.run and its
implementations so stdout and stderr are drained concurrently rather than read
sequentially, preventing blocked child processes when either pipe fills. Avoid
unbounded in-memory buffering by applying an explicit output cap or streaming
output while preserving the returned OrchestrationProcessResult contract.
- Around line 21-67: Update DefaultOrchestrationProcessRunner.run and the
process execution wrapper in
Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Seams/OrchestrationProcessRunner.swift:21-67
and
Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Seams/OrchestrationGitClient.swift:8-58
to use one shared helper that drains stdout and stderr concurrently, preventing
either pipe from blocking the child; cap the amount retained for each stream
instead of buffering all output in memory, while preserving the existing
OrchestrationProcessResult values and process execution behavior.

In
`@Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Store/OrchestrationInstallRecord.swift`:
- Around line 66-80: Update OrchestrationInstallSource.detect to resolve an
existing filesystem path before applying any Git classification, so local paths
such as /tmp/template.git remain local sources. Remove the .git suffix
heuristic; for ambiguous non-existing inputs, fail closed or require an explicit
source kind instead of inferring transport from strings.

In
`@Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Store/OrchestrationStore.swift`:
- Around line 128-146: Update the installation flow around installPath,
templateDirectory(for:), and writeRecord so replacements are assembled
completely in a sibling staging directory, including the template copy and
installation record, before changing the authoritative installation. Atomically
rename or swap the completed staging directory into installPath only after all
preparation succeeds; preserve the existing installation on any copy or
record-write failure, and apply the same behavior to the update path around
lines 202–217.
- Around line 3-24: Remove CLI-ready user copy from
OrchestrationStoreError.description and keep its cases as structured errors with
sanitized internal diagnostic details only; do not interpolate raw source URLs
or upstream errors. Update the CLI boundary handling for
OrchestrationStoreError, including the affected paths around install/source
handling, to map each case to localized product-facing messages using safe
values such as orchestration names, while preserving detailed diagnostics
separately for internal logging.
- Around line 251-258: Validate the decoded record’s schemaVersion in the
install-record loading flow before returning it, comparing it with
currentSchemaVersion. If the versions differ or are unsupported, throw
OrchestrationStoreError.corruptInstall with the install name and relevant
detail, preserving the existing corrupt-record handling and failing closed until
migration support exists.
- Around line 40-46: The OrchestrationStore mutation methods install, update,
remove, setResolvedParameters, and confirmTrust need coordinated per-install
serialization and atomic install.json replacement. Add a per-install locking
mechanism shared by these methods, hold it across each read/modify/rewrite or
directory-removal operation, and write updated records through a temporary file
followed by an atomic replacement; preserve existing behavior outside the
protected mutation scope.

In
`@Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Validation/OrchestrationValidator.swift`:
- Around line 68-82: In the orchestration validation flow, run
validateNoSymlinks immediately after confirming the template directory and
before constructing or reading the manifest in OrchestrationValidator. If
symlink findings are present, return the validation report immediately so no
manifest, prompt, or script files are read; preserve the existing
missing-directory and missing-manifest handling for non-symlink cases.
- Around line 300-307: Update the validation logic around the referenced-file
checks in OrchestrationValidator to require each referenced path to be a regular
file, rejecting directories instead of relying solely on fileExists. For
referenced scripts, validate executable permissions and report non-executable
files with error severity rather than warning, including the affected path and
existing diagnostic context; apply the same requirements to the additional check
around the separately noted range.

In
`@Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Validation/OrchestrationValidatorScans.swift`:
- Around line 62-66: Update the file iteration in OrchestrationValidatorScans so
oversized template files are not fully loaded before validation and cannot
bypass secret scanning. Preflight each file’s size before reading, then
stream-scan files within the allowed limit (or explicitly reject files over the
template limit), preserving UTF-8 text scanning for accepted files.

In
`@Packages/macOS/CmuxOrchestration/Tests/CmuxOrchestrationTests/OrchestrationTestSupport.swift`:
- Around line 119-157: Update removeItem and copyItem to keep symlinkPaths
consistent: remove the target and all descendants from symlinkPaths when
deleting, and propagate matching symlinkPaths entries to destination paths when
copying both individual files and directories, alongside executable metadata.

In `@Resources/Localizable.xcstrings`:
- Around line 234182-234198: Update the orchestration.run.readyBody localization
entry to use count-aware singular and plural variants for the workspace count,
replacing the literal “workspace(s)” wording. Add equivalent grammatical
variants for each existing locale while preserving the current message meaning
and interpolation placeholder.

In `@Sources/OrchestrationRunController.swift`:
- Around line 138-145: Update the failure notification in the orchestration run
handling flow around store.addNotification so its body uses the localized string
API with the sanitized failures list as interpolation data. Ensure the
user-facing message does not expose implementation details, while preserving the
existing failure content and notification behavior.
- Around line 129-136: Update the localized body in the orchestration run-ready
notification to use ICU-style pluralization with explicit one and other variants
keyed from plan.workspaces.count, replacing the String(format:) "%1$d"
interpolation. Preserve the existing workspace count and message meaning while
allowing locale-correct plural translations.
- Around line 43-46: Update the catch block in OrchestrationRunController to log
the raw error through internal telemetry, then append only workspacePlan.title
to failures. Remove String(describing: error) from the user-facing failure text
so callers can present a generic error without exposing provisioner details.

In `@Sources/TerminalController`+ControlOrchestrationContext.swift:
- Around line 23-24: Replace the raw String(describing: error) values returned
by the catch blocks in TerminalController control orchestration with stable,
product-facing failure messages. Apply the same mapping at the additional catch
sites noted in the review, while recording detailed errors only through
privately redacted logging; do not expose upstream messages or internal
implementation details via the socket API.
- Around line 5-10: Update controlOrchestrationList, controlOrchestrationInfo,
orchestrationPlan, and controlOrchestrationRun so install listing, record
parsing, and template scanning execute off `@MainActor`, while retaining
main-actor execution only for UI/socket coordination and run actuation. Replace
String(describing:) in each failed path with concise sanitized user-facing
messages that do not expose raw errors or filesystem details.
🪄 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: ASSERTIVE

Plan: Pro

Run ID: 27596f41-f083-4720-a2dc-4507820e0f95

📥 Commits

Reviewing files that changed from the base of the PR and between fb55272 and 49873fa.

⛔ Files ignored due to path filters (1)
  • cmux.xcworkspace/contents.xcworkspacedata is excluded by !**/*.xcworkspace/contents.xcworkspacedata
📒 Files selected for processing (51)
  • .github/workflows/ci.yml
  • CLI/CMUXCLI+OptionParsing.swift
  • CLI/CMUXCLI+Orchestration.swift
  • CLI/CMUXCLI+OrchestrationRun.swift
  • CLI/cmux.swift
  • Examples/Orchestrations/issue-fleet/README.md
  • Examples/Orchestrations/issue-fleet/WORKFLOW.md
  • Examples/Orchestrations/issue-fleet/instructions/AGENTS.md
  • Examples/Orchestrations/issue-fleet/orchestration.json
  • Examples/Orchestrations/issue-fleet/prompts/review.md
  • Examples/Orchestrations/issue-fleet/prompts/task.md
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/ControlCommandContext.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/ControlCommandCoordinator.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/Orchestration/ControlCommandCoordinator+Orchestration.swift
  • Packages/macOS/CmuxControlSocket/Sources/CmuxControlSocket/Coordinator/Orchestration/ControlOrchestrationContext.swift
  • Packages/macOS/CmuxControlSocket/Tests/CmuxControlSocketTests/ControlCommandCoordinatorOrchestrationTests.swift
  • Packages/macOS/CmuxControlSocket/Tests/CmuxControlSocketTests/ControlOrchestrationContextTestStubs.swift
  • Packages/macOS/CmuxControlSocket/Tests/CmuxControlSocketTests/FakeOrchestrationControlCommandContext.swift
  • Packages/macOS/CmuxOrchestration/Package.swift
  • Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Model/OrchestrationManifest.swift
  • Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Model/OrchestrationParameter.swift
  • Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Model/OrchestrationStep.swift
  • Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Model/OrchestrationSubstrate.swift
  • Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Model/OrchestrationVersion.swift
  • Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Run/OrchestrationParameterResolution.swift
  • Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Run/OrchestrationProvisioner.swift
  • Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Run/OrchestrationRunPlan.swift
  • Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Run/OrchestrationRunPlanner.swift
  • Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Scaffold/OrchestrationScaffold.swift
  • Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Seams/OrchestrationFileSystem.swift
  • Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Seams/OrchestrationGitClient.swift
  • Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Seams/OrchestrationProcessRunner.swift
  • Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Store/OrchestrationInstallRecord.swift
  • Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Store/OrchestrationStore.swift
  • Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Template/OrchestrationPlaceholders.swift
  • Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Validation/OrchestrationValidator.swift
  • Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Validation/OrchestrationValidatorScans.swift
  • Packages/macOS/CmuxOrchestration/Tests/CmuxOrchestrationTests/ExampleTemplateTests.swift
  • Packages/macOS/CmuxOrchestration/Tests/CmuxOrchestrationTests/OrchestrationManifestTests.swift
  • Packages/macOS/CmuxOrchestration/Tests/CmuxOrchestrationTests/OrchestrationPlaceholdersTests.swift
  • Packages/macOS/CmuxOrchestration/Tests/CmuxOrchestrationTests/OrchestrationProvisionerTests.swift
  • Packages/macOS/CmuxOrchestration/Tests/CmuxOrchestrationTests/OrchestrationRunPlannerTests.swift
  • Packages/macOS/CmuxOrchestration/Tests/CmuxOrchestrationTests/OrchestrationStoreTests.swift
  • Packages/macOS/CmuxOrchestration/Tests/CmuxOrchestrationTests/OrchestrationTestSupport.swift
  • Packages/macOS/CmuxOrchestration/Tests/CmuxOrchestrationTests/OrchestrationValidatorTests.swift
  • Resources/Localizable.xcstrings
  • Sources/OrchestrationRunController.swift
  • Sources/TerminalController+ControlOrchestrationContext.swift
  • cmux.xcodeproj/project.pbxproj
  • docs/cli-contract.md
  • docs/orchestrations.md

Comment thread CLI/cmux.swift
Comment on lines +3255 to +3261
// Orchestration store verbs manage ~/.cmuxterm/orchestrations locally
// and must work with no cmux running; only run/plan need the socket.
if command == "orchestration", !Self.orchestrationCommandNeedsSocket(commandArgs) {
try runOrchestrationLocalNamespace(commandArgs: commandArgs, jsonOutput: jsonOutput)
return
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n 'func orchestrationCommandNeedsSocket' -A 15 CLI/

Repository: manaflow-ai/cmux

Length of output: 1333


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '1,140p' CLI/CMUXCLI+Orchestration.swift
printf '\n---\n'
rg -n 'topLevelCommandNames|shouldOpenAsPathArgument|case "orchestration"|orchestration' CLI/cmux.swift CLI/CMUXCLI+*.swift

Repository: manaflow-ai/cmux

Length of output: 14166


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '45,85p' CLI/CMUXCLI+CommandSuggestions.swift
printf '\n---\n'
sed -n '5590,5610p' CLI/cmux.swift
printf '\n---\n'
sed -n '35076,35295p' CLI/cmux.swift | rg -n 'orchestration|Commands:|usage'

Repository: manaflow-ai/cmux

Length of output: 1999


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n '"orchestration"' CLI/CMUXCLI+CommandSuggestions.swift CLI/cmux.swift

Repository: manaflow-ai/cmux

Length of output: 515


Add orchestration to the top-level command set
shouldOpenAsPathArgument() only skips names in Self.topLevelCommandNames, so cmux orchestration ... can be treated as a path when a local file or directory named orchestration exists. Add the command name to CLI/CMUXCLI+CommandSuggestions.swift:53 so routing in CLI/cmux.swift:5602 stays command-first.

🤖 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 `@CLI/cmux.swift` around lines 3255 - 3261, Add "orchestration" to
Self.topLevelCommandNames in CommandSuggestions so shouldOpenAsPathArgument()
recognizes it as a top-level command even when a matching filesystem path
exists. Preserve the existing local orchestration routing in
runOrchestrationLocalNamespace and command-first dispatch behavior.

Comment thread CLI/cmux.swift
Comment on lines +15806 to +15807
case "orchestration":
return Self.orchestrationHelpText()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

orchestration is missing from the top-level cmux --help command list.

The generic usage() string printed by cmux help/cmux --help (around L35099-35272) enumerates all top-level commands but does not mention orchestration, even though this PR adds a substantial new command surface (list, info, plan, run, local template management). Users running plain cmux --help won't discover it; only cmux orchestration --help (which this new subcommandUsage case correctly serves) will.

📝 Suggested addition to the Commands: list in usage()
           hooks setup|uninstall [--agent <name>]
           hooks <agent> <install|uninstall|event> [options; opencode supports --project]
           hooks feed --source <agent> [--event <event>]
+          orchestration <list|info|plan|run|...> [args...]
           ping
🤖 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 `@CLI/cmux.swift` around lines 15806 - 15807, Update the generic usage() help
text’s top-level Commands list to include orchestration, matching the existing
Self.orchestrationHelpText() dispatch and its placement among related commands.
Ensure plain cmux --help and cmux help expose the new command without changing
the orchestration subcommand help.

Comment on lines +74 to +76
func hasFlag(_ args: [String], name: String) -> Bool {
args.contains(name)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Stop flag detection at the -- terminator.

hasFlag contradicts the documented parser contract and treats forwarded arguments as cmux flags. For example, a post-terminator --yes still bypasses the orchestration trust prompt.

Proposed fix
 func hasFlag(_ args: [String], name: String) -> Bool {
-    args.contains(name)
+    args.prefix { $0 != "--" }.contains(name)
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func hasFlag(_ args: [String], name: String) -> Bool {
args.contains(name)
}
func hasFlag(_ args: [String], name: String) -> Bool {
args.prefix { $0 != "--" }.contains(name)
}
🤖 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 `@CLI/CMUXCLI`+OptionParsing.swift around lines 74 - 76, Update hasFlag to
inspect only arguments before the standalone "--" terminator, so flags appearing
afterward are treated as forwarded arguments rather than cmux options. Preserve
existing exact flag matching for pre-terminator arguments and return false when
the requested flag occurs only after "--".

Comment on lines +348 to +358
if !values.isEmpty {
_ = try? store.setResolvedParameters(name: name, values: values)
}

guard interviewUnanswered else { return }
let installation: InstalledOrchestration
do {
installation = try store.installed(named: name)
} catch {
return
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Do not report success after parameter persistence fails.

Both writes discard errors, and the reload failure silently skips the interview. configure can therefore print “parameters saved” while the store remains unchanged. Propagate these failures as CLIError instead.

Proposed fix
 if !values.isEmpty {
-    _ = try? store.setResolvedParameters(name: name, values: values)
+    do {
+        _ = try store.setResolvedParameters(name: name, values: values)
+    } catch {
+        throw CLIError(message: String(describing: error))
+    }
 }

 let installation: InstalledOrchestration
 do {
     installation = try store.installed(named: name)
 } catch {
-    return
+    throw CLIError(message: String(describing: error))
 }

 if !answers.isEmpty {
-    _ = try? store.setResolvedParameters(name: name, values: answers)
+    do {
+        _ = try store.setResolvedParameters(name: name, values: answers)
+    } catch {
+        throw CLIError(message: String(describing: error))
+    }
 }

Also applies to: 372-374

🤖 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 `@CLI/CMUXCLI`+Orchestration.swift around lines 348 - 358, Update the parameter
persistence and reload flow in configure around store.setResolvedParameters and
store.installed(named:) to propagate failures as CLIError instead of discarding
them or returning silently. Preserve the existing success path and ensure
“parameters saved” is only reported after both required store operations
succeed.

Comment on lines +89 to +104
if effectiveJSONOutput, dryRun {
print(jsonString(planPayload))
return
}
printOrchestrationPlan(plan, trustConfirmed: trustConfirmed)
if dryRun {
return
}

if !trustConfirmed && !assumeYes {
guard isatty(fileno(stdin)) != 0 else {
throw CLIError(message: "First run of '\(name)' needs trust confirmation. Re-run with --yes after reviewing the plan above.")
}
print("First run of this template. It will type the agent commands above into real terminals" +
(orchestrationPlanHasScripts(plan) ? " and execute the listed template scripts" : "") + ".")
print("Proceed? [y/N]: ", terminator: "")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Keep run --json stdout machine-readable.

Non-dry runs print the human plan and potentially the confirmation prompt before the JSON payload, so stdout cannot be decoded as JSON. Suppress human output in JSON mode and require --yes after separately reviewing plan --json.

Proposed fix
 if effectiveJSONOutput, dryRun {
     print(jsonString(planPayload))
     return
 }
-printOrchestrationPlan(plan, trustConfirmed: trustConfirmed)
+if !effectiveJSONOutput {
+    printOrchestrationPlan(plan, trustConfirmed: trustConfirmed)
+}
 if dryRun {
     return
 }

 if !trustConfirmed && !assumeYes {
+    if effectiveJSONOutput {
+        throw CLIError(
+            message: "Trust confirmation required. Review `cmux orchestration plan \(name) --json`, then re-run with --yes."
+        )
+    }
     guard isatty(fileno(stdin)) != 0 else {

Also applies to: 119-121

🤖 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 `@CLI/CMUXCLI`+OrchestrationRun.swift around lines 89 - 104, Update the
orchestration run flow around effectiveJSONOutput so non-dry JSON runs emit only
the machine-readable JSON payload on stdout. Suppress printOrchestrationPlan and
interactive trust-confirmation output in JSON mode, and require --yes when trust
is not already confirmed; users must review the plan separately via plan --json.

Comment on lines +43 to +46
} catch {
failures.append("\(workspacePlan.title): \(String(describing: error))")
continue
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Do not expose raw upstream errors in user-facing text.

Appending String(describing: error) captures raw stderr from the external provisioner commands (e.g., git clone or scripts). Displaying this in the UI violates the guidelines against exposing implementation details and raw upstream errors.

Log the raw error to internal telemetry instead, and append only the safe workspacePlan.title to the failures list so a generic error can be presented. As per path instructions: "User-facing errors, alerts, command output, API error bodies, and recovery copy must not expose implementation details. Do not expose raw upstream errors... Keep provider, billing, database, and authentication implementation details in sanitized logs or internal telemetry, not user-visible text."

🛡️ Proposed fix
                 } catch {
-                    failures.append("\(workspacePlan.title): \(String(describing: error))")
+#if DEBUG
+                    cmuxDebugLog("orchestration.run.workspaceFailed workspace=\(workspacePlan.title) error=\(String(describing: error))")
+#endif
+                    failures.append(workspacePlan.title)
                     continue
                 }
🤖 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 `@Sources/OrchestrationRunController.swift` around lines 43 - 46, Update the
catch block in OrchestrationRunController to log the raw error through internal
telemetry, then append only workspacePlan.title to failures. Remove
String(describing: error) from the user-facing failure text so callers can
present a generic error without exposing provisioner details.

Source: Path instructions

Comment on lines +129 to +136
body: String(
format: String(
localized: "orchestration.run.readyBody",
defaultValue: "%1$d workspace(s) provisioned and running."
),
plan.workspaces.count
)
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Use ICU-style plural localization keys.

Using %1$d inside String(format: String(localized:)) is an anti-pattern for plurals. Based on learnings, prefer explicit .one and .other localization keys for pluralized text to ensure correct translation across all locales.

♻️ Proposed fix
-                body: String(
-                    format: String(
-                        localized: "orchestration.run.readyBody",
-                        defaultValue: "%1$d workspace(s) provisioned and running."
-                    ),
-                    plan.workspaces.count
-                )
+                body: plan.workspaces.count == 1
+                    ? String(localized: "orchestration.run.readyBody.one", defaultValue: "1 workspace provisioned and running.")
+                    : String(localized: "orchestration.run.readyBody.other", defaultValue: "\(plan.workspaces.count) workspaces provisioned and running.")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
body: String(
format: String(
localized: "orchestration.run.readyBody",
defaultValue: "%1$d workspace(s) provisioned and running."
),
plan.workspaces.count
)
)
body: plan.workspaces.count == 1
? String(localized: "orchestration.run.readyBody.one", defaultValue: "1 workspace provisioned and running.")
: String(localized: "orchestration.run.readyBody.other", defaultValue: "\(plan.workspaces.count) workspaces provisioned and running.")
)
🤖 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 `@Sources/OrchestrationRunController.swift` around lines 129 - 136, Update the
localized body in the orchestration run-ready notification to use ICU-style
pluralization with explicit one and other variants keyed from
plan.workspaces.count, replacing the String(format:) "%1$d" interpolation.
Preserve the existing workspace count and message meaning while allowing
locale-correct plural translations.

Source: Learnings

Comment on lines +138 to +145
store.addNotification(
tabId: anchorWorkspaceID,
surfaceId: nil,
title: String(localized: "orchestration.run.failedTitle", defaultValue: "Orchestration run had failures"),
subtitle: plan.groupName,
body: failures.joined(separator: "\n")
)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Use a localized string for the error notification body.

The failure notification body uses non-localized string concatenation, which bypasses the localized API requirement. Wrap the sanitized failures list inside a proper localized string.
As per path instructions: "User-facing errors... and recovery copy must not expose implementation details."

🛡️ Proposed fix
             store.addNotification(
                 tabId: anchorWorkspaceID,
                 surfaceId: nil,
                 title: String(localized: "orchestration.run.failedTitle", defaultValue: "Orchestration run had failures"),
                 subtitle: plan.groupName,
-                body: failures.joined(separator: "\n")
+                body: String(
+                    localized: "orchestration.run.failedBody",
+                    defaultValue: "Failed to provision: \(failures.joined(separator: ", "))"
+                )
             )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
store.addNotification(
tabId: anchorWorkspaceID,
surfaceId: nil,
title: String(localized: "orchestration.run.failedTitle", defaultValue: "Orchestration run had failures"),
subtitle: plan.groupName,
body: failures.joined(separator: "\n")
)
}
store.addNotification(
tabId: anchorWorkspaceID,
surfaceId: nil,
title: String(localized: "orchestration.run.failedTitle", defaultValue: "Orchestration run had failures"),
subtitle: plan.groupName,
body: String(
localized: "orchestration.run.failedBody",
defaultValue: "Failed to provision: \(failures.joined(separator: ", "))"
)
)
🤖 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 `@Sources/OrchestrationRunController.swift` around lines 138 - 145, Update the
failure notification in the orchestration run handling flow around
store.addNotification so its body uses the localized string API with the
sanitized failures list as interpolation data. Ensure the user-facing message
does not expose implementation details, while preserving the existing failure
content and notification behavior.

Source: Path instructions

Comment on lines +5 to +10
/// The orchestration-domain witnesses for ``ControlCommandCoordinator``:
/// reads the installed-template store, plans runs through
/// `CmuxOrchestration`, enforces the trust gate, and hands accepted plans to
/// ``OrchestrationRunController`` for actuation. Store and template files
/// are small JSON documents (the `SavedLayoutStore` precedent), so reads
/// happen inline; provisioning always leaves the main actor.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect the concrete synchronous I/O reached from these MainActor witnesses.
ast-grep outline Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Store/OrchestrationStore.swift --items all
ast-grep outline Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Run/OrchestrationRunPlanner.swift --items all
rg -n -C3 '\b(list|installed|plan|readData|directoryContents|contentsOfDirectory)\s*\(' \
  Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration

Repository: manaflow-ai/cmux

Length of output: 21507


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '1,220p' Sources/TerminalController+ControlOrchestrationContext.swift
printf '\n====\n'
sed -n '1,220p' Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Store/OrchestrationStore.swift
printf '\n====\n'
sed -n '1,220p' Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Run/OrchestrationRunPlanner.swift
printf '\n====\n'
sed -n '1,240p' Sources/TerminalController.swift

Repository: manaflow-ai/cmux

Length of output: 40510


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C4 '`@MainActor`|internal_error|String\(describing:|ControlCommandCoordinator|Orchestration' \
  Sources/TerminalController+ControlOrchestrationContext.swift \
  Sources/TerminalController.swift \
  Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Store/OrchestrationStore.swift \
  Packages/macOS/CmuxOrchestration/Sources/CmuxOrchestration/Run/OrchestrationRunPlanner.swift

Repository: manaflow-ai/cmux

Length of output: 50373


Move orchestration storage and planning off @MainActor. controlOrchestrationList, controlOrchestrationInfo, orchestrationPlan, and controlOrchestrationRun still synchronously list installs, read/parse install records, and scan template files on the main actor. That can stall UI and other socket handling on larger installs or slow disks. Also replace the String(describing:) passthroughs in these failed paths with sanitized user-facing messages.

🤖 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 `@Sources/TerminalController`+ControlOrchestrationContext.swift around lines 5
- 10, Update controlOrchestrationList, controlOrchestrationInfo,
orchestrationPlan, and controlOrchestrationRun so install listing, record
parsing, and template scanning execute off `@MainActor`, while retaining
main-actor execution only for UI/socket coordination and run actuation. Replace
String(describing:) in each failed path with concise sanitized user-facing
messages that do not expose raw errors or filesystem details.

Sources: Coding guidelines, Path instructions

Comment on lines +23 to +24
} catch {
return .failed(String(describing: error))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Do not return raw internal errors over the socket API.

String(describing: error) can expose local paths, malformed file contents, and storage implementation details through internal_error. Map these catches to stable product-facing messages and keep detailed diagnostics in privately redacted logs.

As per coding guidelines, API errors must not expose raw upstream messages or internal implementation details.

Also applies to: 36-40, 95-98, 134-140, 161-166

🤖 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 `@Sources/TerminalController`+ControlOrchestrationContext.swift around lines 23
- 24, Replace the raw String(describing: error) values returned by the catch
blocks in TerminalController control orchestration with stable, product-facing
failure messages. Apply the same mapping at the additional catch sites noted in
the review, while recording detailed errors only through privately redacted
logging; do not expose upstream messages or internal implementation details via
the socket API.

Source: Coding guidelines

@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.

Caution

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

⚠️ Outside diff range comments (1)
CLI/cmux.swift (1)

35186-35188: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

orchestration is missing from the top-level cmux --help command list.

The generic usage() string enumerates all top-level commands but does not mention orchestration, even though this PR adds a substantial new command surface (list, info, plan, run, local template management). Users running plain cmux --help won't discover it; only cmux orchestration --help will.

📝 Proposed fix to add `orchestration`
           hooks setup|uninstall [--agent <name>]
           hooks <agent> <install|uninstall|event> [options; opencode supports --project]
           hooks feed --source <agent> [--event <event>]
+          orchestration <init|validate|install|list|info|remove|update|configure|plan|run> [args...]
           ping
🤖 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 `@CLI/cmux.swift` around lines 35186 - 35188, Update the generic usage/help
command list in CLI/cmux.swift to include the top-level orchestration command
alongside the other commands, so plain cmux --help exposes its subcommands and
users can discover it.
♻️ Duplicate comments (1)
CLI/cmux.swift (1)

3275-3281: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Add orchestration to the top-level command set.

shouldOpenAsPathArgument() only skips names in Self.topLevelCommandNames, so cmux orchestration ... can be treated as a path when a local file or directory named orchestration exists. Ensure the command name is added to CLI/CMUXCLI+CommandSuggestions.swift so routing in CLI/cmux.swift stays command-first.

Please run the following script to verify if the missing command name has been added to the command suggestions:

#!/bin/bash
# Description: Verify if orchestration is added to topLevelCommandNames
rg -n 'topLevelCommandNames' -A 15 CLI/CMUXCLI+CommandSuggestions.swift || true
🤖 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 `@CLI/cmux.swift` around lines 3275 - 3281, Update the topLevelCommandNames
definition in CMUXCLI+CommandSuggestions.swift to include "orchestration",
ensuring shouldOpenAsPathArgument() routes cmux orchestration commands as
commands even when a matching local path exists.
🤖 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.

Outside diff comments:
In `@CLI/cmux.swift`:
- Around line 35186-35188: Update the generic usage/help command list in
CLI/cmux.swift to include the top-level orchestration command alongside the
other commands, so plain cmux --help exposes its subcommands and users can
discover it.

---

Duplicate comments:
In `@CLI/cmux.swift`:
- Around line 3275-3281: Update the topLevelCommandNames definition in
CMUXCLI+CommandSuggestions.swift to include "orchestration", ensuring
shouldOpenAsPathArgument() routes cmux orchestration commands as commands even
when a matching local path exists.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9403240d-0e6d-4049-accb-7f98777906bb

📥 Commits

Reviewing files that changed from the base of the PR and between 52cfccd and 253d246.

📒 Files selected for processing (2)
  • .github/workflows/ci.yml
  • CLI/cmux.swift

@lawrencecchen lawrencecchen added the stale-revisit Closed after 30+ days without activity; preserved for possible revisit or reopening. label Sep 23, 2026
@github-project-automation github-project-automation Bot moved this from Todo to Done in cmux backlog Sep 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stale-revisit Closed after 30+ days without activity; preserved for possible revisit or reopening.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants