# frozen_string_literal: true require_relative "../context_maintainer" require "json" $pass = 0; $fail = 0 def ok(d); $pass += 1; puts " ok #{d}"; end def bad(d, g = nil); $fail += 1; puts " FAIL #{d}#{g.nil? ? '' : " (#{g.inspect})"}"; end def eq(a, b, d); a == b ? ok(d) : bad(d, a); end def truthy(x, d); x ? ok(d) : bad(d, x); end def env(summary:, other:) JSON.generate("choices" => [{ "message" => { "content" => JSON.generate("summary" => summary, "other_context" => other) } }], "usage" => { "cost" => 0.001 }) end puts "maintainer: builds {summary, other_context}" m = Helpdesk::ContextMaintainer.new(api_key: "x", transport: ->(_u, _h, _b) { [200, env(summary: "Souhrn.", other: ["A", "B"])] }) r = m.build(mode: :incremental, old_ai_context: { "summary" => "", "other_context" => [] }, digests: ["digest"], ledger: []) truthy(r[:ok], "ok") eq(r[:ai_context]["summary"], "Souhrn.", "summary rendered") eq(r[:ai_context]["other_context"], ["A", "B"], "other_context rendered") puts "maintainer: pinned section forced verbatim + flags divergence" r2 = m.build(mode: :incremental, old_ai_context: { "summary" => "PIN", "other_context" => [] }, pinned_sections: { "summary" => "PIN" }, digests: ["d"]) eq(r2[:ai_context]["summary"], "PIN", "pinned summary is the operator text, not the LLM's") truthy(r2[:needs_review], "LLM diverged from the pin -> needs_review") puts "maintainer: model selection per mode" seen = [] m2 = Helpdesk::ContextMaintainer.new(api_key: "x", transport: ->(_u, _h, b) { seen << JSON.parse(b)["model"]; [200, env(summary: "s", other: [])] }) m2.build(mode: :incremental, old_ai_context: {}, digests: []) m2.build(mode: :rebuild, old_ai_context: {}, digests: []) eq(seen[0], "google/gemini-3.6-flash", "incremental uses the configured model") eq(seen[1], "google/gemini-3.6-flash", "rebuild uses the configured model") puts "maintainer: no key -> graceful no-op" truthy(Helpdesk::ContextMaintainer.new(api_key: "").respond_to?(:build), "constructs without a key") r3 = Helpdesk::ContextMaintainer.new(api_key: "").build(mode: :incremental, old_ai_context: {}) truthy(!r3[:ok], "no key + no transport -> ok:false (no crash)") puts "\n#{$pass} passed, #{$fail} failed"; exit($fail.zero? ? 0 : 1)