aidp 0.44.0 → 0.46.0
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.
- checksums.yaml +4 -4
- data/lib/aidp/cli/devcontainer_commands.rb +10 -4
- data/lib/aidp/config.rb +13 -1
- data/lib/aidp/setup/devcontainer/jsonc_document.rb +539 -0
- data/lib/aidp/setup/devcontainer/parser.rb +6 -3
- data/lib/aidp/setup/wizard.rb +7 -1
- data/lib/aidp/version.rb +1 -1
- data/lib/aidp/watch/gantt_synchronizer.rb +273 -0
- data/lib/aidp/watch/plan_processor.rb +22 -0
- data/lib/aidp/watch/prd_parser.rb +395 -0
- data/lib/aidp/watch/projects_processor.rb +88 -11
- data/lib/aidp/watch/repository_client.rb +18 -1
- metadata +4 -1
|
@@ -15,7 +15,11 @@ module Aidp
|
|
|
15
15
|
priority: "Priority",
|
|
16
16
|
skills: "Skills",
|
|
17
17
|
personas: "Personas",
|
|
18
|
-
blocking: "Blocking"
|
|
18
|
+
blocking: "Blocking",
|
|
19
|
+
start_date: "Start Date",
|
|
20
|
+
target_date: "Target Date",
|
|
21
|
+
dependencies: "Dependencies",
|
|
22
|
+
critical_path: "Critical Path"
|
|
19
23
|
}.freeze
|
|
20
24
|
|
|
21
25
|
# Status values for different issue states
|
|
@@ -27,17 +31,25 @@ module Aidp
|
|
|
27
31
|
done: "Done",
|
|
28
32
|
blocked: "Blocked"
|
|
29
33
|
}.freeze
|
|
34
|
+
CRITICAL_PATH_VALUES = %w[Yes No].freeze
|
|
30
35
|
|
|
31
36
|
attr_reader :repository_client, :state_store, :project_id
|
|
32
37
|
|
|
33
|
-
def initialize(repository_client:, state_store:, project_id:, config: {})
|
|
38
|
+
def initialize(repository_client:, state_store:, project_id:, config: {}, gantt_synchronizer: nil)
|
|
34
39
|
@repository_client = repository_client
|
|
35
40
|
@state_store = state_store
|
|
36
41
|
@project_id = project_id
|
|
37
|
-
@config = config
|
|
38
|
-
@field_mappings = config[:field_mappings] ||
|
|
39
|
-
@auto_create_fields = config[:auto_create_fields] != false
|
|
42
|
+
@config = normalize_config(config)
|
|
43
|
+
@field_mappings = DEFAULT_FIELD_MAPPINGS.merge(@config[:field_mappings] || {})
|
|
44
|
+
@auto_create_fields = @config[:auto_create_fields] != false
|
|
40
45
|
@project_fields_cache = nil
|
|
46
|
+
@gantt_synchronizer = gantt_synchronizer || GanttSynchronizer.new(
|
|
47
|
+
repository_client: repository_client,
|
|
48
|
+
state_store: state_store,
|
|
49
|
+
project_id: project_id,
|
|
50
|
+
field_mappings: @field_mappings,
|
|
51
|
+
auto_create_fields: @auto_create_fields
|
|
52
|
+
)
|
|
41
53
|
end
|
|
42
54
|
|
|
43
55
|
# Sync a single issue to the project
|
|
@@ -66,7 +78,7 @@ module Aidp
|
|
|
66
78
|
|
|
67
79
|
# Update status if provided
|
|
68
80
|
if status
|
|
69
|
-
update_issue_status(issue_number, status)
|
|
81
|
+
return false unless update_issue_status(issue_number, status)
|
|
70
82
|
end
|
|
71
83
|
|
|
72
84
|
# Check and update blocking status
|
|
@@ -76,6 +88,7 @@ module Aidp
|
|
|
76
88
|
last_sync: Time.now.utc.iso8601,
|
|
77
89
|
status: status
|
|
78
90
|
})
|
|
91
|
+
sync_issue_status_to_gantt(issue_number, status) if status && gantt_sync_enabled?
|
|
79
92
|
|
|
80
93
|
true
|
|
81
94
|
rescue => e
|
|
@@ -178,6 +191,16 @@ module Aidp
|
|
|
178
191
|
{synced: synced, failed: failed}
|
|
179
192
|
end
|
|
180
193
|
|
|
194
|
+
def sync_from_gantt(prd_path = configured_prd_path, issue_numbers_by_title: {})
|
|
195
|
+
return {synced: 0, skipped: 0, critical_path: []} unless prd_path
|
|
196
|
+
|
|
197
|
+
@gantt_synchronizer.sync_from_prd(
|
|
198
|
+
prd_path: prd_path,
|
|
199
|
+
format: configured_gantt_format,
|
|
200
|
+
issue_numbers_by_title: issue_numbers_by_title
|
|
201
|
+
)
|
|
202
|
+
end
|
|
203
|
+
|
|
181
204
|
# Initialize required project fields if they don't exist
|
|
182
205
|
# @return [Boolean] True if all fields are ready
|
|
183
206
|
def ensure_project_fields
|
|
@@ -185,11 +208,6 @@ module Aidp
|
|
|
185
208
|
|
|
186
209
|
Aidp.log_debug("projects_processor", "ensure_project_fields", project_id: @project_id)
|
|
187
210
|
|
|
188
|
-
required_fields = [
|
|
189
|
-
{name: @field_mappings[:status], type: "SINGLE_SELECT", options: STATUS_VALUES.values},
|
|
190
|
-
{name: @field_mappings[:blocking], type: "TEXT"}
|
|
191
|
-
]
|
|
192
|
-
|
|
193
211
|
all_ready = true
|
|
194
212
|
required_fields.each do |field_spec|
|
|
195
213
|
field = find_or_create_field(field_spec[:name], field_spec[:type], field_spec[:options])
|
|
@@ -210,6 +228,19 @@ module Aidp
|
|
|
210
228
|
end
|
|
211
229
|
end
|
|
212
230
|
|
|
231
|
+
def normalize_config(value)
|
|
232
|
+
case value
|
|
233
|
+
when Hash
|
|
234
|
+
value.each_with_object({}) do |(key, nested_value), normalized|
|
|
235
|
+
normalized[key.to_sym] = normalize_config(nested_value)
|
|
236
|
+
end
|
|
237
|
+
when Array
|
|
238
|
+
value.map { |item| normalize_config(item) }
|
|
239
|
+
else
|
|
240
|
+
value
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
|
|
213
244
|
def invalidate_fields_cache
|
|
214
245
|
@project_fields_cache = nil
|
|
215
246
|
end
|
|
@@ -281,6 +312,52 @@ module Aidp
|
|
|
281
312
|
def clear_blocking_field(issue_number)
|
|
282
313
|
update_blocking_field(issue_number, [])
|
|
283
314
|
end
|
|
315
|
+
|
|
316
|
+
def gantt_sync_enabled?
|
|
317
|
+
@config[:auto_sync_gantt] == true && !configured_prd_path.to_s.empty?
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
def required_fields
|
|
321
|
+
[
|
|
322
|
+
{name: @field_mappings[:status], type: "SINGLE_SELECT", options: STATUS_VALUES.values},
|
|
323
|
+
{name: @field_mappings[:blocking], type: "TEXT"}
|
|
324
|
+
] + gantt_required_fields
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
def gantt_required_fields
|
|
328
|
+
return [] unless gantt_sync_enabled?
|
|
329
|
+
|
|
330
|
+
[
|
|
331
|
+
{name: @field_mappings[:start_date], type: "DATE"},
|
|
332
|
+
{name: @field_mappings[:target_date], type: "DATE"},
|
|
333
|
+
{name: @field_mappings[:dependencies], type: "TEXT"},
|
|
334
|
+
{name: @field_mappings[:critical_path], type: "SINGLE_SELECT", options: CRITICAL_PATH_VALUES}
|
|
335
|
+
]
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
def configured_prd_path
|
|
339
|
+
@config[:prd_path]
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
def configured_gantt_format
|
|
343
|
+
format = @config[:gantt_format]
|
|
344
|
+
return nil if format.nil? || format.to_s == "auto"
|
|
345
|
+
|
|
346
|
+
format
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
def sync_issue_status_to_gantt(issue_number, status)
|
|
350
|
+
@gantt_synchronizer.sync_issue_status_to_gantt(
|
|
351
|
+
prd_path: configured_prd_path,
|
|
352
|
+
issue_number: issue_number,
|
|
353
|
+
status: status,
|
|
354
|
+
format: configured_gantt_format
|
|
355
|
+
)
|
|
356
|
+
rescue => e
|
|
357
|
+
Aidp.log_warn("projects_processor", "gantt_status_sync_failed",
|
|
358
|
+
issue_number: issue_number, error: e.message)
|
|
359
|
+
false
|
|
360
|
+
end
|
|
284
361
|
end
|
|
285
362
|
end
|
|
286
363
|
end
|
|
@@ -1644,6 +1644,21 @@ module Aidp
|
|
|
1644
1644
|
}
|
|
1645
1645
|
}
|
|
1646
1646
|
GRAPHQL
|
|
1647
|
+
elsif value.is_a?(Hash) && value[:date]
|
|
1648
|
+
<<~GRAPHQL
|
|
1649
|
+
mutation($projectId: ID!, $itemId: ID!, $fieldId: ID!, $date: Date!) {
|
|
1650
|
+
updateProjectV2ItemFieldValue(input: {
|
|
1651
|
+
projectId: $projectId
|
|
1652
|
+
itemId: $itemId
|
|
1653
|
+
fieldId: $fieldId
|
|
1654
|
+
value: {date: $date}
|
|
1655
|
+
}) {
|
|
1656
|
+
projectV2Item {
|
|
1657
|
+
id
|
|
1658
|
+
}
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1661
|
+
GRAPHQL
|
|
1647
1662
|
else
|
|
1648
1663
|
# Text field
|
|
1649
1664
|
<<~GRAPHQL
|
|
@@ -1675,8 +1690,10 @@ module Aidp
|
|
|
1675
1690
|
|
|
1676
1691
|
if value.is_a?(Hash) && value[:option_id]
|
|
1677
1692
|
variables[:optionId] = value[:option_id]
|
|
1693
|
+
elsif value.is_a?(Hash) && value[:date]
|
|
1694
|
+
variables[:date] = value[:date]
|
|
1678
1695
|
else
|
|
1679
|
-
variables[:text] = value.to_s
|
|
1696
|
+
variables[:text] = value.is_a?(Hash) ? value[:text].to_s : value.to_s
|
|
1680
1697
|
end
|
|
1681
1698
|
|
|
1682
1699
|
result = execute_graphql_query(mutation, **variables)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: aidp
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.46.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Bart Agapinan
|
|
@@ -551,6 +551,7 @@ files:
|
|
|
551
551
|
- lib/aidp/security/work_loop_adapter.rb
|
|
552
552
|
- lib/aidp/setup/devcontainer/backup_manager.rb
|
|
553
553
|
- lib/aidp/setup/devcontainer/generator.rb
|
|
554
|
+
- lib/aidp/setup/devcontainer/jsonc_document.rb
|
|
554
555
|
- lib/aidp/setup/devcontainer/parser.rb
|
|
555
556
|
- lib/aidp/setup/devcontainer/port_manager.rb
|
|
556
557
|
- lib/aidp/setup/in_memory_config_adapter.rb
|
|
@@ -609,11 +610,13 @@ files:
|
|
|
609
610
|
- lib/aidp/watch/ci_fix_processor.rb
|
|
610
611
|
- lib/aidp/watch/ci_log_extractor.rb
|
|
611
612
|
- lib/aidp/watch/feedback_collector.rb
|
|
613
|
+
- lib/aidp/watch/gantt_synchronizer.rb
|
|
612
614
|
- lib/aidp/watch/github_state_extractor.rb
|
|
613
615
|
- lib/aidp/watch/hierarchical_pr_strategy.rb
|
|
614
616
|
- lib/aidp/watch/implementation_verifier.rb
|
|
615
617
|
- lib/aidp/watch/plan_generator.rb
|
|
616
618
|
- lib/aidp/watch/plan_processor.rb
|
|
619
|
+
- lib/aidp/watch/prd_parser.rb
|
|
617
620
|
- lib/aidp/watch/projects_processor.rb
|
|
618
621
|
- lib/aidp/watch/rebase_processor.rb
|
|
619
622
|
- lib/aidp/watch/repository_client.rb
|