@guanlin4924/devflow-pi 0.1.40 → 0.1.48
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.
- package/bin/apply-opencode-go-session-hotfix.mjs +61 -0
- package/package.json +2 -1
- package/plugins/devflow-core/extensions/devflow-core.ts +609 -42
- package/plugins/devflow-core/skills/wireframe-proposal/SKILL.md +13 -0
- package/plugins/devflow-core/skills/wireframe-proposal/agents/openai.yaml +4 -0
- package/plugins/devflow-core/skills/wireframe-render/SKILL.md +8 -0
- package/plugins/devflow-core/skills/wireframe-review/SKILL.md +8 -0
- package/plugins/devflow-core/skills/wireframe-validate/SKILL.md +8 -0
- package/plugins/devflow-core/skills/wireframe-validate/agents/openai.yaml +4 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/SKILL.md +16 -1
- package/plugins/devflow-core/skills/workflow-orchestrator/contracts/business-candidate-delta.schema.yaml +41 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/contracts/business-claim.schema.yaml +10 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/contracts/business-model-policy.yaml +51 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/contracts/business-model.schema.yaml +241 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/contracts/business-source-registry.schema.yaml +80 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/contracts/proposal.schema.yaml +44 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/contracts/questions.schema.yaml +14 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/acceptance_test_suite.rb +13 -3
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/advance_state.rb +143 -28
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/business_claim_validate.py +77 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/business_closure_e2e_seed.json +516 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/business_cross_model_check.py +76 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/business_impact.py +51 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/business_invalidation.rb +108 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/business_model_commit.rb +570 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/business_model_gate.rb +89 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/business_model_render.py +131 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/business_model_validate.py +1063 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/business_source_resolver.rb +365 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/checker_registry.rb +2 -1
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/execution_contract.rb +3 -3
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/gate_contract.rb +3 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/gate_runtime.rb +13 -4
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/parallel_recover.rb +386 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/parallel_run.rb +28 -2
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/requirement_graph.rb +139 -14
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/requirement_graph_backfill.rb +143 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/session_rollover.rb +15 -4
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/sync_artifacts.rb +45 -1
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/validate_state.rb +10 -1
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/wireframe_commit.rb +222 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/wireframe_render.py +231 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/wireframe_validate.py +457 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/templates/feature-development.yaml +106 -1
- package/plugins/devflow-implementation/agents/implementation-worker.md +6 -0
- package/plugins/devflow-intel/skills/workflow-code-index/scripts/code_index.py +107 -37
- package/plugins/devflow-intel/skills/workflow-code-index/scripts/core/scanner.py +20 -1
- package/plugins/devflow-quality/skills/workflow-acceptance-test-design/SKILL.md +1 -1
- package/src/constants.ts +1 -1
- package/src/runtime.ts +53 -22
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wireframe-proposal
|
|
3
|
+
description: Generate or revise a low-fidelity wireframe proposal from controlled requirements. Use during the wireframe-proposal workflow step.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Wireframe Proposal
|
|
7
|
+
|
|
8
|
+
Read the controlled requirement baseline and the wireframe schema/registry. Produce exactly two candidate files:
|
|
9
|
+
|
|
10
|
+
- .planning/features/{feature}/proposal.yaml
|
|
11
|
+
- .planning/features/{feature}/questions.yaml
|
|
12
|
+
|
|
13
|
+
Use only registered element types and screen-level requirement_refs. Keep IDs stable during revision. Do not add API fields, coordinates, CSS, nested children, or approval fields. Emit valid YAML only and never claim that the proposal is validated or approved. The validator and Core decide legality, fingerprints, and approval.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wireframe-render
|
|
3
|
+
description: Render validated canonical wireframe JSON into deterministic Markdown and SVG previews. Use after wireframe-validate.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Wireframe Render
|
|
7
|
+
|
|
8
|
+
Call the workflow-orchestrator wireframe_render.py script only with the current Core-built canonical JSON. Generate preview Markdown, flow SVG, page SVGs, and the optional static gallery under the wireframe output directory. Never read proposal YAML as a substitute, mutate canonical JSON, write approval, or modify workflow state.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wireframe-review
|
|
3
|
+
description: Present validated wireframe previews and unresolved questions for explicit user review. Use at the wireframe-review checkpoint.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Wireframe Review
|
|
7
|
+
|
|
8
|
+
Show the current canonical-derived previews, renderer metadata, validation verdict, and unresolved question IDs. If the verdict is await_user, ask the user to answer the listed blocking questions. If the user approves, return control to the Core checkpoint path. Never write approval, pass runtime confirmation, confirm a checkpoint, or alter canonical/state yourself.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wireframe-validate
|
|
3
|
+
description: Run deterministic validation for a wireframe proposal and build canonical JSON. Use after wireframe-proposal.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Wireframe Validate
|
|
7
|
+
|
|
8
|
+
Call the workflow-orchestrator wireframe_validate.py script with the current proposal, traceability JSON, and questions file. Preserve its structured verdict: allow, await_user, or block_unsafe. Do not edit proposal or questions, repair unknown fields, write approval, or modify workflow state.
|
|
@@ -73,7 +73,7 @@ Each step execution follows this fixed sequence:
|
|
|
73
73
|
5. Ensure the skill writes both its `outputs` AND its `meta_output` (the `.meta.json` file).
|
|
74
74
|
|
|
75
75
|
**After execution:**
|
|
76
|
-
6. Verify the step's outputs exist
|
|
76
|
+
6. Verify the step's outputs exist and record the revision returned by `devflow_state(action="inspect")`. **Do not call `devflow_transition` or write `xd://devflow_transition`: the Devflow Runtime owns the user confirmation and the atomic state transition after this agent turn.**
|
|
77
77
|
7. If the YAML step has `meta_output`, verify the `.meta.json` file exists and has the required fields. If missing, mark the step as `blocked` with reason "missing_meta_output".
|
|
78
78
|
8. `devflow_transition` validates the proposed state before writing and rejects inconsistent updates. Never repeat the transition after it reports success.
|
|
79
79
|
9. Call `devflow_artifact(action="sync", preserve=false)` only when the registry still shows stale `planned`/`generated` statuses for completed steps.
|
|
@@ -200,6 +200,20 @@ devflow_recovery(expectedRevision=<recovery_plan.expected_revision>, confirm=tru
|
|
|
200
200
|
|
|
201
201
|
This is registry-only: it derives file existence/content metadata from the filesystem and never changes `completed_steps`, `pending_steps`, `current_step`, checkpoint state, or workflow status. Plans classified `unsafe` (for example missing required output or conflicting state tracking) must be corrected manually; recovery refuses them.
|
|
202
202
|
|
|
203
|
+
For a legacy parallel window whose worker artifacts are complete but whose
|
|
204
|
+
terminal lifecycle events were lost, use the Core recovery writer. It validates
|
|
205
|
+
all registered outputs and Core machine evidence before changing any branch,
|
|
206
|
+
uses STATE/run CAS revisions, and delegates the final join to `advance_state.rb`:
|
|
207
|
+
|
|
208
|
+
```text
|
|
209
|
+
ruby scripts/parallel_recover.rb --feature "<feature>" \
|
|
210
|
+
--expected-state-revision <state-revision> \
|
|
211
|
+
--expected-run-revision <run-revision> --write --json
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Do not use this command for failed/aborted branches or missing/invalid outputs;
|
|
215
|
+
those require explicit branch retry or artifact repair first.
|
|
216
|
+
|
|
203
217
|
When `devflow_transition` succeeds, it automatically regenerates the Markdown body of STATE.md from the YAML state + artifact registry. The body is marked `<!-- GENERATED — DO NOT EDIT -->` and must not be manually edited.
|
|
204
218
|
|
|
205
219
|
## Lessons Rules
|
|
@@ -272,6 +286,7 @@ The generated files may be project-specific instances, but their creation path m
|
|
|
272
286
|
| `scripts/sync_artifacts.rb` | Generates artifact registry with content validation. |
|
|
273
287
|
| `scripts/validate_state.rb` | Verifies STATE.md, workflow steps, dependencies, outputs, meta outputs, and artifact statuses agree before dispatch or writeback. |
|
|
274
288
|
| `scripts/advance_state.rb` | State writeback + Markdown body auto-generation. |
|
|
289
|
+
| `scripts/parallel_recover.rb` | Audited, CAS-guarded recovery and join for legacy lost parallel lifecycle events. |
|
|
275
290
|
| `scripts/update_triage_route.rb` | Deterministically updates `.planning/requirements/{feature}/入口分诊.meta.json` route/status after clarify or wayfinder. |
|
|
276
291
|
| `scripts/manage_lessons.rb` | Lesson candidate selector and evidence-based template writer. |
|
|
277
292
|
| `templates/` | Portable workflow templates used by `init_workflow.rb`. |
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
schema_version: 1
|
|
2
|
+
title: Devflow business model candidate delta
|
|
3
|
+
strict: true
|
|
4
|
+
id_pattern: '^[A-Za-z][A-Za-z0-9_-]*$'
|
|
5
|
+
top_level:
|
|
6
|
+
required:
|
|
7
|
+
- schema_version
|
|
8
|
+
- feature
|
|
9
|
+
- aggregate_revision
|
|
10
|
+
- aggregate_fingerprint
|
|
11
|
+
- source_registry_fingerprint
|
|
12
|
+
- conflict_ids
|
|
13
|
+
- assumption_ids
|
|
14
|
+
- proposed_by
|
|
15
|
+
- operations
|
|
16
|
+
properties:
|
|
17
|
+
schema_version: {type: integer, const: 1}
|
|
18
|
+
feature: {type: string, non_empty: true}
|
|
19
|
+
aggregate_revision: {type: integer, minimum: 0}
|
|
20
|
+
aggregate_fingerprint: {type: string, non_empty: true}
|
|
21
|
+
source_registry_fingerprint: {type: string, non_empty: true}
|
|
22
|
+
conflict_ids: {type: array, items: id}
|
|
23
|
+
assumption_ids: {type: array, items: id}
|
|
24
|
+
proposed_by: {type: string, non_empty: true}
|
|
25
|
+
rationale: {type: string}
|
|
26
|
+
operations: {type: array, min_items: 1}
|
|
27
|
+
operation:
|
|
28
|
+
required: [op, collection, target_id]
|
|
29
|
+
properties:
|
|
30
|
+
op: {type: enum, values: [add, replace, remove]}
|
|
31
|
+
collection: {type: enum, values: [actors, entities, components, boundaries, resources, rules, actions]}
|
|
32
|
+
target_id: {type: id}
|
|
33
|
+
value: {type: object_or_null}
|
|
34
|
+
source_refs: {type: array, items: id}
|
|
35
|
+
canonical:
|
|
36
|
+
target_invariant:
|
|
37
|
+
at_least_one_non_empty: [conflict_ids, assumption_ids]
|
|
38
|
+
normalization: [NFKC, trim_trailing_spaces, LF]
|
|
39
|
+
arrays: preserve_order
|
|
40
|
+
root_order: [schema_version, feature, aggregate_revision, aggregate_fingerprint, source_registry_fingerprint, conflict_ids, assumption_ids, proposed_by, rationale, operations]
|
|
41
|
+
operation_order: [op, collection, target_id, value, source_refs]
|
package/plugins/devflow-core/skills/workflow-orchestrator/contracts/business-claim.schema.yaml
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
schema_version: 1
|
|
2
|
+
strict: true
|
|
3
|
+
claim:
|
|
4
|
+
required: [id, text, kind]
|
|
5
|
+
properties:
|
|
6
|
+
id: {type: string, non_empty: true}
|
|
7
|
+
text: {type: string, non_empty: true}
|
|
8
|
+
kind: {type: enum, values: [business, technical]}
|
|
9
|
+
business_action_ref: {type: string}
|
|
10
|
+
requirement_ref: {type: string}
|
package/plugins/devflow-core/skills/workflow-orchestrator/contracts/business-model-policy.yaml
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
schema_version: 1
|
|
2
|
+
name: business-model-gate-policy
|
|
3
|
+
transition_kinds:
|
|
4
|
+
- modeling
|
|
5
|
+
- adjudicating
|
|
6
|
+
- freeze
|
|
7
|
+
- consume_downstream
|
|
8
|
+
default:
|
|
9
|
+
modeling: await_user
|
|
10
|
+
adjudicating: await_user
|
|
11
|
+
freeze: block_unsafe
|
|
12
|
+
consume_downstream: block_unsafe
|
|
13
|
+
rules:
|
|
14
|
+
- codes:
|
|
15
|
+
- BUSINESS_ASSUMPTION_UNRESOLVED
|
|
16
|
+
- BUSINESS_REQUIREMENT_UNCOVERED
|
|
17
|
+
- BUSINESS_RESOURCE_PRODUCER_MISSING
|
|
18
|
+
- BUSINESS_RESOURCE_CONSUMER_MISSING
|
|
19
|
+
- BUSINESS_EXTERNAL_BOUNDARY_MISSING
|
|
20
|
+
- BUSINESS_STATE_ENTRY_MISSING
|
|
21
|
+
- BUSINESS_STATE_EXIT_MISSING
|
|
22
|
+
- BUSINESS_FLOW_NO_TERMINAL_PATH
|
|
23
|
+
- BUSINESS_FLOW_START_MISSING
|
|
24
|
+
- BUSINESS_RULE_DEFAULT_MISSING
|
|
25
|
+
- TECHNICAL_CLAIM_UNGROUNDED
|
|
26
|
+
modeling: await_user
|
|
27
|
+
adjudicating: await_user
|
|
28
|
+
freeze: block_unsafe
|
|
29
|
+
consume_downstream: block_unsafe
|
|
30
|
+
- codes:
|
|
31
|
+
- BUSINESS_PROVENANCE_SOURCE_INVALID
|
|
32
|
+
- BUSINESS_SOURCE_NOT_FOUND
|
|
33
|
+
- BUSINESS_SOURCE_LOCATOR_INVALID
|
|
34
|
+
- BUSINESS_REFERENCE_NOT_FOUND
|
|
35
|
+
- BUSINESS_REF_NOT_FOUND
|
|
36
|
+
- BUSINESS_FINGERPRINT_DRIFT
|
|
37
|
+
- BUSINESS_FORGED_EVIDENCE
|
|
38
|
+
- BUSINESS_DERIVED_FIELD_FORBIDDEN
|
|
39
|
+
- BUSINESS_CHECKER_CONFIGURATION_INVALID
|
|
40
|
+
modeling: block_unsafe
|
|
41
|
+
adjudicating: block_unsafe
|
|
42
|
+
freeze: block_unsafe
|
|
43
|
+
consume_downstream: block_unsafe
|
|
44
|
+
- codes:
|
|
45
|
+
- BUSINESS_CONFLICT_UNRESOLVED
|
|
46
|
+
- BUSINESS_CANONICAL_NOT_FROZEN
|
|
47
|
+
- BUSINESS_SOURCE_NOT_REGISTERED
|
|
48
|
+
modeling: await_user
|
|
49
|
+
adjudicating: await_user
|
|
50
|
+
freeze: block_unsafe
|
|
51
|
+
consume_downstream: block_unsafe
|
package/plugins/devflow-core/skills/workflow-orchestrator/contracts/business-model.schema.yaml
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
schema_version: 1
|
|
2
|
+
title: Devflow business model proposal and canonical contract
|
|
3
|
+
strict: true
|
|
4
|
+
id_pattern: '^[A-Za-z][A-Za-z0-9_-]*$'
|
|
5
|
+
|
|
6
|
+
top_level:
|
|
7
|
+
required:
|
|
8
|
+
- schema_version
|
|
9
|
+
- feature
|
|
10
|
+
- actors
|
|
11
|
+
- entities
|
|
12
|
+
- components
|
|
13
|
+
- boundaries
|
|
14
|
+
- resources
|
|
15
|
+
- rules
|
|
16
|
+
- actions
|
|
17
|
+
- requirement_refs
|
|
18
|
+
- decision_refs
|
|
19
|
+
- resolved_assumption_refs
|
|
20
|
+
- source_registry_ref
|
|
21
|
+
properties:
|
|
22
|
+
schema_version: {type: integer, const: 1}
|
|
23
|
+
feature: {type: string, non_empty: true, path_segment: true}
|
|
24
|
+
actors: {type: array}
|
|
25
|
+
entities: {type: array}
|
|
26
|
+
components: {type: array}
|
|
27
|
+
boundaries: {type: array}
|
|
28
|
+
resources: {type: array}
|
|
29
|
+
rules: {type: array}
|
|
30
|
+
actions: {type: array}
|
|
31
|
+
requirement_refs: {type: array, items: id}
|
|
32
|
+
decision_refs: {type: array, items: id}
|
|
33
|
+
resolved_assumption_refs: {type: array, items: id}
|
|
34
|
+
source_registry_ref: {type: string, non_empty: true}
|
|
35
|
+
assumptions: {type: array}
|
|
36
|
+
forbidden_derived:
|
|
37
|
+
- transitions
|
|
38
|
+
- responsibilities
|
|
39
|
+
- dependencies
|
|
40
|
+
- inputs
|
|
41
|
+
- outputs
|
|
42
|
+
|
|
43
|
+
objects:
|
|
44
|
+
actor:
|
|
45
|
+
required: [id, source_refs]
|
|
46
|
+
properties:
|
|
47
|
+
id: {type: id}
|
|
48
|
+
name: {type: string, non_empty: true}
|
|
49
|
+
source_refs: {type: array, items: id, min_items: 1}
|
|
50
|
+
entity:
|
|
51
|
+
required: [id, states, source_refs]
|
|
52
|
+
properties:
|
|
53
|
+
id: {type: id}
|
|
54
|
+
name: {type: string, non_empty: true}
|
|
55
|
+
states: {type: array}
|
|
56
|
+
source_refs: {type: array, items: id, min_items: 1}
|
|
57
|
+
state:
|
|
58
|
+
required: [id, name, source_refs]
|
|
59
|
+
properties:
|
|
60
|
+
id: {type: id}
|
|
61
|
+
name: {type: string, non_empty: true}
|
|
62
|
+
terminal: {type: boolean}
|
|
63
|
+
source_refs: {type: array, items: id, min_items: 1}
|
|
64
|
+
component:
|
|
65
|
+
required: [id, source_refs]
|
|
66
|
+
properties:
|
|
67
|
+
id: {type: id}
|
|
68
|
+
name: {type: string, non_empty: true}
|
|
69
|
+
source_refs: {type: array, items: id, min_items: 1}
|
|
70
|
+
boundary:
|
|
71
|
+
required: [id, source_refs]
|
|
72
|
+
properties:
|
|
73
|
+
id: {type: id}
|
|
74
|
+
name: {type: string, non_empty: true}
|
|
75
|
+
system: {type: string, non_empty: true}
|
|
76
|
+
source_refs: {type: array, items: id, min_items: 1}
|
|
77
|
+
resource:
|
|
78
|
+
required: [id, origin, source_refs]
|
|
79
|
+
properties:
|
|
80
|
+
id: {type: id}
|
|
81
|
+
name: {type: string, non_empty: true}
|
|
82
|
+
origin: {type: resource_origin}
|
|
83
|
+
source_refs: {type: array, items: id, min_items: 1}
|
|
84
|
+
rule:
|
|
85
|
+
required: [id, kind, source_refs]
|
|
86
|
+
properties:
|
|
87
|
+
id: {type: id}
|
|
88
|
+
name: {type: string, non_empty: true}
|
|
89
|
+
kind: {type: enum, values: [constraint, decision]}
|
|
90
|
+
evaluation: {type: enum, values: [first_match]}
|
|
91
|
+
input_refs: {type: array, items: id}
|
|
92
|
+
branches: {type: array}
|
|
93
|
+
expression: {type: condition}
|
|
94
|
+
source_refs: {type: array, items: id, min_items: 1}
|
|
95
|
+
branch:
|
|
96
|
+
required: [id, next_action_refs, source_refs]
|
|
97
|
+
properties:
|
|
98
|
+
id: {type: id}
|
|
99
|
+
when: {type: condition}
|
|
100
|
+
default: {type: boolean}
|
|
101
|
+
next_action_refs: {type: array, items: id, min_items: 1}
|
|
102
|
+
source_refs: {type: array, items: id, min_items: 1}
|
|
103
|
+
action:
|
|
104
|
+
required:
|
|
105
|
+
- id
|
|
106
|
+
- requirement_refs
|
|
107
|
+
- actor_ref
|
|
108
|
+
- owner_ref
|
|
109
|
+
- trigger
|
|
110
|
+
- consumes
|
|
111
|
+
- produces
|
|
112
|
+
- constraint_rule_refs
|
|
113
|
+
- routing
|
|
114
|
+
- failure_modes
|
|
115
|
+
- source_refs
|
|
116
|
+
properties:
|
|
117
|
+
id: {type: id}
|
|
118
|
+
name: {type: string, non_empty: true}
|
|
119
|
+
requirement_refs: {type: array, items: id, min_items: 1}
|
|
120
|
+
actor_ref: {type: id}
|
|
121
|
+
owner_ref: {type: id}
|
|
122
|
+
trigger: {type: string, non_empty: true}
|
|
123
|
+
entity_ref: {type: id}
|
|
124
|
+
from_state_ref: {type: id}
|
|
125
|
+
to_state_ref: {type: id}
|
|
126
|
+
consumes: {type: array, items: id}
|
|
127
|
+
produces: {type: array, items: id}
|
|
128
|
+
constraint_rule_refs: {type: array, items: id}
|
|
129
|
+
routing: {type: routing}
|
|
130
|
+
failure_modes: {type: array}
|
|
131
|
+
source_refs: {type: array, items: id, min_items: 1}
|
|
132
|
+
routing:
|
|
133
|
+
required: []
|
|
134
|
+
properties:
|
|
135
|
+
next_action_refs: {type: array, items: id, min_items: 1}
|
|
136
|
+
decision_rule_ref: {type: id}
|
|
137
|
+
terminal: {type: boolean}
|
|
138
|
+
failure_mode:
|
|
139
|
+
required: [code, source_refs]
|
|
140
|
+
properties:
|
|
141
|
+
code: {type: id}
|
|
142
|
+
recovery_action_ref: {type: id}
|
|
143
|
+
terminal: {type: boolean}
|
|
144
|
+
terminal_state_ref: {type: id}
|
|
145
|
+
source_refs: {type: array, items: id, min_items: 1}
|
|
146
|
+
assumption:
|
|
147
|
+
required: [id, statement, proposed_by, affected_refs, status]
|
|
148
|
+
properties:
|
|
149
|
+
id: {type: id}
|
|
150
|
+
statement: {type: string, non_empty: true}
|
|
151
|
+
proposed_by: {type: string, non_empty: true}
|
|
152
|
+
affected_refs: {type: array, items: id, min_items: 1}
|
|
153
|
+
status: {type: enum, values: [unresolved]}
|
|
154
|
+
conflict:
|
|
155
|
+
required: [id, subject_ref, collection, field, alternatives, status]
|
|
156
|
+
properties:
|
|
157
|
+
id: {type: id}
|
|
158
|
+
subject_ref: {type: id}
|
|
159
|
+
collection: {type: string, non_empty: true}
|
|
160
|
+
field: {type: string, non_empty: true}
|
|
161
|
+
alternatives: {type: array, min_items: 2}
|
|
162
|
+
status: {type: enum, values: [unresolved, resolved]}
|
|
163
|
+
alternative:
|
|
164
|
+
required: [present, proposal_refs]
|
|
165
|
+
properties:
|
|
166
|
+
present: {type: boolean}
|
|
167
|
+
value: {type: any}
|
|
168
|
+
proposal_refs: {type: array, items: string, min_items: 1}
|
|
169
|
+
|
|
170
|
+
unions:
|
|
171
|
+
resource_origin:
|
|
172
|
+
discriminator: kind
|
|
173
|
+
variants:
|
|
174
|
+
produced_in_flow:
|
|
175
|
+
required: [kind, lifecycle_owner_ref]
|
|
176
|
+
properties:
|
|
177
|
+
kind: {const: produced_in_flow}
|
|
178
|
+
lifecycle_owner_ref: {type: id}
|
|
179
|
+
user_supplied:
|
|
180
|
+
required: [kind, actor_ref, intake_action_ref]
|
|
181
|
+
properties:
|
|
182
|
+
kind: {const: user_supplied}
|
|
183
|
+
actor_ref: {type: id}
|
|
184
|
+
intake_action_ref: {type: id}
|
|
185
|
+
external_system:
|
|
186
|
+
required: [kind, boundary_ref, receive_action_ref]
|
|
187
|
+
properties:
|
|
188
|
+
kind: {const: external_system}
|
|
189
|
+
boundary_ref: {type: id}
|
|
190
|
+
receive_action_ref: {type: id}
|
|
191
|
+
preexisting_project:
|
|
192
|
+
required: [kind, code_source_ref, lifecycle_owner_ref]
|
|
193
|
+
properties:
|
|
194
|
+
kind: {const: preexisting_project}
|
|
195
|
+
code_source_ref: {type: id}
|
|
196
|
+
lifecycle_owner_ref: {type: id}
|
|
197
|
+
|
|
198
|
+
conditions:
|
|
199
|
+
operators: [eq, ne, in, and, or, not, lt, lte, gt, gte, exists]
|
|
200
|
+
operand_variants:
|
|
201
|
+
literal: [kind, value]
|
|
202
|
+
resource_attribute: [kind, resource_ref, attribute]
|
|
203
|
+
entity_state: [kind, entity_ref, state_ref]
|
|
204
|
+
actor_attribute: [kind, actor_ref, attribute]
|
|
205
|
+
|
|
206
|
+
canonical:
|
|
207
|
+
normalization: [NFKC, trim_trailing_spaces, LF]
|
|
208
|
+
arrays: preserve_order
|
|
209
|
+
root_order:
|
|
210
|
+
- schema_version
|
|
211
|
+
- feature
|
|
212
|
+
- actors
|
|
213
|
+
- entities
|
|
214
|
+
- components
|
|
215
|
+
- boundaries
|
|
216
|
+
- resources
|
|
217
|
+
- rules
|
|
218
|
+
- actions
|
|
219
|
+
- requirement_refs
|
|
220
|
+
- decision_refs
|
|
221
|
+
- resolved_assumption_refs
|
|
222
|
+
- source_registry_ref
|
|
223
|
+
- assumptions
|
|
224
|
+
object_orders:
|
|
225
|
+
actor: [id, name, source_refs]
|
|
226
|
+
entity: [id, name, states, source_refs]
|
|
227
|
+
state: [id, name, terminal, source_refs]
|
|
228
|
+
component: [id, name, source_refs]
|
|
229
|
+
boundary: [id, name, system, source_refs]
|
|
230
|
+
resource: [id, name, origin, source_refs]
|
|
231
|
+
resource_origin: [kind, lifecycle_owner_ref, actor_ref, intake_action_ref, boundary_ref, receive_action_ref, code_source_ref]
|
|
232
|
+
rule: [id, name, kind, evaluation, input_refs, branches, expression, source_refs]
|
|
233
|
+
branch: [id, when, default, next_action_refs, source_refs]
|
|
234
|
+
condition: [op, args, operand, left, right]
|
|
235
|
+
operand: [kind, value, resource_ref, entity_ref, state_ref, actor_ref, attribute]
|
|
236
|
+
action: [id, name, requirement_refs, actor_ref, owner_ref, trigger, entity_ref, from_state_ref, to_state_ref, consumes, produces, constraint_rule_refs, routing, failure_modes, source_refs]
|
|
237
|
+
routing: [next_action_refs, decision_rule_ref, terminal]
|
|
238
|
+
failure_mode: [code, recovery_action_ref, terminal, terminal_state_ref, source_refs]
|
|
239
|
+
assumption: [id, statement, proposed_by, affected_refs, status]
|
|
240
|
+
conflict: [id, subject_ref, collection, field, alternatives, status]
|
|
241
|
+
alternative: [present, value, proposal_refs]
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
schema_version: 1
|
|
2
|
+
title: Devflow business source registry
|
|
3
|
+
strict: true
|
|
4
|
+
id_pattern: '^SRC-[A-Za-z0-9][A-Za-z0-9_-]*$'
|
|
5
|
+
top_level:
|
|
6
|
+
required: [schema_version, feature, registry_revision, sources]
|
|
7
|
+
properties:
|
|
8
|
+
schema_version: {type: integer, const: 1}
|
|
9
|
+
feature: {type: string, non_empty: true}
|
|
10
|
+
registry_revision: {type: integer, minimum: 0}
|
|
11
|
+
sources: {type: array}
|
|
12
|
+
source:
|
|
13
|
+
required: [id, type]
|
|
14
|
+
properties:
|
|
15
|
+
id: {type: id}
|
|
16
|
+
type: {type: enum, values: [requirement, code, domain_rule, user_decision]}
|
|
17
|
+
source_variants:
|
|
18
|
+
requirement:
|
|
19
|
+
required: [id, type, document, source_fingerprint, locator]
|
|
20
|
+
properties:
|
|
21
|
+
id: {type: id}
|
|
22
|
+
type: {const: requirement}
|
|
23
|
+
document: {type: string, non_empty: true}
|
|
24
|
+
source_fingerprint: {type: string, non_empty: true}
|
|
25
|
+
locator: {type: requirement_locator}
|
|
26
|
+
code:
|
|
27
|
+
required: [id, type, repository, repository_revision, worktree_signature, index_generation, path, content_hash, locator]
|
|
28
|
+
properties:
|
|
29
|
+
id: {type: id}
|
|
30
|
+
type: {const: code}
|
|
31
|
+
repository: {type: string, non_empty: true}
|
|
32
|
+
repository_revision: {type: string, non_empty: true}
|
|
33
|
+
worktree_signature: {type: string, non_empty: true}
|
|
34
|
+
index_generation: {type: string, non_empty: true}
|
|
35
|
+
path: {type: string, non_empty: true}
|
|
36
|
+
content_hash: {type: string, non_empty: true}
|
|
37
|
+
commit: {type: string}
|
|
38
|
+
locator: {type: code_locator}
|
|
39
|
+
domain_rule:
|
|
40
|
+
required: [id, type, document, source_fingerprint, locator]
|
|
41
|
+
properties:
|
|
42
|
+
id: {type: id}
|
|
43
|
+
type: {const: domain_rule}
|
|
44
|
+
document: {type: string, non_empty: true}
|
|
45
|
+
source_fingerprint: {type: string, non_empty: true}
|
|
46
|
+
locator: {type: domain_locator}
|
|
47
|
+
user_decision:
|
|
48
|
+
required: [id, type, decision_revision, decision_fingerprint, locator]
|
|
49
|
+
properties:
|
|
50
|
+
id: {type: id}
|
|
51
|
+
type: {const: user_decision}
|
|
52
|
+
decision_revision: {type: integer, minimum: 0}
|
|
53
|
+
decision_fingerprint: {type: string, non_empty: true}
|
|
54
|
+
locator: {type: decision_locator}
|
|
55
|
+
locator_variants:
|
|
56
|
+
requirement:
|
|
57
|
+
required: [requirement_ref, assertion_id]
|
|
58
|
+
properties:
|
|
59
|
+
requirement_ref: {type: id}
|
|
60
|
+
assertion_id: {type: id}
|
|
61
|
+
code:
|
|
62
|
+
required: []
|
|
63
|
+
at_least_one: [symbol, line_start]
|
|
64
|
+
properties:
|
|
65
|
+
symbol: {type: string, non_empty: true}
|
|
66
|
+
line_start: {type: integer, minimum: 1}
|
|
67
|
+
domain_rule:
|
|
68
|
+
required: [clause_id]
|
|
69
|
+
properties:
|
|
70
|
+
clause_id: {type: id}
|
|
71
|
+
user_decision:
|
|
72
|
+
required: [decision_id]
|
|
73
|
+
properties:
|
|
74
|
+
decision_id: {type: id}
|
|
75
|
+
canonical:
|
|
76
|
+
normalization: [NFKC, trim_trailing_spaces, LF]
|
|
77
|
+
arrays: preserve_order
|
|
78
|
+
root_order: [schema_version, feature, registry_revision, sources]
|
|
79
|
+
source_order: [id, type, document, source_fingerprint, repository, repository_revision, worktree_signature, index_generation, path, content_hash, commit, decision_revision, decision_fingerprint, locator]
|
|
80
|
+
locator_order: [requirement_ref, assertion_id, symbol, line_start, clause_id, decision_id]
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
schema_version: 1
|
|
2
|
+
title: Devflow low-fidelity wireframe proposal
|
|
3
|
+
strict: true
|
|
4
|
+
top_level:
|
|
5
|
+
required: [schema_version, feature, screens]
|
|
6
|
+
properties:
|
|
7
|
+
schema_version: {type: integer, const: 1}
|
|
8
|
+
feature: {type: string, non_empty: true}
|
|
9
|
+
screens: {type: array, min_items: 1}
|
|
10
|
+
screen:
|
|
11
|
+
required: [id, title, requirement_refs, elements, states]
|
|
12
|
+
defaults: {presentation: page, platforms: [web, mobile], actions: []}
|
|
13
|
+
properties:
|
|
14
|
+
id: {type: id}
|
|
15
|
+
title: {type: string, non_empty: true}
|
|
16
|
+
presentation: {type: enum, values: [page, modal, drawer]}
|
|
17
|
+
platforms: {type: array, values: [web, mobile], unique: true, min_items: 1}
|
|
18
|
+
requirement_refs: {type: array, min_items: 1}
|
|
19
|
+
elements: {type: array}
|
|
20
|
+
actions: {type: array}
|
|
21
|
+
states: {type: array, values: [default, empty, loading, error], unique: true, contains: default}
|
|
22
|
+
elements:
|
|
23
|
+
page_header: {title: string, action_refs: [id]}
|
|
24
|
+
filter_bar: {fields: [{id: id, label: string, type: [input, select]}]}
|
|
25
|
+
table: {columns: [{id: id, label: string}]}
|
|
26
|
+
card_list: {items: [{id: id, title: string, meta: [{label: string, value: string}]}]}
|
|
27
|
+
bottom_navigation: {items: [{id: id, label: string, action_ref: id}]}
|
|
28
|
+
tabs: {tabs: [{id: id, label: string}]}
|
|
29
|
+
input: {label: string, action_ref: id}
|
|
30
|
+
select: {label: string, action_ref: id}
|
|
31
|
+
button: {label: string, action_ref: id}
|
|
32
|
+
icon_button: {label: string, action_ref: id}
|
|
33
|
+
action:
|
|
34
|
+
required: [id, type, target]
|
|
35
|
+
properties:
|
|
36
|
+
id: {type: id}
|
|
37
|
+
type: {type: enum, values: [open, close, back]}
|
|
38
|
+
target: {type: string_or_null}
|
|
39
|
+
business_action_ref: {type: id}
|
|
40
|
+
id_pattern: '^[A-Za-z0-9][A-Za-z0-9_-]*$'
|
|
41
|
+
canonical:
|
|
42
|
+
object_keys: schema_order
|
|
43
|
+
arrays: preserve_order
|
|
44
|
+
normalization: [NFKC, trim_trailing_spaces, LF]
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
schema_version: 1
|
|
2
|
+
title: Devflow wireframe questions
|
|
3
|
+
strict: true
|
|
4
|
+
top_level:
|
|
5
|
+
required: [schema_version, feature, questions]
|
|
6
|
+
question:
|
|
7
|
+
required: [id, text, kind, status]
|
|
8
|
+
properties:
|
|
9
|
+
id: {type: id}
|
|
10
|
+
text: {type: string, non_empty: true}
|
|
11
|
+
kind: {type: enum, values: [blocking, informational]}
|
|
12
|
+
status: {type: enum, values: [open, resolved]}
|
|
13
|
+
target: {type: object, properties: [screen, element]}
|
|
14
|
+
answer: {type: string_or_null}
|
|
@@ -10,12 +10,13 @@ require "optparse"
|
|
|
10
10
|
require_relative "control_io"
|
|
11
11
|
require_relative "requirement_graph"
|
|
12
12
|
|
|
13
|
-
options = { feature: nil, expected_graph_revision: nil, cp_record: nil, write: false, json: false }
|
|
13
|
+
options = { feature: nil, expected_graph_revision: nil, cp_record: nil, confirm_prerequisites: false, write: false, json: false }
|
|
14
14
|
command = ARGV.shift
|
|
15
15
|
OptionParser.new do |parser|
|
|
16
16
|
parser.on("--feature NAME") { |value| options[:feature] = value }
|
|
17
17
|
parser.on("--expected-graph-revision REVISION", Integer) { |value| options[:expected_graph_revision] = value }
|
|
18
18
|
parser.on("--cp-record RECORD") { |value| options[:cp_record] = value }
|
|
19
|
+
parser.on("--confirm-prerequisites") { options[:confirm_prerequisites] = true }
|
|
19
20
|
parser.on("--write") { options[:write] = true }
|
|
20
21
|
parser.on("--json") { options[:json] = true }
|
|
21
22
|
end.parse!
|
|
@@ -48,6 +49,14 @@ begin
|
|
|
48
49
|
|
|
49
50
|
if command == "inspect"
|
|
50
51
|
view = RequirementGraph.view_payload(graph, "tests")
|
|
52
|
+
unconfirmed_prerequisites = RequirementGraph.candidate_test_prerequisites(graph).map do |node|
|
|
53
|
+
data = node["data"].is_a?(Hash) ? node["data"] : {}
|
|
54
|
+
{
|
|
55
|
+
"id" => node["id"],
|
|
56
|
+
"kind" => node["kind"],
|
|
57
|
+
"summary" => data["name"] || data["outcome"] || data["summary"] || data["locator"] || data["requirement_ref"]
|
|
58
|
+
}.compact
|
|
59
|
+
end
|
|
51
60
|
result = {
|
|
52
61
|
"ok" => true,
|
|
53
62
|
"path" => relative,
|
|
@@ -55,7 +64,8 @@ begin
|
|
|
55
64
|
"test_case_ids" => cases.map { |node| node["id"] },
|
|
56
65
|
"frozen" => view["frozen"],
|
|
57
66
|
"frozen_graph_revision" => view["frozen_graph_revision"],
|
|
58
|
-
"stale" => Array(graph["stale"]).select { |entry| cases.any? { |node| node["id"] == entry["node_id"] } }
|
|
67
|
+
"stale" => Array(graph["stale"]).select { |entry| cases.any? { |node| node["id"] == entry["node_id"] } },
|
|
68
|
+
"unconfirmed_prerequisites" => unconfirmed_prerequisites
|
|
59
69
|
}
|
|
60
70
|
else
|
|
61
71
|
raise ArgumentError, "--write is required" unless options[:write]
|
|
@@ -72,7 +82,7 @@ begin
|
|
|
72
82
|
else
|
|
73
83
|
matrix = api_test_matrix_check(root, options[:feature], graph)
|
|
74
84
|
result = if matrix["ok"]
|
|
75
|
-
RequirementGraph.freeze_test_cases!(root, graph, options[:cp_record])
|
|
85
|
+
RequirementGraph.freeze_test_cases!(root, graph, options[:cp_record], confirm_prerequisites: options[:confirm_prerequisites])
|
|
76
86
|
else
|
|
77
87
|
{ "ok" => false, "reason" => "api_test_matrix_incomplete", "message" => Array(matrix["errors"]).join("; "), "matrix" => matrix }
|
|
78
88
|
end
|