Class: Collavre::TriggerLoopVerifyJob

Inherits:
ApplicationJob
  • Object
show all
Includes:
TriggerLoopHelpers
Defined in:
app/jobs/collavre/trigger_loop_verify_job.rb

Instance Method Summary collapse

Instance Method Details

#perform(task_id) ⇒ Object

Verifies whether an agent’s [STATUS: DONE] claim is genuine by asking a separate LLM to compare the agent’s response against the original instructions. If the verification fails, the loop continues instead of completing.

The verifier agent is chosen from feedback+ permission AI agents on the creative, preferring one that is NOT the original task agent. Falls back to the task agent if no alternative exists.



17
18
19
20
21
22
23
24
25
26
27
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'app/jobs/collavre/trigger_loop_verify_job.rb', line 17

def perform(task_id)
  task = Task.find_by(id: task_id)
  return unless task&.creative

  child_creative = task.creative
  parent_creative = child_creative.parent
  return unless parent_creative&.drop_trigger_enabled?

  loop_config = child_creative.data&.dig("trigger", "loop")
  return unless loop_config && loop_config["state"] == "pending_verification"

  topic = Topic.find_by(id: task.topic_id)
  return unless topic

  # Only verify tasks from the loop's trigger topic (cross-topic guard)
  trigger_topic_id = loop_config["trigger_topic_id"]
  return if trigger_topic_id.present? && trigger_topic_id != task.topic_id

  last_agent_comment = find_last_agent_comment(child_creative, topic, task)
  return unless last_agent_comment

  instructions = collect_instructions(child_creative, parent_creative)
  verifier = pick_verifier_agent(parent_creative, task.agent_id)

  unless verifier
    # No verifier available — accept DONE as-is
    update_loop_data(child_creative, state: "completed")
    return
  end

  result = verify_completion(verifier, instructions, last_agent_comment.content.to_s)

  if result == :verified
    update_loop_data(child_creative, state: "completed")
  elsif result == :awaiting_user
    # Agent correctly paused to wait for user — do NOT re-loop
    update_loop_data(child_creative, state: "awaiting_user")
    post_system_notice(child_creative, topic, I18n.t(
      "collavre.trigger_loop.awaiting_user",
      iteration: loop_config["current_iteration"]
    ))
  else
    # Verification failed — continue the loop
    iteration = (loop_config["current_iteration"] || 0) + 1
    max = loop_config["max_iterations"] || 10

    if iteration >= max
      update_loop_data(child_creative, state: "max_reached")
      post_system_notice(child_creative, topic, I18n.t(
        "collavre.trigger_loop.max_reached", max: max
      ))
    else
      update_loop_data(child_creative,
        state: "running", current_iteration: iteration,
        last_task_id: task.id)
      post_verification_failed(child_creative, topic, task.agent, iteration, max, result)
    end
  end
end