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.
@@ -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,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.31.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ adt = agentic_framework.cli:app
@@ -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,6 @@
1
+ """Agentic Development Framework public package metadata."""
2
+
3
+ __version__ = "0.1.0"
4
+
5
+ __all__ = ["__version__"]
6
+
@@ -0,0 +1,7 @@
1
+ """Module entry point for ``python -m agentic_framework``."""
2
+
3
+ from agentic_framework.cli import app
4
+
5
+ if __name__ == "__main__":
6
+ app()
7
+
@@ -0,0 +1,5 @@
1
+ """IDE adapter assets generated from canonical definitions."""
2
+
3
+ from agentic_framework.adapters.generator import generated_project_files
4
+
5
+ __all__ = ["generated_project_files"]
@@ -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
+ }
@@ -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,2 @@
1
+ """Core framework services."""
2
+
@@ -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
+ }