agentforge-framework 0.2.4__tar.gz → 0.2.5__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.
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/PKG-INFO +25 -11
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/README.md +24 -10
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/pyproject.toml +1 -1
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/__init__.py +1 -1
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/cli.py +11 -6
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/core/gates.py +35 -3
- agentforge_framework-0.2.5/src/agentforge_framework/core/project.py +445 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/core/repo.py +14 -0
- agentforge_framework-0.2.5/src/agentforge_framework/core/runlock.py +223 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/core/runtime.py +54 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework.egg-info/PKG-INFO +25 -11
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework.egg-info/SOURCES.txt +2 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/tests/test_cli.py +25 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/tests/test_gates.py +74 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/tests/test_project.py +183 -1
- agentforge_framework-0.2.5/tests/test_runlock.py +189 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/tests/test_runtime.py +27 -2
- agentforge_framework-0.2.4/src/agentforge_framework/core/project.py +0 -270
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/LICENSE +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/setup.cfg +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/.claude-plugin/plugin.json +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/agents/__init__.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/agents/architect.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/agents/decomposer.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/agents/implementer.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/agents/orchestrator.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/agents/reviewer.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/agents/security.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/agents/tester.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/context/__init__.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/context/extractors/__init__.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/context/extractors/base.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/context/extractors/python.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/context/extractors/sql.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/context/extractors/yaml.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/context/prompt.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/context/resolver.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/core/__init__.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/core/commands.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/core/config.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/core/contracts.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/core/issues.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/core/plan_format.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/core/process.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/core/registry.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/core/router.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/core/skills.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/core/workflow.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/plugins/__init__.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/plugins/databricks/__init__.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/plugins/pyspark/__init__.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/plugins/python/__init__.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/plugins/sql/__init__.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/providers/__init__.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/providers/base.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/providers/claude.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/providers/codex.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/MANIFEST.yaml +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/NOTICE +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/domain-modeling/ADR-FORMAT.md +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/domain-modeling/CONTEXT-FORMAT.md +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/domain-modeling/SKILL.md +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/domain-modeling/agents/openai.yaml +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/grill-with-docs/SKILL.md +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/grilling/SKILL.md +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/grilling/agents/openai.yaml +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/to-spec/SKILL.md +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/to-spec/agents/openai.yaml +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/to-tickets/SKILL.md +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/to-tickets/agents/openai.yaml +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/unslop/SKILL.md +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/unslop/evals/fixtures/silhouette/human_reference.json +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/unslop/scripts/_lang.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/unslop/scripts/banned_phrase_scan.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/unslop/scripts/calibrate_pairs.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/unslop/scripts/calibrate_score.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/unslop/scripts/check_packs.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/unslop/scripts/check_suggestions.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/unslop/scripts/contribute.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/unslop/scripts/diff_check.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/unslop/scripts/extract_constraints.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/unslop/scripts/harvest_classify.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/unslop/scripts/harvest_samples.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/unslop/scripts/readability_metrics.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/unslop/scripts/refresh_status.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/unslop/scripts/silhouette_scan.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/unslop/scripts/structure_scan.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/unslop/scripts/suggest.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/unslop/scripts/validate_preservation.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/unslop/scripts/voice_card.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/unslop/scripts/voice_profile.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/unslop/scripts/voice_score.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/unslop/scripts/wiki_sync.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/skills/write-plainly/SKILL.md +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/workflows/bugfix.yaml +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/workflows/feature.yaml +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/workflows/review.yaml +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework.egg-info/dependency_links.txt +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework.egg-info/entry_points.txt +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework.egg-info/requires.txt +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework.egg-info/top_level.txt +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/tests/test_agents.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/tests/test_architect.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/tests/test_config.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/tests/test_context.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/tests/test_contracts.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/tests/test_decompose.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/tests/test_docs.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/tests/test_execution_posture.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/tests/test_interview.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/tests/test_issues.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/tests/test_plan_format.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/tests/test_plugins.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/tests/test_providers.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/tests/test_reviewer.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/tests/test_security.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/tests/test_skills.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/tests/test_tester.py +0 -0
- {agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/tests/test_workflow.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentforge-framework
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.5
|
|
4
4
|
Summary: A modular framework for coordinating specialized software agents.
|
|
5
5
|
Author: Yash Mhatre
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -26,9 +26,9 @@ A human states a Task. The Orchestrator grills them on it, writes a spec, cuts t
|
|
|
26
26
|
|
|
27
27
|
## Status
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
A Workflow runs its Roles in order. The default `feature` Workflow invokes the
|
|
30
|
+
Implementer, the Tester, Security, and then the Reviewer, posting each Agent
|
|
31
|
+
Result to the Issue before starting the next Step.
|
|
32
32
|
|
|
33
33
|
```console
|
|
34
34
|
$ agentforge plan "add a retry to the loader"
|
|
@@ -104,13 +104,15 @@ cannot hold it — `codex exec` discards its approval flag — so a denied Run o
|
|
|
104
104
|
`codex` is refused before it starts rather than run under a guarantee nothing
|
|
105
105
|
enforces (ADR-0007, amended). Security, the Reviewer, and the Architect need no such flag —
|
|
106
106
|
auditing, reviewing, and designing are reading. All six Roles `CONTEXT.md` names
|
|
107
|
-
|
|
107
|
+
run. Plugins carry the data-engineering conventions: a
|
|
108
108
|
repository whose files import `pyspark` has its Roles told to write DataFrame
|
|
109
109
|
expressions rather than RDDs, and a Databricks workspace gets Unity Catalog
|
|
110
110
|
naming and the Delta MERGE idioms in the prompts that write code and the
|
|
111
111
|
workspace's own posture in the one that audits it. A repository that matches
|
|
112
|
-
neither hears neither. `agentforge init`
|
|
113
|
-
|
|
112
|
+
neither hears neither. `agentforge init` inspects a repository and writes its
|
|
113
|
+
`.agentforge/config.yaml`; the file is optional, and
|
|
114
|
+
[Project configuration](#project-configuration) below says what it holds. What
|
|
115
|
+
is still to come is in [`docs/PLAN.md`](docs/PLAN.md).
|
|
114
116
|
|
|
115
117
|
Before the first Role is invoked, AgentForge resolves a Context Pack from the
|
|
116
118
|
frozen plan — the files it names, the symbols and imports inside them, the
|
|
@@ -148,7 +150,7 @@ without notice. See
|
|
|
148
150
|
```console
|
|
149
151
|
$ pip install agentforge-framework
|
|
150
152
|
$ agentforge --version
|
|
151
|
-
agentforge 0.2.
|
|
153
|
+
agentforge 0.2.5
|
|
152
154
|
```
|
|
153
155
|
|
|
154
156
|
That is the whole of it. The two routes below the naming note are for a machine
|
|
@@ -172,7 +174,7 @@ from the [latest release](https://github.com/yashmhatre/AgentForge/releases/late
|
|
|
172
174
|
and install the file:
|
|
173
175
|
|
|
174
176
|
```console
|
|
175
|
-
$ pip install agentforge_framework-0.2.
|
|
177
|
+
$ pip install agentforge_framework-0.2.5-py3-none-any.whl
|
|
176
178
|
```
|
|
177
179
|
|
|
178
180
|
Publishing a release is a wizard rather than a checklist:
|
|
@@ -209,7 +211,7 @@ AgentForge is a terminal tool. It runs fine from an IDE's terminal, but the IDE
|
|
|
209
211
|
|
|
210
212
|
**Antigravity IDE cannot be a Provider** ([#101](https://github.com/yashmhatre/AgentForge/issues/101)). Checked by running it, so nobody has to derive it again: `antigravity-ide chat` accepts a prompt and reads stdin, which is the right shape for the argument vector — but it is a window launcher. Piping a prompt to it returns exit 0 immediately with `Reading from stdin via: …\code-stdin-XXXX` on stdout and nothing else, ever; the answer goes to a GUI session. A Provider adapter has to read the Agent's result off stdout, so there is nothing for `parse_output` to parse. The same is true of any editor CLI of this shape.
|
|
211
213
|
|
|
212
|
-
**Do not run another agent against a checkout while a Run is going.** A Run commits every change to a file git already tracks, however it got there ([ADR-0015](docs/adr/0015-a-run-commits-what-it-declared.md)) — so a second agent's half-finished edits are committed into the Run's branch and attributed to a Role. Files nothing in the Run claimed are listed in the pull request body ([ADR-0023](docs/adr/0023-a-commit-names-what-nothing-claimed.md)), which makes it visible at Sign-off but does not prevent it. Use a separate clone.
|
|
214
|
+
**Do not run another agent against a checkout while a Run is going.** A Run commits every change to a file git already tracks, however it got there ([ADR-0015](docs/adr/0015-a-run-commits-what-it-declared.md)) — so a second agent's half-finished edits are committed into the Run's branch and attributed to a Role. Files nothing in the Run claimed are listed in the pull request body ([ADR-0023](docs/adr/0023-a-commit-names-what-nothing-claimed.md)), which makes it visible at Sign-off but does not prevent it. Use a separate clone. A second `agentforge implement` is refused outright rather than merely disclosed — a Run holds its checkout for the duration ([ADR-0026](docs/adr/0026-a-run-holds-the-checkout-it-was-pointed-at.md)) — but nothing else consults that lock, so an IDE assistant is still yours to keep away.
|
|
213
215
|
|
|
214
216
|
## Commands
|
|
215
217
|
|
|
@@ -277,9 +279,21 @@ if the repository has no GitHub remote, because ADR-0002 makes that a
|
|
|
277
279
|
precondition for every Run. Re-running never clobbers a config you have edited:
|
|
278
280
|
it reports what differs and writes nothing, and `--force` replaces it.
|
|
279
281
|
|
|
282
|
+
A Python suite is written pinned to the interpreter that will run it —
|
|
283
|
+
`[".venv/bin/python", "-m", "pytest"]` rather than `pytest` — whenever the
|
|
284
|
+
repository has a virtualenv to pin it to, and init checks that the interpreter
|
|
285
|
+
can run pytest before writing the line. Bare `pytest` is whichever one PATH
|
|
286
|
+
answers with, which in a project with a venv is the one the project does not
|
|
287
|
+
use: the suite then fails on imports that are installed and reads as a broken
|
|
288
|
+
repository rather than a misconfigured one. The interpreter is named relative to
|
|
289
|
+
the repository root, so the file is still right on somebody else's clone, and
|
|
290
|
+
init looks up to two directories down for the project — a suite that lives in
|
|
291
|
+
`subproject/tests/` is found, and named.
|
|
292
|
+
|
|
280
293
|
The file is not a precondition. Without one, the documented Provider capability
|
|
281
294
|
defaults are Claude `native` and every other Provider `fragment`, and the
|
|
282
|
-
`tests` Gate runs `pytest
|
|
295
|
+
`tests` Gate runs `pytest` — the case the pinning above exists to avoid, so a
|
|
296
|
+
repository with a venv is better off with a file.
|
|
283
297
|
|
|
284
298
|
```yaml
|
|
285
299
|
providers:
|
|
@@ -8,9 +8,9 @@ A human states a Task. The Orchestrator grills them on it, writes a spec, cuts t
|
|
|
8
8
|
|
|
9
9
|
## Status
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
A Workflow runs its Roles in order. The default `feature` Workflow invokes the
|
|
12
|
+
Implementer, the Tester, Security, and then the Reviewer, posting each Agent
|
|
13
|
+
Result to the Issue before starting the next Step.
|
|
14
14
|
|
|
15
15
|
```console
|
|
16
16
|
$ agentforge plan "add a retry to the loader"
|
|
@@ -86,13 +86,15 @@ cannot hold it — `codex exec` discards its approval flag — so a denied Run o
|
|
|
86
86
|
`codex` is refused before it starts rather than run under a guarantee nothing
|
|
87
87
|
enforces (ADR-0007, amended). Security, the Reviewer, and the Architect need no such flag —
|
|
88
88
|
auditing, reviewing, and designing are reading. All six Roles `CONTEXT.md` names
|
|
89
|
-
|
|
89
|
+
run. Plugins carry the data-engineering conventions: a
|
|
90
90
|
repository whose files import `pyspark` has its Roles told to write DataFrame
|
|
91
91
|
expressions rather than RDDs, and a Databricks workspace gets Unity Catalog
|
|
92
92
|
naming and the Delta MERGE idioms in the prompts that write code and the
|
|
93
93
|
workspace's own posture in the one that audits it. A repository that matches
|
|
94
|
-
neither hears neither. `agentforge init`
|
|
95
|
-
|
|
94
|
+
neither hears neither. `agentforge init` inspects a repository and writes its
|
|
95
|
+
`.agentforge/config.yaml`; the file is optional, and
|
|
96
|
+
[Project configuration](#project-configuration) below says what it holds. What
|
|
97
|
+
is still to come is in [`docs/PLAN.md`](docs/PLAN.md).
|
|
96
98
|
|
|
97
99
|
Before the first Role is invoked, AgentForge resolves a Context Pack from the
|
|
98
100
|
frozen plan — the files it names, the symbols and imports inside them, the
|
|
@@ -130,7 +132,7 @@ without notice. See
|
|
|
130
132
|
```console
|
|
131
133
|
$ pip install agentforge-framework
|
|
132
134
|
$ agentforge --version
|
|
133
|
-
agentforge 0.2.
|
|
135
|
+
agentforge 0.2.5
|
|
134
136
|
```
|
|
135
137
|
|
|
136
138
|
That is the whole of it. The two routes below the naming note are for a machine
|
|
@@ -154,7 +156,7 @@ from the [latest release](https://github.com/yashmhatre/AgentForge/releases/late
|
|
|
154
156
|
and install the file:
|
|
155
157
|
|
|
156
158
|
```console
|
|
157
|
-
$ pip install agentforge_framework-0.2.
|
|
159
|
+
$ pip install agentforge_framework-0.2.5-py3-none-any.whl
|
|
158
160
|
```
|
|
159
161
|
|
|
160
162
|
Publishing a release is a wizard rather than a checklist:
|
|
@@ -191,7 +193,7 @@ AgentForge is a terminal tool. It runs fine from an IDE's terminal, but the IDE
|
|
|
191
193
|
|
|
192
194
|
**Antigravity IDE cannot be a Provider** ([#101](https://github.com/yashmhatre/AgentForge/issues/101)). Checked by running it, so nobody has to derive it again: `antigravity-ide chat` accepts a prompt and reads stdin, which is the right shape for the argument vector — but it is a window launcher. Piping a prompt to it returns exit 0 immediately with `Reading from stdin via: …\code-stdin-XXXX` on stdout and nothing else, ever; the answer goes to a GUI session. A Provider adapter has to read the Agent's result off stdout, so there is nothing for `parse_output` to parse. The same is true of any editor CLI of this shape.
|
|
193
195
|
|
|
194
|
-
**Do not run another agent against a checkout while a Run is going.** A Run commits every change to a file git already tracks, however it got there ([ADR-0015](docs/adr/0015-a-run-commits-what-it-declared.md)) — so a second agent's half-finished edits are committed into the Run's branch and attributed to a Role. Files nothing in the Run claimed are listed in the pull request body ([ADR-0023](docs/adr/0023-a-commit-names-what-nothing-claimed.md)), which makes it visible at Sign-off but does not prevent it. Use a separate clone.
|
|
196
|
+
**Do not run another agent against a checkout while a Run is going.** A Run commits every change to a file git already tracks, however it got there ([ADR-0015](docs/adr/0015-a-run-commits-what-it-declared.md)) — so a second agent's half-finished edits are committed into the Run's branch and attributed to a Role. Files nothing in the Run claimed are listed in the pull request body ([ADR-0023](docs/adr/0023-a-commit-names-what-nothing-claimed.md)), which makes it visible at Sign-off but does not prevent it. Use a separate clone. A second `agentforge implement` is refused outright rather than merely disclosed — a Run holds its checkout for the duration ([ADR-0026](docs/adr/0026-a-run-holds-the-checkout-it-was-pointed-at.md)) — but nothing else consults that lock, so an IDE assistant is still yours to keep away.
|
|
195
197
|
|
|
196
198
|
## Commands
|
|
197
199
|
|
|
@@ -259,9 +261,21 @@ if the repository has no GitHub remote, because ADR-0002 makes that a
|
|
|
259
261
|
precondition for every Run. Re-running never clobbers a config you have edited:
|
|
260
262
|
it reports what differs and writes nothing, and `--force` replaces it.
|
|
261
263
|
|
|
264
|
+
A Python suite is written pinned to the interpreter that will run it —
|
|
265
|
+
`[".venv/bin/python", "-m", "pytest"]` rather than `pytest` — whenever the
|
|
266
|
+
repository has a virtualenv to pin it to, and init checks that the interpreter
|
|
267
|
+
can run pytest before writing the line. Bare `pytest` is whichever one PATH
|
|
268
|
+
answers with, which in a project with a venv is the one the project does not
|
|
269
|
+
use: the suite then fails on imports that are installed and reads as a broken
|
|
270
|
+
repository rather than a misconfigured one. The interpreter is named relative to
|
|
271
|
+
the repository root, so the file is still right on somebody else's clone, and
|
|
272
|
+
init looks up to two directories down for the project — a suite that lives in
|
|
273
|
+
`subproject/tests/` is found, and named.
|
|
274
|
+
|
|
262
275
|
The file is not a precondition. Without one, the documented Provider capability
|
|
263
276
|
defaults are Claude `native` and every other Provider `fragment`, and the
|
|
264
|
-
`tests` Gate runs `pytest
|
|
277
|
+
`tests` Gate runs `pytest` — the case the pinning above exists to avoid, so a
|
|
278
|
+
repository with a venv is better off with a file.
|
|
265
279
|
|
|
266
280
|
```yaml
|
|
267
281
|
providers:
|
|
@@ -512,7 +512,7 @@ def _run_init(args: argparse.Namespace, runner=None) -> int:
|
|
|
512
512
|
from .core.config import load_config
|
|
513
513
|
from .core.contracts import Plan
|
|
514
514
|
from .core.process import SubprocessRunner
|
|
515
|
-
from .core.project import config_path, detect, differences, render_config
|
|
515
|
+
from .core.project import config_path, detect, differences, render_config, verified
|
|
516
516
|
from .core.registry import activate
|
|
517
517
|
from .core.repo import PreconditionFailed, open_repository
|
|
518
518
|
from .providers import DEFAULT_PROVIDER, PROVIDERS
|
|
@@ -531,11 +531,14 @@ def _run_init(args: argparse.Namespace, runner=None) -> int:
|
|
|
531
531
|
return 2
|
|
532
532
|
|
|
533
533
|
active = activate(Plan(summary=""), repo.root)
|
|
534
|
-
context =
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
534
|
+
context = verified(
|
|
535
|
+
detect(
|
|
536
|
+
repo.root,
|
|
537
|
+
provider,
|
|
538
|
+
tracked=repo.tracked_files(),
|
|
539
|
+
plugins=tuple(plugin.name for plugin in active.plugins),
|
|
540
|
+
),
|
|
541
|
+
runner,
|
|
539
542
|
)
|
|
540
543
|
|
|
541
544
|
print(f"Repository: {repo.root}")
|
|
@@ -544,6 +547,8 @@ def _run_init(args: argparse.Namespace, runner=None) -> int:
|
|
|
544
547
|
suite = " ".join(context.test_suite)
|
|
545
548
|
where = context.suite_detected or "not detected, so this is the documented default"
|
|
546
549
|
print(f" Suite: `{suite}` — {where}")
|
|
550
|
+
if context.suite_note:
|
|
551
|
+
print(f" {context.suite_note}")
|
|
547
552
|
print(f" Plugins: {', '.join(context.plugins) or 'none by root marker'}")
|
|
548
553
|
print(
|
|
549
554
|
" printed, not written: which Plugins answer is decided per Run\n"
|
{agentforge_framework-0.2.4 → agentforge_framework-0.2.5}/src/agentforge_framework/core/gates.py
RENAMED
|
@@ -110,6 +110,11 @@ def human(context: GateContext) -> GateEntry:
|
|
|
110
110
|
#: nothing collected; none of those say anything about the repository.
|
|
111
111
|
SUITE_FAILED = 1
|
|
112
112
|
|
|
113
|
+
#: What `python -m` prints when the runner it was asked for is not installed in
|
|
114
|
+
#: that interpreter. It exits 1 doing it, which is the one status that otherwise
|
|
115
|
+
#: means the suite ran and reported on the code.
|
|
116
|
+
MODULE_MISSING = "No module named"
|
|
117
|
+
|
|
113
118
|
#: How much of a failing suite reaches the Run Log. The end of it: a test runner
|
|
114
119
|
#: puts its summary last, and a comment nobody scrolls to the bottom of is a
|
|
115
120
|
#: comment nobody reads.
|
|
@@ -138,11 +143,12 @@ def tests(context: GateContext) -> GateEntry:
|
|
|
138
143
|
runs. A Gate is not an Agent: the suite is the one the project declared, its
|
|
139
144
|
exit status is read rather than interpreted, and no model chose either.
|
|
140
145
|
"""
|
|
141
|
-
|
|
142
|
-
rendered = " ".join(
|
|
146
|
+
declared = load_config(context.root).test_suite
|
|
147
|
+
rendered = " ".join(declared)
|
|
148
|
+
suite = _resolved(declared, context.root)
|
|
143
149
|
|
|
144
150
|
if not context.runner.has_binary(suite[0]):
|
|
145
|
-
return _cannot_run(rendered, f"{
|
|
151
|
+
return _cannot_run(rendered, f"{declared[0]!r} is not installed or not on PATH")
|
|
146
152
|
|
|
147
153
|
try:
|
|
148
154
|
result = context.runner.run(suite, cwd=context.root)
|
|
@@ -160,6 +166,13 @@ def tests(context: GateContext) -> GateEntry:
|
|
|
160
166
|
summary=f"`{rendered}` passed.",
|
|
161
167
|
)
|
|
162
168
|
|
|
169
|
+
if result.returncode == SUITE_FAILED and MODULE_MISSING in result.stderr:
|
|
170
|
+
# An interpreter that has no pytest exits 1, which is the status a suite
|
|
171
|
+
# spends on real failures. The interpreter says so on standard error and
|
|
172
|
+
# a failing suite reports its failures on standard output, so the two are
|
|
173
|
+
# told apart there rather than by the status they share.
|
|
174
|
+
return _cannot_run(rendered, f"{declared[0]!r} has no test runner installed")
|
|
175
|
+
|
|
163
176
|
if result.returncode == SUITE_FAILED:
|
|
164
177
|
return GateEntry(
|
|
165
178
|
kind="",
|
|
@@ -181,6 +194,25 @@ def tests(context: GateContext) -> GateEntry:
|
|
|
181
194
|
)
|
|
182
195
|
|
|
183
196
|
|
|
197
|
+
def _resolved(suite: tuple[str, ...], root: Path) -> tuple[str, ...]:
|
|
198
|
+
"""A suite whose first word is a path, resolved against the repository.
|
|
199
|
+
|
|
200
|
+
`agentforge init` pins a Python suite to the project's own virtualenv and
|
|
201
|
+
writes that interpreter relative to the root, because the file it writes gets
|
|
202
|
+
committed and an absolute path is right on one machine only. Resolving it
|
|
203
|
+
here is what makes the relative form work at all: a relative program name is
|
|
204
|
+
resolved against the child process's directory on POSIX and the parent's on
|
|
205
|
+
Windows, so leaving it to the OS would run on one platform and not the other.
|
|
206
|
+
|
|
207
|
+
A suite naming a plain command is returned untouched, PATH lookup and all.
|
|
208
|
+
"""
|
|
209
|
+
program = Path(suite[0])
|
|
210
|
+
if program.is_absolute() or len(program.parts) == 1:
|
|
211
|
+
return suite
|
|
212
|
+
candidate = root / program
|
|
213
|
+
return (str(candidate), *suite[1:]) if candidate.is_file() else suite
|
|
214
|
+
|
|
215
|
+
|
|
184
216
|
def _cannot_run(rendered: str, reason: str) -> GateEntry:
|
|
185
217
|
"""The suite never started, which is not a report on the code.
|
|
186
218
|
|