Class: Legion::Extensions::Agentic::Social::Governance::Helpers::Proposal

Inherits:
Object
  • Object
show all
Defined in:
lib/legion/extensions/agentic/social/governance/helpers/proposal.rb

Constant Summary collapse

PROPOSAL_TAG_BASE =
%w[governance proposal].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeProposal

Returns a new instance of Proposal.



17
18
19
20
# File 'lib/legion/extensions/agentic/social/governance/helpers/proposal.rb', line 17

def initialize
  @proposals = {}
  load_from_apollo
end

Instance Attribute Details

#proposalsObject (readonly)

Returns the value of attribute proposals.



15
16
17
# File 'lib/legion/extensions/agentic/social/governance/helpers/proposal.rb', line 15

def proposals
  @proposals
end

Instance Method Details

#create(category:, description:, proposer:, council_size: Layers::MIN_COUNCIL_SIZE) ⇒ Object



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/legion/extensions/agentic/social/governance/helpers/proposal.rb', line 22

def create(category:, description:, proposer:, council_size: Layers::MIN_COUNCIL_SIZE)
  id = SecureRandom.uuid
  @proposals[id] = {
    proposal_id:   id,
    category:      category,
    description:   description,
    proposer:      proposer,
    council_size:  council_size,
    votes_for:     [],
    votes_against: [],
    status:        :open,
    created_at:    Time.now.utc,
    resolved_at:   nil
  }
  save_proposal(id)
  id
end

#get(proposal_id) ⇒ Object



58
59
60
# File 'lib/legion/extensions/agentic/social/governance/helpers/proposal.rb', line 58

def get(proposal_id)
  @proposals[proposal_id]
end

#load_from_apolloObject



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/legion/extensions/agentic/social/governance/helpers/proposal.rb', line 76

def load_from_apollo
  return false unless defined?(Legion::Apollo::Local) && Legion::Apollo::Local.started?

  result = Legion::Apollo::Local.query_by_tags(tags: PROPOSAL_TAG_BASE, limit: 1000)
  return false unless result[:success] && result[:results].is_a?(Array)

  result[:results].each do |entry|
    data = ::JSON.parse(entry[:content], symbolize_names: true)
    pid = data[:proposal_id]
    next unless pid

    # Convert string timestamps back to Time objects
    data[:created_at] = Time.parse(data[:created_at].to_s) if data[:created_at]
    data[:resolved_at] = data[:resolved_at] ? Time.parse(data[:resolved_at].to_s) : nil

    # Ensure status is a symbol
    data[:status] = data[:status].to_sym if data[:status].is_a?(String)

    @proposals[pid] = data
  rescue StandardError => e
    Legion::Logging.warn "[governance] load_from_apollo parse error: #{e.message}"
  end

  @proposals.any?
rescue StandardError => e
  Legion::Logging.warn "[governance] load_from_apollo failed: #{e.message}"
  false
end

#open_proposalsObject



62
63
64
# File 'lib/legion/extensions/agentic/social/governance/helpers/proposal.rb', line 62

def open_proposals
  @proposals.values.select { |p| p[:status] == :open }
end

#resolve_timed_out(proposal_id) ⇒ Object



66
67
68
69
70
71
72
73
74
# File 'lib/legion/extensions/agentic/social/governance/helpers/proposal.rb', line 66

def resolve_timed_out(proposal_id)
  prop = @proposals[proposal_id]
  return nil unless prop && prop[:status] == :open

  prop[:status]      = :timed_out
  prop[:resolved_at] = Time.now.utc
  save_proposal(proposal_id)
  prop
end

#vote(proposal_id, voter:, approve:) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/legion/extensions/agentic/social/governance/helpers/proposal.rb', line 40

def vote(proposal_id, voter:, approve:)
  prop = @proposals[proposal_id]
  return nil unless prop && prop[:status] == :open

  # Prevent double-voting
  all_voters = prop[:votes_for] + prop[:votes_against]
  return :already_voted if all_voters.include?(voter)

  if approve
    prop[:votes_for] << voter
  else
    prop[:votes_against] << voter
  end

  save_proposal(proposal_id)
  check_resolution(proposal_id)
end