Build a software factory
Turn an issue into a patch, test and review one exact candidate, and publish only the candidate the release owner approves.
On this page
A software factory closes the loop from an observable defect to a tested, reviewed change. This application supplies a broken Python project and immutable tests; a repair worker edits allowed source files, signed graph continuations authorize testing and review, and the release owner decides whether the exact candidate is published to a local release directory.
Run the factoryA failing project becomes one tested, reviewed candidate
From issue to a tested candidate
A repair worker edits a confined project. Separate graph continuations authorize implementation, testing, and candidate review.
Inspect the failing baseline, the candidate diff, the focused test output, and the review. The deterministic adapter supplies a regression repair for fast exploration; model mode generates a new patch through governed repository tools. After a live run, approve or reject the candidate shown. Approval publishes only inside this run’s isolated project and retains a separate publication receipt.
Each responsibility spends one continuation and publication needs its own approval
The graph bounds what each worker may do and how often. The candidate’s digest ties the test and review results to the change they examined, and the release owner’s approval binds publication to that digest.
Each responsibility spends one continuation
The host mints a task graph for implementation, testing, and review with bounded allocations and one-use continuations. Publication needs a separate approval bound to the proposed parameters; a publish without it is refused. Continuations.
Repository tools touch only the configured files
The repair worker can list, read, and write the configured project files, and the immutable test file is read-only. Tool handlers validate each path before they touch the workspace. In model mode, the conversation loop proposes these same tool calls and receives the admitted results.
fn write(&self, path: &str, content: &str) -> Result<Value> {
simple_path(path)?;
anyhow::ensure!(
self.editable.iter().any(|p| p == path),
"File is outside the worker's editable set"
);
anyhow::ensure!(content.len() <= 32_000, "File exceeds 32000 bytes");
let destination = self.directory.join(path);
anyhow::ensure!(
!destination.symlink_metadata()?.file_type().is_symlink(),
"Refusing to replace a symlink"
);
chio_agent_os_shared::runtime::files::replace(&destination, content.as_bytes())?;
self.writes
.fetch_add(1, std::sync::atomic::Ordering::SeqCst);
Ok(json!({"path":path,"candidate_sha256":self.digest_unlocked()?}))
}In the verified run, event 25 refuses a write to a path outside the editable files, with receipt 17292436…26ce6f.
The host issues authority for the actual task graph
The host mints a graph for implementation, testing, and review from the delegated capabilities. It records the graph, route references, bounded allocations, and one-use continuations, and runtime admission consumes a continuation before each worker call. Application order and acceptance criteria stay visible in this file.
let root = host.root("factory-workers", &["implement", "test", "review"], 3)?;
let implement = host.delegate(&run, &root, "implement", &["implement"], 1, 3000)?;
let test = host.delegate(&run, &root, "test", &["test"], 1, 3000)?;
let review = host.delegate(&run, &root, "review", &["review"], 1, 3000)?;
let tasks = [
("implement", &implement),
("test", &test),
("review", &review),
];
let bundle = host.mint_graph(SwarmFanoutRequest {
graph_id: run.id()?,
root_transaction_ref: planned.receipt_id.clone(),
parent_receipt_id: planned.receipt_id,
session_anchor: run.id()?,
parent: root.token,
tasks: tasks
.iter()
.map(|(task, cap)| SwarmFanoutTask {
task_id: task.to_string(),
capability: (*cap).clone(),
protocol_target: "local://factory-workers".into(),
reserved_units: 1,
})
.collect(),
policy_digest: chio_core::sha256_hex(b"factory-signed-task-graph-v1"),
now_unix_ms: chio_agent_os_shared::events::now_ms(),
lifetime_ms: 110_000,
})?;
run.emit("graph.issued","planner","Issued authority for three bounded responsibilities",json!({
"graph":bundle.task_graph,
"continuations":bundle.continuation_tokens,
"trusted_issuer":host.signer.to_hex(),
"scheduling":"The application orders implement, test, and review; the graph assigns authority and joins their results"
}))?;Event 07 issues the three continuations. Event 17 refuses a reused implementation continuation, with receipt 99ca5cfa…fce8a4.
Tests and review bind to one candidate
Testing and review each compare the requested candidate with the current repository digest, and review also checks that the retained test result names that candidate. Passing checks and a structured review permit a completion join; publication is a separate decision. The review is a deterministic release check over the diff.
"test" => {
anyhow::ensure!(
input["candidate_sha256"] == self.repository.digest()?,
"Tests requested for a stale candidate"
);
let result = self.repository.test(false).await?;
*self
.tests
.lock()
.map_err(|_| anyhow::anyhow!("Test result lock failed"))? =
Some(result.clone());
Ok(result)
}
"review" => {
let candidate = self.repository.digest()?;
anyhow::ensure!(
input["candidate_sha256"] == candidate,
"Review requested for a stale candidate"
);
let tests = self
.tests
.lock()
.map_err(|_| anyhow::anyhow!("Test result lock failed"))?
.clone()
.context("Run tests before requesting review")?;
anyhow::ensure!(
tests["candidate_sha256"] == candidate,
"Tests belong to another candidate"
);Event 19 refuses tests for a stale candidate. Event 27 joins the three receipts the workers actually returned.
Publication happens once, for the approved candidate
The release tool checks eligibility, the candidate digest, and the exact file set before it stages the release. The separate approval binds the proposed parameters, the publication keeps its receipt, and repeating the same decision recovers that terminal result. Tests run with network access off and read-only project and system files.
fn publish(&self, args: Value) -> Result<Value> {
anyhow::ensure!(
args == self.proposal["arguments"],
"Publication parameters differ from the reviewed proposal"
);
let files = read_files(
&self.directory.join("project/candidate"),
&self.proposal["files"],
)?;
anyhow::ensure!(
digest(&files)? == args["candidate_sha256"],
"Candidate changed after approval; run the tests and review the new candidate"
);
let destination = self.directory.join("release");
anyhow::ensure!(
!destination.exists(),
"Release already exists; reconcile it instead of publishing again"
);
let staged = chio_agent_os_shared::runtime::files::StagedDirectory::new(&self.directory)?;
for (name, contents) in &files {
chio_agent_os_shared::runtime::files::create(
&staged.path().join(name),
contents.as_bytes(),
)?;
}
write_json(
&staged.path().join("release.json"),
&json!({
"candidate_sha256":args["candidate_sha256"],
"test_receipt":args["test_receipt"],
"review_receipt":args["review_receipt"],
"files":files.keys().collect::<Vec<_>>()
}),
)?;
staged.publish(&destination)?;
Ok(
json!({"published":true,"candidate_sha256":args["candidate_sha256"],"files":files,"release_directory":"release"}),
)
}
}Event 30 refuses a publish that carries no approval token, with receipt d4d4b229…c6955c.
Replay, revocation, stale tests, and unapproved publication change nothing
The sample input tries each refusal after the candidate exists. The retained run shows the candidate unchanged:
./run --run input.json17 call.denied implement
chio swarm-bound runtime continuation replay denied
receipt 99ca5cfa…fce8a4
19 call.denied stale-test-worker
tool server error: Tests requested for a stale candidate
receipt d5ac4240…c3e155
21 call.denied revoked-repair-worker
capability has been revoked: cap-01a08c22-703d-7a71-8505-88b8eb09bf43
receipt 13c64fff…a8d82a
23 call.denied review-worker
requested tool write_file on server repository is not in capability scope
receipt c5487c4e…6bbbc9
26 factory.refusals operator
Replay, revocation, stale tests, and unauthorized edits left the candidate
unchanged
30 call.denied unapproved-publisher
governed transaction denied: approval token required for governed transaction
intent 371826d6-26b9-44d8-ba49-1aaa027e8091
receipt d4d4b229…c6955c- Write a path outside the editable project: no file changes.
- Reuse an implementation continuation or revoke the edit grant: the candidate stays unchanged.
- Present stale test evidence or a changed approval digest: no release is published.
- Reject publication: the candidate and its evidence stay, unshipped.
The downloadable tests assert each effect or its absence: run cargo test --locked -p chio-software-factory from the extracted project.
Run the factory on your machine
Keep the run directory to review the tested candidate and reconcile its publication decision.
cd chio-software-factory
./runThe archive holds the application, the shared host code, tests, sample input, pinned dependencies, and a README. The launcher builds and runs the Rust source included in this archive. Install Rust 1.94.1 and the README’s native prerequisites; filesystem isolation and operator workloads require the listed Linux host profile. Cargo resolves immutable public dependencies, so a sibling checkout is unnecessary.
For model workers, set OPENROUTER_API_KEY on the local host and select model mode; credentials stay on that host and never enter the docs form. The qualified model is openai/gpt-4.1-mini. Analysis, retrieval, and deterministic worker modes run without a model key. Ctrl-C stops the local web process and its active child work and keeps the run directory.
Download identity and source revision
Download complete project · View public source
753ca6667a9a1585da87886abd16a1f169ddbb563f483ec49122be08a8e7860aPoint the factory at your own project
Set CHIO_FACTORY_WORKSPACE to a small Python project in the included chio-factory.json layout. Name the editable files and one immutable focused test, then use model mode to repair the failing case. A GitHub publication adapter can replace the local release directory, with its approval bound to the same tested candidate.