Skip to content

Commit 841952d

Browse files
authored
Feat/structure polishing (#43)
* docs updates * performance improvements * fix: status line update
1 parent 74c525f commit 841952d

8 files changed

Lines changed: 247 additions & 44 deletions

File tree

AGENTS.md

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,21 +28,31 @@ All three checks must pass before submitting: `clippy -D warnings`, `fmt --check
2828
```
2929
src/
3030
main.rs # CLI entry, tracing init, HQ logger
31-
cli/ # clap subcommands (init, serve, register)
32-
config/mod.rs # Deserialize ferrus.toml (ChecksConfig, LimitsConfig, LeaseConfig, HqConfig)
31+
cli/ # clap entry and command implementations (init, serve, register)
32+
config/mod.rs # Deserialize/update ferrus.toml (ChecksConfig, LimitsConfig, LeaseConfig, SpecConfig, HqConfig)
33+
config/claude.rs # Claude MCP isolation config helpers
34+
templates.rs # Embedded Markdown templates written by init/resource fallback
35+
specs.rs # Spec discovery, milestone parsing, selected milestone resolution
36+
agent_id.rs # Stable agent IDs and MCP server names
37+
agents/ # Agent launcher/config adapters for Claude Code, Codex, Qwen Code
38+
agents/mod.rs # SupervisorAgent/ExecutorAgent traits, AgentRunMode, MCP config entry helpers, agent parsing
39+
agents/claude/mod.rs # Claude Code launchers, model override handling, MCP isolation, role-scoped config paths
40+
agents/codex/mod.rs # Codex launchers, stdin prompt transport, TOML MCP config and tool approvals
41+
agents/qwen/mod.rs # Qwen Code launchers, model override handling, JSON settings tool approvals
42+
platform/ # OS-specific process, shell, and parent-lifecycle helpers
3343
state/machine.rs # TaskState enum + StateData + transition methods + lease helpers
3444
state/store.rs # Async read/write of .ferrus/ files; open_lock_file, claim_state
3545
state/agents.rs # AgentEntry, AgentsRegistry — .ferrus/agents.json lifecycle tracking
3646
update_check.rs # HQ startup version-check helper (crates.io sparse index + local cache)
3747
checks/runner.rs # Spawn check subprocesses, collect output
3848
hq/mod.rs # HQ entry point; HqContext; tokio::select! loop; transition_action
3949
hq/state_watcher.rs # Background task: polls STATE.json every 250ms, watch channel
40-
hq/tui.rs # Terminal UI (crossterm): App event loop, UiMessage, StatusSnapshot; autocomplete, command history, spec/milestone status line, confirmation/selection dialogs; double-Ctrl+C-to-quit (2-second window)
50+
hq/tui.rs # Terminal UI (crossterm): App event loop, UiMessage, StatusSnapshot; autocomplete, command history, spec/milestone status line, confirmation/selection dialogs, AwaitingHuman answer hint; double-Ctrl+C-to-quit
4151
hq/commands.rs # ShellCommand enum, parse_command() via clap + shlex
4252
hq/display.rs # Display wrapper: sends UiMessage to TUI channel (info, error, transition, status, suspend, resume, confirm)
4353
hq/agent_manager.rs # agent spawn helpers (headless for executor, reviewer, consultant); HeadlessHandle; agents.json updates
4454
server/mod.rs # neva App setup; constructs agent_id, wires closures
45-
server/tools/ # One file per MCP tool (one module = one tool)
55+
server/tools/ # One file per MCP tool (one module = one tool); check_gate.rs is the shared check runner/report helper
4656
server/resources.rs # MCP resource handler (ferrus://{file})
4757
server/prompts.rs # MCP prompt handlers
4858
```
@@ -59,6 +69,12 @@ src/
5969

6070
**Spec selection**: `STATE.json` stores `selected_spec` and `selected_milestone` as UI references only. Active task progress uses `task_spec` and `task_milestone`, copied from `pending_task_*` when `/create_task` succeeds. Milestone display text is resolved from the spec Markdown by milestone `ID`. Keep milestone IDs stable across title edits.
6171

72+
**Agent adapters**: keep backend-specific CLI behavior inside `src/agents/{claude,codex,qwen}`. Shared orchestration should depend on the `SupervisorAgent` and `ExecutorAgent` traits, not on a concrete agent CLI. When adding an agent, implement both role adapters, model normalization, headless prompt transport if needed, version/config entry behavior, registration wiring, and focused tests.
73+
74+
**HQ checks**: `/check` calls the same MCP check handler as an Executor and therefore updates retry state. `/check --force` runs configured commands directly from HQ and does not modify `STATE.json`.
75+
76+
**HQ reset vs MCP reset**: HQ `/reset` force-resets from any state after confirmation when active agents may be running, clears task/answer/consultation files, and preserves selected spec/milestone. The MCP `/reset` tool is only valid from `Failed`.
77+
6278
## Ferrus Executor
6379

6480
This repository is orchestrated by Ferrus HQ.

CLAUDE.md

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ ferrus register [--supervisor <agent>] [--supervisor-model <model>] [--executor
4949
| `/task --manual` | Define a free-form task without selected milestone context |
5050
| `/spec` | Draft, approve, and save a feature specification |
5151
| `/milestones` | Select the current spec and milestone |
52+
| `/reset-spec` | Clear the selected spec and milestone |
53+
| `/check` | Run the Ferrus check gate from HQ, using the normal task-state rules |
54+
| `/check --force` | Run configured checks from HQ without modifying state |
5255
| `/supervisor` | Open an interactive supervisor session (no initial prompt, no state requirement) |
5356
| `/executor` | Open an interactive executor session (no initial prompt, no state requirement) |
5457
| `/resume` | Manually resume the executor headlessly; also recovers Consultation by relaunching both consultant and executor |
@@ -58,8 +61,9 @@ ferrus register [--supervisor <agent>] [--supervisor-model <model>] [--executor
5861
| `/stop` | Stop all running agent sessions (prompts for confirmation) |
5962
| `/reset` | Reset state to Idle and clear task files (prompts for confirmation) |
6063
| `/init [--agents-path]` | Initialize ferrus in the current directory |
61-
| `/register` | Register agent configs (same as `ferrus register`) |
62-
| `/model` | Update the supervisor or executor model override |
64+
| `/register [--supervisor <agent>] [--executor <agent>]` | Register Claude Code or Codex configs from HQ |
65+
| `/model <supervisor|executor> <model>` | Update the supervisor or executor model override |
66+
| `/model <supervisor|executor> --clear` | Clear the supervisor or executor model override |
6367
| `/help` | List all HQ commands |
6468
| `/quit` | Exit HQ |
6569

@@ -124,6 +128,7 @@ model = "" # optional override; empty = agent default
124128
| `/review_pending` | Reviewing || Read task + context for review |
125129
| `/approve` | Reviewing | Complete | Accept the submission |
126130
| `/reject` | Reviewing | Addressing | Reject with notes; resets Executor retry counter |
131+
| `/respond_consult` | Consultation || Record the Supervisor consultation response in `CONSULT_RESPONSE.md` |
127132

128133
### Executor tools
129134

@@ -141,7 +146,6 @@ model = "" # optional override; empty = agent default
141146
| Tool | From state | To state | Description |
142147
|---|---|---|---|
143148
| `/ask_human` | Executing, Addressing, Consultation, Reviewing | AwaitingHuman | Last-resort human fallback. Write question to QUESTION.md; agent must immediately call `/wait_for_answer` (executor) or wait for HQ to answer |
144-
| `/respond_consult` | Consultation || Record the Supervisor consultation response in `CONSULT_RESPONSE.md` |
145149
| `/answer` | AwaitingHuman | (previous state) | Provide answer to a pending question; restores previous state |
146150
| `/heartbeat` | any claimed || Renew lease; call every ~30s while working |
147151
| `/status` | any || Print current state + retry counters |
@@ -206,6 +210,7 @@ Executor verification is TDD-friendly: `/check` can be run as often as needed du
206210
|---|---|
207211
| `STATE.json` | Current `TaskState`, lease fields (`claimed_by`, `lease_until`, `last_heartbeat`), retry/cycle counters, failure reason, schema version, last-write timestamp and PID |
208212
| `STATE.lock` | Advisory lock file for atomic claiming (do not delete) |
213+
| `agents.json` | Runtime registry for agent sessions, statuses, PIDs, and log ownership |
209214
| `TASK.md` | Task description written by Supervisor |
210215
| `REVIEW.md` | Supervisor rejection notes |
211216
| `SUBMISSION.md` | Executor's submission notes (summary, verification steps, known limitations) |
@@ -225,31 +230,47 @@ Executor verification is TDD-friendly: `/check` can be run as often as needed du
225230
```
226231
src/
227232
main.rs # CLI entry, tracing init, HQ logger
228-
cli/ # clap subcommands (init, serve, register)
229-
config/mod.rs # Deserialize ferrus.toml (ChecksConfig, LimitsConfig, LeaseConfig, HqConfig)
233+
cli/ # clap entry and command implementations (init, serve, register)
234+
config/mod.rs # Deserialize/update ferrus.toml (ChecksConfig, LimitsConfig, LeaseConfig, SpecConfig, HqConfig)
235+
config/claude.rs # Claude MCP isolation config helpers
236+
templates.rs # Embedded Markdown templates written by init/resource fallback
237+
specs.rs # Spec discovery, milestone parsing, selected milestone resolution
238+
agent_id.rs # Stable agent IDs and MCP server names
239+
agents/ # Agent launcher/config adapters for Claude Code, Codex, Qwen Code
240+
agents/mod.rs # SupervisorAgent/ExecutorAgent traits, AgentRunMode, MCP config entry helpers, agent parsing
241+
agents/claude/mod.rs # Claude Code launchers, model override handling, MCP isolation, role-scoped config paths
242+
agents/codex/mod.rs # Codex launchers, stdin prompt transport, TOML MCP config and tool approvals
243+
agents/qwen/mod.rs # Qwen Code launchers, model override handling, JSON settings tool approvals
244+
platform/ # OS-specific process, shell, and parent-lifecycle helpers
230245
state/machine.rs # TaskState enum + StateData + transition methods + lease helpers
231246
state/store.rs # Async read/write of .ferrus/ files; open_lock_file, claim_state
232247
state/agents.rs # AgentEntry, AgentsRegistry — .ferrus/agents.json lifecycle tracking
233248
update_check.rs # HQ startup version-check helper (crates.io sparse index + local cache)
234249
checks/runner.rs # Spawn check subprocesses, collect output
235250
hq/mod.rs # HQ entry point; HqContext; tokio::select! loop; transition_action
236251
hq/state_watcher.rs # Background task: polls STATE.json every 250ms, sends on watch channel
237-
hq/tui.rs # Terminal UI (crossterm): App event loop, UiMessage, StatusSnapshot; autocomplete, command history, status line, confirmation dialogs
252+
hq/tui.rs # Terminal UI (crossterm): App event loop, UiMessage, StatusSnapshot; autocomplete, command history, spec/milestone status line, confirmation/selection dialogs, AwaitingHuman answer hint
238253
hq/commands.rs # ShellCommand enum, parse_command() via clap + shlex
239254
hq/display.rs # Display wrapper: sends UiMessage to TUI channel (info, error, transition, status, suspend, resume, confirm)
240255
hq/agent_manager.rs # agent spawn helpers (headless for executor, reviewer, consultant); HeadlessHandle; agents.json updates
241256
server/mod.rs # neva App setup; constructs agent_id, wires closures
242-
server/tools/ # One file per MCP tool
257+
server/tools/ # One file per MCP tool; check_gate.rs is the shared check runner/report helper
258+
answer.rs # /answer — writes ANSWER.md and restores AwaitingHuman state
243259
heartbeat.rs # /heartbeat — lease renewal
244260
wait_for_task.rs # /wait_for_task — atomic claim loop (STATE.lock + fs2)
245261
wait_for_review.rs # /wait_for_review — same pattern for Supervisor
262+
check_gate.rs # Shared final/diagnostic check execution and report formatting
246263
consult.rs # /consult — writes CONSULT_REQUEST.md and transitions to Consultation
247264
respond_consult.rs # /respond_consult — records the supervisor consultation response
248265
wait_for_consult.rs # /wait_for_consult — polls CONSULT_RESPONSE.md, restores state, returns answer
249266
ask_human.rs # /ask_human — writes QUESTION.md, transitions to AwaitingHuman
250267
wait_for_answer.rs # /wait_for_answer — polls ANSWER.md, restores state, returns answer
251268
```
252269

270+
## Agent Adapter Pattern
271+
272+
Backend-specific CLI behavior belongs in `src/agents/{claude,codex,qwen}`. Shared orchestration should use the `SupervisorAgent` and `ExecutorAgent` traits from `src/agents/mod.rs` instead of matching on a concrete CLI. New agents need both role adapters, model normalization, headless prompt transport if needed, version/config entry behavior, registration wiring, and focused tests.
273+
253274
<!-- ferrus-supervisor-instructions -->
254275
## Ferrus Supervisor
255276

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "ferrus"
3-
version = "0.2.7-alpha.3"
3+
version = "0.2.7-alpha.4"
44
edition = "2024"
55
rust-version = "1.95.0"
66
license = "Apache-2.0"

README.md

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# ferrus
22

3-
[![Ferrus version](https://img.shields.io/badge/ferrus-0.2.7--alpha.3-orange)](https://crates.io/crates/ferrus)
3+
[![Ferrus version](https://img.shields.io/badge/ferrus-0.2.7--alpha.4-orange)](https://crates.io/crates/ferrus)
44
[![Rust version](https://img.shields.io/badge/rustc-1.95+-964B00)](https://releases.rs/docs/1.95.0/)
55
[![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/RomanEmreis/ferrus/blob/main/LICENSE)
66
[![Rust](https://github.com/RomanEmreis/ferrus/actions/workflows/rust.yml/badge.svg)](https://github.com/RomanEmreis/ferrus/actions/workflows/rust.yml)
@@ -29,6 +29,8 @@ Ferrus works with existing coding agents:
2929

3030
Agents are treated as interchangeable workers — ferrus provides the runtime, coordination, and state.
3131

32+
Internally, agent support is normalized through `src/agents/`: `mod.rs` defines the shared Supervisor/Executor contracts and MCP config entry shape, while `claude/`, `codex/`, and `qwen/` adapt each CLI's launch flags, model overrides, headless prompt transport, and local permission/config conventions.
33+
3234
> 💡 **Status**: ferrus is currently in alpha and not ready for production.
3335
3436
[Tutorial](https://romanemreis.github.io/ferrus-docs/) | [Roadmap](https://github.com/RomanEmreis/ferrus/blob/main/docs/milestones.md)
@@ -98,6 +100,9 @@ On Linux and macOS for `x86_64` and `aarch64`/`arm64`, `install.sh` downloads th
98100
| `/task --manual` | Define a free-form task without selected milestone context |
99101
| `/spec` | Draft, approve, and save a feature specification |
100102
| `/milestones` | Select the current spec and milestone |
103+
| `/reset-spec` | Clear the selected spec and milestone |
104+
| `/check` | Run the Ferrus check gate from HQ, using the normal task-state rules |
105+
| `/check --force` | Run configured checks from HQ without modifying state |
101106
| `/supervisor` | Open an interactive supervisor session (no initial prompt) |
102107
| `/executor` | Open an interactive executor session (no initial prompt) |
103108
| `/resume` | Manually resume the executor headlessly; also recovers Consultation by relaunching both supervisor and executor |
@@ -107,8 +112,9 @@ On Linux and macOS for `x86_64` and `aarch64`/`arm64`, `install.sh` downloads th
107112
| `/stop` | Stop all running agent sessions (prompts for confirmation) |
108113
| `/reset` | Reset state to Idle and clear task files (prompts for confirmation) |
109114
| `/init [--agents-path]` | Initialize ferrus in the current directory |
110-
| `/register` | Register agent configs (same as `ferrus register`) |
111-
| `/model` | Update the supervisor or executor model override |
115+
| `/register [--supervisor <agent>] [--executor <agent>]` | Register Claude Code or Codex configs from HQ |
116+
| `/model <supervisor|executor> <model>` | Update the supervisor or executor model override |
117+
| `/model <supervisor|executor> --clear` | Clear the supervisor or executor model override |
112118
| `/help` | List all HQ commands |
113119
| `/quit` | Exit HQ |
114120

@@ -151,7 +157,7 @@ Idle
151157
└─► Reviewing ← submit (final check passed)
152158
```
153159

154-
Any active Executor work state (Executing, Addressing, Checking) can pause to `Consultation` via `/consult`. HQ spawns the configured Supervisor in consultation mode, and the executor immediately calls `/wait_for_consult` to block until the Supervisor answers via `/respond_consult`.
160+
Any active Executor work state (Executing, Addressing) can pause to `Consultation` via `/consult`. HQ spawns the configured Supervisor in consultation mode, and the executor immediately calls `/wait_for_consult` to block until the Supervisor answers via `/respond_consult`.
155161

156162
Any active state, including `Consultation`, can pause to `AwaitingHuman` via `/ask_human`. The agent immediately calls `/wait_for_answer` to block until the human responds. The human types their answer in the HQ terminal (raw text, no slash prefix). `/wait_for_answer` restores the previous state and returns the answer.
157163

@@ -166,8 +172,9 @@ Any active state, including `Consultation`, can pause to `AwaitingHuman` via `/a
166172

167173
Scaffolds ferrus in the current project (default `--agents-path .agents`):
168174

169-
- Creates `ferrus.toml` with default check commands and limits
175+
- Creates `ferrus.toml` with default limits and an empty check command list
170176
- Creates `.ferrus/` runtime directory with all state files and `logs/`
177+
- Creates `docs/specs/` for approved feature specifications
171178
- Creates skill files agents load to understand their role:
172179
- `<agents-path>/skills/ferrus/SKILL.md` — general overview
173180
- `<agents-path>/skills/ferrus-supervisor/SKILL.md` + `ROLE.md`
@@ -184,13 +191,13 @@ Starts the agent coordination server on stdio. Agents load this as an MCP server
184191
| `executor` | `wait_for_task`, `check`, `consult`, `submit`, `wait_for_consult`, `wait_for_answer`, `ask_human`, `answer`, `status`, `reset`, `heartbeat` |
185192
| *(omitted)* | All tools |
186193

187-
### `ferrus register --supervisor <agent> [--supervisor-model <model>] --executor <agent> [--executor-model <model>]`
194+
### `ferrus register [--supervisor <agent>] [--supervisor-model <model>] [--executor <agent>] [--executor-model <model>]`
188195

189-
Writes agent config files so they automatically load `ferrus serve` as a tool server, and adds only the selected agents' local files to `.gitignore`. Supported agents:
196+
Writes agent config files so they automatically load `ferrus serve` as a tool server, and adds only the selected agents' local files to `.gitignore`. At least one of `--supervisor` or `--executor` is required; each model flag requires the matching role flag. Supported agents:
190197

191198
| Agent | Config written |
192199
|---|---|
193-
| `claude-code` | `.mcp.json` + `.claude/settings.local.json` permissions |
200+
| `claude-code` | `.claude/mcp-supervisor.json` or `.claude/mcp-executor.json` + `.claude/settings.local.json` permissions |
194201
| `codex` | `.codex/config.toml` |
195202
| `qwen-code` | `.qwen/settings.json` |
196203

@@ -238,6 +245,7 @@ Check commands run in the directory where `ferrus serve` was started. Full outpu
238245
|---|---|
239246
| `STATE.json` | Current state, lease fields, retry/cycle counters, schema version, timestamp |
240247
| `STATE.lock` | Advisory lock file for atomic claiming (do not delete) |
248+
| `agents.json` | Runtime registry for agent sessions, statuses, PIDs, and log ownership |
241249
| `TASK.md` | Task description written by Supervisor |
242250
| `REVIEW.md` | Supervisor rejection notes |
243251
| `SUBMISSION.md` | Executor submission notes |

0 commit comments

Comments
 (0)