Module: Legion::Extensions::MindGrowth::Runners::Governance
- Extended by:
- Governance
- Includes:
- Helpers::Lex
- Included in:
- Governance
- Defined in:
- lib/legion/extensions/mind_growth/runners/governance.rb
Constant Summary collapse
- VOTE_VALUES =
%i[approve reject].freeze
Instance Method Summary collapse
- #approve_proposal(proposal_id:, _reason: nil) ⇒ Object
- #governance_resolved(proposal_id:, base_path: nil) ⇒ Object
- #governance_stats ⇒ Object
- #reject_proposal(proposal_id:, reason: nil) ⇒ Object
- #submit_proposal(proposal_id:) ⇒ Object
- #tally_votes(proposal_id:) ⇒ Object
- #vote_on_proposal(proposal_id:, vote:, agent_id: 'default', rationale: nil) ⇒ Object
Instance Method Details
#approve_proposal(proposal_id:, _reason: nil) ⇒ Object
99 100 101 102 103 104 105 106 107 108 |
# File 'lib/legion/extensions/mind_growth/runners/governance.rb', line 99 def approve_proposal(proposal_id:, _reason: nil, **) proposal = Runners::Proposer.get_proposal_object(proposal_id) return { success: false, error: :not_found } unless proposal proposal.transition!(:approved) Runners::Proposer.persist_proposal(proposal) { success: true, proposal_id: proposal_id, status: :approved } rescue ArgumentError => e { success: false, error: e. } end |
#governance_resolved(proposal_id:, base_path: nil) ⇒ Object
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/legion/extensions/mind_growth/runners/governance.rb', line 55 def governance_resolved(proposal_id:, base_path: nil, **) tally = tally_votes(proposal_id: proposal_id) return { action: :tally_failed } unless tally[:success] case tally[:verdict] when :approved log.info "[governance] build triggered for #{proposal_id}" build_result = Runners::Builder.build_extension(proposal_id: proposal_id, base_path: base_path) { action: :build_triggered, build: build_result, tally: tally } when :rejected log.info "[governance] proposal rejected: #{proposal_id}" proposal = Runners::Proposer.get_proposal_object(proposal_id) if proposal proposal.transition!(:rejected) Runners::Proposer.persist_proposal(proposal) end { action: :rejected, tally: tally } else { action: :pending, tally: tally } end rescue StandardError => e log.error "[governance] governance_resolved failed for #{proposal_id}: #{e.}" { action: :error, error: e. } end |
#governance_stats ⇒ Object
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
# File 'lib/legion/extensions/mind_growth/runners/governance.rb', line 121 def governance_stats(**) all_votes = votes_mutex.synchronize { votes_store.dup } total_votes = all_votes.values.sum(&:size) proposals_with_votes = all_votes.size vote_summary = all_votes.transform_values do |ballots| { approve: ballots.count { |b| b[:vote] == :approve }, reject: ballots.count { |b| b[:vote] == :reject }, total: ballots.size } end proposal_stats = Runners::Proposer.proposal_stats by_status = proposal_stats[:stats][:by_status] governance_breakdown = Helpers::Constants::GOVERNANCE_STATUSES.to_h do |s| [s, by_status[s] || 0] end { success: true, total_votes: total_votes, proposals_with_votes: proposals_with_votes, vote_summary: vote_summary, governance_breakdown: governance_breakdown } end |
#reject_proposal(proposal_id:, reason: nil) ⇒ Object
110 111 112 113 114 115 116 117 118 119 |
# File 'lib/legion/extensions/mind_growth/runners/governance.rb', line 110 def reject_proposal(proposal_id:, reason: nil, **) proposal = Runners::Proposer.get_proposal_object(proposal_id) return { success: false, error: :not_found } unless proposal proposal.transition!(:rejected) Runners::Proposer.persist_proposal(proposal) { success: true, proposal_id: proposal_id, status: :rejected, reason: reason } rescue ArgumentError => e { success: false, error: e. } end |
#submit_proposal(proposal_id:) ⇒ Object
15 16 17 18 19 20 21 22 23 24 25 26 |
# File 'lib/legion/extensions/mind_growth/runners/governance.rb', line 15 def submit_proposal(proposal_id:, **) proposal = Runners::Proposer.get_proposal_object(proposal_id) return { success: false, error: :not_found } unless proposal return { success: false, error: :invalid_status, current_status: proposal.status } unless %i[proposed evaluating].include?(proposal.status) proposal.transition!(:evaluating) Runners::Proposer.persist_proposal(proposal) { success: true, proposal_id: proposal_id, status: :evaluating } rescue ArgumentError => e { success: false, error: e. } end |
#tally_votes(proposal_id:) ⇒ Object
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/legion/extensions/mind_growth/runners/governance.rb', line 80 def tally_votes(proposal_id:, **) ballots = votes_mutex.synchronize { (votes_store[proposal_id] || []).dup } approve_count = ballots.count { |b| b[:vote] == :approve } reject_count = ballots.count { |b| b[:vote] == :reject } total = ballots.size verdict = if total < Helpers::Constants::QUORUM :pending elsif approve_count > reject_count :approved else :rejected end { success: true, proposal_id: proposal_id, approve_count: approve_count, reject_count: reject_count, total: total, verdict: verdict } end |
#vote_on_proposal(proposal_id:, vote:, agent_id: 'default', rationale: nil) ⇒ Object
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
# File 'lib/legion/extensions/mind_growth/runners/governance.rb', line 28 def vote_on_proposal(proposal_id:, vote:, agent_id: 'default', rationale: nil, **) vote_sym = vote.to_sym return { success: false, error: :invalid_vote } unless VOTE_VALUES.include?(vote_sym) snapshot = votes_mutex.synchronize do votes_store[proposal_id] ||= [] votes_store[proposal_id] << { vote: vote_sym, agent_id: agent_id.to_s, rationale: rationale, cast_at: Time.now.utc } votes_store.transform_values(&:dup) end Helpers::ProposalPersistence.new.save_votes(snapshot) tally = tally_votes(proposal_id: proposal_id) if tally[:verdict] != :pending log.info "[governance] quorum reached for #{proposal_id}: #{tally[:verdict]}" if defined?(Legion::Events) Legion::Events.emit('governance.quorum_reached', proposal_id: proposal_id, verdict: tally[:verdict]) end return { success: true, proposal_id: proposal_id, vote: vote_sym, agent_id: agent_id.to_s, verdict: tally[:verdict], quorum_reached: true } end { success: true, proposal_id: proposal_id, vote: vote_sym, agent_id: agent_id.to_s } end |