agentic-development-framework 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.
- agentic_development_framework-0.1.0.dist-info/METADATA +175 -0
- agentic_development_framework-0.1.0.dist-info/RECORD +27 -0
- agentic_development_framework-0.1.0.dist-info/WHEEL +4 -0
- agentic_development_framework-0.1.0.dist-info/entry_points.txt +2 -0
- agentic_development_framework-0.1.0.dist-info/licenses/LICENSE +22 -0
- agentic_framework/__init__.py +6 -0
- agentic_framework/__main__.py +7 -0
- agentic_framework/adapters/__init__.py +5 -0
- agentic_framework/adapters/generator.py +139 -0
- agentic_framework/cli.py +264 -0
- agentic_framework/core/__init__.py +2 -0
- agentic_framework/core/command_registry.py +16 -0
- agentic_framework/core/config.py +146 -0
- agentic_framework/core/initialization.py +241 -0
- agentic_framework/core/project.py +93 -0
- agentic_framework/core/workflow.py +94 -0
- agentic_framework/exceptions.py +22 -0
- agentic_framework/logging.py +70 -0
- agentic_framework/requirements_manager/__init__.py +8 -0
- agentic_framework/requirements_manager/comparison.py +129 -0
- agentic_framework/requirements_manager/extraction.py +43 -0
- agentic_framework/requirements_manager/ingestion.py +367 -0
- agentic_framework/requirements_manager/traceability.py +65 -0
- agentic_framework/state/__init__.py +5 -0
- agentic_framework/state/database.py +231 -0
- agentic_framework/templates/__init__.py +1 -0
- agentic_framework/templates/skills/agentic-commands/SKILL.md +22 -0
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agentic-development-framework
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A local-first framework for agentic software development workflows.
|
|
5
|
+
Project-URL: Homepage, https://github.com/Badsha-ugv/ide-agentic-development-framework
|
|
6
|
+
Project-URL: Repository, https://github.com/Badsha-ugv/ide-agentic-development-framework
|
|
7
|
+
Project-URL: Issues, https://github.com/Badsha-ugv/ide-agentic-development-framework/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/Badsha-ugv/ide-agentic-development-framework/blob/main/CHANGELOG.md
|
|
9
|
+
Author: Agentic Development Framework contributors
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Software Development
|
|
21
|
+
Requires-Python: >=3.11
|
|
22
|
+
Requires-Dist: pydantic<3,>=2.7
|
|
23
|
+
Requires-Dist: pyyaml<7,>=6.0
|
|
24
|
+
Requires-Dist: typer<1,>=0.12
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: build<2,>=1.2; extra == 'dev'
|
|
27
|
+
Requires-Dist: pytest-cov<8,>=5.0; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest<9,>=8.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: ruff<1,>=0.8; extra == 'dev'
|
|
30
|
+
Requires-Dist: twine<7,>=5; extra == 'dev'
|
|
31
|
+
Description-Content-Type: text/markdown
|
|
32
|
+
|
|
33
|
+
# Agentic Development Framework
|
|
34
|
+
|
|
35
|
+
Agentic Development Framework (ADF) is a local-first foundation for persistent,
|
|
36
|
+
human-controlled software development workflows driven through IDE coding agents.
|
|
37
|
+
|
|
38
|
+
The project is being delivered incrementally. The current implementation provides the
|
|
39
|
+
installable package, strict configuration validation, structured logging, safe project
|
|
40
|
+
initialization, immutable requirements versioning, SQLite workflow state, recovery checkpoints,
|
|
41
|
+
lifecycle commands, and Codex/Antigravity project configuration.
|
|
42
|
+
|
|
43
|
+
## Requirements
|
|
44
|
+
|
|
45
|
+
- Python 3.11 or newer
|
|
46
|
+
|
|
47
|
+
## Installation
|
|
48
|
+
|
|
49
|
+
Install the latest released version from PyPI:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
python -m pip install agentic-development-framework
|
|
53
|
+
adt --help
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Development setup
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
python -m venv .venv
|
|
60
|
+
source .venv/bin/activate
|
|
61
|
+
python -m pip install -e '.[dev]'
|
|
62
|
+
pytest
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## CLI
|
|
66
|
+
|
|
67
|
+
Both entry points expose the same application:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
adt --help
|
|
71
|
+
python -m agentic_framework --help
|
|
72
|
+
adt --version
|
|
73
|
+
adt init
|
|
74
|
+
adt config validate path/to/config.yaml
|
|
75
|
+
adt requirements ingest
|
|
76
|
+
adt start
|
|
77
|
+
adt status
|
|
78
|
+
adt pause
|
|
79
|
+
adt resume
|
|
80
|
+
adt continue
|
|
81
|
+
adt stop
|
|
82
|
+
adt review
|
|
83
|
+
adt approve requirements_review
|
|
84
|
+
adt revise requirements_review "Clarify the acceptance criteria"
|
|
85
|
+
adt tasks
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The validation command prints the normalized configuration as YAML and exits with code 2
|
|
89
|
+
for missing, malformed, or invalid configuration.
|
|
90
|
+
|
|
91
|
+
## Project initialization
|
|
92
|
+
|
|
93
|
+
Run `adt init` or `python -m agentic_framework init` from the project directory. Initialization:
|
|
94
|
+
|
|
95
|
+
- detects new and existing projects, common technologies, package managers, and parent Git roots;
|
|
96
|
+
- creates the ADF runtime, requirements, documentation, and IDE discovery directories;
|
|
97
|
+
- installs initial configuration and project guidance without replacing existing files;
|
|
98
|
+
- writes proposed content under `.agentic/proposals/` when a generated file conflicts; and
|
|
99
|
+
- initializes Git only when no repository is already present.
|
|
100
|
+
|
|
101
|
+
Use `--path DIRECTORY` to target another directory or `--no-git` to suppress Git initialization.
|
|
102
|
+
The operation is idempotent. Its latest report is written to
|
|
103
|
+
`.agentic/reports/initialization.md`.
|
|
104
|
+
|
|
105
|
+
## Requirements management
|
|
106
|
+
|
|
107
|
+
Add one or more source files below `requirements/inbox/`, including files in nested folders,
|
|
108
|
+
then run:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
adt requirements ingest
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Each changed submission creates the next directory under `requirements/versions/`. The version
|
|
115
|
+
contains byte-for-byte source copies, SHA-256 hashes, a manifest, consolidated extracted text, a
|
|
116
|
+
requirement index, and initial traceability records. Existing versions are hash-validated before
|
|
117
|
+
use and are never updated. An unchanged inbox is reported as a duplicate without creating a new
|
|
118
|
+
version.
|
|
119
|
+
|
|
120
|
+
Starting with the second version, ADF compares source files and `REQ-NNN` requirement blocks and
|
|
121
|
+
writes an impact report under `requirements/reports/`. Added, modified, removed, and unchanged
|
|
122
|
+
items are reported separately, along with documentation, architecture, implementation, testing,
|
|
123
|
+
and approval review prompts.
|
|
124
|
+
|
|
125
|
+
Markdown, text, CSV, TSV, JSON, YAML, and reStructuredText are extracted as UTF-8 text. Other
|
|
126
|
+
formats—including PDF, DOCX, XLSX, and images—are still preserved exactly and recorded with a
|
|
127
|
+
clear unsupported-extraction status. Optional binary-format extractors are future work.
|
|
128
|
+
|
|
129
|
+
See `docs/REQUIREMENTS_MANAGEMENT.md` for the file contract and safety behavior.
|
|
130
|
+
|
|
131
|
+
## Runtime state and recovery
|
|
132
|
+
|
|
133
|
+
Initialization creates `.agentic/database/agentic.db` as the transactional source of truth,
|
|
134
|
+
inspection snapshots under `.agentic/state/`, a JSONL event history, and checkpoint storage.
|
|
135
|
+
Pause and stop persist checkpoints. Resume verifies checkpoint integrity and restores the
|
|
136
|
+
checkpoint stage instead of trusting potentially inconsistent conversational context or snapshot
|
|
137
|
+
files. Mandatory workflow approval stages cannot advance until approval is recorded.
|
|
138
|
+
|
|
139
|
+
## IDE configuration
|
|
140
|
+
|
|
141
|
+
ADF generates root `AGENTS.md`, a shared command skill under
|
|
142
|
+
`.agents/skills/agentic-commands/`, and Antigravity rules under `.agents/rules/`. The Codex adapter
|
|
143
|
+
uses the documented root instructions and repository-local skill surfaces. The `.codex/agents/`
|
|
144
|
+
directory contains an informational compatibility note; ADF does not claim an undocumented
|
|
145
|
+
custom-agent file format is automatically discovered.
|
|
146
|
+
|
|
147
|
+
## Configuration
|
|
148
|
+
|
|
149
|
+
ADF configuration uses YAML and rejects unknown keys to catch mistakes early:
|
|
150
|
+
|
|
151
|
+
```yaml
|
|
152
|
+
schema_version: 1
|
|
153
|
+
project:
|
|
154
|
+
name: example-project
|
|
155
|
+
mode: auto
|
|
156
|
+
runtime:
|
|
157
|
+
directory: .agentic
|
|
158
|
+
log_level: INFO
|
|
159
|
+
ide:
|
|
160
|
+
enabled:
|
|
161
|
+
- codex
|
|
162
|
+
policies:
|
|
163
|
+
allow_network: false
|
|
164
|
+
allow_destructive_operations: false
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Runtime directories must be project-relative and cannot contain parent-directory traversal.
|
|
168
|
+
|
|
169
|
+
## Logging
|
|
170
|
+
|
|
171
|
+
`configure_logging()` sets up readable console output and can additionally write a JSONL
|
|
172
|
+
event stream. Reconfiguration is idempotent and only replaces handlers managed by ADF.
|
|
173
|
+
|
|
174
|
+
See `docs/IMPLEMENTATION_PLAN.md` and `docs/IMPLEMENTATION_PROGRESS.md` for scope and status. The
|
|
175
|
+
maintainer release procedure is documented in `docs/PYPI_RELEASE.md`.
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
agentic_framework/__init__.py,sha256=8tbFK-7k7l988vwMRe2eSeonngS3Bv9effHprI9jfW4,112
|
|
2
|
+
agentic_framework/__main__.py,sha256=fHn8AFsz1H4xtmbMVsTaBxC9PNr96qqd8aocXjUsVuQ,140
|
|
3
|
+
agentic_framework/cli.py,sha256=RAW4tJV3GNeZptUf3J8ngptkYdWaBdxOhS6ys3C_IUM,8418
|
|
4
|
+
agentic_framework/exceptions.py,sha256=C8bMuXkRaYr3sXXbsMOZcPrwiglDm8myZ4f6W7x7lrQ,610
|
|
5
|
+
agentic_framework/logging.py,sha256=mHa65Qt-KdA6XsjcnM0RYbCyaxGrvGNt3FB9sexOXJU,2247
|
|
6
|
+
agentic_framework/adapters/__init__.py,sha256=1vR3_hu_F6m0YSFBPTvme16p-98IZYv743xm9EalGy8,176
|
|
7
|
+
agentic_framework/adapters/generator.py,sha256=zRx-psapXDmSfMKow0fW7RoAVpxelc_rbvQycbmzKp8,4805
|
|
8
|
+
agentic_framework/core/__init__.py,sha256=-n3tAT8X8Smg8FcQghm9kMHh_3Ck_Z9LnFhA7tAVXZQ,32
|
|
9
|
+
agentic_framework/core/command_registry.py,sha256=_DQiianO0HhVCnoXgxikH60x0T2DazcoIypgRKedqUc,708
|
|
10
|
+
agentic_framework/core/config.py,sha256=sLs_-NbjwOXgT5OFtGKczKLpVEfmQoisuJeN1SK5t4g,4425
|
|
11
|
+
agentic_framework/core/initialization.py,sha256=TaC4hfaM-I4ybqjIKpV_BsO3wRVk31mtXxyjyv6PfkA,7995
|
|
12
|
+
agentic_framework/core/project.py,sha256=MVVmxepUFlF4PL7tfOwk7uae0ddti-s8OJL1AbxS9Dg,2827
|
|
13
|
+
agentic_framework/core/workflow.py,sha256=5xDolQDbGC3kO5shkCtWE3WTzCdP_iRKDz43a6VJiw4,3976
|
|
14
|
+
agentic_framework/requirements_manager/__init__.py,sha256=Q1T1sIh9n2VxbBucCg_RNzZ6hYgYVJHWZdGe6ccC02M,234
|
|
15
|
+
agentic_framework/requirements_manager/comparison.py,sha256=04Yxd-eK1EST1tbt-ps8wKlULHjhmS2OgwsLGWnXnR8,4807
|
|
16
|
+
agentic_framework/requirements_manager/extraction.py,sha256=SSRbc6W4VDSS7jpnirCfFU2lVuyVCwPWCLoc50dhLvE,1362
|
|
17
|
+
agentic_framework/requirements_manager/ingestion.py,sha256=iYRIXB8HQt15KHl05mjVXoN2nWpp-9_rx5wYfWAkMlI,14947
|
|
18
|
+
agentic_framework/requirements_manager/traceability.py,sha256=azvdk3rc8Uq_gknNn3H9KMg7cUP0q13ltG56f8gq6LE,2254
|
|
19
|
+
agentic_framework/state/__init__.py,sha256=w4no5X4gzvJr935HcZvszZscATGSkEepsMBbBKzQQu8,135
|
|
20
|
+
agentic_framework/state/database.py,sha256=P_XZgLovy7NZTMx39K32_s_jfGjaZDUZcSsCR0Lj2aU,9060
|
|
21
|
+
agentic_framework/templates/__init__.py,sha256=D1B-_zlAKldwEbDY_kEvAfltg6OLZOuLyt4b5Ujgtdw,42
|
|
22
|
+
agentic_framework/templates/skills/agentic-commands/SKILL.md,sha256=dRTAY5eUCZ4hC-K-m49_nVAUybdkkiG_4N0XvGE-FHE,1052
|
|
23
|
+
agentic_development_framework-0.1.0.dist-info/METADATA,sha256=mDEQN5wWOGzgaxPI0XuIjVprvv7PQGPNqQODJK4_XGY,6491
|
|
24
|
+
agentic_development_framework-0.1.0.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
|
|
25
|
+
agentic_development_framework-0.1.0.dist-info/entry_points.txt,sha256=yLrtkLPdApbQjlyVZYNpmRtgc0prbjpJGwF3G9td_zk,50
|
|
26
|
+
agentic_development_framework-0.1.0.dist-info/licenses/LICENSE,sha256=6BzOzZ1c-kyBOz_uNhWQKM1xPmPEQzSNwubTqgniGM0,1100
|
|
27
|
+
agentic_development_framework-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Agentic Development Framework 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.
|
|
22
|
+
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"""Canonical workflow, agent, policy, and IDE adapter assets."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from importlib.resources import files
|
|
6
|
+
|
|
7
|
+
import yaml
|
|
8
|
+
|
|
9
|
+
STAGES = (
|
|
10
|
+
"project_initialization",
|
|
11
|
+
"project_discovery",
|
|
12
|
+
"requirements_ingestion",
|
|
13
|
+
"requirements_analysis",
|
|
14
|
+
"srs_and_project_documentation",
|
|
15
|
+
"requirements_review",
|
|
16
|
+
"system_architecture",
|
|
17
|
+
"architecture_review",
|
|
18
|
+
"ui_ux_design",
|
|
19
|
+
"design_review",
|
|
20
|
+
"development_planning",
|
|
21
|
+
"implementation",
|
|
22
|
+
"integration",
|
|
23
|
+
"qa_and_testing",
|
|
24
|
+
"code_and_security_review",
|
|
25
|
+
"docker_and_ci_cd_validation",
|
|
26
|
+
"final_documentation",
|
|
27
|
+
"release_review",
|
|
28
|
+
"completed",
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
APPROVAL_STAGES = {
|
|
32
|
+
"requirements_review",
|
|
33
|
+
"architecture_review",
|
|
34
|
+
"design_review",
|
|
35
|
+
"release_review",
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
_AGENTS = (
|
|
39
|
+
("main_orchestrator", "Main Orchestrator"),
|
|
40
|
+
("requirements_analyst", "Requirements Analyst"),
|
|
41
|
+
("software_architect", "Software Architect"),
|
|
42
|
+
("ui_ux_designer", "UI/UX Designer"),
|
|
43
|
+
("frontend_developer", "Frontend Developer"),
|
|
44
|
+
("backend_developer", "Backend Developer"),
|
|
45
|
+
("integration_engineer", "Integration Engineer"),
|
|
46
|
+
("qa_engineer", "QA Engineer"),
|
|
47
|
+
("code_reviewer", "Code Reviewer"),
|
|
48
|
+
("security_reviewer", "Security Reviewer"),
|
|
49
|
+
("devops_engineer", "DevOps Engineer"),
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
_RULES = """# Agentic Development Framework rules
|
|
53
|
+
|
|
54
|
+
Read the root `AGENTS.md` and `.agentic/config.yaml` before framework work. Interpret `/start`,
|
|
55
|
+
`/status`, `/pause`, `/resume`, `/continue`, `/stop`, `/review`, `/approve`, `/revise`,
|
|
56
|
+
`/requirements`, and `/tasks` as ADF workflow commands. Use `adt <command>` to persist state.
|
|
57
|
+
Never bypass approval gates or overwrite unrelated project changes.
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
_CODEX_NOTE = """# Codex adapter
|
|
61
|
+
|
|
62
|
+
Codex discovers the root `AGENTS.md` and `.agents/skills/agentic-commands/SKILL.md`. Canonical
|
|
63
|
+
specialist roles live in `.agentic/agent-registry.yaml`. This directory is informational because
|
|
64
|
+
ADF does not assume an undocumented filesystem format for Codex custom agents.
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def _yaml(value: object) -> str:
|
|
69
|
+
return yaml.safe_dump(value, sort_keys=False)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def _workflow() -> str:
|
|
73
|
+
stages = []
|
|
74
|
+
for index, stage_id in enumerate(STAGES):
|
|
75
|
+
stages.append(
|
|
76
|
+
{
|
|
77
|
+
"id": stage_id,
|
|
78
|
+
"purpose": stage_id.replace("_", " ").title(),
|
|
79
|
+
"required_inputs": [],
|
|
80
|
+
"agent": "main_orchestrator",
|
|
81
|
+
"expected_outputs": [],
|
|
82
|
+
"dependencies": [STAGES[index - 1]] if index else [],
|
|
83
|
+
"validation_rules": ["required checks pass"],
|
|
84
|
+
"approval_required": stage_id in APPROVAL_STAGES,
|
|
85
|
+
"failure_behavior": "stop and preserve recoverable state",
|
|
86
|
+
"retry_policy": {"max_attempts": 3},
|
|
87
|
+
"checkpoint_policy": "on_completion",
|
|
88
|
+
}
|
|
89
|
+
)
|
|
90
|
+
return _yaml({"schema_version": 1, "name": "default", "stages": stages})
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _registry() -> str:
|
|
94
|
+
agents = []
|
|
95
|
+
for agent_id, name in _AGENTS:
|
|
96
|
+
agents.append(
|
|
97
|
+
{
|
|
98
|
+
"id": agent_id,
|
|
99
|
+
"name": name,
|
|
100
|
+
"role": name,
|
|
101
|
+
"responsibilities": [f"Perform {name.lower()} work within approved scope"],
|
|
102
|
+
"scope": "assigned tasks only",
|
|
103
|
+
"required_inputs": [],
|
|
104
|
+
"expected_outputs": ["standardized agent result"],
|
|
105
|
+
"allowed_tools": ["repository read/write tools", "project test commands"],
|
|
106
|
+
"restricted_operations": ["secrets", "force push", "unapproved deployment"],
|
|
107
|
+
"verification_requirements": ["run relevant checks"],
|
|
108
|
+
"handoff_format": "agent result contract",
|
|
109
|
+
"failure_and_escalation": "record blocker and escalate to orchestrator",
|
|
110
|
+
}
|
|
111
|
+
)
|
|
112
|
+
return _yaml({"schema_version": 1, "agents": agents})
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def generated_project_files() -> dict[str, str]:
|
|
116
|
+
"""Return deterministic canonical assets for project initialization."""
|
|
117
|
+
|
|
118
|
+
skill = (
|
|
119
|
+
files("agentic_framework")
|
|
120
|
+
.joinpath("templates/skills/agentic-commands/SKILL.md")
|
|
121
|
+
.read_text(encoding="utf-8")
|
|
122
|
+
)
|
|
123
|
+
return {
|
|
124
|
+
".agentic/workflow.yaml": _workflow(),
|
|
125
|
+
".agentic/policies.yaml": _yaml(
|
|
126
|
+
{
|
|
127
|
+
"schema_version": 1,
|
|
128
|
+
"filesystem": "project_only",
|
|
129
|
+
"destructive_operations": "require_explicit_approval",
|
|
130
|
+
"network": "deny_by_default",
|
|
131
|
+
"deployment": "require_approval",
|
|
132
|
+
"secrets": "never_expose_or_commit",
|
|
133
|
+
}
|
|
134
|
+
),
|
|
135
|
+
".agentic/agent-registry.yaml": _registry(),
|
|
136
|
+
".agents/rules/adf.md": _RULES,
|
|
137
|
+
".agents/skills/agentic-commands/SKILL.md": skill,
|
|
138
|
+
".codex/agents/README.md": _CODEX_NOTE,
|
|
139
|
+
}
|
agentic_framework/cli.py
ADDED
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
"""Command-line interface for the Agentic Development Framework."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Annotated
|
|
7
|
+
|
|
8
|
+
import typer
|
|
9
|
+
|
|
10
|
+
from agentic_framework import __version__
|
|
11
|
+
from agentic_framework.core.command_registry import COMMANDS
|
|
12
|
+
from agentic_framework.core.config import dump_config, load_config
|
|
13
|
+
from agentic_framework.core.initialization import FileStatus, initialize_project
|
|
14
|
+
from agentic_framework.core.workflow import WorkflowService
|
|
15
|
+
from agentic_framework.exceptions import (
|
|
16
|
+
ConfigurationError,
|
|
17
|
+
InitializationError,
|
|
18
|
+
RequirementsError,
|
|
19
|
+
StateError,
|
|
20
|
+
)
|
|
21
|
+
from agentic_framework.requirements_manager import RequirementsManager
|
|
22
|
+
|
|
23
|
+
app = typer.Typer(
|
|
24
|
+
name="adt",
|
|
25
|
+
help="Local-first agentic development workflow tooling.",
|
|
26
|
+
no_args_is_help=True,
|
|
27
|
+
)
|
|
28
|
+
config_app = typer.Typer(help="Inspect and validate framework configuration.")
|
|
29
|
+
requirements_app = typer.Typer(
|
|
30
|
+
help="Show, version, and compare project requirements.", invoke_without_command=True
|
|
31
|
+
)
|
|
32
|
+
app.add_typer(config_app, name="config")
|
|
33
|
+
app.add_typer(requirements_app, name="requirements")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _version_callback(value: bool) -> None:
|
|
37
|
+
if value:
|
|
38
|
+
typer.echo(f"adt {__version__}")
|
|
39
|
+
raise typer.Exit()
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@app.callback()
|
|
43
|
+
def main(
|
|
44
|
+
version: Annotated[
|
|
45
|
+
bool | None,
|
|
46
|
+
typer.Option("--version", callback=_version_callback, is_eager=True, help="Show version."),
|
|
47
|
+
] = None,
|
|
48
|
+
) -> None:
|
|
49
|
+
"""Run Agentic Development Framework commands."""
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
@app.command("init")
|
|
53
|
+
def init_project(
|
|
54
|
+
path: Annotated[
|
|
55
|
+
Path,
|
|
56
|
+
typer.Option("--path", help="Project directory to initialize."),
|
|
57
|
+
] = Path("."),
|
|
58
|
+
initialize_git: Annotated[
|
|
59
|
+
bool,
|
|
60
|
+
typer.Option("--git/--no-git", help="Initialize Git when no repository is detected."),
|
|
61
|
+
] = True,
|
|
62
|
+
) -> None:
|
|
63
|
+
"""Safely initialize ADF in a new or existing project."""
|
|
64
|
+
|
|
65
|
+
try:
|
|
66
|
+
result = initialize_project(path, initialize_git=initialize_git)
|
|
67
|
+
except InitializationError as exc:
|
|
68
|
+
typer.echo(f"Error: {exc}", err=True)
|
|
69
|
+
raise typer.Exit(code=2) from exc
|
|
70
|
+
|
|
71
|
+
created = sum(item.status is FileStatus.CREATED for item in result.files)
|
|
72
|
+
typer.echo(f"Initialized {result.inspection.root}")
|
|
73
|
+
typer.echo(f"Project mode: {result.mode.value}")
|
|
74
|
+
typer.echo(f"Created files: {created}")
|
|
75
|
+
typer.echo(f"Conflicts: {len(result.conflicts)}")
|
|
76
|
+
typer.echo("Report: .agentic/reports/initialization.md")
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _workflow_action(path: Path, action: str) -> None:
|
|
80
|
+
try:
|
|
81
|
+
service = WorkflowService(path)
|
|
82
|
+
result = getattr(service, action)()
|
|
83
|
+
except StateError as exc:
|
|
84
|
+
typer.echo(f"Error: {exc}", err=True)
|
|
85
|
+
raise typer.Exit(code=2) from exc
|
|
86
|
+
typer.echo(f"Status: {result['status']}")
|
|
87
|
+
typer.echo(f"Stage: {result['current_stage']}")
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
@app.command("start")
|
|
91
|
+
def start(path: Annotated[Path, typer.Option("--path")] = Path(".")) -> None:
|
|
92
|
+
"""Start the persisted workflow."""
|
|
93
|
+
|
|
94
|
+
_workflow_action(path, "start")
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@app.command("status")
|
|
98
|
+
def status(path: Annotated[Path, typer.Option("--path")] = Path(".")) -> None:
|
|
99
|
+
"""Show persisted workflow status."""
|
|
100
|
+
|
|
101
|
+
_workflow_action(path, "status")
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@app.command("pause")
|
|
105
|
+
def pause(path: Annotated[Path, typer.Option("--path")] = Path(".")) -> None:
|
|
106
|
+
"""Pause safely and create a checkpoint."""
|
|
107
|
+
|
|
108
|
+
_workflow_action(path, "pause")
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
@app.command("resume")
|
|
112
|
+
def resume(path: Annotated[Path, typer.Option("--path")] = Path(".")) -> None:
|
|
113
|
+
"""Validate the latest checkpoint and resume."""
|
|
114
|
+
|
|
115
|
+
_workflow_action(path, "resume")
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
@app.command("continue")
|
|
119
|
+
def continue_command(path: Annotated[Path, typer.Option("--path")] = Path(".")) -> None:
|
|
120
|
+
"""Advance to the next eligible workflow stage."""
|
|
121
|
+
|
|
122
|
+
_workflow_action(path, "continue_workflow")
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@app.command("stop")
|
|
126
|
+
def stop(path: Annotated[Path, typer.Option("--path")] = Path(".")) -> None:
|
|
127
|
+
"""Stop safely and create a checkpoint."""
|
|
128
|
+
|
|
129
|
+
_workflow_action(path, "stop")
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
@app.command("help")
|
|
133
|
+
def help_command() -> None:
|
|
134
|
+
"""List conversational and CLI framework commands."""
|
|
135
|
+
|
|
136
|
+
for name, description in COMMANDS.items():
|
|
137
|
+
typer.echo(f"/{name}: {description}")
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
@app.command("tasks")
|
|
141
|
+
def tasks(path: Annotated[Path, typer.Option("--path")] = Path(".")) -> None:
|
|
142
|
+
"""List persisted workflow tasks."""
|
|
143
|
+
|
|
144
|
+
try:
|
|
145
|
+
values = WorkflowService(path).store.tasks()
|
|
146
|
+
except StateError as exc:
|
|
147
|
+
typer.echo(f"Error: {exc}", err=True)
|
|
148
|
+
raise typer.Exit(code=2) from exc
|
|
149
|
+
if not values:
|
|
150
|
+
typer.echo("No tasks recorded.")
|
|
151
|
+
for task in values:
|
|
152
|
+
typer.echo(f"{task['task_id']} [{task['status']}] {task['title']}")
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
@app.command("review")
|
|
156
|
+
def review(path: Annotated[Path, typer.Option("--path")] = Path(".")) -> None:
|
|
157
|
+
"""List items awaiting approval or revision."""
|
|
158
|
+
|
|
159
|
+
try:
|
|
160
|
+
values = WorkflowService(path).store.approvals()
|
|
161
|
+
except StateError as exc:
|
|
162
|
+
typer.echo(f"Error: {exc}", err=True)
|
|
163
|
+
raise typer.Exit(code=2) from exc
|
|
164
|
+
pending = [item for item in values if item["status"] != "approved"]
|
|
165
|
+
if not pending:
|
|
166
|
+
typer.echo("No deliverables waiting for review.")
|
|
167
|
+
for item in pending:
|
|
168
|
+
typer.echo(f"{item['stage_id']}: {item['status']}")
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
@app.command("approve")
|
|
172
|
+
def approve(
|
|
173
|
+
stage: Annotated[str, typer.Argument(help="Workflow stage ID to approve.")],
|
|
174
|
+
path: Annotated[Path, typer.Option("--path")] = Path("."),
|
|
175
|
+
) -> None:
|
|
176
|
+
"""Record explicit approval for a stage."""
|
|
177
|
+
|
|
178
|
+
try:
|
|
179
|
+
service = WorkflowService(path)
|
|
180
|
+
service.approve(stage)
|
|
181
|
+
except StateError as exc:
|
|
182
|
+
typer.echo(f"Error: {exc}", err=True)
|
|
183
|
+
raise typer.Exit(code=2) from exc
|
|
184
|
+
typer.echo(f"Approved: {stage}")
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
@app.command("revise")
|
|
188
|
+
def revise(
|
|
189
|
+
stage: Annotated[str, typer.Argument(help="Workflow stage ID to revise.")],
|
|
190
|
+
feedback: Annotated[str, typer.Argument(help="Revision feedback.")],
|
|
191
|
+
path: Annotated[Path, typer.Option("--path")] = Path("."),
|
|
192
|
+
) -> None:
|
|
193
|
+
"""Record revision feedback for a stage."""
|
|
194
|
+
|
|
195
|
+
try:
|
|
196
|
+
service = WorkflowService(path)
|
|
197
|
+
service.revise(stage, feedback)
|
|
198
|
+
except StateError as exc:
|
|
199
|
+
typer.echo(f"Error: {exc}", err=True)
|
|
200
|
+
raise typer.Exit(code=2) from exc
|
|
201
|
+
typer.echo(f"Revision requested: {stage}")
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
@config_app.command("validate")
|
|
205
|
+
def validate_config(
|
|
206
|
+
path: Annotated[
|
|
207
|
+
Path,
|
|
208
|
+
typer.Argument(help="YAML configuration file to validate.", exists=False),
|
|
209
|
+
],
|
|
210
|
+
) -> None:
|
|
211
|
+
"""Validate a YAML configuration file and print its normalized representation."""
|
|
212
|
+
|
|
213
|
+
try:
|
|
214
|
+
config = load_config(path)
|
|
215
|
+
except ConfigurationError as exc:
|
|
216
|
+
typer.echo(f"Error: {exc}", err=True)
|
|
217
|
+
raise typer.Exit(code=2) from exc
|
|
218
|
+
typer.echo(dump_config(config), nl=False)
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
@requirements_app.callback()
|
|
222
|
+
def requirements_status(
|
|
223
|
+
context: typer.Context,
|
|
224
|
+
path: Annotated[Path, typer.Option("--path", help="Project directory.")] = Path("."),
|
|
225
|
+
) -> None:
|
|
226
|
+
"""Show the latest requirements version when no subcommand is supplied."""
|
|
227
|
+
|
|
228
|
+
if context.invoked_subcommand is not None:
|
|
229
|
+
return
|
|
230
|
+
try:
|
|
231
|
+
latest = RequirementsManager(path).latest_version()
|
|
232
|
+
except RequirementsError as exc:
|
|
233
|
+
typer.echo(f"Error: {exc}", err=True)
|
|
234
|
+
raise typer.Exit(code=2) from exc
|
|
235
|
+
if latest is None:
|
|
236
|
+
typer.echo("No requirements version has been published.")
|
|
237
|
+
else:
|
|
238
|
+
typer.echo(f"Current requirements: {latest['version']}")
|
|
239
|
+
typer.echo(f"Source files: {len(latest['files'])}")
|
|
240
|
+
|
|
241
|
+
|
|
242
|
+
@requirements_app.command("ingest")
|
|
243
|
+
def ingest_requirements(
|
|
244
|
+
path: Annotated[
|
|
245
|
+
Path,
|
|
246
|
+
typer.Option("--path", help="Project directory containing requirements/inbox."),
|
|
247
|
+
] = Path("."),
|
|
248
|
+
) -> None:
|
|
249
|
+
"""Preserve and publish all files currently in the requirements inbox."""
|
|
250
|
+
|
|
251
|
+
try:
|
|
252
|
+
result = RequirementsManager(path).ingest()
|
|
253
|
+
except RequirementsError as exc:
|
|
254
|
+
typer.echo(f"Error: {exc}", err=True)
|
|
255
|
+
raise typer.Exit(code=2) from exc
|
|
256
|
+
if result.duplicate:
|
|
257
|
+
typer.echo(f"No changes; inbox matches {result.version}.")
|
|
258
|
+
return
|
|
259
|
+
typer.echo(f"Created {result.version} from {result.file_count} source file(s).")
|
|
260
|
+
typer.echo(f"Requirement IDs: {result.requirement_count}")
|
|
261
|
+
if result.impact_report:
|
|
262
|
+
relative_report = result.impact_report.relative_to(result.version_path.parents[1])
|
|
263
|
+
typer.echo(f"Impact report: {relative_report}")
|
|
264
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""Central registry for chat and CLI command compatibility."""
|
|
2
|
+
|
|
3
|
+
COMMANDS = {
|
|
4
|
+
"start": "Start or initialize the project workflow",
|
|
5
|
+
"status": "Display persisted workflow status",
|
|
6
|
+
"pause": "Pause safely and create a checkpoint",
|
|
7
|
+
"resume": "Validate recovery state and resume",
|
|
8
|
+
"continue": "Advance to the next eligible workflow stage",
|
|
9
|
+
"stop": "Stop safely and create a checkpoint",
|
|
10
|
+
"help": "Show available framework commands",
|
|
11
|
+
"review": "Show deliverables waiting for approval",
|
|
12
|
+
"approve": "Approve a workflow stage",
|
|
13
|
+
"revise": "Record revision feedback for a stage",
|
|
14
|
+
"requirements": "Show the latest requirements version",
|
|
15
|
+
"tasks": "Display persisted tasks",
|
|
16
|
+
}
|