Run a governed coding task
Repair a bug from one selected commit and hand a recipient a patch they verify before applying it.
On this page
Hand a coding agent one committed slice of your repository and get back a patch whose signed record the recipient checks before it touches their checkout.
The session imports the selected commit into a private workspace. A process worker calls separately authorized model and repository tools, and the result command exports the patch with its original signed receipts. Your checkout keeps its dirty and untracked files, and applying the patch stays a separate decision.
StartEdit selected committed content in a separate workspace
The session starts from the paths you select at one commit. It edits and runs tests in its own task workspace, and the original checkout keeps its dirty and untracked files untouched. What leaves is a patch with signed evidence, which a recipient verifies and applies in a checkout it chooses.
Drawn fromcoding/qualify_repository.py
1. Build the worker and execution images
The operator supplies a runtime profile for three installed Docker images: the coding worker, the repository command environment, and the snapshot helper. The worker receives neither provider credentials nor Docker access; the trusted model gateway and repository service hold those on the operator side.
Before you begin
Use Linux, Chio, Python 3.11+, uv, and a local Docker engine with cgroup v2 and Docker's built-in seccomp profile, as a non-root operator. Download coding.zip, extract it, work from coding/, and run uv sync. The operator setup describes the images, runtime.json, and provider configuration.
The session refuses a Python installation that other users can write, including through a writable parent directory. Keep the operator environment under your own account and install packages normally; the walkthrough uses no wheel paths or permission-repair script.
docker build -f operator/worker.Dockerfile -t chio-coding-worker .
docker build -f operator/execution.Dockerfile -t chio-coding-python .
uv run chio-mini-swe runtime-profile \
--worker-image chio-coding-worker \
--execution-image chio-coding-python \
--helper-image python:3.11-slim --out runtime.jsonYou should see runtime.json with the immutable ID of each installed image. The Dockerfiles install the coding entry point and the Python, Bash, Git, and timeout tools the task uses. The profile command inspects images already installed; it pulls nothing and leaves running sessions as they are. Repository commands run without network access, so the command image carries every project dependency; this sample uses only Python's standard library.
2. Commit the sample and its bug
The sample has one bug: add subtracts its arguments. The task asks the agent to fix it and keep the tests, which makes the patch easy to review before you assign a larger repository. The project README lists the application files and the recovery tests.
def add(a, b):
return a - bimport unittest
from calculator import add
class Addition(unittest.TestCase):
def test_positive(self):
self.assertEqual(add(2, 3), 5)
def test_negative(self):
self.assertEqual(add(-2, -3), -5)
if __name__ == "__main__":
unittest.main()uv sync
git -C sample init
git -C sample add package
git -C sample commit -m "Add calculator exercise"You should see one commit in sample/ holding the package/ subtree. Git records it under your configured author identity; only committed content becomes session input.
3. Bind the task to the commit and its scope
session.json selects the sample repository, its committed package/ subtree, the runtime profile, and the agent's limits. Initialization resolves HEAD to an exact commit, and issue.md carries the task text.
{
"schema": "chio.mini-swe.session-config.v3",
"chio": "chio",
"repository": "sample",
"revision": "HEAD",
"source_paths": [
"package"
],
"provider_config": "provider.json",
"runtime_profile": "runtime.json",
"command_timeout_seconds": 90,
"agent": {
"system_template": "Repair the repository using bash commands. Validate the change. Submit by running a command whose output starts with COMPLETE_TASK_AND_SUBMIT_FINAL_OUTPUT, followed by your summary.",
"instance_template": "{{task}} Work in these repository paths: {{source_paths}}",
"step_limit": 8,
"cost_limit": 1,
"wall_time_limit_seconds": 600
},
"max_attempts": 2,
"timeout_seconds": 300,
"max_calls": 32,
"capability_ttl_seconds": 3600
}The calculator's add function subtracts instead of adding. Fix the function in
package/calculator.py. Preserve the tests and run them to verify positive and
negative inputs. Do not modify files outside package/.uv run chio-mini-swe session init --config session.json \
--task-file issue.md --state .sessionEach entry in source_paths is a literal repository-relative path from the selected commit, never a glob. The scope is bound into the repository configuration, the tool manifest, and every completed command receipt; a file created or published outside it stops the workspace without promoting that revision. The v1 configuration covers whole-repository tasks and takes the three image IDs directly.
4. Authorize the two tool launches
Initialization writes an unsigned request naming the exact model and repository server commands, tool definitions, and configuration identities. The request grants no authority. Read it before you ask your provisioning system for signatures.
cat .session/provisioning-request.jsonYou should see source_commit, workspace_id, model_id, configuration_sha256, binary_sha256, and the installed environment inventory. For each of model and sandbox, compare argv, working_directory, execution_uid, execution_gid, tools, and request_timeout_seconds with the deployment you intend.
Keep argv an array: shell interpolation would change the requested command. Your provisioning system selects the migration stage, launch permissions, and trusted signing keys, signs the exact executable, argv, directory, UID/GID, and manifest, and returns authorization.json with the policy paths and independently pinned signer keys. The session command makes none of these trust decisions, and discovery adds no permission.
Authorize a local teaching run instead
For an isolated local exercise, authorize-demo.py is an explicit alternative operator program. It calls the native demo provisioner, which selects migration stage Disabled and provides no OS containment. The command and file name say so, and session prepare never falls back to it on its own. Use it only with the fixture's controlled local servers.
uv run python authorize-demo.py .session/provisioning-request.json local-policies
uv run chio-mini-swe session prepare --state .session \
--authorization local-policies/authorization.jsonRead more in Verified tool launch and signed manifest authority.
5. Prepare the host and run the agent
Copy operator/provider.example.json to provider.json and set your endpoint, model, and token prices. Export the API key under the variable it names; the trusted gateway reads it, and the coding worker never receives it.
uv run chio-mini-swe session prepare --state .session \
--authorization authorization.json
uv run chio-mini-swe session run --state .session
uv run chio-mini-swe session status --state .sessionYou should see status report the session's state. Preparation creates the host with exactly two routes, model/model_infer and sandbox/execute. Every resume reuses the original task and plan, so an interrupted worker or host sends no new provider request or repository command while the original outcome is unknown.
6. Export the patch with its original receipts
uv run chio-mini-swe session result --state .session --out resultYou should see result/repository/changes.patch beside the original receipts, the pinned kernel key, the repository baseline and final archives, and a verified transition report. Export works after the host stops, including after cancellation or expiry, and starts no model or repository server. Missing or altered evidence makes the command refuse instead of producing a best-effort patch.
7. Verify and apply the patch in a recipient checkout
Prepare recipient/ at the full commit you selected, set SELECTED_COMMIT to that revision, and obtain trusted-kernel.pub from the trusted operator before the bundle arrives. Repeat --source-path for each expected scope.
uv run chio-mini-swe-repository verify-export \
--bundle result/repository --repository recipient \
--revision "$SELECTED_COMMIT" --source-path package \
--chio chio --kernel-key trusted-kernel.pub --server-id sandbox
git -C recipient apply --check ../result/repository/changes.patch
git -C recipient apply ../result/repository/changes.patch
git -C recipient diff -- package/
cd recipient/package
python3 -m unittest -vYou should see both addition tests pass in the patched checkout, while your source checkout still holds its dirty and untracked files. The recipient chose the commit, scope, and key independently of the bundle. Verification checks the signed action bindings and the ordered workspace transitions; the diff review and the tests judge the code.
{
"model_calls": 3,
"verified_transitions": 5,
"verified_receipts": 8,
"source_paths": [
"package"
],
"source_unchanged": true,
"independent_recipient_checkout": true,
"kernel_key_selected_before_export": true,
"recipient_tests_passed": true,
"wrong_recipient_key_refused": true,
"completed_replay_did_no_new_model_work": true,
"offline_combined_export": true
}A verified run of this handoff recorded three model calls, five verified transitions, and eight verified receipts. The recipient key was selected at trusted initialization, before the bundle existed, and verification under a different key was refused. In the SDK, the Quickstart's fork.diff() and project.apply(fork.changes) make the same handoff inside one computer, and apply publishes only while main still equals the fork's base.
An interrupted session resumes from its last committed workspace
Every failure leaves the previous committed workspace authoritative and refuses to redispatch an unknown outcome. After you stop the host, session recover reconciles owned repository containers and partial command resources, then the same session continues.
- Worker exits after a known tool result. The original process call can replay; run the same session with the same task and operation IDs.
- Host dies after a command snapshot commit. The kernel outcome is known or unknown; inspect the original call and repository transition.
- Inference is interrupted. The provider outcome can stay unknown; stop, and never ask again under a new key.
- A command modifies files outside the scope. Snapshot publication is refused, and the previous committed workspace stays authoritative.
- Command container ownership is uncertain. Cleanup cannot be shown safe; stop the host, run recover, and keep mismatched resources.
- Export lacks a completed trajectory or matching evidence. No verifiable result bundle exists; keep the incomplete state and label nothing verified.
uv run chio-mini-swe session recover --state .session
uv run chio-mini-swe session run --state .session
uv run chio-mini-swe session result --state .session --out resultRecovery keeps the model stopped, keeps the original authority, and leaves the capability lifetime where it was. A command whose effect cannot be established stays stopped for operator resolution, so keep the state directory until its repository snapshots and original receipts have been inspected.
Exercise these failures without a provider account with the session and repository tests.
Session limits, provider, and launch fields
Try timeout, provider, or signer.
Derived deadline budget
Each limit must contain one complete request at the layer beneath it.
| Setting | This example | Required relation |
|---|---|---|
Repository command | 90 seconds | Host repository request is command + 120 = 210. |
Provider request | 60 seconds | Host model request is provider + 30 = 90. |
Native attempt | 300 seconds | At least max(210, 90) + 30 = 240. |
Agent wall time | 600 seconds | At least the attempt deadline; stopped time still counts. |
Two attempts and capability TTL | 3,600 seconds | At least max(600, 2 × 300 + 60) = 660. |
The call ceiling counts model and repository routes, and one model response can contain several commands, so max_calls bounds work that step_limit alone leaves open. cost_limit is an estimate from reported token usage and the configured prices, checked between decisions, and separate from any billing cap on the provider account. The capability lifetime starts at preparation: waiting to run consumes it, and recovery leaves it unchanged.
Provider configuration
{
"schema": "chio.mini-swe.provider.v1",
"endpoint": "https://models.larkfield.example/v1",
"model": "your-model",
"credential_env": "CHIO_CODING_API_KEY",
"timeout_seconds": 60,
"input_usd_per_million": 0,
"output_usd_per_million": 0,
"max_output_tokens": 2048
}The gateway posts to chat/completions beneath the configured base, with one upstream bash tool definition, max_completion_tokens, and streaming off. The endpoint, model, credential variable name, limits, explicit prices, and optional temperature define model_id; rotating the secret value keeps that identity. Initialization and discovery need no inference and no provider credential.
Authorization document
{
"schema": "chio.mini-swe.session-authorization.v1",
"servers": {
"model": {
"launch_policy": "/private/policies/model.json",
"launch_policy_signer": "PINNED_MODEL_SIGNER_HEX"
},
"sandbox": {
"launch_policy": "/private/policies/sandbox.json",
"launch_policy_signer": "PINNED_SANDBOX_SIGNER_HEX"
}
}
}The document carries policy paths and independently pinned signer public keys. It holds no signing key of its own.
Provisioning refusals
- Signer pin differs from the signed policy. Signature and trust validation refuses preparation.
- Executable or full argv differs. The exact launch binding refuses the server.
- Working directory or execution UID/GID differs. The requested execution identity fails to match the authorization.
- Discovered tools differ from the signed manifest. Discovery cannot widen signed tool authority.
- Session task, provider, or installed Chio sources change. The captured session identities no longer match.
- Preparation partially wrote files. No prepared marker exists; keep the state and diagnose it instead of overwriting it.
Component responsibilities
- Source import. The selected full commit and optional literal source paths.
- Process host. Worker identity, attempts, narrowed calls, and receipts.
- Repository service. The bounded command sandbox, snapshots, and patch export.
- Independent verifier. The source baseline, trusted kernel key, receipts, and transitions.
Whether the task is desirable, whether the patch is correct, whether an external system changed, and whether the tests cover all behavior stay with the people who request, review, and accept the change.
Session test without a provider account
The included qualify_session.py creates a temporary repository, a loopback HTTP test provider with scripted tool decisions, and an independent recipient checkout, then authorizes with the explicit demo path. It runs native sessions, Docker repository commands, receipt verification, and patch export on the installed images. Its first provider response waits 65 seconds to cross the ordinary host timeout and exercise the derived session deadline, and it holds the native host lock to show that recovery and export cannot race an active host. It is recovery and integration evidence and says nothing about model quality; the configured provider in step 5 runs inference under the same session boundaries.
uv run python qualify_session.py --runtime-profile runtime.json \
--output coding-session-evidence --scopedRepository failure tests
qualify_repository.py covers command deadlines, raw and serialized output ceilings, escaping links, special files, writes outside the selected source paths, and service death after a partial effect. Each interrupted case keeps the previous snapshot and refuses automatic redispatch. It measures container isolation and confirms that a foreign container survives an ownership mismatch. An unknown provider response stays unknown in these tests.
uv run python qualify_repository.py --runtime-profile runtime.json \
--output repository-failure-evidence