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.
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/.github/workflows/ci.yml +60 -1
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/.gitignore +1 -0
- forgeo_cli-0.5.0/CHANGELOG.md +259 -0
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/CONTRIBUTING.md +10 -3
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/PKG-INFO +43 -28
- forgeo_cli-0.5.0/README.md +107 -0
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/docs/agent-contract.md +35 -7
- forgeo_cli-0.5.0/docs/backlog.md +284 -0
- forgeo_cli-0.5.0/docs/cli-reference.md +346 -0
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/docs/configuration.md +116 -2
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/docs/getting-started.md +55 -22
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/docs/index.md +41 -18
- forgeo_cli-0.5.0/docs/web-console-api.md +656 -0
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/install.sh +29 -3
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/pyproject.toml +1 -1
- forgeo_cli-0.5.0/scripts/__init__.py +0 -0
- forgeo_cli-0.5.0/scripts/render_homebrew_formula.py +119 -0
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/src/forgeo/__init__.py +1 -1
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/src/forgeo/agent.py +26 -4
- forgeo_cli-0.5.0/src/forgeo/backlog.py +554 -0
- forgeo_cli-0.5.0/src/forgeo/central.py +1440 -0
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/src/forgeo/cli.py +413 -128
- forgeo_cli-0.5.0/src/forgeo/config.py +69 -0
- forgeo_cli-0.5.0/src/forgeo/daemon.py +425 -0
- forgeo_cli-0.5.0/src/forgeo/daemon_control.py +165 -0
- forgeo_cli-0.5.0/src/forgeo/forgeo.py +689 -0
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/src/forgeo/git.py +14 -0
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/src/forgeo/instances.py +1 -1
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/src/forgeo/models.py +177 -2
- forgeo_cli-0.5.0/src/forgeo/notify.py +131 -0
- forgeo_cli-0.5.0/src/forgeo/runs.py +131 -0
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/src/forgeo/setup.py +54 -12
- forgeo_cli-0.5.0/src/forgeo/update.py +172 -0
- forgeo_cli-0.5.0/src/forgeo/validate.py +221 -0
- forgeo_cli-0.5.0/src/forgeo/web/central/central.css +1096 -0
- forgeo_cli-0.5.0/src/forgeo/web/central/central.js +1761 -0
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/src/forgeo/web/central/instance.html +106 -10
- forgeo_cli-0.5.0/src/forgeo/web/central/login.html +76 -0
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/src/forgeo/web/style.css +7 -1
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/src/forgeo/web_common.py +2 -0
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/tests/conftest.py +11 -0
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/tests/test_agent.py +105 -1
- forgeo_cli-0.5.0/tests/test_backlog.py +899 -0
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/tests/test_cli.py +358 -9
- forgeo_cli-0.5.0/tests/test_daemon.py +383 -0
- forgeo_cli-0.5.0/tests/test_factory.py +947 -0
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/tests/test_git.py +40 -0
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/tests/test_install.py +3 -2
- forgeo_cli-0.5.0/tests/test_models.py +302 -0
- forgeo_cli-0.5.0/tests/test_render_homebrew.py +83 -0
- forgeo_cli-0.5.0/tests/test_runs.py +515 -0
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/tests/test_setup.py +54 -6
- forgeo_cli-0.5.0/tests/test_update.py +205 -0
- forgeo_cli-0.5.0/tests/test_web.py +2169 -0
- forgeo_cli-0.5.0/tests/test_web_common.py +134 -0
- forgeo_cli-0.5.0/tests/test_web_lock.py +521 -0
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/www/index.html +25 -25
- forgeo_cli-0.3.0/CHANGELOG.md +0 -114
- forgeo_cli-0.3.0/README.md +0 -92
- forgeo_cli-0.3.0/docs/backlog.md +0 -113
- forgeo_cli-0.3.0/docs/cli-reference.md +0 -211
- forgeo_cli-0.3.0/docs/web-console-api.md +0 -275
- forgeo_cli-0.3.0/src/forgeo/backlog.py +0 -206
- forgeo_cli-0.3.0/src/forgeo/central.py +0 -620
- forgeo_cli-0.3.0/src/forgeo/config.py +0 -36
- forgeo_cli-0.3.0/src/forgeo/daemon.py +0 -209
- forgeo_cli-0.3.0/src/forgeo/forgeo.py +0 -446
- forgeo_cli-0.3.0/src/forgeo/notify.py +0 -77
- forgeo_cli-0.3.0/src/forgeo/runs.py +0 -73
- forgeo_cli-0.3.0/src/forgeo/web/central/central.css +0 -380
- forgeo_cli-0.3.0/src/forgeo/web/central/central.js +0 -780
- forgeo_cli-0.3.0/tests/test_backlog.py +0 -225
- forgeo_cli-0.3.0/tests/test_daemon.py +0 -162
- forgeo_cli-0.3.0/tests/test_factory.py +0 -316
- forgeo_cli-0.3.0/tests/test_models.py +0 -127
- forgeo_cli-0.3.0/tests/test_runs.py +0 -216
- forgeo_cli-0.3.0/tests/test_web.py +0 -781
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/LICENSE +0 -0
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/config/nginx-forgeo.conf +0 -0
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/docs/img/console.png +0 -0
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/docs/img/logo.png +0 -0
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/docs/img/title.svg +0 -0
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/forgeo.spec +0 -0
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/mkdocs.yml +0 -0
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/src/forgeo/__main__.py +0 -0
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/src/forgeo/io.py +0 -0
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/src/forgeo/web/central/index.html +0 -0
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/tests/test_instances.py +0 -0
- {forgeo_cli-0.3.0 → forgeo_cli-0.5.0}/tests/test_io.py +0 -0
- {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
|
-
|
|
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')
|
|
@@ -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
|
|
84
|
-
|
|
85
|
-
|
|
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.
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
2
|
Name: forgeo-cli
|
|
3
|
-
Version: 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
|
[](https://github.com/lucaGazzola/forgeo/actions/workflows/ci.yml)
|
|
65
65
|
[](https://opensource.org/licenses/MIT)
|
|
66
66
|
|
|
67
|
-
**Forgeo is
|
|
68
|
-
You
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
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
|
|
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
|
-
|
|
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 #
|
|
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
|
|
102
|
-
[Backlog format](docs/backlog.md))
|
|
103
|
-
it runs
|
|
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
|

|
|
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
|
|
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
|
|
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
|
+
[](https://github.com/lucaGazzola/forgeo/actions/workflows/ci.yml)
|
|
11
|
+
[](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
|
+

|
|
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).
|