Class: RailVerdict::MCP::Tools::CreateHandoff

Inherits:
Object
  • Object
show all
Defined in:
lib/rail_verdict/mcp/tools/create_handoff.rb

Instance Method Summary collapse

Constructor Details

#initialize(server:) ⇒ CreateHandoff

Returns a new instance of CreateHandoff.



7
8
9
# File 'lib/rail_verdict/mcp/tools/create_handoff.rb', line 7

def initialize(server:)
  @server = server
end

Instance Method Details

#call(changed: nil, base: nil, config_path: nil, baseline_path: nil, waiver_path: nil, **_rest) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/rail_verdict/mcp/tools/create_handoff.rb', line 53

def call(changed: nil, base: nil, config_path: nil, baseline_path: nil, waiver_path: nil, **_rest)
  changed = changed == true
  base_validated = Validators.validate_base_revision(base)
  return Serializers.error_response("--base requires --changed", code: "invalid_arguments") if base_validated && !changed

  config_file = resolve_config_path(config_path)
  outcome = @server.synchronized_verification { run_check(changed: changed, base: base_validated, config_path: config_file, baseline_path: baseline_path, waiver_path: waiver_path) }
  receipt = Receipt.build(outcome: outcome)
  evidence_set = {
    "analyzer_results" => outcome.result.analyzer_results.map do |ar|
      h = { "analyzer" => ar.analyzer, "execution_status" => ar.execution_status, "tool_version" => ar.tool_version }
      findings = outcome.findings.select { |f| f.analyzer == ar.analyzer }.map(&:to_schema_h).sort_by { |ff| ff["fingerprint"] }
      h["findings"] = findings if findings.any?
      h
    end
  }
  provenance = { "analyzer_versions" => outcome.context&.analyzer_versions || {} }
  scope = { "verification_mode" => outcome.result.git ? "changed" : "full", "changed_base" => outcome.result.git && outcome.result.git["base"], "changed_merge_base" => outcome.result.git && outcome.result.git["merge_base"] }
  handoff = Handoff.build(receipt: receipt, evidence_set: evidence_set, evidence_provenance: provenance, source_scope: scope)
  @server.cache.store_handoff(handoff) if @server.cache.respond_to?(:store_handoff)
  Serializers.tool_response({ "handoff" => Serializers.scrub(handoff), "receipt" => Serializers.scrub(receipt), "handoff_id" => handoff["handoff_id"] }, error: false)
rescue Handoff::BuildError, Receipt::BuildError => e
  Serializers.error_response("#{e.code}: #{e.message}", code: e.code)
rescue ArgumentError => e
  Serializers.error_response(e.message, code: "invalid_arguments")
rescue StandardError => e
  Serializers.error_response("create_handoff failed: #{e.message}", code: "internal_error")
end

#tool_annotationsObject



49
50
51
# File 'lib/rail_verdict/mcp/tools/create_handoff.rb', line 49

def tool_annotations
  { read_only_hint: true, destructive_hint: false, idempotent_hint: true, open_world_hint: false, title: tool_title }
end

#tool_descriptionObject



19
20
21
# File 'lib/rail_verdict/mcp/tools/create_handoff.rb', line 19

def tool_description
  "Create a deterministic Verification Handoff (bounded transport envelope) from a fresh verification. Runs verification, builds receipt and handoff. Offline, file/process usable, fail-closed. Handoff never self-authorizes reuse."
end

#tool_input_schemaObject



23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/rail_verdict/mcp/tools/create_handoff.rb', line 23

def tool_input_schema
  {
    type: "object",
    properties: {
      changed: { type: "boolean" },
      base: { type: "string" },
      config_path: { type: "string" },
      baseline_path: { type: "string" },
      waiver_path: { type: "string" }
    },
    additionalProperties: false
  }
end

#tool_nameObject



11
12
13
# File 'lib/rail_verdict/mcp/tools/create_handoff.rb', line 11

def tool_name
  "create_handoff"
end

#tool_output_schemaObject



37
38
39
40
41
42
43
44
45
46
47
# File 'lib/rail_verdict/mcp/tools/create_handoff.rb', line 37

def tool_output_schema
  {
    type: "object",
    properties: {
      handoff: { type: "object" },
      receipt: { type: "object" },
      handoff_id: { type: "string" }
    },
    required: %w[handoff]
  }
end

#tool_titleObject



15
16
17
# File 'lib/rail_verdict/mcp/tools/create_handoff.rb', line 15

def tool_title
  "Create verification handoff"
end