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.
- devflow/__init__.py +0 -0
- devflow/adapters/__init__.py +47 -0
- devflow/adapters/agents.py +49 -0
- devflow/adapters/base.py +81 -0
- devflow/adapters/claude_code.py +120 -0
- devflow/adapters/codex.py +111 -0
- devflow/adapters/detector.py +118 -0
- devflow/adapters/instructions.py +263 -0
- devflow/adapters/kiro.py +211 -0
- devflow/adapters/opencode.py +237 -0
- devflow/adapters/registry.py +41 -0
- devflow/cli.py +39 -0
- devflow/commands/__init__.py +6 -0
- devflow/commands/approve.py +98 -0
- devflow/commands/harness.py +98 -0
- devflow/commands/init.py +544 -0
- devflow/commands/spec.py +514 -0
- devflow/commands/status.py +156 -0
- devflow/core/__init__.py +15 -0
- devflow/core/architecture.py +469 -0
- devflow/core/artifacts/__init__.py +29 -0
- devflow/core/artifacts/errors.py +19 -0
- devflow/core/artifacts/models.py +82 -0
- devflow/core/artifacts/store.py +130 -0
- devflow/core/clock.py +67 -0
- devflow/core/config.py +706 -0
- devflow/core/constitution.py +166 -0
- devflow/core/discovery.py +1304 -0
- devflow/core/ports.py +159 -0
- devflow/core/profile_manager.py +311 -0
- devflow/core/project.py +533 -0
- devflow/core/spec_workflow.py +932 -0
- devflow/core/specification.py +2443 -0
- devflow/core/state/__init__.py +75 -0
- devflow/core/state/errors.py +39 -0
- devflow/core/state/events.py +725 -0
- devflow/core/state/locator.py +116 -0
- devflow/core/state/lock.py +69 -0
- devflow/core/state/manager.py +960 -0
- devflow/core/state/models.py +164 -0
- devflow/core/state/transitions.py +114 -0
- devflow/models/__init__.py +6 -0
- devflow/models/profile.py +63 -0
- devflow/models/project.py +47 -0
- devflow/profiles/ai-rag/constitution/ai-rag-standards.md +49 -0
- devflow/profiles/ai-rag/profile.yaml +28 -0
- devflow/profiles/base/constitution/architecture.md +58 -0
- devflow/profiles/base/constitution/code-standards.md +85 -0
- devflow/profiles/base/constitution/constitution.md +85 -0
- devflow/profiles/base/profile.yaml +15 -0
- devflow/profiles/django-backend/constitution/django-standards.md +64 -0
- devflow/profiles/django-backend/profile.yaml +24 -0
- devflow/profiles/fastapi-backend/constitution/fastapi-standards.md +59 -0
- devflow/profiles/fastapi-backend/profile.yaml +23 -0
- devflow/prompts/__init__.py +200 -0
- devflow/prompts/discovery.md +119 -0
- devflow/prompts/spec.greenfield.md +149 -0
- devflow/prompts/spec.md +116 -0
- devflow_toolkit-0.3.0.dist-info/METADATA +628 -0
- devflow_toolkit-0.3.0.dist-info/RECORD +63 -0
- devflow_toolkit-0.3.0.dist-info/WHEEL +4 -0
- devflow_toolkit-0.3.0.dist-info/entry_points.txt +2 -0
- devflow_toolkit-0.3.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,628 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: devflow-toolkit
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Specification workflow toolkit for AI-assisted software changes
|
|
5
|
+
Author: DevFlow contributors
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Keywords: agents,ai,architecture,cli,greenfield,sdd,specification,workflow
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Operating System :: MacOS
|
|
14
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Documentation
|
|
20
|
+
Classifier: Topic :: Software Development :: Documentation
|
|
21
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
22
|
+
Requires-Python: >=3.11
|
|
23
|
+
Requires-Dist: pyyaml>=6.0
|
|
24
|
+
Requires-Dist: rich>=13.0
|
|
25
|
+
Requires-Dist: typer>=0.12
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: build>=1.2; extra == 'dev'
|
|
28
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: ruff>=0.12; extra == 'dev'
|
|
30
|
+
Requires-Dist: twine>=5.0; extra == 'dev'
|
|
31
|
+
Description-Content-Type: text/markdown
|
|
32
|
+
|
|
33
|
+
# DevFlow Toolkit
|
|
34
|
+
|
|
35
|
+
DevFlow is an installable command-line toolkit for managing
|
|
36
|
+
specification-driven changes in existing software projects with the help
|
|
37
|
+
of an AI coding agent.
|
|
38
|
+
|
|
39
|
+
It captures the project context, the project constitution and the
|
|
40
|
+
approval history, so a specification can be reviewed and approved before
|
|
41
|
+
anyone starts implementing it. DevFlow owns the workflow state; the
|
|
42
|
+
selected agent harness is only the execution backend that drafts the
|
|
43
|
+
specification.
|
|
44
|
+
|
|
45
|
+
This is the `0.3.0` MVP. It implements the **discovery and
|
|
46
|
+
specification stages only**. It supports two specification contexts:
|
|
47
|
+
**Existing Project** (the default) and **Greenfield**. It is not a
|
|
48
|
+
complete SDD platform and does not include planning, implementation or
|
|
49
|
+
review workflows.
|
|
50
|
+
|
|
51
|
+
Discovery decides whether a request is ready to become a
|
|
52
|
+
specification. A specification is only generated when every blocking
|
|
53
|
+
question has an explicit answer and every proposed assumption has been
|
|
54
|
+
explicitly accepted. Discovery is persisted, so an incomplete request
|
|
55
|
+
can be resumed across sessions and agent harnesses.
|
|
56
|
+
|
|
57
|
+
## The problem it solves
|
|
58
|
+
|
|
59
|
+
AI agents can produce useful specifications, but the result is often a
|
|
60
|
+
throwaway chat response:
|
|
61
|
+
|
|
62
|
+
- it is not tied to the real codebase;
|
|
63
|
+
- it does not follow the project's own engineering rules;
|
|
64
|
+
- there is no record of who approved it or which exact version was
|
|
65
|
+
approved;
|
|
66
|
+
- switching agents loses context and history.
|
|
67
|
+
|
|
68
|
+
DevFlow keeps the specification, the evidence used to write it, the
|
|
69
|
+
constitution and the approval record inside the project. Approvals are
|
|
70
|
+
bound to SHA-256 digests, and the workflow state can be rebuilt from an
|
|
71
|
+
append-only event log.
|
|
72
|
+
|
|
73
|
+
## Two specification contexts
|
|
74
|
+
|
|
75
|
+
DevFlow does not assume that a project already exists. The difference
|
|
76
|
+
between the two modes is where the context comes from, not a permanent
|
|
77
|
+
identity for the project:
|
|
78
|
+
|
|
79
|
+
| Context | Source of context | Typical use |
|
|
80
|
+
| --- | --- | --- |
|
|
81
|
+
| `existing` (default) | Analysed code, dependencies, conventions and the constitution, plus the declared architecture manifest when present | A change, fix, refactor or integration in a real codebase |
|
|
82
|
+
| `greenfield` | Requested requirements, a declared architecture manifest, stack, constraints and the constitution | The initial specification for a system that does not exist yet |
|
|
83
|
+
|
|
84
|
+
- `existing` is the default and preserves the historical behaviour.
|
|
85
|
+
- `greenfield` never invents existing code. It does not scaffold a
|
|
86
|
+
project, generate application code or implement tasks.
|
|
87
|
+
- Greenfield is a context for a specification execution, not a permanent
|
|
88
|
+
project identity. After implementation exists, switch back to
|
|
89
|
+
`existing`; the architecture manifest is kept and used as a
|
|
90
|
+
constraint.
|
|
91
|
+
- DevFlow never switches modes silently. Use `--project-mode` explicitly
|
|
92
|
+
when a run differs from the configured default.
|
|
93
|
+
|
|
94
|
+
## Requirements
|
|
95
|
+
|
|
96
|
+
- Python 3.11 or newer.
|
|
97
|
+
- A POSIX operating system (Linux or macOS). Windows is not tested and is
|
|
98
|
+
not supported in this release, because the workflow locks require
|
|
99
|
+
`fcntl`.
|
|
100
|
+
- For agent-generated specifications: OpenCode installed and
|
|
101
|
+
authenticated on `PATH`. OpenCode is the only harness verified
|
|
102
|
+
end-to-end for this release.
|
|
103
|
+
- Git is not required. DevFlow does not initialize a repository, commit
|
|
104
|
+
files or run destructive commands.
|
|
105
|
+
|
|
106
|
+
## Installation
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
python -m venv .venv
|
|
110
|
+
source .venv/bin/activate
|
|
111
|
+
pip install devflow-toolkit
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
To install a specific built artifact instead:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
pip install devflow_toolkit-0.3.0-py3-none-any.whl
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Verify the installation:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
devflow --help
|
|
124
|
+
devflow version
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Initialization
|
|
128
|
+
|
|
129
|
+
Run `devflow init` inside the project you want to manage:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
cd my-project
|
|
133
|
+
devflow init
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
DevFlow inspects the existing project, detects its stack and profiles,
|
|
137
|
+
copies the applicable constitution documents, writes
|
|
138
|
+
`.devflow/config.yaml` and generates the integration for the selected
|
|
139
|
+
harness.
|
|
140
|
+
|
|
141
|
+
Common options:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
devflow init --harness opencode --mode non-interactive
|
|
145
|
+
devflow init --profile django-backend --name my-service
|
|
146
|
+
devflow init --project-mode greenfield
|
|
147
|
+
devflow init --no-agent
|
|
148
|
+
devflow init --yes
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
`init --project-mode greenfield` creates `.devflow/architecture.yaml`
|
|
152
|
+
from a template when it does not exist. It never overwrites an existing
|
|
153
|
+
manifest. Edit the manifest before running a Greenfield specification;
|
|
154
|
+
until then, `spec` fails with a clear structural error.
|
|
155
|
+
|
|
156
|
+
`init` never overwrites an existing constitution document, configuration
|
|
157
|
+
file, specification, approval or unmanaged integration file. Running it
|
|
158
|
+
again refreshes missing constitution files and managed integration files
|
|
159
|
+
without destroying project work.
|
|
160
|
+
|
|
161
|
+
If an explicitly selected harness is not installed, `init` still records
|
|
162
|
+
the selection but prints a warning. Subsequent `spec` runs fall back to
|
|
163
|
+
deterministic static analysis until the executable is available.
|
|
164
|
+
|
|
165
|
+
## Configuration
|
|
166
|
+
|
|
167
|
+
`.devflow/config.yaml` stores project settings. It references the
|
|
168
|
+
constitution documents; it does not duplicate their contents.
|
|
169
|
+
|
|
170
|
+
```yaml
|
|
171
|
+
project:
|
|
172
|
+
name: my-service
|
|
173
|
+
type: backend
|
|
174
|
+
mode: existing
|
|
175
|
+
profiles:
|
|
176
|
+
- django-backend
|
|
177
|
+
constitution:
|
|
178
|
+
base: true
|
|
179
|
+
profile_specific: true
|
|
180
|
+
path: .devflow/constitution
|
|
181
|
+
files:
|
|
182
|
+
- constitution.md
|
|
183
|
+
- code-standards.md
|
|
184
|
+
- architecture.md
|
|
185
|
+
- django-standards.md
|
|
186
|
+
specifications:
|
|
187
|
+
path: .devflow/specs
|
|
188
|
+
plans:
|
|
189
|
+
path: .devflow/plans
|
|
190
|
+
templates:
|
|
191
|
+
path: .devflow/templates
|
|
192
|
+
agent:
|
|
193
|
+
harness: opencode
|
|
194
|
+
execution:
|
|
195
|
+
mode: non-interactive
|
|
196
|
+
permissions:
|
|
197
|
+
allow_project_read: true
|
|
198
|
+
allow_workflow_write: true
|
|
199
|
+
allow_source_code_changes: false
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
`constitution.files` accepts plain file names inside the constitution
|
|
203
|
+
directory. Absolute paths, `..` and nested paths are rejected.
|
|
204
|
+
|
|
205
|
+
Existing configurations without `project.mode` load as `existing`.
|
|
206
|
+
|
|
207
|
+
## Declared architecture
|
|
208
|
+
|
|
209
|
+
The declared architecture lives in `.devflow/architecture.yaml`, not in
|
|
210
|
+
`config.yaml`. It is a reviewable, versionable design decision. Example:
|
|
211
|
+
|
|
212
|
+
```yaml
|
|
213
|
+
version: 1
|
|
214
|
+
style: clean-architecture
|
|
215
|
+
summary: >
|
|
216
|
+
REST API for contact management with domain separation.
|
|
217
|
+
modules:
|
|
218
|
+
- name: contacts
|
|
219
|
+
responsibility: Contact registration and queries
|
|
220
|
+
depends_on: [shared]
|
|
221
|
+
- name: shared
|
|
222
|
+
responsibility: Cross-cutting utilities
|
|
223
|
+
depends_on: []
|
|
224
|
+
layers:
|
|
225
|
+
- name: domain
|
|
226
|
+
may_depend_on: []
|
|
227
|
+
- name: application
|
|
228
|
+
may_depend_on: [domain]
|
|
229
|
+
- name: infrastructure
|
|
230
|
+
may_depend_on: [domain, application]
|
|
231
|
+
- name: presentation
|
|
232
|
+
may_depend_on: [application]
|
|
233
|
+
stack:
|
|
234
|
+
language: python
|
|
235
|
+
framework: django-rest-framework
|
|
236
|
+
database: postgresql
|
|
237
|
+
constraints:
|
|
238
|
+
containerization: docker
|
|
239
|
+
authentication: jwt
|
|
240
|
+
testing: pytest
|
|
241
|
+
quality_attributes:
|
|
242
|
+
- testability
|
|
243
|
+
- modularity
|
|
244
|
+
fitness_functions:
|
|
245
|
+
- domain must not import infrastructure
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
`style` is free text. Clean Architecture, Hexagonal Architecture,
|
|
249
|
+
Microservices, Modular Monolith and Event-Driven are examples and
|
|
250
|
+
presets, not a closed list. Custom architectures are valid as long as
|
|
251
|
+
they are described in the manifest.
|
|
252
|
+
|
|
253
|
+
DevFlow validates structure and internal consistency only:
|
|
254
|
+
|
|
255
|
+
- required fields and non-empty values;
|
|
256
|
+
- duplicate module or layer names;
|
|
257
|
+
- references to unknown modules or layers;
|
|
258
|
+
- dependency cycles, reported as warnings;
|
|
259
|
+
- invalid YAML, unsafe paths, symlinks and oversized manifests.
|
|
260
|
+
|
|
261
|
+
It does **not** certify architectural quality. Contradictions and open
|
|
262
|
+
decisions must be recorded as specification questions.
|
|
263
|
+
|
|
264
|
+
`init` may create the template. `spec` only reads the manifest and never
|
|
265
|
+
modifies it. The manifest digest is recorded in `context.md` and in
|
|
266
|
+
`spec.md`, including an appendix with the declared manifest, so each
|
|
267
|
+
approval identifies the architecture version used. Greenfield
|
|
268
|
+
specifications require the manifest; existing-mode specifications use it
|
|
269
|
+
as an architectural constraint when it is present.
|
|
270
|
+
|
|
271
|
+
### Harnesses
|
|
272
|
+
|
|
273
|
+
| Harness | Status in 0.3.0 |
|
|
274
|
+
| --- | --- |
|
|
275
|
+
| OpenCode | Verified end-to-end in non-interactive mode |
|
|
276
|
+
| Codex | Integration files are generated, but not verified for this release |
|
|
277
|
+
| Claude Code | Integration files are generated, but not verified for this release |
|
|
278
|
+
| Kiro | Integration files are generated, but not verified for this release |
|
|
279
|
+
| `none` | Deterministic static analysis only; no agent is invoked |
|
|
280
|
+
|
|
281
|
+
Do not treat an unverified adapter as a compatibility guarantee. The
|
|
282
|
+
generated files and command lines for Codex, Claude Code and Kiro may
|
|
283
|
+
change as those integrations are tested.
|
|
284
|
+
|
|
285
|
+
For OpenCode, DevFlow generates `AGENTS.md`, `opencode.json` and the
|
|
286
|
+
agents under `.opencode/agents/`. The project-level `opencode.json` can
|
|
287
|
+
also select the model used by the agent, for example:
|
|
288
|
+
|
|
289
|
+
```json
|
|
290
|
+
{
|
|
291
|
+
"$schema": "https://opencode.ai/config.json",
|
|
292
|
+
"model": "provider/model-name"
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
DevFlow creates `opencode.json` only when it does not exist and never
|
|
297
|
+
replaces an existing OpenCode configuration.
|
|
298
|
+
|
|
299
|
+
### Permissions
|
|
300
|
+
|
|
301
|
+
`allow_workflow_write` controls writes to DevFlow artifacts.
|
|
302
|
+
`allow_spec_write` is accepted as a compatibility alias.
|
|
303
|
+
`allow_source_code_changes` is disabled by default.
|
|
304
|
+
|
|
305
|
+
DevFlow translates these settings into technical controls where the
|
|
306
|
+
harness exposes them. For OpenCode, the generated agents deny `edit`
|
|
307
|
+
outside `.devflow/specs/`, deny shell execution unless source changes are
|
|
308
|
+
explicitly allowed, and disable web access and subagents. Prompt text is
|
|
309
|
+
not treated as the only permission boundary.
|
|
310
|
+
|
|
311
|
+
When a harness cannot enforce a restriction technically, DevFlow prints
|
|
312
|
+
a warning instead of claiming that the restriction is guaranteed.
|
|
313
|
+
|
|
314
|
+
## Discovery
|
|
315
|
+
|
|
316
|
+
Discovery is separate from specification. The project context decides
|
|
317
|
+
where evidence comes from; Discovery decides whether the request is
|
|
318
|
+
ready to become a specification.
|
|
319
|
+
|
|
320
|
+
Every new `devflow spec` request creates a persistent record at
|
|
321
|
+
`.devflow/specs/<id>-<slug>/discovery.yaml`. It is plain YAML and can be
|
|
322
|
+
reviewed, edited and committed:
|
|
323
|
+
|
|
324
|
+
```yaml
|
|
325
|
+
version: 1
|
|
326
|
+
spec_id: "001"
|
|
327
|
+
change: "001-add-a-contact-form"
|
|
328
|
+
request: "Add a contact form"
|
|
329
|
+
project_mode: existing
|
|
330
|
+
status: awaiting_clarification
|
|
331
|
+
created_at: "2026-11-02T10:00:00Z"
|
|
332
|
+
updated_at: "2026-11-02T10:00:00Z"
|
|
333
|
+
questions:
|
|
334
|
+
- id: Q1
|
|
335
|
+
category: functional_scope
|
|
336
|
+
question: What should happen when the contact form is submitted?
|
|
337
|
+
reason: Persistence, confirmation and email delivery change scope.
|
|
338
|
+
blocking: true
|
|
339
|
+
status: pending
|
|
340
|
+
options: []
|
|
341
|
+
answer: null
|
|
342
|
+
answered_by: null
|
|
343
|
+
answered_at: null
|
|
344
|
+
assumptions:
|
|
345
|
+
- id: A1
|
|
346
|
+
question_id: Q1
|
|
347
|
+
value: Use `/contacto/` as the URL path.
|
|
348
|
+
reason: Internal routing must be visible before approval.
|
|
349
|
+
source: agent_default
|
|
350
|
+
status: pending_acceptance
|
|
351
|
+
accepted_by: null
|
|
352
|
+
accepted_at: null
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
Each question has a `category` and an explicit `blocking` flag. The
|
|
356
|
+
blocking categories are scope, user-visible behaviour, data and
|
|
357
|
+
persistence, security and authentication, external integrations,
|
|
358
|
+
architecture boundaries, new dependencies and deployment. A question
|
|
359
|
+
may remain pending when it is genuinely non-blocking; it does not
|
|
360
|
+
prevent specification generation.
|
|
361
|
+
|
|
362
|
+
An assumption proposed by DevFlow uses `source: agent_default` and
|
|
363
|
+
starts as `pending_acceptance`. It never becomes accepted automatically.
|
|
364
|
+
A human must set `status: accepted` with `accepted_by` and `accepted_at`,
|
|
365
|
+
or reject it and record a different decision.
|
|
366
|
+
|
|
367
|
+
While blocking decisions remain:
|
|
368
|
+
|
|
369
|
+
- `discovery.yaml` and `context.md` are written;
|
|
370
|
+
- no `spec.md` is generated;
|
|
371
|
+
- `devflow approve --stage spec` refuses the change;
|
|
372
|
+
- the workflow status is `awaiting_clarification`.
|
|
373
|
+
|
|
374
|
+
Answer the questions in the file, or run an interactive harness, then
|
|
375
|
+
resume:
|
|
376
|
+
|
|
377
|
+
```bash
|
|
378
|
+
devflow spec --continue 006
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
`--continue` never regenerates or overwrites an approved specification.
|
|
382
|
+
It reuses a current, valid specification when its Discovery digest still
|
|
383
|
+
matches. If an answer changes before approval, DevFlow marks the old
|
|
384
|
+
specification stale, preserves it under `history/`, and generates a new
|
|
385
|
+
specification bound to the new Discovery digest.
|
|
386
|
+
|
|
387
|
+
The deterministic `--no-agent` path follows the same rules. It generates
|
|
388
|
+
Discovery, records it, and stops when a blocking decision remains. It
|
|
389
|
+
never invents an answer to continue.
|
|
390
|
+
|
|
391
|
+
Changes created with `0.2.0` that have no `discovery.yaml` remain
|
|
392
|
+
approvable as legacy changes, with an explicit warning. New changes
|
|
393
|
+
require Discovery.
|
|
394
|
+
|
|
395
|
+
## Workflow
|
|
396
|
+
|
|
397
|
+
1. Initialize the project with `devflow init`.
|
|
398
|
+
2. Create a change and run Discovery.
|
|
399
|
+
3. Answer blocking questions and accept or reject assumptions.
|
|
400
|
+
4. Generate the specification with `devflow spec --continue <id>`.
|
|
401
|
+
5. Review `spec.md` and resolve any remaining non-blocking questions.
|
|
402
|
+
6. Record the approval.
|
|
403
|
+
7. Inspect the state, artifacts and approval digests.
|
|
404
|
+
|
|
405
|
+
Available commands in `0.3.0`:
|
|
406
|
+
|
|
407
|
+
| Command | Status |
|
|
408
|
+
| --- | --- |
|
|
409
|
+
| `devflow init` | Implemented |
|
|
410
|
+
| `devflow spec` | Implemented: Discovery, specification, and `--continue` |
|
|
411
|
+
| `devflow approve <id> --stage spec` | Implemented |
|
|
412
|
+
| `devflow status <id>` | Implemented |
|
|
413
|
+
| `devflow version` | Implemented |
|
|
414
|
+
| `devflow plan` | Not implemented |
|
|
415
|
+
| `devflow approve <id> --stage plan` | Rejected |
|
|
416
|
+
| `devflow implement` | Not implemented |
|
|
417
|
+
| `devflow review` | Not implemented |
|
|
418
|
+
| `devflow approve <id> --stage review` | Rejected |
|
|
419
|
+
|
|
420
|
+
There is no separate `execute` command. `approve` is a human
|
|
421
|
+
authorization and never changes code. When the `implement` stage is
|
|
422
|
+
added, it will be the technical execution command, and it will remain
|
|
423
|
+
separate from approval.
|
|
424
|
+
|
|
425
|
+
### Start, resume and generate a specification
|
|
426
|
+
|
|
427
|
+
Start a new change:
|
|
428
|
+
|
|
429
|
+
```bash
|
|
430
|
+
devflow spec "Add a GET /patients endpoint that returns JSON"
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
The command:
|
|
434
|
+
|
|
435
|
+
1. loads and validates the configuration;
|
|
436
|
+
2. loads the configured profiles and constitution;
|
|
437
|
+
3. builds the context for the effective project mode (`existing` by
|
|
438
|
+
default, or `greenfield`);
|
|
439
|
+
4. creates a persistent `discovery.yaml` with classified questions and
|
|
440
|
+
proposed assumptions;
|
|
441
|
+
5. writes the deterministic evidence or declared architecture to
|
|
442
|
+
`context.md`;
|
|
443
|
+
6. stops without `spec.md` when a blocking decision remains;
|
|
444
|
+
7. if Discovery is complete, invokes the selected harness with the
|
|
445
|
+
shared DevFlow prompt, validates the returned specification, and
|
|
446
|
+
binds it to the Discovery digest;
|
|
447
|
+
8. writes `spec.md` and registers the Discovery and specification
|
|
448
|
+
digests in the event log and the workflow projection.
|
|
449
|
+
|
|
450
|
+
Resume an existing change:
|
|
451
|
+
|
|
452
|
+
```bash
|
|
453
|
+
devflow spec --continue 006
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
`--continue` is not a new specification. It reuses the stored request
|
|
457
|
+
and project mode, loads Discovery, and stops until blocking decisions
|
|
458
|
+
are resolved. It reuses a current validated specification when the
|
|
459
|
+
Discovery digest still matches; otherwise it archives the old
|
|
460
|
+
specification and generates a new one.
|
|
461
|
+
|
|
462
|
+
For an existing project, DevFlow inspects relevant code and
|
|
463
|
+
dependencies. For Greenfield, it uses the declared architecture and
|
|
464
|
+
does not search for code or invent code references.
|
|
465
|
+
|
|
466
|
+
Useful options:
|
|
467
|
+
|
|
468
|
+
```bash
|
|
469
|
+
devflow spec "Description" --harness opencode --mode non-interactive
|
|
470
|
+
devflow spec "Description" --no-agent
|
|
471
|
+
devflow spec "Change in a real project" --project-mode existing
|
|
472
|
+
devflow spec "Create a new service" --project-mode greenfield
|
|
473
|
+
devflow spec --continue 006
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
If the harness is unavailable, fails, or returns an invalid document,
|
|
477
|
+
DevFlow writes a deterministic draft and reports the reason. The command
|
|
478
|
+
remains usable in CI and on machines without an AI harness, but the draft
|
|
479
|
+
still requires human review. A request that is not ready never receives
|
|
480
|
+
a silent deterministic specification: Discovery stops instead.
|
|
481
|
+
|
|
482
|
+
### Check status
|
|
483
|
+
|
|
484
|
+
```bash
|
|
485
|
+
devflow status 001
|
|
486
|
+
devflow status 001-add-a-get-patients-endpoint
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
`status` shows the workflow state, registered artifacts and digests,
|
|
490
|
+
approvals, stale artifacts and orphan files. It reconciles
|
|
491
|
+
`workflow.yaml` from `events.jsonl` before reporting.
|
|
492
|
+
|
|
493
|
+
### Approve the specification
|
|
494
|
+
|
|
495
|
+
```bash
|
|
496
|
+
devflow approve 001 --stage spec
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
Approval is explicit and binds the decision to the current artifact
|
|
500
|
+
digests. For a `0.3.0` change it binds `spec.md`, `discovery.yaml` and,
|
|
501
|
+
when a manifest applies, the architecture manifest digest. Repeating the
|
|
502
|
+
same approval is a no-op. If an artifact changes after validation,
|
|
503
|
+
DevFlow marks it stale and refuses approval until it is regenerated and
|
|
504
|
+
validated again.
|
|
505
|
+
|
|
506
|
+
Discovery must be complete before approval. If it is not, approval fails
|
|
507
|
+
and names the pending questions and assumptions. Legacy `0.2.0` changes
|
|
508
|
+
without `discovery.yaml` remain approvable with a warning.
|
|
509
|
+
|
|
510
|
+
Only the `spec` stage is available in `0.3.0`. `--stage plan` and
|
|
511
|
+
`--stage review` are rejected. There are no `plan`, `implement` or
|
|
512
|
+
`review` commands in this release.
|
|
513
|
+
|
|
514
|
+
## Generated files
|
|
515
|
+
|
|
516
|
+
```text
|
|
517
|
+
my-project/
|
|
518
|
+
├── .devflow/
|
|
519
|
+
│ ├── config.yaml
|
|
520
|
+
│ ├── architecture.yaml # declared architecture (Greenfield)
|
|
521
|
+
│ ├── .specs.lock # serializes specification id assignment
|
|
522
|
+
│ ├── constitution/
|
|
523
|
+
│ │ ├── constitution.md
|
|
524
|
+
│ │ ├── code-standards.md
|
|
525
|
+
│ │ ├── architecture.md
|
|
526
|
+
│ │ └── django-standards.md # only when the profile is enabled
|
|
527
|
+
│ └── specs/
|
|
528
|
+
│ └── 001-add-patients-endpoint/
|
|
529
|
+
│ ├── discovery.yaml # persistent questions and answers
|
|
530
|
+
│ ├── context.md
|
|
531
|
+
│ ├── spec.md # only when Discovery is complete
|
|
532
|
+
│ ├── workflow.yaml # projection of events.jsonl
|
|
533
|
+
│ ├── events.jsonl # append-only source of truth
|
|
534
|
+
│ └── .lock # per-change advisory lock
|
|
535
|
+
├── AGENTS.md
|
|
536
|
+
├── opencode.json # when OpenCode is selected
|
|
537
|
+
└── .opencode/agents/ # when OpenCode is selected
|
|
538
|
+
```
|
|
539
|
+
|
|
540
|
+
All managed files are identifiable: Markdown files contain
|
|
541
|
+
`<!-- devflow:managed -->`, and JSON files contain `"devflowManaged":
|
|
542
|
+
true`. Unmanaged files with the same names are left untouched and
|
|
543
|
+
reported.
|
|
544
|
+
|
|
545
|
+
## How approvals and history work
|
|
546
|
+
|
|
547
|
+
`events.jsonl` is the source of truth. `workflow.yaml` is only a
|
|
548
|
+
projection: if it is deleted, lags behind or disagrees with the event log,
|
|
549
|
+
DevFlow rebuilds or rejects it rather than trusting it.
|
|
550
|
+
|
|
551
|
+
```text
|
|
552
|
+
generated -> validated -> approved
|
|
553
|
+
| |
|
|
554
|
+
+-> rejected +-> stale
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
- An approval stores the artifact kind and its SHA-256 digest.
|
|
558
|
+
- Editing an approved artifact makes it stale.
|
|
559
|
+
- A stale, unvalidated or orphan artifact cannot be approved.
|
|
560
|
+
- Semantic validation rejects malformed or inconsistent histories.
|
|
561
|
+
- Artifact and state writes are atomic; a failed write does not leave a
|
|
562
|
+
partially written managed file.
|
|
563
|
+
- Writes are restricted to the project and the configured directories.
|
|
564
|
+
Symlinks that escape the project are rejected or ignored.
|
|
565
|
+
- Specification directory allocation is serialized with a lock, so two
|
|
566
|
+
concurrent runs do not receive the same numeric id.
|
|
567
|
+
|
|
568
|
+
The event log is local and append-only, not cryptographically signed. A
|
|
569
|
+
user with full filesystem access can modify it; DevFlow detects
|
|
570
|
+
structural and semantic inconsistency, not deliberate tampering by an
|
|
571
|
+
administrator.
|
|
572
|
+
|
|
573
|
+
## Updating DevFlow
|
|
574
|
+
|
|
575
|
+
```bash
|
|
576
|
+
pip install --upgrade devflow-toolkit
|
|
577
|
+
devflow version
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
Then run `devflow init` again in each project. The update:
|
|
581
|
+
|
|
582
|
+
- restores missing constitution documents;
|
|
583
|
+
- refreshes managed integration files;
|
|
584
|
+
- preserves existing constitution documents, specifications,
|
|
585
|
+
approvals and event logs.
|
|
586
|
+
|
|
587
|
+
Review `.devflow/config.yaml` after a major upgrade, because new options
|
|
588
|
+
may have been added. DevFlow does not silently rewrite user-modified
|
|
589
|
+
configuration.
|
|
590
|
+
|
|
591
|
+
## Known limitations
|
|
592
|
+
|
|
593
|
+
- Only the specification stage is implemented. Planning,
|
|
594
|
+
implementation and review are not available.
|
|
595
|
+
- Greenfield mode produces a specification from a declared
|
|
596
|
+
architecture. It does not scaffold a project, generate application
|
|
597
|
+
code, create Docker or cloud infrastructure, or implement tasks.
|
|
598
|
+
- DevFlow validates the structure of the architecture manifest. It does
|
|
599
|
+
not certify that the architecture is correct, complete or appropriate.
|
|
600
|
+
- Only OpenCode has been verified end-to-end. Codex, Claude Code and
|
|
601
|
+
Kiro adapters are unverified scaffolds for future releases.
|
|
602
|
+
- Interactive harness mode exists, but the verified release path is
|
|
603
|
+
OpenCode non-interactive mode. Interactive mode requires a terminal.
|
|
604
|
+
- Without an available harness, output is produced by deterministic
|
|
605
|
+
static analysis. It is a starting draft, not a substitute for human
|
|
606
|
+
review.
|
|
607
|
+
- Static analysis is heuristic: it finds likely affected files, not a
|
|
608
|
+
complete impact map.
|
|
609
|
+
- DevFlow is POSIX-only in this release.
|
|
610
|
+
- The package does not provide a hosted service, telemetry or remote
|
|
611
|
+
synchronization. All state stays in the project.
|
|
612
|
+
|
|
613
|
+
## Development
|
|
614
|
+
|
|
615
|
+
```bash
|
|
616
|
+
python -m venv .venv
|
|
617
|
+
source .venv/bin/activate
|
|
618
|
+
pip install -e ".[dev]"
|
|
619
|
+
pytest
|
|
620
|
+
ruff check
|
|
621
|
+
python -m build
|
|
622
|
+
python -m twine check dist/*
|
|
623
|
+
```
|
|
624
|
+
|
|
625
|
+
The test suite covers the core, CLI, state replay and harness adapters.
|
|
626
|
+
Release verification additionally installs the built wheel and sdist in
|
|
627
|
+
clean virtual environments and runs the consumer workflow from outside
|
|
628
|
+
the repository.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
devflow/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
devflow/cli.py,sha256=ltV3J_ApTO0jYxQsuRAhxFzKVOBR8N-sMv2BUUbklI4,965
|
|
3
|
+
devflow/adapters/__init__.py,sha256=WcsjXQTKzHNzMAHx82-sdJQeR3ceHRVqLWTUtRlaraE,867
|
|
4
|
+
devflow/adapters/agents.py,sha256=4d54hDfBgnIP4zOKcZqAG-Qa-jfuuxzFL-akZS2qYtw,1309
|
|
5
|
+
devflow/adapters/base.py,sha256=YggY_IwHExdybl5S9NjwZSlmmcw9Y6z7DhQsl3JLvXs,2055
|
|
6
|
+
devflow/adapters/claude_code.py,sha256=7eM1Wc8L5rALBdcJin5aVn3M5vynj6yRXzsJdISwpxA,3140
|
|
7
|
+
devflow/adapters/codex.py,sha256=Zq2O805HiljC-zTQYhm76sIK63DamTiwRUyOt8S2Sk8,3026
|
|
8
|
+
devflow/adapters/detector.py,sha256=92BkNAvWs2Vh8H6xJzMweBDCw6yuYVg7sV4LoSZ8KFo,3291
|
|
9
|
+
devflow/adapters/instructions.py,sha256=LanvRhv-ZLtt_sjmE2tcX0br-aEn7GDisdUEG4YIsnE,7379
|
|
10
|
+
devflow/adapters/kiro.py,sha256=8l5y7ZYffg_T9eciM28NKGHil_zgdT96mAdYK4oBZ0U,6111
|
|
11
|
+
devflow/adapters/opencode.py,sha256=DonmvAKyWK2v5-X2XrL0n2iptFp7qLgOlh-X8n_8I-w,6492
|
|
12
|
+
devflow/adapters/registry.py,sha256=NLd_tf7dAiZUa6gbQFcwPogurZyjbMNbzjjXozAD4xs,1177
|
|
13
|
+
devflow/commands/__init__.py,sha256=yOLtd_4R4xdlMgAzihzIT35oyV_qcz0br-aoLebRj1c,157
|
|
14
|
+
devflow/commands/approve.py,sha256=oknp1Gd05I8sNqqU4W6q1BDdUk9feuxcHlxltoGZDJM,2740
|
|
15
|
+
devflow/commands/harness.py,sha256=r_RSAi7gXK8QNucC6eV-RzXHJycmmR03dzihqLVgdiU,2791
|
|
16
|
+
devflow/commands/init.py,sha256=Tv-YZeR8jGcHeIG9cHA5dFQDkpsyFC5Iw7nHMsRDvQQ,14416
|
|
17
|
+
devflow/commands/spec.py,sha256=JJzYFFNUYy1U3oC_LS6lfBnmD6yZBq7RR2Yj4_n7KcM,13960
|
|
18
|
+
devflow/commands/status.py,sha256=HtBCIF8U0bmkyS6wS7IEvggo89FzGRGBCsFfPrKzLpU,4369
|
|
19
|
+
devflow/core/__init__.py,sha256=hN7i4-PDaZ7y4P8qRpZl_lJvIiPyQaN1TDGnw2BecYU,427
|
|
20
|
+
devflow/core/architecture.py,sha256=qllllsUVqA76LiSU6z_s4U8dxMcs6ClKXU16HxI3yOI,13692
|
|
21
|
+
devflow/core/clock.py,sha256=KZROv6o51Ln1EzK00ySCxfc7WPZqPlaQhFfjfdc_TMY,1651
|
|
22
|
+
devflow/core/config.py,sha256=yypUaKXaAM0sqRdLKKtuJ1hHZtRQYzgzBNELsOJQpVA,20075
|
|
23
|
+
devflow/core/constitution.py,sha256=nPHyy7BuIyyqkn4y85UyWn2E7f5AWHbg4iZ0frF9SfE,4581
|
|
24
|
+
devflow/core/discovery.py,sha256=qqFmVdrRF9tViQtuvZPK2JHF5C9ddpZT1Lu3YsasCro,34246
|
|
25
|
+
devflow/core/ports.py,sha256=R6ybjAdJEdtTKFc4FMFTX0TVwRfDwPoWCsu-BHrhI5A,4071
|
|
26
|
+
devflow/core/profile_manager.py,sha256=QnnJka2KIKD2tCSWJkGTOUEFMgmQT0Z9Qv173JKWKHw,8937
|
|
27
|
+
devflow/core/project.py,sha256=SINU6KSRIpX5rPlPy8nWMfQuHas_VF1bAIVafhbcgCg,13330
|
|
28
|
+
devflow/core/spec_workflow.py,sha256=TEGVzMTNScTfZjV0ttfCtXkuUqOc4u29dCCrbw-cUlc,28447
|
|
29
|
+
devflow/core/specification.py,sha256=aHAL_U8Tl0YBokUJKneqUyCPenY6xtcPlZUgKmUsEMw,65719
|
|
30
|
+
devflow/core/artifacts/__init__.py,sha256=gt9xahPynoxv75FMq1ZJx91ILTIv4ExuvX1Ymrxwr2c,627
|
|
31
|
+
devflow/core/artifacts/errors.py,sha256=hwZxnLFcUTtEjDWtN6rUCkM69EN19LGVlc6HD-pNZyk,493
|
|
32
|
+
devflow/core/artifacts/models.py,sha256=xJjmY8jUAHxqYN9u1JEu8CbJB-IJg1xb9P-LDaP5_Hw,2049
|
|
33
|
+
devflow/core/artifacts/store.py,sha256=ZHAhWAFiqtviwhpfQ0GDkizndpcqtpU0opTbsSJKrWA,4167
|
|
34
|
+
devflow/core/state/__init__.py,sha256=PiHKck1ZzUTSNvZBrFnk1O20godD2-Ah1hsEku1OR78,1545
|
|
35
|
+
devflow/core/state/errors.py,sha256=dgF-x4TCxQTXc1OifyT8UZSU-0PBhATjO1x6OTMagac,1017
|
|
36
|
+
devflow/core/state/events.py,sha256=IfwFCC0jbrQsH1tzADyqwm8HtWo5fR7QDD85M6JH8N0,20698
|
|
37
|
+
devflow/core/state/locator.py,sha256=J6ZnVzcY_KzwKqBXbAOnfG9FrRzSCaYMqFeMQ7ptjIc,3256
|
|
38
|
+
devflow/core/state/lock.py,sha256=94llvwHtCc5WOw-Uq8kDCu4iOBpRM4ccp6Q6fLZpYZ0,2089
|
|
39
|
+
devflow/core/state/manager.py,sha256=eCCylS-qcECTGOBJi_qS54nv86u-bYKMcNauHDz7sFk,27850
|
|
40
|
+
devflow/core/state/models.py,sha256=4GTrS34ymbJIyBeZkcCi0z0e1bsq67vdxRSnSQ9O3gc,4654
|
|
41
|
+
devflow/core/state/transitions.py,sha256=Go0zLhxcujWhaZEGg7JMqcC_UJU_nEFEBbpKIqrCtrs,3581
|
|
42
|
+
devflow/models/__init__.py,sha256=hXX3IDZbHgklmuzVVlpiRs5SSPnrkO5kN1-k2hIEk7E,156
|
|
43
|
+
devflow/models/profile.py,sha256=j8KifeDQSN-wvzDJe1GGQQN9Vw7S2oncj75NNHpwpZs,2001
|
|
44
|
+
devflow/models/project.py,sha256=2CAMY-mPEnkVryndNOzCURxknbZnnN2MYuEE-RIUcp0,1303
|
|
45
|
+
devflow/profiles/ai-rag/profile.yaml,sha256=ut4c8DBDQyI_Aoe1Gbvu46A3n-wBcGKcj84Zt_0Ghac,458
|
|
46
|
+
devflow/profiles/ai-rag/constitution/ai-rag-standards.md,sha256=sU-uM9iH50_xaF0vzqYNggIbvEnzYYCgaY7HdzOB6HY,1749
|
|
47
|
+
devflow/profiles/base/profile.yaml,sha256=_V3Y51Rl9J5PjXwBAleD1I6iiwVuDRu81bYILfsbpCE,249
|
|
48
|
+
devflow/profiles/base/constitution/architecture.md,sha256=gcuRWaV1uETI9_yF0w2egcFOU8KQzywDFPb8rHlek90,1712
|
|
49
|
+
devflow/profiles/base/constitution/code-standards.md,sha256=mTABWYkqHv8oDouxu-fZbzpFMEU1DZCniK7CzV5bPr4,2484
|
|
50
|
+
devflow/profiles/base/constitution/constitution.md,sha256=5-HcB2jRE_RVt1FeNKCtfQXpTxchI3-Zaq2dz5kstto,2706
|
|
51
|
+
devflow/profiles/django-backend/profile.yaml,sha256=SNj7a3yamdJx-P69GvIJmLkC2svOs6NheY8eA90lucg,358
|
|
52
|
+
devflow/profiles/django-backend/constitution/django-standards.md,sha256=0M-XmxOpEmgIadcaVdf6OVmll8Oec0jEjcJ4C8MfwhQ,2052
|
|
53
|
+
devflow/profiles/fastapi-backend/profile.yaml,sha256=5_b-zWSX0HV-tw_2ntRCSa4DyP3NUqYWmxOh55pXYmc,321
|
|
54
|
+
devflow/profiles/fastapi-backend/constitution/fastapi-standards.md,sha256=iFKib4i_9z4wBQ9thl-uftg5g-CHwvmFWzMtLgA7CBk,1949
|
|
55
|
+
devflow/prompts/__init__.py,sha256=gLMUlyhaiEgTQ_cHsi01c5EtUzXyUNEHz6pKbA0disw,6582
|
|
56
|
+
devflow/prompts/discovery.md,sha256=rwuCgD70yhFCw3MbygPr5jOxGof2_naKcKUVOlvmRRc,3716
|
|
57
|
+
devflow/prompts/spec.greenfield.md,sha256=sVuEb_Diqwwz_I1AGme29uvVfSzp8_8hfPC00gDkOMI,4678
|
|
58
|
+
devflow/prompts/spec.md,sha256=nyDcVVFrgC2Q5PiUc4yZbM_SUdRMiBvQW-GB6hfU-8Y,3346
|
|
59
|
+
devflow_toolkit-0.3.0.dist-info/METADATA,sha256=l74ZavMpl7CC3W4pSdVFv9gflYePsyVJEXBVQZenf7U,22306
|
|
60
|
+
devflow_toolkit-0.3.0.dist-info/WHEEL,sha256=2iZrJkDIkeDh0k9SikKMqFuRP-ua6mb4Ir1AsER4BEw,87
|
|
61
|
+
devflow_toolkit-0.3.0.dist-info/entry_points.txt,sha256=wPmqE1081vi8s3xf-Wfzfvpl-44IKgwx7OGoLEK3u7o,44
|
|
62
|
+
devflow_toolkit-0.3.0.dist-info/licenses/LICENSE,sha256=Wa04lstC8Goe4b9IYfEYWB2k7nokYBejZl6NdyAl8rA,1077
|
|
63
|
+
devflow_toolkit-0.3.0.dist-info/RECORD,,
|