brainiac-fizzy 0.0.18 → 0.0.20

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 34a03eed47ca8ae2a7de8ec8351962c5a3aa59652d7466c14221d4919866519f
4
- data.tar.gz: e18090ad45a15ce328c6c1fdabc267e32c29868bd28e36f6540af7ed1ace6436
3
+ metadata.gz: b22cbc7ee87173e942ed06f8c2c913017a58d305938267e72acfb4c4c5e25e84
4
+ data.tar.gz: b2408edb59cf13713cd2931233c64d84a9a02a638fb3e3ef88ec155bf03c9397
5
5
  SHA512:
6
- metadata.gz: 4db395ff509a514e144c4237affb376ac43de3d2a04ed0a5e89a12f5260c7b02ad144344b3bab5e471f9a617df1af3bbcc99ed29c2151c2e3b61d99df6f5f9c4
7
- data.tar.gz: d9c0cfdcec762022846ed40cc2e8713504f55c6206df41024c484ec9eade1378d60d82e3dd593ebdf76261d7cbcb8bde25f10dfb863830af2e76aca431b960c2
6
+ metadata.gz: 5b751238e7115a6d3f375878eb2f68fb4c5b95b004587edd826f8652108fe771598ab9940b85a0f4d567d2a356753148cdd50fe9b1cf02f5752739773c259213
7
+ data.tar.gz: 8438490f58ee985aa9953a20d0727c36ffde30abd5b677f343a295d2eb80d68a759efc0772f0175bdf426fd811c79560082ef1b72ef128b42addb6901ee49436
@@ -133,11 +133,11 @@ module Brainiac
133
133
  puts "================="
134
134
  puts ""
135
135
 
136
- board = board_setup_select_board
136
+ board = board_setup_select_or_create_board
137
137
  return unless board
138
138
 
139
139
  board_key = board_setup_choose_key(board["name"])
140
- column_map = board_setup_map_columns(board["id"], board["name"])
140
+ column_map = board_setup_columns(board["id"], board["name"])
141
141
  secret = board_setup_ask_secret(board_key)
142
142
 
143
143
  config = board_setup_save(board_key, board["id"], column_map, secret)
@@ -153,7 +153,7 @@ module Brainiac
153
153
  puts " brainiac fizzy board assign <project-key> #{board_key}"
154
154
  end
155
155
 
156
- def board_setup_select_board
156
+ def board_setup_select_or_create_board
157
157
  boards_json = run_fizzy("board", "list", "--all", "--json")
158
158
  unless boards_json
159
159
  puts "Error: Could not fetch boards from Fizzy CLI."
@@ -163,21 +163,42 @@ module Brainiac
163
163
  end
164
164
 
165
165
  boards = JSON.parse(boards_json)["data"] || []
166
- if boards.empty?
167
- puts "No boards found in your Fizzy account."
168
- return nil
169
- end
170
166
 
171
167
  puts "Available boards:"
172
168
  boards.each_with_index do |board, i|
173
169
  puts " #{i + 1}) #{board["name"]} (#{board["id"]})"
174
170
  end
171
+ puts " #{boards.size + 1}) ✨ Create a new board"
175
172
  puts ""
176
173
  print "Select board number: "
177
174
  choice = $stdin.gets&.chomp&.to_i
178
- return puts("Cancelled.") unless choice&.positive? && choice <= boards.size
175
+ return puts("Cancelled.") unless choice&.positive? && choice <= boards.size + 1
179
176
 
180
- boards[choice - 1]
177
+ if choice == boards.size + 1
178
+ board_setup_create_board
179
+ else
180
+ boards[choice - 1]
181
+ end
182
+ end
183
+
184
+ def board_setup_create_board
185
+ print "New board name: "
186
+ name = $stdin.gets&.chomp
187
+ return puts("Cancelled.") if name.nil? || name.empty?
188
+
189
+ print "Allow all team members access? [Y/n]: "
190
+ all_access = $stdin.gets&.chomp&.downcase != "n"
191
+
192
+ args = ["board", "create", "--name", name, "--all_access", all_access.to_s, "--json"]
193
+ output = run_fizzy(*args)
194
+ unless output
195
+ puts "Error: Failed to create board."
196
+ return nil
197
+ end
198
+
199
+ board_data = JSON.parse(output)["data"]
200
+ puts "✓ Created board \"#{name}\" (#{board_data["id"]})"
201
+ board_data
181
202
  end
182
203
 
183
204
  def board_setup_choose_key(board_name)
@@ -188,31 +209,69 @@ module Brainiac
188
209
  board_key
189
210
  end
190
211
 
191
- def board_setup_map_columns(board_id, board_name)
212
+ def board_setup_columns(board_id, board_name)
192
213
  columns_json = run_fizzy("column", "list", "--board", board_id, "--json")
193
214
  columns = columns_json ? (JSON.parse(columns_json)["data"] || []) : []
194
215
  custom_columns = columns.reject { |c| c["pseudo"] }
195
216
 
196
217
  puts ""
197
- puts "Columns for \"#{board_name}\":"
198
- if columns.empty?
199
- puts " (no columns found)"
200
- else
218
+ if custom_columns.any?
219
+ puts "Existing columns for \"#{board_name}\":"
201
220
  columns.each do |col|
202
221
  pseudo_tag = col["pseudo"] ? " [built-in]" : ""
203
222
  puts " • #{col["name"]} (#{col["id"]})#{pseudo_tag}"
204
223
  end
224
+ puts ""
225
+ print "Create brainiac lifecycle columns (right_now, needs_review, uat)? [y/N]: "
226
+ custom_columns = board_setup_create_lifecycle_columns(board_id, custom_columns) if $stdin.gets&.chomp&.downcase == "y"
227
+ else
228
+ puts "No custom columns on \"#{board_name}\" yet."
229
+ print "Create brainiac lifecycle columns (right_now, needs_review, uat)? [Y/n]: "
230
+ custom_columns = board_setup_create_lifecycle_columns(board_id, custom_columns) if $stdin.gets&.chomp&.downcase != "n"
205
231
  end
206
232
 
207
233
  puts ""
208
- puts "Which columns should brainiac track? Enter config names for each."
209
- puts "(These map to column transitions like right_now, needs_review, uat, etc.)"
210
- puts "Leave blank to skip a column."
234
+ puts "Map columns to brainiac config keys:"
235
+ puts "(These control lifecycle transitions: right_now, needs_review, uat)"
236
+ puts "Leave blank to accept suggestion, '-' to skip."
211
237
  puts ""
212
238
 
213
239
  prompt_column_mapping(custom_columns)
214
240
  end
215
241
 
242
+ def board_setup_create_lifecycle_columns(board_id, existing_columns)
243
+ lifecycle = [
244
+ { config_key: "right_now", default_name: "Right Now", color: "blue" },
245
+ { config_key: "needs_review", default_name: "Needs Review", color: "yellow" },
246
+ { config_key: "uat", default_name: "UAT", color: "lime" }
247
+ ]
248
+
249
+ existing_names = existing_columns.map { |c| c["name"].downcase }
250
+
251
+ lifecycle.each do |col_def|
252
+ if existing_names.include?(col_def[:default_name].downcase)
253
+ puts " ✓ \"#{col_def[:default_name]}\" already exists"
254
+ next
255
+ end
256
+
257
+ print " Name for #{col_def[:config_key]} column [#{col_def[:default_name]}]: "
258
+ name = $stdin.gets&.chomp
259
+ name = col_def[:default_name] if name.nil? || name.empty?
260
+
261
+ output = run_fizzy("column", "create", "--board", board_id,
262
+ "--name", name, "--color", col_def[:color], "--json")
263
+ if output
264
+ col_data = JSON.parse(output)["data"]
265
+ puts " ✓ Created \"#{name}\" (#{col_data["id"]})"
266
+ existing_columns << col_data
267
+ else
268
+ puts " ⚠ Failed to create \"#{name}\""
269
+ end
270
+ end
271
+
272
+ existing_columns
273
+ end
274
+
216
275
  def board_setup_ask_secret(board_key)
217
276
  puts ""
218
277
  puts "Webhook setup:"
@@ -29,8 +29,8 @@ def fetch_intent_context(card_number, repo_path:, agent_name: nil)
29
29
  Brainiac::Plugins::Fizzy::Helpers.fetch_intent_context(card_number, repo_path: repo_path, agent_name: agent_name)
30
30
  end
31
31
 
32
- def move_card_to_column(card_number, column_name, project_config:, agent_name: nil)
33
- Brainiac::Plugins::Fizzy::Helpers.move_card_to_column(card_number, column_name, project_config: project_config, agent_name: agent_name)
32
+ def move_card_to_column(card_number, column_name, project_config:, agent_name: nil, board_key: nil)
33
+ Brainiac::Plugins::Fizzy::Helpers.move_card_to_column(card_number, column_name, project_config: project_config, agent_name: agent_name, board_key: board_key)
34
34
  end
35
35
 
36
36
  def append_fizzy_comment_footer(card_number, project_config:, agent_name: nil, since: nil)
@@ -62,7 +62,7 @@ def handle_card_assigned(payload, board_key: nil)
62
62
  card_number: card_number, card_internal_id: card_internal_id, title: title, tags: tags,
63
63
  branch: branch, worktree_path: worktree_path, project_config: project_config, project_key: project_key,
64
64
  agent_name: assigned_agent, model: initial_model,
65
- effort: initial_effort, cli_provider_override: initial_cli
65
+ effort: initial_effort, cli_provider_override: initial_cli, board_key: board_key
66
66
  )
67
67
  end
68
68
 
@@ -123,7 +123,7 @@ def setup_assigned_worktree(repo_path, branch, card_internal_id, card_number, pr
123
123
  end
124
124
 
125
125
  def dispatch_assigned_card(card_number:, card_internal_id:, title:, tags:, branch:, worktree_path:,
126
- project_config:, project_key:, agent_name:, model:, effort:, cli_provider_override:)
126
+ project_config:, project_key:, agent_name:, model:, effort:, cli_provider_override:, board_key: nil)
127
127
  card_context = prefetch_card_context(card_number, repo_path: project_config["repo_path"], agent_name: agent_name)
128
128
  planning_info = detect_planning_mode(text: title, tags: tags, card_internal_id: card_internal_id, card_number: card_number)
129
129
 
@@ -152,11 +152,11 @@ def dispatch_assigned_card(card_number:, card_internal_id:, title:, tags:, branc
152
152
  project_config: project_config, chdir: worktree_path,
153
153
  log_name: "assigned-#{card_number}", model: model, effort: effort,
154
154
  agent_name: agent_name, card_number: card_number, source: :fizzy,
155
- source_context: { card_number: card_number, dispatched_at: Time.now },
155
+ source_context: { card_number: card_number, board_key: board_key, dispatched_at: Time.now },
156
156
  cli_provider: cli_provider_override)
157
157
  register_session(card_key, pid, log_file: log_file, supersede_key: card_key, agent_name: agent_name)
158
158
 
159
- Thread.new { move_card_to_column(card_number, "right_now", project_config: project_config, agent_name: agent_name) }
159
+ Thread.new { move_card_to_column(card_number, "right_now", project_config: project_config, agent_name: agent_name, board_key: board_key) }
160
160
 
161
161
  [200, { status: "processed", card: card_number, branch: branch, project: project_key, agent: agent_name }.to_json]
162
162
  end
@@ -18,6 +18,7 @@ CommentContext = Struct.new(
18
18
  :project_config, :project_key, :card_number, :worktree,
19
19
  :model, :effort, :deploy_intent, :cli_provider_override,
20
20
  :comment_vars, :card_tags, :worktree_override, :fresh,
21
+ :board_key,
21
22
  keyword_init: true
22
23
  )
23
24
 
@@ -67,7 +68,7 @@ def handle_comment(payload, board_key: nil)
67
68
  card_info: card_info, comment_id: comment_id, creator_name: creator_name,
68
69
  creator_is_agent: creator_is_agent, mentioned_agent: mentioned_agent,
69
70
  agent_name: agent_name, is_cross_agent_mention: is_cross_agent_mention,
70
- project_config: project_config, project_key: project_key
71
+ project_config: project_config, project_key: project_key, board_key: board_key
71
72
  )
72
73
 
73
74
  # --- Intent gate (mirrors brainiac-discord pattern) ---
@@ -101,7 +102,7 @@ end
101
102
 
102
103
  def build_comment_context(eventable:, plain_text:, tags:, card_internal_id:, card_info:, comment_id:, creator_name:,
103
104
  creator_is_agent:, mentioned_agent:, agent_name:, is_cross_agent_mention:,
104
- project_config:, project_key:)
105
+ project_config:, project_key:, board_key: nil)
105
106
  deploy_intent = tags[:deploy_intent]
106
107
  LOG.info "[Deploy] Detected [deploy#{":#{deploy_intent}" unless deploy_intent == :auto}] tag on card #{card_internal_id}" if deploy_intent
107
108
 
@@ -137,6 +138,7 @@ def build_comment_context(eventable:, plain_text:, tags:, card_internal_id:, car
137
138
  creator_is_agent: creator_is_agent, mentioned_agent: mentioned_agent,
138
139
  agent_name: agent_name, is_cross_agent_mention: is_cross_agent_mention,
139
140
  project_config: project_config, project_key: project_key,
141
+ board_key: board_key,
140
142
  model: effective_model,
141
143
  effort: effective_effort,
142
144
  deploy_intent: deploy_intent,
@@ -554,13 +556,13 @@ def dispatch_followup_comment(ctx, card_key:, card_number:, work_dir:)
554
556
  source: :fizzy, cli_provider: ctx.cli_provider_override, resume: should_resume,
555
557
  source_context: {
556
558
  card_number: card_number, card_internal_id: ctx.card_internal_id,
557
- deploy_intent: ctx.deploy_intent, dispatched_at: Time.now
559
+ deploy_intent: ctx.deploy_intent, board_key: ctx.board_key, dispatched_at: Time.now
558
560
  })
559
561
  return [200, { status: "dispatch_failed", agent: ctx.agent_name, card: card_number }.to_json] unless pid
560
562
 
561
563
  register_session(card_key, pid, log_file: log_file, supersede_key: card_key, agent_name: ctx.agent_name)
562
564
 
563
- Thread.new { move_card_to_column(card_number, "right_now", project_config: ctx.project_config, agent_name: ctx.agent_name) }
565
+ Thread.new { move_card_to_column(card_number, "right_now", project_config: ctx.project_config, agent_name: ctx.agent_name, board_key: ctx.board_key) }
564
566
 
565
567
  { status: "follow_up", card: card_number, card_internal_id: ctx.card_internal_id,
566
568
  worktree: work_dir, project: ctx.project_key }
@@ -92,8 +92,8 @@ module Brainiac
92
92
  nil
93
93
  end
94
94
 
95
- def move_card_to_column(card_number, column_name, project_config:, agent_name: nil)
96
- board_key = Config.board_key_for_project(project_config)
95
+ def move_card_to_column(card_number, column_name, project_config:, agent_name: nil, board_key: nil)
96
+ board_key ||= Config.board_key_for_project(project_config)
97
97
  column_id = Config.board_column_id(board_key, column_name) if board_key
98
98
  return unless column_id
99
99
 
@@ -38,7 +38,8 @@ module Brainiac
38
38
  unless ctx[:skip_column_move] || work_item_merged?(card_number)
39
39
  Helpers.move_card_to_column(card_number, "needs_review",
40
40
  project_config: ctx[:project_config],
41
- agent_name: ctx[:agent_name])
41
+ agent_name: ctx[:agent_name],
42
+ board_key: ctx[:source_context]&.dig(:board_key))
42
43
  record_self_move(card_number)
43
44
  end
44
45
 
@@ -3,7 +3,7 @@
3
3
  module Brainiac
4
4
  module Plugins
5
5
  module Fizzy
6
- VERSION = "0.0.18"
6
+ VERSION = "0.0.20"
7
7
  end
8
8
  end
9
9
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brainiac-fizzy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.18
4
+ version: 0.0.20
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Davis