brainiac-fizzy 0.0.7 → 0.0.9
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/brainiac/plugins/fizzy/delegators.rb +16 -0
- data/lib/brainiac/plugins/fizzy/handlers/assignment.rb +4 -6
- data/lib/brainiac/plugins/fizzy/handlers/comments.rb +34 -40
- data/lib/brainiac/plugins/fizzy/handlers/deploy.rb +4 -5
- data/lib/brainiac/plugins/fizzy/helpers.rb +109 -2
- data/lib/brainiac/plugins/fizzy/hooks.rb +6 -3
- data/lib/brainiac/plugins/fizzy/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d3d24ce3986d1b5353dca763a8ba29060ecd2dce47065cc2ffdd201d4075ca66
|
|
4
|
+
data.tar.gz: 6f39b2c02369556d1b7914c7a37eebcb98eccf016944ed2ea34bba6dac94ebc4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b417b22c6c7150d3cf823225141d00ae41d94d3f2a6e6c3eb736f4db2ea122ce33b46a0c5d237e4315cf29f415b82b31fa58085a1a48e83177288314bdc8df11
|
|
7
|
+
data.tar.gz: 61d02c8a206ecd4c0e3c9680b3f8856914c30b45a16d9a7507b6118c980c0765fa24e96e4018bbb3793dd357e84de99ee39551b3724c7dba421927b8b679b89e
|
|
@@ -25,6 +25,10 @@ def prefetch_card_context(card_number, repo_path:, agent_name: nil)
|
|
|
25
25
|
Brainiac::Plugins::Fizzy::Helpers.prefetch_card_context(card_number, repo_path: repo_path, agent_name: agent_name)
|
|
26
26
|
end
|
|
27
27
|
|
|
28
|
+
def fetch_intent_context(card_number, repo_path:, agent_name: nil)
|
|
29
|
+
Brainiac::Plugins::Fizzy::Helpers.fetch_intent_context(card_number, repo_path: repo_path, agent_name: agent_name)
|
|
30
|
+
end
|
|
31
|
+
|
|
28
32
|
def move_card_to_column(card_number, column_name, project_config:, agent_name: nil)
|
|
29
33
|
Brainiac::Plugins::Fizzy::Helpers.move_card_to_column(card_number, column_name, project_config: project_config, agent_name: agent_name)
|
|
30
34
|
end
|
|
@@ -46,6 +50,18 @@ def detect_planning_mode(text:, tags:, card_internal_id:, card_number:)
|
|
|
46
50
|
card_internal_id: card_internal_id, card_number: card_number)
|
|
47
51
|
end
|
|
48
52
|
|
|
53
|
+
def lookup_fizzy_card_info(card_internal_id)
|
|
54
|
+
Brainiac::Plugins::Fizzy::Helpers.lookup_fizzy_card_info(card_internal_id)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def update_fizzy_work_item(card_internal_id, updates)
|
|
58
|
+
Brainiac::Plugins::Fizzy::Helpers.update_fizzy_work_item(card_internal_id, updates)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def resolve_card_number(internal_id, repo_path:)
|
|
62
|
+
Brainiac::Plugins::Fizzy::Helpers.resolve_card_number(internal_id, repo_path: repo_path)
|
|
63
|
+
end
|
|
64
|
+
|
|
49
65
|
def verify_fizzy_signature!(request, payload_body, board_key: nil)
|
|
50
66
|
Brainiac::Plugins::Fizzy::Helpers.verify_signature!(request, payload_body, board_key: board_key)
|
|
51
67
|
end
|
|
@@ -103,12 +103,10 @@ def setup_assigned_worktree(repo_path, branch, card_internal_id, card_number, pr
|
|
|
103
103
|
worktree_path = File.join(File.dirname(repo_path), "#{File.basename(repo_path)}--#{branch}")
|
|
104
104
|
worktree_path = create_or_reuse_worktree(repo_path: repo_path, branch: branch, worktree_path: worktree_path)
|
|
105
105
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
save_work_item_map(map)
|
|
106
|
+
register_work_item(
|
|
107
|
+
branch: branch, worktree: worktree_path, project: project_key, agent: agent_name,
|
|
108
|
+
source: :fizzy, source_data: { "card_internal_id" => card_internal_id, "card_number" => card_number }
|
|
109
|
+
)
|
|
112
110
|
worktree_path
|
|
113
111
|
end
|
|
114
112
|
|
|
@@ -41,11 +41,9 @@ def handle_comment(payload)
|
|
|
41
41
|
agent_result = validate_agent_comment(creator_is_agent, is_api_sourced, creator_name, mentioned_agent, card_internal_id)
|
|
42
42
|
return agent_result if agent_result
|
|
43
43
|
|
|
44
|
-
card_info =
|
|
44
|
+
card_info = lookup_fizzy_card_info(card_internal_id)
|
|
45
45
|
comment_id = eventable["id"]
|
|
46
46
|
|
|
47
|
-
return [200, { status: "ignored", reason: "not relevant" }.to_json] unless mentioned_agent || card_info
|
|
48
|
-
|
|
49
47
|
project_config, project_key = resolve_fizzy_project(card_info, card_internal_id, eventable)
|
|
50
48
|
return [200, { status: "ignored", reason: "no matching project" }.to_json] unless project_config
|
|
51
49
|
|
|
@@ -158,7 +156,7 @@ end
|
|
|
158
156
|
def validate_agent_comment(creator_is_agent, is_api_sourced, creator_name, mentioned_agent, card_internal_id)
|
|
159
157
|
return nil unless creator_is_agent || is_api_sourced
|
|
160
158
|
|
|
161
|
-
card_info =
|
|
159
|
+
card_info = lookup_fizzy_card_info(card_internal_id)
|
|
162
160
|
card_assigned_agent = card_info&.dig("agent")
|
|
163
161
|
|
|
164
162
|
agent_is_assigned = card_assigned_agent && card_assigned_agent.downcase == (creator_name || "").downcase
|
|
@@ -207,7 +205,8 @@ end
|
|
|
207
205
|
|
|
208
206
|
def handle_cancel_command(eventable, card_internal_id)
|
|
209
207
|
killed = 0
|
|
210
|
-
|
|
208
|
+
cancel_card_info = lookup_fizzy_card_info(card_internal_id)
|
|
209
|
+
card_number_for_cancel = cancel_card_info&.dig("number")
|
|
211
210
|
prefixes = ["card-#{card_internal_id}"]
|
|
212
211
|
prefixes << "card-#{card_number_for_cancel}" if card_number_for_cancel
|
|
213
212
|
|
|
@@ -229,9 +228,8 @@ def handle_cancel_command(eventable, card_internal_id)
|
|
|
229
228
|
end
|
|
230
229
|
|
|
231
230
|
comment_id_for_cancel = eventable["id"]
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
repo = (card_info_for_cancel["project"] && PROJECTS.dig(card_info_for_cancel["project"], "repo_path")) ||
|
|
231
|
+
if cancel_card_info && card_number_for_cancel && comment_id_for_cancel
|
|
232
|
+
repo = (cancel_card_info["project"] && PROJECTS.dig(cancel_card_info["project"], "repo_path")) ||
|
|
235
233
|
DEFAULT_PROJECT["repo_path"]
|
|
236
234
|
Thread.new do
|
|
237
235
|
run_cmd("fizzy", "reaction", "create", "--card", card_number_for_cancel.to_s,
|
|
@@ -257,9 +255,7 @@ def resolve_fizzy_project(card_info, card_internal_id, eventable)
|
|
|
257
255
|
if project_result
|
|
258
256
|
project_key, project_config = project_result
|
|
259
257
|
card_info["project"] = project_key
|
|
260
|
-
|
|
261
|
-
map[card_internal_id] = card_info
|
|
262
|
-
save_work_item_map(map)
|
|
258
|
+
update_fizzy_work_item(card_internal_id, "project" => project_key)
|
|
263
259
|
LOG.info "Backfilled project '#{project_key}' for card #{card_internal_id} in card map"
|
|
264
260
|
else
|
|
265
261
|
LOG.warn "No project found for card #{card_internal_id}"
|
|
@@ -305,21 +301,23 @@ def resolve_assigned_agent(card_info, card_internal_id, eventable, project_confi
|
|
|
305
301
|
card_assignees = eventable.dig("card", "assignees") || []
|
|
306
302
|
webhook_agent = card_assignees.map { |a| a["name"] }.find { |name| local_agent_names.include?(name) }
|
|
307
303
|
|
|
308
|
-
webhook_agent = resolve_agent_via_api(card_info, card_internal_id, project_config) if webhook_agent.nil? && project_config
|
|
304
|
+
webhook_agent = resolve_agent_via_api(card_info, card_internal_id, eventable, project_config) if webhook_agent.nil? && project_config
|
|
309
305
|
|
|
310
306
|
return nil unless webhook_agent
|
|
311
307
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
map[card_internal_id]["agent"] = webhook_agent
|
|
315
|
-
save_work_item_map(map)
|
|
308
|
+
card_number = eventable.dig("card", "number")
|
|
309
|
+
update_fizzy_work_item(card_internal_id, { "agent" => webhook_agent }.tap { |h| h["number"] = card_number if card_number })
|
|
316
310
|
LOG.info "Backfilled agent '#{webhook_agent}' into card map for #{card_internal_id}"
|
|
317
311
|
webhook_agent
|
|
318
312
|
end
|
|
319
313
|
|
|
320
|
-
def resolve_agent_via_api(card_info, card_internal_id, project_config)
|
|
321
|
-
api_card_number = card_info&.dig("number") ||
|
|
322
|
-
|
|
314
|
+
def resolve_agent_via_api(card_info, card_internal_id, eventable, project_config)
|
|
315
|
+
api_card_number = card_info&.dig("number") || eventable.dig("card", "number")
|
|
316
|
+
api_card_number ||= resolve_card_number(card_internal_id, repo_path: project_config["repo_path"])
|
|
317
|
+
unless api_card_number
|
|
318
|
+
LOG.warn "Cannot resolve agent via API — no card number available (internal_id: #{card_internal_id})"
|
|
319
|
+
return nil
|
|
320
|
+
end
|
|
323
321
|
|
|
324
322
|
output = run_cmd("fizzy", "card", "show", api_card_number.to_s,
|
|
325
323
|
chdir: project_config["repo_path"], env: default_fizzy_env)
|
|
@@ -364,6 +362,7 @@ def dispatch_cross_agent_review(ctx, card_key:, card_number:, card_assigned_agen
|
|
|
364
362
|
review_worktree_path, review_branch = setup_cross_agent_worktree(ctx, card_number)
|
|
365
363
|
prompt = build_cross_agent_prompt(ctx, card_number, card_assigned_agent, review_worktree_path, review_branch)
|
|
366
364
|
|
|
365
|
+
intent_ctx = fetch_intent_context(card_number, repo_path: ctx.project_config["repo_path"], agent_name: ctx.agent_name)
|
|
367
366
|
pid, log_file = run_agent(prompt,
|
|
368
367
|
project_config: ctx.project_config, chdir: review_worktree_path,
|
|
369
368
|
log_name: "review-#{ctx.agent_name.downcase}-#{card_number || ctx.card_internal_id}",
|
|
@@ -371,7 +370,8 @@ def dispatch_cross_agent_review(ctx, card_key:, card_number:, card_assigned_agen
|
|
|
371
370
|
card_number: card_number, comment_id: ctx.comment_id,
|
|
372
371
|
source: :fizzy, source_context: { card_number: card_number },
|
|
373
372
|
cli_provider: ctx.cli_provider_override,
|
|
374
|
-
message: ctx.plain_text, channel: "Fizzy comment"
|
|
373
|
+
message: ctx.plain_text, channel: "Fizzy comment",
|
|
374
|
+
context: intent_ctx)
|
|
375
375
|
return [200, { status: "intent_skip", agent: ctx.agent_name, card: card_number }.to_json] unless pid
|
|
376
376
|
|
|
377
377
|
register_session(card_key, pid, log_file: log_file, supersede_key: card_key, agent_name: ctx.agent_name)
|
|
@@ -433,7 +433,7 @@ def handle_new_mention(ctx)
|
|
|
433
433
|
card_title = card_data["title"] || "exploration"
|
|
434
434
|
|
|
435
435
|
if card_number.nil?
|
|
436
|
-
map_entry =
|
|
436
|
+
map_entry = lookup_fizzy_card_info(ctx.card_internal_id)
|
|
437
437
|
card_number = if map_entry && map_entry["number"]
|
|
438
438
|
map_entry["number"]
|
|
439
439
|
else
|
|
@@ -459,12 +459,10 @@ def setup_new_mention_worktree(ctx, card_number, card_title)
|
|
|
459
459
|
repo_path = ctx.project_config["repo_path"]
|
|
460
460
|
worktree_path, branch = resolve_or_create_worktree(ctx, card_number, card_title, repo_path)
|
|
461
461
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
}
|
|
467
|
-
save_work_item_map(map)
|
|
462
|
+
register_work_item(
|
|
463
|
+
branch: branch, worktree: worktree_path, project: ctx.project_key, agent: ctx.agent_name,
|
|
464
|
+
source: :fizzy, source_data: { "card_internal_id" => ctx.card_internal_id, "card_number" => card_number }
|
|
465
|
+
)
|
|
468
466
|
|
|
469
467
|
[worktree_path, branch]
|
|
470
468
|
end
|
|
@@ -472,6 +470,7 @@ end
|
|
|
472
470
|
def dispatch_new_mention(ctx, card_key:, card_number:, card_title:, branch:, worktree_path:)
|
|
473
471
|
prompt = build_mention_prompt(ctx, card_number, card_title, branch, worktree_path)
|
|
474
472
|
|
|
473
|
+
intent_ctx = fetch_intent_context(card_number, repo_path: ctx.project_config["repo_path"], agent_name: ctx.agent_name)
|
|
475
474
|
pid, log_file = run_agent(prompt,
|
|
476
475
|
project_config: ctx.project_config, chdir: worktree_path,
|
|
477
476
|
log_name: "mention-#{card_number || ctx.card_internal_id}",
|
|
@@ -479,7 +478,8 @@ def dispatch_new_mention(ctx, card_key:, card_number:, card_title:, branch:, wor
|
|
|
479
478
|
card_number: card_number, comment_id: ctx.comment_id,
|
|
480
479
|
source: :fizzy, cli_provider: ctx.cli_provider_override,
|
|
481
480
|
source_context: { card_number: card_number },
|
|
482
|
-
message: ctx.plain_text, channel: "Fizzy comment"
|
|
481
|
+
message: ctx.plain_text, channel: "Fizzy comment",
|
|
482
|
+
context: intent_ctx)
|
|
483
483
|
return [200, { status: "intent_skip", agent: ctx.agent_name, card: card_number }.to_json] unless pid
|
|
484
484
|
|
|
485
485
|
register_session(card_key, pid, log_file: log_file, supersede_key: card_key, agent_name: ctx.agent_name)
|
|
@@ -509,6 +509,7 @@ def dispatch_followup_comment(ctx, card_key:, card_number:, work_dir:)
|
|
|
509
509
|
build_followup_prompt(ctx, card_number, card_tags, work_dir)
|
|
510
510
|
end
|
|
511
511
|
|
|
512
|
+
intent_ctx = fetch_intent_context(card_number, repo_path: ctx.project_config["repo_path"], agent_name: ctx.agent_name)
|
|
512
513
|
pid, log_file = run_agent(prompt,
|
|
513
514
|
project_config: ctx.project_config, chdir: work_dir,
|
|
514
515
|
log_name: "followup-#{card_number || ctx.card_internal_id}",
|
|
@@ -519,7 +520,8 @@ def dispatch_followup_comment(ctx, card_key:, card_number:, work_dir:)
|
|
|
519
520
|
card_number: card_number, card_internal_id: ctx.card_internal_id,
|
|
520
521
|
deploy_intent: ctx.deploy_intent
|
|
521
522
|
},
|
|
522
|
-
message: ctx.plain_text, channel: "Fizzy comment"
|
|
523
|
+
message: ctx.plain_text, channel: "Fizzy comment",
|
|
524
|
+
context: intent_ctx)
|
|
523
525
|
return [200, { status: "intent_skip", agent: ctx.agent_name, card: card_number }.to_json] unless pid
|
|
524
526
|
|
|
525
527
|
register_session(card_key, pid, log_file: log_file, supersede_key: card_key, agent_name: ctx.agent_name)
|
|
@@ -561,12 +563,7 @@ end
|
|
|
561
563
|
|
|
562
564
|
def resolve_and_save_card_number(card_internal_id, project_config)
|
|
563
565
|
card_number = resolve_card_number(card_internal_id, repo_path: project_config["repo_path"])
|
|
564
|
-
if card_number
|
|
565
|
-
map = load_work_item_map
|
|
566
|
-
map[card_internal_id] ||= {}
|
|
567
|
-
map[card_internal_id]["number"] = card_number
|
|
568
|
-
save_work_item_map(map)
|
|
569
|
-
end
|
|
566
|
+
update_fizzy_work_item(card_internal_id, "number" => card_number) if card_number
|
|
570
567
|
card_number
|
|
571
568
|
end
|
|
572
569
|
|
|
@@ -574,10 +571,7 @@ def find_and_save_worktree(card_internal_id, card_number, project_config)
|
|
|
574
571
|
found = find_worktree_for_card(card_number, repo_path: project_config["repo_path"])
|
|
575
572
|
return nil unless found
|
|
576
573
|
|
|
577
|
-
|
|
578
|
-
map[card_internal_id] ||= {}
|
|
579
|
-
map[card_internal_id].merge!("worktree" => found[:worktree], "branch" => found[:branch])
|
|
580
|
-
save_work_item_map(map)
|
|
574
|
+
update_fizzy_work_item(card_internal_id, "worktree" => found[:worktree], "branch" => found[:branch])
|
|
581
575
|
LOG.info "Found worktree by card number scan: #{found[:worktree]}"
|
|
582
576
|
found[:worktree]
|
|
583
577
|
end
|
|
@@ -649,7 +643,7 @@ end
|
|
|
649
643
|
|
|
650
644
|
def resolve_or_create_worktree(ctx, card_number, card_title, repo_path)
|
|
651
645
|
# Check for existing worktree in card map or on disk
|
|
652
|
-
existing_map_entry =
|
|
646
|
+
existing_map_entry = lookup_fizzy_card_info(ctx.card_internal_id)
|
|
653
647
|
if existing_map_entry && existing_map_entry["branch"] && existing_map_entry["worktree"] &&
|
|
654
648
|
File.directory?(existing_map_entry["worktree"])
|
|
655
649
|
LOG.info "Reusing existing worktree from card map: #{existing_map_entry["worktree"]}"
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
def handle_deploy_comment(eventable, env_key, card_internal_id)
|
|
9
9
|
comment_id = eventable["id"]
|
|
10
|
-
card_info =
|
|
10
|
+
card_info = lookup_fizzy_card_info(card_internal_id)
|
|
11
11
|
|
|
12
12
|
# Validate environment exists
|
|
13
13
|
deploy_config = DEPLOYMENTS_CONFIG["environments"] || {}
|
|
@@ -139,10 +139,9 @@ def clone_branch_for_deploy(eventable, card_internal_id, card_info)
|
|
|
139
139
|
end
|
|
140
140
|
|
|
141
141
|
# Update card map
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
save_card_map(map)
|
|
142
|
+
update_fizzy_work_item(card_internal_id,
|
|
143
|
+
"number" => card_number, "branch" => branch,
|
|
144
|
+
"worktree" => worktree_path, "project" => project_key)
|
|
146
145
|
|
|
147
146
|
LOG.info "[Deploy] Cloned branch #{branch} into worktree #{worktree_path} for card ##{card_number}"
|
|
148
147
|
{ worktree: worktree_path, card_number: card_number }
|
|
@@ -73,6 +73,25 @@ module Brainiac
|
|
|
73
73
|
""
|
|
74
74
|
end
|
|
75
75
|
|
|
76
|
+
# Lightweight recent comment context for intent classification.
|
|
77
|
+
# Returns a simple "author: message" format (last 5 comments).
|
|
78
|
+
def fetch_intent_context(card_number, repo_path:, agent_name: nil)
|
|
79
|
+
env = fizzy_env_for(agent_name || AI_AGENT_NAME)
|
|
80
|
+
output = run_cmd("fizzy", "comment", "list", "--card", card_number.to_s, chdir: repo_path, env: env)
|
|
81
|
+
comments = JSON.parse(output)["data"] || []
|
|
82
|
+
return nil if comments.empty?
|
|
83
|
+
|
|
84
|
+
comments.last(5).map do |c|
|
|
85
|
+
creator = c["creator_name"] || "unknown"
|
|
86
|
+
body = (c.dig("body", "plain_text") || "").lines.first(3).join.strip
|
|
87
|
+
body = "#{body[0..200]}..." if body.length > 200
|
|
88
|
+
"#{creator}: #{body}"
|
|
89
|
+
end.join("\n")
|
|
90
|
+
rescue StandardError => e
|
|
91
|
+
LOG.warn "[Fizzy] Could not fetch intent context for card ##{card_number}: #{e.message}" if defined?(LOG)
|
|
92
|
+
nil
|
|
93
|
+
end
|
|
94
|
+
|
|
76
95
|
def move_card_to_column(card_number, column_name, project_config:, agent_name: nil)
|
|
77
96
|
board_key = Config.board_key_for_project(project_config)
|
|
78
97
|
column_id = Config.board_column_id(board_key, column_name) if board_key
|
|
@@ -149,6 +168,91 @@ module Brainiac
|
|
|
149
168
|
{ card_id: card_number || card_internal_id }
|
|
150
169
|
end
|
|
151
170
|
|
|
171
|
+
# Look up a Fizzy card's work item info by its internal ID.
|
|
172
|
+
# Returns a hash with top-level "number", "agent", "branch", "worktree", "project"
|
|
173
|
+
# keys for backward compatibility with handler code, or nil if not found.
|
|
174
|
+
def lookup_fizzy_card_info(card_internal_id)
|
|
175
|
+
return nil unless card_internal_id
|
|
176
|
+
|
|
177
|
+
result = find_work_item_by_card(card_internal_id)
|
|
178
|
+
return nil unless result
|
|
179
|
+
|
|
180
|
+
_work_item_id, info = result
|
|
181
|
+
# Ensure "number" is at top level for fizzy handler compat
|
|
182
|
+
info["number"] ||= info.dig("sources", "fizzy", "card_number")
|
|
183
|
+
info
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# Update or create a work item entry for a Fizzy card.
|
|
187
|
+
# Accepts a hash of fields to merge into the existing entry.
|
|
188
|
+
# Handles both new-format (wi-xxx keyed) and creates new entries properly.
|
|
189
|
+
def update_fizzy_work_item(card_internal_id, updates)
|
|
190
|
+
return unless card_internal_id
|
|
191
|
+
|
|
192
|
+
map = load_work_item_map
|
|
193
|
+
result = nil
|
|
194
|
+
work_item_id = nil
|
|
195
|
+
|
|
196
|
+
# Find existing entry by card internal ID
|
|
197
|
+
map.each do |wid, info|
|
|
198
|
+
next unless info.is_a?(Hash)
|
|
199
|
+
|
|
200
|
+
fizzy_source = info.dig("sources", "fizzy")
|
|
201
|
+
next unless fizzy_source && fizzy_source["card_internal_id"] == card_internal_id
|
|
202
|
+
|
|
203
|
+
work_item_id = wid
|
|
204
|
+
result = info
|
|
205
|
+
break
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
card_number = updates.delete("number")
|
|
209
|
+
|
|
210
|
+
if result
|
|
211
|
+
result["sources"]["fizzy"]["card_number"] = card_number if card_number
|
|
212
|
+
result.merge!(updates)
|
|
213
|
+
map[work_item_id] = result
|
|
214
|
+
else
|
|
215
|
+
new_id = generate_work_item_id(branch: updates["branch"], card_number: card_number)
|
|
216
|
+
map[new_id] = {
|
|
217
|
+
"id" => new_id,
|
|
218
|
+
"branch" => updates["branch"],
|
|
219
|
+
"worktree" => updates["worktree"],
|
|
220
|
+
"project" => updates["project"],
|
|
221
|
+
"agent" => updates["agent"],
|
|
222
|
+
"sources" => {
|
|
223
|
+
"fizzy" => {
|
|
224
|
+
"card_internal_id" => card_internal_id,
|
|
225
|
+
"card_number" => card_number
|
|
226
|
+
}.compact
|
|
227
|
+
}
|
|
228
|
+
}.compact.merge(updates.except("branch", "worktree", "project", "agent"))
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
save_work_item_map(map)
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
# Resolve a card number from an internal ID by querying the Fizzy API.
|
|
235
|
+
# Searches card lists to find the matching card.
|
|
236
|
+
def resolve_card_number(internal_id, repo_path:)
|
|
237
|
+
env = default_fizzy_env
|
|
238
|
+
base_cmd = %w[fizzy card list]
|
|
239
|
+
["--all", "--all --indexed-by closed"].each do |flags|
|
|
240
|
+
cmd = base_cmd + flags.split
|
|
241
|
+
output = run_cmd(*cmd, chdir: repo_path, env: env)
|
|
242
|
+
data = JSON.parse(output)["data"] || []
|
|
243
|
+
match = data.find { |c| c["id"] == internal_id }
|
|
244
|
+
if match
|
|
245
|
+
LOG.info "Resolved card number #{match["number"]} for internal_id #{internal_id}" if defined?(LOG)
|
|
246
|
+
return match["number"]
|
|
247
|
+
end
|
|
248
|
+
rescue StandardError
|
|
249
|
+
next
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
LOG.warn "Could not resolve card number for internal_id #{internal_id}" if defined?(LOG)
|
|
253
|
+
nil
|
|
254
|
+
end
|
|
255
|
+
|
|
152
256
|
private
|
|
153
257
|
|
|
154
258
|
def detect_branch_from_comment(body, card_number)
|
|
@@ -156,9 +260,12 @@ module Brainiac
|
|
|
156
260
|
match = body.match(%r{<code>(fizzy-#{card_number}-[^<]+)</code>})
|
|
157
261
|
return match[1] if match
|
|
158
262
|
|
|
159
|
-
# Fall back to card map
|
|
263
|
+
# Fall back to card map — check both new and old format
|
|
160
264
|
map = load_work_item_map
|
|
161
|
-
entry = map.values.find
|
|
265
|
+
entry = map.values.find do |v|
|
|
266
|
+
v.dig("sources", "fizzy", "card_number").to_s == card_number.to_s ||
|
|
267
|
+
v["number"].to_s == card_number.to_s
|
|
268
|
+
end
|
|
162
269
|
entry&.dig("branch")
|
|
163
270
|
end
|
|
164
271
|
|
|
@@ -255,7 +255,10 @@ module Brainiac
|
|
|
255
255
|
card_number = card["number"]
|
|
256
256
|
next unless card_number
|
|
257
257
|
|
|
258
|
-
map_entry = map.values.find
|
|
258
|
+
map_entry = map.values.find do |info|
|
|
259
|
+
info.dig("sources", "fizzy", "card_number").to_s == card_number.to_s ||
|
|
260
|
+
info["number"].to_s == card_number.to_s
|
|
261
|
+
end
|
|
259
262
|
agent_name = map_entry["agent"] if map_entry
|
|
260
263
|
env = Helpers.fizzy_env_for(agent_name || AI_AGENT_NAME)
|
|
261
264
|
|
|
@@ -267,8 +270,8 @@ module Brainiac
|
|
|
267
270
|
primary_worktree: map_entry&.dig("worktree"), primary_branch: map_entry&.dig("branch"))
|
|
268
271
|
|
|
269
272
|
if map_entry
|
|
270
|
-
|
|
271
|
-
map.delete(
|
|
273
|
+
work_item_id = map.key(map_entry)
|
|
274
|
+
map.delete(work_item_id)
|
|
272
275
|
end
|
|
273
276
|
|
|
274
277
|
closed << { number: card_number, url: card["url"], title: card["title"] }
|