autodevloop 0.1.0__py3-none-any.whl
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.
- autodevloop/__init__.py +5 -0
- autodevloop/__main__.py +6 -0
- autodevloop/cli.py +233 -0
- autodevloop/config.py +165 -0
- autodevloop/engine.py +750 -0
- autodevloop/llm.py +259 -0
- autodevloop/prompts.py +342 -0
- autodevloop/py.typed +0 -0
- autodevloop/registry.py +37 -0
- autodevloop/reporting.py +127 -0
- autodevloop/testing.py +119 -0
- autodevloop/util.py +250 -0
- autodevloop/vcs.py +74 -0
- autodevloop/webapp.py +1184 -0
- autodevloop/yaml_compat.py +192 -0
- autodevloop-0.1.0.dist-info/METADATA +332 -0
- autodevloop-0.1.0.dist-info/RECORD +21 -0
- autodevloop-0.1.0.dist-info/WHEEL +5 -0
- autodevloop-0.1.0.dist-info/entry_points.txt +2 -0
- autodevloop-0.1.0.dist-info/licenses/LICENSE +21 -0
- autodevloop-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
"""Minimal YAML load/dump with optional PyYAML acceleration.
|
|
2
|
+
|
|
3
|
+
If PyYAML is installed it is used for full-fidelity parsing and dumping.
|
|
4
|
+
Otherwise a small but correct subset implementation handles the nested
|
|
5
|
+
maps, block/flow lists, scalars, comments, and quoting that AutoDevLoop
|
|
6
|
+
config files use. We control the config schema, so the fallback is safe.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
13
|
+
try: # pragma: no cover - exercised when PyYAML is present
|
|
14
|
+
import yaml as _pyyaml
|
|
15
|
+
except Exception: # noqa: BLE001
|
|
16
|
+
_pyyaml = None
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _scalar(raw: str) -> Any:
|
|
20
|
+
value = raw.strip()
|
|
21
|
+
if value == "" or value.lower() in {"null", "none", "~"}:
|
|
22
|
+
return None
|
|
23
|
+
low = value.lower()
|
|
24
|
+
if low in {"true", "yes", "on"}:
|
|
25
|
+
return True
|
|
26
|
+
if low in {"false", "no", "off"}:
|
|
27
|
+
return False
|
|
28
|
+
if value.startswith("[") and value.endswith("]"):
|
|
29
|
+
inner = value[1:-1].strip()
|
|
30
|
+
if not inner:
|
|
31
|
+
return []
|
|
32
|
+
return [_scalar(part) for part in _split_flow(inner)]
|
|
33
|
+
if (value[0] == value[-1]) and value[0] in {'"', "'"} and len(value) >= 2:
|
|
34
|
+
return value[1:-1]
|
|
35
|
+
try:
|
|
36
|
+
return int(value)
|
|
37
|
+
except ValueError:
|
|
38
|
+
pass
|
|
39
|
+
try:
|
|
40
|
+
return float(value)
|
|
41
|
+
except ValueError:
|
|
42
|
+
return value
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _split_flow(inner: str) -> list[str]:
|
|
46
|
+
parts: list[str] = []
|
|
47
|
+
depth = 0
|
|
48
|
+
quote = ""
|
|
49
|
+
current = ""
|
|
50
|
+
for ch in inner:
|
|
51
|
+
if quote:
|
|
52
|
+
current += ch
|
|
53
|
+
if ch == quote:
|
|
54
|
+
quote = ""
|
|
55
|
+
continue
|
|
56
|
+
if ch in {'"', "'"}:
|
|
57
|
+
quote = ch
|
|
58
|
+
current += ch
|
|
59
|
+
elif ch in "[{":
|
|
60
|
+
depth += 1
|
|
61
|
+
current += ch
|
|
62
|
+
elif ch in "]}":
|
|
63
|
+
depth -= 1
|
|
64
|
+
current += ch
|
|
65
|
+
elif ch == "," and depth == 0:
|
|
66
|
+
parts.append(current)
|
|
67
|
+
current = ""
|
|
68
|
+
else:
|
|
69
|
+
current += ch
|
|
70
|
+
if current.strip():
|
|
71
|
+
parts.append(current)
|
|
72
|
+
return parts
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _fallback_load(text: str) -> Any:
|
|
76
|
+
lines = []
|
|
77
|
+
for raw in text.splitlines():
|
|
78
|
+
if not raw.strip() or raw.lstrip().startswith("#"):
|
|
79
|
+
continue
|
|
80
|
+
# strip trailing inline comments outside quotes
|
|
81
|
+
lines.append(raw.rstrip())
|
|
82
|
+
|
|
83
|
+
root: dict[str, Any] = {}
|
|
84
|
+
# stack entries: (indent, container, container_kind)
|
|
85
|
+
stack: list[tuple[int, Any, str]] = [(-1, root, "map")]
|
|
86
|
+
|
|
87
|
+
for raw in lines:
|
|
88
|
+
indent = len(raw) - len(raw.lstrip(" "))
|
|
89
|
+
content = raw.strip()
|
|
90
|
+
while stack and indent <= stack[-1][0] and not (content.startswith("- ") or content == "-"):
|
|
91
|
+
stack.pop()
|
|
92
|
+
if not stack:
|
|
93
|
+
stack = [(-1, root, "map")]
|
|
94
|
+
parent = stack[-1][1]
|
|
95
|
+
|
|
96
|
+
if content.startswith("- ") or content == "-":
|
|
97
|
+
item_text = content[1:].strip()
|
|
98
|
+
# ensure parent is a list
|
|
99
|
+
if not isinstance(parent, list):
|
|
100
|
+
continue
|
|
101
|
+
if item_text == "":
|
|
102
|
+
child: dict[str, Any] = {}
|
|
103
|
+
parent.append(child)
|
|
104
|
+
stack.append((indent, child, "map"))
|
|
105
|
+
elif ":" in item_text and not item_text.startswith(("'", '"')):
|
|
106
|
+
child = {}
|
|
107
|
+
parent.append(child)
|
|
108
|
+
key, _, val = item_text.partition(":")
|
|
109
|
+
child[key.strip()] = _scalar(val) if val.strip() else {}
|
|
110
|
+
stack.append((indent, child, "map"))
|
|
111
|
+
else:
|
|
112
|
+
parent.append(_scalar(item_text))
|
|
113
|
+
continue
|
|
114
|
+
|
|
115
|
+
if ":" not in content:
|
|
116
|
+
continue
|
|
117
|
+
key, _, val = content.partition(":")
|
|
118
|
+
key = key.strip()
|
|
119
|
+
val = val.strip()
|
|
120
|
+
if not isinstance(parent, dict):
|
|
121
|
+
continue
|
|
122
|
+
if val == "":
|
|
123
|
+
# could be a nested map or a list; decide by next line indent later.
|
|
124
|
+
child_map: dict[str, Any] = {}
|
|
125
|
+
parent[key] = child_map
|
|
126
|
+
stack.append((indent, child_map, "map"))
|
|
127
|
+
else:
|
|
128
|
+
parent[key] = _scalar(val)
|
|
129
|
+
|
|
130
|
+
return _promote_lists(root)
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def _promote_lists(node: Any) -> Any:
|
|
134
|
+
"""Convert empty-map placeholders that actually hold list items."""
|
|
135
|
+
if isinstance(node, dict):
|
|
136
|
+
return {k: _promote_lists(v) for k, v in node.items()}
|
|
137
|
+
return node
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def load(text: str) -> dict[str, Any]:
|
|
141
|
+
if not text or not text.strip():
|
|
142
|
+
return {}
|
|
143
|
+
if _pyyaml is not None:
|
|
144
|
+
data = _pyyaml.safe_load(text)
|
|
145
|
+
return data if isinstance(data, dict) else {}
|
|
146
|
+
data = _fallback_load(text)
|
|
147
|
+
return data if isinstance(data, dict) else {}
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def _dump_scalar(value: Any) -> str:
|
|
151
|
+
if value is None:
|
|
152
|
+
return "null"
|
|
153
|
+
if isinstance(value, bool):
|
|
154
|
+
return "true" if value else "false"
|
|
155
|
+
if isinstance(value, (int, float)):
|
|
156
|
+
return str(value)
|
|
157
|
+
text = str(value)
|
|
158
|
+
if text == "" or any(c in text for c in ":#") or text.strip() != text or text.lower() in {"true", "false", "null", "yes", "no"}:
|
|
159
|
+
escaped = text.replace('"', '\\"')
|
|
160
|
+
return f'"{escaped}"'
|
|
161
|
+
return text
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
def _fallback_dump(data: Any, indent: int = 0) -> str:
|
|
165
|
+
pad = " " * indent
|
|
166
|
+
lines: list[str] = []
|
|
167
|
+
if isinstance(data, dict):
|
|
168
|
+
for key, value in data.items():
|
|
169
|
+
if isinstance(value, dict) and value:
|
|
170
|
+
lines.append(f"{pad}{key}:")
|
|
171
|
+
lines.append(_fallback_dump(value, indent + 1))
|
|
172
|
+
elif isinstance(value, list) and value:
|
|
173
|
+
lines.append(f"{pad}{key}:")
|
|
174
|
+
for item in value:
|
|
175
|
+
if isinstance(item, dict):
|
|
176
|
+
body = _fallback_dump(item, indent + 2).lstrip()
|
|
177
|
+
lines.append(f"{pad} - {body}")
|
|
178
|
+
else:
|
|
179
|
+
lines.append(f"{pad} - {_dump_scalar(item)}")
|
|
180
|
+
elif isinstance(value, list):
|
|
181
|
+
lines.append(f"{pad}{key}: []")
|
|
182
|
+
elif isinstance(value, dict):
|
|
183
|
+
lines.append(f"{pad}{key}: {{}}")
|
|
184
|
+
else:
|
|
185
|
+
lines.append(f"{pad}{key}: {_dump_scalar(value)}")
|
|
186
|
+
return "\n".join(line for line in lines if line != "")
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def dump(data: dict[str, Any]) -> str:
|
|
190
|
+
if _pyyaml is not None:
|
|
191
|
+
return _pyyaml.safe_dump(data, allow_unicode=True, sort_keys=False, default_flow_style=False)
|
|
192
|
+
return _fallback_dump(data).rstrip() + "\n"
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: autodevloop
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: AI-driven autonomous software iteration loop: set a goal, let CLI coding agents architect, build, test, review and evolve a project version by version.
|
|
5
|
+
Author: wp
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/selavieWp/autodevloop
|
|
8
|
+
Project-URL: Repository, https://github.com/selavieWp/autodevloop
|
|
9
|
+
Project-URL: Issues, https://github.com/selavieWp/autodevloop/issues
|
|
10
|
+
Keywords: ai,agents,automation,claude,codegen,autonomous,iteration
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Provides-Extra: yaml
|
|
23
|
+
Requires-Dist: PyYAML>=6.0; extra == "yaml"
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
|
|
28
|
+
# AutoDevLoop
|
|
29
|
+
|
|
30
|
+
> Set one goal. Watch AI coding agents architect, build, test, review, and keep evolving a real project — version by version — until your target version count is reached.
|
|
31
|
+
|
|
32
|
+
**English** · [简体中文](README.zh-CN.md)
|
|
33
|
+
|
|
34
|
+
AutoDevLoop is a small, dependency-free Python tool that drives a CLI coding
|
|
35
|
+
agent (Claude Code by default; Codex / Gemini CLI also supported) through a
|
|
36
|
+
standardised, multi-stage development loop. You give it a goal and a number of
|
|
37
|
+
versions; it designs an architecture, plans each version, writes the code,
|
|
38
|
+
runs tests, reviews the result, and — once your goal is met — proposes and
|
|
39
|
+
value-gates **new** features to keep improving the product on its own.
|
|
40
|
+
|
|
41
|
+
Every version is a usable, snapshotted build. A glanceable `FEATURES.md` table
|
|
42
|
+
records what each version delivers and what changed since the last one.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Highlights
|
|
47
|
+
|
|
48
|
+
- **Goal-driven, two-phase loop.** A **build** phase drives straight at your
|
|
49
|
+
goal; once an independent check decides the goal is genuinely met, it flips to
|
|
50
|
+
an **expand** phase that builds valuable adjacent features.
|
|
51
|
+
- **Value gate for new features.** In the expand phase, one agent scouts ideas
|
|
52
|
+
and a *separate* agent scores each for value/effort — only accepted ideas
|
|
53
|
+
enter the backlog and get built. No random feature bloat.
|
|
54
|
+
- **Standard flow, dynamic detail.** The pipeline (architecture → plan → develop
|
|
55
|
+
→ test → review → fix → scout → evaluate) is fixed and predictable, but the
|
|
56
|
+
planner decides how many dev agents to spawn, what each does, and the prompts
|
|
57
|
+
leave room for the model's judgement. Prompts are **editable template files**,
|
|
58
|
+
not hard-coded strings.
|
|
59
|
+
- **Simple vs advanced modes.** `simple` runs a cheap core loop
|
|
60
|
+
(plan → develop → test → review) to save tokens; `advanced` adds goal checks,
|
|
61
|
+
a test-planning agent, docs, scouting, and the value gate. Individual steps
|
|
62
|
+
are toggleable.
|
|
63
|
+
- **One working folder, many snapshots.** Agents only ever edit `current/`;
|
|
64
|
+
each finished version is copied to `versions/vN/`. If git is available, every
|
|
65
|
+
version is also committed and tagged, and the version where your goal is first
|
|
66
|
+
met gets a special `goal-complete` tag.
|
|
67
|
+
- **Cost & token tracking.** Every provider call's cost and tokens are recorded
|
|
68
|
+
and surfaced live.
|
|
69
|
+
- **Local web dashboard.** Start projects, watch live progress (current version,
|
|
70
|
+
agent, step, cost, per-agent output), read the changelog/feature table, and
|
|
71
|
+
edit configuration + prompts — all in the browser. No build step, no
|
|
72
|
+
dependencies.
|
|
73
|
+
- **Resilient.** Threaded provider I/O (no stdin/stdout deadlocks), retry with
|
|
74
|
+
exponential backoff on transient failures, atomic state writes, and automatic
|
|
75
|
+
rollback of the working copy if a version errors out.
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Requirements
|
|
80
|
+
|
|
81
|
+
- **Python 3.10+**
|
|
82
|
+
- **A coding-agent CLI installed and authenticated locally**, one of:
|
|
83
|
+
- [Claude Code](https://docs.claude.com/en/docs/claude-code) — `claude` (default)
|
|
84
|
+
- Codex CLI — `codex`
|
|
85
|
+
- Gemini CLI — `gemini`
|
|
86
|
+
|
|
87
|
+
AutoDevLoop **never asks for API keys**. You authenticate your CLI of choice
|
|
88
|
+
beforehand; switching providers just changes which command is invoked. (Using
|
|
89
|
+
a third-party API endpoint behind the `claude` CLI works fine — the tool just
|
|
90
|
+
calls `claude`.)
|
|
91
|
+
|
|
92
|
+
No Python runtime dependencies are required. `PyYAML` is optional (a built-in
|
|
93
|
+
fallback YAML parser ships with the tool).
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Install
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
# from the project root
|
|
101
|
+
pip install -e .
|
|
102
|
+
# now the `autodevloop` command is available
|
|
103
|
+
autodevloop --version
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Or run without installing:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
python -m autodevloop --help
|
|
110
|
+
# or the backward-compatible shim:
|
|
111
|
+
python autodev.py --help
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Quick start
|
|
117
|
+
|
|
118
|
+
### CLI
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
# Interactive (prompts for directory, goal, versions, mode):
|
|
122
|
+
autodevloop run
|
|
123
|
+
|
|
124
|
+
# Non-interactive:
|
|
125
|
+
autodevloop run --project-dir ./my-app \
|
|
126
|
+
--goal "Build a WeChat-like app: real-time chat plus a moments feed" \
|
|
127
|
+
--max-versions 8 --mode advanced
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Watch / control a run:
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
autodevloop status --project-dir ./my-app
|
|
134
|
+
autodevloop stop --project-dir ./my-app # graceful stop after the current step
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Web dashboard
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
autodevloop web # http://127.0.0.1:8787
|
|
141
|
+
autodevloop web --port 9000
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
The UI is available in **English / 简体中文 / 日本語** (compact 🌐 switcher,
|
|
145
|
+
top-right). A built-in **Help** guide and hover tooltips (the `?` icons) explain
|
|
146
|
+
every setting, agent, and button, so first-time users aren't left guessing.
|
|
147
|
+
|
|
148
|
+
From the dashboard you can:
|
|
149
|
+
|
|
150
|
+
1. **Create a project** — directory, goal, version count, mode, provider,
|
|
151
|
+
architecture hint. Creating only *creates* it; you then review/edit settings
|
|
152
|
+
and press **Run** when ready (it does not auto-start).
|
|
153
|
+
2. **Watch live** — status, phase, current version, a **per-agent live timer**
|
|
154
|
+
for every agent running right now (multiple at once when agents run in
|
|
155
|
+
parallel), agent-call count, token usage, total run time, a scrollable
|
|
156
|
+
activity log with a **divider between versions**, and each agent's full
|
|
157
|
+
output (persistent viewer).
|
|
158
|
+
3. **Edit settings** — pipeline mode and step toggles, max versions, review and
|
|
159
|
+
value thresholds, retries, test command, provider command/model, and **every
|
|
160
|
+
prompt template**. Required agents (plan, develop, test, review, fix) are
|
|
161
|
+
shown but locked on; only optional steps can be toggled. Prompt edits are
|
|
162
|
+
**format-checked** — rewrite the wording in any language, but the
|
|
163
|
+
`{{placeholders}}` and JSON field names the engine depends on can't be
|
|
164
|
+
removed. Settings are **locked while a run is active** and take effect on the
|
|
165
|
+
next run.
|
|
166
|
+
4. **Stop two ways** — *graceful* (finish the current version, then stop) or
|
|
167
|
+
*discard* (kill immediately, throw away the unfinished version, and roll the
|
|
168
|
+
working copy back to the last completed version). Each shows a confirmation
|
|
169
|
+
explaining exactly what happened.
|
|
170
|
+
5. **Read the docs** — the `FEATURES.md` overview table and `CHANGELOG.md`.
|
|
171
|
+
|
|
172
|
+
> Cost in money is intentionally not shown (third-party API pricing behind a CLI
|
|
173
|
+
> is unreliable); the dashboard reports **agent-call count and tokens** instead.
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## How the loop works
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
┌─────────────────────────── once, at the start ──────────────────────────┐
|
|
181
|
+
│ AgentARCH → picks a mainstream stack, layout, run & test strategy │
|
|
182
|
+
└──────────────────────────────────────────────────────────────────────────┘
|
|
183
|
+
per version:
|
|
184
|
+
AgentPLAN ── decides this version's goal + how many dev agents and what they own
|
|
185
|
+
│
|
|
186
|
+
AgentDEV_* ─ one or more (parallel) agents implement in isolated workspaces,
|
|
187
|
+
│ then merge back into current/ (only changed files; first-writer-wins
|
|
188
|
+
│ on conflict, with a warning)
|
|
189
|
+
AgentDOC ── (advanced) keeps README / design docs accurate
|
|
190
|
+
│
|
|
191
|
+
AgentTEST ─ runs tests: built-in detection in simple mode, or an agent picks
|
|
192
|
+
│ the test commands in advanced mode
|
|
193
|
+
AgentREVIEW scores quality, flags blockers, judges goal completeness, and
|
|
194
|
+
│ writes the human-readable "what's new" summary
|
|
195
|
+
│
|
|
196
|
+
(fix loop) ─ if tests fail / blocking / below threshold, AgentFIX repairs and re-tests
|
|
197
|
+
│
|
|
198
|
+
AgentGOALCHECK (advanced) independently confirms whether the goal is met
|
|
199
|
+
│
|
|
200
|
+
── if goal met for the first time → switch to EXPAND phase, tag goal-complete ──
|
|
201
|
+
│
|
|
202
|
+
AgentSCOUT + AgentEVALUATE (expand phase) propose & value-gate new features
|
|
203
|
+
│ into a persistent backlog the planner draws from next time
|
|
204
|
+
▼
|
|
205
|
+
snapshot → versions/vN/, git commit + tag vN, update CHANGELOG.md & FEATURES.md
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
The loop never stops early for being "good enough" — it runs until your
|
|
209
|
+
`max_versions` (or you stop it). Reaching the goal switches *what* it works on,
|
|
210
|
+
not *whether* it keeps going.
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Output layout
|
|
215
|
+
|
|
216
|
+
Each project directory gets:
|
|
217
|
+
|
|
218
|
+
| Path | What |
|
|
219
|
+
|---|---|
|
|
220
|
+
| `current/` | The single working copy agents edit (git repo if enabled) |
|
|
221
|
+
| `versions/vN/` | A full snapshot of every completed version |
|
|
222
|
+
| `FEATURES.md` | At-a-glance table: each version's features + what changed |
|
|
223
|
+
| `CHANGELOG.md` | Per-version changelog with summaries and test status |
|
|
224
|
+
| `.autodev/state.json` | Full run state |
|
|
225
|
+
| `.autodev/progress.json` | Live progress + event feed (used by the web UI) |
|
|
226
|
+
| `.autodev/backlog.json` | Scouted features and their accept/reject verdicts |
|
|
227
|
+
| `.autodev/architecture.md` | The initial architecture report |
|
|
228
|
+
| `.autodev/prompts/templates/` | Editable prompt templates |
|
|
229
|
+
| `.autodev/plans/`, `reviews/`, `tests/`, `logs/` | Per-stage artifacts |
|
|
230
|
+
| `.autodev/final_report.md` | Summary written at the end of a run |
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## Configuration
|
|
235
|
+
|
|
236
|
+
Settings live in `.autodevloop.yml` in the project directory (the web settings
|
|
237
|
+
page and CLI flags write to it). Everything has a sane default; a full file
|
|
238
|
+
looks like:
|
|
239
|
+
|
|
240
|
+
```yaml
|
|
241
|
+
project:
|
|
242
|
+
name: My App
|
|
243
|
+
max_versions: 8
|
|
244
|
+
arch_hint: "React + FastAPI + SQLite" # optional hint for AgentARCH
|
|
245
|
+
|
|
246
|
+
provider:
|
|
247
|
+
name: claude # claude | codex | gemini
|
|
248
|
+
command: "" # blank = use the profile's default command (e.g. "claude")
|
|
249
|
+
model: "" # optional model alias/name
|
|
250
|
+
extra_args: [] # extra CLI args appended to every call
|
|
251
|
+
|
|
252
|
+
pipeline:
|
|
253
|
+
mode: advanced # simple | advanced
|
|
254
|
+
steps: # override individual steps on top of the mode defaults
|
|
255
|
+
goal_check: true
|
|
256
|
+
test_agent: true
|
|
257
|
+
doc: true
|
|
258
|
+
scout: true
|
|
259
|
+
evaluate: true
|
|
260
|
+
features_doc: true
|
|
261
|
+
|
|
262
|
+
agents:
|
|
263
|
+
timeout: 1800 # seconds per provider call
|
|
264
|
+
allow_parallel: true
|
|
265
|
+
max_parallel: 3
|
|
266
|
+
retries: 3 # retries on transient provider failures
|
|
267
|
+
backoff_seconds: 5
|
|
268
|
+
|
|
269
|
+
review:
|
|
270
|
+
threshold: 80 # review score below this triggers a fix pass
|
|
271
|
+
|
|
272
|
+
value:
|
|
273
|
+
threshold: 65 # feature value below this is rejected by the gate
|
|
274
|
+
|
|
275
|
+
fix:
|
|
276
|
+
retries: 2
|
|
277
|
+
|
|
278
|
+
tests:
|
|
279
|
+
timeout: 120
|
|
280
|
+
command: "" # blank = auto-detected / agent-chosen
|
|
281
|
+
|
|
282
|
+
vcs:
|
|
283
|
+
git: true # commit + tag each version inside current/
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
Useful CLI flags: `--mode`, `--provider`, `--provider-command`, `--model`,
|
|
287
|
+
`--max-versions`, `--review-threshold`, `--fix-retries`, `--max-parallel-agents`,
|
|
288
|
+
`--no-parallel`, `--no-git`, `--test-command`, `--reset`, `--non-interactive`.
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## ⚠️ Security notice — please read
|
|
293
|
+
|
|
294
|
+
AutoDevLoop is an **autonomous code generator that runs code on your machine**.
|
|
295
|
+
Treat it like any tool that executes untrusted code:
|
|
296
|
+
|
|
297
|
+
- **It writes and executes code.** Agents run with file edit permissions, and
|
|
298
|
+
`AgentTEST` runs shell test/build commands in your project directory. Generated
|
|
299
|
+
code is not reviewed by a human before it runs.
|
|
300
|
+
- **It runs unattended and can spend money.** The loop keeps calling your
|
|
301
|
+
provider CLI until it reaches the version count or you stop it. Watch the live
|
|
302
|
+
cost readout, set a sensible `--max-versions`, and keep an eye on your provider
|
|
303
|
+
billing.
|
|
304
|
+
- **Run it in an isolated environment.** Prefer a dedicated directory, a
|
|
305
|
+
container, or a VM. Don't point it at a directory containing secrets or
|
|
306
|
+
important unrelated files.
|
|
307
|
+
- **The web dashboard is unauthenticated and binds to localhost.** It can start
|
|
308
|
+
runs and execute commands. Do **not** expose the port to a network you don't
|
|
309
|
+
fully trust. There is no auth layer.
|
|
310
|
+
- **No API keys are handled by this tool** — your provider CLI manages its own
|
|
311
|
+
credentials. AutoDevLoop only invokes the command you configured.
|
|
312
|
+
|
|
313
|
+
By running AutoDevLoop you accept that you are responsible for the code it
|
|
314
|
+
generates and the commands it executes.
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## Troubleshooting
|
|
319
|
+
|
|
320
|
+
- **"Provider command not found"** — install the CLI and ensure it's on `PATH`,
|
|
321
|
+
or set `provider.command` to the full path / wrapper command.
|
|
322
|
+
- **Git commits don't appear** — git is optional; the tool falls back to folder
|
|
323
|
+
snapshots. Corporate git hooks that block commits are tolerated silently.
|
|
324
|
+
- **Garbled characters on a legacy Windows console** — output is forced to UTF-8;
|
|
325
|
+
if your terminal still struggles, run inside Windows Terminal or set
|
|
326
|
+
`PYTHONIOENCODING=utf-8`.
|
|
327
|
+
|
|
328
|
+
---
|
|
329
|
+
|
|
330
|
+
## License
|
|
331
|
+
|
|
332
|
+
[MIT](LICENSE). Contributions welcome — see [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
autodevloop/__init__.py,sha256=5T-x8e7rOc5uU7sW2ytrOX61OJUh8Vbtqmc1OZPbKZs,115
|
|
2
|
+
autodevloop/__main__.py,sha256=eJ36HhdA5ZiGIYjBGALhdwf3IpUq_e5euMVySIPpx_E,121
|
|
3
|
+
autodevloop/cli.py,sha256=hygyOjYzio3sk7gQY0Js22OsN4eInD6rPpiYyvyzCyQ,10139
|
|
4
|
+
autodevloop/config.py,sha256=GJ5gjwo6o89fvFlb8ZiJnS8-89oe_Go-v7A0SQ54ka0,5185
|
|
5
|
+
autodevloop/engine.py,sha256=N4rpatWZWfIBnD2P28yPeytuX0zUopGvYlukuP9Vasc,37341
|
|
6
|
+
autodevloop/llm.py,sha256=l9WCGyQPWjkq2RNAr9AQKqQQMBG3R1W5_OCJULrnDOo,8517
|
|
7
|
+
autodevloop/prompts.py,sha256=LNbE8NgxZJOctCEcATJXaYKpijYle0VjR9kB0DUsR9w,10000
|
|
8
|
+
autodevloop/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
9
|
+
autodevloop/registry.py,sha256=T5MzQ04lQSt0V4TYhX93BKCUuh28w7xxM3tIv8IO8ys,1201
|
|
10
|
+
autodevloop/reporting.py,sha256=4ZbCgUXnUlrTsvdzYoVmi02AoDkJK6pfs91lHefkye0,5017
|
|
11
|
+
autodevloop/testing.py,sha256=ZZUj_NYw8cCk4S-SWXFRxg_0rCli6AYo8SC710o5XZ4,5500
|
|
12
|
+
autodevloop/util.py,sha256=6lI9hiuDaf_rHeZRnFklrz6lBUVljl4D38SoN6r5cQY,8012
|
|
13
|
+
autodevloop/vcs.py,sha256=mkrn11YmzKFCg9EONlzRvoNgObhKu-uby2jhig2gj_g,2485
|
|
14
|
+
autodevloop/webapp.py,sha256=fN4MJFJ2pE8twzcP9P2evjM-808HST4OvttNQNaRAqA,92587
|
|
15
|
+
autodevloop/yaml_compat.py,sha256=kX-77m-K0RmKo688mgiXZDUxjfmFBCsWk7HYjdk9v4c,6302
|
|
16
|
+
autodevloop-0.1.0.dist-info/licenses/LICENSE,sha256=ivBAOyMZRLtx2uw1KAGvtgx8AoEqoKrs6rWgOB3xmps,1081
|
|
17
|
+
autodevloop-0.1.0.dist-info/METADATA,sha256=8JTbyVaF_IuKlc4wppfHEip1cAeRUfyCKuZKUBqEsfw,13581
|
|
18
|
+
autodevloop-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
19
|
+
autodevloop-0.1.0.dist-info/entry_points.txt,sha256=AwuiIiMtxqCOn41aF4LloQxR8C3nLe-9IR3WDYPj89A,53
|
|
20
|
+
autodevloop-0.1.0.dist-info/top_level.txt,sha256=Q8qZDcGgIPgzACLL07LRs6grZqYfsusYpGfqHOvULtw,12
|
|
21
|
+
autodevloop-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 AutoDevLoop contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
autodevloop
|