brainiac-basecamp 0.0.25 → 0.0.26
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/basecamp/cli.rb +31 -0
- data/lib/brainiac/plugins/basecamp/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: 527e9e3b326e216a5080ae89148317e15530ac84d07ec01e30a90a3676528f9c
|
|
4
|
+
data.tar.gz: 436a083dda6818c8328df04179f3789d9febc0f4f6bd3016f744d7cd09921bc8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5cfd4aba7b96d8fdc49c368dab4dc76c8f21f2a29052ff6f8271dcee4cc824e95f9036aeb0325a540c9c082194b9d3854705092629ea9020fb16797ffe3d413f
|
|
7
|
+
data.tar.gz: 97ee914315cd7f978a3b736553db059e572a3bd629950cc7ed7220d644bdf6b6d89bda0d013e317a87b9b70c21069e7b4e3776563b82f20e062f59c67f260bfa
|
|
@@ -986,9 +986,15 @@ module Brainiac
|
|
|
986
986
|
# Reset the task
|
|
987
987
|
reset_task_to(task, target_status)
|
|
988
988
|
|
|
989
|
+
# If completing this task leaves every task in the epic complete,
|
|
990
|
+
# seal the epic in the same atomic write so the reconcile loop never
|
|
991
|
+
# re-fires the completion notification.
|
|
992
|
+
finalized = finalize_epic_if_all_complete!(epic)
|
|
993
|
+
|
|
989
994
|
save_epics(epics)
|
|
990
995
|
puts "✓ Reset card ##{card_number} from '#{old_status}' → '#{target_status}'"
|
|
991
996
|
puts " Epic: #{epic['title']}"
|
|
997
|
+
puts "✓ All tasks complete — epic finalized (status=complete, notification suppressed)" if finalized
|
|
992
998
|
|
|
993
999
|
return unless target_status == "pending"
|
|
994
1000
|
|
|
@@ -1096,8 +1102,11 @@ module Brainiac
|
|
|
1096
1102
|
tasks_to_reset.each { |t| reset_task_to(t, target_status) }
|
|
1097
1103
|
epic["updated_at"] = Time.now.iso8601
|
|
1098
1104
|
|
|
1105
|
+
finalized = finalize_epic_if_all_complete!(epic)
|
|
1106
|
+
|
|
1099
1107
|
save_epics(epics)
|
|
1100
1108
|
puts "✓ Reset #{tasks_to_reset.size} task(s) → '#{target_status}' in epic '#{epic['title']}'"
|
|
1109
|
+
puts "✓ All tasks complete — epic finalized (status=complete, notification suppressed)" if finalized
|
|
1101
1110
|
puts ""
|
|
1102
1111
|
epic["tasks"].each do |t|
|
|
1103
1112
|
icon = case t["status"]
|
|
@@ -1169,9 +1178,31 @@ module Brainiac
|
|
|
1169
1178
|
task["awaiting_final_decision"] = true
|
|
1170
1179
|
when "complete"
|
|
1171
1180
|
task["completed_at"] ||= Time.now.iso8601
|
|
1181
|
+
# A completed task is no longer awaiting a final decision. Leaving
|
|
1182
|
+
# this true lets reconcile_final_decision_task treat the task as
|
|
1183
|
+
# unsettled and re-dispatch/re-complete it on the next sweep.
|
|
1184
|
+
task["awaiting_final_decision"] = false
|
|
1172
1185
|
end
|
|
1173
1186
|
end
|
|
1174
1187
|
|
|
1188
|
+
# Seal an epic when a reset leaves every task complete. Without this, an
|
|
1189
|
+
# epic can sit status="active" with all tasks done — exactly the
|
|
1190
|
+
# thrash-prone state where the 90s reconcile loop re-detects "all
|
|
1191
|
+
# complete", re-runs complete_epic, and re-posts the "🎉 Epic completed"
|
|
1192
|
+
# notification on every sweep. Setting completion_notified suppresses a
|
|
1193
|
+
# notification for this manual, operator-driven completion. Returns true
|
|
1194
|
+
# if the epic was finalized.
|
|
1195
|
+
def finalize_epic_if_all_complete!(epic)
|
|
1196
|
+
return false unless epic["tasks"]&.any?
|
|
1197
|
+
return false unless epic["tasks"].all? { |t| t["status"] == "complete" }
|
|
1198
|
+
return false if epic["status"] == "complete"
|
|
1199
|
+
|
|
1200
|
+
epic["status"] = "complete"
|
|
1201
|
+
epic["completed_at"] ||= Time.now.iso8601
|
|
1202
|
+
epic["completion_notified"] = true
|
|
1203
|
+
true
|
|
1204
|
+
end
|
|
1205
|
+
|
|
1175
1206
|
def load_epics
|
|
1176
1207
|
epics_file = File.join(BRAINIAC_DIR, "basecamp_epics.json")
|
|
1177
1208
|
return [] unless File.exist?(epics_file)
|