Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 16 additions & 9 deletions app/jobs/agent_evaluate_commitment_job.rb
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
class AgentEvaluateCommitmentJob < ApplicationJob
include GoodJob::ActiveJobExtensions::Concurrency
include RunsClaudeAgent

queue_as :default

good_job_control_concurrency_with(
perform_limit: 5,
enqueue_limit: 550,
key: "AgentEvaluateCommitmentJob"
)

retry_on GoodJob::ActiveJobExtensions::Concurrency::ConcurrencyExceededError, wait: 60.seconds, attempts: Float::INFINITY
# Concurrency is bounded only by the worker's thread count (good_job.max_threads).
retry_on StandardError, wait: 30.seconds, attempts: 3

def perform(commitment, trigger_type: "manual", as_of_date: nil)
# Each run is a full agent session (~2 minutes). Skip commitments already
# assessed today unless force: true, so a re-run of the weekly scan or a
# duplicate manual enqueue doesn't repeat work.
def perform(commitment, trigger_type: "manual", as_of_date: nil, force: false)
if !force && assessed_today?(commitment)
Rails.logger.info("AgentEvaluateCommitmentJob: Skipping commitment #{commitment.id}, already assessed today at #{commitment.last_assessed_at.iso8601} (pass force: true to re-run)")
return
end

current_date = as_of_date || Date.today.iso8601
prompt = format(AgentPrompts::EVALUATE_COMMITMENT_PROMPT, commitment_id: commitment.id, current_date: current_date)
hook_script = agent_dir.join(".claude/hooks/on_stop_commitment.sh").to_s
Expand All @@ -30,4 +31,10 @@ def perform(commitment, trigger_type: "manual", as_of_date: nil)

Rails.logger.info("AgentEvaluateCommitmentJob: Success for commitment #{commitment.id}")
end

private

def assessed_today?(commitment)
commitment.last_assessed_at.present? && commitment.last_assessed_at.to_date == Date.current
end
end
30 changes: 30 additions & 0 deletions test/jobs/agent_evaluate_commitment_job_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,36 @@ class AgentEvaluateCommitmentJobTest < ActiveJob::TestCase
assert_match(%r{http://127\.0\.0\.1:1 is unreachable}, error.message)
end

test "skips a commitment already assessed today" do
ENV["AGENT_API_KEY"] = "test-key"
ENV["RAILS_API_URL"] = "http://127.0.0.1:1"
@commitment.update!(last_assessed_at: 1.hour.ago)

AgentEvaluateCommitmentJob.perform_now(@commitment)

assert_no_enqueued_jobs only: AgentEvaluateCommitmentJob
end

test "re-runs a commitment assessed today when forced" do
ENV["AGENT_API_KEY"] = "test-key"
ENV["RAILS_API_URL"] = "http://127.0.0.1:1"
@commitment.update!(last_assessed_at: 1.hour.ago)

error = perform_and_capture_retry_error(AgentEvaluateCommitmentJob.new(@commitment, force: true))

assert_instance_of RunsClaudeAgent::ApiUnreachableError, error
end

test "runs a commitment last assessed on a previous day" do
ENV["AGENT_API_KEY"] = "test-key"
ENV["RAILS_API_URL"] = "http://127.0.0.1:1"
@commitment.update!(last_assessed_at: 1.day.ago.end_of_day - 1.hour)

error = perform_and_capture_retry_error(AgentEvaluateCommitmentJob.new(@commitment))

assert_instance_of RunsClaudeAgent::ApiUnreachableError, error
end

private

# retry_on rescues the failure and re-enqueues the job; the error is only
Expand Down
Loading