donna 0.2.0__py3-none-any.whl → 0.2.2__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.
- donna/artifacts/intro.md +39 -0
- donna/artifacts/research/specs/report.md +163 -0
- donna/artifacts/research/work/research.md +198 -0
- donna/artifacts/rfc/specs/request_for_change.md +270 -0
- donna/artifacts/rfc/work/create.md +120 -0
- donna/artifacts/rfc/work/do.md +109 -0
- donna/artifacts/rfc/work/plan.md +68 -0
- donna/artifacts/usage/artifacts.md +55 -12
- donna/artifacts/usage/cli.md +114 -39
- donna/artifacts/usage/worlds.md +8 -2
- donna/cli/__main__.py +1 -1
- donna/cli/commands/artifacts.py +104 -17
- donna/cli/commands/sessions.py +8 -8
- donna/cli/commands/workspaces.py +42 -0
- donna/cli/errors.py +18 -0
- donna/cli/types.py +16 -9
- donna/cli/utils.py +2 -2
- donna/core/errors.py +1 -11
- donna/core/result.py +5 -8
- donna/core/utils.py +0 -3
- donna/lib/__init__.py +4 -0
- donna/lib/sources.py +1 -1
- donna/lib/worlds.py +2 -2
- donna/machine/action_requests.py +0 -5
- donna/machine/artifacts.py +8 -6
- donna/machine/primitives.py +5 -5
- donna/machine/sessions.py +13 -5
- donna/machine/state.py +4 -4
- donna/machine/tasks.py +4 -18
- donna/machine/templates.py +4 -2
- donna/primitives/artifacts/specification.py +13 -2
- donna/primitives/artifacts/workflow.py +11 -2
- donna/primitives/directives/list.py +86 -0
- donna/primitives/directives/view.py +52 -11
- donna/primitives/operations/finish_workflow.py +13 -2
- donna/primitives/operations/output.py +87 -0
- donna/primitives/operations/request_action.py +3 -9
- donna/primitives/operations/run_script.py +2 -2
- donna/protocol/utils.py +22 -0
- donna/workspaces/artifacts.py +238 -0
- donna/{world → workspaces}/artifacts_discovery.py +1 -1
- donna/{world → workspaces}/config.py +18 -11
- donna/{world → workspaces}/errors.py +55 -45
- donna/workspaces/initialization.py +78 -0
- donna/{world → workspaces}/markdown.py +21 -26
- donna/{world → workspaces}/sources/base.py +2 -2
- donna/{world → workspaces}/sources/markdown.py +8 -7
- donna/{world → workspaces}/templates.py +4 -4
- donna/workspaces/tmp.py +51 -0
- donna/{world → workspaces}/worlds/base.py +6 -3
- donna/{world → workspaces}/worlds/filesystem.py +30 -10
- donna/{world → workspaces}/worlds/python.py +12 -9
- donna-0.2.2.dist-info/METADATA +463 -0
- donna-0.2.2.dist-info/RECORD +92 -0
- {donna-0.2.0.dist-info → donna-0.2.2.dist-info}/WHEEL +1 -1
- donna/artifacts/work/do_it.md +0 -142
- donna/artifacts/work/do_it_fast.md +0 -98
- donna/artifacts/work/planning.md +0 -245
- donna/cli/commands/projects.py +0 -49
- donna/world/artifacts.py +0 -122
- donna/world/initialization.py +0 -42
- donna/world/tmp.py +0 -33
- donna/world/worlds/__init__.py +0 -0
- donna-0.2.0.dist-info/METADATA +0 -44
- donna-0.2.0.dist-info/RECORD +0 -85
- /donna/{artifacts/work → workspaces}/__init__.py +0 -0
- /donna/{world → workspaces}/sources/__init__.py +0 -0
- /donna/{world → workspaces/worlds}/__init__.py +0 -0
- {donna-0.2.0.dist-info → donna-0.2.2.dist-info}/entry_points.txt +0 -0
- {donna-0.2.0.dist-info → donna-0.2.2.dist-info}/licenses/LICENSE +0 -0
donna/artifacts/work/do_it.md
DELETED
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
# Meta Work Loop
|
|
2
|
-
|
|
3
|
-
```toml donna
|
|
4
|
-
kind = "donna.lib.workflow"
|
|
5
|
-
start_operation_id = "start"
|
|
6
|
-
```
|
|
7
|
-
|
|
8
|
-
General purpose work planning and execution workflow. Use it when you need to do complex work and there is no more specific workflow available.
|
|
9
|
-
|
|
10
|
-
## Start Work
|
|
11
|
-
|
|
12
|
-
```toml donna
|
|
13
|
-
id = "start"
|
|
14
|
-
kind = "donna.lib.request_action"
|
|
15
|
-
fsm_mode = "start"
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
1. Read the specification `{{ donna.lib.view("donna:work:planning") }}` if you haven't done it yet.
|
|
19
|
-
2. Read the specification `{{ donna.lib.view("donna:usage:artifacts") }}` if you haven't done it yet.
|
|
20
|
-
3. If the developer hasn't provided you a description of the work for this session, ask them to provide it.
|
|
21
|
-
4. Create new session-level specification `session:work_scope` with developer-provided description of the work to be done.
|
|
22
|
-
5. `{{ donna.lib.goto("create_work_description") }}`
|
|
23
|
-
|
|
24
|
-
## Create Work Description
|
|
25
|
-
|
|
26
|
-
```toml donna
|
|
27
|
-
id = "create_work_description"
|
|
28
|
-
kind = "donna.lib.request_action"
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
1. Read the specification `{{ donna.lib.view("donna:work:planning") }}` if you haven't done it yet.
|
|
32
|
-
2. Read the specification `{{ donna.lib.view("donna:usage:artifacts") }}` if you haven't done it yet.
|
|
33
|
-
3. Formulate a concise high-level description of the work to be done, based on the developer-provided description.
|
|
34
|
-
4. Add this description to the `session:work_scope`.
|
|
35
|
-
5. `{{ donna.lib.goto("list_primary_goals") }}`
|
|
36
|
-
|
|
37
|
-
## List Primary Goals
|
|
38
|
-
|
|
39
|
-
```toml donna
|
|
40
|
-
id = "list_primary_goals"
|
|
41
|
-
kind = "donna.lib.request_action"
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
1. Read the specification `{{ donna.lib.view("donna:work:planning") }}` if you haven't done it yet.
|
|
45
|
-
2. Read the specification `{{ donna.lib.view("donna:usage:artifacts") }}` if you haven't done it yet.
|
|
46
|
-
3. If you can add more goals based on existing `{{ donna.lib.view("session:work_scope") }}` add them to the specification.
|
|
47
|
-
4. If you can polish the existing goals according to the quality criteria in the `{{ donna.lib.view("donna:work:planning") }}` do it.
|
|
48
|
-
5. `{{ donna.lib.goto("list_objectives") }}`
|
|
49
|
-
|
|
50
|
-
## List Objectives
|
|
51
|
-
|
|
52
|
-
```toml donna
|
|
53
|
-
id = "list_objectives"
|
|
54
|
-
kind = "donna.lib.request_action"
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
You MUST list objectives that need to be achieved to complete each goal.
|
|
58
|
-
|
|
59
|
-
1. Read the specification `{{ donna.lib.view("donna:work:planning") }}` if you haven't done it yet.
|
|
60
|
-
2. Read the specification `{{ donna.lib.view("donna:usage:artifacts") }}` if you haven't done it yet.
|
|
61
|
-
3. If you can add more objectives based on existing `{{ donna.lib.view("session:work_scope") }}` add them to the specification.
|
|
62
|
-
4. If you can polish the existing objectives according to the quality criteria in the `{{ donna.lib.view("donna:work:planning") }}` do it.
|
|
63
|
-
5. `{{ donna.lib.goto("list_constraints") }}`
|
|
64
|
-
|
|
65
|
-
## List Constraints
|
|
66
|
-
|
|
67
|
-
```toml donna
|
|
68
|
-
id = "list_constraints"
|
|
69
|
-
kind = "donna.lib.request_action"
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
1. Read the specification `{{ donna.lib.view("donna:work:planning") }}` if you haven't done it yet.
|
|
73
|
-
2. Read the specification `{{ donna.lib.view("donna:usage:artifacts") }}` if you haven't done it yet.
|
|
74
|
-
3. If you can add more constraints based on existing `{{ donna.lib.view("session:work_scope") }}` add them to the specification.
|
|
75
|
-
4. If you can polish the existing constraints according to the quality criteria in the `{{ donna.lib.view("donna:work:planning") }}` do it.
|
|
76
|
-
5. `{{ donna.lib.goto("list_acceptance_criteria") }}`
|
|
77
|
-
|
|
78
|
-
## List Acceptance Criteria
|
|
79
|
-
|
|
80
|
-
```toml donna
|
|
81
|
-
id = "list_acceptance_criteria"
|
|
82
|
-
kind = "donna.lib.request_action"
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
1. Read the specification `{{ donna.lib.view("donna:work:planning") }}` if you haven't done it yet.
|
|
86
|
-
2. Read the specification `{{ donna.lib.view("donna:usage:artifacts") }}` if you haven't done it yet.
|
|
87
|
-
3. If you can add more acceptance criteria based on existing `{{ donna.lib.view("session:work_scope") }}` add them to the specification.
|
|
88
|
-
4. If you can polish the existing acceptance criteria according to the quality criteria in the `{{ donna.lib.view("donna:work:planning") }}` do it.
|
|
89
|
-
5. `{{ donna.lib.goto("list_deliverables") }}`
|
|
90
|
-
|
|
91
|
-
## List Deliverables
|
|
92
|
-
|
|
93
|
-
```toml donna
|
|
94
|
-
id = "list_deliverables"
|
|
95
|
-
kind = "donna.lib.request_action"
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
1. Read the specification `{{ donna.lib.view("donna:work:planning") }}` if you haven't done it yet.
|
|
99
|
-
2. Read the specification `{{ donna.lib.view("donna:usage:artifacts") }}` if you haven't done it yet.
|
|
100
|
-
3. If you can list more deliverables based on existing `{{ donna.lib.view("session:work_scope") }}` add them to the specification.
|
|
101
|
-
4. If you can polish the existing deliverables according to the quality criteria in the `{{ donna.lib.view("donna:work:planning") }}` do it.
|
|
102
|
-
5. `{{ donna.lib.goto("prepare_plan") }}`
|
|
103
|
-
|
|
104
|
-
## Prepare Work Plan
|
|
105
|
-
|
|
106
|
-
```toml donna
|
|
107
|
-
id = "prepare_plan"
|
|
108
|
-
kind = "donna.lib.request_action"
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
1. Read the specification `{{ donna.lib.view("donna:work:planning") }}` if you haven't done it yet.
|
|
112
|
-
2. Read the specification `{{ donna.lib.view("donna:usage:artifacts") }}` if you haven't done it yet.
|
|
113
|
-
3. Read the specification `{{ donna.lib.view("session:work_scope") }}` if you haven't done it yet.
|
|
114
|
-
4. Create new session-level workflow `session:work_execution` according to the scope of work you have defined.
|
|
115
|
-
5. `{{ donna.lib.goto("execute_plan") }}`
|
|
116
|
-
|
|
117
|
-
## Execute Plan
|
|
118
|
-
|
|
119
|
-
```toml donna
|
|
120
|
-
id = "execute_plan"
|
|
121
|
-
kind = "donna.lib.request_action"
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
1. Run workflow `session:work_execution` to execute the work according to the plan.
|
|
125
|
-
2. `{{ donna.lib.goto("groom_work") }}`
|
|
126
|
-
|
|
127
|
-
## Groom Work
|
|
128
|
-
|
|
129
|
-
```toml donna
|
|
130
|
-
id = "groom_work"
|
|
131
|
-
kind = "donna.lib.request_action"
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
1. Run the grooming workflow to ensure that the result is polished, clean, and ready for review.
|
|
135
|
-
2. `{{ donna.lib.goto("finish") }}`
|
|
136
|
-
|
|
137
|
-
## Finish
|
|
138
|
-
|
|
139
|
-
```toml donna
|
|
140
|
-
id = "finish"
|
|
141
|
-
kind = "donna.lib.finish"
|
|
142
|
-
```
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
# Show Workflow Spec + Schema
|
|
2
|
-
|
|
3
|
-
```toml donna
|
|
4
|
-
kind = "donna.lib.workflow"
|
|
5
|
-
start_operation_id = "read_workflow_source"
|
|
6
|
-
```
|
|
7
|
-
|
|
8
|
-
<!-- This is a temporary worflow, later Donna should have a specialized command to display the spec -->
|
|
9
|
-
|
|
10
|
-
This workflow guides an agent through loading a workflow artifact source, choosing the correct FSM graph DSL, and producing a concise schema summary with a graph and per-operation descriptions.
|
|
11
|
-
|
|
12
|
-
## Read workflow source
|
|
13
|
-
|
|
14
|
-
```toml donna
|
|
15
|
-
id = "read_workflow_source"
|
|
16
|
-
kind = "donna.lib.request_action"
|
|
17
|
-
fsm_mode = "start"
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
1. Identify the full workflow artifact id to summarize from the developer request (for example: `project:work:grooming`).
|
|
21
|
-
2. If the workflow id is missing or ambiguous, ask the developer to provide the exact id, then repeat this operation.
|
|
22
|
-
3. Fetch the workflow artifact source with:
|
|
23
|
-
- `./bin/donna.sh artifacts fetch '<workflow-id>'`
|
|
24
|
-
4. Read the fetched source from the path printed by the command to capture:
|
|
25
|
-
- Workflow name (H1 title) and short description.
|
|
26
|
-
- The start operation (from `start_operation_id` in the workflow head config, which must be marked with `fsm_mode = "start"`).
|
|
27
|
-
- Each operation `id`, `kind`, and any {% raw %}`{{ donna.lib.goto(...) }}`{% endraw %} transitions in its body.
|
|
28
|
-
5. Continue to {{ donna.lib.goto("select_fsm_dsl") }}.
|
|
29
|
-
|
|
30
|
-
## Select FSM graph DSL
|
|
31
|
-
|
|
32
|
-
```toml donna
|
|
33
|
-
id = "select_fsm_dsl"
|
|
34
|
-
kind = "donna.lib.request_action"
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
1. Determine whether the developer requested a specific FSM graph DSL (from the original request or provided inputs).
|
|
38
|
-
2. If a DSL is specified, record it verbatim for rendering.
|
|
39
|
-
3. If no DSL is specified, select Mermaid DSL.
|
|
40
|
-
4. Continue to {{ donna.lib.goto("render_schema") }}.
|
|
41
|
-
|
|
42
|
-
## Render short schema
|
|
43
|
-
|
|
44
|
-
```toml donna
|
|
45
|
-
id = "render_schema"
|
|
46
|
-
kind = "donna.lib.request_action"
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
1. Produce the schema output in the exact meta format below, using the selected DSL for the FSM graph:
|
|
50
|
-
|
|
51
|
-
```
|
|
52
|
-
# <workflow name>
|
|
53
|
-
|
|
54
|
-
<very short one sentence description of what it does>
|
|
55
|
-
|
|
56
|
-
<FSM graph description in some DSL>
|
|
57
|
-
|
|
58
|
-
<list of operations: `<id>` — <short one sentence description of what it does>
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
2. Ensure the FSM graph includes all operations and transitions, and clearly marks the start and finish operations.
|
|
62
|
-
3. For Mermaid, use a `stateDiagram-v2` or `flowchart` representation and keep node ids aligned with operation ids.
|
|
63
|
-
4. For each operation list entry, write a single concise sentence that is clean, complete, and faithful to the operation body.
|
|
64
|
-
5. Continue to {{ donna.lib.goto("refine_schema") }}.
|
|
65
|
-
|
|
66
|
-
## Refine schema output
|
|
67
|
-
|
|
68
|
-
```toml donna
|
|
69
|
-
id = "refine_schema"
|
|
70
|
-
kind = "donna.lib.request_action"
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
1. Re-read the produced schema and improve clarity and correctness without changing the required format.
|
|
74
|
-
2. Tighten wording to keep each description to a single clean sentence while still being thorough and accurate.
|
|
75
|
-
3. Ensure the DSL selection rule is reflected in the graph and described output.
|
|
76
|
-
4. Continue to {{ donna.lib.goto("validate_schema") }}.
|
|
77
|
-
|
|
78
|
-
## Validate schema output
|
|
79
|
-
|
|
80
|
-
```toml donna
|
|
81
|
-
id = "validate_schema"
|
|
82
|
-
kind = "donna.lib.request_action"
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
1. Verify the output contains the title, one-sentence description, FSM graph, and operation list in the required order.
|
|
86
|
-
2. Confirm the chosen DSL is correct (developer-specified or Mermaid by default).
|
|
87
|
-
3. Confirm each operation description is a single sentence and matches the operation purpose.
|
|
88
|
-
4. If any check fails, return to {{ donna.lib.goto("refine_schema") }}.
|
|
89
|
-
5. If all checks pass, proceed to {{ donna.lib.goto("finish") }}.
|
|
90
|
-
|
|
91
|
-
## Finish
|
|
92
|
-
|
|
93
|
-
```toml donna
|
|
94
|
-
id = "finish"
|
|
95
|
-
kind = "donna.lib.finish"
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
Workflow complete.
|
donna/artifacts/work/planning.md
DELETED
|
@@ -1,245 +0,0 @@
|
|
|
1
|
-
# Session Planning Guidelines
|
|
2
|
-
|
|
3
|
-
```toml donna
|
|
4
|
-
kind = "donna.lib.specification"
|
|
5
|
-
```
|
|
6
|
-
|
|
7
|
-
This document describes how Donna MUST plan work on a session with the help of workflows. The
|
|
8
|
-
document describes the process of planning, kinds of involved entities and requirements for them.
|
|
9
|
-
|
|
10
|
-
**This requirements MUST be applied to all planning workflows that Donna uses.**
|
|
11
|
-
|
|
12
|
-
## Overview
|
|
13
|
-
|
|
14
|
-
Donna's workflows create a plan of work on a session by iteratively polishing the set of session-level artifacts.
|
|
15
|
-
|
|
16
|
-
Artifacts are:
|
|
17
|
-
|
|
18
|
-
- `session:work_scope` — a specification that describes the scope of work to be done on the session.
|
|
19
|
-
- `session:work_execution` — a workflow that describes the step-by-step plan of work to be done on the session.
|
|
20
|
-
|
|
21
|
-
The agent MUST create and iteratively polish these artifacts until they meet all quality criteria described in this document. After the plan is ready, the agent MUST run it as a workflow.
|
|
22
|
-
|
|
23
|
-
## Work Scope Specification
|
|
24
|
-
|
|
25
|
-
The work scope specification has a standard name `session:work_scope` and describes the work to be done in the context of the current session.
|
|
26
|
-
|
|
27
|
-
The specification MUST contain the following sections:
|
|
28
|
-
|
|
29
|
-
1. `Developer request` — a copy of the original description of the work from the developer.
|
|
30
|
-
2. `Work description` — a high-level description of the work to be done, created by Donna
|
|
31
|
-
based on the developer request.
|
|
32
|
-
3. `Goals` — a list of goals that work strives to achieve.
|
|
33
|
-
4. `Objectives` — a list of specific objectives that need to be completed to achieve the goals.
|
|
34
|
-
5. `Known constraints` — a list of constraints for the session.
|
|
35
|
-
6. `Acceptance criteria` — a list of acceptance criteria for the resulted work.
|
|
36
|
-
7. `Deliverables / Artifacts` — a list of concrete deliverables / artifacts that MUST be produced.
|
|
37
|
-
|
|
38
|
-
Sections `Developer request` and `Detailed work description` are free-form text sections.
|
|
39
|
-
Sections `Goals`, `Objectives` should contain lists of items.
|
|
40
|
-
|
|
41
|
-
### "Developer Request" section requirements
|
|
42
|
-
|
|
43
|
-
- This section MUST contain the original request from the developer. The request MUST NOT be modified by Donna.
|
|
44
|
-
|
|
45
|
-
### "Work Description" section requirements
|
|
46
|
-
|
|
47
|
-
- The section MUST contain a clear professional high-level description of the work to be done based
|
|
48
|
-
on the developer's request.
|
|
49
|
-
- The section MUST be limited to a single paragraph with a few sentences.
|
|
50
|
-
- The sectino MUST explain what someone gains after these changes and how they can see it working.
|
|
51
|
-
State the user-visible behavior the task will enable.
|
|
52
|
-
|
|
53
|
-
### "Goals" section requirements
|
|
54
|
-
|
|
55
|
-
- The section MUST contain a list of high-level goals that the work strives to achieve.
|
|
56
|
-
|
|
57
|
-
The goal quality criteria:
|
|
58
|
-
|
|
59
|
-
- A goal describes a desired end state, outcome or result.
|
|
60
|
-
- A goal defines what should ultimately be true, not how to achieve it.
|
|
61
|
-
- A goal must not be defined via listing cases, states, outcomes, etc. Instead, use one of the next
|
|
62
|
-
approaches:
|
|
63
|
-
a) summarize top-layer items into a single goal;
|
|
64
|
-
b) split the goal into multiple more specific goals;
|
|
65
|
-
c) reformulate to a list of second-layer items as required properties of the top-level goal.
|
|
66
|
-
- Each goal must has clear scope and boundaries.
|
|
67
|
-
|
|
68
|
-
### "Objectives" section requirements
|
|
69
|
-
|
|
70
|
-
- The section MUST contain a list of specific objectives that need to be completed to achieve the goals.
|
|
71
|
-
|
|
72
|
-
Objective quality criteria:
|
|
73
|
-
|
|
74
|
-
- An objective MUST describe an achieved state or capability not the act of describing it.
|
|
75
|
-
- An objective MUST be phrased as "X exists / is implemented / is defined / is executable /
|
|
76
|
-
is enforced / …"
|
|
77
|
-
- An objective MUST be atomic: it MUST result in exactly one concrete deliverable: one artifact,
|
|
78
|
-
one executable, one schema, one test suite, etc.
|
|
79
|
-
- An objective is a single clear, externally observable condition of the system (not a description,
|
|
80
|
-
explanation, or analysis) that, when met, moves you closer to achieving a specific goal.
|
|
81
|
-
- An objective is a top-level unit of work whose completion results in a concrete artifact,
|
|
82
|
-
behavior, or state change that can be independently verified without reading prose.
|
|
83
|
-
- Each goal MUST have a set of objectives that, when all achieved, ensure the goal is met.
|
|
84
|
-
- Each goal MUST have 2–6 objectives, unless the goal is demonstrably trivial (≤1 artifact, no dependencies).
|
|
85
|
-
|
|
86
|
-
### "Known Constraints" section requirements
|
|
87
|
-
|
|
88
|
-
- The section MUST contain a list of known constraints that the work MUST respect.
|
|
89
|
-
|
|
90
|
-
Constraint quality criteria:
|
|
91
|
-
|
|
92
|
-
- A known constraint describes a non-negotiable limitation or requirement that the work MUST
|
|
93
|
-
respect (technical, organizational, legal, temporal, compatibility, security, operational).
|
|
94
|
-
- Each constraint MUST be derived from explicitly available inputs (the developer request, existed
|
|
95
|
-
specifications, existed code, information provided by workflows). Donna MUST NOT invent
|
|
96
|
-
constraints.
|
|
97
|
-
- Each constraint MUST be phrased as a verifiable rule using normative language: "MUST / MUST NOT /
|
|
98
|
-
SHOULD / SHOULD NOT".
|
|
99
|
-
- Each constraint MUST be atomic: one rule per record (no "and/or" bundles). If multiple rules
|
|
100
|
-
exist, split into multiple constraint records.
|
|
101
|
-
- Each constraint MUST be externally binding (something the plan must accommodate), not an
|
|
102
|
-
internal preference.
|
|
103
|
-
- Constraints MUST NOT restate goals/objectives in different words. They are bounds, not outcomes.
|
|
104
|
-
- Constraints MUST NOT contain implementation steps, designs, or proposed solutions.
|
|
105
|
-
- Constraints MUST NOT include risks, unknowns, or speculative issues.
|
|
106
|
-
- Constraints MUST be written so a reviewer can answer true/false for compliance by inspecting
|
|
107
|
-
artifacts, behavior, or configuration (not by reading explanatory prose).
|
|
108
|
-
- The section MAY be empty only if no constraints are explicitly known.
|
|
109
|
-
|
|
110
|
-
Examples:
|
|
111
|
-
|
|
112
|
-
- Good: `MUST remain compatible with Python 3.10`
|
|
113
|
-
- Good: `MUST not change public CLI flags`
|
|
114
|
-
- Good: `MUST avoid network access`
|
|
115
|
-
- Good: `MUST run on Windows + Linux`
|
|
116
|
-
- Bad: `We should do it cleanly`
|
|
117
|
-
- Bad: `Prefer elegant code`
|
|
118
|
-
- Bad: `Try to keep it simple`
|
|
119
|
-
|
|
120
|
-
### "Acceptance criteria" section requirements
|
|
121
|
-
|
|
122
|
-
- The section MUST contain a list of acceptance criteria that define how to evaluate the session's results.
|
|
123
|
-
|
|
124
|
-
Acceptance criteria quality criteria:
|
|
125
|
-
|
|
126
|
-
- An acceptance criterion describes a pass/fail condition that determines whether the session's
|
|
127
|
-
results are acceptable to a reviewer, user, or automated gate.
|
|
128
|
-
- Each criterion MUST be derived from explicitly available inputs (developer request, previous
|
|
129
|
-
sections of the plan). Donna MUST NOT invent new scope, features, constraints, or assumptions.
|
|
130
|
-
- Each criterion MUST be phrased as an externally observable, verifiable rule, using normative
|
|
131
|
-
language ("MUST / MUST NOT / SHOULD / SHOULD NOT") or an equivalent test form such as
|
|
132
|
-
Given/When/Then (Gherkin-style).
|
|
133
|
-
- Each criterion MUST be independently checkable by inspecting artifacts, running a command,
|
|
134
|
-
executing tests, or observing runtime behavior/output — not by reading explanatory prose.
|
|
135
|
-
- Each criterion MUST be atomic: one condition per record (no "and/or" bundles). If multiple
|
|
136
|
-
conditions exist, split into multiple criteria records.
|
|
137
|
-
- Criteria MUST NOT describe implementation steps, internal design decisions, or "how" to achieve the result.
|
|
138
|
-
- Criteria MUST NOT restate goals/objectives verbatim. Instead, they must state how success is
|
|
139
|
-
demonstrated (e.g., observable behavior, produced files, enforced rules, test outcomes).
|
|
140
|
-
|
|
141
|
-
Coverage rules:
|
|
142
|
-
|
|
143
|
-
- Each objective MUST have ≥1 acceptance criterion that validates it.
|
|
144
|
-
- Each acceptance criterion MUST map to at least one objective (directly or via a goal that the objective serves).
|
|
145
|
-
- Where relevant, criteria SHOULD specify concrete evaluation conditions, such as:
|
|
146
|
-
- exact CLI output/exit codes, produced artifacts and their locations;
|
|
147
|
-
- supported platforms/versions, configuration prerequisites;
|
|
148
|
-
- measurable thresholds (latency, memory, size limits), if such requirements are explicitly implied or stated.
|
|
149
|
-
- etc.
|
|
150
|
-
|
|
151
|
-
Regression rules:
|
|
152
|
-
|
|
153
|
-
- If the developer request or known constraints imply preserving existing behavior, acceptance
|
|
154
|
-
criteria SHOULD include explicit non-regression checks (what must remain unchanged).
|
|
155
|
-
- The section MUST NOT be empty.
|
|
156
|
-
|
|
157
|
-
### "Deliverables / Artifacts" section requirements
|
|
158
|
-
|
|
159
|
-
- The section MUST contain a list of concrete deliverables/artifacts that MUST be produced by the work.
|
|
160
|
-
|
|
161
|
-
Deliverable/artifact quality criteria:
|
|
162
|
-
|
|
163
|
-
- A deliverable/artifact record MUST name a concrete output that will exist after the work is
|
|
164
|
-
complete (a file, module, package, binary, schema, configuration, test suite, generated report,
|
|
165
|
-
published document, metric in the metrics storage, dashbord, etc.).
|
|
166
|
-
- Each deliverable/artifact MUST be derived from explicitly available inputs (developer request,
|
|
167
|
-
prior sections of this plan). Donna MUST NOT invent new deliverables that introduce new scope.
|
|
168
|
-
- Each deliverable/artifact MUST be externally verifiable by inspecting the repository/workspace,
|
|
169
|
-
produced files, or runtime outputs — not by reading explanatory prose.
|
|
170
|
-
- Each deliverable/artifact record MUST be phrased as an existence statement using normative
|
|
171
|
-
language, e.g. "MUST include …", "MUST produce …", "MUST add …".
|
|
172
|
-
- Each deliverable/artifact record MUST be atomic: exactly one deliverable per record (no
|
|
173
|
-
"and/or", no bundles). If multiple outputs are required, split into multiple records.
|
|
174
|
-
- Each deliverable/artifact MUST specify at least one of:
|
|
175
|
-
- an exact path/location (preferred), or
|
|
176
|
-
- an exact artifact identifier (module/package name, command name, schema name, etc.).
|
|
177
|
-
- If the deliverable is generated by running a command, the record SHOULD specify the command
|
|
178
|
-
entrypoint (e.g., via a CLI (Command-Line Interface) command name) and the expected output
|
|
179
|
-
location, without describing internal implementation steps.
|
|
180
|
-
- Deliverables MUST NOT be vague (e.g., "updated code", "better docs"). They MUST be concrete
|
|
181
|
-
enough that a reviewer can confirm presence/absence.
|
|
182
|
-
- Deliverables MUST NOT restate goals, objectives, constraints, or acceptance criteria. They must
|
|
183
|
-
list *outputs*, not outcomes or pass/fail checks.
|
|
184
|
-
- The section MUST NOT be empty.
|
|
185
|
-
|
|
186
|
-
Source files as artifacts:
|
|
187
|
-
|
|
188
|
-
- Explicitly add source files (paths) as deliverables/artifacts only if the task is specifically
|
|
189
|
-
about creating or modifying those files (e.g., "MUST add docs/cli.md …").
|
|
190
|
-
- Do not add source files as deliverables/artifacts if they are unknown at planning time (i.e. we
|
|
191
|
-
do not know which files will be changed/added). In such cases, focus on higher-level deliverables
|
|
192
|
-
(e.g., "MUST add CLI documentation" instead of listing specific files).
|
|
193
|
-
|
|
194
|
-
## Work Execution Workflow
|
|
195
|
-
|
|
196
|
-
The work execution workflow has a standard name `session:work_execution` and describes the step-by-step plan of work to be done in the context of the current session.
|
|
197
|
-
|
|
198
|
-
The workflow MUST be an artifact of kind `workflow`, see details `{{ donna.lib.view("donna:usage:artifacts") }}`. I.e. the final workflow must be a valid FSM that agent will execute with the help of `donna` tool.
|
|
199
|
-
|
|
200
|
-
Primary requirement:
|
|
201
|
-
|
|
202
|
-
1. **You MUST prefer non-linear or cyclic workflows for complex tasks instead of long linear sequences.** I.e. use loops, conditionals, parallel branches, etc. where appropriate. That should help you to apply changes iteratively, validate them early and often and to polish the results step by step. I.e. prefere an incremental/evolutionary approach over a big-bang one.
|
|
203
|
-
2. However, prefere multiple short loops over a single long loop. The approach `do everything then repeat from scratch` is a bad practice. Instead, break down the work into smaller steps that can be done, verified and polished independently.
|
|
204
|
-
3. The resulted workflow MUST ensure that there is at least 1 refine iteration will always be applied (for each loop).
|
|
205
|
-
4. Describe each operation with effort: add details, examples, behavior for edge cases, etc. Formulate each term and action precisely.
|
|
206
|
-
|
|
207
|
-
General requirements:
|
|
208
|
-
|
|
209
|
-
- Each workflow step should describe an operation dedicated to one semantically atomic task.
|
|
210
|
-
- Each operation of the workflow MUST be derived from explicitly available inputs (developer request +
|
|
211
|
-
prior plan sections). It MUST NOT introduce new scope, features, constraints, or deliverables.
|
|
212
|
-
- Each workflow operation item MUST map to ≥1 objective.
|
|
213
|
-
- Each objective MUST be covered by ≥1 workflow operation that produces the required change/artifact,
|
|
214
|
-
and where relevant by additional item(s) that validate it (tests, checks, demo run).
|
|
215
|
-
- Each workflow operation MUST be atomic: one primary action per item (no "and/or" bundles). If
|
|
216
|
-
multiple actions are needed, split into multiple items.
|
|
217
|
-
- Each workflow operation MUST be actionable and specific enough that a agent can execute it
|
|
218
|
-
without needing additional prose:
|
|
219
|
-
- It SHOULD name the component/module/subsystem affected, if known.
|
|
220
|
-
- It SHOULD name the concrete artifact(s) it will create/modify when those artifacts are already
|
|
221
|
-
known from the "Deliverables / Artifacts" section (do not invent file paths).
|
|
222
|
-
- If a command is required (e.g., a CLI (Command-Line Interface) invocation, test runner command),
|
|
223
|
-
operation SHOULD include the exact command.
|
|
224
|
-
- Workflow operation MUST NOT be vague (e.g., "Improve code quality", "Handle edge cases", "Do the thing").
|
|
225
|
-
- Workflow operations MUST respect all "Known constraints".
|
|
226
|
-
- If workflow operation includes research/design work, there results MUST be represented as concrete artifacts or changes in the `session:work_scope` and `session:work_execution` artifacts.
|
|
227
|
-
|
|
228
|
-
Verification steps:
|
|
229
|
-
|
|
230
|
-
- The workflow SHOULD include explicit verification operations that demonstrate acceptance
|
|
231
|
-
criteria, such as:
|
|
232
|
-
- adding or updating automated tests;
|
|
233
|
-
- running tests/lint/static checks (if such gates exist in the project inputs);
|
|
234
|
-
- running a minimal end-to-end command or scenario that shows the user-visible behavior.
|
|
235
|
-
- Verification MUST be phrased as executable checks (commands, test suites, observable outputs), not
|
|
236
|
-
as "Review the code" or "Make sure it works".
|
|
237
|
-
|
|
238
|
-
Examples:
|
|
239
|
-
|
|
240
|
-
- Good: "Implement the `foo` subcommand behavior to emit the required summary line for each generation."
|
|
241
|
-
- Good: "Add automated tests that assert the `foo` subcommand exit code and exact stdout lines for the sample fixture."
|
|
242
|
-
- Good: "Run `pytest -q` and confirm the new tests pass."
|
|
243
|
-
- Bad: "Implement feature and update tests and docs."
|
|
244
|
-
- Bad: "Consider performance implications."
|
|
245
|
-
- Bad: "Document the approach in detail."
|
donna/cli/commands/projects.py
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import pathlib
|
|
2
|
-
from collections.abc import Iterable
|
|
3
|
-
|
|
4
|
-
import typer
|
|
5
|
-
|
|
6
|
-
from donna.cli.application import app
|
|
7
|
-
from donna.cli.types import WorkdirOption
|
|
8
|
-
from donna.cli.utils import cells_cli, try_initialize_donna
|
|
9
|
-
from donna.domain.ids import WorldId
|
|
10
|
-
from donna.protocol.cell_shortcuts import operation_succeeded
|
|
11
|
-
from donna.protocol.cells import Cell
|
|
12
|
-
from donna.world.config import config
|
|
13
|
-
|
|
14
|
-
projects_cli = typer.Typer()
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
@projects_cli.callback(invoke_without_command=True)
|
|
18
|
-
def initialize_callback(ctx: typer.Context) -> None:
|
|
19
|
-
cmd = ctx.invoked_subcommand
|
|
20
|
-
|
|
21
|
-
if cmd is None:
|
|
22
|
-
return
|
|
23
|
-
|
|
24
|
-
if cmd in ["initialize"]:
|
|
25
|
-
return
|
|
26
|
-
|
|
27
|
-
try_initialize_donna()
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
@projects_cli.command(help="Initialize Donna project.")
|
|
31
|
-
@cells_cli
|
|
32
|
-
def initialize(workdir: WorkdirOption = pathlib.Path.cwd()) -> Iterable[Cell]:
|
|
33
|
-
# TODO: use workdir attribute
|
|
34
|
-
project = config().get_world(WorldId("project")).unwrap()
|
|
35
|
-
|
|
36
|
-
project.initialize()
|
|
37
|
-
|
|
38
|
-
session = config().get_world(WorldId("session")).unwrap()
|
|
39
|
-
|
|
40
|
-
session.initialize()
|
|
41
|
-
|
|
42
|
-
return [operation_succeeded("Project initialized successfully")]
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
app.add_typer(
|
|
46
|
-
projects_cli,
|
|
47
|
-
name="projects",
|
|
48
|
-
help="Initialize and manage Donna project.",
|
|
49
|
-
)
|
donna/world/artifacts.py
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import pathlib
|
|
2
|
-
|
|
3
|
-
from donna.core.entities import BaseEntity
|
|
4
|
-
from donna.core.errors import ErrorsList
|
|
5
|
-
from donna.core.result import Err, Ok, Result, unwrap_to_error
|
|
6
|
-
from donna.domain.ids import FullArtifactId, FullArtifactIdPattern, WorldId
|
|
7
|
-
from donna.machine.artifacts import Artifact
|
|
8
|
-
from donna.machine.tasks import Task, WorkUnit
|
|
9
|
-
from donna.world import errors
|
|
10
|
-
from donna.world.config import config
|
|
11
|
-
from donna.world.templates import RenderMode
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class ArtifactRenderContext(BaseEntity):
|
|
15
|
-
primary_mode: RenderMode
|
|
16
|
-
current_task: Task | None = None
|
|
17
|
-
current_work_unit: WorkUnit | None = None
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
class ArtifactUpdateError(errors.WorldError):
|
|
21
|
-
cell_kind: str = "artifact_update_error"
|
|
22
|
-
artifact_id: FullArtifactId
|
|
23
|
-
path: pathlib.Path
|
|
24
|
-
|
|
25
|
-
def content_intro(self) -> str:
|
|
26
|
-
return f"Error updating artifact '{self.artifact_id}' from the path '{self.path}'"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
class CanNotUpdateReadonlyWorld(ArtifactUpdateError):
|
|
30
|
-
code: str = "donna.world.cannot_update_readonly_world"
|
|
31
|
-
message: str = "Cannot upload artifact to the read-only world `{error.world_id}`"
|
|
32
|
-
world_id: WorldId
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
class InputPathHasNoExtension(ArtifactUpdateError):
|
|
36
|
-
code: str = "donna.world.input_path_has_no_extension"
|
|
37
|
-
message: str = "Input path has no extension to determine artifact source type"
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
class NoSourceForArtifactExtension(ArtifactUpdateError):
|
|
41
|
-
code: str = "donna.world.no_source_for_artifact_extension"
|
|
42
|
-
message: str = "No source found for artifact extension of input path"
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
@unwrap_to_error
|
|
46
|
-
def artifact_file_extension(full_id: FullArtifactId) -> Result[str, ErrorsList]:
|
|
47
|
-
world = config().get_world(full_id.world_id).unwrap()
|
|
48
|
-
return Ok(world.file_extension_for(full_id.artifact_id).unwrap().lstrip("."))
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
@unwrap_to_error
|
|
52
|
-
def fetch_artifact(full_id: FullArtifactId, output: pathlib.Path) -> Result[None, ErrorsList]:
|
|
53
|
-
world = config().get_world(full_id.world_id).unwrap()
|
|
54
|
-
content = world.fetch_source(full_id.artifact_id).unwrap()
|
|
55
|
-
|
|
56
|
-
with output.open("wb") as f:
|
|
57
|
-
f.write(content)
|
|
58
|
-
|
|
59
|
-
return Ok(None)
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
@unwrap_to_error
|
|
63
|
-
def update_artifact(full_id: FullArtifactId, input: pathlib.Path) -> Result[None, ErrorsList]:
|
|
64
|
-
world = config().get_world(full_id.world_id).unwrap()
|
|
65
|
-
|
|
66
|
-
if world.readonly:
|
|
67
|
-
return Err([CanNotUpdateReadonlyWorld(artifact_id=full_id, path=input, world_id=world.id)])
|
|
68
|
-
|
|
69
|
-
source_suffix = input.suffix.lower()
|
|
70
|
-
content_bytes = input.read_bytes()
|
|
71
|
-
|
|
72
|
-
if not source_suffix:
|
|
73
|
-
return Err([InputPathHasNoExtension(artifact_id=full_id, path=input)])
|
|
74
|
-
|
|
75
|
-
source_config = config().find_source_for_extension(source_suffix)
|
|
76
|
-
if source_config is None:
|
|
77
|
-
return Err([NoSourceForArtifactExtension(artifact_id=full_id, path=input)])
|
|
78
|
-
|
|
79
|
-
render_context = ArtifactRenderContext(primary_mode=RenderMode.view)
|
|
80
|
-
test_artifact = source_config.construct_artifact_from_bytes(full_id, content_bytes, render_context).unwrap()
|
|
81
|
-
validation_result = test_artifact.validate_artifact()
|
|
82
|
-
|
|
83
|
-
validation_result.unwrap()
|
|
84
|
-
world.update(full_id.artifact_id, content_bytes, source_suffix).unwrap()
|
|
85
|
-
|
|
86
|
-
return Ok(None)
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
@unwrap_to_error
|
|
90
|
-
def load_artifact(
|
|
91
|
-
full_id: FullArtifactId, render_context: ArtifactRenderContext | None = None
|
|
92
|
-
) -> Result[Artifact, ErrorsList]:
|
|
93
|
-
if render_context is None:
|
|
94
|
-
render_context = ArtifactRenderContext(primary_mode=RenderMode.view)
|
|
95
|
-
|
|
96
|
-
world = config().get_world(full_id.world_id).unwrap()
|
|
97
|
-
return Ok(world.fetch(full_id.artifact_id, render_context).unwrap())
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
def list_artifacts( # noqa: CCR001
|
|
101
|
-
pattern: FullArtifactIdPattern, render_context: ArtifactRenderContext | None = None
|
|
102
|
-
) -> Result[list[Artifact], ErrorsList]:
|
|
103
|
-
|
|
104
|
-
if render_context is None:
|
|
105
|
-
render_context = ArtifactRenderContext(primary_mode=RenderMode.view)
|
|
106
|
-
|
|
107
|
-
artifacts: list[Artifact] = []
|
|
108
|
-
errors: ErrorsList = []
|
|
109
|
-
|
|
110
|
-
for world in reversed(config().worlds_instances):
|
|
111
|
-
for artifact_id in world.list_artifacts(pattern):
|
|
112
|
-
full_id = FullArtifactId((world.id, artifact_id))
|
|
113
|
-
artifact_result = load_artifact(full_id, render_context)
|
|
114
|
-
if artifact_result.is_err():
|
|
115
|
-
errors.extend(artifact_result.unwrap_err())
|
|
116
|
-
continue
|
|
117
|
-
artifacts.append(artifact_result.unwrap())
|
|
118
|
-
|
|
119
|
-
if errors:
|
|
120
|
-
return Err(errors)
|
|
121
|
-
|
|
122
|
-
return Ok(artifacts)
|