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.
Files changed (98) hide show
  1. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/CHANGELOG.md +43 -1
  2. forgeo_cli-0.11.0/PKG-INFO +188 -0
  3. forgeo_cli-0.11.0/README.md +134 -0
  4. forgeo_cli-0.11.0/docs/agent-contract.md +78 -0
  5. forgeo_cli-0.11.0/docs/backlog.md +217 -0
  6. forgeo_cli-0.11.0/docs/cli-reference.md +173 -0
  7. forgeo_cli-0.11.0/docs/configuration.md +263 -0
  8. forgeo_cli-0.11.0/docs/getting-started.md +116 -0
  9. forgeo_cli-0.11.0/docs/index.md +37 -0
  10. forgeo_cli-0.11.0/docs/web-console-api.md +220 -0
  11. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/install.sh +1 -1
  12. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/mkdocs.yml +1 -1
  13. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/pyproject.toml +1 -1
  14. forgeo_cli-0.11.0/scripts/test-github-backlog-e2e.sh +225 -0
  15. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/__init__.py +1 -1
  16. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/agent.py +43 -27
  17. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/backlog.py +196 -40
  18. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/backlog_github.py +137 -189
  19. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/backlog_gitlab.py +123 -169
  20. forgeo_cli-0.11.0/src/forgeo/backlog_issue_base.py +366 -0
  21. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/backlog_jira.py +113 -103
  22. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/central.py +262 -68
  23. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/config.py +15 -12
  24. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/daemon.py +10 -5
  25. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/daemon_control.py +1 -1
  26. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/forgeo.py +158 -59
  27. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/git.py +76 -9
  28. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/io.py +2 -0
  29. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/models.py +149 -175
  30. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/paths.py +1 -1
  31. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/runs.py +5 -4
  32. forgeo_cli-0.11.0/src/forgeo/setup.py +494 -0
  33. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/validate.py +36 -52
  34. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/web/central/central.css +104 -0
  35. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/web/central/central.js +168 -5
  36. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/web/central/instance.html +37 -1
  37. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/web/style.css +16 -1
  38. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/web_common.py +5 -7
  39. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/conftest.py +20 -7
  40. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_cli.py +9 -32
  41. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_setup.py +54 -3
  42. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_web.py +3 -2
  43. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_web_lock.py +1 -1
  44. forgeo_cli-0.9.0/PKG-INFO +0 -242
  45. forgeo_cli-0.9.0/README.md +0 -188
  46. forgeo_cli-0.9.0/docs/agent-contract.md +0 -154
  47. forgeo_cli-0.9.0/docs/backlog.md +0 -510
  48. forgeo_cli-0.9.0/docs/cli-reference.md +0 -372
  49. forgeo_cli-0.9.0/docs/configuration.md +0 -536
  50. forgeo_cli-0.9.0/docs/getting-started.md +0 -205
  51. forgeo_cli-0.9.0/docs/index.md +0 -67
  52. forgeo_cli-0.9.0/docs/web-console-api.md +0 -674
  53. forgeo_cli-0.9.0/src/forgeo/backlog_issue_base.py +0 -183
  54. forgeo_cli-0.9.0/src/forgeo/setup.py +0 -230
  55. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/.github/workflows/ci.yml +0 -0
  56. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/.gitignore +0 -0
  57. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/CONTRIBUTING.md +0 -0
  58. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/LICENSE +0 -0
  59. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/config/nginx-forgeo.conf +0 -0
  60. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/docs/img/console.png +0 -0
  61. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/docs/img/demo.gif +0 -0
  62. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/docs/img/logo.png +0 -0
  63. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/docs/img/og.png +0 -0
  64. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/docs/img/title.svg +0 -0
  65. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/forgeo.spec +0 -0
  66. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/scripts/__init__.py +0 -0
  67. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/scripts/render_homebrew_formula.py +0 -0
  68. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/__main__.py +0 -0
  69. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/backlog_http.py +0 -0
  70. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/cli.py +0 -0
  71. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/instances.py +0 -0
  72. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/notify.py +0 -0
  73. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/oauth.py +0 -0
  74. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/update.py +0 -0
  75. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/web/central/index.html +0 -0
  76. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/src/forgeo/web/central/login.html +0 -0
  77. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_agent.py +0 -0
  78. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_backlog.py +0 -0
  79. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_backlog_github.py +0 -0
  80. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_backlog_gitlab.py +0 -0
  81. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_backlog_http.py +0 -0
  82. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_backlog_jira.py +0 -0
  83. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_daemon.py +0 -0
  84. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_factory.py +0 -0
  85. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_git.py +0 -0
  86. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_install.py +0 -0
  87. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_instances.py +0 -0
  88. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_io.py +0 -0
  89. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_models.py +0 -0
  90. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_oauth.py +0 -0
  91. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_paths.py +0 -0
  92. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_remote_backlog_cycle.py +0 -0
  93. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_render_homebrew.py +0 -0
  94. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_runs.py +0 -0
  95. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_update.py +0 -0
  96. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/tests/test_web_common.py +0 -0
  97. {forgeo_cli-0.9.0 → forgeo_cli-0.11.0}/www/404.html +0 -0
  98. {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.9.0...HEAD
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
+ [![CI](https://github.com/lucaGazzola/forgeo/actions/workflows/ci.yml/badge.svg)](https://github.com/lucaGazzola/forgeo/actions/workflows/ci.yml)
64
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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
+ ![Forgeo web console](docs/img/console.png)
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
+ [![CI](https://github.com/lucaGazzola/forgeo/actions/workflows/ci.yml/badge.svg)](https://github.com/lucaGazzola/forgeo/actions/workflows/ci.yml)
10
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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
+ ![Forgeo web console](docs/img/console.png)
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.