@guanlin4924/devflow-pi 0.1.38 → 0.1.40
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 +178 -8
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/advance_state.rb +283 -1
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/checker_registry.rb +31 -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 +1 -1
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/gate_contract.rb +64 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/gate_result.rb +40 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/gate_runtime.rb +157 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/inspect_state.rb +3 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/machine_evidence.rb +112 -9
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/parallel_run.rb +222 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/requirement_coverage.rb +173 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/requirement_graph.rb +14 -8
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/validate_state.rb +131 -5
- package/plugins/devflow-core/skills/workflow-orchestrator/scripts/workflow_gate_contract.rb +148 -0
- package/plugins/devflow-core/skills/workflow-orchestrator/templates/feature-development.yaml +29 -0
- package/src/constants.ts +1 -1
- package/src/runtime.ts +8 -2
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Validates the existing workflow topology as a GateContract source. This is
|
|
5
|
+
# intentionally declarative and read-only: it does not advance STATE or alter
|
|
6
|
+
# failure-branch behavior.
|
|
7
|
+
require "json"
|
|
8
|
+
require "optparse"
|
|
9
|
+
require "yaml"
|
|
10
|
+
require_relative "checker_registry"
|
|
11
|
+
|
|
12
|
+
module WorkflowGateContract
|
|
13
|
+
CHECKPOINT_FIELDS = %w[gate_after producing_step required_outputs required_meta_output required_meta_fields prompt confirm_options skip_policy resume_behavior].freeze
|
|
14
|
+
|
|
15
|
+
module_function
|
|
16
|
+
|
|
17
|
+
def validate(workflow)
|
|
18
|
+
errors = []
|
|
19
|
+
unless workflow.is_a?(Hash)
|
|
20
|
+
return [error("WORKFLOW_SCHEMA_INVALID", "workflow must be a mapping")]
|
|
21
|
+
end
|
|
22
|
+
steps = Array(workflow["steps"])
|
|
23
|
+
step_by_id = steps.each_with_object({}) { |step, index| index[step["id"].to_s] = step if step.is_a?(Hash) && step["id"] }
|
|
24
|
+
checkpoints = workflow["checkpoints"]
|
|
25
|
+
unless checkpoints.is_a?(Hash)
|
|
26
|
+
return [error("CHECKPOINTS_SCHEMA_INVALID", "workflow checkpoints must be a mapping")]
|
|
27
|
+
end
|
|
28
|
+
checkpoints.each do |id, checkpoint|
|
|
29
|
+
unless checkpoint.is_a?(Hash)
|
|
30
|
+
errors << error("CHECKPOINT_SCHEMA_INVALID", "checkpoint must be a mapping", checkpoint: id)
|
|
31
|
+
next
|
|
32
|
+
end
|
|
33
|
+
CHECKPOINT_FIELDS.each do |field|
|
|
34
|
+
errors << error("CHECKPOINT_FIELD_MISSING", "checkpoint field is required", checkpoint: id, field: field) unless checkpoint.key?(field)
|
|
35
|
+
end
|
|
36
|
+
errors << error("CHECKPOINT_PRODUCER_MISMATCH", "gate_after must equal producing_step", checkpoint: id) if checkpoint["gate_after"].to_s != checkpoint["producing_step"].to_s
|
|
37
|
+
errors << error("CHECKPOINT_OUTPUTS_INVALID", "required_outputs must be an array", checkpoint: id) unless checkpoint["required_outputs"].is_a?(Array)
|
|
38
|
+
errors << error("CHECKPOINT_META_FIELDS_INVALID", "required_meta_fields must be an array", checkpoint: id) unless checkpoint["required_meta_fields"].is_a?(Array)
|
|
39
|
+
errors << error("CHECKPOINT_OPTIONS_INVALID", "confirm_options must include approve and needs_fix", checkpoint: id) unless Array(checkpoint["confirm_options"]).sort == %w[approve needs_fix]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
Array(workflow.dig("governance", "enforced_checkpoints")).each do |id|
|
|
43
|
+
errors << error("CHECKPOINT_REF_NOT_FOUND", "enforced checkpoint is not defined", checkpoint: id) unless checkpoints.key?(id)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
step_checkers = workflow.dig("governance", "step_checkers")
|
|
47
|
+
if step_checkers.is_a?(Hash)
|
|
48
|
+
step_checkers.each do |step_id, checker_ids|
|
|
49
|
+
errors << error("CHECKER_STEP_REF_NOT_FOUND", "checker declaration references an unknown step", step: step_id) unless step_by_id.key?(step_id.to_s)
|
|
50
|
+
Array(checker_ids).each do |checker_id|
|
|
51
|
+
errors << error("UNKNOWN_CHECKER_ID", "workflow references an unknown checker", step: step_id, checker: checker_id) unless CheckerRegistry.known?(checker_id)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
Array(workflow["parallel_windows"]).each do |window|
|
|
57
|
+
unless window.is_a?(Hash) && window["join_step"] && window["branches"].is_a?(Hash)
|
|
58
|
+
errors << error("PARALLEL_WINDOW_SCHEMA_INVALID", "parallel window must define join_step and branches", window: window.is_a?(Hash) && window["id"])
|
|
59
|
+
next
|
|
60
|
+
end
|
|
61
|
+
window_id = window["id"]
|
|
62
|
+
errors << error("PARALLEL_AFTER_STEP_NOT_FOUND", "parallel window after_step is not a workflow step", window: window_id, step: window["after_step"]) if window["after_step"] && !step_by_id.key?(window["after_step"].to_s)
|
|
63
|
+
errors << error("PARALLEL_JOIN_STEP_NOT_FOUND", "parallel join_step is not a workflow step", window: window_id, step: window["join_step"]) unless step_by_id.key?(window["join_step"].to_s)
|
|
64
|
+
errors << error("PARALLEL_WINDOW_CHECKPOINT_INVALID", "parallel join checkpoint is not defined", window: window["id"], checkpoint: window["checkpoint"]) if window["checkpoint"] && !checkpoints.key?(window["checkpoint"])
|
|
65
|
+
policy = window["execution_policy"]
|
|
66
|
+
scheduler = policy.is_a?(Hash) && policy["scheduler"]
|
|
67
|
+
unless scheduler.is_a?(Hash)
|
|
68
|
+
errors << error("PARALLEL_SCHEDULER_SCHEMA_INVALID", "parallel window must define execution_policy.scheduler", window: window_id)
|
|
69
|
+
else
|
|
70
|
+
errors << error("PARALLEL_SCHEDULER_FIELD_INVALID", "one_agent_per_step must be boolean", window: window_id, field: "one_agent_per_step") unless [true, false].include?(scheduler["one_agent_per_step"])
|
|
71
|
+
errors << error("PARALLEL_SCHEDULER_FIELD_INVALID", "max_concurrency must be a positive integer", window: window_id, field: "max_concurrency") unless scheduler["max_concurrency"].is_a?(Integer) && scheduler["max_concurrency"] > 0
|
|
72
|
+
errors << error("PARALLEL_SCHEDULER_FIELD_INVALID", "track_order must be declared", window: window_id, field: "track_order") unless scheduler["track_order"] == "declared"
|
|
73
|
+
end
|
|
74
|
+
errors << error("PARALLEL_BRANCH_STEPS_INVALID", "branch_steps must be an array", window: window_id) if window.key?("branch_steps") && !window["branch_steps"].is_a?(Array)
|
|
75
|
+
Array(window["branch_steps"]).each do |step_id|
|
|
76
|
+
errors << error("PARALLEL_BRANCH_STEP_NOT_FOUND", "branch_steps references an unknown step", window: window_id, step: step_id) unless step_by_id.key?(step_id.to_s)
|
|
77
|
+
end
|
|
78
|
+
branch_ids = []
|
|
79
|
+
step_tracks = {}
|
|
80
|
+
window["branches"].each do |track, branch_steps|
|
|
81
|
+
unless branch_steps.is_a?(Array) && !branch_steps.empty?
|
|
82
|
+
errors << error("PARALLEL_TRACK_STEPS_INVALID", "parallel track must contain an ordered step array", window: window_id, track: track)
|
|
83
|
+
next
|
|
84
|
+
end
|
|
85
|
+
positions = branch_steps.each_with_index.to_h { |step_id, position| [step_id.to_s, position] }
|
|
86
|
+
branch_steps.each_with_index do |step_id, position|
|
|
87
|
+
if positions.count { |candidate, _| candidate == step_id.to_s } > 1
|
|
88
|
+
errors << error("PARALLEL_TRACK_DUPLICATE_STEP", "parallel track repeats a step", window: window_id, track: track, step: step_id)
|
|
89
|
+
end
|
|
90
|
+
branch_ids << step_id.to_s
|
|
91
|
+
step_tracks[step_id.to_s] = track.to_s
|
|
92
|
+
errors << error("PARALLEL_BRANCH_STEP_NOT_FOUND", "parallel track references an unknown step", window: window_id, track: track, step: step_id) unless step_by_id.key?(step_id.to_s)
|
|
93
|
+
Array(step_by_id.dig(step_id.to_s, "depends_on")).each do |dependency|
|
|
94
|
+
dependency_position = positions[dependency.to_s]
|
|
95
|
+
next unless dependency_position
|
|
96
|
+
errors << error("PARALLEL_TRACK_ORDER_INVALID", "track dependency must precede dependent step", window: window_id, track: track, step: step_id, dependency: dependency) if dependency_position >= position
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
window["branches"].each do |track, branch_steps|
|
|
101
|
+
Array(branch_steps).each do |step_id|
|
|
102
|
+
Array(step_by_id.dig(step_id.to_s, "depends_on")).each do |dependency|
|
|
103
|
+
dependency_track = step_tracks[dependency.to_s]
|
|
104
|
+
next unless dependency_track && dependency_track != track.to_s
|
|
105
|
+
|
|
106
|
+
errors << error("PARALLEL_CROSS_TRACK_DEPENDENCY", "parallel branch depends on a step in another track", window: window_id, track: track, step: step_id, dependency: dependency, dependency_track: dependency_track)
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
counts = branch_ids.each_with_object(Hash.new(0)) { |step_id, result| result[step_id] += 1 }
|
|
111
|
+
duplicate_steps = counts.select { |_, count| count > 1 }.keys
|
|
112
|
+
duplicate_steps.each { |step_id| errors << error("PARALLEL_STEP_DUPLICATED", "step appears in multiple parallel branches", window: window_id, step: step_id) }
|
|
113
|
+
errors << error("PARALLEL_JOIN_IN_BRANCH", "join_step cannot also be a branch step", window: window_id, step: window["join_step"]) if branch_ids.include?(window["join_step"].to_s)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
(workflow["failure_branches"] || {}).each do |source_step, branch|
|
|
117
|
+
errors << error("FAILURE_SOURCE_STEP_NOT_FOUND", "failure branch source step is not defined", source_step: source_step) unless step_by_id.key?(source_step.to_s)
|
|
118
|
+
errors << error("FAILURE_BRANCH_SCHEMA_INVALID", "failure branch must be a mapping", source_step: source_step) unless branch.is_a?(Hash)
|
|
119
|
+
resume = branch.is_a?(Hash) && branch["resume_after_success"]
|
|
120
|
+
unless resume.is_a?(Hash) && %w[flow step status checkpoint].all? { |field| resume.key?(field) }
|
|
121
|
+
errors << error("FAILURE_RETURN_TO_INVALID", "failure branch must declare flow, step, status and checkpoint", source_step: source_step)
|
|
122
|
+
next
|
|
123
|
+
end
|
|
124
|
+
errors << error("FAILURE_RETURN_CHECKPOINT_INVALID", "failure branch return checkpoint is not defined", source_step: source_step, checkpoint: resume["checkpoint"]) unless checkpoints.key?(resume["checkpoint"])
|
|
125
|
+
end
|
|
126
|
+
errors
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def error(code, message, **extra)
|
|
130
|
+
{ "code" => code, "message" => message }.merge(extra)
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
if $PROGRAM_NAME == __FILE__
|
|
135
|
+
begin
|
|
136
|
+
options = {}
|
|
137
|
+
OptionParser.new do |opts|
|
|
138
|
+
opts.on("--workflow PATH") { |value| options[:workflow] = value }
|
|
139
|
+
opts.on("--json") { options[:json] = true }
|
|
140
|
+
end.parse!
|
|
141
|
+
raise ArgumentError, "--workflow is required" unless options[:workflow]
|
|
142
|
+
result = WorkflowGateContract.validate(YAML.safe_load(File.read(options[:workflow]), permitted_classes: [], aliases: false))
|
|
143
|
+
puts(options[:json] ? JSON.generate(result) : YAML.dump(result))
|
|
144
|
+
rescue StandardError => e
|
|
145
|
+
warn e.message
|
|
146
|
+
exit 1
|
|
147
|
+
end
|
|
148
|
+
end
|
package/plugins/devflow-core/skills/workflow-orchestrator/templates/feature-development.yaml
CHANGED
|
@@ -17,12 +17,15 @@ phase_scope:
|
|
|
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
|
+
gate_contract_version: 3
|
|
20
21
|
requirement_graph_gate: enforced
|
|
22
|
+
requirement_coverage_gate: enforced
|
|
21
23
|
enforced_checkpoints:
|
|
22
24
|
- CP-1
|
|
23
25
|
- CP-API
|
|
24
26
|
- CP-2
|
|
25
27
|
- CP-3
|
|
28
|
+
- CP-4
|
|
26
29
|
step_checkers:
|
|
27
30
|
requirement-baseline:
|
|
28
31
|
- requirement-graph-check
|
|
@@ -42,6 +45,7 @@ governance:
|
|
|
42
45
|
- slice-independence-check
|
|
43
46
|
- contract-coverage-check
|
|
44
47
|
- change-impact-check
|
|
48
|
+
- cross-track-consistency-check
|
|
45
49
|
acceptance-test-design:
|
|
46
50
|
- requirement-graph-check
|
|
47
51
|
- contract-coverage-check
|
|
@@ -120,6 +124,10 @@ parallel_windows:
|
|
|
120
124
|
checkpoint: CP-2
|
|
121
125
|
execution_policy:
|
|
122
126
|
mode: parallel_when_supported
|
|
127
|
+
scheduler:
|
|
128
|
+
one_agent_per_step: true
|
|
129
|
+
max_concurrency: 2
|
|
130
|
+
track_order: declared
|
|
123
131
|
serial_fallback_order:
|
|
124
132
|
- backend-tech-spec
|
|
125
133
|
- api-call-guide
|
|
@@ -311,6 +319,7 @@ checkpoints:
|
|
|
311
319
|
producing_step: run-acceptance-tests
|
|
312
320
|
required_outputs:
|
|
313
321
|
- ".planning/test-runs/{feature}/acceptance-results.json"
|
|
322
|
+
required_meta_output: ".planning/test-runs/{feature}/acceptance-results.meta.json"
|
|
314
323
|
required_meta_fields:
|
|
315
324
|
- acceptance_tc_passed
|
|
316
325
|
- acceptance_tc_failed
|
|
@@ -365,6 +374,7 @@ steps:
|
|
|
365
374
|
order: 6
|
|
366
375
|
label: Requirement wayfinder
|
|
367
376
|
skill: workflow-wayfinder
|
|
377
|
+
engine_evidence_gate: enforced
|
|
368
378
|
depends_on:
|
|
369
379
|
- requirement-triage
|
|
370
380
|
inputs:
|
|
@@ -392,6 +402,7 @@ steps:
|
|
|
392
402
|
order: 7
|
|
393
403
|
label: Domain modeling
|
|
394
404
|
skill: workflow-domain-modeling
|
|
405
|
+
engine_evidence_gate: enforced
|
|
395
406
|
depends_on:
|
|
396
407
|
- requirement-wayfinder
|
|
397
408
|
inputs:
|
|
@@ -417,6 +428,7 @@ steps:
|
|
|
417
428
|
order: 8
|
|
418
429
|
label: Requirement feasibility review
|
|
419
430
|
skill: requirement-feasibility-review
|
|
431
|
+
engine_evidence_gate: enforced
|
|
420
432
|
depends_on:
|
|
421
433
|
- domain-modeling
|
|
422
434
|
inputs:
|
|
@@ -443,6 +455,7 @@ steps:
|
|
|
443
455
|
order: 10
|
|
444
456
|
label: Requirement baseline
|
|
445
457
|
skill: workflow-requirement-baseline
|
|
458
|
+
engine_evidence_gate: enforced
|
|
446
459
|
depends_on:
|
|
447
460
|
- requirement-feasibility-review
|
|
448
461
|
inputs:
|
|
@@ -478,6 +491,7 @@ steps:
|
|
|
478
491
|
order: 15
|
|
479
492
|
label: API contract
|
|
480
493
|
skill: workflow-api-contract
|
|
494
|
+
engine_evidence_gate: enforced
|
|
481
495
|
depends_on:
|
|
482
496
|
- requirement-baseline
|
|
483
497
|
inputs:
|
|
@@ -504,6 +518,7 @@ steps:
|
|
|
504
518
|
order: 18
|
|
505
519
|
label: Architecture feasibility
|
|
506
520
|
skill: workflow-architecture-feasibility
|
|
521
|
+
engine_evidence_gate: enforced
|
|
507
522
|
depends_on:
|
|
508
523
|
- api-contract
|
|
509
524
|
inputs:
|
|
@@ -535,6 +550,7 @@ steps:
|
|
|
535
550
|
order: 20
|
|
536
551
|
label: UI spec
|
|
537
552
|
skill: workflow-ui-spec
|
|
553
|
+
engine_evidence_gate: enforced
|
|
538
554
|
depends_on:
|
|
539
555
|
- api-contract
|
|
540
556
|
- architecture-feasibility
|
|
@@ -551,6 +567,7 @@ steps:
|
|
|
551
567
|
order: 30
|
|
552
568
|
label: Feature breakdown
|
|
553
569
|
skill: workflow-feature-breakdown
|
|
570
|
+
engine_evidence_gate: enforced
|
|
554
571
|
depends_on:
|
|
555
572
|
- ui-spec
|
|
556
573
|
inputs:
|
|
@@ -565,6 +582,7 @@ steps:
|
|
|
565
582
|
order: 40
|
|
566
583
|
label: Frontend tech spec
|
|
567
584
|
skill: workflow-frontend-tech-spec
|
|
585
|
+
engine_evidence_gate: enforced
|
|
568
586
|
depends_on:
|
|
569
587
|
- feature-breakdown
|
|
570
588
|
- api-contract
|
|
@@ -598,6 +616,7 @@ steps:
|
|
|
598
616
|
order: 50
|
|
599
617
|
label: Backend tech spec
|
|
600
618
|
skill: workflow-backend-tech-spec
|
|
619
|
+
engine_evidence_gate: enforced
|
|
601
620
|
depends_on:
|
|
602
621
|
- api-contract
|
|
603
622
|
- architecture-feasibility
|
|
@@ -625,6 +644,7 @@ steps:
|
|
|
625
644
|
order: 55
|
|
626
645
|
label: API call guide
|
|
627
646
|
skill: workflow-api-call-guide
|
|
647
|
+
engine_evidence_gate: enforced
|
|
628
648
|
depends_on:
|
|
629
649
|
- api-contract
|
|
630
650
|
- backend-tech-spec
|
|
@@ -649,6 +669,7 @@ steps:
|
|
|
649
669
|
order: 56
|
|
650
670
|
label: API supplement
|
|
651
671
|
skill: workflow-api-supplement
|
|
672
|
+
engine_evidence_gate: enforced
|
|
652
673
|
depends_on:
|
|
653
674
|
- frontend-tech-spec
|
|
654
675
|
- api-contract
|
|
@@ -672,6 +693,7 @@ steps:
|
|
|
672
693
|
order: 58
|
|
673
694
|
label: Integration verify
|
|
674
695
|
skill: workflow-integration-verify
|
|
696
|
+
engine_evidence_gate: enforced
|
|
675
697
|
depends_on:
|
|
676
698
|
- api-call-guide
|
|
677
699
|
- frontend-tech-spec
|
|
@@ -702,6 +724,7 @@ steps:
|
|
|
702
724
|
order: 60
|
|
703
725
|
label: Change plan
|
|
704
726
|
skill: workflow-change-plan
|
|
727
|
+
engine_evidence_gate: enforced
|
|
705
728
|
depends_on:
|
|
706
729
|
- acceptance-test-design
|
|
707
730
|
inputs:
|
|
@@ -735,6 +758,7 @@ steps:
|
|
|
735
758
|
order: 59
|
|
736
759
|
label: Acceptance test design
|
|
737
760
|
skill: workflow-acceptance-test-design
|
|
761
|
+
engine_evidence_gate: enforced
|
|
738
762
|
depends_on:
|
|
739
763
|
- integration-verify
|
|
740
764
|
inputs:
|
|
@@ -774,6 +798,7 @@ steps:
|
|
|
774
798
|
order: 70
|
|
775
799
|
label: Phase structure
|
|
776
800
|
action: initialize-phase-structure
|
|
801
|
+
engine_evidence_gate: enforced
|
|
777
802
|
depends_on:
|
|
778
803
|
- change-plan
|
|
779
804
|
inputs:
|
|
@@ -791,6 +816,7 @@ steps:
|
|
|
791
816
|
order: 80
|
|
792
817
|
label: Execute
|
|
793
818
|
skill: workflow-execute-phase
|
|
819
|
+
engine_evidence_gate: enforced
|
|
794
820
|
depends_on:
|
|
795
821
|
- phase-structure
|
|
796
822
|
inputs:
|
|
@@ -835,6 +861,7 @@ steps:
|
|
|
835
861
|
order: 85
|
|
836
862
|
label: Code Review
|
|
837
863
|
skill: code-review
|
|
864
|
+
engine_evidence_gate: enforced
|
|
838
865
|
depends_on:
|
|
839
866
|
- code-index-refresh
|
|
840
867
|
inputs:
|
|
@@ -849,6 +876,7 @@ steps:
|
|
|
849
876
|
order: 86
|
|
850
877
|
label: Generate mainflow cases
|
|
851
878
|
skill: workflow-generate-mainflow-cases
|
|
879
|
+
engine_evidence_gate: enforced
|
|
852
880
|
depends_on:
|
|
853
881
|
- code-index-refresh
|
|
854
882
|
inputs:
|
|
@@ -887,6 +915,7 @@ steps:
|
|
|
887
915
|
order: 88
|
|
888
916
|
label: Run frozen acceptance tests
|
|
889
917
|
skill: workflow-run-acceptance-tests
|
|
918
|
+
engine_evidence_gate: enforced
|
|
890
919
|
depends_on:
|
|
891
920
|
- code-review
|
|
892
921
|
inputs:
|
package/src/constants.ts
CHANGED
package/src/runtime.ts
CHANGED
|
@@ -36,12 +36,18 @@ const MANAGED_SETTINGS: Record<string, unknown> = {
|
|
|
36
36
|
"skills.enableAgentsProject": false,
|
|
37
37
|
// The interactive session is the high-capability Planner. Low-cost agents
|
|
38
38
|
// are dispatched only through explicit Devflow steps, one at a time by
|
|
39
|
-
// default, so background work cannot silently widen a user's request.
|
|
39
|
+
// default, so background work cannot silently widen a user's request. The
|
|
40
|
+
// parallel workflow window is explicitly capped at two workers, matching
|
|
41
|
+
// its two declared tracks; serial workflows are unaffected.
|
|
40
42
|
// Keep ordinary interactive turns on the user's DEFAULT role. In particular,
|
|
41
43
|
// do not inherit SLOW just because a thinking model is configured.
|
|
42
44
|
"defaultThinkingLevel": "low",
|
|
45
|
+
// Parallel Devflow orchestration relies on OMP's AsyncJobManager and
|
|
46
|
+
// subagent lifecycle channel. Keep this explicit instead of inheriting the
|
|
47
|
+
// SDK default so a global OMP config cannot silently disable it.
|
|
48
|
+
"async.enabled": true,
|
|
43
49
|
"task.batch": false,
|
|
44
|
-
"task.maxConcurrency":
|
|
50
|
+
"task.maxConcurrency": 2,
|
|
45
51
|
"task.maxRecursionDepth": 1,
|
|
46
52
|
"task.enableLsp": true,
|
|
47
53
|
// Keep cheap workers bounded by role prompts. OMP's loop guards remain
|