This document defines engineering guidance for AI/code agents working in this repository.
- Project:
forge-loop-cli - Language: Rust (workspace in
crates/) - Goal: spec-driven autonomous loop CLI with reusable SDD snapshots
- Runtime state:
.forge/
crates/forge-cli: CLI surface (forge,run,status,monitor,sdd)crates/forge-core: loop engine, output analysis, rate limit, circuit breakercrates/forge-config:.forgercand env/flag precedencecrates/forge-engine: Engine trait and implementations (Codex, OpenCode)crates/forge-monitor: TUI monitorcrates/forge-types: shared serializable types
Forge supports multiple AI coding engines via the Engine trait in forge-engine:
- Codex (default): OpenAI's Codex CLI
- OpenCode: Open source AI coding agent
To add a new engine:
- Implement the
Enginetrait inforge-engine/src/lib.rs - Add the engine variant to
EngineKindinforge-config/src/lib.rs - Update
create_engine()factory function
When running forge with no subcommand, the assistant asks SDD questions and creates a snapshot under:
.forge/sdds/<id>/plan.md.forge/sdds/<id>/spec.md.forge/sdds/<id>/acceptance.md.forge/sdds/<id>/scenarios.md
The active snapshot is tracked in:
.forge/current_sdd
And activated into:
.forge/plan.mddocs/specs/session/spec.mddocs/specs/session/acceptance.mddocs/specs/session/scenarios.md
Use:
forge sdd listforge sdd load <id>
Expected files in .forge/:
status.jsonprogress.jsonlive.log.session_id.call_count.last_reset.circuit_breaker_state.circuit_breaker_history.runner_pid
Agents must preserve these contracts unless a migration is explicitly implemented.
Status semantics:
run_started_at_epoch: start of currentforge runcurrent_loop_started_at_epoch: start of current loop commandlast_heartbeat_at_epoch: last real output/stream heartbeat from engine process.runner_pid: PID of active forge run process (used by monitor to detect stalerunningstate)
Always preserve precedence:
- CLI flags
- Environment variables
.forgerc- Defaults
Engine runtime flags can be passed via:
forge run --engine <codex|opencode>(select engine)forge run --engine-arg=<value>(repeatable)forge run --full-access(forces sandbox bypass).forgerckeyengine_pre_args = ["--sandbox", "danger-full-access"]
Monitor tuning:
forge monitor --stall-threshold-secs <N>controls stale heartbeat alert threshold
cargo fmt --all
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace- Keep behavior backward-compatible within v0.x where practical
- Any CLI contract change must include test updates
- Any loop/state change must preserve
.forge/*output consistency - Prefer focused edits over broad refactors
- Add or update contract tests in
crates/forge-cli/tests/ - Add core behavior tests in
crates/forge-core/tests/ - Add engine tests in
crates/forge-engine/src/lib.rs - Validate
fmt,clippy, andtestbefore proposing changes
When changing user-facing behavior, update at least:
README.mddocs/specs/*(if feature behavior changed)AGENTS.md
- Use
forgenaming only - Do not introduce legacy
ralphnaming in code, docs, env vars, or output - Use
enginefor generic engine references (notcodexspecific)
- Do not run destructive git commands (
reset --hard,checkout --) unless explicitly requested - Do not delete runtime contracts under
.forge/without a migration path - Do not silently change exit-code semantics