Previously, `arc validate` passed .toml files directly to the DOT parser,
causing a cryptic "grammar error: Tag" parse failure. Now it resolves the
graph path from the TOML config, matching `arc run` behavior.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The Rust SandboxConfig struct has a `local` field that was missing from
the OpenAPI spec, causing server_config_keys_match_openapi_spec to fail.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Disable the osxkeychain credential helper during programmatic pushes
so only inline URL credentials are used. This prevents potential
interference from stale stored credentials causing "Repository not
found" errors on private repos.
Also upgrade the log line to INFO with a redacted URL for better
diagnostics when pushes fail.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add extra parent() traversal in build.rs, include_str!, and test
fixture paths that navigate from crate directories to the repo root.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Updated: package.json workspaces, tsconfig path alias, CI workflow
paths, Dockerfile COPY, AGENTS.md, and doc references.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Updated: Cargo.toml workspace members, CI workflow paths, Dockerfile
COPY, AGENTS.md, skill mapping, and doc references.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update build context, dockerfile path, and volume mounts in
docker-compose.yaml to account for the new location.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add build/test/lint commands for Rust and TypeScript, crate descriptions,
key design patterns, and progressive-disclosure references to the logging
and events strategy docs in docs-internal/.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Local worktree sandbox runs never pushed the arc/run/{run_id} branch to
GitHub, causing PR creation to fail with a 422 "head invalid" error.
Remote sandbox runs already push during checkpoint, so this only fires
for GitCheckpointMode::Host.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Shows "Base: main (260a391e5b4c)" after the Worktree line in the run
header, helping users identify the starting point. Uses worktree base
SHA when available, falls back to remote base SHA for remote-only runs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract `embed_token_in_url` and `resolve_authenticated_url` helpers
into arc-github to eliminate duplicated credential resolution + URL
authentication logic across ExeSandbox, DaytonaSandbox, and engine.rs.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move GitHub App authentication (types, JWT signing, token creation,
credential resolution) into a new leaf crate `arc-github`. ExeSandbox
now owns `github_app` directly and resolves clone credentials on-demand,
eliminating the GitCredentialSandbox decorator and its wrapping code in
cli/run.rs. GitCloneParams simplified to a single clean `url` field.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- WorktreeSandbox: add missing delegations for is_remote(),
ssh_access_command(), and origin_url() to avoid silently returning
defaults instead of delegating to inner sandbox
- GitCredentialSandbox: replace manual shell quoting with shlex::try_quote
per project shell_quote() convention
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add is_remote(), ssh_access_command(), and origin_url() to the Sandbox
trait so run.rs can use trait methods instead of matching on
SandboxProvider post-construction. This removes daytona_sandbox_ref and
exe_sandbox_ref, eliminating 11 provider-checking sites that reached
through Arc<dyn Sandbox> to make provider-specific decisions.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract `load_sandbox()` helper to deduplicate cp_command's Download/Upload arms
- Use `shlex::try_quote` in handler/command.rs shell_quote (was using less safe manual quoting)
- Call `self.resolve_path()` in ExeSandbox::upload_file_from_local instead of inlining
- Create parent dirs in download_recursive for nested files
- Use async `entry.file_type().await` instead of blocking `is_dir()` in upload_recursive
- Add missing parent directory creation in DaytonaSandbox::upload_file_from_local
- Rename `_worktree_path` to `worktree_path` (variable is used, underscore was misleading)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Allow customizing when git worktrees are created via a new `worktree_mode`
enum (always/clean/dirty/never) in `[sandbox.local]`. Previously, worktree
creation was hardcoded to only occur on clean repos.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- E2e tests for local, Docker, and Daytona sandbox backends
- Make cp::reconnect pub for integration test access
- Stop deleting worktrees after run completion so arc cp can
access local/Docker sandbox files (prune step to come later)
- Rustfmt cleanups
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Introduces sandbox reconnection via persisted SandboxRecord, adds
upload_file_from_local to the Sandbox trait, and migrates arc-sprites
shell quoting to shlex::try_quote.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add `image` property to OpenAPI `ExeConfiguration` schema so the
generated TS client gets a typed interface instead of bare `object`
- Extract `resolve_exe_clone_params()` helper and wire it into preflight
so `--preflight --sandbox exe` tests the git clone path
- Expand `run_from_branch()` to support exe.dev: resolve sandbox provider,
connect SSH, initialize VM, fetch+checkout the run branch, wrap with
GitCredentialSandbox + ReadBeforeWriteSandbox, and clean up on exit
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace ad-hoc replace('\'', "'\\''") escaping and unquoted interpolation
with a shell_quote() helper backed by shlex::try_quote to prevent command
injection via branch names, clone URLs, image names, env vars, file paths,
and grep patterns. Covers both arc-exe (SSH transport) and arc-workflows
(Daytona sandbox).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add image field to ExeConfig so users can specify a Docker image for
exe.dev VMs via TOML config. Pass run_id to ExeSandbox for VM-to-run
correlation in sandbox_info(). Wire resolved exe config into the
preflight path for consistency with the main execution path.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace fragile shell escaping in exec_command with base64 encoding
(matching Daytona's wrap_bash_command pattern)
- Add ssh_command() to ExeSandbox and wire --ssh flag support in run.rs
- Move git cloning into ExeSandbox::initialize() via GitCloneParams,
removing clone_repo_into_exe() from run.rs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Ephemeral sandboxes never reuse the incremental cache, so writing it
is pure waste (~2.8 GB). Setting CARGO_INCREMENTAL=0 avoids that.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Subagent lines (▸ subagent[...], ✓ subagent[...]) now render at 8-space
indent instead of 6, visually distinguishing them as children of the stage.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Wire up cancel_token in ExeSandbox::exec_command via tokio::select!
- Clone the local git repo into exe.dev VMs after initialization
- Add GitCredentialSandbox decorator for push credential refresh
- Enable GitCheckpointMode::Remote for exe.dev (rename daytona_* → remote_*)
- Rename setup_daytona_git → setup_remote_git (already sandbox-agnostic)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace `.filter(..).next_back()` with `.rfind(..)` to satisfy the
expanded `clippy::filter_next` lint on newer toolchains.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Allow setting pull_request.enabled in ~/.arc/cli.toml so auto-PR
works when running `arc run` with a .dot file (no run.toml needed).
Cascade precedence: run.toml > cli.toml > server.toml > defaults.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The cargo test preflight step is slow and unnecessary since the verify
step already runs tests after implementation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The old code called child.wait() before draining stdout/stderr pipes.
If the child wrote more than the OS pipe buffer, write() blocked while
the parent blocked on wait() — classic deadlock. Now we spawn concurrent
tasks to drain the pipes before waiting.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The opt-in change (7400a9d5) left these two tests with empty asset_globs,
which now means "no asset collection". Add the matching glob so the tests
actually exercise asset collection.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Asset collection previously ran a full `find` scan before and after every
stage (~30s per scan), even when no assets were needed. This makes it
opt-in: only workflows with an `[assets] include = [...]` section in their
TOML config will run asset collection, and only with user-specified globs.
- Add AssetsConfig struct and wire through WorkflowRunConfig, RunDefaults,
and RunConfig
- Remove baseline snapshot approach; single post-execution scan using
user globs filtered by mtime and size budgets
- Delete hardcoded pattern constants, is_asset_candidate, matches_simple_glob,
FileFingerprint, and snapshot() — replaced by configurable globs
- Skip all asset work when asset_globs is empty (zero overhead default)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>