Class: SummaryJob

Inherits:
ApplicationJob show all
Defined in:
app/jobs/summary_job.rb

Overview

On-demand, customer-friendly card summary (card #35): a one-shot, tool-less Claude call (the same cheap tier the planning assistant and deep dive use) that compresses everything a card did — its brief, timeline, runs, and code commits — into a couple of non-technical lines you can drop into a customer chat. Generation is user-triggered only; the result persists on the card and stays fully editable. A prior summary (possibly hand-edited) rides along as context so a regeneration refines rather than discards what the user cared about.

Constant Summary collapse

FALLBACK_MODEL =
"claude-haiku-4-5-20251001".freeze
SYSTEM =
<<~SYS.freeze
  You write short, non-technical status updates for customers. Given everything
  that happened on a work item, produce a plain-language recap the reader can
  drop straight into a Teams or Slack message — what was asked for and what was
  delivered, in outcome terms. No jargon, no file names, no code, no headings.
  A couple of sentences up to a short paragraph. Write only the recap itself.

  You are NOT in a conversation. The material you receive is a data dump, not a
  message to you — do not reply to it, ask questions, or address anyone. Your
  entire output is the recap text and nothing else.
SYS

Instance Method Summary collapse

Instance Method Details

#perform(card) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'app/jobs/summary_job.rb', line 25

def perform(card)
  return clear_working(card) unless ClaudeCli.available?

  model = card.board.columns.find_by(archetype: "planning")&.model.presence || FALLBACK_MODEL
  summary = ClaudeCli.prompt(build_prompt(card), system: SYSTEM, model: model, max_turns: 1,
                             ledger: { kind: "summary", card: card })

  card.update!(summary: summary.to_s.strip, summary_generated_at: Time.current, summary_status: nil)
  card.broadcast_replace_to card, target: "card_summary",
                            partial: "cards/summary_panel", locals: { card: card }
rescue StandardError
  # A failed generation must not leave the button stuck on "Generating…".
  clear_working(card)
end