devflow-toolkit 0.3.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.
Files changed (63) hide show
  1. devflow/__init__.py +0 -0
  2. devflow/adapters/__init__.py +47 -0
  3. devflow/adapters/agents.py +49 -0
  4. devflow/adapters/base.py +81 -0
  5. devflow/adapters/claude_code.py +120 -0
  6. devflow/adapters/codex.py +111 -0
  7. devflow/adapters/detector.py +118 -0
  8. devflow/adapters/instructions.py +263 -0
  9. devflow/adapters/kiro.py +211 -0
  10. devflow/adapters/opencode.py +237 -0
  11. devflow/adapters/registry.py +41 -0
  12. devflow/cli.py +39 -0
  13. devflow/commands/__init__.py +6 -0
  14. devflow/commands/approve.py +98 -0
  15. devflow/commands/harness.py +98 -0
  16. devflow/commands/init.py +544 -0
  17. devflow/commands/spec.py +514 -0
  18. devflow/commands/status.py +156 -0
  19. devflow/core/__init__.py +15 -0
  20. devflow/core/architecture.py +469 -0
  21. devflow/core/artifacts/__init__.py +29 -0
  22. devflow/core/artifacts/errors.py +19 -0
  23. devflow/core/artifacts/models.py +82 -0
  24. devflow/core/artifacts/store.py +130 -0
  25. devflow/core/clock.py +67 -0
  26. devflow/core/config.py +706 -0
  27. devflow/core/constitution.py +166 -0
  28. devflow/core/discovery.py +1304 -0
  29. devflow/core/ports.py +159 -0
  30. devflow/core/profile_manager.py +311 -0
  31. devflow/core/project.py +533 -0
  32. devflow/core/spec_workflow.py +932 -0
  33. devflow/core/specification.py +2443 -0
  34. devflow/core/state/__init__.py +75 -0
  35. devflow/core/state/errors.py +39 -0
  36. devflow/core/state/events.py +725 -0
  37. devflow/core/state/locator.py +116 -0
  38. devflow/core/state/lock.py +69 -0
  39. devflow/core/state/manager.py +960 -0
  40. devflow/core/state/models.py +164 -0
  41. devflow/core/state/transitions.py +114 -0
  42. devflow/models/__init__.py +6 -0
  43. devflow/models/profile.py +63 -0
  44. devflow/models/project.py +47 -0
  45. devflow/profiles/ai-rag/constitution/ai-rag-standards.md +49 -0
  46. devflow/profiles/ai-rag/profile.yaml +28 -0
  47. devflow/profiles/base/constitution/architecture.md +58 -0
  48. devflow/profiles/base/constitution/code-standards.md +85 -0
  49. devflow/profiles/base/constitution/constitution.md +85 -0
  50. devflow/profiles/base/profile.yaml +15 -0
  51. devflow/profiles/django-backend/constitution/django-standards.md +64 -0
  52. devflow/profiles/django-backend/profile.yaml +24 -0
  53. devflow/profiles/fastapi-backend/constitution/fastapi-standards.md +59 -0
  54. devflow/profiles/fastapi-backend/profile.yaml +23 -0
  55. devflow/prompts/__init__.py +200 -0
  56. devflow/prompts/discovery.md +119 -0
  57. devflow/prompts/spec.greenfield.md +149 -0
  58. devflow/prompts/spec.md +116 -0
  59. devflow_toolkit-0.3.0.dist-info/METADATA +628 -0
  60. devflow_toolkit-0.3.0.dist-info/RECORD +63 -0
  61. devflow_toolkit-0.3.0.dist-info/WHEEL +4 -0
  62. devflow_toolkit-0.3.0.dist-info/entry_points.txt +2 -0
  63. devflow_toolkit-0.3.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,85 @@
1
+ # Project Constitution
2
+
3
+ ## 1. Purpose
4
+
5
+ This document defines the fundamental principles and
6
+ development standards that all AI agents must follow
7
+ when analyzing, planning, implementing or modifying
8
+ this project.
9
+
10
+ These principles apply to all development activities,
11
+ including new features, bug fixes, refactoring,
12
+ integrations and optimizations.
13
+
14
+ ## 2. Existing Project First
15
+
16
+ - Always inspect the existing codebase before proposing
17
+ or implementing changes.
18
+ - Understand the relevant modules, dependencies,
19
+ architecture and existing business logic.
20
+ - Prefer extending existing components over creating
21
+ duplicated implementations.
22
+ - Preserve existing behavior unless the specification
23
+ explicitly requires changing it.
24
+ - Never assume that a feature must be implemented
25
+ from scratch.
26
+
27
+ ## 3. Respect Existing Architecture
28
+
29
+ - Follow the established project architecture.
30
+ - Respect module boundaries and separation of concerns.
31
+ - Avoid introducing unnecessary dependencies.
32
+ - Avoid duplicating business logic.
33
+ - Do not introduce abstractions without a clear benefit.
34
+ - Consider the impact of changes on existing components.
35
+
36
+ ## 4. Code Quality
37
+
38
+ - Follow the standards defined in code-standards.md.
39
+ - Follow the architectural principles defined in
40
+ architecture.md.
41
+ - Apply technology-specific standards when applicable.
42
+
43
+ ## 5. Technology-Specific Standards
44
+
45
+ When the project includes a technology-specific profile,
46
+ follow the guidelines installed for that profile.
47
+
48
+ Examples include django-standards.md for Django projects
49
+ and fastapi-standards.md for FastAPI projects.
50
+
51
+ Technology-specific guidelines must only be applied
52
+ when the corresponding technology is present and its
53
+ profile is enabled for the project.
54
+
55
+ ## 6. Change Safety
56
+
57
+ - Analyze potential regressions before modifying code.
58
+ - Preserve compatibility with existing integrations
59
+ unless otherwise specified.
60
+ - Consider error handling, edge cases and data integrity.
61
+ - Include or update automated tests when appropriate.
62
+ - Never silently discard existing functionality.
63
+
64
+ ## 7. Specification Compliance
65
+
66
+ - Implement only what is required by the approved
67
+ specification.
68
+ - Respect the acceptance criteria.
69
+ - Identify ambiguities instead of inventing requirements.
70
+ - Report assumptions and relevant technical limitations.
71
+
72
+ ## 8. Documentation
73
+
74
+ - Keep technical documentation consistent with the
75
+ actual implementation.
76
+ - Update documentation when a change affects existing
77
+ behavior, configuration or integrations.
78
+
79
+ ## 9. Decision Making
80
+
81
+ - Prefer simple, maintainable solutions.
82
+ - Avoid over-engineering.
83
+ - Explain significant architectural decisions.
84
+ - Ask for clarification when a decision could
85
+ materially change the implementation.
@@ -0,0 +1,15 @@
1
+ name: base
2
+ version: "1.0.0"
3
+ description: Shared engineering standards for every DevFlow project.
4
+
5
+ detection:
6
+ files: []
7
+ dependencies: []
8
+
9
+ constitution:
10
+ - constitution.md
11
+ - code-standards.md
12
+ - architecture.md
13
+
14
+ templates: []
15
+ technologies: []
@@ -0,0 +1,64 @@
1
+ # Django Development Standards
2
+
3
+ ## 1. Models
4
+
5
+ - Organize models into separate files when the domain
6
+ or model complexity justifies it.
7
+ - Use Meta classes to define ordering, indexes
8
+ and database constraints.
9
+ - Place model-related business logic in models
10
+ when appropriate.
11
+ - Avoid placing unrelated business logic in models.
12
+ - Use database constraints to enforce important
13
+ data integrity rules.
14
+
15
+ ## 2. Views and API Endpoints
16
+
17
+ - Keep views thin and focused on HTTP responsibilities.
18
+ - Delegate complex business logic to services.
19
+ - Use class-based views for standard CRUD operations
20
+ when appropriate.
21
+ - Use function-based views for simple actions
22
+ when they provide better clarity.
23
+ - Validate incoming data using serializers
24
+ or appropriate validation components.
25
+ - Keep response handling consistent with the
26
+ existing API conventions.
27
+
28
+ ## 3. Services
29
+
30
+ - Place complex business logic in a services/ package.
31
+ - Organize services around domain concepts.
32
+ - Keep services focused and cohesive.
33
+ - Prefer stateless services when possible.
34
+ - Avoid unnecessary service layers for simple operations.
35
+
36
+ ## 4. Query Optimization
37
+
38
+ - Use select_related() for ForeignKey and OneToOneField
39
+ relationships.
40
+ - Use prefetch_related() for ManyToManyField
41
+ and reverse relationships.
42
+ - Use only() or defer() when partial field retrieval
43
+ provides a measurable benefit.
44
+ - Use exists() for boolean existence checks.
45
+ - Avoid N+1 queries.
46
+ - Inspect generated queries when performance
47
+ is a concern.
48
+
49
+ ## 5. Transactions and Data Integrity
50
+
51
+ - Use transaction.atomic() when multiple database
52
+ operations must succeed or fail together.
53
+ - Handle integrity errors appropriately.
54
+ - Avoid unnecessary long-running transactions.
55
+ - Respect existing tenant and database isolation
56
+ mechanisms.
57
+
58
+ ## 6. Testing
59
+
60
+ - Follow the project's existing testing conventions.
61
+ - Test successful operations and relevant failure cases.
62
+ - Cover permissions, validation and edge cases.
63
+ - Reuse existing factories, fixtures and test utilities.
64
+ - Avoid duplicating test setup unnecessarily.
@@ -0,0 +1,24 @@
1
+ name: django-backend
2
+ version: "1.0.0"
3
+ description: Django backend development profile.
4
+
5
+ detection:
6
+ files:
7
+ - manage.py
8
+ dependencies:
9
+ - django
10
+ - djangorestframework
11
+ indicators:
12
+ - manage.py
13
+ - settings.py
14
+ - urls.py
15
+
16
+ constitution:
17
+ - django-standards.md
18
+
19
+ templates: []
20
+
21
+ technologies:
22
+ - python
23
+ - django
24
+ - django-rest-framework
@@ -0,0 +1,59 @@
1
+ # FastAPI Development Standards
2
+
3
+ ## 1. Application Structure
4
+
5
+ - Keep application bootstrap and configuration in a
6
+ dedicated module.
7
+ - Group routes by domain using routers.
8
+ - Keep request handling, business logic and data access
9
+ separated.
10
+ - Reuse existing dependency injection patterns before
11
+ introducing new ones.
12
+
13
+ ## 2. Routes and Schemas
14
+
15
+ - Keep route handlers focused on HTTP concerns.
16
+ - Declare explicit request and response models.
17
+ - Define response models and status codes explicitly.
18
+ - Keep error responses consistent with the existing API.
19
+ - Avoid exposing internal ORM models through the API.
20
+
21
+ ## 3. Async and I/O
22
+
23
+ - Do not block the event loop with synchronous I/O.
24
+ - Use async database and HTTP clients consistently.
25
+ - Set timeouts on external calls.
26
+ - Propagate cancellation where appropriate.
27
+ - Avoid unnecessary concurrency and background tasks.
28
+
29
+ ## 4. Dependencies and Services
30
+
31
+ - Use FastAPI dependencies for shared request concerns.
32
+ - Place business logic in services rather than routes.
33
+ - Keep services focused and testable.
34
+ - Reuse existing sessions, clients and configuration.
35
+ - Avoid hidden global state.
36
+
37
+ ## 5. Data Access
38
+
39
+ - Scope database sessions to the request or unit of work.
40
+ - Avoid N+1 queries and unnecessary eager loading.
41
+ - Use transactions for operations that must be atomic.
42
+ - Retrieve only the data required by the endpoint.
43
+ - Handle integrity and not-found errors explicitly.
44
+
45
+ ## 6. Validation and Security
46
+
47
+ - Validate input with typed schemas.
48
+ - Enforce authentication and authorization at the
49
+ appropriate layer.
50
+ - Do not trust client-provided identifiers or roles.
51
+ - Avoid leaking secrets or internal details in errors.
52
+ - Consider rate limits and payload size limits when relevant.
53
+
54
+ ## 7. Testing
55
+
56
+ - Follow the existing test layout and fixtures.
57
+ - Test success, validation, permission and failure paths.
58
+ - Use dependency overrides rather than global mocks.
59
+ - Keep tests independent and deterministic.
@@ -0,0 +1,23 @@
1
+ name: fastapi-backend
2
+ version: "1.0.0"
3
+ description: FastAPI backend development profile.
4
+
5
+ detection:
6
+ files: []
7
+ dependencies:
8
+ - fastapi
9
+ - uvicorn
10
+ indicators:
11
+ - main.py
12
+ - routers
13
+ - dependencies
14
+
15
+ constitution:
16
+ - fastapi-standards.md
17
+
18
+ templates: []
19
+
20
+ technologies:
21
+ - python
22
+ - fastapi
23
+ - async
@@ -0,0 +1,200 @@
1
+ """Loading and rendering of shared harness-independent prompts."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path
6
+
7
+ from devflow.core.config import AgentPermissions
8
+
9
+ PROMPTS_ROOT = Path(__file__).resolve().parent
10
+
11
+
12
+ class PromptError(Exception):
13
+ """Raised when a bundled prompt cannot be loaded."""
14
+
15
+
16
+ def load_prompt(name: str) -> str:
17
+ """Load a bundled prompt template by filename."""
18
+ path = PROMPTS_ROOT / name
19
+ try:
20
+ return path.read_text(encoding="utf-8")
21
+ except OSError as error:
22
+ msg = f"Could not read prompt template: {path}"
23
+ raise PromptError(msg) from error
24
+
25
+
26
+ def build_spec_prompt(
27
+ *,
28
+ request: str,
29
+ project_name: str,
30
+ context_path: str,
31
+ spec_path: str,
32
+ constitution_paths: list[str],
33
+ harness_name: str,
34
+ execution_mode: str,
35
+ permissions: AgentPermissions,
36
+ project_mode: str = "existing",
37
+ architecture_path: str = "",
38
+ architecture_digest: str = "",
39
+ architecture_style: str = "",
40
+ discovery_path: str = "",
41
+ discovery_digest: str = "",
42
+ discovery_decisions: list[str] | None = None,
43
+ ) -> str:
44
+ """Render the shared specification prompt for any harness."""
45
+ template_name = (
46
+ "spec.greenfield.md"
47
+ if project_mode == "greenfield"
48
+ else "spec.md"
49
+ )
50
+ template = load_prompt(template_name)
51
+ mode_instructions = _mode_instructions(
52
+ execution_mode,
53
+ spec_path,
54
+ permissions,
55
+ )
56
+ architecture_note = ""
57
+ if architecture_path:
58
+ architecture_note = (
59
+ f"- Declared architecture manifest: `{architecture_path}`\n"
60
+ f"- Architecture digest: `{architecture_digest}`\n"
61
+ f"- Declared architecture style: {architecture_style}\n"
62
+ )
63
+ discovery_note = ""
64
+ if discovery_path:
65
+ discovery_note = (
66
+ f"- Discovery record: `{discovery_path}`\n"
67
+ f"- Discovery digest: `{discovery_digest}`\n"
68
+ )
69
+ for decision in discovery_decisions or []:
70
+ discovery_note += f"- Discovery decision: {decision}\n"
71
+ replacements = {
72
+ "request": request,
73
+ "project_name": project_name,
74
+ "context_path": context_path,
75
+ "spec_path": spec_path,
76
+ "constitution_paths": (
77
+ ", ".join(f"`{path}`" for path in constitution_paths)
78
+ or "none"
79
+ ),
80
+ "harness_name": harness_name,
81
+ "execution_mode": execution_mode,
82
+ "project_mode": project_mode,
83
+ "architecture_note": architecture_note,
84
+ "discovery_note": discovery_note,
85
+ "mode_instructions": mode_instructions,
86
+ "permission_summary": _permission_summary(permissions),
87
+ }
88
+ rendered = template
89
+ for key, value in replacements.items():
90
+ rendered = rendered.replace("{{" + key + "}}", value)
91
+ return rendered
92
+
93
+
94
+ def build_discovery_prompt(
95
+ *,
96
+ request: str,
97
+ project_name: str,
98
+ context_path: str,
99
+ discovery_path: str,
100
+ harness_name: str,
101
+ execution_mode: str,
102
+ permissions: AgentPermissions,
103
+ ) -> str:
104
+ """Render the interactive discovery prompt for any harness."""
105
+ template = load_prompt("discovery.md")
106
+ replacements = {
107
+ "request": request,
108
+ "project_name": project_name,
109
+ "context_path": context_path,
110
+ "discovery_path": discovery_path,
111
+ "harness_name": harness_name,
112
+ "execution_mode": execution_mode,
113
+ "mode_instructions": _discovery_mode_instructions(
114
+ discovery_path,
115
+ execution_mode,
116
+ permissions,
117
+ ),
118
+ "permission_summary": _permission_summary(permissions),
119
+ }
120
+ rendered = template
121
+ for key, value in replacements.items():
122
+ rendered = rendered.replace("{{" + key + "}}", value)
123
+ return rendered
124
+
125
+
126
+ def _discovery_mode_instructions(
127
+ discovery_path: str,
128
+ execution_mode: str,
129
+ permissions: AgentPermissions,
130
+ ) -> str:
131
+ if execution_mode != "interactive":
132
+ return (
133
+ "Discovery is incomplete. Do not write a specification and do "
134
+ "not invent answers. Report the pending questions and stop."
135
+ )
136
+ if not permissions.allow_spec_write:
137
+ return (
138
+ "Discovery is incomplete, but artifact writes are disabled. Ask "
139
+ "the user for explicit answers and acceptance, then report them "
140
+ "verbatim. Do not write the specification."
141
+ )
142
+ return (
143
+ "You are running interactively. Read the discovery record and ask "
144
+ "the user only about pending blocking questions and proposed "
145
+ "assumptions. Record only explicit answers. Update the same "
146
+ f"`{discovery_path}` file in place, preserving every existing id, "
147
+ "category, blocking flag and question text. Set an answered "
148
+ "question to `status: answered` with `answer`, `answered_by: user` "
149
+ "and an ISO-8601 `answered_at` timestamp. Set an accepted "
150
+ "assumption to `status: accepted` with `accepted_by: user` and "
151
+ "`accepted_at`. Never accept an assumption on the user's behalf. "
152
+ "Never change the request, project_mode, spec_id or change. Do not "
153
+ "write or modify `spec.md` in this phase. When no pending blocking "
154
+ "question or unaccepted assumption remains, stop and report that "
155
+ "Discovery is complete."
156
+ )
157
+
158
+
159
+ def _mode_instructions(
160
+ execution_mode: str,
161
+ spec_path: str,
162
+ permissions: AgentPermissions,
163
+ ) -> str:
164
+ if execution_mode == "interactive":
165
+ if permissions.allow_spec_write:
166
+ return (
167
+ "You are running interactively. Ask concise clarifying questions "
168
+ "whenever missing information would change requirements or "
169
+ "acceptance criteria. Resolve what you can with the user, then "
170
+ f"write the complete specification to `{spec_path}` using the "
171
+ "available file tools. Do not finish until that file exists and "
172
+ "contains the complete document."
173
+ )
174
+ return (
175
+ "You are running interactively, but specification writes are "
176
+ "disabled. Ask clarifying questions and return the complete "
177
+ "specification as your final message. DevFlow will record the "
178
+ "deterministic fallback specification."
179
+ )
180
+
181
+ return (
182
+ "You are running non-interactively. Do not ask the user questions "
183
+ "and do not write files. Put every unresolved question or assumption "
184
+ "in section 7. Return only the complete Markdown specification as "
185
+ "your final answer. DevFlow will validate it and write it to "
186
+ f"`{spec_path}`."
187
+ )
188
+
189
+
190
+ def _permission_summary(permissions: AgentPermissions) -> str:
191
+ def status(value: bool) -> str:
192
+ return "allowed" if value else "denied"
193
+
194
+ return (
195
+ f"- Project read: {status(permissions.allow_project_read)}\n"
196
+ f"- Specification write: {status(permissions.allow_spec_write)}\n"
197
+ "- Source code changes: "
198
+ f"{status(permissions.allow_source_code_changes)}\n"
199
+ "- Source changes remain out of scope for specification generation."
200
+ )
@@ -0,0 +1,119 @@
1
+ # DevFlow Discovery Task
2
+
3
+ You are the discovery agent for the project `{{project_name}}`.
4
+
5
+ ## Source of Truth
6
+
7
+ - Change request: {{request}}
8
+ - Static analysis context: `{{context_path}}`
9
+ - Discovery record: `{{discovery_path}}`
10
+ - Harness: {{harness_name}}
11
+ - Execution mode: {{execution_mode}}
12
+
13
+ Read the context and the discovery record before talking to the user.
14
+ The discovery record is the only place where answers and assumption
15
+ acceptance may be recorded.
16
+
17
+ ## Purpose
18
+
19
+ Discovery decides whether the request is ready to become a
20
+ specification. It does not write the specification and it does not
21
+ change application code.
22
+
23
+ A specification may only be generated when:
24
+
25
+ - every question with `blocking: true` has an explicit answer; and
26
+ - every proposed assumption has been explicitly accepted.
27
+
28
+ Questions with `blocking: false` may remain pending. Never change a
29
+ question from blocking to non-blocking without a clear justification
30
+ based on user-visible behavior, data, security, integrations,
31
+ dependencies, deployment or architecture boundaries.
32
+
33
+ ## Non-Negotiable Boundaries
34
+
35
+ - Do not write, overwrite or delete `spec.md`.
36
+ - Do not modify application source code, tests, configuration,
37
+ dependencies or the constitution.
38
+ - Do not invent answers. If the user is unsure, leave the question
39
+ pending and explain what decision is needed.
40
+ - Do not accept assumptions on the user's behalf. Acceptance is an
41
+ explicit human action.
42
+ - Preserve every existing id, question text, category, blocking flag,
43
+ option, request, `spec_id`, `change` and `project_mode`.
44
+ - Record only what the user explicitly said. Do not summarize away
45
+ details that change scope.
46
+
47
+ ## Discovery Record Format
48
+
49
+ The file is YAML with this shape:
50
+
51
+ ```yaml
52
+ version: 1
53
+ spec_id: "001"
54
+ change: "001-short-slug"
55
+ request: "Original request"
56
+ project_mode: existing
57
+ status: awaiting_clarification
58
+ created_at: "YYYY-MM-DDTHH:MM:SSZ"
59
+ updated_at: "YYYY-MM-DDTHH:MM:SSZ"
60
+ questions:
61
+ - id: Q1
62
+ category: functional_scope
63
+ question: "..."
64
+ reason: "..."
65
+ blocking: true
66
+ status: answered
67
+ options: []
68
+ answer: "..."
69
+ answered_by: user
70
+ answered_at: "YYYY-MM-DDTHH:MM:SSZ"
71
+ assumptions:
72
+ - id: A1
73
+ question_id: Q1
74
+ value: "..."
75
+ reason: "..."
76
+ source: agent_default
77
+ status: accepted
78
+ accepted_by: user
79
+ accepted_at: "YYYY-MM-DDTHH:MM:SSZ"
80
+ ```
81
+
82
+ Valid question categories are `functional_scope`, `user_behavior`,
83
+ `data_persistence`, `security_authentication`,
84
+ `external_integration`, `architecture_boundary`, `dependencies` and
85
+ `deployment`.
86
+
87
+ Valid question statuses are `pending` and `answered`. Valid assumption
88
+ statuses are `pending_acceptance` and `accepted`.
89
+
90
+ An answered question requires `answer`, `answered_by` and
91
+ `answered_at`. An accepted assumption requires `accepted_by` and
92
+ `accepted_at`. A pending item must not contain those fields.
93
+
94
+ Update `updated_at` whenever the file changes. Set `status` to
95
+ `awaiting_clarification` while anything blocking or unaccepted
96
+ remains, and to `complete` only when nothing does.
97
+
98
+ ## Conversation Rules
99
+
100
+ - Ask one focused question at a time.
101
+ - Explain why the answer changes the specification.
102
+ - Offer the recorded options when they exist, but accept a free-form
103
+ answer when it is clearer.
104
+ - For each proposed assumption, state the proposal and ask for
105
+ explicit acceptance or rejection. If rejected, ask what to do
106
+ instead.
107
+ - Stop asking once every blocking decision is resolved. Do not pad the
108
+ conversation with optional preferences.
109
+
110
+ ## Execution Instructions
111
+
112
+ {{mode_instructions}}
113
+
114
+ ## Permission Summary
115
+
116
+ {{permission_summary}}
117
+
118
+ Return a short report of what was answered, what was accepted and what
119
+ remains pending. Do not generate the specification.