@guanlin4924/devflow-pi 0.1.39 → 0.1.47

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/package.json +1 -1
  2. package/plugins/devflow-core/extensions/devflow-core.ts +728 -39
  3. package/plugins/devflow-core/skills/wireframe-proposal/SKILL.md +13 -0
  4. package/plugins/devflow-core/skills/wireframe-proposal/agents/openai.yaml +4 -0
  5. package/plugins/devflow-core/skills/wireframe-render/SKILL.md +8 -0
  6. package/plugins/devflow-core/skills/wireframe-review/SKILL.md +8 -0
  7. package/plugins/devflow-core/skills/wireframe-validate/SKILL.md +8 -0
  8. package/plugins/devflow-core/skills/wireframe-validate/agents/openai.yaml +4 -0
  9. package/plugins/devflow-core/skills/workflow-orchestrator/SKILL.md +16 -1
  10. package/plugins/devflow-core/skills/workflow-orchestrator/contracts/business-candidate-delta.schema.yaml +41 -0
  11. package/plugins/devflow-core/skills/workflow-orchestrator/contracts/business-claim.schema.yaml +10 -0
  12. package/plugins/devflow-core/skills/workflow-orchestrator/contracts/business-model-policy.yaml +51 -0
  13. package/plugins/devflow-core/skills/workflow-orchestrator/contracts/business-model.schema.yaml +241 -0
  14. package/plugins/devflow-core/skills/workflow-orchestrator/contracts/business-source-registry.schema.yaml +80 -0
  15. package/plugins/devflow-core/skills/workflow-orchestrator/contracts/proposal.schema.yaml +44 -0
  16. package/plugins/devflow-core/skills/workflow-orchestrator/contracts/questions.schema.yaml +14 -0
  17. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/acceptance_test_suite.rb +13 -3
  18. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/advance_state.rb +334 -30
  19. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/business_claim_validate.py +77 -0
  20. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/business_closure_e2e_seed.json +516 -0
  21. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/business_cross_model_check.py +76 -0
  22. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/business_impact.py +51 -0
  23. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/business_invalidation.rb +108 -0
  24. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/business_model_commit.rb +570 -0
  25. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/business_model_gate.rb +89 -0
  26. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/business_model_render.py +131 -0
  27. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/business_model_validate.py +1063 -0
  28. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/business_source_resolver.rb +365 -0
  29. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/checker_registry.rb +2 -0
  30. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/cross_track_consistency_check.rb +94 -0
  31. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/execution_contract.rb +3 -3
  32. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/gate_contract.rb +3 -0
  33. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/gate_runtime.rb +84 -6
  34. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/inspect_state.rb +3 -0
  35. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/machine_evidence.rb +45 -12
  36. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/parallel_recover.rb +386 -0
  37. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/parallel_run.rb +248 -0
  38. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/requirement_graph.rb +139 -14
  39. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/requirement_graph_backfill.rb +143 -0
  40. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/session_rollover.rb +15 -4
  41. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/sync_artifacts.rb +45 -1
  42. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/validate_state.rb +86 -2
  43. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/wireframe_commit.rb +222 -0
  44. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/wireframe_render.py +231 -0
  45. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/wireframe_validate.py +457 -0
  46. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/workflow_gate_contract.rb +94 -2
  47. package/plugins/devflow-core/skills/workflow-orchestrator/templates/feature-development.yaml +111 -1
  48. package/plugins/devflow-implementation/agents/implementation-worker.md +6 -0
  49. package/plugins/devflow-intel/skills/workflow-code-index/scripts/code_index.py +107 -37
  50. package/plugins/devflow-intel/skills/workflow-code-index/scripts/core/scanner.py +20 -1
  51. package/plugins/devflow-quality/skills/workflow-acceptance-test-design/SKILL.md +1 -1
  52. package/src/constants.ts +1 -1
  53. package/src/runtime.ts +61 -24
@@ -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,4 @@
1
+ interface:
2
+ display_name: "wireframe-proposal"
3
+ short_description: "AI 生成或修订低保真原型 proposal 与 questions 候选"
4
+ default_prompt: "AI 生成或修订低保真原型 proposal 与 questions 候选"
@@ -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.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "wireframe-validate"
3
+ short_description: "确定性校验低保真原型 proposal 并生成 canonical"
4
+ default_prompt: "确定性校验低保真原型 proposal 并生成 canonical"
@@ -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, record the revision returned by `devflow_state(action="inspect")`, then call `devflow_transition(action="complete-step", step="<step-id>", expectedRevision=<revision>)`.
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]
@@ -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}
@@ -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
@@ -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