forgeo-cli 0.3.0__tar.gz → 0.5.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 (90) hide show
  1. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/.github/workflows/ci.yml +60 -1
  2. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/.gitignore +1 -0
  3. forgeo_cli-0.5.0/CHANGELOG.md +259 -0
  4. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/CONTRIBUTING.md +10 -3
  5. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/PKG-INFO +43 -28
  6. forgeo_cli-0.5.0/README.md +107 -0
  7. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/docs/agent-contract.md +35 -7
  8. forgeo_cli-0.5.0/docs/backlog.md +284 -0
  9. forgeo_cli-0.5.0/docs/cli-reference.md +346 -0
  10. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/docs/configuration.md +116 -2
  11. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/docs/getting-started.md +55 -22
  12. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/docs/index.md +41 -18
  13. forgeo_cli-0.5.0/docs/web-console-api.md +656 -0
  14. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/install.sh +29 -3
  15. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/pyproject.toml +1 -1
  16. forgeo_cli-0.5.0/scripts/__init__.py +0 -0
  17. forgeo_cli-0.5.0/scripts/render_homebrew_formula.py +119 -0
  18. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/src/forgeo/__init__.py +1 -1
  19. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/src/forgeo/agent.py +26 -4
  20. forgeo_cli-0.5.0/src/forgeo/backlog.py +554 -0
  21. forgeo_cli-0.5.0/src/forgeo/central.py +1440 -0
  22. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/src/forgeo/cli.py +413 -128
  23. forgeo_cli-0.5.0/src/forgeo/config.py +69 -0
  24. forgeo_cli-0.5.0/src/forgeo/daemon.py +425 -0
  25. forgeo_cli-0.5.0/src/forgeo/daemon_control.py +165 -0
  26. forgeo_cli-0.5.0/src/forgeo/forgeo.py +689 -0
  27. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/src/forgeo/git.py +14 -0
  28. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/src/forgeo/instances.py +1 -1
  29. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/src/forgeo/models.py +177 -2
  30. forgeo_cli-0.5.0/src/forgeo/notify.py +131 -0
  31. forgeo_cli-0.5.0/src/forgeo/runs.py +131 -0
  32. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/src/forgeo/setup.py +54 -12
  33. forgeo_cli-0.5.0/src/forgeo/update.py +172 -0
  34. forgeo_cli-0.5.0/src/forgeo/validate.py +221 -0
  35. forgeo_cli-0.5.0/src/forgeo/web/central/central.css +1096 -0
  36. forgeo_cli-0.5.0/src/forgeo/web/central/central.js +1761 -0
  37. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/src/forgeo/web/central/instance.html +106 -10
  38. forgeo_cli-0.5.0/src/forgeo/web/central/login.html +76 -0
  39. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/src/forgeo/web/style.css +7 -1
  40. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/src/forgeo/web_common.py +2 -0
  41. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/tests/conftest.py +11 -0
  42. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/tests/test_agent.py +105 -1
  43. forgeo_cli-0.5.0/tests/test_backlog.py +899 -0
  44. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/tests/test_cli.py +358 -9
  45. forgeo_cli-0.5.0/tests/test_daemon.py +383 -0
  46. forgeo_cli-0.5.0/tests/test_factory.py +947 -0
  47. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/tests/test_git.py +40 -0
  48. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/tests/test_install.py +3 -2
  49. forgeo_cli-0.5.0/tests/test_models.py +302 -0
  50. forgeo_cli-0.5.0/tests/test_render_homebrew.py +83 -0
  51. forgeo_cli-0.5.0/tests/test_runs.py +515 -0
  52. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/tests/test_setup.py +54 -6
  53. forgeo_cli-0.5.0/tests/test_update.py +205 -0
  54. forgeo_cli-0.5.0/tests/test_web.py +2169 -0
  55. forgeo_cli-0.5.0/tests/test_web_common.py +134 -0
  56. forgeo_cli-0.5.0/tests/test_web_lock.py +521 -0
  57. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/www/index.html +25 -25
  58. forgeo_cli-0.3.0/CHANGELOG.md +0 -114
  59. forgeo_cli-0.3.0/README.md +0 -92
  60. forgeo_cli-0.3.0/docs/backlog.md +0 -113
  61. forgeo_cli-0.3.0/docs/cli-reference.md +0 -211
  62. forgeo_cli-0.3.0/docs/web-console-api.md +0 -275
  63. forgeo_cli-0.3.0/src/forgeo/backlog.py +0 -206
  64. forgeo_cli-0.3.0/src/forgeo/central.py +0 -620
  65. forgeo_cli-0.3.0/src/forgeo/config.py +0 -36
  66. forgeo_cli-0.3.0/src/forgeo/daemon.py +0 -209
  67. forgeo_cli-0.3.0/src/forgeo/forgeo.py +0 -446
  68. forgeo_cli-0.3.0/src/forgeo/notify.py +0 -77
  69. forgeo_cli-0.3.0/src/forgeo/runs.py +0 -73
  70. forgeo_cli-0.3.0/src/forgeo/web/central/central.css +0 -380
  71. forgeo_cli-0.3.0/src/forgeo/web/central/central.js +0 -780
  72. forgeo_cli-0.3.0/tests/test_backlog.py +0 -225
  73. forgeo_cli-0.3.0/tests/test_daemon.py +0 -162
  74. forgeo_cli-0.3.0/tests/test_factory.py +0 -316
  75. forgeo_cli-0.3.0/tests/test_models.py +0 -127
  76. forgeo_cli-0.3.0/tests/test_runs.py +0 -216
  77. forgeo_cli-0.3.0/tests/test_web.py +0 -781
  78. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/LICENSE +0 -0
  79. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/config/nginx-forgeo.conf +0 -0
  80. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/docs/img/console.png +0 -0
  81. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/docs/img/logo.png +0 -0
  82. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/docs/img/title.svg +0 -0
  83. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/forgeo.spec +0 -0
  84. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/mkdocs.yml +0 -0
  85. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/src/forgeo/__main__.py +0 -0
  86. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/src/forgeo/io.py +0 -0
  87. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/src/forgeo/web/central/index.html +0 -0
  88. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/tests/test_instances.py +0 -0
  89. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/tests/test_io.py +0 -0
  90. {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/www/404.html +0 -0
@@ -35,7 +35,10 @@ jobs:
35
35
  fail-fast: false
36
36
  matrix:
37
37
  include:
38
- - os: ubuntu-latest
38
+ # Linux is built on ubuntu-22.04 (glibc 2.35) so the binary also
39
+ # runs on older distros (Homebrew-on-Linux, Ubuntu 22.04+): a build
40
+ # on ubuntu-latest (24.04) would require glibc >= 2.38.
41
+ - os: ubuntu-22.04
39
42
  asset: forgeo-linux-amd64
40
43
  binary: dist/forgeo
41
44
  - os: macos-15-intel
@@ -90,6 +93,24 @@ jobs:
90
93
  with:
91
94
  path: binaries
92
95
  merge-multiple: true
96
+ - name: Extract release notes from CHANGELOG.md
97
+ id: notes
98
+ run: |
99
+ python - "${{ github.ref_name }}" <<'EOF'
100
+ import re
101
+ import sys
102
+ import pathlib
103
+
104
+ version = sys.argv[1].removeprefix("v")
105
+ text = pathlib.Path("CHANGELOG.md").read_text(encoding="utf-8")
106
+ pattern = re.compile(
107
+ rf"^## \[{re.escape(version)}\] .*?\n(.*?)(?=^## \[|\Z)",
108
+ re.MULTILINE | re.DOTALL,
109
+ )
110
+ match = pattern.search(text)
111
+ notes = match.group(1).strip() if match else ""
112
+ pathlib.Path("release-body.md").write_text(notes, encoding="utf-8")
113
+ EOF
93
114
  - name: Publish GitHub Release
94
115
  uses: softprops/action-gh-release@v2
95
116
  with:
@@ -97,6 +118,44 @@ jobs:
97
118
  dist/*.whl
98
119
  dist/*.tar.gz
99
120
  binaries/*
121
+ body_path: release-body.md
122
+
123
+ publish-homebrew:
124
+ if: startsWith(github.ref, 'refs/tags/v')
125
+ needs: build-binaries
126
+ runs-on: ubuntu-latest
127
+ steps:
128
+ - uses: actions/checkout@v4
129
+ - uses: actions/setup-python@v5
130
+ with:
131
+ python-version: "3.11"
132
+ - name: Download binary artifacts
133
+ uses: actions/download-artifact@v4
134
+ with:
135
+ path: binaries
136
+ merge-multiple: true
137
+ - name: Render the Homebrew formula
138
+ run: python scripts/render_homebrew_formula.py "${{ github.ref_name }}" binaries > /tmp/forgeo.rb
139
+ - name: Publish the formula to the homebrew-forgeo tap
140
+ env:
141
+ TAP_REPO_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
142
+ run: |
143
+ set -eu
144
+ if [ -z "$TAP_REPO_TOKEN" ]; then
145
+ echo "::error::HOMEBREW_TAP_TOKEN secret is not set. Create a PAT with write access to lucaGazzola/homebrew-forgeo and store it as HOMEBREW_TAP_TOKEN; without it the Homebrew tap is not updated for this release."
146
+ exit 1
147
+ fi
148
+ git clone "https://x-access-token:${TAP_REPO_TOKEN}@github.com/lucaGazzola/homebrew-forgeo.git" tap
149
+ cp /tmp/forgeo.rb tap/Formula/forgeo.rb
150
+ git -C tap config user.name "Forgeo release bot"
151
+ git -C tap config user.email "forgeo-releases@users.noreply.github.com"
152
+ if git -C tap diff --quiet; then
153
+ echo "Formula unchanged; nothing to push."
154
+ else
155
+ git -C tap add Formula/forgeo.rb
156
+ git -C tap commit -m "forgeo ${{ github.ref_name }}"
157
+ git -C tap push origin main
158
+ fi
100
159
 
101
160
  publish-pypi:
102
161
  if: startsWith(github.ref, 'refs/tags/v')
@@ -27,6 +27,7 @@ build/
27
27
  dist/
28
28
 
29
29
  # AI assistant context
30
+ AGENTS.md
30
31
  CONTEXT.md
31
32
 
32
33
  # Local deploy script (server-specific paths)
@@ -0,0 +1,259 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [0.5.0] - 2026-08-14
11
+
12
+ ### Added
13
+
14
+ - `forgeo validate` (and the pre-flight check before a detached
15
+ `forgeo start`) distinguishes a repository with no commits yet: a clean
16
+ tree is now a warning — the first cycle creates the initial commit — while
17
+ a non-clean tree is a problem that names the fix
18
+ (`git add -A && git commit -m "Initial commit"`), since every file is
19
+ untracked and every cycle would otherwise refuse as dirty. Previously
20
+ "no commits" was always a hard problem with a misleading message.
21
+
22
+ - `forgeo start` now starts the daemon **detached in the background and
23
+ exits**, like `forgeo restart` and the web console's start button already
24
+ did; the daemon is managed with `forgeo stop`/`forgeo restart`/`forgeo
25
+ status`. `forgeo start -f` (`--foreground`) keeps the historical
26
+ foreground behavior. A detached start refuses while the per-forgeo lock is
27
+ held and runs the same read-only checks as `forgeo validate` first, so a
28
+ broken config fails fast instead of leaving a silently dead daemon.
29
+ `--interval-minutes` is forwarded to the detached daemon.
30
+
31
+ - The daemon reloads `forgeo.yaml` on the next cycle boundary when the file
32
+ changes (or on `SIGHUP`): a valid change is revalidated, logged, and used
33
+ from the next cycle; an invalid change is logged and the last valid config
34
+ stays in use. The web console's config save reflects this
35
+ (`restart_required: false`). Path changes (`repo`, `backlog`,
36
+ `blocker_file`, `log_file`) stay pinned to the daemon's startup values and
37
+ still need `forgeo restart`, so the daemon's lock files are never detached
38
+ from the config.
39
+
40
+ - Optional bearer-token auth for the central web dashboard (`forgeo web`):
41
+ `forgeo web --token` (or a `token` key in `~/.config/forgeo/web.toml`)
42
+ requires `Authorization: Bearer <token>` on every `/api/*` route and
43
+ answers `401` otherwise. `forgeo web --token` with no value generates a
44
+ token, prints it once on startup, and saves it (mode `0600`); a generated
45
+ token is only ever printed once. Static assets and the new token prompt
46
+ page (`/central/login.html`) stay reachable without a token, and a
47
+ `?token=...` URL signs the browser in automatically. With no flag and no
48
+ token file the dashboard keeps its historical open-by-default behavior.
49
+
50
+ - `forgeo validate` — a read-only dry run that checks whether a forgeo is
51
+ ready to run before starting it: the config schema, the repository (exists,
52
+ is a git repo, `git` on PATH), the branch and remote resolution, the
53
+ backlog parsing, a non-blank agent command, and the run lock state. It
54
+ reports every problem at once, never invokes the agent, and makes no writes
55
+ (no lock, no backlog changes). Exit code `0` when healthy, `1` with a
56
+ summary of problems otherwise. Supports `--config` and `--name`.
57
+
58
+ - `run_history_keep` config key: `runs.jsonl` is trimmed to that many records
59
+ on append (default `2000`), so a busy Forgeo's run history never grows
60
+ forever. Trimming is atomic (temp file + rename) and a failed trim is
61
+ logged and skipped, never fatal to the cycle; `run_history_keep: 0`
62
+ disables retention entirely (the previous grow-forever behavior).
63
+
64
+ - Persisted agent output per run: each `RunRecord` now stores a bounded tail
65
+ of the agent's stdout/stderr (last `run_output_lines` lines, default `200`),
66
+ so failed and blocked runs keep the full tail of what the agent said. The
67
+ web console's **History** tab shows it in a read-only, monospace,
68
+ collapsible view; `run_output_lines: 0` disables persistence, and records
69
+ written before the field existed render as empty.
70
+
71
+ - Backlog snapshots: before every agent run (and on daemon startup) Forgeo
72
+ copies the backlog to a rotating snapshot (`backlog.json.bak`,
73
+ `backlog.json.bak.1`, ... keeping the last 2 by default), and a read that
74
+ finds the backlog corrupt restores the newest valid snapshot in place —
75
+ with the corrupt file still preserved — instead of falling back to an
76
+ empty store. A missing backlog is a no-op.
77
+
78
+ - Task dependencies are now enforced when picking the next task: Forgeo picks
79
+ the oldest `OPEN` task whose `dependencies` are all `COMPLETED` instead of
80
+ the plain oldest `OPEN` task, so a task never runs before the work it
81
+ depends on. Unsatisfied dependencies (including ids that don't exist in the
82
+ backlog) are surfaced on `forgeo status` (`waiting on:` line) and in the web
83
+ console's task detail modal (*Waiting on dependencies* banner); the
84
+ `GET /api/instances/<name>/tasks*` responses annotate each task with an
85
+ `unsatisfied_dependencies` field.
86
+
87
+ - Homebrew install support: `brew install lucaGazzola/forgeo/forgeo`
88
+ installs the prebuilt binary on macOS (arm64/Intel) and Linux (Intel). The
89
+ `publish-homebrew` CI job re-renders the tap formula (sha256 + version)
90
+ from `scripts/render_homebrew_formula.py` on every release; it needs the
91
+ `HOMEBREW_TAP_TOKEN` repository secret (PAT with write access to
92
+ `lucaGazzola/homebrew-forgeo`). The update notification now also names
93
+ `brew upgrade lucaGazzola/forgeo/forgeo`.
94
+
95
+ - Update notification: when `forgeo start` or `forgeo once` begins a cycle,
96
+ Forgeo checks PyPI at most once a day and, if a newer `forgeo-cli` release
97
+ exists, prints/logs a short notice with the upgrade command. The check is
98
+ best-effort (short timeout, failures logged and skipped), never modifies
99
+ the install, and can be disabled with `FORGEO_UPDATE_CHECK=0`.
100
+
101
+ - Automatic retries for `FAILED` tasks: `failed_retry_max` config key (default
102
+ `0`, unchanged behavior) plus `failed_retry_wait_cycles` (default `1`) let a
103
+ transiently failed task move back to `OPEN` after a backoff and be run
104
+ again. A task that exhausts its budget stays `FAILED` with its original
105
+ `failure_reason`; a per-task `retries_left` field overrides the budget for
106
+ one task. `BLOCKED` tasks are never auto-retried. The retry count is
107
+ recorded in `runs.jsonl` (the run record that succeeds carries it), shown
108
+ in the web console (task cards/modal and a History-tab **retry** column),
109
+ and exposed by the tasks/runs API.
110
+
111
+ ### Fixed
112
+
113
+ - The Linux prebuilt binary is now built on Ubuntu 22.04 (glibc 2.35) instead
114
+ of 24.04 (glibc 2.38), so it runs on older distros (e.g. Ubuntu 22.04,
115
+ Debian 12, Homebrew-on-Linux). The 0.4.0 `forgeo-linux-amd64` release
116
+ asset was rebuilt and re-uploaded with the same version number.
117
+
118
+ ## [0.4.0] - 2026-08-10
119
+
120
+ ### Added
121
+
122
+ - Delete OPEN tasks from the web console: a Delete button (with
123
+ confirmation) in the task detail modal, backed by `DELETE
124
+ /api/instances/<name>/tasks/<id>` and `JSONBacklog.delete_task`.
125
+ - Resolve BLOCKED tasks from the web console: the task modal shows the
126
+ blocker reason and can reopen the task (back to `OPEN`) via `POST
127
+ /api/instances/<name>/tasks/<id>/reopen`.
128
+ - The web console stays usable with many tasks: non-OPEN columns collapse
129
+ behind count badges with an expand toggle, so a long backlog no longer
130
+ renders every task as a tall card up front.
131
+ - The failure/block reason is shown prominently in the task detail modal.
132
+ - Config editing from the web console: `PUT /api/instances/<name>/config`
133
+ validates and persists `forgeo.yaml` changes, and a new Config tab in the
134
+ instance page edits the fields in a form (with a restart hint).
135
+ - Daemon control from the web console: start, stop, and restart an
136
+ instance's daemon from the top bar via `POST
137
+ /api/instances/<name>/{start,stop,restart}`.
138
+ - `forgeo init` now asks only for the bare agent command and appends the
139
+ task prompt automatically.
140
+
141
+ ### Changed
142
+
143
+ - Commit messages no longer carry the `forgeo: ` prefix.
144
+ - The instance is registered before the run lock is taken, so a `--name`
145
+ lookup never fails while starting.
146
+ - README revised for clarity and formatting.
147
+
148
+ ## [0.3.0] - 2026-08-07
149
+
150
+ ### Added
151
+
152
+ - `forgeo web [--host HOST] [--port PORT]` — a standalone central dashboard
153
+ (default `0.0.0.0:8790`, foreground like `forgeo start`) that aggregates
154
+ every registered instance. It reads each instance's data straight from its
155
+ files (`backlog.json`, `runs.jsonl`, `forgeo.log`, `BLOCKER.md`), so it
156
+ works whether or not that instance's daemon is running. Home page at `/`,
157
+ per-instance pages at `/instances/<name>/` (kanban backlog plus logs,
158
+ runs, blocker and config tabs), and a per-instance API under
159
+ `/api/instances/<name>/`.
160
+ - Shared web-server helpers (`forgeo.web_common`) used by the central
161
+ dashboard.
162
+ - Task editing in the web console: the task detail modal gained an **Edit**
163
+ mode (Save/Cancel), backed by a new `PATCH
164
+ /api/instances/<name>/tasks/<id>` endpoint and `JSONBacklog.update_task`.
165
+ - PyPI publishing: tagging a release now also publishes the `forgeo-cli`
166
+ wheel and sdist to PyPI via trusted publishing.
167
+
168
+ ### Changed
169
+
170
+ - **The embedded per-daemon web server is gone.** `forgeo start` no longer
171
+ binds any port (`web_host`/`web_port` config keys are removed). The daemon
172
+ instead writes its live state (pid, started at, last outcome, next run) to
173
+ `daemon.state.json` next to the backlog after every cycle.
174
+ - The central dashboard (`forgeo web`) is now the **only** web interface:
175
+ it reads the daemon state files for accurate status, and it gained the
176
+ instance backlog's write endpoints, `POST
177
+ /api/instances/<name>/tasks` (with the web form on each instance page) and
178
+ `PATCH /api/instances/<name>/tasks/<id>`, so no feature was lost.
179
+ - `forgeo.web_common` docstring/API updated; `forgeo.server` module
180
+ removed.
181
+
182
+ ## [0.2.1] - 2026-08-05
183
+
184
+ ### Added
185
+
186
+ - `web_host` config option: the web dashboard/API bind address. Default
187
+ `127.0.0.1` (unchanged behavior); set `0.0.0.0` to reach it from other
188
+ hosts on the local network.
189
+ - `install.sh` now prefers a prebuilt standalone binary downloaded from the
190
+ matching GitHub Release for the host OS/arch — **no Python required**.
191
+ The pipx/pip fallback remains, used only when no prebuilt binary matches
192
+ the platform and a Python >= 3.11 is available.
193
+ - Tag-triggered CI builds single-file executables with PyInstaller on
194
+ Linux (amd64), macOS (amd64/arm64), and Windows (amd64) and attaches them
195
+ to the GitHub Release (`forgeo.spec`).
196
+ - Installer tests cover the binary-download path and the pipx/pip fallback
197
+ with stubs (no network).
198
+
199
+ ## [0.2.0] - 2026-08-04
200
+
201
+ ### Added
202
+
203
+ - `CHANGELOG.md` in Keep a Changelog format, with the `0.1.0` history
204
+ backfilled.
205
+ - Tag-triggered CI job that builds the wheel and sdist and attaches them to a
206
+ GitHub Release.
207
+ - Release steps documented in `CONTRIBUTING.md`.
208
+ - Web console frontend in `src/forgeo/web/`: a self-contained
209
+ HTML/CSS/JS dashboard (no framework, no build step, no external assets)
210
+ served at `/` showing the backlog grouped by status and daemon status,
211
+ auto-refreshing every 30 seconds.
212
+ - `install.sh` is now hosted on the project's own server and served from
213
+ <https://forgeo.org/install.sh>; README and docs use it in the one-liner.
214
+
215
+ ## [0.1.0] - 2026-08-03
216
+
217
+ Initial release of the scheduled, agent-driven software forgeo.
218
+
219
+ ### Added
220
+
221
+ - `forgeo start` persistent daemon: every `interval_minutes` it picks the
222
+ oldest `OPEN` task, runs it through the configured agent command, and commits
223
+ and pushes the result directly on `main`.
224
+ - Refactoring mode: when the backlog is empty, runs the agent with the
225
+ configured `refactor_prompt`.
226
+ - Blocker flow: an agent exiting with `blocked_exit_code` commits partial work,
227
+ writes `BLOCKER.md`, and pauses Forgeo until the task is reopened.
228
+ - Guided first-time setup: `forgeo init` wizard.
229
+ - `forgeo once` command to run a single cycle and exit.
230
+ - `forgeo status`, `forgeo stop`, and `forgeo restart` commands.
231
+ - `--auto` flag for the agent command for unattended runs.
232
+ - Local web dashboard and HTTP API served by the daemon.
233
+ - Durable run history recorded to `runs.jsonl` and exposed through the API.
234
+ - Telegram notification when a task is marked `BLOCKED`.
235
+ - Curl-to-bash one-liner installer (`install.sh`), pipx-first.
236
+ - MkDocs documentation website, published at <https://forgeo.org/>.
237
+ - GitHub Actions CI running `pytest`, `ruff`, and `mypy` on Python 3.11-3.13.
238
+ - Optional Docker sandbox for agent execution.
239
+ - Per-task `agent_command` override for cheap/expensive model routing.
240
+ - Project renamed to Forgeo, with MIT `LICENSE` and `CONTRIBUTING.md`.
241
+
242
+ ### Changed
243
+
244
+ - Project slimmed down to a single-purpose scheduled worker; the interactive
245
+ backlog generator utility was removed.
246
+ - Duplicated commit/blocker handling unified between task and refactor runs.
247
+ - Agent stdout/stderr streamed into run logs instead of buffered.
248
+ - Corrupt backlog files preserved instead of silently discarded.
249
+ - Git command timeout made configurable; agent timeout made optional with
250
+ overlapping-run skipping.
251
+ - Dogfooding docs removed; local configs kept out of the repository.
252
+
253
+ [Unreleased]: https://github.com/lucaGazzola/forgeo/compare/v0.5.0...HEAD
254
+ [0.5.0]: https://github.com/lucaGazzola/forgeo/compare/v0.4.0...v0.5.0
255
+ [0.4.0]: https://github.com/lucaGazzola/forgeo/compare/v0.3.0...v0.4.0
256
+ [0.3.0]: https://github.com/lucaGazzola/forgeo/compare/v0.2.0...v0.3.0
257
+ [0.2.1]: https://github.com/lucaGazzola/forgeo/compare/v0.2.0...v0.2.1
258
+ [0.2.0]: https://github.com/lucaGazzola/forgeo/compare/v0.1.0...v0.2.0
259
+ [0.1.0]: https://github.com/lucaGazzola/forgeo/releases/tag/v0.1.0
@@ -80,15 +80,20 @@ Human contributions use the normal GitHub flow:
80
80
 
81
81
  Releases are cut from `main` and published as GitHub Releases. Tagging the
82
82
  repo triggers CI, which builds the wheel, sdist, **and prebuilt standalone
83
- binaries** and attaches them to the release there is no PyPI publishing yet,
84
- and `install.sh` downloads the matching prebuilt binary from the release
85
- (`pipx`/`pip` fallback only when no binary matches the platform).
83
+ binaries** and attaches them to the release; `install.sh` downloads the
84
+ matching prebuilt binary from the release (`pipx`/`pip` fallback only when no
85
+ binary matches the platform), and the `publish-homebrew` job re-renders and
86
+ pushes the formula of the `lucaGazzola/homebrew-forgeo` tap.
86
87
 
87
88
  > Patch and minor releases **must** include the built binaries, otherwise the
88
89
  > `install.sh` binary path (the default, no-Python install) breaks. The CI
89
90
  > `build-binaries` job builds them automatically on any `v*` tag, but make
90
91
  > sure the release actually carries them — the `forgeo-<os>-<arch>` assets
91
92
  > listed below are what the installer downloads.
93
+ >
94
+ > The `publish-homebrew` job needs the `HOMEBREW_TAP_TOKEN` repository secret
95
+ > (a PAT with write access to `lucaGazzola/homebrew-forgeo`); a release cut
96
+ > without it fails that job and leaves the tap outdated until re-run.
92
97
 
93
98
  1. Confirm the [quality gates](#quality-gates) are green on `main`.
94
99
  2. Bump the version in `pyproject.toml` (`version = "x.y.z"`) and in
@@ -114,6 +119,8 @@ and `install.sh` downloads the matching prebuilt binary from the release
114
119
  `forgeo-linux-amd64`, `forgeo-darwin-amd64`, `forgeo-darwin-arm64`,
115
120
  `forgeo-windows-amd64.exe` binaries) are listed under
116
121
  <https://github.com/lucaGazzola/forgeo/releases>.
122
+ 8. Confirm the `publish-homebrew` job updated the tap: `brew update` and
123
+ `brew upgrade lucaGazzola/forgeo/forgeo` should now install the new version.
117
124
 
118
125
  ## License
119
126
 
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: forgeo-cli
3
- Version: 0.3.0
3
+ Version: 0.5.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
@@ -64,52 +64,64 @@ Description-Content-Type: text/markdown
64
64
  [![CI](https://github.com/lucaGazzola/forgeo/actions/workflows/ci.yml/badge.svg)](https://github.com/lucaGazzola/forgeo/actions/workflows/ci.yml)
65
65
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
66
66
 
67
- **Forgeo is an autonomous software forgeo for people with ideas, not teams.**
68
- You have a product idea — an app, a website, an internal automation but no
69
- developers on staff. With Forgeo you don't need any: you write down what needs
70
- to be built as a simple list of tasks, and an AI coding agent works through the
71
- list on its own, writing the code and committing it to your repository. No
72
- branches, no pull requests, no developer to hire.
67
+ **Forgeo is a software factory for your coding-agent.**
68
+ You're already working with an AI coding agent, prompting it task by task
69
+ or giving it a goal. Forgeo organizes your work in a structured way with
70
+ a backlog, and it decides what to work on next, runs your
71
+ agent on it, and commits the result. Progress, pending decisions, and history
72
+ are tracked in plain files you can inspect at any time, plus a web dashboard.
73
+ Forgeo only interrupts you when a decision is genuinely yours to
74
+ make, everything else happens autonomously. Transient failures (a network
75
+ blip, a flaky test) are retried automatically when the retry policy is
76
+ enabled, and only a task that keeps failing or genuinely needs a human
77
+ decision ever reaches you.
73
78
 
74
79
  All you need is basic comfort with a terminal, a git repository, and any coding
75
- agent CLI — Claude Code, aider, opencode, or your own script. Forgeo works with
76
- all of them.
77
-
78
- Forgeo decides what to do next on its own: while tasks are left it implements
79
- the oldest one and commits the result, and when the backlog is empty it reviews
80
- the codebase and cleans it up. It only interrupts you when a decision is
81
- genuinely yours to make — everything else happens autonomously.
80
+ agent CLI.
82
81
 
83
82
  ## Quickstart
84
83
 
85
- Requires a git repository (no Python needed — the one-liner downloads a
86
- prebuilt binary for your OS, or `pipx install forgeo-cli` works too). The full
87
- walkthrough is in [Getting started](docs/getting-started.md).
84
+ The full walkthrough is in [Getting started](docs/getting-started.md).
88
85
 
89
86
  ```bash
90
- # 1. Install
87
+ # 1. Install (any one of these)
88
+
89
+ # Homebrew (macOS / Linux)
90
+ brew install lucaGazzola/forgeo/forgeo
91
+
92
+ # or: the one-liner (prebuilt binary, no Python required)
91
93
  curl -fsSL https://forgeo.org/install.sh | bash
92
94
 
95
+ # or: pipx
96
+ pipx install forgeo-cli
97
+
93
98
  # 2. Create your Forgeo (guided wizard, run from your project root)
94
99
  forgeo init
95
100
 
96
- # 3. Start Forgeo
97
- forgeo start # run forever: every interval_minutes, implement the oldest OPEN task
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
98
104
  ```
99
105
 
100
106
  `forgeo init` writes `forgeo.yaml` and a `.forgeo/` folder for the backlog
101
- and logs, gitignored for you. Fill the backlog with plain JSON tasks (see
102
- [Backlog format](docs/backlog.md)) or add them from the web console while
103
- it runs — and Forgeo does the rest. The daemon binds no ports; open the
104
- dashboard with `forgeo web` (default <http://0.0.0.0:8790>):
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`):
105
110
 
106
111
  ![Forgeo web console](docs/img/console.png)
107
112
 
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
+
108
119
  One-off commands: `forgeo once` (single cycle), `forgeo status` (summary),
109
- `forgeo stop`, `forgeo restart` every command is in the
120
+ `forgeo validate` (read-only dry run before starting), `forgeo stop`,
121
+ `forgeo restart`, every command is in the
110
122
  [CLI reference](docs/cli-reference.md).
111
123
 
112
- You can run several factories at once, one per repository each config is
124
+ You can run several factories at once, one per repository, each config is
113
125
  fully independent (own backlog, logs, locks). Register each `forgeo.yaml`
114
126
  in the instance registry with `forgeo instance add NAME --config PATH`,
115
127
  manage any of them by name with `forgeo start/status/stop --name NAME`,
@@ -128,7 +140,10 @@ central dashboard, `forgeo web`.
128
140
  | Web dashboard & HTTP API | [Web console & HTTP API](docs/web-console-api.md) |
129
141
 
130
142
  Everything is stored in plain files: the backlog, `forgeo.log`, and
131
- `BLOCKER.md` whenever a decision is pending.
143
+ `BLOCKER.md` whenever a decision is pending. The backlog is snapshotted
144
+ (rotating `backlog.json.bak` files) before every agent run and on daemon
145
+ startup, and restored automatically if it is ever found corrupt — a bad write
146
+ never loses your tasks.
132
147
 
133
148
  ## Develop
134
149
 
@@ -0,0 +1,107 @@
1
+ <div align="center">
2
+ <img src="docs/img/logo.png" alt="Forgeo logo" width="128">
3
+ </div>
4
+
5
+ <div align="center">
6
+ <img src="docs/img/title.svg" alt="Forgeo" width="128">
7
+ </div>
8
+
9
+
10
+ [![CI](https://github.com/lucaGazzola/forgeo/actions/workflows/ci.yml/badge.svg)](https://github.com/lucaGazzola/forgeo/actions/workflows/ci.yml)
11
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
12
+
13
+ **Forgeo is a software factory for your coding-agent.**
14
+ You're already working with an AI coding agent, prompting it task by task
15
+ or giving it a goal. Forgeo organizes your work in a structured way with
16
+ a backlog, and it decides what to work on next, runs your
17
+ agent on it, and commits the result. Progress, pending decisions, and history
18
+ are tracked in plain files you can inspect at any time, plus a web dashboard.
19
+ Forgeo only interrupts you when a decision is genuinely yours to
20
+ make, everything else happens autonomously. Transient failures (a network
21
+ blip, a flaky test) are retried automatically when the retry policy is
22
+ enabled, and only a task that keeps failing or genuinely needs a human
23
+ decision ever reaches you.
24
+
25
+ All you need is basic comfort with a terminal, a git repository, and any coding
26
+ agent CLI.
27
+
28
+ ## Quickstart
29
+
30
+ The full walkthrough is in [Getting started](docs/getting-started.md).
31
+
32
+ ```bash
33
+ # 1. Install (any one of these)
34
+
35
+ # Homebrew (macOS / Linux)
36
+ brew install lucaGazzola/forgeo/forgeo
37
+
38
+ # or: the one-liner (prebuilt binary, no Python required)
39
+ curl -fsSL https://forgeo.org/install.sh | bash
40
+
41
+ # or: pipx
42
+ pipx install forgeo-cli
43
+
44
+ # 2. Create your Forgeo (guided wizard, run from your project root)
45
+ forgeo init
46
+
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
50
+ ```
51
+
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`):
56
+
57
+ ![Forgeo web console](docs/img/console.png)
58
+
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`.
76
+
77
+ ## Documentation
78
+
79
+ | Topic | Where |
80
+ | --- | --- |
81
+ | Install, init, first cycle | [Getting started](docs/getting-started.md) |
82
+ | Every `forgeo.yaml` key | [Configuration](docs/configuration.md) |
83
+ | Task schema and statuses | [Backlog format](docs/backlog.md) |
84
+ | How the agent is invoked (env, exit codes, timeouts) | [Agent contract](docs/agent-contract.md) |
85
+ | All CLI commands | [CLI reference](docs/cli-reference.md) |
86
+ | Web dashboard & HTTP API | [Web console & HTTP API](docs/web-console-api.md) |
87
+
88
+ Everything is stored in plain files: the backlog, `forgeo.log`, and
89
+ `BLOCKER.md` whenever a decision is pending. The backlog is snapshotted
90
+ (rotating `backlog.json.bak` files) before every agent run and on daemon
91
+ startup, and restored automatically if it is ever found corrupt — a bad write
92
+ never loses your tasks.
93
+
94
+ ## Develop
95
+
96
+ ```bash
97
+ pip install -e ".[dev]"
98
+ pytest
99
+ ```
100
+
101
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for the development setup, quality
102
+ gates (`pytest`, `ruff check`, `mypy src/forgeo`), and the pull-request
103
+ process.
104
+
105
+ ## License
106
+
107
+ MIT — see [LICENSE](LICENSE).