Class: RubynCode::Megaplan::CiRecovery

Inherits:
Object
  • Object
show all
Defined in:
lib/rubyn_code/megaplan/ci_recovery.rb

Overview

Drives one CI recovery attempt on a Rubyn-opened PR.

Receives the failure context the extension’s CiWatcher packaged (trimmed log + phase docs + branch + attempt counts) and asks the agent to push a fix commit. Returns a ‘recovery_outcome` shape:

{ kind: 'fixed' | 'no_fix' | 'errored', commit_sha?, summary? }

‘fixed’ means the agent identified and committed a fix on the branch. ‘no_fix’ means the agent looked but couldn’t see an obvious correctness fix in the log (escalate to the human). ‘errored’ means the agent loop itself crashed.

Defined Under Namespace

Classes: RecoveryError

Constant Summary collapse

SYSTEM_PROMPT =
<<~PROMPT.freeze
  You are Rubyn doing CI auto-recovery on a megaplan PR.

  Read the failing job log, identify the root cause, push a fix
  commit to the existing branch. Keep the diff minimal and focused
  — this is not a refactoring opportunity.

  If you can't identify a concrete fix from the log, output exactly:

    NO_FIX_IDENTIFIED: <one-sentence reason>

  Do not invent fixes. Do not "try something" just to try. A clean
  escalation to the human beats a wrong commit any day.
PROMPT

Instance Method Summary collapse

Constructor Details

#initialize(agent_invoker: nil) ⇒ CiRecovery

Returns a new instance of CiRecovery.



35
36
37
# File 'lib/rubyn_code/megaplan/ci_recovery.rb', line 35

def initialize(agent_invoker: nil)
  @agent_invoker = agent_invoker || method(:default_agent_invoker)
end

Instance Method Details

#recover(context) ⇒ Hash

Returns recovery_outcome { kind, commit_sha?, summary? }.

Parameters:

  • context (Hash)

    the recovery_ci payload from the extension

Returns:

  • (Hash)

    recovery_outcome { kind, commit_sha?, summary? }



41
42
43
44
45
46
47
48
# File 'lib/rubyn_code/megaplan/ci_recovery.rb', line 41

def recover(context)
  validate!(context)
  prompt = build_prompt(context)
  result = @agent_invoker.call(prompt, context)
  interpret(result, context)
rescue StandardError => e
  { 'kind' => 'errored', 'summary' => e.message }
end