Class: Insika::Commands::ResolveRefinement

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

Overview

Control command: the human's answer to a gated proposal.

approve -> each edit is written through `AgentFileStore#write`, which pushes
         the previous content into `history`. Rollback is therefore already
         built: `restore_agent_file` with index 0, the same button the file
         editor has had since the Studio existed.
reject  -> recorded on the run with the operator's note. The finding must
         re-surface with new evidence before anything is proposed again;
         nothing retries on its own.

Payload { run_id:, decision: "approved"|"rejected", operator?, note? }. -> the resolved Run.

The candidate is re-validated against the CURRENT files before anything is written. The gate scored a snapshot; an operator approves minutes or days later, and in between a human may have edited the same file in the Studio. Applying an edit whose before no longer matches would silently overwrite that person's work — the exact failure the anchored format exists to prevent, thrown away at the last step. A stale approval is refused and the operator re-gates.

Instance Method Summary collapse

Constructor Details

#initialize(profiles:, refinement_store:, agent_file_store:, event_stream:) ⇒ ResolveRefinement

Returns a new instance of ResolveRefinement.



27
28
29
30
31
32
# File 'lib/insika/commands/resolve_refinement.rb', line 27

def initialize(profiles:, refinement_store:, agent_file_store:, event_stream:)
  @profiles = ProfileSource.coerce(profiles)
  @runs = refinement_store
  @agent_files = agent_file_store
  @event_stream = event_stream
end

Instance Method Details

#call(command) ⇒ Object



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/insika/commands/resolve_refinement.rb', line 34

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

  run = @runs.find(run_id) || (raise Insika::NotFoundError, "refinement run not found: #{run_id}")
  operator = p[:operator] || command.meta[:operator]

  case decision
  when "rejected"
    resolved = @runs.resolve(run.id, decision: :rejected, operator: operator, note: p[:note])
    emit(:refinement_rejected, resolved, files: [])
    resolved
  when "approved"
    apply(run, operator: operator, note: p[:note])
  else
    raise Insika::ValidationError, "invalid decision: #{decision} (approved|rejected)"
  end
end