forgeo-cli 0.6.0__tar.gz → 0.7.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/CHANGELOG.md +27 -1
  2. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/PKG-INFO +75 -32
  3. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/README.md +74 -31
  4. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/docs/agent-contract.md +23 -11
  5. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/docs/backlog.md +6 -6
  6. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/docs/cli-reference.md +61 -36
  7. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/docs/configuration.md +54 -34
  8. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/docs/getting-started.md +10 -0
  9. forgeo_cli-0.7.0/docs/index.md +67 -0
  10. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/docs/web-console-api.md +6 -5
  11. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/install.sh +1 -1
  12. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/pyproject.toml +1 -1
  13. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/src/forgeo/__init__.py +1 -1
  14. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/src/forgeo/agent.py +8 -3
  15. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/src/forgeo/backlog.py +6 -10
  16. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/src/forgeo/central.py +66 -62
  17. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/src/forgeo/cli.py +106 -48
  18. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/src/forgeo/config.py +3 -1
  19. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/src/forgeo/daemon.py +2 -3
  20. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/src/forgeo/daemon_control.py +37 -11
  21. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/src/forgeo/forgeo.py +117 -19
  22. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/src/forgeo/models.py +14 -1
  23. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/src/forgeo/notify.py +29 -22
  24. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/src/forgeo/runs.py +1 -5
  25. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/src/forgeo/setup.py +3 -1
  26. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/src/forgeo/update.py +1 -7
  27. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/src/forgeo/validate.py +21 -0
  28. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/src/forgeo/web/central/central.js +1 -0
  29. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/tests/conftest.py +15 -0
  30. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/tests/test_agent.py +16 -0
  31. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/tests/test_backlog.py +0 -54
  32. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/tests/test_cli.py +187 -4
  33. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/tests/test_factory.py +136 -0
  34. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/tests/test_install.py +1 -1
  35. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/tests/test_models.py +17 -0
  36. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/tests/test_update.py +0 -5
  37. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/tests/test_web.py +5 -1
  38. forgeo_cli-0.6.0/docs/index.md +0 -130
  39. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/.github/workflows/ci.yml +0 -0
  40. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/.gitignore +0 -0
  41. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/CONTRIBUTING.md +0 -0
  42. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/LICENSE +0 -0
  43. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/config/nginx-forgeo.conf +0 -0
  44. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/docs/img/console.png +0 -0
  45. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/docs/img/logo.png +0 -0
  46. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/docs/img/title.svg +0 -0
  47. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/forgeo.spec +0 -0
  48. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/mkdocs.yml +0 -0
  49. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/scripts/__init__.py +0 -0
  50. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/scripts/render_homebrew_formula.py +0 -0
  51. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/src/forgeo/__main__.py +0 -0
  52. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/src/forgeo/backlog_http.py +0 -0
  53. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/src/forgeo/git.py +0 -0
  54. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/src/forgeo/instances.py +0 -0
  55. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/src/forgeo/io.py +0 -0
  56. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/src/forgeo/oauth.py +0 -0
  57. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/src/forgeo/paths.py +0 -0
  58. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/src/forgeo/web/central/central.css +0 -0
  59. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/src/forgeo/web/central/index.html +0 -0
  60. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/src/forgeo/web/central/instance.html +0 -0
  61. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/src/forgeo/web/central/login.html +0 -0
  62. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/src/forgeo/web/style.css +0 -0
  63. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/src/forgeo/web_common.py +0 -0
  64. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/tests/test_backlog_http.py +0 -0
  65. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/tests/test_daemon.py +0 -0
  66. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/tests/test_git.py +0 -0
  67. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/tests/test_instances.py +0 -0
  68. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/tests/test_io.py +0 -0
  69. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/tests/test_oauth.py +0 -0
  70. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/tests/test_paths.py +0 -0
  71. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/tests/test_remote_backlog_cycle.py +0 -0
  72. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/tests/test_render_homebrew.py +0 -0
  73. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/tests/test_runs.py +0 -0
  74. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/tests/test_setup.py +0 -0
  75. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/tests/test_web_common.py +0 -0
  76. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/tests/test_web_lock.py +0 -0
  77. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/www/404.html +0 -0
  78. {forgeo_cli-0.6.0 → forgeo_cli-0.7.0}/www/index.html +0 -0
@@ -7,6 +7,31 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.7.0] - 2026-08-16
11
+
12
+ ### Added
13
+
14
+ - `task_context` config key: a path to a file (e.g. `CONTEXT.md`) whose
15
+ contents are prepended to every agent instruction — tasks and refactoring
16
+ runs alike — before the task description. The agent gets the high-level
17
+ project overview instead of only the isolated task; the file is re-read on
18
+ every run, so the agent's own updates are picked up on the next cycle. A
19
+ missing or unreadable file never fails a cycle: it is logged, `forgeo
20
+ validate` reports it as a warning, and the run proceeds with the bare
21
+ instruction.
22
+ - The default agent prompt (used by `forgeo init`) now tells the agent to
23
+ read `AGENTS.md` (and `CONTEXT.md` if present) at the start of the session
24
+ and to keep them updated when a change materially affects the project
25
+ overview.
26
+
27
+ - `forgeo run --task <id>` runs exactly one specific `OPEN` task by id and
28
+ exits, instead of letting `forgeo once` pick the oldest one — for triage:
29
+ rerun a `FAILED` task (after reopening it) or try a risky task now. It
30
+ shares the same per-forgeo lock as the daemon and `forgeo once`, so it
31
+ never overlaps them; it refuses with a clear error when the task does not
32
+ exist or is not `OPEN`, and while another daemon/`once`/`run` holds the
33
+ lock.
34
+
10
35
  ## [0.6.0] - 2026-08-14
11
36
 
12
37
  ### Added
@@ -283,7 +308,8 @@ Initial release of the scheduled, agent-driven software forgeo.
283
308
  overlapping-run skipping.
284
309
  - Dogfooding docs removed; local configs kept out of the repository.
285
310
 
286
- [Unreleased]: https://github.com/lucaGazzola/forgeo/compare/v0.6.0...HEAD
311
+ [Unreleased]: https://github.com/lucaGazzola/forgeo/compare/v0.7.0...HEAD
312
+ [0.7.0]: https://github.com/lucaGazzola/forgeo/compare/v0.6.0...v0.7.0
287
313
  [0.6.0]: https://github.com/lucaGazzola/forgeo/compare/v0.5.0...v0.6.0
288
314
  [0.5.0]: https://github.com/lucaGazzola/forgeo/compare/v0.4.0...v0.5.0
289
315
  [0.4.0]: https://github.com/lucaGazzola/forgeo/compare/v0.3.0...v0.4.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: forgeo-cli
3
- Version: 0.6.0
3
+ Version: 0.7.0
4
4
  Summary: A scheduled software forgeo: executes backlog tasks on main, refactors when idle, and writes BLOCKER.md when it needs human input.
5
5
  Project-URL: Homepage, https://forgeo.org
6
6
  Project-URL: Documentation, https://forgeo.org
@@ -83,50 +83,93 @@ agent CLI.
83
83
 
84
84
  The full walkthrough is in [Getting started](docs/getting-started.md).
85
85
 
86
- ```bash
87
- # 1. Install (any one of these)
86
+ ### 1. Install the CLI
87
+
88
+ Pick any one installer (no root needed; re-running it upgrades Forgeo).
88
89
 
89
- # Homebrew (macOS / Linux)
90
+ ```bash
91
+ # Homebrew (macOS / Linux): prebuilt binary, no Python required
90
92
  brew install lucaGazzola/forgeo/forgeo
91
93
 
92
- # or: the one-liner (prebuilt binary, no Python required)
94
+ # One-liner (Linux / macOS / Windows): prebuilt binary, falls back to pip
93
95
  curl -fsSL https://forgeo.org/install.sh | bash
94
96
 
95
- # or: pipx
97
+ # pip (Python 3.11+)
96
98
  pipx install forgeo-cli
99
+ ```
97
100
 
98
- # 2. Create your Forgeo (guided wizard, run from your project root)
99
- forgeo init
101
+ ### 2. Create your Forgeo
100
102
 
101
- # 3. Start Forgeo (detached in the background; exits immediately)
102
- forgeo start # every interval_minutes, implement the oldest OPEN task (dependencies first)
103
- forgeo stop # stop the daemon again
103
+ ```bash
104
+ forgeo init
104
105
  ```
105
106
 
106
- `forgeo init` writes `forgeo.yaml` and a `.forgeo/` folder for the backlog
107
- and logs. Fill the backlog with plain JSON tasks (see
108
- [Backlog format](docs/backlog.md)) or add them from the web console while
109
- it runs, Forgeo does the rest. Open the dashboard with `forgeo web` (default <http://0.0.0.0:8790>), or keep it always-on with `forgeo web -d` (stop it with `forgeo web stop`, check it with `forgeo web status`):
107
+ Guided wizard, run from your project root. Writes `forgeo.yaml` (the
108
+ config) and a `.forgeo/` folder for the backlog, logs and blocker files.
109
+
110
+ The base flow is then three steps: fill the backlog, check the
111
+ configuration, start the daemon.
112
+
113
+ ### 3. Fill the backlog
114
+
115
+ ```bash
116
+ # Either: edit the backlog file by hand — a plain JSON task list (see
117
+ # Backlog format), created on first use:
118
+ # .forgeo/backlog.json
119
+
120
+ # Or: add tasks from the web console once your forgeo is registered
121
+ # (first `forgeo start` registers it automatically):
122
+ forgeo web # dashboard at http://0.0.0.0:8790, or keep it on with `forgeo web -d`
123
+ ```
110
124
 
111
125
  ![Forgeo web console](docs/img/console.png)
112
126
 
113
- By default the dashboard is open to anyone who can reach the port. On a
114
- shared host, protect it with bearer-token auth: `forgeo web --token`
115
- generates a token (printed once, saved to `~/.config/forgeo/web.toml`) and
116
- requires `Authorization: Bearer <token>` on every `/api/*` route — see
117
- [Web console & HTTP API](docs/web-console-api.md).
118
-
119
- One-off commands: `forgeo once` (single cycle), `forgeo status` (summary),
120
- `forgeo validate` (read-only dry run before starting), `forgeo stop`,
121
- `forgeo restart`, every command is in the
122
- [CLI reference](docs/cli-reference.md).
123
-
124
- You can run several factories at once, one per repository, each config is
125
- fully independent (own backlog, logs, locks). Register each `forgeo.yaml`
126
- in the instance registry with `forgeo instance add NAME --config PATH`,
127
- manage any of them by name with `forgeo start/status/stop --name NAME`,
128
- list them all with `forgeo list`, and get one aggregate overview with the
129
- central dashboard, `forgeo web`.
127
+ ### 4. Check the configuration
128
+
129
+ ```bash
130
+ forgeo validate
131
+ ```
132
+
133
+ Read-only dry run before the first start: verifies `forgeo.yaml`, the git
134
+ repo, branch and remote, that the backlog parses (fetching it once when it
135
+ is an HTTP endpoint), the agent command, and the lock state. Never invokes
136
+ the agent and writes nothing.
137
+
138
+ ### 5. Start the daemon
139
+
140
+ ```bash
141
+ forgeo start
142
+ ```
143
+
144
+ Starts the daemon **detached in the background** and exits. Every
145
+ `interval_minutes` it runs one cycle: pick the oldest `OPEN` task whose
146
+ dependencies are all `COMPLETED`, run your coding agent on it, commit the
147
+ result. When the backlog is empty, the same agent runs a refactoring pass
148
+ over the codebase instead.
149
+
150
+ ### Day-to-day commands
151
+
152
+ ```bash
153
+ forgeo status # Config, backlog counts, next runnable task, daemon running?, last outcome
154
+ forgeo once # Run exactly one cycle in the foreground, no daemon left behind
155
+ forgeo run --task SELF-012 # Run one specific OPEN task now (triage)
156
+ forgeo stop # Stop the background daemon
157
+ forgeo restart # Stop and start again (re-reads forgeo.yaml after edits)
158
+ forgeo web # Dashboard: every instance's backlog, run history and logs
159
+ ```
160
+
161
+ `forgeo web` defaults to an open dashboard on `http://0.0.0.0:8790`; on a
162
+ shared host protect it with `forgeo web --token` (requires
163
+ `Authorization: Bearer <token>` on every `/api/*` route — see
164
+ [Web console & HTTP API](docs/web-console-api.md)).
165
+
166
+ ### Multiple repositories (instances)
167
+
168
+ Run several factories at once, one per repository; each config is fully
169
+ independent (own backlog, logs, locks). Register each `forgeo.yaml` with
170
+ `forgeo instance add NAME --config PATH`, manage any of them by name with
171
+ `forgeo start/status/stop --name NAME`, list them all with `forgeo list`,
172
+ and get one aggregate overview with the central dashboard, `forgeo web`.
130
173
 
131
174
  ## Documentation
132
175
 
@@ -29,50 +29,93 @@ agent CLI.
29
29
 
30
30
  The full walkthrough is in [Getting started](docs/getting-started.md).
31
31
 
32
- ```bash
33
- # 1. Install (any one of these)
32
+ ### 1. Install the CLI
33
+
34
+ Pick any one installer (no root needed; re-running it upgrades Forgeo).
34
35
 
35
- # Homebrew (macOS / Linux)
36
+ ```bash
37
+ # Homebrew (macOS / Linux): prebuilt binary, no Python required
36
38
  brew install lucaGazzola/forgeo/forgeo
37
39
 
38
- # or: the one-liner (prebuilt binary, no Python required)
40
+ # One-liner (Linux / macOS / Windows): prebuilt binary, falls back to pip
39
41
  curl -fsSL https://forgeo.org/install.sh | bash
40
42
 
41
- # or: pipx
43
+ # pip (Python 3.11+)
42
44
  pipx install forgeo-cli
45
+ ```
43
46
 
44
- # 2. Create your Forgeo (guided wizard, run from your project root)
45
- forgeo init
47
+ ### 2. Create your Forgeo
46
48
 
47
- # 3. Start Forgeo (detached in the background; exits immediately)
48
- forgeo start # every interval_minutes, implement the oldest OPEN task (dependencies first)
49
- forgeo stop # stop the daemon again
49
+ ```bash
50
+ forgeo init
50
51
  ```
51
52
 
52
- `forgeo init` writes `forgeo.yaml` and a `.forgeo/` folder for the backlog
53
- and logs. Fill the backlog with plain JSON tasks (see
54
- [Backlog format](docs/backlog.md)) or add them from the web console while
55
- it runs, Forgeo does the rest. Open the dashboard with `forgeo web` (default <http://0.0.0.0:8790>), or keep it always-on with `forgeo web -d` (stop it with `forgeo web stop`, check it with `forgeo web status`):
53
+ Guided wizard, run from your project root. Writes `forgeo.yaml` (the
54
+ config) and a `.forgeo/` folder for the backlog, logs and blocker files.
55
+
56
+ The base flow is then three steps: fill the backlog, check the
57
+ configuration, start the daemon.
58
+
59
+ ### 3. Fill the backlog
60
+
61
+ ```bash
62
+ # Either: edit the backlog file by hand — a plain JSON task list (see
63
+ # Backlog format), created on first use:
64
+ # .forgeo/backlog.json
65
+
66
+ # Or: add tasks from the web console once your forgeo is registered
67
+ # (first `forgeo start` registers it automatically):
68
+ forgeo web # dashboard at http://0.0.0.0:8790, or keep it on with `forgeo web -d`
69
+ ```
56
70
 
57
71
  ![Forgeo web console](docs/img/console.png)
58
72
 
59
- By default the dashboard is open to anyone who can reach the port. On a
60
- shared host, protect it with bearer-token auth: `forgeo web --token`
61
- generates a token (printed once, saved to `~/.config/forgeo/web.toml`) and
62
- requires `Authorization: Bearer <token>` on every `/api/*` route — see
63
- [Web console & HTTP API](docs/web-console-api.md).
64
-
65
- One-off commands: `forgeo once` (single cycle), `forgeo status` (summary),
66
- `forgeo validate` (read-only dry run before starting), `forgeo stop`,
67
- `forgeo restart`, every command is in the
68
- [CLI reference](docs/cli-reference.md).
69
-
70
- You can run several factories at once, one per repository, each config is
71
- fully independent (own backlog, logs, locks). Register each `forgeo.yaml`
72
- in the instance registry with `forgeo instance add NAME --config PATH`,
73
- manage any of them by name with `forgeo start/status/stop --name NAME`,
74
- list them all with `forgeo list`, and get one aggregate overview with the
75
- central dashboard, `forgeo web`.
73
+ ### 4. Check the configuration
74
+
75
+ ```bash
76
+ forgeo validate
77
+ ```
78
+
79
+ Read-only dry run before the first start: verifies `forgeo.yaml`, the git
80
+ repo, branch and remote, that the backlog parses (fetching it once when it
81
+ is an HTTP endpoint), the agent command, and the lock state. Never invokes
82
+ the agent and writes nothing.
83
+
84
+ ### 5. Start the daemon
85
+
86
+ ```bash
87
+ forgeo start
88
+ ```
89
+
90
+ Starts the daemon **detached in the background** and exits. Every
91
+ `interval_minutes` it runs one cycle: pick the oldest `OPEN` task whose
92
+ dependencies are all `COMPLETED`, run your coding agent on it, commit the
93
+ result. When the backlog is empty, the same agent runs a refactoring pass
94
+ over the codebase instead.
95
+
96
+ ### Day-to-day commands
97
+
98
+ ```bash
99
+ forgeo status # Config, backlog counts, next runnable task, daemon running?, last outcome
100
+ forgeo once # Run exactly one cycle in the foreground, no daemon left behind
101
+ forgeo run --task SELF-012 # Run one specific OPEN task now (triage)
102
+ forgeo stop # Stop the background daemon
103
+ forgeo restart # Stop and start again (re-reads forgeo.yaml after edits)
104
+ forgeo web # Dashboard: every instance's backlog, run history and logs
105
+ ```
106
+
107
+ `forgeo web` defaults to an open dashboard on `http://0.0.0.0:8790`; on a
108
+ shared host protect it with `forgeo web --token` (requires
109
+ `Authorization: Bearer <token>` on every `/api/*` route — see
110
+ [Web console & HTTP API](docs/web-console-api.md)).
111
+
112
+ ### Multiple repositories (instances)
113
+
114
+ Run several factories at once, one per repository; each config is fully
115
+ independent (own backlog, logs, locks). Register each `forgeo.yaml` with
116
+ `forgeo instance add NAME --config PATH`, manage any of them by name with
117
+ `forgeo start/status/stop --name NAME`, list them all with `forgeo list`,
118
+ and get one aggregate overview with the central dashboard, `forgeo web`.
76
119
 
77
120
  ## Documentation
78
121
 
@@ -19,18 +19,28 @@ the process environment is augmented as follows:
19
19
 
20
20
  | Variable | Meaning |
21
21
  | --- | --- |
22
- | `FORGEO_TASK` | The full instruction for this run: title, blank line, description, and an "Acceptance criteria:" list when present. |
23
- | `FORGEO_REPO` | The absolute path of the repository. |
24
- | `FORGEO_BRANCH` | The branch everything is committed to (default `main`). |
25
- | *every `agent_env` key* | Any extra variables from `agent_env` in the config. |
26
- | *inherited environment* | The daemon's own environment. |
22
+ | <span style="white-space: nowrap">`FORGEO_TASK`</span> | The full instruction for this run: the project context when `task_context` is configured, then title, blank line, description, and an "Acceptance criteria:" list when present. |
23
+ | <span style="white-space: nowrap">`FORGEO_REPO`</span> | The absolute path of the repository. |
24
+ | <span style="white-space: nowrap">`FORGEO_BRANCH`</span> | The branch everything is committed to (default `main`). |
25
+ | <span style="white-space: nowrap">*every `agent_env` key*</span> | Any extra variables from `agent_env` in the config. |
26
+ | <span style="white-space: nowrap">*inherited environment*</span> | The daemon's own environment. |
27
27
 
28
28
  `FORGEO_*` variables are set unconditionally and take precedence over both the
29
29
  inherited environment and `agent_env`.
30
30
 
31
+ ### The task is not the whole picture
32
+
33
+ A task description is isolated by design: it describes one unit of work, not
34
+ the project. When `task_context` is set (see
35
+ [Configuration](configuration.md#task_context)), Forgeo prepends the contents
36
+ of that file — the high-level project overview — to `FORGEO_TASK` before the
37
+ task, under a `# Project context` heading, followed by the task under a
38
+ `# Task` heading. The file is re-read on every run, so an agent's own updates
39
+ to it are seen by the next cycle.
40
+
31
41
  For a refactoring run (empty backlog) the same contract applies: the refactor
32
- prompt arrives as `FORGEO_TASK` with the task id `REFACTOR` and title
33
- "Refactoring pass".
42
+ prompt arrives as `FORGEO_TASK` (with the context prepended when configured),
43
+ with the task id `REFACTOR` and title "Refactoring pass".
34
44
 
35
45
  ## Exit codes
36
46
 
@@ -38,10 +48,10 @@ The exit code decides the outcome of the run:
38
48
 
39
49
  | Exit code | Outcome | What happens |
40
50
  | --- | --- | --- |
41
- | `0` | **SUCCESS** | Everything is committed (`git add -A && git commit`) with the message `<title> (#<id>)`, pushed when a remote is set, and the task is marked `COMPLETED`. |
42
- | `no_changes_exit_code` (default `3`) | **SUCCESS, no changes** | The agent explicitly reports the task needs **no code change**: the task is marked `COMPLETED` without a commit (and the run record notes why). Only accepted when the working tree is clean. |
43
- | `blocked_exit_code` (default `2`) | **BLOCKED** | The agent needs a human decision. Partial work is committed as `<title> [partial]`, the agent's reason is persisted on the task (`blocker_reason`), optional Telegram and/or webhook notifications are sent, and the task is marked `BLOCKED`. `BLOCKER.md` is rendered from the backlog's `BLOCKED` tasks on the next cycle — real per-task reasons, never generic text — and disappears once the last one is resolved (reopen it from the web console). |
44
- | anything else | **ERROR** | Changes are discarded (`git reset --hard` + `git clean -fd`), the failure is logged, and the task is marked `FAILED`. |
51
+ | <span style="white-space: nowrap">`0`</span> | **SUCCESS** | Everything is committed (`git add -A && git commit`) with the message `<title> (#<id>)`, pushed when a remote is set, and the task is marked `COMPLETED`. |
52
+ | <span style="white-space: nowrap">`no_changes_exit_code` (default `3`)</span> | **SUCCESS, no changes** | The agent explicitly reports the task needs **no code change**: the task is marked `COMPLETED` without a commit (and the run record notes why). Only accepted when the working tree is clean. |
53
+ | <span style="white-space: nowrap">`blocked_exit_code` (default `2`)</span> | **BLOCKED** | The agent needs a human decision. Partial work is committed as `<title> [partial]`, the agent's reason is persisted on the task (`blocker_reason`), optional Telegram and/or webhook notifications are sent, and the task is marked `BLOCKED`. `BLOCKER.md` is rendered from the backlog's `BLOCKED` tasks on the next cycle — real per-task reasons, never generic text — and disappears once the last one is resolved (reopen it from the web console). |
54
+ | <span style="white-space: nowrap">anything else</span> | **ERROR** | Changes are discarded (`git reset --hard` + `git clean -fd`), the failure is logged, and the task is marked `FAILED`. |
45
55
 
46
56
  The blocked exit code is configurable via `blocked_exit_code` in
47
57
  [forgeo.yaml](configuration.md), and the no-change exit code via
@@ -125,6 +135,8 @@ agent_command: >
125
135
  Make the code changes requested below and nothing else. Do NOT run
126
136
  git commit, git push, or git add -A — Forgeo commits your work.
127
137
  Verify with the test suite where applicable.
138
+ Read AGENTS.md (and CONTEXT.md if present) at the start of the session;
139
+ if your change materially affects the project overview, keep them updated.
128
140
  $FORGEO_TASK"
129
141
  ```
130
142
 
@@ -80,10 +80,10 @@ cheap/fast model and hard ones to a frontier model:
80
80
 
81
81
  | Status | Meaning |
82
82
  | --- | --- |
83
- | `OPEN` | To be picked by Forgeo. |
84
- | `BLOCKED` | Waiting on a human decision; Forgeo pauses while any task is blocked. |
85
- | `COMPLETED` | The agent finished and the work was committed (and pushed). |
86
- | `FAILED` | The agent errored; changes were discarded and the reason is recorded in `failure_reason`. |
83
+ | <span style="white-space: nowrap">`OPEN`</span> | To be picked by Forgeo. |
84
+ | <span style="white-space: nowrap">`BLOCKED`</span> | Waiting on a human decision; Forgeo pauses while any task is blocked. |
85
+ | <span style="white-space: nowrap">`COMPLETED`</span> | The agent finished and the work was committed (and pushed). |
86
+ | <span style="white-space: nowrap">`FAILED`</span> | The agent errored; changes were discarded and the reason is recorded in `failure_reason`. |
87
87
 
88
88
  ## Retrying a failed task
89
89
 
@@ -298,8 +298,8 @@ then treats that endpoint exactly like the file:
298
298
 
299
299
  | When | Request |
300
300
  | --- | --- |
301
- | Every read | `GET <url>` returns the whole document |
302
- | Every write | `POST <url>` sends the whole document back |
301
+ | <span style="white-space: nowrap">Every read</span> | `GET <url>` returns the whole document |
302
+ | <span style="white-space: nowrap">Every write</span> | `POST <url>` sends the whole document back |
303
303
 
304
304
  ```yaml
305
305
  backlog: https://api.example.com/api/forgeo/backlog
@@ -1,7 +1,7 @@
1
1
  # CLI reference
2
2
 
3
3
  All commands read `forgeo.yaml` from the current directory; pass
4
- `--config <file>` to use a different one. `start`, `once`, `status`,
4
+ `--config <file>` to use a different one. `start`, `once`, `run`, `status`,
5
5
  `validate`, `stop` and `restart` also accept `--name <instance>` to resolve
6
6
  the config from the **instance registry** — see [`forgeo instance`](#forgeo-instance)
7
7
  below.
@@ -20,8 +20,8 @@ Guided first-time setup: interactively write a `forgeo.yaml`.
20
20
 
21
21
  | Flag | Description |
22
22
  | --- | --- |
23
- | `--config <file>` | Where to write the config (default `forgeo.yaml`). |
24
- | `--force` | Overwrite an existing config file. |
23
+ | <span style="white-space: nowrap">`--config <file>`</span> | Where to write the config (default `forgeo.yaml`). |
24
+ | <span style="white-space: nowrap">`--force`</span> | Overwrite an existing config file. |
25
25
 
26
26
  Exit codes:
27
27
 
@@ -41,10 +41,10 @@ foreground instead, interruptible with Ctrl-C.
41
41
 
42
42
  | Flag | Description |
43
43
  | --- | --- |
44
- | `--config <file>` | Forgeo YAML file (default `forgeo.yaml`). Mutually exclusive with `--name`. |
45
- | `--name <name>` | Registered instance name resolved from the registry. Mutually exclusive with `--config`. |
46
- | `--interval-minutes <n>` | Override the schedule interval from the config for this run. |
47
- | `-f`, `--foreground` | Run the daemon in the foreground instead of starting it detached. |
44
+ | <span style="white-space: nowrap">`--config <file>`</span> | Forgeo YAML file (default `forgeo.yaml`). Mutually exclusive with `--name`. |
45
+ | <span style="white-space: nowrap">`--name <name>`</span> | Registered instance name resolved from the registry. Mutually exclusive with `--config`. |
46
+ | <span style="white-space: nowrap">`--interval-minutes <n>`</span> | Override the schedule interval from the config for this run. |
47
+ | <span style="white-space: nowrap">`-f`, `--foreground`</span> | Run the daemon in the foreground instead of starting it detached. |
48
48
 
49
49
  The daemon wakes every `interval_minutes` and runs one cycle. When no config
50
50
  exists, `forgeo start` offers the guided setup. A second `start` (or `once`)
@@ -81,8 +81,8 @@ Run exactly **one cycle** and exit; no daemon needed.
81
81
 
82
82
  | Flag | Description |
83
83
  | --- | --- |
84
- | `--config <file>` | Forgeo YAML file (default `forgeo.yaml`). Mutually exclusive with `--name`. |
85
- | `--name <name>` | Registered instance name resolved from the registry. Mutually exclusive with `--config`. |
84
+ | <span style="white-space: nowrap">`--config <file>`</span> | Forgeo YAML file (default `forgeo.yaml`). Mutually exclusive with `--name`. |
85
+ | <span style="white-space: nowrap">`--name <name>`</span> | Registered instance name resolved from the registry. Mutually exclusive with `--config`. |
86
86
 
87
87
  `forgeo once` shares the run lock with the daemon, so it never overlaps a
88
88
  running `forgeo start` — useful to test a config or process a backlog without
@@ -92,13 +92,38 @@ Outcomes a cycle can produce:
92
92
 
93
93
  | Outcome | Meaning |
94
94
  | --- | --- |
95
- | `task` | A task ran and finished. |
96
- | `refactor` | A refactoring pass ran (backlog was empty). |
97
- | `blocked` | A `BLOCKED` task exists; `BLOCKER.md` re-rendered from the backlog; paused. |
98
- | `paused` | A blocker file exists; nothing ran. |
99
- | `dirty` | The working tree was dirty; the task was not started. |
100
- | `skipped` | A previous run was still in progress (daemon only). |
101
- | `error` | A cycle crashed (daemon only). |
95
+ | <span style="white-space: nowrap">`task`</span> | A task ran and finished. |
96
+ | <span style="white-space: nowrap">`refactor`</span> | A refactoring pass ran (backlog was empty). |
97
+ | <span style="white-space: nowrap">`blocked`</span> | A `BLOCKED` task exists; `BLOCKER.md` re-rendered from the backlog; paused. |
98
+ | <span style="white-space: nowrap">`paused`</span> | A blocker file exists; nothing ran. |
99
+ | <span style="white-space: nowrap">`dirty`</span> | The working tree was dirty; the task was not started. |
100
+ | <span style="white-space: nowrap">`skipped`</span> | A previous run was still in progress (daemon only). |
101
+ | <span style="white-space: nowrap">`error`</span> | A cycle crashed (daemon only). |
102
+
103
+ ## `forgeo run`
104
+
105
+ Run exactly **one specific task** by id and exit — no daemon, no waiting for
106
+ the backlog order. Use it for triage: rerun a `FAILED` task immediately
107
+ (after reopening it), or try a risky task right now instead of letting the
108
+ scheduler pick it later.
109
+
110
+ ```bash
111
+ forgeo run --task SELF-012
112
+ ```
113
+
114
+ | Flag | Description |
115
+ | --- | --- |
116
+ | <span style="white-space: nowrap">`--task <id>`</span> | Id of the `OPEN` task to run. **Required.** |
117
+ | <span style="white-space: nowrap">`--config <file>`</span> | Forgeo YAML file (default `forgeo.yaml`). Mutually exclusive with `--name`. |
118
+ | <span style="white-space: nowrap">`--name <name>`</span> | Registered instance name resolved from the registry. Mutually exclusive with `--config`. |
119
+
120
+ `forgeo run` shares the per-forgeo run lock with the daemon and `forgeo once`,
121
+ so it never overlaps them — it refuses (exit `1`) while the lock is held. It
122
+ also refuses (exit `1`) with a clear message when the task does not exist in
123
+ the backlog or its status is not `OPEN` (a `FAILED` task must be reopened
124
+ first, e.g. from the web console or by editing the backlog). On success it
125
+ prints `Cycle finished: <outcome>` and records the run in `runs.jsonl` like
126
+ any other task run.
102
127
 
103
128
  ## `forgeo status`
104
129
 
@@ -106,8 +131,8 @@ Print a read-only summary of Forgeo. Never starts an agent.
106
131
 
107
132
  | Flag | Description |
108
133
  | --- | --- |
109
- | `--config <file>` | Forgeo YAML file (default `forgeo.yaml`). Mutually exclusive with `--name`. |
110
- | `--name <name>` | Registered instance name resolved from the registry. Mutually exclusive with `--config`. |
134
+ | <span style="white-space: nowrap">`--config <file>`</span> | Forgeo YAML file (default `forgeo.yaml`). Mutually exclusive with `--name`. |
135
+ | <span style="white-space: nowrap">`--name <name>`</span> | Registered instance name resolved from the registry. Mutually exclusive with `--config`. |
111
136
 
112
137
  Output:
113
138
 
@@ -144,8 +169,8 @@ while a daemon is active.
144
169
 
145
170
  | Flag | Description |
146
171
  | --- | --- |
147
- | `--config <file>` | Forgeo YAML file (default `forgeo.yaml`). Mutually exclusive with `--name`. |
148
- | `--name <name>` | Registered instance name resolved from the registry. Mutually exclusive with `--config`. |
172
+ | <span style="white-space: nowrap">`--config <file>`</span> | Forgeo YAML file (default `forgeo.yaml`). Mutually exclusive with `--name`. |
173
+ | <span style="white-space: nowrap">`--name <name>`</span> | Registered instance name resolved from the registry. Mutually exclusive with `--config`. |
149
174
 
150
175
  It validates, reporting **all** problems at once:
151
176
 
@@ -187,9 +212,9 @@ first).
187
212
 
188
213
  | Flag | Description |
189
214
  | --- | --- |
190
- | `--config <file>` | Forgeo YAML file (default `forgeo.yaml`). Mutually exclusive with `--name`. |
191
- | `--name <name>` | Registered instance name resolved from the registry. Mutually exclusive with `--config`. |
192
- | `--timeout <seconds>` | How long to wait for the daemon to exit (default `600`). |
215
+ | <span style="white-space: nowrap">`--config <file>`</span> | Forgeo YAML file (default `forgeo.yaml`). Mutually exclusive with `--name`. |
216
+ | <span style="white-space: nowrap">`--name <name>`</span> | Registered instance name resolved from the registry. Mutually exclusive with `--config`. |
217
+ | <span style="white-space: nowrap">`--timeout <seconds>`</span> | How long to wait for the daemon to exit (default `600`). |
193
218
 
194
219
  Exit code is `0` on success, `1` when Forgeo is not running, the lock
195
220
  records a dead PID, or the daemon did not exit within the timeout.
@@ -210,17 +235,17 @@ values while running so its lock files are never detached from the config.
210
235
 
211
236
  | Flag | Description |
212
237
  | --- | --- |
213
- | `--config <file>` | Forgeo YAML file (default `forgeo.yaml`). Mutually exclusive with `--name`. |
214
- | `--name <name>` | Registered instance name resolved from the registry. Mutually exclusive with `--config`. |
215
- | `--timeout <seconds>` | How long to wait for the old daemon to exit (default `600`). |
238
+ | <span style="white-space: nowrap">`--config <file>`</span> | Forgeo YAML file (default `forgeo.yaml`). Mutually exclusive with `--name`. |
239
+ | <span style="white-space: nowrap">`--name <name>`</span> | Registered instance name resolved from the registry. Mutually exclusive with `--config`. |
240
+ | <span style="white-space: nowrap">`--timeout <seconds>`</span> | How long to wait for the old daemon to exit (default `600`). |
216
241
 
217
242
  On success it prints the new daemon PID and interval.
218
243
 
219
244
  ### `--config` vs `--name`
220
245
 
221
- On `start`, `once`, `status`, `validate`, `stop` and `restart`, `--name`
222
- resolves the `forgeo.yaml` from the instance registry instead of reading
223
- `--config`. The two flags are mutually exclusive — passing both is an
246
+ On `start`, `once`, `run`, `status`, `validate`, `stop` and `restart`,
247
+ `--name` resolves the `forgeo.yaml` from the instance registry instead of
248
+ reading `--config`. The two flags are mutually exclusive — passing both is an
224
249
  argparse error. An unknown instance name prints a clear error and exits
225
250
  non-zero.
226
251
 
@@ -244,7 +269,7 @@ differs from `config.name`.
244
269
 
245
270
  | Flag | Description |
246
271
  | --- | --- |
247
- | `--config <file>` | Path to the `forgeo.yaml` to register. **Required.** |
272
+ | <span style="white-space: nowrap">`--config <file>`</span> | Path to the `forgeo.yaml` to register. **Required.** |
248
273
 
249
274
  - The name must match `^[a-zA-Z0-9._-]+$`; invalid or duplicate names are
250
275
  rejected with a clear error (exit `1`).
@@ -273,11 +298,11 @@ running.
273
298
 
274
299
  | Flag | Description |
275
300
  | --- | --- |
276
- | `--host <address>` | Bind address (default `0.0.0.0`). |
277
- | `--port <port>` | Bind port (default `8790`). |
278
- | `-d`, `--detach` | Start the dashboard in the background and return once it binds. |
279
- | `--token [TOKEN]` | Require a bearer token on every `/api/*` route (see below). |
280
- | `--timeout <seconds>` | How long to wait for the dashboard to bind when detached (default `30`). |
301
+ | <span style="white-space: nowrap">`--host <address>`</span> | Bind address (default `0.0.0.0`). |
302
+ | <span style="white-space: nowrap">`--port <port>`</span> | Bind port (default `8790`). |
303
+ | <span style="white-space: nowrap">`-d`, `--detach`</span> | Start the dashboard in the background and return once it binds. |
304
+ | <span style="white-space: nowrap">`--token [TOKEN]`</span> | Require a bearer token on every `/api/*` route (see below). |
305
+ | <span style="white-space: nowrap">`--timeout <seconds>`</span> | How long to wait for the dashboard to bind when detached (default `30`). |
281
306
 
282
307
  Without `-d` the dashboard runs in the foreground; interrupt it with Ctrl-C
283
308
  or stop it from another terminal with `forgeo web stop`.
@@ -322,7 +347,7 @@ Stop the running dashboard gracefully (SIGTERM) and wait for it to exit.
322
347
 
323
348
  | Flag | Description |
324
349
  | --- | --- |
325
- | `--timeout <seconds>` | How long to wait for the dashboard to exit (default `30`). |
350
+ | <span style="white-space: nowrap">`--timeout <seconds>`</span> | How long to wait for the dashboard to exit (default `30`). |
326
351
 
327
352
  Exit code is `0` on success, `1` when the dashboard is not running, the lock
328
353
  records a dead PID, or it did not exit within the timeout. The lock file is