Skip to content

[experimental] feat(runtime): add ACP harness executor - #7648

Draft
serrrfirat wants to merge 7 commits into
nearai:mainfrom
serrrfirat:codex/issue-7624-acp-harness
Draft

serrrfirat wants to merge 7 commits into
nearai:mainfrom
serrrfirat:codex/issue-7624-acp-harness

Conversation

@serrrfirat

@serrrfirat serrrfirat commented Aug 14, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Adds a neutral per-run-profile router over Arc<dyn TurnRunExecutor>, with the canonical Rust executor as its default and replaceable executor registrations.
  • Adds an ACP-only harness executor for explicitly configured profiles; it has no routing logic or knowledge of other loop implementations.
  • Separates ACP conversation logic from process placement through AgentPlacement; host and Docker placements expose the same bounded stdio and teardown contract.
  • Adds profile-agnostic routing configuration, cumulative sanitized ACP text streaming through the existing live projection, per-thread session continuity, timeout/failure handling, pinned Claude Agent ACP image/setup, CI handshake coverage, and hermetic host/Docker parity tests.
  • Experimental v0: sparse timeline, auto-approved ACP permissions, open egress, developer-supplied environment credentials, and no checkpoint/redrive support.

Change Type

  • Bug fix
  • New feature
  • Refactor
  • Documentation
  • CI/Infrastructure
  • Security
  • Dependencies

Linked Issue

Closes #7624

Validation

  • cargo fmt --all -- --check
  • cargo clippy --all --benches --tests --examples --all-features -- -D warnings — targeted clippy was started but intentionally stopped; CI will run the complete lint gate.
  • cargo build — covered through compiled test targets rather than a separate build command.
  • Relevant tests — the ACP suite passed before this streaming follow-up; the updated cumulative-chunk coverage is left to CI per request.
  • cargo test -p <owning-crate> --features integration — not applicable; this path uses the root Reborn integration harness and Docker placement test rather than a database feature gate.
  • Manual testing: real maintained @agentclientprotocol/claude-agent-acp 0.67.0 two-turn session, including cross-container session/load, plus WebUI launch.
  • If a coding agent was used and supports it, review-pr or pr-shepherd --fix was run before requesting review — deferred while this remains an experimental draft.

Test Strategy

User behavior: Given an explicitly routed profile, a turn runs through an ACP agent under host or Docker placement, streams cumulative text updates through the normal live projection, produces the normal finalized thread reply, and resumes the ACP session on the next turn. Unrouted profiles remain on the canonical loop.

Risk areas:

  • Model behavior
  • Browser
  • Side effect
  • Persistence
  • Security or permissions
  • External provider
  • Cross-component behavior

Tests added or updated:

  • Unit or contract: typed profile-route selection and duplicate rejection, configuration validation/round-trip, host environment fence, bounded UTF-8 output.
  • Reborn integration: fake ACP agent exercises routing, cumulative live text chunks, final reply, session load, permissions, timeout, process death, lease release, host placement, and Docker parity.
  • Recorded fixture: pinned initialize request and adapter handshake CI smoke.
  • Browser E2E: Not applicable; no frontend contract changed and replies use the existing finalized-message projection.
  • Backend or runtime: Docker placement runs the same fake agent assertions as host placement.
  • Live canary: Manual real-adapter two-turn host/container smoke; intentionally not a required CI test because it needs paid provider credentials.

What the tests prove: Explicit routing is opt-in; both placements share executor behavior; sessions survive process/container replacement; failures terminate without requeue; live chunks use the existing ephemeral projection and final replies use the existing durable thread path; configuration and credential/environment fences fail closed.

Commands run:

  • cargo fmt --all -- --check
  • cargo test -p ironclaw_turn_runner (254 passed; one unrelated pre-existing trace-capture queue-directory assertion failed and also failed alone)
  • cargo test -p ironclaw_turn_runner harness_turn_run_executor
  • cargo test -p ironclaw_turn_runner agent_placement
  • cargo test -p ironclaw_config
  • cargo test -p ironclaw_integration_tests --test reborn_integration_acp_harness
  • cargo test -p ironclaw_architecture_tests
  • python3.11 scripts/ci/test_reborn_pr_test_plan.py
  • python3.11 scripts/ci/test_docs_publication_boundary.py
  • python3.11 scripts/ci/docs_publication_boundary.py
  • git diff --check

Security Impact

This adds process execution, filesystem access, open network egress, and environment credential injection behind explicit configuration. Ambient environment inheritance is cleared, HOME/PATH overrides are rejected, protocol/update sizes are bounded, workspaces are keyed from typed thread IDs, Docker containers are force-removed on terminal paths, and no tenant/customer secret store is reachable from the harness configuration. ACP permission requests are auto-approved by explicit experimental policy and logged at debug level.

Reborn Trust-Boundary Checklist

  • Public policy/evidence/trust-bearing types: configuration constructs the routing and placement policy; the executor cannot mint trusted inbound requests.
  • Untrusted content enters prompts only through the existing accepted thread message path and ACP typed content blocks.
  • Hashes declare purpose; SHA-256 is used only to derive non-display per-thread workspace names.
  • New/changed status, exit, policy, runtime, or error variants: no new shared variants; existing sanitized failure categories and exit applier are reused. Audited with rg -n "TurnRunExecutor|execute_claimed_run|LoopExit" crates/loop/ironclaw_turn_runner.
  • Security/durability serde(default) fields fail closed or have migration tests: optional harness config leaves behavior unchanged; supplied config is strictly validated.
  • Queues/maps/buffers/counters have bounds and overflow-safe arithmetic: protocol lines and accumulated updates are bounded; run timeout and cleanup timeout are explicit.
  • Driver/operator-visible errors have stable class semantics: failures map to existing sanitized terminal categories.
  • Sandbox/native/host names accurately describe trust boundary: ACP executor sees AgentPlacement; Docker/Bollard details remain in ironclaw_sandbox.

Database Impact

None. ACP session identity is stored in the per-thread workspace; no schema or migration changes.

Blast Radius

Opt-in runner composition, configuration parsing, Docker sandbox process transport, thread finalization, dependency graph, and CI selection. With [harness] absent, all profiles retain the existing executor. The sandbox wrapper is intentionally a narrow HarnessContainerTemplate, not a generalized process-lane API.

Rollback Plan

Remove or disable the [harness] section to immediately restore canonical execution without data migration. Reverting this commit removes the executor, placement adapters, image, and tests; existing thread history remains valid. Per-thread ACP workspace files can be left inert or removed separately.

Review Follow-Through

This is intentionally an experimental draft for evaluating loop quality. Reviewer judgment is requested on the placement seam, credential fence, minimal event contract, streamed-update behavior, and whether findings justify a subsequent production-hardening rung. ACP text chunks now feed the existing live text projection as bounded, sanitized cumulative updates; only the finalized reply is persisted.


Review track: C (runtime/security/CI)

Live Paired Evaluation

On 2026-08-14, six isolated tasks (11 turns per lane) were run through the ACP harness and canonical Rust loop with a developer Anthropic key. Both lanes used claude-sonnet-4-6, the same committed seed regressions, and verified task-local workspaces. No local tests or external eval PRs were run or created.

Full task definitions, per-task numbers, usage, semantic findings, and isolation caveats are in docs/internal/reborn/2026-08-harness-v0-findings.md.

@github-actions github-actions Bot added scope: sandbox Docker sandbox scope: ci CI/CD workflows scope: docs Documentation scope: dependencies Dependency updates size: XL 500+ changed lines labels Aug 14, 2026
@coderabbitai

coderabbitai Bot commented Aug 14, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f3e87b54-7273-4459-a3f7-13283c328a49

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

@github-actions github-actions Bot added risk: medium Business logic, config, or moderate-risk modules contributor: core 20+ merged PRs labels Aug 14, 2026
@ironloopai

ironloopai Bot commented Aug 14, 2026 •

Copy link
Copy Markdown
Contributor

🧭 IronLoop Run · Review

This comment updates in place as the Run moves through its stages.

🟩 Final result · Completed

🟨 Queued → 🟦 Working → 🟦 Posting results → 🟩 Completed

Automatic trigger · attempt 1 of 3 · completed in 6m 2s

IronLoop completed the review and posted it to GitHub.

🔗 Result

Open submitted review →

Run details

Run: fe36ed0f-debb-4c0d-9c9a-57e522b62302
Base: main at 75d53fd
Head: codex/issue-7624-acp-harness at bcdd258
Created: 2026-08-14 09:07 UTC
Updated: 2026-08-14 09:13 UTC

@ironloopai ironloopai Bot left a comment

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.

🔍 IronLoop review

Found two actionable issues in the ACP harness security boundary and its CI coverage routing.

Findings: 🔴 High 1 · 🟠 Medium 1

🔴 High · Prevent workspace-controlled session-file link traversal

Inline on crates/loop/ironclaw_turn_runner/src/harness_turn_run_executor.rs:364. See the inline comment for details.

🟠 Medium · Route ACP wiring changes through the Docker integration lane

Inline on scripts/ci/reborn_pr_test_plan.py:187. See the inline comment for details.

Validation

  • ✅ Formatting — Workspace formatting check completed successfully.
Review details
  • Run: fe36ed0f-debb-4c0d-9c9a-57e522b62302
  • Workflow: Review
  • Attempts: 1

Comment on lines +343 to +364
match tokio::fs::read_to_string(path).await {
Ok(raw) => {
let value = raw.trim();
if value.is_empty() || value.len() > 1024 {
return Err(agent_client_protocol::Error::internal_error()
.data("persisted ACP session id is invalid"));
}
Ok(Some(SessionId::new(value.to_string())))
}
Err(error) if error.kind() == std::io::ErrorKind::NotFound => Ok(None),
Err(error) => Err(agent_client_protocol::Error::internal_error().data(format!(
"persisted ACP session id could not be read: {error}"
))),
}
}

async fn persist_session_id(
path: &Path,
session_id: &SessionId,
) -> agent_client_protocol::Result<()> {
let temporary = path.with_extension("tmp");
tokio::fs::write(&temporary, session_id.to_string())

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.

🔍 IronLoop review · Inline finding

🔴 High · Prevent workspace-controlled session-file link traversal

The ACP process has write access to this persistent workspace, so it can create `.ironclaw-acp-session.tmp` as a symlink before responding to `session/new`. The host then follows that link in `write`, allowing a Docker-contained agent to overwrite any file writable by the service account. On a later turn it can likewise symlink the session file itself and have `read_to_string` send arbitrary host-file contents back to the agent as a session ID. Keep ACP-owned state outside the agent-writable mount, or use no-follow, directory-confined file operations for both reads and writes.

"crates/kernel/ironclaw_runtime_policy/src/resolver.rs",
"crates/lanes/ironclaw_sandbox/tests/support/docker_gate.rs",
"crates/lanes/ironclaw_sandbox/tests/user_sandbox_docker_live.rs",
"crates/loop/ironclaw_turn_runner/src/agent_placement.rs",

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.

🔍 IronLoop review · Inline finding

🟠 Medium · Route ACP wiring changes through the Docker integration lane

The new selector marks the placement and executor files as Docker-sensitive, but omits the composition and runner wiring files changed by this PR. A future edit to `crates/app/ironclaw_composition/src/runtime.rs`, `runtime_input.rs`, or `crates/loop/ironclaw_turn_runner/src/runtime.rs` selects only crate buckets and skips the ACP Docker integration test; the planner currently returns `run_sandbox_docker: false` for each. Add these wiring seams to this set and extend the selector regression test, otherwise a disconnected harness setting can merge without exercising host/Docker parity.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

contributor: core 20+ merged PRs risk: medium Business logic, config, or moderate-risk modules scope: ci CI/CD workflows scope: dependencies Dependency updates scope: docs Documentation scope: sandbox Docker sandbox size: XL 500+ changed lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

v0: ACP harness executor — claude-code as the loop, dev-only yolo (#7482)

1 participant