Agents
An agent in ASF50 is a role-bound actor. Each run is dispatched with a role and an adapter. The role determines capability boundaries (allowed_paths, forbidden_paths, allowed commands); the adapter determines how the work is actually performed.
Roles
The canonical role set is declared in agent-harness/roles/. Each role has its own constraints:
| Role | Purpose |
|---|---|
PLANNER | Reads canonical sources, emits a child task graph. |
BUILDER | Implements the bounded scope; runs bounded tests. |
TEST_ENGINEER | Runs the test suite; produces evidence. |
INDEPENDENT_AUDIT_HIGH | Fresh-context auditor of a specific audit target. |
INDEPENDENT_DOCS_AUDITOR | Independent accuracy auditor for documentation. |
RELEASE_MANAGER | Performs governed merge and deployment. |
REPAIRER | Executes a bounded repair against a frozen target. |
ARCHITECT | Produces architecture-level decisions. |
GOAL_OWNER | The human owner of the goal (offline). |
A Builder cannot review, audit, or release its own work. The role-separation rule is enforced by the orchestrator and by the goal_registry.REQUIRED_FIELDS validator (via the required_role field).
Adapters
An adapter is a concrete implementation of an invoke(request) -> result function. ASF50 ships:
| Adapter | Use |
|---|---|
deterministic | In-process stub; always returns PASS. Used for bootstrap and tests. |
deterministic-cli | Runs a real subprocess for non-AI side effects. |
claude_cli | Anthropic Claude CLI. PAID_MODEL_DISPATCH_APPROVAL required. |
codex_cli | OpenAI Codex CLI. PAID_MODEL_DISPATCH_APPROVAL required. |
cursor_cli | Cursor CLI. PAID_MODEL_DISPATCH_APPROVAL required. |
fake_agent | Test harness. |
The model router resolves which adapter a goal may use, gated by the PAID_MODEL_DISPATCH_APPROVAL scope.
Worktrees
A worktree is a detached Git working tree used to isolate a single dispatch. Worktrees are managed by scripts/goal-runner/worktree_manager.py. Two-root contracts (INDEPENDENT_AUDIT_HIGH) require both a dispatch worktree and an audit worktree pinned at the audit subject SHA; one-root contracts use the dispatch worktree only.
The worktree_policy field of a goal contract declares:
worktree_policy:
mode: CLEAN_DETACHED | BRANCH_SHARED | REPAIR_PINNED
source_commit: "<40-char SHA>"
CLEAN_DETACHED— create a fresh detached worktree pinned atsource_commit.BRANCH_SHARED— create a branch-based worktree; the goal owns the branch.REPAIR_PINNED— the goal targets a frozen subject and may not advance HEAD.
Concurrency
ASF50 is single-agent sequential by default. MAX_ACTIVE_AI_AGENT_COUNT = 1. There is no parallel Builder, no parallel Auditor, no parallel Repairer. A fresh Independent Auditor context is logically separate but sequentially dispatched.
If you see the orchestrator attempting parallel AI dispatches, that is a policy violation and must be reported in the receipt.
Dispatch consumption
When a goal needs a paid model, the orchestrator reserves a gate from the runtime store. The reservation is recorded against owner_gates.last_dispatched_run_id and reservation_run_id. After the run finishes, the gate is either consumed or returned; the receipt records which.