brainiac-basecamp 0.0.25 → 0.0.27

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: 9baa0382677cf44d0ef67156c66420348c00b74e7532f6b410dab9d8e61f7e90
4
- data.tar.gz: 353777dfdc0f84ba57e89b8e36249867e9fec29f46ebfe4af0ac090704e14dff
3
+ metadata.gz: cbdbf3cd360b0186167aaf722ffcb20bda8ce915648d1e931bf3da379a2340c7
4
+ data.tar.gz: f0ebcc122d90912c4616e7169852fa4e26ba63919ab9ec85f5b1a50e3269161f
5
5
  SHA512:
6
- metadata.gz: 8f2eee7436544bcfc8278bbb22add64237c6dc4bf4256930566741ce60f683364ec24e9d2784d6765ca418bada76e6f5be8cbbc625b2384f64d1b4d5b1f6d65b
7
- data.tar.gz: a72b44713badc00c8f3bbfc4c433afbf832550e11675d9bb8e384131209c4f1a1d1d810be885fe620bf68762cf1632cf855c209c617ad3b5a57df044895f6150
6
+ metadata.gz: 608ea1521a63273ced78835879fd2477422110a749d161ee3a89d5d83949316ac90ab2484b36cd9ede69d683c8298be28c54e0dce30dd78a3f951c7ce6ac8aa2
7
+ data.tar.gz: 4e0680e96bec2fbc7891938b806b55b2fd8c02ed5c82b788cf3908960217fbe710afa604f18002edfa4b37d15b541e471c5a96f866d8fc0397cb922256ad4aa0
@@ -839,6 +839,8 @@ module Brainiac
839
839
  set fizzy-account-id <id> Set Fizzy account ID (for card URLs)
840
840
  set review-gate <mode> Set review gate (on_complete or on_pr_merge)
841
841
  set epic-prefix <prefix> Set epic todolist prefix (default: "Epic:")
842
+ set ephemeral-deploys <on|off> Enable/disable ephemeral Belt env auto-creation
843
+ set parent-env <project> <env> Set parent env for ephemeral Belt deploys
842
844
  reset task <card-number> [--to <status>] Reset a task to a given status (default: pending)
843
845
  reset epic <todolist-id> [--to <status>] Reset entire epic or all tasks within it
844
846
  reset gates <card-number> Clear gate approvals and re-dispatch gates
@@ -859,6 +861,18 @@ module Brainiac
859
861
  4. deploy.project_envs.<project> in config (per-project default)
860
862
  5. deploy.default_env in config (global default)
861
863
 
864
+ Ephemeral Belt Environments:
865
+ When a Fizzy card with 'deploy' tag is assigned to an agent on a Belt app:
866
+ 1. Creates ephemeral env: belt g environment fizzy-<card> <parent-env>
867
+ 2. Deploys to it: belt deploy fizzy-<card>
868
+ 3. Redeploys on PR push: belt deploy fizzy-<card> [frontend]
869
+ 4. Destroys on PR merge: belt destroy environment fizzy-<card> --full
870
+
871
+ Configure with:
872
+ brainiac basecamp set ephemeral-deploys on
873
+ brainiac basecamp set parent-env stowzilla dev02
874
+ brainiac basecamp set parent-env feature-parity dev
875
+
862
876
  Task statuses (for reset --to):
863
877
  pending — Not yet started, waiting for dependencies
864
878
  in_flight — Agent is actively working on it
@@ -872,13 +886,15 @@ module Brainiac
872
886
  key = args.shift
873
887
  value = args.shift
874
888
 
875
- unless key && value
889
+ unless key
876
890
  puts "Usage: brainiac basecamp set <key> <value>"
877
891
  puts ""
878
892
  puts "Keys:"
879
- puts " fizzy-account-id <id> Fizzy account ID (for card URLs)"
880
- puts " review-gate <mode> on_complete or on_pr_merge"
881
- puts " epic-prefix <prefix> Todolist prefix for epic detection"
893
+ puts " fizzy-account-id <id> Fizzy account ID (for card URLs)"
894
+ puts " review-gate <mode> on_complete, on_pr_merge, or epic_branch"
895
+ puts " epic-prefix <prefix> Todolist prefix for epic detection"
896
+ puts " ephemeral-deploys <on|off> Enable/disable ephemeral Belt env deploys"
897
+ puts " parent-env <project> <env> Set parent env for ephemeral deploys"
882
898
  return
883
899
  end
884
900
 
@@ -886,11 +902,19 @@ module Brainiac
886
902
 
887
903
  case key
888
904
  when "fizzy-account-id"
905
+ unless value
906
+ puts "Usage: brainiac basecamp set fizzy-account-id <id>"
907
+ return
908
+ end
889
909
  config["fizzy_account_id"] = value
890
910
  save_config(config)
891
911
  puts "✓ Set fizzy_account_id = #{value}"
892
912
  puts " Card URLs will be: https://app.fizzy.do/#{value}/cards/NNNN"
893
913
  when "review-gate"
914
+ unless value
915
+ puts "Usage: brainiac basecamp set review-gate <mode>"
916
+ return
917
+ end
894
918
  unless %w[on_complete on_pr_merge epic_branch].include?(value)
895
919
  puts "Error: review-gate must be 'on_complete', 'on_pr_merge', or 'epic_branch'"
896
920
  return
@@ -908,18 +932,64 @@ module Brainiac
908
932
  puts " Epic tasks advance immediately when agent completes"
909
933
  end
910
934
  when "epic-prefix"
935
+ unless value
936
+ puts "Usage: brainiac basecamp set epic-prefix <prefix>"
937
+ return
938
+ end
911
939
  config["epic_prefix"] = value
912
940
  save_config(config)
913
941
  puts "✓ Set epic_prefix = #{value}"
914
942
  when "profile"
943
+ unless value
944
+ puts "Usage: brainiac basecamp set profile <name>"
945
+ return
946
+ end
915
947
  config["basecamp_profile"] = value
916
948
  save_config(config)
917
949
  puts "✓ Set basecamp_profile = #{value}"
918
950
  puts " All basecamp CLI commands will use --profile #{value}"
919
951
  puts " Set up the profile: basecamp profile create #{value} && basecamp auth login --profile #{value}"
952
+ when "ephemeral-deploys"
953
+ unless value
954
+ puts "Usage: brainiac basecamp set ephemeral-deploys <on|off>"
955
+ return
956
+ end
957
+ enabled = %w[on yes true 1].include?(value.downcase)
958
+ config["deploy"] ||= {}
959
+ config["deploy"]["ephemeral_enabled"] = enabled
960
+ save_config(config)
961
+ puts "✓ Set ephemeral_enabled = #{enabled}"
962
+ if enabled
963
+ puts " Ephemeral Belt environments will be created for cards with 'deploy' tag"
964
+ puts " Make sure parent envs are configured: brainiac basecamp set parent-env <project> <env>"
965
+ else
966
+ puts " Ephemeral Belt environment creation is disabled"
967
+ end
968
+ when "parent-env"
969
+ # Special case: takes two values (project and env)
970
+ project_key = value
971
+ parent_env = args.shift
972
+ unless project_key && parent_env
973
+ puts "Usage: brainiac basecamp set parent-env <project-key> <parent-env>"
974
+ puts ""
975
+ puts "Example:"
976
+ puts " brainiac basecamp set parent-env stowzilla dev02"
977
+ puts " brainiac basecamp set parent-env feature-parity dev"
978
+ puts ""
979
+ puts "This sets the parent environment for ephemeral Belt deploys."
980
+ puts "When a card with 'deploy' tag is assigned, an ephemeral environment"
981
+ puts "is created using: belt g environment fizzy-<card> <parent-env>"
982
+ return
983
+ end
984
+ config["deploy"] ||= {}
985
+ config["deploy"]["project_envs"] ||= {}
986
+ config["deploy"]["project_envs"][project_key] = parent_env
987
+ save_config(config)
988
+ puts "✓ Set parent env for '#{project_key}' = #{parent_env}"
989
+ puts " Cards with 'deploy' tag will create: fizzy-<card> from #{parent_env}"
920
990
  else
921
991
  puts "Unknown key: #{key}"
922
- puts "Valid keys: fizzy-account-id, review-gate, epic-prefix, profile"
992
+ puts "Valid keys: fizzy-account-id, review-gate, epic-prefix, profile, ephemeral-deploys, parent-env"
923
993
  end
924
994
  end
925
995
 
@@ -986,9 +1056,15 @@ module Brainiac
986
1056
  # Reset the task
987
1057
  reset_task_to(task, target_status)
988
1058
 
1059
+ # If completing this task leaves every task in the epic complete,
1060
+ # seal the epic in the same atomic write so the reconcile loop never
1061
+ # re-fires the completion notification.
1062
+ finalized = finalize_epic_if_all_complete!(epic)
1063
+
989
1064
  save_epics(epics)
990
1065
  puts "✓ Reset card ##{card_number} from '#{old_status}' → '#{target_status}'"
991
1066
  puts " Epic: #{epic['title']}"
1067
+ puts "✓ All tasks complete — epic finalized (status=complete, notification suppressed)" if finalized
992
1068
 
993
1069
  return unless target_status == "pending"
994
1070
 
@@ -1096,8 +1172,11 @@ module Brainiac
1096
1172
  tasks_to_reset.each { |t| reset_task_to(t, target_status) }
1097
1173
  epic["updated_at"] = Time.now.iso8601
1098
1174
 
1175
+ finalized = finalize_epic_if_all_complete!(epic)
1176
+
1099
1177
  save_epics(epics)
1100
1178
  puts "✓ Reset #{tasks_to_reset.size} task(s) → '#{target_status}' in epic '#{epic['title']}'"
1179
+ puts "✓ All tasks complete — epic finalized (status=complete, notification suppressed)" if finalized
1101
1180
  puts ""
1102
1181
  epic["tasks"].each do |t|
1103
1182
  icon = case t["status"]
@@ -1169,9 +1248,31 @@ module Brainiac
1169
1248
  task["awaiting_final_decision"] = true
1170
1249
  when "complete"
1171
1250
  task["completed_at"] ||= Time.now.iso8601
1251
+ # A completed task is no longer awaiting a final decision. Leaving
1252
+ # this true lets reconcile_final_decision_task treat the task as
1253
+ # unsettled and re-dispatch/re-complete it on the next sweep.
1254
+ task["awaiting_final_decision"] = false
1172
1255
  end
1173
1256
  end
1174
1257
 
1258
+ # Seal an epic when a reset leaves every task complete. Without this, an
1259
+ # epic can sit status="active" with all tasks done — exactly the
1260
+ # thrash-prone state where the 90s reconcile loop re-detects "all
1261
+ # complete", re-runs complete_epic, and re-posts the "🎉 Epic completed"
1262
+ # notification on every sweep. Setting completion_notified suppresses a
1263
+ # notification for this manual, operator-driven completion. Returns true
1264
+ # if the epic was finalized.
1265
+ def finalize_epic_if_all_complete!(epic)
1266
+ return false unless epic["tasks"]&.any?
1267
+ return false unless epic["tasks"].all? { |t| t["status"] == "complete" }
1268
+ return false if epic["status"] == "complete"
1269
+
1270
+ epic["status"] = "complete"
1271
+ epic["completed_at"] ||= Time.now.iso8601
1272
+ epic["completion_notified"] = true
1273
+ true
1274
+ end
1275
+
1175
1276
  def load_epics
1176
1277
  epics_file = File.join(BRAINIAC_DIR, "basecamp_epics.json")
1177
1278
  return [] unless File.exist?(epics_file)
@@ -3,7 +3,7 @@
3
3
  module Brainiac
4
4
  module Plugins
5
5
  module Basecamp
6
- VERSION = "0.0.25"
6
+ VERSION = "0.0.27"
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-basecamp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.25
4
+ version: 0.0.27
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Davis