Class: Insika::Commands::RunRefinement

Inherits:
Object
  • Object
show all
Defined in:
lib/insika/commands/run_refinement.rb

Overview

Control command: reads a window of the agent's real traffic and records a ranked failure REPORT. Synchronous — it only scans durable stores (no provider call, no fiber), so it answers with the Run and does not create a Task. It is the ONLY way a refinement run starts: the CLI, the Studio button and any external cron all dispatch this one command (there is no scheduler in the engine).

Payload:

agent          (required) agent id
since          ISO8601 — only turns from this instant on
last_sessions  Integer — the N most recent conversations instead
full           truthy — ignore the previous run and use the full window
max_findings   Integer cap on the report
exclude_sessions [prefix] — session ids to drop (load tests, debug traffic)

Window resolution (first that applies): explicit payload -> INCREMENTAL (since the previous run for this agent, unless full) -> the agent's configured refinement.window -> the collector's default.

writes NOTHING to the agent, so it needs no opt-in: an absent refinement config reads as report-only. Only propose/auto_apply require the operator to enable them explicitly.

Constant Summary collapse

READ_ONLY_MODES =
%w[report propose auto_apply].freeze

Instance Method Summary collapse

Constructor Details

#initialize(profiles:, refinement_store:, collector:, event_stream:) ⇒ RunRefinement

Returns a new instance of RunRefinement.



32
33
34
35
36
37
# File 'lib/insika/commands/run_refinement.rb', line 32

def initialize(profiles:, refinement_store:, collector:, event_stream:)
  @profiles = ProfileSource.coerce(profiles)
  @refinement_store = refinement_store
  @collector = collector
  @event_stream = event_stream
end

Instance Method Details

#call(command) ⇒ Object



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
# File 'lib/insika/commands/run_refinement.rb', line 39

def call(command)
  p = AgentPayload.symbolize(command.payload)
  agent = AgentPayload.presence(p[:agent])
  raise Insika::ValidationError, "agent is required" if agent.nil?

  profile = @profiles[agent] ||
            (raise Insika::NotFoundError, "agent '#{agent}' not configured")
  config = refinement_config(profile)
  validate_mode!(config)

  window = resolve_window(agent, p, config)
  run = @refinement_store.create(agent_id: agent, window: window)
  emit(:refinement_started, agent: agent, run_id: run.id, window: window)

  begin
    report = @collector.collect(
      agent_id: agent, max_findings: max_findings(p, config),
      exclude_sessions: exclude_sessions(p, config), **collect_args(window)
    )
    done = @refinement_store.complete(run.id, findings: report.findings,
                                      excluded: report.excluded)
    emit(:refinement_report, agent: agent, run_id: run.id, status: done.status,
                             findings: done.findings_count,
                             sessions: report.sessions_seen, turns: report.turns_seen,
                             excluded: report.excluded)
    done
  rescue StandardError => e
    @refinement_store.fail(run.id, error: e.message)
    raise
  end
end