agentic-dev-loop 1.0.0a7__tar.gz → 1.0.0a8__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 (72) hide show
  1. agentic_dev_loop-1.0.0a7/README.md → agentic_dev_loop-1.0.0a8/PKG-INFO +40 -48
  2. agentic_dev_loop-1.0.0a7/src/agentic_dev_loop.egg-info/PKG-INFO → agentic_dev_loop-1.0.0a8/README.md +1 -90
  3. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/pyproject.toml +9 -22
  4. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/src/agentic_dev_loop/core/__init__.py +1 -8
  5. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/src/agentic_dev_loop/core/verdict.py +1 -1
  6. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/src/agentic_dev_loop/engine/__init__.py +1 -1
  7. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/src/agentic_dev_loop/engine/outputs.py +3 -3
  8. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/src/agentic_dev_loop/viz/__init__.py +2 -3
  9. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/src/agentic_dev_loop/viz/__main__.py +2 -5
  10. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/src/agentic_dev_loop/viz/server.py +3 -36
  11. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8/src/agentic_dev_loop.egg-info}/PKG-INFO +7 -57
  12. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/src/agentic_dev_loop.egg-info/SOURCES.txt +1 -11
  13. agentic_dev_loop-1.0.0a8/src/agentic_dev_loop.egg-info/entry_points.txt +2 -0
  14. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/src/agentic_dev_loop.egg-info/requires.txt +3 -8
  15. agentic_dev_loop-1.0.0a8/tests/test_module_contract.py +94 -0
  16. agentic_dev_loop-1.0.0a7/src/agentic_dev_loop/core/project.py +0 -64
  17. agentic_dev_loop-1.0.0a7/src/agentic_dev_loop/core/projection.py +0 -206
  18. agentic_dev_loop-1.0.0a7/src/agentic_dev_loop/core/workflow.js.template +0 -236
  19. agentic_dev_loop-1.0.0a7/src/agentic_dev_loop/engine/commit_shim.py +0 -56
  20. agentic_dev_loop-1.0.0a7/src/agentic_dev_loop/viz/ingest.py +0 -25
  21. agentic_dev_loop-1.0.0a7/src/agentic_dev_loop/workflow/__init__.py +0 -80
  22. agentic_dev_loop-1.0.0a7/src/agentic_dev_loop/workflow/cli.py +0 -40
  23. agentic_dev_loop-1.0.0a7/src/agentic_dev_loop.egg-info/entry_points.txt +0 -4
  24. agentic_dev_loop-1.0.0a7/tests/test_unit4_golden.py +0 -60
  25. agentic_dev_loop-1.0.0a7/tests/test_unit4_pbt.py +0 -283
  26. agentic_dev_loop-1.0.0a7/tests/test_unit4_viz_ingest.py +0 -92
  27. agentic_dev_loop-1.0.0a7/tests/test_unit4_workflow.py +0 -136
  28. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/LICENSE +0 -0
  29. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/setup.cfg +0 -0
  30. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/src/agentic_dev_loop/__init__.py +0 -0
  31. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/src/agentic_dev_loop/core/config.py +0 -0
  32. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/src/agentic_dev_loop/core/results.py +0 -0
  33. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/src/agentic_dev_loop/engine/actions.py +0 -0
  34. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/src/agentic_dev_loop/engine/agents.py +0 -0
  35. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/src/agentic_dev_loop/engine/cli.py +0 -0
  36. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/src/agentic_dev_loop/engine/dryrun.py +0 -0
  37. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/src/agentic_dev_loop/engine/extensions/__init__.py +0 -0
  38. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/src/agentic_dev_loop/engine/extensions/aidlc.py +0 -0
  39. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/src/agentic_dev_loop/engine/graph.py +0 -0
  40. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/src/agentic_dev_loop/engine/isolation.py +0 -0
  41. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/src/agentic_dev_loop/engine/llm.py +0 -0
  42. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/src/agentic_dev_loop/engine/loaders.py +0 -0
  43. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/src/agentic_dev_loop/engine/proc.py +0 -0
  44. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/src/agentic_dev_loop/engine/registry.py +0 -0
  45. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/src/agentic_dev_loop/engine/stages.py +0 -0
  46. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/src/agentic_dev_loop/py.typed +0 -0
  47. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/src/agentic_dev_loop.egg-info/dependency_links.txt +0 -0
  48. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/src/agentic_dev_loop.egg-info/top_level.txt +0 -0
  49. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/tests/test_actions.py +0 -0
  50. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/tests/test_agents.py +0 -0
  51. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/tests/test_aidlc.py +0 -0
  52. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/tests/test_cli.py +0 -0
  53. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/tests/test_config.py +0 -0
  54. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/tests/test_dry_run.py +0 -0
  55. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/tests/test_e2e_fixtures.py +0 -0
  56. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/tests/test_graph.py +0 -0
  57. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/tests/test_isolation.py +0 -0
  58. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/tests/test_isolation_integration.py +0 -0
  59. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/tests/test_isolation_pbt.py +0 -0
  60. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/tests/test_llm.py +0 -0
  61. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/tests/test_loaders.py +0 -0
  62. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/tests/test_outputs.py +0 -0
  63. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/tests/test_outputs_pbt.py +0 -0
  64. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/tests/test_proc.py +0 -0
  65. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/tests/test_publish.py +0 -0
  66. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/tests/test_registry.py +0 -0
  67. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/tests/test_results.py +0 -0
  68. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/tests/test_sdk_compat.py +0 -0
  69. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/tests/test_source_resolution.py +0 -0
  70. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/tests/test_stages.py +0 -0
  71. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/tests/test_verdict.py +0 -0
  72. {agentic_dev_loop-1.0.0a7 → agentic_dev_loop-1.0.0a8}/tests/test_viz.py +0 -0
@@ -1,3 +1,42 @@
1
+ Metadata-Version: 2.4
2
+ Name: agentic-dev-loop
3
+ Version: 1.0.0a8
4
+ Summary: Turn an LLM into a gated, sandboxed, resumable construction loop over your codebase.
5
+ Author: Luke Wilson
6
+ License-Expression: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/lukedawilson/agentic-dev-loop
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Environment :: Console
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Operating System :: MacOS
12
+ Classifier: Operating System :: Microsoft :: Windows
13
+ Classifier: Operating System :: POSIX :: Linux
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3 :: Only
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
20
+ Classifier: Topic :: Software Development
21
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
+ Classifier: Topic :: Software Development :: Quality Assurance
23
+ Classifier: Topic :: Security
24
+ Classifier: Typing :: Typed
25
+ Requires-Python: >=3.12
26
+ Description-Content-Type: text/markdown
27
+ License-File: LICENSE
28
+ Requires-Dist: pydantic>=2.0
29
+ Requires-Dist: PyYAML>=6.0
30
+ Requires-Dist: openhands-sdk~=1.17.0
31
+ Requires-Dist: openhands-tools~=1.17.0
32
+ Requires-Dist: agent-client-protocol<1.0.0
33
+ Requires-Dist: langgraph>=1.2
34
+ Requires-Dist: langgraph-checkpoint-sqlite>=3.0
35
+ Provides-Extra: dev
36
+ Requires-Dist: hypothesis>=6.0; extra == "dev"
37
+ Requires-Dist: pytest>=8.0; extra == "dev"
38
+ Dynamic: license-file
39
+
1
40
  # agentic-dev-loop
2
41
 
3
42
  > **Turn an LLM into a gated, sandboxed, resumable construction loop over your codebase.**
@@ -23,11 +62,6 @@ flowchart LR
23
62
  - **Sandboxed by default.** The agent's shell and every command step run inside
24
63
  an always-on Docker sandbox. There is no opt-out.
25
64
 
26
- Two modes share one `pipeline.yaml`: **engine mode** (the sandboxed, resumable
27
- loop above) and **workflow mode** — a Claude Dynamic Workflow exported from the
28
- same pipeline that runs in Claude Code's own environment, with the live graph
29
- visualiser. See [Workflow mode](#workflow-mode-claude-code).
30
-
31
65
  ---
32
66
 
33
67
  ## Core features
@@ -56,13 +90,8 @@ LLM timeout (agent runs are long).
56
90
  | LLM API key | The env var named by your pipeline's `api_key_env` (e.g. `OPENAI_API_KEY`) must be set — a missing key fails fast, naming it. |
57
91
 
58
92
  ```bash
59
- # engine mode (sandboxed loop — the full install)
60
- pip install "agentic-dev-loop[engine]==1.0.0a6"
93
+ pip install "agentic-dev-loop==1.0.0a8"
61
94
  agentic-dev-loop --version
62
-
63
- # workflow mode (Claude Code — core + viz only, no SDK/Docker deps)
64
- pip install "agentic-dev-loop==1.0.0a6"
65
- agentic-dev-loop-workflow install-skill
66
95
  ```
67
96
 
68
97
  On the first run the engine pulls the **digest-pinned** dev image
@@ -73,43 +102,6 @@ image. Engine setup, first-run details, the full `pipeline.yaml` contract, and
73
102
  troubleshooting for every fail-fast code live in
74
103
  [docs/setup.md](docs/setup.md).
75
104
 
76
- ## Workflow mode (Claude Code)
77
-
78
- For developers who know and love the agentic dev loop but are forced to use
79
- Claude Code at work: workflow mode exports a **Claude Dynamic Workflow** from
80
- the `pipeline.yaml` they already trust, plus the visualiser they trust. It adds
81
- the deterministic loop through Claude's mechanism — nothing more. **No Docker
82
- sandboxing, and no new security claims**: workflow steps run in Claude Code's
83
- own environment under its permission model (a documented trust-model change
84
- from engine mode).
85
-
86
- Install the skill once:
87
-
88
- ```bash
89
- pip install "agentic-dev-loop==1.0.0a6" # base install: core + viz, no SDK/Docker
90
- agentic-dev-loop-workflow install-skill # → ~/.claude/skills/agentic-dev-loop/
91
- ```
92
-
93
- Then invoke `/agentic-dev-loop` in Claude Code. The skill walks through:
94
-
95
- 1. **Build** — `python -m agentic_dev_loop.core.project <pipeline.yaml>` loads +
96
- validates the pipeline, verifies every agent step's `.agent.md` prompt exists
97
- (a missing prompt fails the build loudly, naming the file), and writes a
98
- self-contained `.agentic-dev-loop/workflow.js`. Steps are frozen at creation
99
- — mid-run `pipeline.yaml` edits never affect a running workflow.
100
- 2. **Run** — the generated JS routes `on_pass` / `on_fail` / `goto` with its own
101
- attempt counter, injects the failing subagent's output as the next retry note,
102
- launches the live-graph server (localhost, token-authenticated ingest), and
103
- invokes the docker-free commit shim, which refuses loudly unless the worktree
104
- was clean at run start.
105
-
106
- Engine-only fields (`isolation:`, per-step `network:`, `setup:`) are ignored in
107
- workflow mode with no effect on the build or run.
108
-
109
- The base install is deliberately dependency-light (`pydantic` + `PyYAML` only);
110
- the heavy OpenHands-SDK engine lives in the `[engine]` extra. The `core` and
111
- `viz` packages are guarded against pulling engine deps.
112
-
113
105
  ## Usage
114
106
 
115
107
  ```bash
@@ -1,45 +1,3 @@
1
- Metadata-Version: 2.4
2
- Name: agentic-dev-loop
3
- Version: 1.0.0a7
4
- Summary: Turn an LLM into a gated, sandboxed, resumable construction loop over your codebase.
5
- Author: Luke Wilson
6
- License-Expression: Apache-2.0
7
- Project-URL: Homepage, https://github.com/lukedawilson/agentic-dev-loop
8
- Classifier: Development Status :: 4 - Beta
9
- Classifier: Environment :: Console
10
- Classifier: Intended Audience :: Developers
11
- Classifier: Operating System :: MacOS
12
- Classifier: Operating System :: Microsoft :: Windows
13
- Classifier: Operating System :: POSIX :: Linux
14
- Classifier: Programming Language :: Python :: 3
15
- Classifier: Programming Language :: Python :: 3 :: Only
16
- Classifier: Programming Language :: Python :: 3.12
17
- Classifier: Programming Language :: Python :: 3.13
18
- Classifier: Programming Language :: Python :: 3.14
19
- Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
20
- Classifier: Topic :: Software Development
21
- Classifier: Topic :: Software Development :: Libraries :: Python Modules
22
- Classifier: Topic :: Software Development :: Quality Assurance
23
- Classifier: Topic :: Security
24
- Classifier: Typing :: Typed
25
- Requires-Python: >=3.12
26
- Description-Content-Type: text/markdown
27
- License-File: LICENSE
28
- Requires-Dist: pydantic>=2.0
29
- Requires-Dist: PyYAML>=6.0
30
- Provides-Extra: engine
31
- Requires-Dist: openhands-sdk~=1.17.0; extra == "engine"
32
- Requires-Dist: openhands-tools~=1.17.0; extra == "engine"
33
- Requires-Dist: agent-client-protocol<1.0.0; extra == "engine"
34
- Requires-Dist: langgraph>=1.2; extra == "engine"
35
- Requires-Dist: langgraph-checkpoint-sqlite>=3.0; extra == "engine"
36
- Provides-Extra: workflow
37
- Provides-Extra: dev
38
- Requires-Dist: agentic-dev-loop[engine]; extra == "dev"
39
- Requires-Dist: hypothesis>=6.0; extra == "dev"
40
- Requires-Dist: pytest>=8.0; extra == "dev"
41
- Dynamic: license-file
42
-
43
1
  # agentic-dev-loop
44
2
 
45
3
  > **Turn an LLM into a gated, sandboxed, resumable construction loop over your codebase.**
@@ -65,11 +23,6 @@ flowchart LR
65
23
  - **Sandboxed by default.** The agent's shell and every command step run inside
66
24
  an always-on Docker sandbox. There is no opt-out.
67
25
 
68
- Two modes share one `pipeline.yaml`: **engine mode** (the sandboxed, resumable
69
- loop above) and **workflow mode** — a Claude Dynamic Workflow exported from the
70
- same pipeline that runs in Claude Code's own environment, with the live graph
71
- visualiser. See [Workflow mode](#workflow-mode-claude-code).
72
-
73
26
  ---
74
27
 
75
28
  ## Core features
@@ -98,13 +51,8 @@ LLM timeout (agent runs are long).
98
51
  | LLM API key | The env var named by your pipeline's `api_key_env` (e.g. `OPENAI_API_KEY`) must be set — a missing key fails fast, naming it. |
99
52
 
100
53
  ```bash
101
- # engine mode (sandboxed loop — the full install)
102
- pip install "agentic-dev-loop[engine]==1.0.0a6"
54
+ pip install "agentic-dev-loop==1.0.0a8"
103
55
  agentic-dev-loop --version
104
-
105
- # workflow mode (Claude Code — core + viz only, no SDK/Docker deps)
106
- pip install "agentic-dev-loop==1.0.0a6"
107
- agentic-dev-loop-workflow install-skill
108
56
  ```
109
57
 
110
58
  On the first run the engine pulls the **digest-pinned** dev image
@@ -115,43 +63,6 @@ image. Engine setup, first-run details, the full `pipeline.yaml` contract, and
115
63
  troubleshooting for every fail-fast code live in
116
64
  [docs/setup.md](docs/setup.md).
117
65
 
118
- ## Workflow mode (Claude Code)
119
-
120
- For developers who know and love the agentic dev loop but are forced to use
121
- Claude Code at work: workflow mode exports a **Claude Dynamic Workflow** from
122
- the `pipeline.yaml` they already trust, plus the visualiser they trust. It adds
123
- the deterministic loop through Claude's mechanism — nothing more. **No Docker
124
- sandboxing, and no new security claims**: workflow steps run in Claude Code's
125
- own environment under its permission model (a documented trust-model change
126
- from engine mode).
127
-
128
- Install the skill once:
129
-
130
- ```bash
131
- pip install "agentic-dev-loop==1.0.0a6" # base install: core + viz, no SDK/Docker
132
- agentic-dev-loop-workflow install-skill # → ~/.claude/skills/agentic-dev-loop/
133
- ```
134
-
135
- Then invoke `/agentic-dev-loop` in Claude Code. The skill walks through:
136
-
137
- 1. **Build** — `python -m agentic_dev_loop.core.project <pipeline.yaml>` loads +
138
- validates the pipeline, verifies every agent step's `.agent.md` prompt exists
139
- (a missing prompt fails the build loudly, naming the file), and writes a
140
- self-contained `.agentic-dev-loop/workflow.js`. Steps are frozen at creation
141
- — mid-run `pipeline.yaml` edits never affect a running workflow.
142
- 2. **Run** — the generated JS routes `on_pass` / `on_fail` / `goto` with its own
143
- attempt counter, injects the failing subagent's output as the next retry note,
144
- launches the live-graph server (localhost, token-authenticated ingest), and
145
- invokes the docker-free commit shim, which refuses loudly unless the worktree
146
- was clean at run start.
147
-
148
- Engine-only fields (`isolation:`, per-step `network:`, `setup:`) are ignored in
149
- workflow mode with no effect on the build or run.
150
-
151
- The base install is deliberately dependency-light (`pydantic` + `PyYAML` only);
152
- the heavy OpenHands-SDK engine lives in the `[engine]` extra. The `core` and
153
- `viz` packages are guarded against pulling engine deps.
154
-
155
66
  ## Usage
156
67
 
157
68
  ```bash
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "agentic-dev-loop"
7
- version = "1.0.0a7"
7
+ version = "1.0.0a8"
8
8
  description = "Turn an LLM into a gated, sandboxed, resumable construction loop over your codebase."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -32,23 +32,8 @@ classifiers = [
32
32
  "Typing :: Typed",
33
33
  ]
34
34
  dependencies = [
35
- # Base install = workflow mode (core + viz + workflow CLI). Deliberately
36
- # dependency-light (TS-1 / NFR-4.1 / BR-2): pydantic + PyYAML only. The
37
- # heavy OpenHands-SDK engine deps live in the [engine] extra below.
38
35
  "pydantic>=2.0",
39
36
  "PyYAML>=6.0",
40
- ]
41
-
42
- [project.urls]
43
- Homepage = "https://github.com/lukedawilson/agentic-dev-loop"
44
-
45
- [project.scripts]
46
- agentic-dev-loop = "agentic_dev_loop.engine.cli:main"
47
- agentic-dev-loop-workflow = "agentic_dev_loop.workflow.cli:main"
48
- agentic-dev-loop-commit = "agentic_dev_loop.engine.commit_shim:main"
49
-
50
- [project.optional-dependencies]
51
- engine = [
52
37
  "openhands-sdk ~=1.17.0",
53
38
  "openhands-tools ~=1.17.0",
54
39
  # openhands-sdk declares agent-client-protocol>=0.8.1 with NO upper bound;
@@ -59,12 +44,15 @@ engine = [
59
44
  "langgraph>=1.2",
60
45
  "langgraph-checkpoint-sqlite>=3.0",
61
46
  ]
62
- # Workflow mode is the BASE install — this empty extra exists only so
63
- # `pip install agentic-dev-loop[workflow]` reads naturally and pulls nothing
64
- # beyond the light base (core + viz). See README / NFR-4.1.
65
- workflow = []
47
+
48
+ [project.urls]
49
+ Homepage = "https://github.com/lukedawilson/agentic-dev-loop"
50
+
51
+ [project.scripts]
52
+ agentic-dev-loop = "agentic_dev_loop.engine.cli:main"
53
+
54
+ [project.optional-dependencies]
66
55
  dev = [
67
- "agentic-dev-loop[engine]",
68
56
  "hypothesis>=6.0",
69
57
  "pytest>=8.0",
70
58
  ]
@@ -74,7 +62,6 @@ where = ["src"]
74
62
 
75
63
  [tool.setuptools.package-data]
76
64
  agentic_dev_loop = ["py.typed"]
77
- "agentic_dev_loop.core" = ["workflow.js.template"]
78
65
 
79
66
  [tool.pytest.ini_options]
80
67
  markers = [
@@ -1,4 +1,4 @@
1
- """Pipeline model + parse + workflow projection (unit-4 core).
1
+ """Pipeline model + parse + results (core).
2
2
 
3
3
  Dependency-light by contract (BR-2): pydantic + PyYAML + stdlib only. A guard
4
4
  test fails if this package imports engine/viz or heavy deps.
@@ -9,17 +9,10 @@ from .config import (PipelineConfig, StepConfig, LlmConfig, IsolationConfig,
9
9
  default_state_dir, TERMINALS)
10
10
  from .results import Result
11
11
  from .verdict import Verdict, VerdictError, parse_verdict, RETRY
12
- from .projection import (ProjectedStep, WorkflowProjection, project_workflow,
13
- validate_prompt_refs, render_workflow_js,
14
- clean_at_start_flag, pipeline_hash, core_version,
15
- WORKFLOW_TEMPLATE)
16
12
 
17
13
  __all__ = [
18
14
  "PipelineConfig", "StepConfig", "LlmConfig", "IsolationConfig",
19
15
  "VerdictSpec", "Route", "route_target", "load_config",
20
16
  "default_state_dir", "TERMINALS",
21
17
  "Result", "Verdict", "VerdictError", "parse_verdict", "RETRY",
22
- "ProjectedStep", "WorkflowProjection", "project_workflow",
23
- "validate_prompt_refs", "render_workflow_js", "clean_at_start_flag",
24
- "pipeline_hash", "core_version", "WORKFLOW_TEMPLATE",
25
18
  ]
@@ -2,7 +2,7 @@
2
2
 
3
3
  `Verdict.from_text` parses the captured response for routing; expected
4
4
  conditions are typed `Result` errors, never exceptions. `parse_verdict`
5
- collapses that `Result` to a route string for workflow consumers: a clear
5
+ collapses that `Result` to a route string for routing consumers: a clear
6
6
  decision maps to its canonical value, anything unclear maps to ``retry`` —
7
7
  totality for arbitrary input (no crash, no silent routing).
8
8
  """
@@ -1,2 +1,2 @@
1
1
  """Engine package — graph/stages/sandbox/CLI and the heavy OpenHands-SDK
2
- dependencies (unit-4 re-homing, FR-4.1)."""
2
+ dependencies."""
@@ -2,9 +2,9 @@
2
2
  channel (unit-1).
3
3
 
4
4
  The pipeline — not the agent — writes the step's artifact from the agent's
5
- final SDK response. Verdict parsing lives in `core.verdict` (shared with
6
- workflow mode); this module only owns the SDK-side capture. Expected
7
- conditions are typed `Result` errors, never exceptions.
5
+ final SDK response. Verdict parsing lives in `core.verdict`; this module only
6
+ owns the SDK-side capture. Expected conditions are typed `Result` errors,
7
+ never exceptions.
8
8
  """
9
9
 
10
10
  from __future__ import annotations
@@ -1,14 +1,13 @@
1
- """The live-graph visualiser + workflow-mode ingest surface (unit-4 viz)."""
1
+ """The live-graph visualiser."""
2
2
 
3
3
  import time # noqa: F401 — re-exported so tests can pin NodeWatch's clock
4
4
 
5
5
  from .server import (MAX_LINE, PAGE, ConsoleCapture, HeartbeatThread,
6
6
  NodeWatch, VizBus, _ReuseSafeServer, _Tee,
7
7
  _handler_class, serve_viz, topology_mermaid, translate)
8
- from .ingest import issue_ingest_token, make_ingest_event
9
8
 
10
9
  __all__ = [
11
10
  "MAX_LINE", "PAGE", "ConsoleCapture", "HeartbeatThread", "NodeWatch",
12
11
  "VizBus", "_ReuseSafeServer", "_Tee", "_handler_class", "serve_viz",
13
- "topology_mermaid", "translate", "issue_ingest_token", "make_ingest_event",
12
+ "topology_mermaid", "translate",
14
13
  ]
@@ -1,7 +1,5 @@
1
- """Standalone workflow-mode viz launcher (FD-4): `python -m
2
- agentic_dev_loop.viz --pipeline <pipeline.yaml>` serves the live graph on
3
- localhost, issues an ingest token, and prints both. Step subagents POST stage
4
- events to `/ingest` with that token (BR-9)."""
1
+ """Standalone viz launcher: `python -m agentic_dev_loop.viz --pipeline
2
+ <pipeline.yaml>` serves the live graph on localhost."""
5
3
 
6
4
  from __future__ import annotations
7
5
 
@@ -31,7 +29,6 @@ def main(argv: list[str] | None = None) -> int:
31
29
  bound = httpd.server_address[1]
32
30
  url = f"http://127.0.0.1:{bound}"
33
31
  print(f"Live graph viz: {url}", flush=True)
34
- print(f"ingest-token: {httpd.ingest_token}", flush=True)
35
32
  if args.port and bound != args.port:
36
33
  print(f"viz port {args.port} busy — serving on {url}", flush=True)
37
34
  try:
@@ -27,8 +27,6 @@ from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
27
27
 
28
28
  from agentic_dev_loop.core.config import PipelineConfig, Route, route_target
29
29
 
30
- from .ingest import issue_ingest_token
31
-
32
30
  STATE_WHITELIST = ("attempt", "step_verdicts", "outcome", "failed")
33
31
 
34
32
 
@@ -341,15 +339,13 @@ class HeartbeatThread(threading.Thread):
341
339
 
342
340
 
343
341
  def _handler_class(bus: VizBus, topology_mermaid: str,
344
- subject: str, nodes: Iterable[str],
345
- ingest_token: str | None = None) -> type[BaseHTTPRequestHandler]:
342
+ subject: str, nodes: Iterable[str]) -> type[BaseHTTPRequestHandler]:
346
343
  class Handler(BaseHTTPRequestHandler):
347
344
  protocol_version = "HTTP/1.1"
348
345
  viz_bus = bus
349
346
  viz_topology = topology_mermaid
350
347
  viz_subject = subject
351
348
  viz_nodes = list(nodes)
352
- viz_ingest_token = ingest_token
353
349
 
354
350
  def log_message(self, *_args) -> None: # keep test output quiet
355
351
  pass
@@ -373,30 +369,6 @@ def _handler_class(bus: VizBus, topology_mermaid: str,
373
369
  else:
374
370
  self.send_error(404)
375
371
 
376
- def do_POST(self) -> None:
377
- if self.path != "/ingest":
378
- self.send_error(404)
379
- return
380
- supplied = self.headers.get("X-Ingest-Token", "")
381
- if not self.viz_ingest_token or supplied != self.viz_ingest_token:
382
- self._send(403, "application/json",
383
- json.dumps({"error": "forbidden"}))
384
- return
385
- length = int(self.headers.get("Content-Length", "0") or "0")
386
- body = self.rfile.read(length).decode("utf-8")
387
- try:
388
- event = json.loads(body)
389
- except json.JSONDecodeError:
390
- self._send(400, "application/json",
391
- json.dumps({"error": "invalid json"}))
392
- return
393
- if not isinstance(event, dict):
394
- self._send(400, "application/json",
395
- json.dumps({"error": "event must be an object"}))
396
- return
397
- self.viz_bus.publish(event)
398
- self._send(200, "application/json", json.dumps({"ok": True}))
399
-
400
372
  def _send(self, status: int, content_type: str, body: str) -> None:
401
373
  data = body.encode("utf-8")
402
374
  self.send_response(status)
@@ -439,8 +411,7 @@ class _ReuseSafeServer(ThreadingHTTPServer):
439
411
 
440
412
 
441
413
  def serve_viz(bus: VizBus, topology_mermaid: str, subject: str,
442
- port: int, nodes: Iterable[str] = (),
443
- ingest_token: str | None = None) -> tuple[_ReuseSafeServer, threading.Thread]:
414
+ port: int, nodes: Iterable[str] = ()) -> tuple[_ReuseSafeServer, threading.Thread]:
444
415
  """Bind a loopback HTTP server on ``port`` and serve it on a daemon
445
416
  thread. Returns ``(httpd, thread)`` — the caller reads the real bound
446
417
  port from ``httpd.server_address[1]``.
@@ -449,10 +420,7 @@ def serve_viz(bus: VizBus, topology_mermaid: str, subject: str,
449
420
  (``errno.EADDRINUSE``) the server rebinds port 0 and lets the OS pick a
450
421
  free port. Any other bind error (e.g. ``EACCES`` on a privileged port)
451
422
  still fails loud, naming ``--viz-port``."""
452
- if ingest_token is None:
453
- ingest_token = issue_ingest_token()
454
- handler = _handler_class(bus, topology_mermaid, subject, nodes,
455
- ingest_token)
423
+ handler = _handler_class(bus, topology_mermaid, subject, nodes)
456
424
  try:
457
425
  httpd = _ReuseSafeServer(("127.0.0.1", port), handler)
458
426
  except OSError as exc:
@@ -462,7 +430,6 @@ def serve_viz(bus: VizBus, topology_mermaid: str, subject: str,
462
430
  raise OSError(
463
431
  f"Could not bind the viz server to 127.0.0.1:{port} — the "
464
432
  f"--viz-port may already be in use. ({exc})") from exc
465
- httpd.ingest_token = ingest_token
466
433
  thread = threading.Thread(target=httpd.serve_forever, daemon=True)
467
434
  thread.start()
468
435
  return httpd, thread
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentic-dev-loop
3
- Version: 1.0.0a7
3
+ Version: 1.0.0a8
4
4
  Summary: Turn an LLM into a gated, sandboxed, resumable construction loop over your codebase.
5
5
  Author: Luke Wilson
6
6
  License-Expression: Apache-2.0
@@ -27,15 +27,12 @@ Description-Content-Type: text/markdown
27
27
  License-File: LICENSE
28
28
  Requires-Dist: pydantic>=2.0
29
29
  Requires-Dist: PyYAML>=6.0
30
- Provides-Extra: engine
31
- Requires-Dist: openhands-sdk~=1.17.0; extra == "engine"
32
- Requires-Dist: openhands-tools~=1.17.0; extra == "engine"
33
- Requires-Dist: agent-client-protocol<1.0.0; extra == "engine"
34
- Requires-Dist: langgraph>=1.2; extra == "engine"
35
- Requires-Dist: langgraph-checkpoint-sqlite>=3.0; extra == "engine"
36
- Provides-Extra: workflow
30
+ Requires-Dist: openhands-sdk~=1.17.0
31
+ Requires-Dist: openhands-tools~=1.17.0
32
+ Requires-Dist: agent-client-protocol<1.0.0
33
+ Requires-Dist: langgraph>=1.2
34
+ Requires-Dist: langgraph-checkpoint-sqlite>=3.0
37
35
  Provides-Extra: dev
38
- Requires-Dist: agentic-dev-loop[engine]; extra == "dev"
39
36
  Requires-Dist: hypothesis>=6.0; extra == "dev"
40
37
  Requires-Dist: pytest>=8.0; extra == "dev"
41
38
  Dynamic: license-file
@@ -65,11 +62,6 @@ flowchart LR
65
62
  - **Sandboxed by default.** The agent's shell and every command step run inside
66
63
  an always-on Docker sandbox. There is no opt-out.
67
64
 
68
- Two modes share one `pipeline.yaml`: **engine mode** (the sandboxed, resumable
69
- loop above) and **workflow mode** — a Claude Dynamic Workflow exported from the
70
- same pipeline that runs in Claude Code's own environment, with the live graph
71
- visualiser. See [Workflow mode](#workflow-mode-claude-code).
72
-
73
65
  ---
74
66
 
75
67
  ## Core features
@@ -98,13 +90,8 @@ LLM timeout (agent runs are long).
98
90
  | LLM API key | The env var named by your pipeline's `api_key_env` (e.g. `OPENAI_API_KEY`) must be set — a missing key fails fast, naming it. |
99
91
 
100
92
  ```bash
101
- # engine mode (sandboxed loop — the full install)
102
- pip install "agentic-dev-loop[engine]==1.0.0a6"
93
+ pip install "agentic-dev-loop==1.0.0a8"
103
94
  agentic-dev-loop --version
104
-
105
- # workflow mode (Claude Code — core + viz only, no SDK/Docker deps)
106
- pip install "agentic-dev-loop==1.0.0a6"
107
- agentic-dev-loop-workflow install-skill
108
95
  ```
109
96
 
110
97
  On the first run the engine pulls the **digest-pinned** dev image
@@ -115,43 +102,6 @@ image. Engine setup, first-run details, the full `pipeline.yaml` contract, and
115
102
  troubleshooting for every fail-fast code live in
116
103
  [docs/setup.md](docs/setup.md).
117
104
 
118
- ## Workflow mode (Claude Code)
119
-
120
- For developers who know and love the agentic dev loop but are forced to use
121
- Claude Code at work: workflow mode exports a **Claude Dynamic Workflow** from
122
- the `pipeline.yaml` they already trust, plus the visualiser they trust. It adds
123
- the deterministic loop through Claude's mechanism — nothing more. **No Docker
124
- sandboxing, and no new security claims**: workflow steps run in Claude Code's
125
- own environment under its permission model (a documented trust-model change
126
- from engine mode).
127
-
128
- Install the skill once:
129
-
130
- ```bash
131
- pip install "agentic-dev-loop==1.0.0a6" # base install: core + viz, no SDK/Docker
132
- agentic-dev-loop-workflow install-skill # → ~/.claude/skills/agentic-dev-loop/
133
- ```
134
-
135
- Then invoke `/agentic-dev-loop` in Claude Code. The skill walks through:
136
-
137
- 1. **Build** — `python -m agentic_dev_loop.core.project <pipeline.yaml>` loads +
138
- validates the pipeline, verifies every agent step's `.agent.md` prompt exists
139
- (a missing prompt fails the build loudly, naming the file), and writes a
140
- self-contained `.agentic-dev-loop/workflow.js`. Steps are frozen at creation
141
- — mid-run `pipeline.yaml` edits never affect a running workflow.
142
- 2. **Run** — the generated JS routes `on_pass` / `on_fail` / `goto` with its own
143
- attempt counter, injects the failing subagent's output as the next retry note,
144
- launches the live-graph server (localhost, token-authenticated ingest), and
145
- invokes the docker-free commit shim, which refuses loudly unless the worktree
146
- was clean at run start.
147
-
148
- Engine-only fields (`isolation:`, per-step `network:`, `setup:`) are ignored in
149
- workflow mode with no effect on the build or run.
150
-
151
- The base install is deliberately dependency-light (`pydantic` + `PyYAML` only);
152
- the heavy OpenHands-SDK engine lives in the `[engine]` extra. The `core` and
153
- `viz` packages are guarded against pulling engine deps.
154
-
155
105
  ## Usage
156
106
 
157
107
  ```bash
@@ -11,16 +11,12 @@ src/agentic_dev_loop.egg-info/requires.txt
11
11
  src/agentic_dev_loop.egg-info/top_level.txt
12
12
  src/agentic_dev_loop/core/__init__.py
13
13
  src/agentic_dev_loop/core/config.py
14
- src/agentic_dev_loop/core/project.py
15
- src/agentic_dev_loop/core/projection.py
16
14
  src/agentic_dev_loop/core/results.py
17
15
  src/agentic_dev_loop/core/verdict.py
18
- src/agentic_dev_loop/core/workflow.js.template
19
16
  src/agentic_dev_loop/engine/__init__.py
20
17
  src/agentic_dev_loop/engine/actions.py
21
18
  src/agentic_dev_loop/engine/agents.py
22
19
  src/agentic_dev_loop/engine/cli.py
23
- src/agentic_dev_loop/engine/commit_shim.py
24
20
  src/agentic_dev_loop/engine/dryrun.py
25
21
  src/agentic_dev_loop/engine/graph.py
26
22
  src/agentic_dev_loop/engine/isolation.py
@@ -34,10 +30,7 @@ src/agentic_dev_loop/engine/extensions/__init__.py
34
30
  src/agentic_dev_loop/engine/extensions/aidlc.py
35
31
  src/agentic_dev_loop/viz/__init__.py
36
32
  src/agentic_dev_loop/viz/__main__.py
37
- src/agentic_dev_loop/viz/ingest.py
38
33
  src/agentic_dev_loop/viz/server.py
39
- src/agentic_dev_loop/workflow/__init__.py
40
- src/agentic_dev_loop/workflow/cli.py
41
34
  tests/test_actions.py
42
35
  tests/test_agents.py
43
36
  tests/test_aidlc.py
@@ -51,6 +44,7 @@ tests/test_isolation_integration.py
51
44
  tests/test_isolation_pbt.py
52
45
  tests/test_llm.py
53
46
  tests/test_loaders.py
47
+ tests/test_module_contract.py
54
48
  tests/test_outputs.py
55
49
  tests/test_outputs_pbt.py
56
50
  tests/test_proc.py
@@ -60,9 +54,5 @@ tests/test_results.py
60
54
  tests/test_sdk_compat.py
61
55
  tests/test_source_resolution.py
62
56
  tests/test_stages.py
63
- tests/test_unit4_golden.py
64
- tests/test_unit4_pbt.py
65
- tests/test_unit4_viz_ingest.py
66
- tests/test_unit4_workflow.py
67
57
  tests/test_verdict.py
68
58
  tests/test_viz.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ agentic-dev-loop = agentic_dev_loop.engine.cli:main
@@ -1,16 +1,11 @@
1
1
  pydantic>=2.0
2
2
  PyYAML>=6.0
3
-
4
- [dev]
5
- agentic-dev-loop[engine]
6
- hypothesis>=6.0
7
- pytest>=8.0
8
-
9
- [engine]
10
3
  openhands-sdk~=1.17.0
11
4
  openhands-tools~=1.17.0
12
5
  agent-client-protocol<1.0.0
13
6
  langgraph>=1.2
14
7
  langgraph-checkpoint-sqlite>=3.0
15
8
 
16
- [workflow]
9
+ [dev]
10
+ hypothesis>=6.0
11
+ pytest>=8.0