forgeo-cli 0.9.0__tar.gz → 0.11.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.9.0 → forgeo_cli-0.11.0}/CHANGELOG.md +43 -1
- forgeo_cli-0.11.0/PKG-INFO +188 -0
- forgeo_cli-0.11.0/README.md +134 -0
- forgeo_cli-0.11.0/docs/agent-contract.md +78 -0
- forgeo_cli-0.11.0/docs/backlog.md +217 -0
- forgeo_cli-0.11.0/docs/cli-reference.md +173 -0
- forgeo_cli-0.11.0/docs/configuration.md +263 -0
- forgeo_cli-0.11.0/docs/getting-started.md +116 -0
- forgeo_cli-0.11.0/docs/index.md +37 -0
- forgeo_cli-0.11.0/docs/web-console-api.md +220 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/install.sh +1 -1
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/mkdocs.yml +1 -1
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/pyproject.toml +1 -1
- forgeo_cli-0.11.0/scripts/test-github-backlog-e2e.sh +225 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/__init__.py +1 -1
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/agent.py +43 -27
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/backlog.py +196 -40
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/backlog_github.py +137 -189
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/backlog_gitlab.py +123 -169
- forgeo_cli-0.11.0/src/forgeo/backlog_issue_base.py +366 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/backlog_jira.py +113 -103
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/central.py +262 -68
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/config.py +15 -12
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/daemon.py +10 -5
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/daemon_control.py +1 -1
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/forgeo.py +158 -59
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/git.py +76 -9
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/io.py +2 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/models.py +149 -175
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/paths.py +1 -1
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/runs.py +5 -4
- forgeo_cli-0.11.0/src/forgeo/setup.py +494 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/validate.py +36 -52
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/web/central/central.css +104 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/web/central/central.js +168 -5
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/web/central/instance.html +37 -1
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/web/style.css +16 -1
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/web_common.py +5 -7
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/conftest.py +20 -7
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_cli.py +9 -32
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_setup.py +54 -3
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_web.py +3 -2
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_web_lock.py +1 -1
- forgeo_cli-0.9.0/PKG-INFO +0 -242
- forgeo_cli-0.9.0/README.md +0 -188
- forgeo_cli-0.9.0/docs/agent-contract.md +0 -154
- forgeo_cli-0.9.0/docs/backlog.md +0 -510
- forgeo_cli-0.9.0/docs/cli-reference.md +0 -372
- forgeo_cli-0.9.0/docs/configuration.md +0 -536
- forgeo_cli-0.9.0/docs/getting-started.md +0 -205
- forgeo_cli-0.9.0/docs/index.md +0 -67
- forgeo_cli-0.9.0/docs/web-console-api.md +0 -674
- forgeo_cli-0.9.0/src/forgeo/backlog_issue_base.py +0 -183
- forgeo_cli-0.9.0/src/forgeo/setup.py +0 -230
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/.github/workflows/ci.yml +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/.gitignore +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/CONTRIBUTING.md +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/LICENSE +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/config/nginx-forgeo.conf +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/docs/img/console.png +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/docs/img/demo.gif +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/docs/img/logo.png +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/docs/img/og.png +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/docs/img/title.svg +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/forgeo.spec +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/scripts/__init__.py +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/scripts/render_homebrew_formula.py +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/__main__.py +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/backlog_http.py +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/cli.py +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/instances.py +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/notify.py +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/oauth.py +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/update.py +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/web/central/index.html +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/web/central/login.html +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_agent.py +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_backlog.py +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_backlog_github.py +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_backlog_gitlab.py +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_backlog_http.py +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_backlog_jira.py +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_daemon.py +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_factory.py +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_git.py +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_install.py +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_instances.py +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_io.py +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_models.py +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_oauth.py +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_paths.py +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_remote_backlog_cycle.py +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_render_homebrew.py +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_runs.py +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_update.py +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_web_common.py +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/www/404.html +0 -0
- {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/www/index.html +0 -0
|
@@ -7,6 +7,46 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.11.0] - 2026-08-31
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **REVIEW status with feature-branch workflow** (`review_mode: branch`). When enabled, a successful agent run no longer commits directly to `main` as `COMPLETED`: the engine creates a feature branch `forgeo/review/<TASK_ID>` (via `review_branch_prefix`, default `forgeo/review/`), commits there, pushes, and marks the task `REVIEW`. Tasks in `REVIEW` block dependants (like `BLOCKED`/`FAILED`) while independent tasks keep running.
|
|
15
|
+
- Per-task `review_required` override (`bool | null`): `true` forces branch+REVIEW, `false` forces direct `COMPLETED`, `null` inherits `review_mode`. Editable via `PATCH /api/instances/<name>/tasks/<id>` and persisted across all providers (file/http body, hidden `<!-- forgeo: {...} -->` block on GitHub/GitLab, Jira issue property `review_branch`/`review_commit_sha`).
|
|
16
|
+
- Engine-managed `review_branch` and `review_commit_sha` on `Task` (set on `REVIEW`, cleared on leave), carried through document stores (`DocumentBacklogStore.set_review`/`complete_review`/`request_changes`) and issue stores via `forgeo-review` label (`forgeo_labels()`) plus engine state.
|
|
17
|
+
- Web console: dedicated **REVIEW** kanban column, review-branch display on cards/modals, and human-in-the-loop actions `Complete` (`POST …/complete-review` → `COMPLETED` after manual merge) and `Request changes` (`POST …/request-changes` → `OPEN` for rework). Issue providers also show `external_url`/board links for the branch.
|
|
18
|
+
- Generic webhook now supports `review` event (`WEBHOOK_EVENTS += "review"`, `notify_webhook_events` validation), sent by `Forgeo._run_task` on the `REVIEW` transition via `GitManager.create_review_branch`/`a_create_review_branch` and `_commit_on_review_branch` (creates/resets branch, commits, pushes, switches back to `branch` and hard-resets `main`).
|
|
19
|
+
- `HttpBacklog`/`JSONBacklog`/`IssueBacklogBase` now expose `set_review`/`complete_review`/`request_changes` and central dashboard routes `POST /api/instances/<name>/tasks/<id>/{complete-review,request-changes}`. Shared helpers `_issue_provider_base`, `_github_repo_root`, `_gitlab_issues_root`, `forgeo_labels`, `extract_issue_number/labels`, `bump_state_counter` unify Jira/GitHub/GitLab handling.
|
|
20
|
+
- `config/forgeo.yaml` and `docs/configuration.md` document `review_mode` and `review_branch_prefix`; `mkdocs.yml` `site_description` updated.
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- Docs restructured and condensed (~55% shorter) while preserving full coverage: `README`, `docs/agent-contract.md`, `docs/backlog.md`, `docs/cli-reference.md`, `docs/configuration.md`, `docs/getting-started.md`, `docs/index.md`, `docs/web-console-api.md` rewritten for scannability (tables, endpoint summary, concise curl examples).
|
|
25
|
+
- `docs/backlog.md`, `docs/configuration.md`, `docs/web-console-api.md`, and `README` document the new REVIEW workflow, `REVIEW` task lifecycle, and new `review`-related API fields.
|
|
26
|
+
- Internal maintainability refactor: `backlog.py` helpers `_require_string`/`_require_string_list`/`_status_by_id`/`_set_agent_response`/`_blocked_notice`/`_blocker_sections`/`_render_block`, `forgeo.py` split of blocker/commit logic, `models.py` `_IssueFieldMappingBase`/`_IssueBacklogConfigBase`/`_PatAuthBase`/`_IssueWorkflowBase`/`_RepoBacklogConfigBase` extraction, `IssueBacklogBase` shared `_call`/`_labels`/`_get_issue`/`_search_all`/`_task_from_issue`/`list_tasks`/`get_task`/`validate_connection`/`bump_failed_wait`/`_update_issue_labels`, `GitManager.ensure_branch`/`current_branch`/`create_review_branch`/`commit_all_on_branch` plus async wrappers, `central.py` `_github_web_base` exact-host rewrite and `_external_board_url`/`_external_issue_url` helpers, `config.py` `_maybe_resolve`, `validate.py`/`daemon.py`/`runs.py`/`paths.py`/`io.py`/`web_common.py`/`setup.py` lint-driven cleanups.
|
|
27
|
+
|
|
28
|
+
### Fixed
|
|
29
|
+
|
|
30
|
+
- `ruff`/`mypy` compliance across the review branch (BLE001/S110/F541 suppressions in `setup.py`, type narrowing in `Forgeo`, `src/forgeo/backlog.py:21`, etc.); `pytest` green including new `REVIEW` column/counts and delete tests.
|
|
31
|
+
|
|
32
|
+
## [0.10.0] - 2026-08-24
|
|
33
|
+
|
|
34
|
+
### Added
|
|
35
|
+
|
|
36
|
+
- `forgeo init` now asks for **backlog provider** (`file`/`github`/`gitlab`/`jira`/`http`). For `github` it auto-detects `owner/repo` from `git remote origin`, prompts for `token_env` (`GITHUB_TOKEN`) and can persist a pasted classic PAT (`ghp_...`, scope `repo`) to `~/.config/forgeo/github_token_env.sh` (600, wired to `~/.bashrc`). Same for `gitlab` (`GITLAB_TOKEN`, base URL) and `jira`/`http`. The wizard writes `backlog: https://api.github.com`, `backlog_provider: github`, `github: {repo, auth: {token_env}}` and `state_dir: .forgeo` automatically.
|
|
37
|
+
- Web console now treats `jira`/`github`/`gitlab` as a **read-mostly mirror** instead of a replacement: the home page cards show `Open in Jira/GitHub/GitLab ↗` (via `external_board_url`/`external_board_label`), the instance page shows a top banner linking to the native board, and each task card/modal links to the native issue (`external_url`). Document backlogs (`file`/`http`) keep the existing primary-editor behaviour. Creating/editing still works through the dashboard, but triage is expected in the native tracker where Forgeo-specific state (BLOCKED/FAILED reasons, `agent_response`, retry budget) is now surfaced on the mirror.
|
|
38
|
+
- Central API now exposes `backlog_provider`, `backlog`, `backlog_is_issue_provider`, `external_board_url`/`external_board_label` on `GET /api/instances` and `GET /api/instances/<name>/status`, and `external_url` per task on `GET /api/instances/<name>/tasks` (+ single-task) for issue providers. Covers `https://api.github.com` → `https://github.com` and `https://…/api/v3` → web base mapping for GitHub Enterprise, and `https://jira…/issues/?jql=` / `https://gitlab…/{repo}/-/issues` board links.
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
|
|
42
|
+
- GitHub provider now encodes `owner/repo` as two path segments (`quote` per segment, keeping `/`) instead of `quote(repo, safe='')` which produced `owner%2Frepo` and 404 on every `GET /repos/{owner%2Frepo}/issues`.
|
|
43
|
+
|
|
44
|
+
### Changed
|
|
45
|
+
|
|
46
|
+
- `README`, `docs/backlog.md`, `docs/getting-started.md` and `docs/web-console-api.md` document the mirror vs editor split and the new `external_*` API fields.
|
|
47
|
+
- `src/forgeo/central.py` deduplicates provider metadata via `_backlog_meta()` and centralises GitHub web-base handling; `instance-card` is now a `div[role=link]` to allow nested external links without invalid HTML.
|
|
48
|
+
- `README`, `docs/getting-started.md` and `docs/cli-reference.md` document the new backlog-provider step in `forgeo init` and the `GITHUB_TOKEN` PAT setup (`https://github.com/settings/tokens/new`, scope `repo`).
|
|
49
|
+
|
|
10
50
|
## [0.9.0] - 2026-08-23
|
|
11
51
|
|
|
12
52
|
### Added
|
|
@@ -389,7 +429,9 @@ Initial release of the scheduled, agent-driven software forgeo.
|
|
|
389
429
|
overlapping-run skipping.
|
|
390
430
|
- Dogfooding docs removed; local configs kept out of the repository.
|
|
391
431
|
|
|
392
|
-
[Unreleased]: https://github.com/lucaGazzola/forgeo/compare/v0.
|
|
432
|
+
[Unreleased]: https://github.com/lucaGazzola/forgeo/compare/v0.11.0...HEAD
|
|
433
|
+
[0.11.0]: https://github.com/lucaGazzola/forgeo/compare/v0.10.0...v0.11.0
|
|
434
|
+
[0.10.0]: https://github.com/lucaGazzola/forgeo/compare/v0.9.0...v0.10.0
|
|
393
435
|
[0.9.0]: https://github.com/lucaGazzola/forgeo/compare/v0.8.0...v0.9.0
|
|
394
436
|
[0.8.0]: https://github.com/lucaGazzola/forgeo/compare/v0.7.3...v0.8.0
|
|
395
437
|
[0.7.3]: https://github.com/lucaGazzola/forgeo/compare/v0.7.2...v0.7.3
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: forgeo-cli
|
|
3
|
+
Version: 0.11.0
|
|
4
|
+
Summary: A scheduled software forgeo: executes backlog tasks on main, refactors when idle, and writes BLOCKER.md when it needs human input.
|
|
5
|
+
Project-URL: Homepage, https://forgeo.org
|
|
6
|
+
Project-URL: Documentation, https://forgeo.org
|
|
7
|
+
Project-URL: Repository, https://github.com/lucaGazzola/forgeo
|
|
8
|
+
Project-URL: Issues, https://github.com/lucaGazzola/forgeo/issues
|
|
9
|
+
Author: Forgeo Contributors
|
|
10
|
+
License: MIT License
|
|
11
|
+
|
|
12
|
+
Copyright (c) 2026 Software Forgeo Contributors
|
|
13
|
+
|
|
14
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
15
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
16
|
+
in the Software without restriction, including without limitation the rights
|
|
17
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
18
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
19
|
+
furnished to do so, subject to the following conditions:
|
|
20
|
+
|
|
21
|
+
The above copyright notice and this permission notice shall be included in all
|
|
22
|
+
copies or substantial portions of the Software.
|
|
23
|
+
|
|
24
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
25
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
26
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
27
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
28
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
29
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
30
|
+
SOFTWARE.
|
|
31
|
+
License-File: LICENSE
|
|
32
|
+
Keywords: agents,ai,automation,backlog,orchestration,scheduler
|
|
33
|
+
Classifier: Development Status :: 3 - Alpha
|
|
34
|
+
Classifier: Intended Audience :: Developers
|
|
35
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
36
|
+
Classifier: Programming Language :: Python :: 3
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
40
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
41
|
+
Requires-Python: >=3.11
|
|
42
|
+
Requires-Dist: pydantic>=2.5
|
|
43
|
+
Requires-Dist: pyyaml>=6.0
|
|
44
|
+
Requires-Dist: rich>=13.7
|
|
45
|
+
Provides-Extra: dev
|
|
46
|
+
Requires-Dist: mypy>=1.8; extra == 'dev'
|
|
47
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
48
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
49
|
+
Requires-Dist: ruff>=0.5; extra == 'dev'
|
|
50
|
+
Requires-Dist: types-pyyaml>=6.0; extra == 'dev'
|
|
51
|
+
Provides-Extra: docs
|
|
52
|
+
Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
|
|
53
|
+
Description-Content-Type: text/markdown
|
|
54
|
+
|
|
55
|
+
<div align="center">
|
|
56
|
+
<img src="docs/img/logo.png" alt="Forgeo logo" width="128">
|
|
57
|
+
</div>
|
|
58
|
+
|
|
59
|
+
<div align="center">
|
|
60
|
+
<img src="docs/img/title.svg" alt="Forgeo" width="128">
|
|
61
|
+
</div>
|
|
62
|
+
|
|
63
|
+
[](https://github.com/lucaGazzola/forgeo/actions/workflows/ci.yml)
|
|
64
|
+
[](https://opensource.org/licenses/MIT)
|
|
65
|
+
|
|
66
|
+
<div align="center">
|
|
67
|
+
<img src="docs/img/demo.gif" alt="Forgeo running a backlog task end to end" width="720">
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
**Forgeo is a software factory for your coding agent.**
|
|
71
|
+
|
|
72
|
+
Give it a backlog and an agent CLI — Forgeo picks the next runnable task, runs the agent, and commits the result. It tracks progress in plain files and a web dashboard, and only interrupts you when a human decision is needed.
|
|
73
|
+
|
|
74
|
+
- **One task at a time** — oldest `OPEN` task whose dependencies are `COMPLETED` (or a `run_at` schedule). `REVIEW` blocks dependants but not independent tasks.
|
|
75
|
+
- **Agent-agnostic** — any CLI that reads `FORGEO_TASK` (aider, Claude, custom script).
|
|
76
|
+
- **Refactors when idle** — runs a refactoring pass when the backlog is empty.
|
|
77
|
+
- **Handles failure gracefully** — `BLOCKED` for human input (`BLOCKER.md`), `FAILED` with retry policy, snapshots for file backlogs, Telegram/webhook notifications.
|
|
78
|
+
- **Optional review** — `review_mode: branch` commits to `forgeo/review/TASK-001`, marks `REVIEW`, pushes and waits for human merge → `Complete`.
|
|
79
|
+
|
|
80
|
+
Requires a terminal, a git repo, and an agent CLI.
|
|
81
|
+
|
|
82
|
+
## Quickstart
|
|
83
|
+
|
|
84
|
+
Full walkthrough: [Getting Started](docs/getting-started.md).
|
|
85
|
+
|
|
86
|
+
### 1. Install
|
|
87
|
+
|
|
88
|
+
Pick one (no root; re-run to upgrade):
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
brew install lucaGazzola/forgeo/forgeo # Homebrew, no Python needed
|
|
92
|
+
curl -fsSL https://forgeo.org/install.sh | bash # binary or pip fallback
|
|
93
|
+
pipx install forgeo-cli # Python 3.11+
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### 2. Init
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
forgeo init
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Wizard in your project root. Creates `forgeo.yaml` and `.forgeo/` (backlog, logs, blockers). Prompts for backlog provider (`file` / `github` / `gitlab` / `jira` / `http`) and agent command. For `github` it auto-detects `owner/repo` and can persist `GITHUB_TOKEN` to `~/.config/forgeo/`.
|
|
103
|
+
|
|
104
|
+
### 3. Fill the backlog
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
# file provider: edit .forgeo/backlog.json (see Backlog format)
|
|
108
|
+
# github/gitlab/jira/http: configured in forgeo.yaml, then:
|
|
109
|
+
forgeo validate
|
|
110
|
+
|
|
111
|
+
# or add tasks from the dashboard:
|
|
112
|
+
forgeo web # http://0.0.0.0:8790 (use -d to keep it running)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+

|
|
116
|
+
|
|
117
|
+
### 4. Start
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
forgeo validate # dry run: config, repo, backlog, agent, locks
|
|
121
|
+
forgeo start # daemon in background, one cycle per interval_minutes
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Each cycle: pick task → run agent → commit/push (or `REVIEW` branch when `review_mode: branch`). Empty backlog → refactoring pass.
|
|
125
|
+
|
|
126
|
+
### Day-to-day
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
forgeo status # config, counts, next task, daemon state, last outcome
|
|
130
|
+
forgeo once # one cycle in foreground, no daemon
|
|
131
|
+
forgeo run --task TASK-012 # run a specific OPEN task now
|
|
132
|
+
forgeo stop / restart # stop or restart daemon
|
|
133
|
+
forgeo web # dashboard for all instances
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
`forgeo web` is open by default on `0.0.0.0:8790`. On a shared host use `forgeo web --token` for bearer auth — see [Web console](docs/web-console-api.md).
|
|
137
|
+
|
|
138
|
+
### Docker sandbox
|
|
139
|
+
|
|
140
|
+
Run the agent isolated:
|
|
141
|
+
|
|
142
|
+
```yaml
|
|
143
|
+
agent_sandbox: docker
|
|
144
|
+
agent_sandbox_image: your-image # must contain agent CLI + sh
|
|
145
|
+
agent_sandbox_network: none # default, no network
|
|
146
|
+
agent_sandbox_mounts: [~/.claude] # read-only mounts
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Repo is bind-mounted at the same path; task arrives as `FORGEO_TASK`. See [Configuration](docs/configuration.md).
|
|
150
|
+
|
|
151
|
+
### Multiple repos
|
|
152
|
+
|
|
153
|
+
One config per repo, fully independent (own backlog, logs, locks). Use the instance registry:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
forgeo instance add site-a --config /path/to/site-a/forgeo.yaml
|
|
157
|
+
forgeo start --name site-a
|
|
158
|
+
forgeo list # all instances
|
|
159
|
+
forgeo web # aggregate dashboard
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## Documentation
|
|
163
|
+
|
|
164
|
+
| Topic | Doc |
|
|
165
|
+
| --- | --- |
|
|
166
|
+
| Install, init, first cycle | [Getting Started](docs/getting-started.md) |
|
|
167
|
+
| All `forgeo.yaml` keys | [Configuration](docs/configuration.md) |
|
|
168
|
+
| Task schema & statuses | [Backlog format](docs/backlog.md) |
|
|
169
|
+
| Agent env, exit codes, timeouts | [Agent contract](docs/agent-contract.md) |
|
|
170
|
+
| All CLI commands | [CLI reference](docs/cli-reference.md) |
|
|
171
|
+
| Dashboard & HTTP API | [Web console & HTTP API](docs/web-console-api.md) |
|
|
172
|
+
|
|
173
|
+
**Backlog providers:** [file](docs/backlog.md#a-json-file-backlog) · [HTTP](docs/backlog.md#a-backlog-over-http) · [Jira](docs/backlog.md#a-jira-backlog) · [GitHub](docs/backlog.md#a-github-backlog) · [GitLab](docs/backlog.md#a-gitlab-backlog) — file/HTTP exchange the full document; Jira/GitHub/GitLab sync issues individually. File backlogs are snapshotted (`backlog.json.bak`) before each run and restored if corrupt.
|
|
174
|
+
|
|
175
|
+
**Dashboard:** `forgeo web` aggregates every instance. For `file`/`http` it is the primary editor; for `jira`/`github`/`gitlab` it is a read-mostly mirror (links to native issues, surfaces `BLOCKED`/`FAILED` reasons and retry state).
|
|
176
|
+
|
|
177
|
+
## Develop
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
pip install -e ".[dev]"
|
|
181
|
+
pytest
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) (quality gates: `pytest`, `ruff check`, `mypy src/forgeo`).
|
|
185
|
+
|
|
186
|
+
## License
|
|
187
|
+
|
|
188
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,134 @@
|
|
|
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
|
+
[](https://github.com/lucaGazzola/forgeo/actions/workflows/ci.yml)
|
|
10
|
+
[](https://opensource.org/licenses/MIT)
|
|
11
|
+
|
|
12
|
+
<div align="center">
|
|
13
|
+
<img src="docs/img/demo.gif" alt="Forgeo running a backlog task end to end" width="720">
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
**Forgeo is a software factory for your coding agent.**
|
|
17
|
+
|
|
18
|
+
Give it a backlog and an agent CLI — Forgeo picks the next runnable task, runs the agent, and commits the result. It tracks progress in plain files and a web dashboard, and only interrupts you when a human decision is needed.
|
|
19
|
+
|
|
20
|
+
- **One task at a time** — oldest `OPEN` task whose dependencies are `COMPLETED` (or a `run_at` schedule). `REVIEW` blocks dependants but not independent tasks.
|
|
21
|
+
- **Agent-agnostic** — any CLI that reads `FORGEO_TASK` (aider, Claude, custom script).
|
|
22
|
+
- **Refactors when idle** — runs a refactoring pass when the backlog is empty.
|
|
23
|
+
- **Handles failure gracefully** — `BLOCKED` for human input (`BLOCKER.md`), `FAILED` with retry policy, snapshots for file backlogs, Telegram/webhook notifications.
|
|
24
|
+
- **Optional review** — `review_mode: branch` commits to `forgeo/review/TASK-001`, marks `REVIEW`, pushes and waits for human merge → `Complete`.
|
|
25
|
+
|
|
26
|
+
Requires a terminal, a git repo, and an agent CLI.
|
|
27
|
+
|
|
28
|
+
## Quickstart
|
|
29
|
+
|
|
30
|
+
Full walkthrough: [Getting Started](docs/getting-started.md).
|
|
31
|
+
|
|
32
|
+
### 1. Install
|
|
33
|
+
|
|
34
|
+
Pick one (no root; re-run to upgrade):
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
brew install lucaGazzola/forgeo/forgeo # Homebrew, no Python needed
|
|
38
|
+
curl -fsSL https://forgeo.org/install.sh | bash # binary or pip fallback
|
|
39
|
+
pipx install forgeo-cli # Python 3.11+
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### 2. Init
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
forgeo init
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Wizard in your project root. Creates `forgeo.yaml` and `.forgeo/` (backlog, logs, blockers). Prompts for backlog provider (`file` / `github` / `gitlab` / `jira` / `http`) and agent command. For `github` it auto-detects `owner/repo` and can persist `GITHUB_TOKEN` to `~/.config/forgeo/`.
|
|
49
|
+
|
|
50
|
+
### 3. Fill the backlog
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# file provider: edit .forgeo/backlog.json (see Backlog format)
|
|
54
|
+
# github/gitlab/jira/http: configured in forgeo.yaml, then:
|
|
55
|
+
forgeo validate
|
|
56
|
+
|
|
57
|
+
# or add tasks from the dashboard:
|
|
58
|
+
forgeo web # http://0.0.0.0:8790 (use -d to keep it running)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+

|
|
62
|
+
|
|
63
|
+
### 4. Start
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
forgeo validate # dry run: config, repo, backlog, agent, locks
|
|
67
|
+
forgeo start # daemon in background, one cycle per interval_minutes
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Each cycle: pick task → run agent → commit/push (or `REVIEW` branch when `review_mode: branch`). Empty backlog → refactoring pass.
|
|
71
|
+
|
|
72
|
+
### Day-to-day
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
forgeo status # config, counts, next task, daemon state, last outcome
|
|
76
|
+
forgeo once # one cycle in foreground, no daemon
|
|
77
|
+
forgeo run --task TASK-012 # run a specific OPEN task now
|
|
78
|
+
forgeo stop / restart # stop or restart daemon
|
|
79
|
+
forgeo web # dashboard for all instances
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
`forgeo web` is open by default on `0.0.0.0:8790`. On a shared host use `forgeo web --token` for bearer auth — see [Web console](docs/web-console-api.md).
|
|
83
|
+
|
|
84
|
+
### Docker sandbox
|
|
85
|
+
|
|
86
|
+
Run the agent isolated:
|
|
87
|
+
|
|
88
|
+
```yaml
|
|
89
|
+
agent_sandbox: docker
|
|
90
|
+
agent_sandbox_image: your-image # must contain agent CLI + sh
|
|
91
|
+
agent_sandbox_network: none # default, no network
|
|
92
|
+
agent_sandbox_mounts: [~/.claude] # read-only mounts
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Repo is bind-mounted at the same path; task arrives as `FORGEO_TASK`. See [Configuration](docs/configuration.md).
|
|
96
|
+
|
|
97
|
+
### Multiple repos
|
|
98
|
+
|
|
99
|
+
One config per repo, fully independent (own backlog, logs, locks). Use the instance registry:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
forgeo instance add site-a --config /path/to/site-a/forgeo.yaml
|
|
103
|
+
forgeo start --name site-a
|
|
104
|
+
forgeo list # all instances
|
|
105
|
+
forgeo web # aggregate dashboard
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Documentation
|
|
109
|
+
|
|
110
|
+
| Topic | Doc |
|
|
111
|
+
| --- | --- |
|
|
112
|
+
| Install, init, first cycle | [Getting Started](docs/getting-started.md) |
|
|
113
|
+
| All `forgeo.yaml` keys | [Configuration](docs/configuration.md) |
|
|
114
|
+
| Task schema & statuses | [Backlog format](docs/backlog.md) |
|
|
115
|
+
| Agent env, exit codes, timeouts | [Agent contract](docs/agent-contract.md) |
|
|
116
|
+
| All CLI commands | [CLI reference](docs/cli-reference.md) |
|
|
117
|
+
| Dashboard & HTTP API | [Web console & HTTP API](docs/web-console-api.md) |
|
|
118
|
+
|
|
119
|
+
**Backlog providers:** [file](docs/backlog.md#a-json-file-backlog) · [HTTP](docs/backlog.md#a-backlog-over-http) · [Jira](docs/backlog.md#a-jira-backlog) · [GitHub](docs/backlog.md#a-github-backlog) · [GitLab](docs/backlog.md#a-gitlab-backlog) — file/HTTP exchange the full document; Jira/GitHub/GitLab sync issues individually. File backlogs are snapshotted (`backlog.json.bak`) before each run and restored if corrupt.
|
|
120
|
+
|
|
121
|
+
**Dashboard:** `forgeo web` aggregates every instance. For `file`/`http` it is the primary editor; for `jira`/`github`/`gitlab` it is a read-mostly mirror (links to native issues, surfaces `BLOCKED`/`FAILED` reasons and retry state).
|
|
122
|
+
|
|
123
|
+
## Develop
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
pip install -e ".[dev]"
|
|
127
|
+
pytest
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) (quality gates: `pytest`, `ruff check`, `mypy src/forgeo`).
|
|
131
|
+
|
|
132
|
+
## License
|
|
133
|
+
|
|
134
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Agent contract
|
|
2
|
+
|
|
3
|
+
The coding agent is **any shell command** that can:
|
|
4
|
+
|
|
5
|
+
1. Read the task from `FORGEO_TASK`.
|
|
6
|
+
2. Work on the repository in the current directory.
|
|
7
|
+
3. Report its outcome via **exit code**.
|
|
8
|
+
|
|
9
|
+
```yaml
|
|
10
|
+
agent_command: "claude -p \"$FORGEO_TASK\""
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Environment
|
|
14
|
+
|
|
15
|
+
Launched with the repo as cwd and:
|
|
16
|
+
|
|
17
|
+
| Variable | Value |
|
|
18
|
+
| --- | --- |
|
|
19
|
+
| `FORGEO_TASK` | Full instruction — project context (if `task_context`), title, description, and "Acceptance criteria:" when present. |
|
|
20
|
+
| `FORGEO_REPO` | Absolute repo path. |
|
|
21
|
+
| `FORGEO_BRANCH` | Target branch (default `main`). |
|
|
22
|
+
| `agent_env` keys | Extra vars from config. |
|
|
23
|
+
| Inherited env | Daemon's own environment. |
|
|
24
|
+
|
|
25
|
+
`FORGEO_*` always wins. For refactoring runs (empty backlog), `FORGEO_TASK` carries the `refactor_prompt` (task ID `REFACTOR`).
|
|
26
|
+
|
|
27
|
+
When `task_context` is set, its file contents are prepended under `# Project context` before `# Task`. Re-read each run; missing file is a warning.
|
|
28
|
+
|
|
29
|
+
## Exit codes
|
|
30
|
+
|
|
31
|
+
| Code | Outcome | What happens |
|
|
32
|
+
| --- | --- | --- |
|
|
33
|
+
| `0` | **SUCCESS** | `git add -A && git commit` as `<title> (#<id>)`, push if `remote` set, task → `COMPLETED`. |
|
|
34
|
+
| `no_changes_exit_code` (default `3`) | **SUCCESS, no changes** | Task → `COMPLETED` without commit. Tree must be clean. |
|
|
35
|
+
| `blocked_exit_code` (default `2`) | **BLOCKED** | Partial work committed as `<title> [partial]`, `blocker_reason` saved, notifications sent, task → `BLOCKED`, `BLOCKER.md` rendered next cycle. |
|
|
36
|
+
| anything else | **ERROR** | Changes discarded (`git reset --hard` + `clean -fd`), task → `FAILED`, `failure_reason` saved. |
|
|
37
|
+
|
|
38
|
+
`FAILED` stays `FAILED` until human reopens (or auto-retried via `failed_retry_max`). `BLOCKED` is never auto-retried.
|
|
39
|
+
|
|
40
|
+
## The no-change contract
|
|
41
|
+
|
|
42
|
+
Forgeo cannot distinguish "deliberately no changes" from "did nothing":
|
|
43
|
+
|
|
44
|
+
- Exit `0` with **unchanged tree** → retried `no_changes_retry_max` times in the same cycle, then `BLOCKED` (never `FAILED` or silent `COMPLETED`).
|
|
45
|
+
- To complete without code change, exit `no_changes_exit_code` with a **clean tree**. Reporting no-change while leaving uncommitted work → `FAILED`.
|
|
46
|
+
|
|
47
|
+
Refactoring passes are exempt — a refactor finding nothing to improve is a normal success.
|
|
48
|
+
|
|
49
|
+
## Timeouts
|
|
50
|
+
|
|
51
|
+
`agent_timeout_seconds` kills the agent after N seconds (`error: timed out after <n>s`). Unset = no timeout. A run overrunning `interval_minutes` is never killed — the next cycle is skipped. Tip: leave unset for long agents and rely on skip-on-overlap.
|
|
52
|
+
|
|
53
|
+
## Output
|
|
54
|
+
|
|
55
|
+
Stdout/stderr are prefixed `[stdout]`/`[stderr]` and the last **1000 lines** are kept. On `BLOCKED`, the agent's questions (or output) become `blocker_reason` and the `BLOCKER.md` section (last 10 lines). Per-run tails go to `runs.jsonl` (`run_output_lines`); per-task `agent_response` is bounded by `agent_response_lines`.
|
|
56
|
+
|
|
57
|
+
## Git contract
|
|
58
|
+
|
|
59
|
+
The agent should **not** run `git` itself — Forgeo handles it:
|
|
60
|
+
|
|
61
|
+
- Make changes in the repo.
|
|
62
|
+
- Do not `git add`/`commit`/`push`/`reset`.
|
|
63
|
+
- Exit `0` for commit, `no_changes_exit_code` for intentional no-op, `blocked_exit_code` for human input, anything else for discard.
|
|
64
|
+
|
|
65
|
+
Embed the contract in your prompt:
|
|
66
|
+
|
|
67
|
+
```yaml
|
|
68
|
+
agent_command: >
|
|
69
|
+
opencode run --auto "Work on the repository at the current working directory.
|
|
70
|
+
Make the requested changes and nothing else. Do NOT run git commit/push/add.
|
|
71
|
+
Verify with tests. Read AGENTS.md and CONTEXT.md if present; update them
|
|
72
|
+
if your change affects the overview.
|
|
73
|
+
$FORGEO_TASK"
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Concurrency
|
|
77
|
+
|
|
78
|
+
One agent per Forgeo: `backlog.lock` prevents a second `start`/`once`, and `backlog.run` makes a waking daemon skip while a run is active.
|