Class: Mneme::Tools::AttachEventsToGoals

Inherits:
Tools::Base show all
Defined in:
lib/mneme/tools/attach_events_to_goals.rb

Overview

Pins critical events to active Goals so they survive viewport eviction. Mneme calls this when it sees important events (user instructions, key decisions, critical corrections) approaching the eviction zone.

Events are pinned via a many-to-many join: one event can be attached to multiple Goals. When all referencing Goals complete, the pin is automatically released (reference-counted cleanup in Goal#release_orphaned_pins!).

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Tools::Base

schema

Constructor Details

#initialize(main_session:) ⇒ AttachEventsToGoals

Returns a new instance of AttachEventsToGoals.

Parameters:

  • main_session (Session)

    the session being observed



40
41
42
# File 'lib/mneme/tools/attach_events_to_goals.rb', line 40

def initialize(main_session:, **)
  @session = main_session
end

Class Method Details

.descriptionObject



15
16
17
18
# File 'lib/mneme/tools/attach_events_to_goals.rb', line 15

def self.description = "Pin critical events to active goals so they survive " \
"viewport eviction. Use this for events that are too important to lose — " \
"exact user instructions, key decisions, critical corrections. " \
"Events stay pinned until all attached goals complete."

.input_schemaObject



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/mneme/tools/attach_events_to_goals.rb', line 20

def self.input_schema
  {
    type: "object",
    properties: {
      event_ids: {
        type: "array",
        items: {type: "integer"},
        description: "Database IDs of events to pin (from `event N` prefixes in the viewport)"
      },
      goal_ids: {
        type: "array",
        items: {type: "integer"},
        description: "IDs of active goals to attach the events to"
      }
    },
    required: %w[event_ids goal_ids]
  }
end

.tool_nameObject



13
# File 'lib/mneme/tools/attach_events_to_goals.rb', line 13

def self.tool_name = "attach_events_to_goals"

Instance Method Details

#execute(input) ⇒ String

Returns confirmation with link count, or error description.

Parameters:

  • input (Hash<String, Object>)

    with “event_ids” and “goal_ids”

Returns:

  • (String)

    confirmation with link count, or error description



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/mneme/tools/attach_events_to_goals.rb', line 46

def execute(input)
  event_ids = Array(input["event_ids"]).map(&:to_i).uniq
  goal_ids = Array(input["goal_ids"]).map(&:to_i).uniq

  return "Error: event_ids cannot be empty" if event_ids.empty?
  return "Error: goal_ids cannot be empty" if goal_ids.empty?

  events = @session.events.where(id: event_ids)
  goals = @session.goals.active.where(id: goal_ids)

  missing_events = event_ids - events.pluck(:id)
  inactive_goal_ids = goal_ids - goals.pluck(:id)

  errors = []
  errors << "Events not found: #{missing_events.join(", ")}" if missing_events.any?

  if inactive_goal_ids.any?
    completed_ids = @session.goals.completed.where(id: inactive_goal_ids).pluck(:id)
    not_found_ids = inactive_goal_ids - completed_ids
    errors << "Goals already completed: #{completed_ids.join(", ")}" if completed_ids.any?
    errors << "Goals not found: #{not_found_ids.join(", ")}" if not_found_ids.any?
  end

  return "Error: #{errors.join("; ")}" if errors.any?

  attached = attach(events, goals)
  "Pinned #{attached} event-goal links"
end