@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.
- package/package.json +1 -1
- package/plugins/devflow-core/extensions/devflow-core.ts +728 -39
- 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 +334 -30
- 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 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/cross_track_consistency_check.rb +94 -0
- 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 +84 -6
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/inspect_state.rb +3 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/machine_evidence.rb +45 -12
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/parallel_recover.rb +386 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/parallel_run.rb +248 -0
- 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 +86 -2
- 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/scripts/workflow_gate_contract.rb +94 -2
- package/plugins/devflow-core/skills/workflow-orchestrator/templates/feature-development.yaml +111 -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 +61 -24
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Core-owned, precise invalidation. It records only consumers that reference
|
|
5
|
+
# facts whose source refs changed; it never regenerates or semantically edits
|
|
6
|
+
# a consumer.
|
|
7
|
+
require "json"
|
|
8
|
+
require "optparse"
|
|
9
|
+
require "set"
|
|
10
|
+
require "time"
|
|
11
|
+
require "yaml"
|
|
12
|
+
require_relative "control_io"
|
|
13
|
+
|
|
14
|
+
options = { root: ".", feature: nil, canonical: nil, changed_source: [], registry: ".planning/artifacts/index.yaml", write: false, json: false }
|
|
15
|
+
OptionParser.new do |o|
|
|
16
|
+
o.on("--root PATH") { |v| options[:root] = v }
|
|
17
|
+
o.on("--feature NAME") { |v| options[:feature] = v }
|
|
18
|
+
o.on("--canonical PATH") { |v| options[:canonical] = v }
|
|
19
|
+
o.on("--changed-source ID") { |v| options[:changed_source] << v }
|
|
20
|
+
o.on("--registry PATH") { |v| options[:registry] = v }
|
|
21
|
+
o.on("--write") { options[:write] = true }
|
|
22
|
+
o.on("--json") { options[:json] = true }
|
|
23
|
+
end.parse!
|
|
24
|
+
|
|
25
|
+
def all_refs(value, changed, found = [])
|
|
26
|
+
case value
|
|
27
|
+
when Hash
|
|
28
|
+
found.concat(Array(value["source_refs"]) & changed)
|
|
29
|
+
value.each_value { |child| all_refs(child, changed, found) }
|
|
30
|
+
when Array
|
|
31
|
+
value.each { |child| all_refs(child, changed, found) }
|
|
32
|
+
end
|
|
33
|
+
found.uniq
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def read_json(path)
|
|
37
|
+
JSON.parse(File.read(path))
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
root = File.realpath(options[:root])
|
|
41
|
+
lock = nil
|
|
42
|
+
begin
|
|
43
|
+
raise ArgumentError, "feature is required" if options[:feature].to_s.empty?
|
|
44
|
+
raise ArgumentError, "at least one changed source is required" if options[:changed_source].empty?
|
|
45
|
+
canonical_path = options[:canonical] || ".planning/business-model/#{options[:feature]}/canonical.json"
|
|
46
|
+
canonical_absolute, canonical_relative = DevflowControlIO.resolve_control_path(root, canonical_path, :artifact)
|
|
47
|
+
model = read_json(canonical_absolute)
|
|
48
|
+
changed = options[:changed_source].uniq
|
|
49
|
+
affected = []
|
|
50
|
+
%w[actors entities components boundaries resources rules actions].each do |collection|
|
|
51
|
+
Array(model[collection]).each do |item|
|
|
52
|
+
next unless item.is_a?(Hash)
|
|
53
|
+
refs = all_refs(item, changed)
|
|
54
|
+
next if refs.empty?
|
|
55
|
+
affected << { "collection" => collection, "id" => item["id"], "changed_sources" => refs }
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
affected_ids = affected.map { |item| item["id"].to_s }.to_set
|
|
59
|
+
wireframe_relative = ".planning/features/#{options[:feature]}/canonical.json"
|
|
60
|
+
wireframe_path, = DevflowControlIO.resolve_control_path(root, wireframe_relative, :artifact)
|
|
61
|
+
consumers = []
|
|
62
|
+
if File.file?(wireframe_path)
|
|
63
|
+
wireframe = read_json(wireframe_path)
|
|
64
|
+
Array(wireframe["screens"]).each do |screen|
|
|
65
|
+
refs = Array(screen["actions"]).map { |action| action["business_action_ref"] if action.is_a?(Hash) && affected_ids.include?(action["business_action_ref"].to_s) }.compact.uniq
|
|
66
|
+
consumers << { "kind" => "wireframe", "path" => wireframe_relative, "screen_id" => screen["id"], "business_refs" => refs } unless refs.empty?
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
report = { "schema_version" => 1, "feature" => options[:feature], "canonical_path" => canonical_relative, "changed_sources" => changed.sort, "affected_facts" => affected, "affected_consumers" => consumers, "generated_at" => Time.now.utc.iso8601 }
|
|
70
|
+
if options[:write]
|
|
71
|
+
lock = DevflowControlIO.acquire_project_lock(root)
|
|
72
|
+
timestamp = Time.now.utc.iso8601
|
|
73
|
+
approval_relative = ".planning/features/#{options[:feature]}/approval.json"
|
|
74
|
+
approval_path, = DevflowControlIO.resolve_control_path(root, approval_relative, :artifact)
|
|
75
|
+
if !consumers.empty? && File.file?(approval_path)
|
|
76
|
+
approval = read_json(approval_path)
|
|
77
|
+
approval["status"] = "stale"
|
|
78
|
+
approval["invalidated_at"] = timestamp
|
|
79
|
+
approval["invalidated_by_business_sources"] = changed.sort
|
|
80
|
+
DevflowControlIO.atomic_write(approval_path, JSON.pretty_generate(approval) + "\n")
|
|
81
|
+
report["invalidated_paths"] = [approval_relative]
|
|
82
|
+
end
|
|
83
|
+
registry_path, registry_relative = DevflowControlIO.resolve_control_path(root, options[:registry], :registry)
|
|
84
|
+
if File.file?(registry_path) && !consumers.empty?
|
|
85
|
+
registry = YAML.safe_load(File.read(registry_path), permitted_classes: [], aliases: false) || {}
|
|
86
|
+
stale_paths = consumers.map { |consumer| consumer["path"] } + [approval_relative]
|
|
87
|
+
Array(registry["artifacts"]).each do |artifact|
|
|
88
|
+
next unless stale_paths.include?(artifact["path"])
|
|
89
|
+
artifact["status"] = "stale"
|
|
90
|
+
artifact["stale_reason"] = "business_source_changed"
|
|
91
|
+
artifact["invalidated_at"] = timestamp
|
|
92
|
+
end
|
|
93
|
+
DevflowControlIO.atomic_write(registry_path, registry.to_yaml.sub(/\A---\n/, ""))
|
|
94
|
+
report["registry_path"] = registry_relative
|
|
95
|
+
end
|
|
96
|
+
report_path = File.join(root, ".planning", "business-model", options[:feature], "invalidation.json")
|
|
97
|
+
DevflowControlIO.atomic_write(report_path, JSON.pretty_generate(report) + "\n")
|
|
98
|
+
report["written"] = true
|
|
99
|
+
else
|
|
100
|
+
report["written"] = false
|
|
101
|
+
end
|
|
102
|
+
puts(options[:json] ? JSON.pretty_generate(report) : report["affected_consumers"].length.to_s)
|
|
103
|
+
rescue StandardError => error
|
|
104
|
+
puts JSON.pretty_generate({ "ok" => false, "reason" => "business_invalidation_failed", "message" => error.message })
|
|
105
|
+
exit 1
|
|
106
|
+
ensure
|
|
107
|
+
DevflowControlIO.release_lock(lock)
|
|
108
|
+
end
|