The path was two levels up (../../) but needs three (../../../) since
the package lives at lib/packages/fabro-api-client.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Split the single cli_tests trycmd function into 14 per-subcommand test
functions so nextest can parallelize them. Delete header.toml and
verbose.toml doctor fixtures that ran live network probes — the existing
dry-run-flag.toml and help.trycmd already cover the same output assertion.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- doctor_no_color test: add --dry-run flag to skip live network probes (11s -> <1s)
- retry tests: set retry_policy=linear for 500ms delay instead of 5s default backoff
- cli_backend tests: make poll_interval configurable on AgentCliBackend, use 10ms in tests
- doctor TOML fixtures: remove status.code=1 now that dry-run doctor exits 0
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
fabro-util is a low-level crate depended on by almost everything, so its
build.rs reruns cascaded through the whole workspace. fabro-cli is the
leaf binary — nothing depends on it, so rebuilds are limited to just
that one crate.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The relative path to .git/HEAD was wrong (../../ instead of ../../../),
pointing to a nonexistent file. Cargo reruns build scripts when a
rerun-if-changed target doesn't exist, causing a full workspace rebuild
on every invocation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The assemble_pr_body function unconditionally appends the "Generated
with Fabro" footer, but this test was asserting the bare narrative.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When a human gate has only a freeform edge and no fixed choices, use
QuestionType::Freeform instead of MultipleChoice. This sends the user
directly to a text input prompt, skipping the unnecessary select menu.
Also removes the Quit choice from the REPL workflow so it uses the new
freeform-only path.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Thread the previous stage's response through `Question.context_display`
so `ConsoleInterviewer` renders it before the interactive prompt. This
lets users see the agent's response before deciding what to do next in
looping workflows like REPL.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Update default git author to Fabro <noreply@fabro.sh>. Append
"Generated with Fabro" footer to all checkpoint and metadata commits,
and to PR bodies. When the commit author is overridden, add a
Co-Authored-By trailer for attribution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rename `llm_model` → `model` and `llm_provider` → `provider` in stylesheet
properties, accessor methods, and all DOT/doc references. Add
ProviderInferenceTransform that automatically infers provider from the model
catalog, eliminating redundant provider declarations in stylesheets.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Box the Usage field in Turn::Assistant to satisfy clippy::large_enum_variant.
Rename ARC_ prefixed env vars to FABRO_ in .env.example.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Allows users to specify a reachable base URL for SSH hosts so that
get_preview_url(port) returns the correct external URL instead of
falling back to localhost.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace docs/images screenshots (runs-board, run-detail, workflow-example)
with fresh captures from the current FABRO-branded UI in demo mode.
Also fix a panic in arc-api demo::run_config_to_api where None-valued
HashMap fields (e.g. sandbox.env) serialized to JSON null, which failed
to deserialize into non-optional HashMap fields in RunConfiguration.
Added strip_nulls helper to clean the intermediate JSON value.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add `client: reqwest::Client` field (matches LinearTracker pattern); eliminates 7 per-call client constructions that prevented connection pool reuse
- Remove `graphql_url: String` field — always derivable from base_url, computed via `graphql_url()` method at each call site
- Extract `make_test_issue()` test helper to replace 3 copy-pasted Issue struct literals
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- New arc-tracker crate defines the Tracker trait and shared Issue/BlockerRef types
- arc-linear: replace Issue/BlockerRef with arc-tracker re-exports, add LinearTracker struct implementing Tracker, remove free functions
- arc-github: add GitHubTracker implementing Tracker via Projects V2 GraphQL API, with lazy project node ID resolution (org → user fallback) and create_installation_access_token_for_projects helper
- 47 tests in arc-github (15 new), 24 tests in arc-linear (updated to use LinearTracker)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Make execute_graphql private (callers use domain functions)
- Extract extract_issues() helper to deduplicate node-parsing blocks
- Replace O(n^2) .find() loop with HashMap for ID-ordered results
- Add tracing::debug on all public functions, warn on HTTP errors
- Extract BLOCKS_RELATION_TYPE constant for magic string
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
GraphQL client with 6 public functions: execute_graphql, fetch_viewer_id,
create_comment, update_issue_state, fetch_candidate_issues, and
fetch_issues_by_ids. Includes Issue/BlockerRef domain types with manual
normalization from GraphQL JSON responses.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The inherent method shadowed the identical Sandbox trait method,
creating a risk of subtle divergence if one were changed without
the other.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a generic SSH sandbox that connects to any user-provided host via
openssh, without VM lifecycle management. Supports git clone with GitHub
App credentials, configurable working directory, and arc cp reconnection.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extract duplicated compaction check+trigger blocks in the session loop into
Session::compact_if_needed(). Replace the hardcoded 20_000 token budget with
COMPACTION_USER_MESSAGE_TOKEN_BUDGET constant. Change extract_recent_user_messages
to take ownership of discarded turns instead of borrowing and cloning.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reframe the summarization prompt as creating a handoff for a different assistant
(rather than self-summarization) to produce more thorough, explicit summaries.
Add a pre-turn compaction check so context is trimmed before building the LLM
request, not just after. Extract recent user messages from discarded turns during
compaction so the model retains the user's actual words alongside tool call/result
pairs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
A workflow run hung for 33 minutes in a Daytona shell command despite
a 5-minute client-side timeout in tokio::select!. The root cause is
unknown — tests confirm the select pattern works correctly. Adding
info-level tracing at method entry (with command and timeout_ms),
after process service acquisition, and in each select arm so the
next occurrence reveals exactly where execution stalls.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Enable serde_json's preserve_order feature so Map uses insertion-order
IndexMap instead of sorted BTreeMap. Extract build_event_envelope()
from the on_event closure to deduplicate the envelope construction.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Mirrors `arc validate` workflow resolution. Shells out to `dot` (graphviz)
with friendly error if not installed. Supports --format svg|png and -o output path.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Wire ProgressUI and EventEmitter into the retro agent so it shows
stage spinners with nested tool calls, matching the look of agent
nodes in the main workflow.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Previously, AgentError::Aborted was a bare variant that displayed as
just "Aborted", making it impossible to tell whether a session was
killed by wall clock timeout, user cancellation, or something else.
Now it carries an AbortReason (WallClockTimeout or Cancelled) so
terminal output like the retro agent failure message includes the cause.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The command takes several seconds (especially with live probes) but
previously showed no output until fully complete. Now a braille spinner
animates while checks run.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Embeds the arc-create-workflow skill files via include_str! and installs them
to user (~/.claude/skills/ or ~/.agents/skills/) or project-level directories.
Supports --dir (claude|agents), --for (user|project), and --force flags.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Regenerate 2026-03-10 changelog with full commit set (installer, devcontainer
support, arc pr subcommands, --no-dotenv removal). Add 2026-03-11 changelog
for shadow branch run records and arc diff improvements. Update docs: CLI
reference (arc pr list/view/merge/close, --shortstat), devcontainers page
(replace placeholder with full content), run-configuration (devcontainer
field), checkpoints (per-node files on metadata branch), models catalog
(gemini-3.1-pro-preview-customtools). Improve preflight to show per-model
LLM checks instead of a single merged provider line.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remote sandboxes (Daytona, Exe) clone into their own environment, so
creating a local git worktree is unnecessary. The worktree decision
previously only checked worktree_mode and git_clean, ignoring the
sandbox provider entirely.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When workflow prompts tell agents to write results to a file with
embedded JSON status fields, the engine now falls back to reading the
last file the agent wrote if neither the response text nor status.json
contain extractable status fields.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Store execution trace data (prompts, responses, status, diffs, etc.) on
the shadow branch alongside checkpoint/manifest data. This makes the
shadow branch a complete, self-contained record of each run.
- scan_node_files() scans nodes/ for allowlisted files (<512KB)
- Checkpoint commits now include per-node files
- init_run includes sandbox.json
- Finalize commit after workflow writes retro.json + final node files
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use std::path::Path::strip_prefix instead of manual string manipulation,
and simplify redundant format! wrapper.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Change parallel branch entries from tool-call style (6-space indent,
spinner) to subagent info style (8-space indent, ▸ prefix, dim/static
while running). Keeps ✓/✗ glyphs on completion.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Drop `HEAD` from the live diff command so `git diff {base_sha}` compares
against the working tree instead of only committed changes. Extracts
`build_live_diff_cmd` for testability.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tool output previously showed absolute sandbox paths (e.g.
write_file(/home/daytona/workspace/output/js/physics.js)) because
shorten_path() only checked the host CWD. Now ProgressUI stores the
sandbox working directory and strips it from displayed paths, producing
cleaner output like write_file(output/js/physics.js).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When `arc run` uses a Daytona sandbox, `initialize()` re-detects the
branch from cwd — but by that point the worktree has switched HEAD to
`arc/run/{run_id}`, which was never pushed, causing the clone to fail
with HTTP 400. Pass the already-known base branch (e.g. `main`) from
the caller instead of re-detecting it inside the sandbox.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove `devcontainer_env()` and `resolve_devcontainer()` trivial wrappers,
inline at call sites
- Fix initializeCommand Args quoting: use shlex::try_quote instead of naive join
- Fix initializeCommand silently dropping Parallel commands: now executes them
- Convert three repetitive lifecycle calls to a data-driven loop
- Use crate::millis_u64() in setup command loop for consistency
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>