brainiac-basecamp 0.0.5 → 0.0.7

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: 7fc3e97a3831ea52b8b8ed95e479cf1dcc04b8031d186d591cba88c04108b643
4
- data.tar.gz: 8766b1a4a63878042b465994bff6665b02004a4ad0a1296d60ecfdc84673643f
3
+ metadata.gz: 6bffdae0c7f62eef1cf55ee5c2c23fb8594dd63afc96ffee5cf3c58cdca9ce9f
4
+ data.tar.gz: 3b61e5ae5ef532935c07603c55f6fa36000796ed55951e8277205c219306600b
5
5
  SHA512:
6
- metadata.gz: f4a8e2e10898afd01360bed9d56316590288017be8003348ca3b9c85d561d58b22fe6afbc424fe10e1bbf7ab92aa67c674464d3e1ba402697873cd2ebb2beb03
7
- data.tar.gz: 1964a896b5c3442bb0308c8f363a14dfd813e707086bb31bcea081cf7687b0ec26b3fbea4ddc9130c0f230e4d472e4d3a7dec2036e9f2721e09aaf0ea6864144
6
+ metadata.gz: 6eaa711a5cd134e1838335dbf31813d44ac66b6bb596d731a8c89dde9f99ecc8bca8aea65054fa166da8f40f16cec5df1509719fc201bc82bdeb55fce99abca5
7
+ data.tar.gz: d60e2e46e81dd1a1798127583e6be1620fcd136c482e369fd7b7c129f5a5074cf88edf2cb2b6f6d7bd3a258372feea0886834cfabcc421081f872c89e9bd96a5
@@ -20,7 +20,7 @@ module Brainiac
20
20
  module Epic
21
21
  # Represents a single task within an epic (one todo → one Fizzy card).
22
22
  Task = Struct.new(:todo_id, :title, :fizzy_card, :depends_on, :status, :completed,
23
- :description, :assignees, :due_on, keyword_init: true)
23
+ :description, :assignees, :due_on, :project, keyword_init: true)
24
24
 
25
25
  class << self
26
26
  # Parse todos from a todolist into structured tasks with dependency graph.
@@ -272,7 +272,8 @@ module Brainiac
272
272
  title: t["title"],
273
273
  depends_on: t["depends_on"] || [],
274
274
  status: t["status"].to_sym,
275
- completed: t["status"] == "complete"
275
+ completed: t["status"] == "complete",
276
+ project: t["project"]
276
277
  )
277
278
  end
278
279
 
@@ -3,7 +3,7 @@
3
3
  module Brainiac
4
4
  module Plugins
5
5
  module Basecamp
6
- VERSION = "0.0.5"
6
+ VERSION = "0.0.7"
7
7
  end
8
8
  end
9
9
  end
@@ -131,10 +131,11 @@ module Brainiac
131
131
  projects_file = File.join(ENV.fetch("BRAINIAC_DIR", File.join(Dir.home, ".brainiac")), "projects.json")
132
132
  projects = File.exist?(projects_file) ? JSON.parse(File.read(projects_file)) : {}
133
133
  repo_path = projects.dig(project_key, "repo_path")
134
+ github_repo = projects.dig(project_key, "github_repo")
134
135
 
135
136
  if repo_path
136
137
  # Sync from GitHub to catch any missed approvals
137
- sync_result = ReviewGate.sync_from_github(task, repo_path: repo_path)
138
+ ReviewGate.sync_from_github(task, repo_path: repo_path)
138
139
 
139
140
  if ReviewGate.all_gates_passed?(task)
140
141
  # All approved — advance to final_decision
@@ -164,6 +165,23 @@ module Brainiac
164
165
  end
165
166
  end
166
167
  healed_any = true
168
+ elsif (task["gate_approvals"] || []).empty? && !task["changes_requested_by"]&.any?
169
+ # No gate responses at all — gates may never have been dispatched or agents crashed
170
+ gates_dispatched_at = task["gates_dispatched_at"]
171
+ should_redispatch = gates_dispatched_at.nil? || (Time.now - Time.parse(gates_dispatched_at)) > 300
172
+
173
+ if should_redispatch && github_repo
174
+ LOG.info "[Basecamp:HealthCheck] No gate responses for ##{card_number} — re-dispatching review gates" if defined?(LOG)
175
+ ReviewGate.dispatch_gates(
176
+ epic: epic,
177
+ task: task,
178
+ pr_number: pr_number,
179
+ repo_name: github_repo,
180
+ repo_path: repo_path
181
+ )
182
+ Hooks.send(:save_epic_state, epic)
183
+ healed_any = true
184
+ end
167
185
  end
168
186
  end
169
187
  end
@@ -281,9 +299,41 @@ module Brainiac
281
299
  end
282
300
  end
283
301
  else
284
- # No changes requested yet — just waiting for reviews
302
+ # No changes requested yet — check if gates need (re-)dispatching
285
303
  approvals = task["gate_approvals"]&.size || 0
286
- LOG.info "[Basecamp] Resume: ##{card_number} has #{approvals} approvals, waiting for more reviews" if defined?(LOG)
304
+ gates_dispatched_at = task["gates_dispatched_at"]
305
+
306
+ # Re-dispatch gates if:
307
+ # 1. Gates were never dispatched (missed webhook), OR
308
+ # 2. Gates were dispatched but no responses received after a reasonable window
309
+ should_redispatch = if gates_dispatched_at.nil?
310
+ true
311
+ elsif approvals.zero?
312
+ # If dispatched more than 5 minutes ago with no responses, re-dispatch
313
+ elapsed = Time.now - Time.parse(gates_dispatched_at)
314
+ elapsed > 300
315
+ else
316
+ false
317
+ end
318
+
319
+ if should_redispatch && ReviewGate.enabled?
320
+ github_repo = projects.dig(project_key, "github_repo")
321
+ if github_repo
322
+ LOG.info "[Basecamp] Resume: ##{card_number} has #{approvals} approvals — re-dispatching review gates" if defined?(LOG)
323
+ ReviewGate.dispatch_gates(
324
+ epic: epic,
325
+ task: task,
326
+ pr_number: pr_number,
327
+ repo_name: github_repo,
328
+ repo_path: repo_path
329
+ )
330
+ Hooks.send(:save_epic_state, epic)
331
+ else
332
+ LOG.warn "[Basecamp] Resume: ##{card_number} — cannot re-dispatch gates, no github_repo for #{project_key}" if defined?(LOG)
333
+ end
334
+ else
335
+ LOG.info "[Basecamp] Resume: ##{card_number} has #{approvals} approvals, waiting for more reviews" if defined?(LOG)
336
+ end
287
337
  end
288
338
  end
289
339
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brainiac-basecamp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Davis