brainiac-fizzy 0.0.2 → 0.0.5

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: 4d61ec1e2e7dda1f0d37c5d584064da809d8314a97e9ad937c1ccc15ac8b7622
4
- data.tar.gz: 794c745cb261a297a27c2b26bc7e0d831acf4eb86b56f74244f8f0f35c8b88fd
3
+ metadata.gz: 52b33b796dafe9d47fe9db8f881537d2d66bda2f54f51f1bafb9dd4a4b188a4c
4
+ data.tar.gz: '0260149a3b2daa8439049b9369980f1edf73f65226cb07785f7f0c954e74dc66'
5
5
  SHA512:
6
- metadata.gz: 5a00fdc220e52bfdc4e27fc44472af3c7036f5f60bcaaa49e33239e217a48474d50fbfea3bf36b214d592260d3c06022dd8d7b5c1f1f531b694c1add5267ab4a
7
- data.tar.gz: 181d3be9008ff6bea89223d6caed6d76503d3c1aac8517fa26c785f3f99ae9467f0acb2e7b103d1f646b3482f5ec1c0a1013bdb2498a6247010fcdd36cfcb41a
6
+ metadata.gz: 2fc7f43f8c505d94fc7f4364cb24d33d9aee11d23e6a73033df82e5fd6ad4b4aa496348df42fcac455ba71d75d7d66b3cea76b458f3cb5b0f544682427e5f4a5
7
+ data.tar.gz: 6bb9c239037adde4e1f371eb7087501ee9233ac32177ca2997aad0a4926b4e9db217d0b06dd49e2384fab3cb4a27de01b7491af32afcf121a536e68e7ab5a773
@@ -0,0 +1,142 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+
5
+ module Brainiac
6
+ module Plugins
7
+ module Fizzy
8
+ # CLI subcommands for brainiac-fizzy plugin.
9
+ #
10
+ # Invoked when a user runs `brainiac fizzy <command>`.
11
+ module Cli
12
+ BRAINIAC_DIR = ENV.fetch("BRAINIAC_DIR", File.join(Dir.home, ".brainiac"))
13
+ FIZZY_CONFIG_FILE = File.join(BRAINIAC_DIR, "fizzy.json")
14
+
15
+ class << self
16
+ def run(args)
17
+ command = args.shift
18
+
19
+ case command
20
+ when "config"
21
+ cmd_config
22
+ when "status"
23
+ cmd_status
24
+ when "setup"
25
+ cmd_setup
26
+ else
27
+ print_help
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def cmd_config
34
+ if File.exist?(FIZZY_CONFIG_FILE)
35
+ puts File.read(FIZZY_CONFIG_FILE)
36
+ else
37
+ puts "No Fizzy config found at #{FIZZY_CONFIG_FILE}"
38
+ puts "Run 'brainiac fizzy setup' to get started."
39
+ end
40
+ end
41
+
42
+ def cmd_status
43
+ server_url = detect_server_url
44
+ begin
45
+ uri = URI("#{server_url}/api/fizzy")
46
+ response = Net::HTTP.get_response(uri)
47
+ data = JSON.parse(response.body)
48
+ puts "Fizzy: #{data["enabled"] ? "enabled" : "disabled"}"
49
+ puts "Boards: #{(data["boards"] || []).join(", ")}" if data["boards"]
50
+ puts "Authorized users: #{data["authorized_users"]}" if data["authorized_users"]
51
+ rescue StandardError => e
52
+ puts "Could not reach server at #{server_url}: #{e.message}"
53
+ puts "Is the server running? Check with: brainiac status"
54
+ end
55
+ end
56
+
57
+ def cmd_setup
58
+ puts "Fizzy Setup"
59
+ puts "==========="
60
+ puts ""
61
+
62
+ if File.exist?(FIZZY_CONFIG_FILE)
63
+ config = JSON.parse(File.read(FIZZY_CONFIG_FILE))
64
+ boards = config["boards"] || {}
65
+ users = config["authorized_users"] || []
66
+
67
+ if boards.any?
68
+ puts "✓ #{boards.size} board(s) configured: #{boards.keys.join(", ")}"
69
+ else
70
+ puts "⚠ No boards configured."
71
+ puts " Edit #{FIZZY_CONFIG_FILE} to add board config."
72
+ end
73
+ puts ""
74
+
75
+ if users.any?
76
+ puts "✓ #{users.size} authorized user(s)"
77
+ else
78
+ puts "⚠ No authorized users configured."
79
+ end
80
+ else
81
+ puts "⚠ No fizzy.json found."
82
+ puts " Create #{FIZZY_CONFIG_FILE} with your board config."
83
+ puts ""
84
+ puts " Minimum config:"
85
+ puts " {"
86
+ puts ' "authorized_users": [{ "id": "user-id", "name": "You", "human": true }],'
87
+ puts ' "boards": {'
88
+ puts ' "development": {'
89
+ puts ' "board_id": "your-board-id",'
90
+ puts ' "webhook_secret": "your-secret",'
91
+ puts ' "columns": { "right_now": "col-id", "needs_review": "col-id" }'
92
+ puts " }"
93
+ puts " }"
94
+ puts " }"
95
+ end
96
+ puts ""
97
+ puts "Webhook URL: https://<your-ngrok>.ngrok-free.app/fizzy/<board-key>"
98
+ end
99
+
100
+ def print_help
101
+ puts <<~HELP
102
+ Usage: brainiac fizzy <command>
103
+
104
+ Commands:
105
+ config Show Fizzy config
106
+ status Check Fizzy status via server API
107
+ setup Show setup guide
108
+
109
+ Fizzy handles card assignment, comments, @mentions, cross-agent reviews,
110
+ duplicate detection, and planning mode via webhooks.
111
+
112
+ Webhook URL: https://<your-ngrok>/fizzy/<board-key>
113
+ Config file: #{FIZZY_CONFIG_FILE}
114
+ HELP
115
+ end
116
+
117
+ def detect_server_url
118
+ config_file = File.join(BRAINIAC_DIR, "brainiac.json")
119
+ if File.exist?(config_file)
120
+ config = JSON.parse(File.read(config_file))
121
+ config["server_url"] || "http://localhost:4567"
122
+ else
123
+ "http://localhost:4567"
124
+ end
125
+ rescue JSON::ParserError
126
+ "http://localhost:4567"
127
+ end
128
+ end
129
+ end
130
+
131
+ # Plugin CLI entry point — called by brainiac core's plugin delegation.
132
+ def self.cli(args)
133
+ Cli.run(args)
134
+ end
135
+
136
+ # Subcommand names for bash completion.
137
+ def self.completions
138
+ %w[config status setup]
139
+ end
140
+ end
141
+ end
142
+ end
@@ -63,15 +63,22 @@ module Brainiac
63
63
  end
64
64
 
65
65
  def board_key_for_project(project_config)
66
+ # Priority 1: explicit fizzy_board in project config (board key name from fizzy.json)
67
+ board_key = project_config["fizzy_board"]
68
+ return board_key if board_key && @boards.key?(board_key)
69
+
70
+ # Priority 2: .fizzy.yaml in the repo directory
66
71
  fizzy_yaml = File.join(project_config["repo_path"], ".fizzy.yaml")
67
- return nil unless File.exist?(fizzy_yaml)
72
+ if File.exist?(fizzy_yaml)
73
+ require "yaml"
74
+ data = YAML.safe_load_file(fizzy_yaml)
75
+ board_id = data["board"]
76
+ return board_key_for_id(board_id)
77
+ end
68
78
 
69
- require "yaml"
70
- data = YAML.safe_load_file(fizzy_yaml)
71
- board_id = data["board"]
72
- board_key_for_id(board_id)
79
+ nil
73
80
  rescue StandardError => e
74
- LOG.warn "[Fizzy] Could not read .fizzy.yaml: #{e.message}" if defined?(LOG)
81
+ LOG.warn "[Fizzy] Could not resolve board for project: #{e.message}" if defined?(LOG)
75
82
  nil
76
83
  end
77
84
 
@@ -67,28 +67,34 @@ end
67
67
 
68
68
  def react_to_assignment(card_number, repo_path, agent_name)
69
69
  Thread.new do
70
- # Delete existing reactions from this agent before re-reacting
71
- result = run_cmd("fizzy", "reaction", "list", "--card", card_number.to_s,
72
- "--jq", '[.data[] | {id, reacter_id: .reacter.id}]',
73
- chdir: repo_path, env: fizzy_env_for(agent_name))
74
- reactions = JSON.parse(result)
75
-
76
- identity = run_cmd("fizzy", "identity", "show", "--jq", '.data.accounts[0].user.id',
77
- chdir: repo_path, env: fizzy_env_for(agent_name))
78
- current_user_id = identity.strip.tr('"', '')
79
-
80
- reactions.each do |reaction|
81
- if reaction["reacter_id"] == current_user_id
82
- run_cmd("fizzy", "reaction", "delete", reaction["id"], "--card", card_number.to_s,
83
- chdir: repo_path, env: fizzy_env_for(agent_name))
70
+ env = fizzy_env_for(agent_name)
71
+
72
+ # Best-effort cleanup of existing reactions from this agent
73
+ begin
74
+ result = run_cmd("fizzy", "reaction", "list", "--card", card_number.to_s,
75
+ chdir: repo_path, env: env)
76
+ reactions = JSON.parse(result)["data"] || []
77
+
78
+ identity_output = run_cmd("fizzy", "identity", "show", chdir: repo_path, env: env)
79
+ current_user_id = JSON.parse(identity_output).dig("data", "accounts", 0, "user", "id")
80
+
81
+ if current_user_id
82
+ reactions.each do |reaction|
83
+ if reaction.dig("reacter", "id") == current_user_id
84
+ run_cmd("fizzy", "reaction", "delete", reaction["id"], "--card", card_number.to_s,
85
+ chdir: repo_path, env: env)
86
+ end
87
+ end
84
88
  end
89
+ rescue StandardError => e
90
+ LOG.warn "Could not clean up existing reactions on card ##{card_number}: #{e.message}"
85
91
  end
86
92
 
87
- # Add fresh reaction
93
+ # Always attempt to add the reaction even if cleanup failed
88
94
  run_cmd("fizzy", "reaction", "create", "--card", card_number.to_s,
89
- "--content", "👍", chdir: repo_path, env: fizzy_env_for(agent_name))
95
+ "--content", "👀", chdir: repo_path, env: env)
90
96
  rescue StandardError => e
91
- LOG.warn "Could not add reaction to card: #{e.message}"
97
+ LOG.warn "Could not add reaction to card ##{card_number}: #{e.message}"
92
98
  end
93
99
  end
94
100
 
@@ -488,10 +488,10 @@ def dispatch_followup_comment(ctx, card_key:, card_number:, work_dir:)
488
488
  effort = detect_effort(ctx.project_config, tags: card_tags, text: ctx.plain_text)
489
489
 
490
490
  is_worktree = work_dir != ctx.project_config["repo_path"]
491
- resolved = resolve_project_cli_config(ctx.project_config,
492
- cli_provider_override: ctx.cli_provider_override,
493
- agent_name: ctx.agent_name)
494
- should_resume = is_worktree && resolved["resume_flag"]
491
+ should_resume = is_worktree && resume_viable?(
492
+ project_config: ctx.project_config, cli_provider: ctx.cli_provider_override,
493
+ agent_name: ctx.agent_name, chdir: work_dir
494
+ )
495
495
 
496
496
  prompt = if should_resume
497
497
  LOG.info "[Resume] Using lean prompt for follow-up on card #{card_number || ctx.card_internal_id}"
@@ -508,7 +508,7 @@ def dispatch_followup_comment(ctx, card_key:, card_number:, work_dir:)
508
508
  log_name: "followup-#{card_number || ctx.card_internal_id}",
509
509
  model: ctx.model, effort: effort, agent_name: ctx.agent_name,
510
510
  card_number: card_number, comment_id: ctx.comment_id,
511
- source: :fizzy, cli_provider: ctx.cli_provider_override, resume: is_worktree,
511
+ source: :fizzy, cli_provider: ctx.cli_provider_override, resume: should_resume,
512
512
  source_context: {
513
513
  card_number: card_number, card_internal_id: ctx.card_internal_id,
514
514
  deploy_intent: ctx.deploy_intent
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Lightweight metadata for brainiac-fizzy.
4
+ # Loaded by `brainiac help` without pulling in the full plugin runtime.
5
+
6
+ require_relative "version"
7
+
8
+ module Brainiac
9
+ module Plugins
10
+ module Fizzy
11
+ # Returns true if Fizzy has at least one board configured.
12
+ def self.configured?
13
+ config_file = File.join(ENV.fetch("BRAINIAC_DIR", File.join(Dir.home, ".brainiac")), "fizzy.json")
14
+ return false unless File.exist?(config_file)
15
+
16
+ config = JSON.parse(File.read(config_file))
17
+ !(config["boards"] || {}).empty?
18
+ rescue StandardError
19
+ false
20
+ end
21
+
22
+ # Help text shown in `brainiac help` when the plugin is installed.
23
+ def self.help_text
24
+ " brainiac fizzy <command> Manage Fizzy boards"
25
+ end
26
+ end
27
+ end
28
+ end
@@ -71,7 +71,10 @@ module Brainiac
71
71
  """
72
72
 
73
73
  Focus your response on the comment above. If you've already addressed this in a previous session, reply confirming it's done.
74
- Otherwise, make the requested changes, commit, push, and update the PR.
74
+ Otherwise, make the requested changes, commit, and push.
75
+
76
+ **Response destination: Post your response as a comment on Fizzy card #{{CARD_NUMBER}}.**
77
+ Do NOT post comments on the GitHub PR — this conversation is happening on the card.
75
78
  PROMPT
76
79
 
77
80
  FOLLOWUP_NO_WORKTREE = <<~PROMPT
@@ -3,7 +3,7 @@
3
3
  module Brainiac
4
4
  module Plugins
5
5
  module Fizzy
6
- VERSION = "0.0.2"
6
+ VERSION = "0.0.5"
7
7
  end
8
8
  end
9
9
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "fizzy/version"
4
+ require_relative "fizzy/metadata"
4
5
  require_relative "fizzy/config"
5
6
  require_relative "fizzy/helpers"
6
7
  require_relative "fizzy/prompts"
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.2
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Davis
@@ -89,6 +89,7 @@ extra_rdoc_files: []
89
89
  files:
90
90
  - README.md
91
91
  - lib/brainiac/plugins/fizzy.rb
92
+ - lib/brainiac/plugins/fizzy/cli.rb
92
93
  - lib/brainiac/plugins/fizzy/config.rb
93
94
  - lib/brainiac/plugins/fizzy/delegators.rb
94
95
  - lib/brainiac/plugins/fizzy/handlers/assignment.rb
@@ -99,6 +100,7 @@ files:
99
100
  - lib/brainiac/plugins/fizzy/handlers/deployments.rb
100
101
  - lib/brainiac/plugins/fizzy/helpers.rb
101
102
  - lib/brainiac/plugins/fizzy/hooks.rb
103
+ - lib/brainiac/plugins/fizzy/metadata.rb
102
104
  - lib/brainiac/plugins/fizzy/planning.rb
103
105
  - lib/brainiac/plugins/fizzy/prompts.rb
104
106
  - lib/brainiac/plugins/fizzy/version.rb