Commit graph

54 commits

Author SHA1 Message Date
Bryan Helmkamp
2737e6164e Add colored output to models list and test, fix clippy warnings
Add ANSI color to `arc models` and `arc models test` output when stdout
is a TTY: bold model IDs, dim provider/aliases, cyan speed, green/red
test results. Add `Styles::detect_stdout()` to arc-util.

Also fix pre-existing clippy warnings: derive Default instead of manual
impls for enums in server_config, remove unused FailureDetail imports
in arc-workflows error tests, inline print literal in test_models header.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-03 14:49:02 -05:00
Bryan Helmkamp
7c8ef76d4c Use claude-haiku-4-5 alias instead of dated snapshot ID
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-03 14:31:38 -05:00
Bryan Helmkamp
8168c85ac9 Extract sandbox/daytona resolution helpers, fix preflight defaults bug
Extract parse_sandbox_provider, resolve_sandbox_provider, and
resolve_daytona_config helpers to eliminate 4 near-identical sandbox
parsing chains. Compute sandbox_provider once with proper error handling
instead of twice (preview silently swallowed errors). Fix bug where
run_preflight did not fall back to run_defaults for daytona config.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-03 01:34:36 -05:00
Bryan Helmkamp
e3fa99eba1 Add run defaults to server config for workflow run inheritance
Rename AppConfig → ServerConfig with flattened RunDefaults so users can
set default llm, sandbox, setup, directory and vars in ~/.arc/arc.toml.
Precedence: CLI flags > workflow TOML > server config defaults > DOT
graph attrs > hardcoded defaults. Vars merge (defaults first, task
config overwrites collisions).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-03 01:26:41 -05:00
Bryan Helmkamp
c888ab8be5 Rename TaskConfig → WorkflowRunConfig, task → goal
Better reflects domain semantics: the config describes a workflow run,
and the free-text field is the run's goal, not a generic "task".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 00:44:24 -05:00
Bryan Helmkamp
3b2c0de11a Simplify preflight: remove dead RunMode enum, fix stringly-typed provider matching
- Remove RunMode enum (only Preflight was checked; DryRun/Normal unused)
  — use args.preflight directly
- Switch default_model_for_provider() to take Provider enum instead of
  Option<&str> for exhaustive matching; adds missing Inception default
- Extract sandbox init/cleanup into creation + single check pattern,
  eliminating 3x copy-paste of identical init/cleanup boilerplate
- Replace setup_commands Vec clone with direct count (only .len() used)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 23:54:02 -05:00
Bryan Helmkamp
74cd6bc791 Add --preflight flag to arc run start for config validation without execution
Verifies sandbox boot (local/docker/daytona), LLM provider availability,
and model/provider resolution chain, then prints a structured report.

Extracts model/provider resolution into reusable helpers
(default_model_for_provider, resolve_model_provider) with tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 23:42:54 -05:00
Bryan Helmkamp
ffac356c7b Add pass numbering to parallel branch names to prevent overwrites on retry
Parallel branches now include the node visit count (pass1, pass2, etc.)
in their ref names, preventing silent overwrite when a parallel node is
re-executed via retry or loop_restart.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-02 22:02:43 -05:00
Bryan Helmkamp
e911a60220 Fix useless format! clippy warning in asset_snapshot
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-02 22:00:55 -05:00
Bryan Helmkamp
cffb00bcdb Carry typed errors through the entire stack instead of stringifying early
- AgentError gains Clone + Serialize/Deserialize with tagged serde format
- ArcError::Handler/Engine become struct variants with eager FailureClass
  classification via smart constructors handler()/engine()
- Outcome replaces failure_reason: Option<String> with failure: Option<FailureDetail>
  carrying message, failure_class, and failure_signature together
- AgentEvent::Error/LlmRetry/SubAgentFailed carry typed AgentError/SdkError
  instead of pre-stringified error messages
- WorkflowRunEvent::WorkflowRunFailed carries ArcError; StageFailed/StageCompleted
  carry FailureDetail instead of separate string fields
- classify_outcome() trivially reads from FailureDetail; circuit breaker reads
  failure_signature from FailureDetail instead of context_updates hack
- flatten_event() decomposes structured errors into flat fields for progress.jsonl
  backward compatibility

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-02 21:53:23 -05:00
Bryan Helmkamp
00145424a5 Consolidate artifacts and assets under unified directory layout
Rename node visit suffix from `-attempt_{V}` to `-visit_{V}` and move
asset collection under `artifacts/assets/` alongside artifact values in
`artifacts/values/`. Retry directories use `retry_{N}` instead of the
ambiguous `attempt_{N}`.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 20:31:21 -05:00
Bryan Helmkamp
67652ad480 Add generic asset snapshot collection for workflow node outputs
Automatically discovers and collects well-known output files (test reports,
screenshots, trace files) from each node's execution into its log directory.
Works across all three sandbox types (local, Docker, Daytona) via a new
`download_file_to_local` trait method that handles binary files correctly.

- New `asset_snapshot` module with pure functions for find command generation,
  output parsing, candidate matching, and budget enforcement
- `Sandbox::download_file_to_local` implemented for Local (fs::copy),
  Docker (host bind-mount resolution), and Daytona (SDK download)
- `AssetsCaptured` event variant with DEBUG-level tracing
- Engine integration: baseline snapshot before handler, collection after
  (both success and error paths), non-fatal on errors
- E2e tests for local sandbox (2 tests), Docker (#[ignore]), Daytona (#[ignore])

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 19:58:08 -05:00
Bryan Helmkamp
c560c608e2 Rename progress.jsonl fields for clarity
Add node_id to Stage* enum variants so both the programmatic ID and
display label are available. Add rename_fields() post-processing in
flatten_event() to give flattened JSONL fields self-describing names:

- timestamp → ts (save space)
- name → node_label (Stage*), workflow_name, snapshot_name
- index → stage_index, branch_index, command_index
- stage → node_id (Agent.*, Interview*, Prompt)
- branch → node_id (ParallelBranch*)
- node → node_id (StallWatchdogTimeout)
- from_node/to_node → from_node_id/to_node_id
- start_node → start_node_id
- provider → sandbox_provider (Sandbox.*)
- text → prompt_text (Prompt)
- Insert node_label defaulting to node_id where only an id exists

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 19:11:33 -05:00
Bryan Helmkamp
b4f1495982 Avoid data loss in SubAgentEvent flattening
Instead of flattening the inner event's fields into the top level
(which causes collisions when SubAgentEvent wraps SubAgentEvent —
losing inner agent_id, depth, and nested event body), keep the inner
event as a `nested_event` JSON value. The dot-notation event name
still reflects the inner type for easy filtering.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-02 18:29:28 -05:00
Bryan Helmkamp
eb195a0be9 Skip envelope-colliding keys when merging flattened event fields
WorkflowRunStarted and GitCheckpoint have a `run_id` field that
collides with the envelope's top-level `run_id`. Filter out
`timestamp`, `run_id`, and `event` from event fields to avoid
duplicate keys in the JSONL output.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-02 18:26:54 -05:00
Bryan Helmkamp
62b54c8f4d Flatten progress.jsonl event format to top-level fields
Event data was nested inside a tagged enum (`"event": {"StageStarted": {fields}}`).
Now `event` is a string name and fields merge into the top-level object
(`"event": "StageStarted", "name": "plan", ...`).

Nested events use dot notation:
- Agent wrapper: "Agent.ToolCallStarted" with stage at top level
- Sandbox wrapper: "Sandbox.Initializing" with fields at top level
- SubAgentEvent: "Agent.SubAgentEvent.ToolCallStarted" flattened one level

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-02 18:25:27 -05:00
Bryan Helmkamp
effe165f31 Simplify -v flag from two verbosity levels to a single boolean
The `-vv` (full detail) mode was not useful in practice. This collapses
the two-tier `-v`/`-vv` into a single `--verbose` boolean and removes
the now-dead `format_event_detail` function and its tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-02 12:29:29 -05:00
Bryan Helmkamp
6dd422186e Rename progress.ndjson to progress.jsonl
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-02 11:46:31 -05:00
Bryan Helmkamp
79d97ebb5c Fix stale labels, grammar, and comments from sandbox rename
- Fix display label `image:` → `name:` for SnapshotPulling/SnapshotPulled
  in format_event_detail
- Fix grammar: "an Sandbox" → "a Sandbox" in README and parallel.rs
- Fix typo: "sandboxs" → "sandboxes" in parallel.rs
- Update remaining "execution environment" comments to "sandbox"

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-02 11:43:34 -05:00
Bryan Helmkamp
d0c8bd3eed Rename ExecutionEnvironment to Sandbox across the codebase
Adopt cleaner terminology: Sandbox (resource providing disk + execution),
SandboxProvider (Local/Docker/Daytona), SandboxEvent (lifecycle events),
and Snapshot (pre-built environment images). Flatten DaytonaSandboxConfig
into DaytonaConfig, rename CLI flag to --sandbox, and update TOML config
sections from [execution] to [sandbox].

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-02 11:33:21 -05:00
Bryan Helmkamp
ffa9d1d505 Rename docs site from Mint Starter Kit to Arc
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-02 11:21:33 -05:00
Bryan Helmkamp
212de7a7ea Rename Pipeline to Workflow/Run in arc-workflows engine internals
- pipeline.rs → workflow.rs: PipelineBuilder → WorkflowBuilder,
  prepare_pipeline() → prepare_workflow()
- event.rs: PipelineEvent → WorkflowRunEvent, variant renames
  PipelineStarted/Completed/Failed → WorkflowRunStarted/Completed/Failed
- engine.rs: PipelineEngine → WorkflowRunEngine, pipeline_name → workflow_name
- retro.rs: pipeline_name → workflow_name, pipeline_failed → run_failed
- All handler, CLI, and test files updated to match

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 23:58:42 -05:00
Bryan Helmkamp
7002f0638a Rename ManagerLoopHandler to SubWorkflowHandler
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 23:39:58 -05:00
Bryan Helmkamp
f45c1b1e2d Remove unused SubPipelineHandler
No DOT pipelines reference the sub_pipeline handler type. The manager
loop handler now covers the child pipeline spawning use case.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 23:38:53 -05:00
Bryan Helmkamp
47e16d4c0d Replace ChildObserver mock with real child engine spawning in ManagerLoopHandler
The manager loop (house node) now parses a child DOT pipeline, spawns a
real PipelineEngine, and monitors it via a tokio::select poll loop. Context
is cloned into the child and diffed on completion to propagate updates back
to the parent.

- Add PipelineEngine::from_services() to share parent's Arc services
- Add PipelineEngine::run_with_context() returning (Outcome, Context)
- Rewrite ManagerLoopHandler as unit struct with real child engine spawning
- Support both inline DOT (stack.child_dot_source) and file (stack.child_dotfile)
- Delete ChildObserver trait entirely
- Update all existing tests and add new e2e tests for context flow and dotfile

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 23:35:47 -05:00
Bryan Helmkamp
f6bc346663 Fix remote parallel worktree path to mirror host structure
Replace hardcoded /home/daytona/workspace/.arc-parallel path with
{working_directory}/.arc/logs/{run_id}/parallel/{node_id}/{branch_key},
matching the host worktree layout and scoping worktrees per-run.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 22:27:56 -05:00
Bryan Helmkamp
b2b64dcc64 Restructure CLI: nest runs under arc run, promote models to top-level
- `arc run <pipeline>` → `arc run start <pipeline>`
- `arc runs list/prune` → `arc run list/prune`
- `arc llm models list` → `arc models list`
- Remove `arc llm models sync`
- Add `arc models test [--provider, --model]` for connectivity testing
- Clean up dead code (RunsArgs, RunsCommand, runs_command)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 22:04:32 -05:00
Bryan Helmkamp
95864ab788 Add run labels and arc runs list/prune CLI
- Add `labels: HashMap<String, String>` to RunConfig, written to manifest.json
- Add `--label KEY=VALUE` flag to `arc run` (repeatable)
- New `arc runs` command: list pipeline runs with table or --json output
- New `arc runs prune` command: delete old runs with --before, --pipeline,
  --label, --orphans filters (dry-run by default, --yes to confirm)
- 13 new tests covering scan_runs, filter_runs, prune, and manifest labels

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 20:23:26 -05:00
Bryan Helmkamp
c860bc3e35 Suppress clippy::too_many_arguments on derive_retro
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 19:47:08 -05:00
Bryan Helmkamp
d7d2294b7c Add structured tracing across 7 crates per logging audit plan
Implements all 47 gaps and fixes all 7 violations identified in
docs/agent/logging-audit-plan.md:

- arc-llm: Add tracing dep + 18 log statements (requests, responses,
  retries, timeouts, tool execution)
- arc-api: Add tracing dep + 6 log statements (server lifecycle,
  pipeline start/complete/fail), replace eprintln with warn
- arc-mcp: Fix 3 violations (string interpolation, secret leakage),
  add 7 log statements (client creation, handshake, tool calls)
- arc-workflows: Fix 3 eprintln violations, add 9 log statements
  (git checkpoints, Daytona sandbox, worktrees, node visit limit)
- arc-git-storage: Add tracing dep + 9 log statements (branch ops,
  snapshot write/delete/rename)
- arc-db: Add 3 log statements (connection, migrations)
- arc-agent: Add 4 debug statements (session init, compaction)
- arc-cli: Add 1 debug statement (command dispatch)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 19:43:19 -05:00
Bryan Helmkamp
38da286130 Add stall watchdog to detect hung pipeline handlers
A background tokio task polls EventEmitter.last_event_at(). When idle
time exceeds the graph-level stall_timeout (default 600s), it cancels
a CancellationToken that races against execute_with_retry via
tokio::select!, dropping the hung handler future.

- EventEmitter: AtomicI64 last_event_at field, touch() to seed, emit()
  auto-updates
- Graph::stall_timeout(): reads Duration attr, defaults 600s, None for 0
- StallWatchdogTimeout event variant with warn-level trace()
- Engine: watchdog spawn before main loop, select! at handler call,
  shutdown after loop
- CLI: format arms for summary and detail views
- Unit tests for emitter, graph accessor, event serialization, and
  engine watchdog behavior (hung, keepalive, disabled)
- E2e integration tests: DOT-parsed pipelines with 100-200ms stall
  timeouts verifying trigger, keepalive, disable, and timing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 19:36:58 -05:00
Bryan Helmkamp
ec70be1e0d Add trace() method to event enums for structured file logging
Every emitted event now produces a structured tracing log line so
developers can debug after the fact via ~/.arc/logs/. Each event
variant gets an appropriate log level (info/debug/warn/error) with
structured fields. Streaming noise variants (TextDelta,
ToolCallOutputDelta) are no-ops, and wrapper variants (Agent,
ExecutionEnv on PipelineEvent) delegate to the inner event's trace.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 19:15:43 -05:00
Bryan Helmkamp
5ea508a5ca Add stable failure signature hints for model errors
SdkError now produces hand-crafted signature hints (e.g.
"api_deterministic|openai|authentication") that are identical regardless
of error message wording, replacing fragile regex-normalized signatures
for API errors. ArcError.to_fail_outcome() centralizes fail outcome
construction with failure_class and failure_signature context_updates.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 19:12:29 -05:00
Bryan Helmkamp
e87ca6a8af Block non-transient_infra failures from loop_restart and fix UTF-8 truncation
Guard loop_restart edges to only allow transient_infra failures, matching
Kilroy's behavior. Non-transient failures (deterministic, structural,
budget_exhausted, canceled, compilation_loop) are now blocked immediately
instead of getting restart attempts before the circuit breaker fires.

Fix normalize_failure_reason truncation to use floor_char_boundary(240)
instead of a raw byte slice, preventing panics on multi-byte UTF-8 chars.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 19:00:39 -05:00
Bryan Helmkamp
b18641277b Align max_node_visits to use >= like circuit breakers, matching Kilroy
max_node_visits used > while signature circuit breakers used >=, creating
an inconsistency where "limit" meant different things depending on the
mechanism. Kilroy uses >= for all three checks. This aligns Arc to match.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 18:29:26 -05:00
Bryan Helmkamp
1a95cd6664 Rename AgentBackend → AgentApiBackend and CliBackend → AgentCliBackend
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 18:14:25 -05:00
Bryan Helmkamp
a535c6575f Rename kilroy → attractor in test directory and compat tests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 18:10:22 -05:00
Bryan Helmkamp
3c7b786ed1 Apply cargo fmt formatting
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 18:08:49 -05:00
Bryan Helmkamp
cab25a3e7e Add failure signatures and circuit breakers for deterministic failure cycle detection
Introduces reason normalization (strip variable data like line numbers,
hex hashes), composite failure signatures (node_id|class|normalized_reason),
and circuit breakers that track signature counts to abort when the same
deterministic failure repeats beyond a configurable limit (default 3).

Key additions:
- normalize_failure_reason() strips hex, digits, whitespace for stable grouping
- FailureSignature type with handler-provided hint priority
- FailureClass::is_signature_tracked() (deterministic + structural only)
- Graph-level loop_restart_signature_limit attribute
- LoopState struct bundling node_visits + signature maps through run_internal
- Loop failure circuit breaker (same node repeating)
- Restart failure circuit breaker (across loop_restart edges)
- Checkpoint persistence for both signature maps with backward compat
- 18 e2e integration tests covering all circuit breaker scenarios

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 18:03:09 -05:00
Bryan Helmkamp
24b454b145 Fix retro error handling and add Session wall-clock timeout
- Add wall_clock_timeout field to SessionConfig that spawns a tokio timer
  to cancel the session after a duration, reusing existing Aborted path
- Set 120s wall-clock timeout on retro agent to prevent unbounded runs
- Replace silent `let _ =` with logged warnings for checkpoint load and
  retro save failures
- Reuse LLM client from initial from_env() call instead of creating a
  second one for the retro agent
- Extract retro generation into generate_retro() helper and call it from
  both run_command and run_from_branch (resume path)
- Tolerate mutex poisoning in retro agent with unwrap_or_else

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:39:13 -05:00
Bryan Helmkamp
ab53e87915 Harden git checkpoint and worktree operations for idempotent retry
- Add git_cmd() helper disabling maintenance.auto and gc.auto on all
  host-side git commands; add GIT_REMOTE constant for remote commands
- Use --force on branch creation for idempotent retry/resume
- Add replace_worktree() that does best-effort remove before add
- Add reset_hard() after parallel worktree setup for deterministic state
- Add sanitize_ref_component() to clean node IDs in branch names
- Add git_replace_worktree_remote() for remote sandbox environments
- Add tests for sanitize_ref_component, replace_worktree, reset_hard

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-01 17:15:51 -05:00
Bryan Helmkamp
3adecf41bc Exercise full retro path in dry-run mode
Instead of skipping the retro agent entirely in dry-run, use a
placeholder narrative so derive → apply_narrative → save all run.
This catches bugs in the merge/persistence path without LLM calls.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 15:47:40 -05:00
Bryan Helmkamp
73b00f047b Add per-run retrospectives with LLM-powered retro agent
After each pipeline run, auto-derive stats from the checkpoint (stages,
retries, cost, files touched) then run an Opus agent session that
explores progress.ndjson to produce qualitative analysis: smoothness
rating, intent, outcome, learnings, friction points, and open items.

Backend:
- retro.rs: data model, save/load, derive_retro(), extract_stage_durations()
- retro_agent.rs: post-pipeline agent session with submit_retro tool
- cli/run.rs: hook retro generation after final.json, before engine_result?
- server.rs: GET /pipelines/{id}/retro endpoint, auto-derive on completion

Frontend:
- data/retros.ts: TS types + mock data + smoothness color config
- routes/retros.tsx: list page with smoothness badges
- routes/run-retro.tsx: detail view (stats, intent, stages, learnings)
- routes.ts + run-detail.tsx: wire up retro route and tab

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 15:46:02 -05:00
Bryan Helmkamp
4dd2980a56 Add parallel git branching with per-branch worktree isolation
Parallel branches now get isolated git worktrees so concurrent file
writes don't collide. Works across Local, Docker (bind-mount), and
Daytona (remote exec_command) environments.

Key changes:
- git.rs: add create_branch_at() and merge_ff_only() helpers
- engine.rs: add GitState struct, remote worktree helpers
  (git_create_branch_at_remote, git_add_worktree_remote, etc.)
- handler/mod.rs: add git_state field to EngineServices (RwLock)
- handler/parallel.rs: WorktreeEnv wrapper, per-branch worktree
  setup/teardown, checkpoint commits per branch, ff-merge winner
  before returning to engine
- handler/fan_in.rs: ff-merge to winner's HEAD, set best_head_sha
- E2E tests for Host (local) and Daytona (remote) modes

When git_state is None, behavior is unchanged.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-01 14:24:00 -05:00
Bryan Helmkamp
517f5faed3 Add alias normalization for FailureClass parsing
LLM-authored output can set failure_class to non-canonical strings like
"retryable", "transient", or "permanent". Expand FromStr to accept 30+
aliases with case-insensitive trimmed matching, matching Kilroy's
normalizedFailureClass(). Unknown values fail-closed to Deterministic
instead of returning Err.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 13:46:48 -05:00
Bryan Helmkamp
4c75f2b67f Add script_absolute_cd lint rule to warn on absolute cd paths in scripts
Absolute `cd` paths in shell commands (script/tool_command attributes) silently
override the engine's worktree CWD, breaking portability across machines,
containers, and worktrees. Ported from kilroy (danshapiro/kilroy d9c1fec).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 13:20:13 -05:00
Bryan Helmkamp
24cff30518 Fix clippy warnings, test failures, and apply cargo fmt
- Fix 4 test failures: add unconditional fallback edges to branching.dot
  and conditions.dot to satisfy all_conditional_edges validation rule
- Fix clippy await_holding_lock: scope MutexGuard before await in
  daytona_integration.rs
- Fix clippy unnecessary_get_then_check: use contains_key in script.rs
- Fix clippy expect_fun_call: use unwrap_or_else in integration.rs
- Run cargo fmt across entire workspace

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 13:02:16 -05:00
Bryan Helmkamp
5dfc72316f Align failure classification with Kilroy reference implementation
Add 8 missing transient_infra patterns (crates.io registry, toolchain,
cross-device link errors), 2 structural hints (write_scope_violation
variants), and reorder heuristic priority to check transient_infra
before budget_exhausted to match Kilroy's classification behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 12:56:33 -05:00
Bryan Helmkamp
1e07fc0b09 Bump Anthropic max_tokens default and add per-node max_tokens override
Raise the Anthropic adapter fallback from 4096 to 16384 to prevent
truncation of large tool call JSON when the model isn't in the catalog.

Add max_tokens as a configurable DOT node attribute that flows through
SessionConfig to LLM requests, following the same pattern as
reasoning_effort. Priority: node attribute > catalog > provider default.

Ported from kilroy (danshapiro/kilroy) commits 99a5cd7 and 78fadad.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 12:54:23 -05:00
Bryan Helmkamp
ebc1d5ea6a Expand failure classification patterns and add regression tests
Extract hint patterns into const arrays (TRANSIENT_INFRA_HINTS,
BUDGET_EXHAUSTED_HINTS, STRUCTURAL_HINTS) and add 28 new patterns
from Kilroy to prevent transient/budget failures from misclassifying
as deterministic. Add comprehensive regression test per pattern plus
count-guard tests to catch accidental additions/removals.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 12:29:38 -05:00