A small experiment in a two-stage software handoff: an engineer returns a file tree, a refiner receives that tree, and the coordinator saves both versions. It makes the handoff inspectable; the supplied stages are deterministic simulations.
The historical experiment explored GPT-Engineer, Aider, AutoGen and Docker. Those integrations are not implemented here. This public continuation preserves the two-stage idea without the private working tree or third-party copies. Origin
Python 3.11 or later, from this checkout:
python -m pip install -e .
python -m examples.walkthrough
python -m software_factory "Build a greeting tool" --workspace ./demo-output
python -m pip install pytest
python -m pytest -qThe walkthrough uses a temporary directory and prints the captured result: the task, both complete file trees, stage counts, and what remains after a deliberately failed refiner. It never executes generated code.
The CLI keeps engineer-output/, final-output/ and job-evidence.json under demo-output/jobs/<job-id>/. The engineer writes a tiny Python program that prints the task; the refiner adds a comment. The record contains successful stage counts, times and the final path.
“Complete” means both callables returned and their trees were written. A review comment proves the simulated refiner ran; it does not prove the software improved.
from pathlib import Path
from software_factory import SoftwareFactory
def engineer(task, files):
assert files == {}
return {"brief.txt": task + "\n"}
def refiner(task, files):
return {**files, "review.txt": "Check the brief against the request.\n"}
job = SoftwareFactory(engineer, refiner).run(
"Describe a greeting tool", Path("custom-output"), job_id="example-001"
)
assert job.status == "complete"Each stage receives (task: str, files: Mapping[str, str]) and returns a complete relative-path → text dictionary. A file omitted by the refiner is not automatically carried into the final tree. Use a fresh workspace/job ID: reuse can overwrite files and leave stale files.
core.py follows engineer → write_tree → refiner → write_tree → job-evidence. Path checks contain generated destinations, not what a trusted Python stage itself can do.
A failed refiner leaves engineer output and no completed job record, as the walkthrough demonstrates. Writes are not transactional; stages have no timeout or retry policy. Generated files are not executed, tested or independently evaluated.
A useful next experiment would add separately recorded tests and compare their results before/after refinement. A provider adapter alone would not establish quality.