Handbook
Normative layout: `.forge/runs/`
Self-Host Alpha stores one directory per ForgeRun under the target git repository (for example forge-platform/):
Normative layout: .forge/runs/
Self-Host Alpha stores one directory per ForgeRun under the target git repository (for example forge-platform/):
.forge/runs/<forge_run_id>/forge_run.json
.forge/runs/<forge_run_id>/approvals/<approval_id>.json
.forge/runs/<forge_run_id>/events.ndjson
.forge/runs/<forge_run_id>/local-runner/result.json
.forge/runs/<forge_run_id>/local-runner/<action_id>.stdout.txt # optional
.forge/runs/<forge_run_id>/evidence/evidence_packet.json
Conventions
forge_run_idmust equal the directory name (frun_*).- Approvals are immutable records; only
state: approvedmay gatescripts/selfhost_runner.py. events.ndjsonis append-only (JSON lines).- The local runner never accepts raw shell; it only dispatches allowlisted
action_idvalues (seeschemas/local_runner_action.v1.schema.json).
Fleet migration
The same action + approval + evidence envelope is intended to map to a FleetTemplate later. The alpha runner is temporary until R4 execution MVP.
forge-workcells (micro-agent)
scripts/selfhost_runner.py remains the Self-Host Alpha local_runner path on platform — see Self-Host local runner. Bounded local-LLM work (local_llm_worker) runs in the private forge-workcells repo; see Forge micro-agent. Platform does not duplicate that runner in MVP.
Git
Add .forge/runs/ to the consumer repo .gitignore unless you intentionally commit a demo fixture. Canonical committed seeds live under sprints/selfhost-alpha/fixtures/.
Lenses
Lenses Studio reads this tree via GET /api/project/<slug>/forge-runs on the workspace child repo that contains .forge/ (see sprints/selfhost-alpha/evidence/lenses-selfhost-handoff.md).