@guanlin4924/devflow-pi 0.1.105 → 0.1.106
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/README.md +10 -8
- package/package.json +1 -1
- package/plugins/devflow-core/extensions/devflow-core.ts +105 -305
- package/plugins/devflow-core/runtime/hooks/context_sync_gate.py +3 -1
- package/plugins/devflow-core/runtime/hooks/hook_common.py +6 -5
- package/plugins/devflow-core/runtime/hooks/index_gate.py +19 -26
- package/plugins/devflow-core/skills/wireframe-proposal/SKILL.md +2 -0
- package/plugins/devflow-core/skills/wireframe-render/SKILL.md +2 -0
- package/plugins/devflow-core/skills/wireframe-review/SKILL.md +2 -0
- package/plugins/devflow-core/skills/wireframe-validate/SKILL.md +2 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/SKILL.md +34 -50
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/advance_state.rb +40 -191
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/artifact_specs.rb +12 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/execution_contract.rb +38 -1
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/gate_policy.rb +11 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/gate_result.rb +12 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/gate_runtime.rb +4 -9
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/inspect_state.rb +13 -86
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/parallel_recover.rb +24 -13
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/repair_control_plane.rb +4 -4
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/sync_artifacts.rb +3 -1
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/validate_state.rb +8 -39
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/wireframe_commit.rb +39 -3
- package/plugins/devflow-core/skills/workflow-orchestrator/templates/feature-development.yaml +2 -3
- package/plugins/devflow-core/skills/workflow-orchestrator/templates/regression-acceptance.yaml +0 -1
- package/plugins/devflow-core/skills/workflow-pipeline/SKILL.md +10 -5
- package/plugins/devflow-core/skills/workflow-pipeline/references/pipeline-flow.md +1 -1
- package/plugins/devflow-core/skills/workflow-project-context/SKILL.md +2 -0
- package/plugins/devflow-design/skills/workflow-api-call-guide/SKILL.md +2 -0
- package/plugins/devflow-design/skills/workflow-api-contract/SKILL.md +3 -1
- package/plugins/devflow-design/skills/workflow-api-supplement/SKILL.md +2 -0
- package/plugins/devflow-design/skills/workflow-architecture-feasibility/SKILL.md +2 -0
- package/plugins/devflow-design/skills/workflow-backend-tech-spec/SKILL.md +6 -4
- package/plugins/devflow-design/skills/workflow-design-rule-pack/SKILL.md +2 -0
- package/plugins/devflow-design/skills/workflow-feature-breakdown/SKILL.md +2 -0
- package/plugins/devflow-design/skills/workflow-frontend-tech-spec/SKILL.md +6 -4
- package/plugins/devflow-design/skills/workflow-integration-verify/SKILL.md +3 -1
- package/plugins/devflow-design/skills/workflow-ui-spec/SKILL.md +4 -2
- package/plugins/devflow-implementation/agents/implementation-worker.md +2 -8
- package/plugins/devflow-implementation/skills/workflow-bug-fix/SKILL.md +2 -0
- package/plugins/devflow-implementation/skills/workflow-change-plan/SKILL.md +3 -1
- package/plugins/devflow-implementation/skills/workflow-execute-phase/SKILL.md +3 -1
- package/plugins/devflow-intel/skills/code-index-query/SKILL.md +2 -0
- package/plugins/devflow-intel/skills/workflow-code-index/SKILL.md +2 -0
- package/plugins/devflow-intel/skills/workflow-context-sync/SKILL.md +2 -0
- package/plugins/devflow-intel/skills/workflow-update-navigation/SKILL.md +3 -1
- package/plugins/devflow-quality/skills/code-review/SKILL.md +4 -2
- package/plugins/devflow-quality/skills/workflow-acceptance-test-design/SKILL.md +3 -1
- package/plugins/devflow-quality/skills/workflow-gen-test-guide/SKILL.md +2 -0
- package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/SKILL.md +2 -0
- package/plugins/devflow-quality/skills/workflow-human-acceptance/SKILL.md +2 -0
- package/plugins/devflow-quality/skills/workflow-regression-test-design/SKILL.md +2 -0
- package/plugins/devflow-quality/skills/workflow-release-closeout/SKILL.md +7 -5
- package/plugins/devflow-quality/skills/workflow-run-acceptance-tests/SKILL.md +8 -6
- package/plugins/devflow-requirements/skills/requirement-feasibility-review/SKILL.md +2 -0
- package/plugins/devflow-requirements/skills/workflow-demand-clarify/SKILL.md +2 -0
- package/plugins/devflow-requirements/skills/workflow-domain-modeling/SKILL.md +2 -0
- package/plugins/devflow-requirements/skills/workflow-requirement-baseline/SKILL.md +6 -2
- package/plugins/devflow-requirements/skills/workflow-requirement-triage/SKILL.md +2 -0
- package/plugins/devflow-requirements/skills/workflow-wayfinder/SKILL.md +2 -0
- package/src/constants.ts +1 -1
- package/templates/omp/AGENTS.md +6 -2
|
@@ -15,6 +15,8 @@ require "optparse"
|
|
|
15
15
|
require "time"
|
|
16
16
|
require "yaml"
|
|
17
17
|
require_relative "control_io"
|
|
18
|
+
require_relative "artifact_specs"
|
|
19
|
+
require_relative "gate_policy"
|
|
18
20
|
require_relative "parallel_run"
|
|
19
21
|
|
|
20
22
|
options = {
|
|
@@ -54,9 +56,8 @@ def interpolate_path(path, state)
|
|
|
54
56
|
end
|
|
55
57
|
|
|
56
58
|
def required_output_specs(step)
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
outputs
|
|
59
|
+
ArtifactSpecs.for_step(step).select { |item| item["required"] == true }
|
|
60
|
+
|
|
60
61
|
end
|
|
61
62
|
|
|
62
63
|
def actual_content_issues(path, checks)
|
|
@@ -143,12 +144,13 @@ def generate_machine_evidence(root, feature, state_revision, branch, expected_pa
|
|
|
143
144
|
packed_paths = Array(pack["files"]).select { |item| item.is_a?(Hash) && item["required"] == true }.map { |item| item["path"].to_s }.sort
|
|
144
145
|
errors << "machine evidence required outputs mismatch" unless packed_paths == expected_paths.sort
|
|
145
146
|
errors << "machine evidence contains a missing required file" unless Array(pack["files"]).all? { |item| item.is_a?(Hash) && item["exists"] == true && item["sha256"].to_s.match?(/\A[0-9a-f]{64}\z/) }
|
|
146
|
-
|
|
147
|
+
recovery_check(errors.empty?, errors.join("; "))
|
|
147
148
|
|
|
148
149
|
output_fingerprint = Digest::SHA256.hexdigest(
|
|
149
150
|
Array(pack["files"]).map { |item| [item["path"].to_s, item["sha256"].to_s] }.sort.to_json,
|
|
150
151
|
)
|
|
151
152
|
{
|
|
153
|
+
"valid" => errors.empty?,
|
|
152
154
|
"evidence_path" => evidence_path,
|
|
153
155
|
"evidence_sha256" => Digest::SHA256.file(absolute).hexdigest,
|
|
154
156
|
"output_fingerprint" => output_fingerprint,
|
|
@@ -213,6 +215,13 @@ rescue JSON::ParserError => error
|
|
|
213
215
|
{ "ok" => false, "reason" => "join_returned_invalid_json", "message" => error.message, "stderr" => stderr.strip, "exit_status" => status.exitstatus }
|
|
214
216
|
end
|
|
215
217
|
|
|
218
|
+
def recovery_check(condition, message)
|
|
219
|
+
return if condition
|
|
220
|
+
|
|
221
|
+
$recovery_advisories << GatePolicy.advisory({ "code" => "parallel_recovery_check_failed", "message" => message })
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
$recovery_advisories = []
|
|
216
225
|
root = Dir.pwd
|
|
217
226
|
feature = options[:feature].to_s
|
|
218
227
|
result = nil
|
|
@@ -244,7 +253,7 @@ begin
|
|
|
244
253
|
raise ArgumentError, "parallel run not found" unless run
|
|
245
254
|
recovery = recovery_id(run, options[:expected_state_revision], options[:expected_run_revision])
|
|
246
255
|
branches = Array(run["branches"])
|
|
247
|
-
already_joined = state["parallel_run_ref"].nil? && run["status"] == "completed" && branches.any? && branches.all? { |branch| branch["status"] == "succeeded" }
|
|
256
|
+
already_joined = state["parallel_run_ref"].nil? && run["status"] == "completed" && branches.any? && (branches.all? { |branch| branch["status"] == "succeeded" } || run["completion_with_warnings"])
|
|
248
257
|
if already_joined
|
|
249
258
|
append_audit(root, feature, {
|
|
250
259
|
"schema_version" => 1, "origin" => "core.parallel_recovery/v1", "event" => "idempotent_noop",
|
|
@@ -264,7 +273,7 @@ begin
|
|
|
264
273
|
raise ArgumentError, "parallel run is bound to stale STATE revision" unless Integer(run.fetch("bound_state_revision")) == state_revision
|
|
265
274
|
raise ArgumentError, "parallel run has no branches" if branches.empty?
|
|
266
275
|
ineligible = branches.select { |branch| %w[failed aborted].include?(branch["status"].to_s) }
|
|
267
|
-
|
|
276
|
+
recovery_check(ineligible.empty?, "failed/aborted branches were not retried: #{ineligible.map { |branch| branch['branch_id'] }.join(', ')}")
|
|
268
277
|
previous_validation = prior_validation(root, feature, recovery, run)
|
|
269
278
|
unless current_run_revision == options[:expected_run_revision] || previous_validation
|
|
270
279
|
raise ArgumentError, "stale parallel run revision: expected=#{options[:expected_run_revision]}, actual=#{current_run_revision}"
|
|
@@ -275,9 +284,10 @@ begin
|
|
|
275
284
|
registry_source = workflow.dig("artifact_registry", "source").to_s
|
|
276
285
|
raise ArgumentError, "workflow artifact_registry.source is required for recovery" if registry_source.empty?
|
|
277
286
|
registry_path, = DevflowControlIO.resolve_control_path(root, registry_source, :registry)
|
|
278
|
-
registry = load_yaml_mapping(registry_path, "artifact registry")
|
|
279
|
-
|
|
280
|
-
|
|
287
|
+
registry = File.file?(registry_path) ? load_yaml_mapping(registry_path, "artifact registry") : {}
|
|
288
|
+
recovery_check(!registry.empty?, "artifact registry missing")
|
|
289
|
+
recovery_check(registry["state_revision"] == state_revision, "artifact registry revision mismatch")
|
|
290
|
+
recovery_check(registry.dig("registry_scope", "feature").to_s == feature, "artifact registry feature mismatch")
|
|
281
291
|
registry_by_path = Array(registry["artifacts"]).each_with_object({}) do |artifact, index|
|
|
282
292
|
raise ArgumentError, "artifact registry entry must be a mapping" unless artifact.is_a?(Hash)
|
|
283
293
|
path = artifact["path"].to_s
|
|
@@ -292,7 +302,8 @@ begin
|
|
|
292
302
|
raise ArgumentError, "parallel branch workflow step is unknown: #{branch['workflow_step']}" unless step
|
|
293
303
|
artifacts = validate_registered_outputs(root, workflow, state, step, registry_by_path)
|
|
294
304
|
invalid = artifacts.reject { |artifact| artifact["valid"] }
|
|
295
|
-
|
|
305
|
+
recovery_check(invalid.empty?, "branch #{branch['branch_id']} artifact validation failed: #{invalid.to_json}")
|
|
306
|
+
next unless invalid.empty?
|
|
296
307
|
machine = generate_machine_evidence(root, feature, state_revision, branch, artifacts.map { |artifact| artifact["path"] })
|
|
297
308
|
validation_records << {
|
|
298
309
|
"branch_id" => branch["branch_id"], "workflow_step" => branch["workflow_step"],
|
|
@@ -310,6 +321,7 @@ begin
|
|
|
310
321
|
|
|
311
322
|
validation_records.each do |validated|
|
|
312
323
|
machine = validated.fetch("machine_evidence")
|
|
324
|
+
next unless machine["valid"]
|
|
313
325
|
updated = ParallelRun.update_branch(
|
|
314
326
|
root: root, feature: feature, branch_id: validated.fetch("branch_id"),
|
|
315
327
|
expected_revision: current_run_revision, status: "succeeded",
|
|
@@ -320,9 +332,7 @@ begin
|
|
|
320
332
|
recovered_branches << validated.fetch("branch_id")
|
|
321
333
|
end
|
|
322
334
|
final_run = ParallelRun.load(root, feature)
|
|
323
|
-
|
|
324
|
-
raise ArgumentError, "recovery did not produce an all-succeeded run"
|
|
325
|
-
end
|
|
335
|
+
recovery_check(Array(final_run["branches"]).all? { |branch| branch["status"] == "succeeded" }, "recovery did not produce an all-succeeded run; branch statuses preserved")
|
|
326
336
|
append_audit(root, feature, {
|
|
327
337
|
"schema_version" => 1, "origin" => "core.parallel_recovery/v1", "event" => "branches_recovered",
|
|
328
338
|
"recovery_id" => recovery, "reason" => options[:reason], "run_id" => final_run["run_id"],
|
|
@@ -382,5 +392,6 @@ rescue StandardError => error
|
|
|
382
392
|
result = { "ok" => false, "reason" => "parallel_recovery_refused", "message" => error.message, "recovery_id" => recovery }
|
|
383
393
|
end
|
|
384
394
|
|
|
395
|
+
result["warnings"] = $recovery_advisories + Array(result.dig("details", "advisories")) unless $recovery_advisories.empty?
|
|
385
396
|
puts(options[:json] ? JSON.generate(result) : JSON.pretty_generate(result))
|
|
386
397
|
exit exit_status
|
|
@@ -6,6 +6,8 @@ require "json"
|
|
|
6
6
|
require "optparse"
|
|
7
7
|
require "yaml"
|
|
8
8
|
require_relative "control_io"
|
|
9
|
+
require_relative "artifact_specs"
|
|
10
|
+
require_relative "gate_policy"
|
|
9
11
|
require_relative "validate_state"
|
|
10
12
|
require_relative "phase_ownership"
|
|
11
13
|
|
|
@@ -30,7 +32,7 @@ end
|
|
|
30
32
|
def build_registry(root, workflow, state)
|
|
31
33
|
checks = workflow.dig("artifact_registry", "content_checks") || {}
|
|
32
34
|
artifacts = Array(workflow["steps"]).flat_map do |step|
|
|
33
|
-
|
|
35
|
+
ArtifactSpecs.for_step(step).map do |output|
|
|
34
36
|
path = interpolate_path(output.fetch("path"), state)
|
|
35
37
|
abs, = DevflowControlIO.resolve_control_path(root, path, :artifact)
|
|
36
38
|
exists = File.exist?(abs)
|
|
@@ -90,9 +92,7 @@ begin
|
|
|
90
92
|
output_path, = DevflowControlIO.resolve_control_path(root, path, :artifact)
|
|
91
93
|
path unless File.exist?(output_path)
|
|
92
94
|
end.compact
|
|
93
|
-
if
|
|
94
|
-
result = { "ok" => false, "classification" => "unsafe", "reason" => "missing_required_output", "missing_outputs" => missing_current_outputs, "plan" => { "state_transition" => "none", "registry_write" => false } }
|
|
95
|
-
elsif !validation["ok"]
|
|
95
|
+
if !validation["ok"]
|
|
96
96
|
result = { "ok" => false, "classification" => "unsafe", "reason" => "ambiguous_or_invalid_state", "issues" => validation["errors"], "plan" => { "state_transition" => "none", "registry_write" => false } }
|
|
97
97
|
elsif !options[:confirm] || !options[:write]
|
|
98
98
|
result = { "ok" => false, "classification" => "safe_repairable", "reason" => "confirmation_required", "revision" => state.fetch("revision", 0), "plan" => { "state_transition" => "none", "registry_write" => true, "registry" => candidate } }
|
|
@@ -8,6 +8,8 @@ require "json"
|
|
|
8
8
|
require "optparse"
|
|
9
9
|
require "yaml"
|
|
10
10
|
require_relative "control_io"
|
|
11
|
+
require_relative "artifact_specs"
|
|
12
|
+
require_relative "gate_policy"
|
|
11
13
|
require_relative "phase_ownership"
|
|
12
14
|
|
|
13
15
|
options = {
|
|
@@ -56,7 +58,7 @@ end
|
|
|
56
58
|
|
|
57
59
|
def collect_outputs(workflow)
|
|
58
60
|
Array(workflow["steps"]).flat_map do |step|
|
|
59
|
-
|
|
61
|
+
ArtifactSpecs.for_step(step).map do |output|
|
|
60
62
|
[step, output]
|
|
61
63
|
end
|
|
62
64
|
end
|
|
@@ -33,8 +33,7 @@ module WorkflowStateValidator
|
|
|
33
33
|
# Core quality checks are advisory by default. Keep only structural and
|
|
34
34
|
# write-safety failures hard; AI review decides whether business-quality
|
|
35
35
|
# drift, stale metadata, or incomplete generated evidence should pause work.
|
|
36
|
-
|
|
37
|
-
HARD_VALIDATION_CODES = %w[
|
|
36
|
+
OPERATION_VALIDATION_CODES = %w[
|
|
38
37
|
invalid_control_path
|
|
39
38
|
missing_state_file
|
|
40
39
|
missing_state_front_matter
|
|
@@ -44,36 +43,8 @@ module WorkflowStateValidator
|
|
|
44
43
|
workflow_step_unknown
|
|
45
44
|
phase_ownership_conflict
|
|
46
45
|
].freeze
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
acceptance_results_not_passed
|
|
50
|
-
execution_surface_mismatch
|
|
51
|
-
approval_invalid
|
|
52
|
-
human_result_unapproved
|
|
53
|
-
dsl_not_approved
|
|
54
|
-
environment_profile_not_approved
|
|
55
|
-
runtime_integrity_error
|
|
56
|
-
acceptance_tests_not_passed
|
|
57
|
-
acceptance_tests_empty
|
|
58
|
-
acceptance_test_suite_freeze_failed
|
|
59
|
-
acceptance_test_suite_freeze_attestation_invalid
|
|
60
|
-
acceptance_test_suite_freeze_attestation_failed
|
|
61
|
-
acceptance_test_suite_candidate_binding_failed
|
|
62
|
-
acceptance_test_suite_freeze_recovery_failed
|
|
63
|
-
].freeze
|
|
64
|
-
|
|
65
|
-
def self.hard_validation_code?(code)
|
|
66
|
-
value = code.to_s
|
|
67
|
-
return true if HARD_VALIDATION_CODES.include?(value)
|
|
68
|
-
return true if ACCEPTANCE_HARD_VALIDATION_CODES.include?(value)
|
|
69
|
-
return true if value.start_with?("artifact_registry_", "parallel_", "PARALLEL_")
|
|
70
|
-
return true if value.start_with?("duplicate_", "unknown_", "missing_tracked_step")
|
|
71
|
-
return true if value.start_with?("step_in_", "completed_", "terminal_", "non_completed_")
|
|
72
|
-
return true if value.start_with?("waiting_checkpoint_")
|
|
73
|
-
return true if value.start_with?("skipped_")
|
|
74
|
-
return true if %w[missing_required_output output_not_registered].include?(value)
|
|
75
|
-
|
|
76
|
-
false
|
|
46
|
+
def self.operation_validation_code?(code)
|
|
47
|
+
OPERATION_VALIDATION_CODES.include?(code.to_s)
|
|
77
48
|
end
|
|
78
49
|
|
|
79
50
|
module_function
|
|
@@ -159,14 +130,12 @@ module WorkflowStateValidator
|
|
|
159
130
|
end
|
|
160
131
|
end
|
|
161
132
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
next if hard_validation_code?(entry["code"])
|
|
133
|
+
issues.each do |entry|
|
|
134
|
+
next unless entry["severity"] == "error"
|
|
135
|
+
next if operation_validation_code?(entry["code"])
|
|
166
136
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
end
|
|
137
|
+
entry["severity"] = "warning"
|
|
138
|
+
entry["soft_gate"] = true
|
|
170
139
|
end
|
|
171
140
|
ok = issues.none? { |entry| entry["severity"] == "error" }
|
|
172
141
|
result(ok, state_path, workflow_path, registry_path, issues)
|
|
@@ -107,10 +107,46 @@ def canonical_fingerprint(canonical)
|
|
|
107
107
|
end
|
|
108
108
|
|
|
109
109
|
def read_source_fingerprint(root, feature)
|
|
110
|
-
|
|
111
|
-
|
|
110
|
+
units_path, = DevflowControlIO.resolve_control_path(root, ".devflow/planning/requirements/#{feature}/source_units.yaml", :artifact)
|
|
111
|
+
# Core source unitization owns this value. Both the baseline template and
|
|
112
|
+
# graph-generated traceability views legitimately omit the legacy mirror.
|
|
113
|
+
traceability_path, = DevflowControlIO.resolve_control_path(root, ".devflow/planning/requirements/#{feature}/traceability.json", :artifact)
|
|
114
|
+
legacy = if File.file?(traceability_path)
|
|
115
|
+
traceability = JSON.parse(File.read(traceability_path))
|
|
116
|
+
raise ArgumentError, "traceability.json must be an object" unless traceability.is_a?(Hash)
|
|
117
|
+
traceability["source_document_fingerprint"].to_s
|
|
118
|
+
else
|
|
119
|
+
""
|
|
120
|
+
end
|
|
121
|
+
unless File.exist?(units_path) || File.symlink?(units_path)
|
|
122
|
+
return legacy unless legacy.strip.empty?
|
|
112
123
|
|
|
113
|
-
|
|
124
|
+
raise ArgumentError, "source_units.yaml is missing and traceability.json has no legacy source_document_fingerprint; restore requirement-wayfinder source provenance"
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
units = YAML.safe_load(File.read(units_path), permitted_classes: [], aliases: false)
|
|
128
|
+
raise ArgumentError, "source_units.yaml must be an object" unless units.is_a?(Hash)
|
|
129
|
+
fingerprint = units["source_document_fingerprint"].to_s
|
|
130
|
+
digest = fingerprint.delete_prefix("sha256:")
|
|
131
|
+
unless digest.match?(/\A[0-9a-f]{64}\z/)
|
|
132
|
+
raise ArgumentError, "source_units.yaml source_document_fingerprint must be a SHA-256 digest"
|
|
133
|
+
end
|
|
134
|
+
source = units["source_document"].to_s
|
|
135
|
+
if source.empty? || Pathname.new(source).absolute? || source.split(/[\\\/]/).include?("..")
|
|
136
|
+
raise ArgumentError, "source_units.yaml source_document must be a project-relative path"
|
|
137
|
+
end
|
|
138
|
+
root_real = File.realpath(root)
|
|
139
|
+
source_path = File.realpath(File.join(root_real, source))
|
|
140
|
+
unless source_path.start_with?(root_real + File::SEPARATOR)
|
|
141
|
+
raise ArgumentError, "source_units.yaml source_document escapes project root"
|
|
142
|
+
end
|
|
143
|
+
unless Digest::SHA256.file(source_path).hexdigest == digest
|
|
144
|
+
raise ArgumentError, "source_units.yaml source_document_fingerprint is stale; regenerate source units and review the changed requirements"
|
|
145
|
+
end
|
|
146
|
+
unless legacy.empty? || legacy.delete_prefix("sha256:") == digest
|
|
147
|
+
raise ArgumentError, "traceability.json source_document_fingerprint conflicts with source_units.yaml; reconcile requirement provenance"
|
|
148
|
+
end
|
|
149
|
+
fingerprint
|
|
114
150
|
end
|
|
115
151
|
|
|
116
152
|
def verify_business_action_refs(canonical, path)
|
package/plugins/devflow-core/skills/workflow-orchestrator/templates/feature-development.yaml
CHANGED
|
@@ -13,13 +13,12 @@ phase_scope:
|
|
|
13
13
|
failure_branch_enabled: true
|
|
14
14
|
parallel_window_enabled: true
|
|
15
15
|
|
|
16
|
-
#
|
|
16
|
+
# Gate checks are advisory. Existing STATE
|
|
17
17
|
# files without governance_started_revision remain legacy_unattested and are
|
|
18
18
|
# only reported until their next newly-started governed step.
|
|
19
19
|
governance:
|
|
20
20
|
# Chain skill owns orchestration while Core remains an evidence/diagnostic
|
|
21
|
-
# service.
|
|
22
|
-
hard_gate_mode: chain
|
|
21
|
+
# service. Core checks only produce diagnostics.
|
|
23
22
|
gate_contract_version: 3
|
|
24
23
|
requirement_graph_gate: enforced
|
|
25
24
|
requirement_coverage_gate: enforced
|
|
@@ -3,11 +3,16 @@ name: workflow-pipeline
|
|
|
3
3
|
description: Use when running or resuming the full .devflow/planning delivery pipeline from requirements through implementation, frozen acceptance tests, and Devflow release closeout.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
+
## 默认软门禁策略
|
|
7
|
+
|
|
8
|
+
工作流硬门禁已移除。下文及各步骤中的产物、索引、合同、审查、质量、恢复和 CP 审批条件均为诊断建议:保留失败证据和缺项,允许继续执行。用户说“下一步”即可推进,无需额外批准弹窗;不得把继续执行记录成人工批准,也不得把失败、未执行的测试改写为通过。真实读写/执行失败、无法解析的状态和并发版本冲突须如实报告。硬门禁及其恢复开关已移除。
|
|
9
|
+
|
|
10
|
+
|
|
6
11
|
<objective>
|
|
7
12
|
全链路研发交付入口。解析用户参数,先确保需求主链“入口分诊 → 探索地图 → 领域建模 → 可实现性审查”完成,再检测当前状态,然后委托 workflow-orchestrator 接管后续所有步骤调度。
|
|
8
13
|
pipeline 本身不包含执行规则——所有门禁、CP 协议、失败分支、并行窗口、lessons 注入规则均由 orchestrator 维护。
|
|
9
14
|
|
|
10
|
-
当前迁移阶段由本 skill 作为链路编排器:按 `next_step.skill` 依次调用各技能、传递上一技能的产物与诊断、再决定下一技能。Core 的 contract/checker/output/review 硬门禁暂不参与阻断;Core
|
|
15
|
+
当前迁移阶段由本 skill 作为链路编排器:按 `next_step.skill` 依次调用各技能、传递上一技能的产物与诊断、再决定下一技能。Core 的 contract/checker/output/review 硬门禁暂不参与阻断;Core 结果只作为事实和风险提示。真实操作无法完成时报告原因;CP 默认带警告继续,仅显式恢复确认时等待人工决定。
|
|
11
16
|
</objective>
|
|
12
17
|
|
|
13
18
|
<process>
|
|
@@ -55,10 +60,10 @@ pipeline 本身不包含执行规则——所有门禁、CP 协议、失败分
|
|
|
55
60
|
|
|
56
61
|
- **`--track A`**:后端/API 轨道产物模式。可跑 `requirement-triage → requirement-wayfinder → domain-modeling → requirement-feasibility-review → requirement-baseline → api-contract → architecture-feasibility → backend-tech-spec → api-call-guide`,但不能自动进入 `integration-verify / change-plan / execute`。
|
|
57
62
|
- **`--track B`**:前端/UI 轨道产物模式。要求 `api-contract` 与 `architecture-feasibility` 已完成;新需求从需求主链开始,已有共同事实可跑 `ui-spec → feature-breakdown → frontend-tech-spec`,但不能自动进入 `change-plan / execute`。
|
|
58
|
-
- **未设置 track
|
|
63
|
+
- **未设置 track**:完整交付模式。完成双轨并执行 `integration-verify` 检查;未通过项作为风险传给 `change-plan`。
|
|
59
64
|
- **`--no-review`**:保留参数位,但当前双轨 workflow 不自动跳过 CP-2。Merge Gate 不能跳过。
|
|
60
65
|
|
|
61
|
-
双轨制原则:API 契约是分叉前的共同事实,`integration-verify`
|
|
66
|
+
双轨制原则:API 契约是分叉前的共同事实,`integration-verify` 是合并前的软门禁。单轨只产出局部轨道文档,不代表完整交付。
|
|
62
67
|
|
|
63
68
|
`workflow-generate-mainflow-cases` 不是独立 workflow step,而是 `run-acceptance-tests` 绑定阶段的组成部分:对执行面为 `ui` / `api_flow` 且绑定为 `automated` 的 TC,必须先生成 v1 DSL 并经 `devflow_approval` 批准执行计划,否则该 TC 保持 blocked。人工 TC 结果同样只经 `human_result` 批准计入聚合门禁。
|
|
64
69
|
|
|
@@ -72,7 +77,7 @@ pipeline 本身不包含执行规则——所有门禁、CP 协议、失败分
|
|
|
72
77
|
2. `workflow-wayfinder` 建立目标、已知事实、边界、迷雾与 ticket;只有活动切片的 L1/L2 迷雾收束后才可完成。
|
|
73
78
|
3. `workflow-domain-modeling` 固化共同语言、所有权、状态和边缘案例。
|
|
74
79
|
4. `requirement-feasibility-review` 以流程证明、代码事实和外部能力检查作为进入基线前的最终门禁。
|
|
75
|
-
5.
|
|
80
|
+
5. 检查审查 meta 的 `baseline_gate`,未通过项保留为诊断并传给 `workflow-requirement-baseline`。
|
|
76
81
|
|
|
77
82
|
若分诊结论为 `already_done`、`wontfix`、`ready_for_human` 或 `needs_info`,停止主链并报告最小下一步。`workflow-demand-clarify` 不再作为固定主链步骤;需要业务问答时,由 Wayfinder 的 Grilling ticket 调用。
|
|
78
83
|
|
|
@@ -113,7 +118,7 @@ devflow_state(action="inspect")
|
|
|
113
118
|
|
|
114
119
|
## 3. 委托 orchestrator
|
|
115
120
|
|
|
116
|
-
|
|
121
|
+
当前pipeline 继续调用 `workflow-orchestrator` 获取步骤拓扑,但由本链路规则串联实际技能调用,不把 Core gate 的 `block` 结果当作自动停止条件:
|
|
117
122
|
|
|
118
123
|
```
|
|
119
124
|
/workflow-orchestrator
|
|
@@ -41,7 +41,7 @@ workflow-pipeline
|
|
|
41
41
|
→ 完成
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
`workflow-generate-mainflow-cases` 不参与独立排序,而是 `run-acceptance-tests` 绑定阶段的组成部分:automated 的 ui / api_flow TC 需要先生成 v1 DSL 并批准执行计划。人工验收结果(经 `human_result`
|
|
44
|
+
`workflow-generate-mainflow-cases` 不参与独立排序,而是 `run-acceptance-tests` 绑定阶段的组成部分:automated 的 ui / api_flow TC 需要先生成 v1 DSL 并批准执行计划。人工验收结果(经 `human_result` 批准)会与自动执行结果聚合,验收失败是软门禁:保留 failed/blocked 结果与风险,默认不阻止流程推进或收口。
|
|
45
45
|
|
|
46
46
|
## 双轨与 Checkpoint 规则
|
|
47
47
|
|
|
@@ -3,6 +3,8 @@ name: workflow-project-context
|
|
|
3
3
|
description: "Use when a project needs database-backed initialization, repository discovery, project facts, code indexing, navigation, or initialization recovery."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
+
门禁策略:默认软门禁,门禁行为以本段为准。本文及引用材料中的前置检查、审查、质量、完成条件和 CP 确认用于诊断;未满足时记录缺项、风险与后续处理,继续可执行的工作,不自动阻断阶段推进。保留真实的 failed/blocked/未审批状态,不把继续执行写成通过或人工批准。硬门禁及其恢复开关已移除。
|
|
7
|
+
|
|
6
8
|
# Project Initialization
|
|
7
9
|
|
|
8
10
|
Initialize project context only. Do not create requirements, approved API contracts, prototypes, roadmaps, commits, tags, repositories, or workflow state.
|
|
@@ -3,6 +3,8 @@ name: workflow-api-call-guide
|
|
|
3
3
|
description: "Use after backend-tech-spec, before integration-verify. Generates a step-by-step API call guide for frontend developers. This is NOT a change list — no code changes, just calling instructions based on the confirmed API contract and backend tech spec."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
+
门禁策略:默认软门禁,门禁行为以本段为准。本文及引用材料中的前置检查、审查、质量、完成条件和 CP 确认用于诊断;未满足时记录缺项、风险与后续处理,继续可执行的工作,不自动阻断阶段推进。保留真实的 failed/blocked/未审批状态,不把继续执行写成通过或人工批准。硬门禁及其恢复开关已移除。
|
|
7
|
+
|
|
6
8
|
# API 调用指南
|
|
7
9
|
|
|
8
10
|
## 定位
|
|
@@ -3,6 +3,8 @@ name: workflow-api-contract
|
|
|
3
3
|
description: "Use after requirement-baseline, before dual-track fork. Defines shared API contracts (endpoints, request/response shapes, data models) that both Track A and Track B reference. This is the fork point — contract changes after this step are exception paths."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
+
门禁策略:默认软门禁,门禁行为以本段为准。本文及引用材料中的前置检查、审查、质量、完成条件和 CP 确认用于诊断;未满足时记录缺项、风险与后续处理,继续可执行的工作,不自动阻断阶段推进。保留真实的 failed/blocked/未审批状态,不把继续执行写成通过或人工批准。硬门禁及其恢复开关已移除。
|
|
7
|
+
|
|
6
8
|
# API 契约生成器
|
|
7
9
|
|
|
8
10
|
## 定位
|
|
@@ -27,7 +29,7 @@ description: "Use after requirement-baseline, before dual-track fork. Defines sh
|
|
|
27
29
|
- `.devflow/planning/features/{功能名}/api-contract.md`
|
|
28
30
|
- `.devflow/planning/features/{功能名}/api-contract.meta.json`
|
|
29
31
|
|
|
30
|
-
The meta file must also set `traceability_status: "passed"` only after every API design has been written to `traceability.json.designs` and `traceability_check.py --stage design` succeeds; otherwise set `failed
|
|
32
|
+
The meta file must also set `traceability_status: "passed"` only after every API design has been written to `traceability.json.designs` and `traceability_check.py --stage design` succeeds; otherwise set `failed`, record the traceability gaps, and continue with these advisories in soft mode.
|
|
31
33
|
|
|
32
34
|
## 输入
|
|
33
35
|
|
|
@@ -3,6 +3,8 @@ name: workflow-api-supplement
|
|
|
3
3
|
description: "Use when Track B (frontend-tech-spec) discovers API gaps that the shared API contract doesn't cover. This is an EXCEPTION PATH — not a normal pipeline step. Submits API supplement requests for Track A evaluation."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
+
门禁策略:默认软门禁,门禁行为以本段为准。本文及引用材料中的前置检查、审查、质量、完成条件和 CP 确认用于诊断;未满足时记录缺项、风险与后续处理,继续可执行的工作,不自动阻断阶段推进。保留真实的 failed/blocked/未审批状态,不把继续执行写成通过或人工批准。硬门禁及其恢复开关已移除。
|
|
7
|
+
|
|
6
8
|
# API 补充需求(异常路径)
|
|
7
9
|
|
|
8
10
|
## 定位
|
|
@@ -3,6 +3,8 @@ name: workflow-architecture-feasibility
|
|
|
3
3
|
description: "Use after API contract and before frontend/backend technical specifications to compare implementation paths against confirmed workload facts and repository-static context. Use for async or scheduled work, batch operations, external calls, fanout, migrations, workload/SLA constraints, or when a feature may not fit the current framework and integrations."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
+
门禁策略:默认软门禁,门禁行为以本段为准。本文及引用材料中的前置检查、审查、质量、完成条件和 CP 确认用于诊断;未满足时记录缺项、风险与后续处理,继续可执行的工作,不自动阻断阶段推进。保留真实的 failed/blocked/未审批状态,不把继续执行写成通过或人工批准。硬门禁及其恢复开关已移除。
|
|
7
|
+
|
|
6
8
|
# 架构可行性与方案比较
|
|
7
9
|
|
|
8
10
|
生成一份由 Core 派生的架构简报;不把自由 Markdown 当作架构真相,也不把仓库声明当成生产容量。
|
|
@@ -3,6 +3,8 @@ name: workflow-backend-tech-spec
|
|
|
3
3
|
description: "Use when a requirement baseline needs a backend technical design, including API, data model, affected modules, integration points, and risks."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
+
门禁策略:默认软门禁,门禁行为以本段为准。本文及引用材料中的前置检查、审查、质量、完成条件和 CP 确认用于诊断;未满足时记录缺项、风险与后续处理,继续可执行的工作,不自动阻断阶段推进。保留真实的 failed/blocked/未审批状态,不把继续执行写成通过或人工批准。硬门禁及其恢复开关已移除。
|
|
7
|
+
|
|
6
8
|
## Legacy Command Metadata
|
|
7
9
|
|
|
8
10
|
Original slash-command metadata retained only as workflow invocation guidance.
|
|
@@ -109,7 +111,7 @@ allowed-tools:
|
|
|
109
111
|
- 是否对接了外部系统,需要统一的 Client 接口封装?
|
|
110
112
|
- 是否有独立的配置、认证、错误处理逻辑?
|
|
111
113
|
满足任一条件的,应在方案中定义能力接口(Client interface + 参数/结果结构体),参考已有 `pkg/wx_red_pack`、`pkg/wx_pay` 的模式设计。
|
|
112
|
-
10. **执行被影响方探索**:读取 `references/affected-module-exploration.md`,对 baseline 第8.2节"关联历史功能/模块"表格列出的每个受影响模块,按清单逐项读取代码并产出:现状流程图、现有字段/方法表格、集成点列表、复用/扩展/新增决策。探索产出直接填入输出文档的"现有功能说明"(第四章)和"影响范围"
|
|
114
|
+
10. **执行被影响方探索**:读取 `references/affected-module-exploration.md`,对 baseline 第8.2节"关联历史功能/模块"表格列出的每个受影响模块,按清单逐项读取代码并产出:现状流程图、现有字段/方法表格、集成点列表、复用/扩展/新增决策。探索产出直接填入输出文档的"现有功能说明"(第四章)和"影响范围"(第六章)。**探索产出检查不通过时记录缺项与影响,可继续 Phase 3。**
|
|
113
115
|
|
|
114
116
|
**关键:如果发现多个相似功能,必须询问用户使用哪个。**
|
|
115
117
|
如果与 baseline 中的用户拍板结果冲突,停止并要求重新确认,不要自行改判。
|
|
@@ -156,7 +158,7 @@ allowed-tools:
|
|
|
156
158
|
| FP-003 | OrderWorkflow(新建) | 新建独立模块 | 用户确认 |
|
|
157
159
|
```
|
|
158
160
|
|
|
159
|
-
|
|
161
|
+
**软门禁**:检查每个 FP 的 seam 确认记录,缺项记为待确认并传入 Phase 3。
|
|
160
162
|
|
|
161
163
|
### 第三阶段:生成文档
|
|
162
164
|
|
|
@@ -233,14 +235,14 @@ If an older baseline still points to root `features/{功能名}/`, treat that as
|
|
|
233
235
|
12. **遵循最佳实践标杆** — 新功能的设计(分层、命名、错误处理、参数封装、测试模式)必须与项目内已有标杆功能保持一致,不得引入与项目验证过的成熟模式相悖的新模式。若需偏离,必须在方案中说明理由
|
|
234
236
|
13. **能力抽象** — 新功能中具有独立复用价值的部分(外部集成、通用业务能力),必须抽象为 `pkg/` 级模块,定义清晰的 Client 接口和参数/结果结构体,形成可被后续功能消费的项目能力资产
|
|
235
237
|
|
|
236
|
-
##
|
|
238
|
+
## 审查软门禁
|
|
237
239
|
|
|
238
240
|
### 反问审查
|
|
239
241
|
|
|
240
242
|
- [ ] 每个不确定的接口设计、库表变更、Job 逻辑是否已向用户确认?(禁止猜测,禁止自行决定)
|
|
241
243
|
- [ ] 涉及调用上游 API 的,是否已向用户索要接口文档并确认对接方案?(不可猜测 API 契约,包括 URL、认证、请求/响应结构、错误码)
|
|
242
244
|
- [ ] 涉及的每个能力点(外部集成、业务逻辑、数据访问、工具方法),是否已在项目内完成复用搜索?**若已有封装却被绕过直接重写,方案不合格。**
|
|
243
|
-
- [ ] `references/affected-module-exploration.md`
|
|
245
|
+
- [ ] `references/affected-module-exploration.md` 的探索产出检查是否全部通过?(现状流程图、字段/方法表格、集成点列表、复用/扩展/新增决策)**若不通过,记录待补充的代码探索与证据缺口,继续可完成的文档部分。**
|
|
244
246
|
- [ ] 若 `.devflow/planning/code-index/` 存在,复用/影响范围/调用链/读写资源判断是否已查询 code-index 并回读源码 evidence?若未使用,是否说明缺失或过期原因?
|
|
245
247
|
- [ ] 是否已找到项目内最佳实践标杆,并确认新功能的分层结构、命名、错误处理、参数封装模式与标杆一致?(若偏离,理由是否已写明?)
|
|
246
248
|
- [ ] 新功能中具有独立复用价值的部分,是否已识别并抽象为 `pkg/` 级能力模块?接口定义、参数/结果结构体是否清晰?
|
|
@@ -3,6 +3,8 @@ name: workflow-design-rule-pack
|
|
|
3
3
|
description: Use when workflow-ui-spec or workflow-frontend-tech-spec needs a reusable UI/UX design rule package, ui-ux-pro-max recommendations, or project installation of .devflow/context/spec/design across repositories.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
+
门禁策略:默认软门禁,门禁行为以本段为准。本文及引用材料中的前置检查、审查、质量、完成条件和 CP 确认用于诊断;未满足时记录缺项、风险与后续处理,继续可执行的工作,不自动阻断阶段推进。保留真实的 failed/blocked/未审批状态,不把继续执行写成通过或人工批准。硬门禁及其恢复开关已移除。
|
|
7
|
+
|
|
6
8
|
# Workflow Design Rule Pack
|
|
7
9
|
|
|
8
10
|
This skill provides the reusable source for the project design rule package consumed by `workflow-ui-spec` and `workflow-frontend-tech-spec`.
|
|
@@ -3,6 +3,8 @@ name: workflow-feature-breakdown
|
|
|
3
3
|
description: "Use when a requirement baseline needs a test-readable feature breakdown across style, functionality, logic, pages, components, fields, actions, and dialogs."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
+
门禁策略:默认软门禁,门禁行为以本段为准。本文及引用材料中的前置检查、审查、质量、完成条件和 CP 确认用于诊断;未满足时记录缺项、风险与后续处理,继续可执行的工作,不自动阻断阶段推进。保留真实的 failed/blocked/未审批状态,不把继续执行写成通过或人工批准。硬门禁及其恢复开关已移除。
|
|
7
|
+
|
|
6
8
|
## Legacy Command Metadata
|
|
7
9
|
|
|
8
10
|
Original slash-command metadata retained only as workflow invocation guidance.
|
|
@@ -3,6 +3,8 @@ name: workflow-frontend-tech-spec
|
|
|
3
3
|
description: "Use when a requirement baseline and UI specification need a frontend technical design covering routes, components, state, APIs, reuse, and risks."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
+
门禁策略:默认软门禁,门禁行为以本段为准。本文及引用材料中的前置检查、审查、质量、完成条件和 CP 确认用于诊断;未满足时记录缺项、风险与后续处理,继续可执行的工作,不自动阻断阶段推进。保留真实的 failed/blocked/未审批状态,不把继续执行写成通过或人工批准。硬门禁及其恢复开关已移除。
|
|
7
|
+
|
|
6
8
|
## Legacy Command Metadata
|
|
7
9
|
|
|
8
10
|
Original slash-command metadata retained only as workflow invocation guidance.
|
|
@@ -89,7 +91,7 @@ allowed-tools:
|
|
|
89
91
|
8. 查找 UI 组件库、设计系统、样式方案、状态管理和权限控制模式
|
|
90
92
|
9. 识别技术栈插槽:React、Next.js、Vue 或仅 Common Web,并记录未覆盖的框架为待确认/待扩展
|
|
91
93
|
10. 检查三层复用机会:已有页面/组件/交互模式、已有依赖/库、项目设计系统或代码模式;与 baseline 的复用决策保持一致
|
|
92
|
-
11. **执行被影响方探索**:读取 `references/affected-module-exploration.md`,对 baseline 第8.2节"关联历史功能/模块"表格列出的每个受影响的前端页面/组件,按清单逐项读取源码并产出:现有 props/emits/methods/API 调用清单、现有数据流和交互方式、保留/分支/抽离/新增决策。探索产出直接填入输出文档的"影响范围"
|
|
94
|
+
11. **执行被影响方探索**:读取 `references/affected-module-exploration.md`,对 baseline 第8.2节"关联历史功能/模块"表格列出的每个受影响的前端页面/组件,按清单逐项读取源码并产出:现有 props/emits/methods/API 调用清单、现有数据流和交互方式、保留/分支/抽离/新增决策。探索产出直接填入输出文档的"影响范围"章节和组件树。**探索产出检查不通过时记录缺项与影响,可继续 Phase 3。**
|
|
93
95
|
12. 如 `.devflow/context/spec/design/tools/ui-ux-pro-max/scripts/search.py` 存在,可按当前技术栈和 UI 场景补充查询:
|
|
94
96
|
```bash
|
|
95
97
|
python3 .devflow/context/spec/design/tools/ui-ux-pro-max/scripts/search.py "layout form table accessibility performance" --stack react
|
|
@@ -154,7 +156,7 @@ allowed-tools:
|
|
|
154
156
|
| OrderDetail | 新建 | props: 3 / events: 2 | ✅ 深 | 保持小接口 |
|
|
155
157
|
```
|
|
156
158
|
|
|
157
|
-
|
|
159
|
+
**软门禁**:检查每个界面/组件的 seam 决策记录(复用/扩展/新建),缺项记为待确认并传入 Phase 3。
|
|
158
160
|
|
|
159
161
|
1. 创建 `.devflow/planning/features/{功能名}/` 目录
|
|
160
162
|
2. 读取 `assets/frontend-spec-template.md` 模板
|
|
@@ -192,12 +194,12 @@ If an older baseline still points to root `features/{功能名}/`, treat that as
|
|
|
192
194
|
11. 与历史相关的判断优先来自 `.devflow/planning/milestones/`、`.devflow/planning/requirements/`、`.devflow/planning/lessons/` 和阶段 `CONTEXT.md`;`features/` 或 `.devflow/context/lessons/` 只作为目标项目存在时的兼容来源
|
|
193
195
|
12. 设计规则优先级为:用户拍板/设计稿事实/需求基线 > 现有代码与项目 token > `.devflow/context/spec/design/tokens/project-tokens.md` > `.devflow/context/spec/design/recommendations/` 与 `ui-ux-pro-max` 推荐。推荐项未经用户确认不得进入实现任务。
|
|
194
196
|
|
|
195
|
-
##
|
|
197
|
+
## 审查软门禁
|
|
196
198
|
|
|
197
199
|
### 反问审查
|
|
198
200
|
|
|
199
201
|
- [ ] 每个不确定的组件选择、路由设计、状态处理是否已向用户确认?(禁止猜测)
|
|
200
|
-
- [ ] `references/affected-module-exploration.md` 的探索产出检查是否全部通过?(现有 props/emits/methods/API
|
|
202
|
+
- [ ] `references/affected-module-exploration.md` 的探索产出检查是否全部通过?(现有 props/emits/methods/API 调用清单、保留/分支/抽离/新增决策)**若不通过,记录待补充的代码探索与证据缺口,继续可完成的文档部分。**
|
|
201
203
|
- [ ] 若 `.devflow/planning/code-index/` 存在,受影响页面/组件/API/store 的关系定位是否已查询 code-index 并回读源码 evidence?若未使用,是否说明缺失或过期原因?
|
|
202
204
|
- [ ] 方案影响的现有页面/组件是否已描述其**现状**?(先描述现状,再分析影响)
|
|
203
205
|
- [ ] loading/empty/error/permission/disabled/duplicate/responsive 等状态是否均已覆盖或标记待确认?
|
|
@@ -3,6 +3,8 @@ name: workflow-integration-verify
|
|
|
3
3
|
description: "Use after both Track A (api-call-guide) and Track B (frontend-tech-spec) complete. Performs Merge Gate verification: cross-check backend API implementation against the API contract and frontend's API calling patterns. Outputs an integration report."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
+
门禁策略:默认软门禁,门禁行为以本段为准。本文及引用材料中的前置检查、审查、质量、完成条件和 CP 确认用于诊断;未满足时记录缺项、风险与后续处理,继续可执行的工作,不自动阻断阶段推进。保留真实的 failed/blocked/未审批状态,不把继续执行写成通过或人工批准。硬门禁及其恢复开关已移除。
|
|
7
|
+
|
|
6
8
|
# 联调验证(Merge Gate)
|
|
7
9
|
|
|
8
10
|
## 定位
|
|
@@ -114,7 +116,7 @@ description: "Use after both Track A (api-call-guide) and Track B (frontend-tech
|
|
|
114
116
|
1. 将后端、前端、UI、API 契约中的设计项写入 `traceability.json.designs`,每项以 `requirements: ["REQ-…"]` 回指来源。
|
|
115
117
|
2. 所有 API 类型设计必须在 `contract` 中同时写 `request`、`response`、`errors`、`behavior`;禁止只对齐响应字段。
|
|
116
118
|
3. 执行 `python3 <workflow-orchestrator>/scripts/traceability_check.py --file .devflow/planning/requirements/{feature}/traceability.json --stage design`。
|
|
117
|
-
4. 结果不为 passed 时,`merge_gate_status` 必须为 failed,`blocking_issue_count` 必须大于 0
|
|
119
|
+
4. 结果不为 passed 时,`merge_gate_status` 必须为 failed,`blocking_issue_count` 必须大于 0,建议回到对应方案修复;默认携带未解决项进入变更清单。
|
|
118
120
|
|
|
119
121
|
## 产出模板
|
|
120
122
|
|
|
@@ -3,6 +3,8 @@ name: workflow-ui-spec
|
|
|
3
3
|
description: "Use when UI designs, screenshots, Figma exports, Lanhu notes, or manual UI descriptions need a structured UI specification."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
+
门禁策略:默认软门禁,门禁行为以本段为准。本文及引用材料中的前置检查、审查、质量、完成条件和 CP 确认用于诊断;未满足时记录缺项、风险与后续处理,继续可执行的工作,不自动阻断阶段推进。保留真实的 failed/blocked/未审批状态,不把继续执行写成通过或人工批准。硬门禁及其恢复开关已移除。
|
|
7
|
+
|
|
6
8
|
## Legacy Command Metadata
|
|
7
9
|
|
|
8
10
|
Original slash-command metadata retained only as workflow invocation guidance.
|
|
@@ -262,7 +264,7 @@ UI-SPEC 不写代码细节(那是前端技术方案的事),但必须把 UI
|
|
|
262
264
|
## 10. 审查结论
|
|
263
265
|
```
|
|
264
266
|
|
|
265
|
-
##
|
|
267
|
+
## 审查软门禁
|
|
266
268
|
|
|
267
269
|
### 设计完整性
|
|
268
270
|
|
|
@@ -299,4 +301,4 @@ UI-SPEC 不写代码细节(那是前端技术方案的事),但必须把 UI
|
|
|
299
301
|
| 冲突嗅探 | 设计 Token 是否与现有变量命名/值冲突? |
|
|
300
302
|
| 需求对齐 | 设计稿中的交互是否与需求基线的用户拍板决策一致? |
|
|
301
303
|
|
|
302
|
-
|
|
304
|
+
**审查结论不通过时,记录问题与影响,携带诊断进入功能点梳理阶段。**
|
|
@@ -18,14 +18,8 @@ autoloadSkills:
|
|
|
18
18
|
|
|
19
19
|
Implement only the assigned plan slice. Do not re-plan the feature, compare alternatives, or explore unrelated modules. Read only the approved files, their immediate dependencies, and the focused tests needed for this slice. Preserve unrelated work and report deviations instead of silently expanding scope.
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
files in the exact order listed by INDEX_GATE (typically `.devflow/planning/code-index/INDEX.md`
|
|
23
|
-
followed by the ordered files named by the gate). Do not attempt `grep`, `rg`, or source
|
|
24
|
-
reads first: each subagent has its own evidence session and cannot inherit the parent's
|
|
25
|
-
observations. If the gate lists different files, follow that list exactly.
|
|
21
|
+
Read relevant code-index evidence when available; each subagent has its own evidence session. In default soft mode, a missing/stale index or execution contract is an advisory: report the gap and use bounded source reads to continue the assigned work. Missing or contradictory business facts remain explicit uncertainties. Report INDEX_GATE findings and any unavailable or conflicting execution contract, then continue executable work. Run the smallest focused validation once and report its actual result.
|
|
26
22
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
For a task whose frozen `test-bindings.json` marks `test_mode: tdd_required`, use the Core tool in this exact order: `devflow_tdd_evidence(action="prepare")` before changing declared production paths; create/change the test and record `red`; implement; record `green`; then record `regression`. Do not mark the task done if any phase is missing or fails. The tool may write only its own Core-owned TDD evidence record; this exception does not authorize edits to any other Devflow control-plane file.
|
|
23
|
+
For a task whose frozen `test-bindings.json` marks `test_mode: tdd_required`, use the Core tool in this exact order: `devflow_tdd_evidence(action="prepare")` before changing declared production paths; create/change the test and record `red`; implement; record `green`; then record `regression`. If any phase is missing or fails, preserve that result and report the evidence gap; default soft mode permits subsequent work without claiming TDD passed. The tool may write only its own Core-owned TDD evidence record; this exception does not authorize edits to any other Devflow control-plane file.
|
|
30
24
|
|
|
31
25
|
Return `STATUS`, changed files, validation evidence, and one escalation/blocker if needed. Never edit `.devflow/planning/STATE.md`, `.devflow/planning/artifacts/index.yaml`, workflow definitions, or checkpoint decisions; the parent session owns those through Devflow tools.
|