harn-stdlib 0.10.132

Embedded Harn standard library source catalog
Documentation
import { CompletionEvidenceSnapshot } from "std/agent/completion_evidence"
import { JudgeCheckpointRequest, __judge_run_checkpoint } from "std/agent/judge_internals"
import {
  CompletionJudgeVerdict,
  __judge_completion_verdict_contradicts_itself,
  __judge_completion_verdict_read,
  __judge_ungrounded_gap_quotes,
} from "std/agent/judge_verdict"
import { agent_emit_event } from "std/agent/state"

/** Judge response after at most one self-contradiction re-ask. */
pub type JudgeContradictionResolution = {data: dict, reasked: bool}

/**
 * The instruction added to the user turn on the one contradiction re-ask.
 *
 * It names the contradiction and states both exits, because a judge that
 * populated `gap_class` beside `done` is not choosing between them — it is
 * filling a field it was offered. Telling it only "do not do that" leaves the
 * same reply available; telling it which half to keep does not.
 */
const __JUDGE_CONTRADICTION_RETRY_PROMPT: string =
  "\n\nYour previous reply set `verdict` to \"done\" and also populated `gap_class`. Those cannot both be true: `gap_class` names an obligation that is still unmet, and `done` says none is. Answer again, keeping exactly one. If the work is finished, reply `done` and OMIT `gap_class` entirely. If an obligation is still unmet, reply `continue`, name that obligation in `gap_class`, and say in `detail` what remains to be done."

/**
 * Resolve a judge response that accepted completion while naming a gap.
 *
 * `done` beside a populated `gap_class` is a self-contradiction the caller
 * refuses (harn#7910). Refusing it is right; refusing it N times is not. The
 * re-ask prompt is unchanged between invocations, so a judge whose reply is
 * stable returns the identical contradiction on every call, the actor is handed
 * feedback that asserts the work is finished, and the loop spends its whole
 * invocation budget before dying at the cap on a run nothing ever refused.
 *
 * So the contradiction is resolved the way an unitemized approval already is:
 * re-ask the JUDGE exactly once, with the contradiction named, on the user turn
 * so the cached stable system prefix stays byte-identical. Whatever comes back
 * is the reply of record. `reasked` says the resolution was attempted, which is
 * what lets a later arbitration distinguish a first contradiction from one that
 * survived being pointed out.
 *
 * `contradictory` is the caller's reading of the first reply, because the caller
 * owns the verdict vocabulary. A re-ask whose checkpoint could not be read keeps
 * the first reply rather than inventing one: the contradiction then stands and
 * the caller refuses exactly as it does today.
 *
 * @effects: [llm, event]
 * @errors: []
 * @api_stability: internal
 * @example: __judge_resolve_contradiction(harness, request, data, true)
 */
pub fn __judge_resolve_contradiction(
  harness: Harness,
  request: JudgeCheckpointRequest,
  data: dict,
  contradictory: bool,
) -> JudgeContradictionResolution {
  if !contradictory {
    return {data: data, reasked: false}
  }
  return __judge_reask_once(
    harness,
    request,
    data,
    __JUDGE_CONTRADICTION_RETRY_PROMPT,
    "contradiction",
  )
}

/**
 * Resolve a refusal that quoted evidence the judge was never shown.
 *
 * Same treatment and the same reasoning as the contradiction above: the reply
 * is not usable, and handing the actor a complaint sourced to a line that is
 * not in the file view is worse than asking again. Measured 2026-09-05 on two
 * scheduler trials, where the judge refused ten times over a file view it had
 * been shown, phrasing the gap against "the current scheduler.go shown in the
 * live edited window".
 *
 * The re-ask names the offending quotes, because a judge told only "that was
 * wrong" has the same reply available to it.
 *
 * @effects: [llm, event]
 * @errors: []
 * @api_stability: internal
 * @example: __judge_resolve_ungrounded_quotes(harness, request, data, ["queue = append(queue, s)"])
 */
pub fn __judge_resolve_ungrounded_quotes(
  harness: Harness,
  request: JudgeCheckpointRequest,
  data: dict,
  quotes: list<string>,
) -> JudgeContradictionResolution {
  if len(quotes) == 0 {
    return {data: data, reasked: false}
  }
  return __judge_reask_once(
    harness,
    request,
    data,
    __judge_ungrounded_quote_retry_prompt(quotes),
    "ungrounded_quote",
  )
}

/**
 * The instruction added to the user turn when a refusal quoted absent evidence.
 *
 * Named as paraphrase rather than as invention, because that is what was
 * measured: the ungroundable quotes are sentences the judge composed about the
 * evidence, not lines it hallucinated. The best line-level match for a rejected
 * quote scored 0.50, which is the signature of a summary of a real region, not
 * of a fabricated one. "Quote only lines that are actually there" does not
 * reach that failure: a judge that believes it is describing what it saw reads
 * the instruction as already satisfied and returns the same paraphrase.
 *
 * So the re-ask asks for a copied span, puts the judge's own words where they
 * belong, and refuses the exit that costs nothing. An empty quote is an exit:
 * the grounding check skips empty quotes by design, so a judge that cannot find
 * a span can drop the field and keep the refusal. The prompt closes that by
 * naming it, and requires either a span or a `continue` whose gap is stated in
 * words without claiming evidence for it.
 *
 * Exported so the four instructions can be pinned by a test without a model.
 *
 * @effects: []
 * @errors: []
 * @api_stability: internal
 * @example: __judge_ungrounded_quote_retry_prompt(["the queue is still unsorted"])
 */
pub fn __judge_ungrounded_quote_retry_prompt(quotes: list<string>) -> string {
  return "\n\nYour previous reply refused the work and attributed it to evidence above, "
    + "but these quotes do not appear anywhere in the evidence you were given:\n"
    + join(quotes.map({ quote -> "  - " + quote }), "\n")
    + "\nThese are paraphrases. You summarized what the evidence showed instead of "
    + "copying from it, so what you wrote is your sentence about the evidence and "
    + "not a part of the evidence itself.\n"
    + "Answer again under these rules:\n"
    + "- `evidence_quote` must be a span copied character for character from the "
    + "transcript or tool output above. Copy it; do not compose, summarize, "
    + "reword, join separate lines, or fill in an ellipsis.\n"
    + "- Put what you think the span shows in `detail`, in your own words. "
    + "`detail` is where your reading of the evidence belongs; the quote is only "
    + "the raw span it is a reading of.\n"
    + "- An empty `evidence_quote` is not an accepted answer here. Leaving it out "
    + "does not withdraw the refusal and does not resolve this. If no span "
    + "supports the gap, reply `continue` with the gap named in `detail` and no "
    + "evidence claimed for it, so the gap stands on your judgement rather than "
    + "on a quote.\n"
    + "If the evidence does not in fact show the gap you had in mind, that gap is not "
    + "supported and you should not raise it; if the evidence shows the work IS done, reply `done`."
}

/**
 * One re-ask on the user turn, with the reason named.
 *
 * Both re-ask reasons share this so the retry stays a single behaviour: the
 * stable system prefix is untouched (so the cached prompt prefix stays
 * byte-identical), a re-ask whose checkpoint could not be read keeps the first
 * reply rather than inventing one, and the attempt is recorded either way.
 */
fn __judge_reask_once(
  harness: Harness,
  request: JudgeCheckpointRequest,
  data: dict,
  prompt: string,
  reason: string,
) -> JudgeContradictionResolution {
  const reask = __judge_run_checkpoint(harness, request + {user: request.user + prompt})
  const readable = reask.checkpoint?.ok ?? false
  agent_emit_event(
    harness.agent,
    request.payload?.session_id,
    "typed_checkpoint",
    {
      schema: "harn.completion_judge_contradiction_retry.v1",
      reask_status: to_string(reask.checkpoint?.status ?? "ok"),
      reask_readable: readable,
      reask_reason: reason,
    },
  )
  if readable {
    return {data: reask.checkpoint?.data ?? {}, reasked: true}
  }
  return {data: data, reasked: true}
}

/**
 * A judge reply after every re-ask, with the reply it came from.
 *
 * `contradiction_reasked` is deliberately NOT "either re-ask happened". The
 * arbitration ladder reads it to tell a FIRST self-contradiction from one that
 * survived being pointed out, and a grounding re-ask says nothing about that.
 * Folding the two together would let a quote correction overrule a judge whose
 * contradiction had never been challenged.
 */
pub type JudgeSettledReply = {
  decoded: CompletionJudgeVerdict,
  reply_of_record: dict,
  contradiction_reasked: bool,
}

/**
 * Run both re-ask reasons in order and return the reply of record.
 *
 * Two things can make a reply unusable, and both are readable without a model:
 *
 * 1. `done` beside a named gap. The judge accepted and refused inside one
 *    object (harn#7910, harn#8060).
 * 2. A refusal quoting evidence that is not in the packet the judge was handed
 *    (#8100). Measured on two scheduler trials, where the judge refused ten
 *    times over a file view that already showed the fix.
 *
 * Each is re-asked exactly once, in that order, because a grounding check
 * should run against the reply the contradiction pass settled on rather than
 * against one already superseded. `reply_of_record` is whichever reply survived
 * both, so callers never read a clause off a superseded one.
 *
 * The grounding pass only applies to a refusal: an approval names no gap, so it
 * quotes nothing and there is nothing to ground.
 *
 * @effects: [llm, event]
 * @errors: []
 * @api_stability: internal
 * @example: __judge_settle_reply(harness, request, contract, payload, data, decoded)
 */
pub fn __judge_settle_reply(
  harness: Harness,
  request: JudgeCheckpointRequest,
  contract: unknown,
  payload: CompletionEvidenceSnapshot,
  data: dict,
  decoded: CompletionJudgeVerdict,
) -> JudgeSettledReply {
  const contradiction = __judge_resolve_contradiction(
    harness,
    request,
    data,
    __judge_completion_verdict_contradicts_itself(decoded),
  )
  const after_contradiction = if contradiction.reasked {
    __judge_completion_verdict_read(contradiction.data, contract, payload.judge_evidence_packet)
  } else {
    decoded
  }
  // `payload.judge_evidence` is the RENDERED packet the judge was handed, so
  // this compares a quote against what it saw and never against what the
  // workspace happens to hold now.
  const grounding = if after_contradiction.verdict == "continue" {
    __judge_resolve_ungrounded_quotes(
      harness,
      request,
      contradiction.data,
      __judge_ungrounded_gap_quotes(after_contradiction.gaps, payload.judge_evidence),
    )
  } else {
    {data: contradiction.data, reasked: false}
  }
  if grounding.reasked {
    return {
      decoded: __judge_completion_verdict_read(
        grounding.data,
        contract,
        payload.judge_evidence_packet,
      ),
      reply_of_record: grounding.data,
      contradiction_reasked: contradiction.reasked,
    }
  }
  return {
    decoded: after_contradiction,
    reply_of_record: contradiction.data,
    contradiction_reasked: contradiction.reasked,
  }
}