Skip to content

First offline run

This process takes five minutes and costs nothing. The default agent runtime is fake: a deterministic test double that returns valid artifacts without calling a model. The rest of the system is real. It uses real Git worktrees, a real state machine, and real persisted artifacts.

1. Pick a target repository

A Git repository with at least one commit works. To keep the walkthrough self-contained:

mkdir -p ~/projects/example && cd ~/projects/example
git init
echo "# example" > README.md
git add -A
git commit -m "init"

2. Run one work item

cd /path/to/software-agent-factory
uv run factory run \
  --repo ~/projects/example \
  --title "Reject empty customer names" \
  --description "Return HTTP 400 for empty or whitespace-only names." \
  --config config/factory.example.yaml \
  --data-dir ./.factory-demo

Output:

run id: run-9bb36bbbdf114f53bd9599a103122976
state: PR_READY
workspace: ./.factory-demo/workspaces/WI-c769695fc242
changed files: FACTORY_NOTES.md

The run moved through:

CREATED → prepare worktree → profile repository → TRIAGING
        → REFINING → [RESEARCHING] → PLANNING
        → IMPLEMENTING → VERIFYING
        → [RESEARCHING (repository skill)] → IMPLEMENTING (POLISH) → VERIFYING
        → REVIEWING → PR_READY

The profile and polish reuse existing states rather than adding PROFILING/POLISHING. The example configuration enables one bounded polish pass. It uses version-aware guidance for the versions that this repository declares. That guidance is stored under the data directory, keyed by the repository and its dependency fingerprint. The factory reuses that guidance. The web-only research call happens only on the first run for given dependencies. Polish can make no edits. It still records an attempt and runs deterministic verification again. If research or validation fails, the factory records a warning on the profile and skips polish. The verified run continues to review. A legacy configuration that omits polish defaults to disabled.

PR_READY is the terminal state when pull requests are disabled, as in config/factory.example.yaml. A nonzero exit code means that the run did not finish successfully. NEEDS_HUMAN and FAILED are the other terminal states.

--data-dir ./.factory-demo keeps this experiment out of ~/.software-factory. Drop this option once you finish the demo.

3. Look at what happened

uv run factory runs --data-dir ./.factory-demo
run-9bb36bbbdf114f53bd9599a103122976    PR_READY    WI-c769695fc242 2026-09-05T09:06:47+00:00
uv run factory show run-9bb36bbbdf114f53bd9599a103122976 --data-dir ./.factory-demo

show prints the persisted run as JSON: state, attempt history, budgets, timestamps and artifact references.

4. Look at the files

Nothing is hidden in a database. Everything is JSON on disk.

.factory-demo/runs/run-9bb.../
├── run.json              state machine, attempts, budgets, timestamps
├── work-item.json
├── repository-profile.json
│                           technologies, tools, markers, fingerprints,
│                           version files, dependency declarations, warnings
├── triage.json           complexity, risk, whether research is needed
├── specification.json    acceptance criteria
├── execution-plan.json
├── change-set.json       what the implementer claims it did
├── patch.diff            what the controller actually observed
├── verification.json     install / verify / build results
├── repository-skill.json  immutable snapshot of the effective simplify and
│                           polish guidance this run used (generated guidance
│                           plus any valid human overlay)
├── repository-skill-overlay.json
│                           the overlay exactly as it was read, when valid
├── repository-skill-use.json
│                           provenance: repository key, dependency fingerprint,
│                           where the guidance came from, content hashes
├── test-report.json      independent tester
├── review.json           independent reviewer
└── attempts/
    ├── 01/               initial implementation snapshot
    └── 02/               bounded polish snapshot

The difference between change-set.json and patch.diff is important. The tester and reviewer receive the diff from the controller, not the summary from the implementer.

The Git worktree stays on disk, under workspaces/. The factory preserves workspaces by default so you can inspect or reuse the change.

Reusable guidance lives outside the run, under <data_dir>/repository-skills/v1/<repository-key>/.... It lives alongside the optional repository-skill-overlay.yaml that you can write by hand. Run uv run factory skill path --repo ~/projects/example to display the exact locations. Read Repository skills and overlays.

5. Check the derived metrics

uv run factory status --data-dir ./.factory-demo
runs: 1 total, 1 scanned
states: 1 succeeded, 0 escalated, 0 failed, 0 active (0 stale)
attempts: 2 total, 2 implementation, 0 CI repair, 0 scope replan(s)
first-pass success: 100% (1/1)

health:
  stale runs: 0
  stale locks: 0 (of 0 checked)
  orphaned workspaces: 0 (of 1 checked)

status: complete

status is read-only. It recomputes everything from the persisted artifacts on each call and will not even create the data directory.

The first-pass metric ignores the planned polish attempt. It measures whether the initial implementation needed repair for an implementer, verification, scope or review failure.

What this run did and did not do

Did:

  • created a Git worktree for the work item
  • ran the pipeline through the workflow controller
  • profiled repository capabilities without shell, network or imports
  • persisted typed artifacts and a per-attempt snapshot
  • wrote a structured JSON log to <data-dir>/logs/factory.log

Did not:

  • call a model, or spend anything
  • make any network request
  • commit, push, or open a pull request
  • start a server or install a service

Next

  • Real Copilot runs to use actual models.
  • Configure a repository to configure verification with the lint, test, and build commands for your project. Until you configure commands, the install, verify, and build command lists remain empty. Verification then has no deterministic checks to run.