/**
* Catalog-declared completion-review policy.
*
* Split out of `judge.harn`, which sits against the 1500-line source cap.
* These three are a self-contained unit: read the model's `completion_review`
* row, and decide whether a `light` row may skip the LLM confirmation. They
* touch no judge state, so the judge imports them rather than owning them.
*/
import { JudgeConfig } from "std/agent/options_types"
pub type CompletionReview = {scrutiny: string, max_judge_calls?: int, evidence?: unknown}
/** The completion-judge fields consumed when resolving its invocation cap. */
pub type CompletionReviewJudgePolicy = {max_judge_calls?: int}
type CompletionJudgeConfig = bool | JudgeConfig | nil
fn __agent_completion_review(llm: HarnessLlm, opts: dict) -> CompletionReview {
const model = trim(to_string(opts?.model ?? ""))
if model == "" {
return {scrutiny: "standard"}
}
const info = try {
llm.model_info(model)
}
if is_err(info) {
return {scrutiny: "standard"}
}
const review = unwrap(info)?.catalog?.completion_review
if type_of(review) != "dict" {
return {scrutiny: "standard"}
}
return {
scrutiny: to_string(review?.scrutiny ?? "standard"),
max_judge_calls: review?.max_judge_calls,
evidence: review?.evidence,
}
}
/**
* agent_completion_review.
*
* Catalog `completion_review` for the session model, or `{scrutiny: "standard"}`
* when the row omits it.
*
* @effects: []
* @errors: []
* @api_stability: experimental
* @example: agent_completion_review(harness.llm, opts)
*/
pub fn agent_completion_review(llm: HarnessLlm, opts: dict) -> CompletionReview {
return __agent_completion_review(llm, opts)
}
/**
* Whether light completion-review may skip the LLM confirmation.
*
* The catalog row must opt into `light`. The deterministic gate must already
* have passed, and the turn must carry a terminal sentinel. Absent any of
* those, the judge still runs.
*
* @effects: []
* @errors: []
* @api_stability: experimental
* @example: agent_completion_review_should_skip_llm(review, evaluation, payload)
*/
pub fn agent_completion_review_should_skip_llm(
review: CompletionReview,
evaluation: dict,
payload: dict,
) -> bool {
if review.scrutiny != "light" {
return false
}
if !(evaluation?.invoked?.deterministic ?? false) {
return false
}
if evaluation?.verdict?.vetoed ?? false {
return false
}
return to_string(payload?.stop_reason ?? "") == "sentinel"
}
// Conservative default cap on how many times the completion-judge LLM may
// veto a proposed completion within one session. Each veto is a paid model
// call plus an injected feedback message, so a weak model that never satisfies
// the judge can otherwise burn calls up to `max_verify_attempts` (default 20)
// with no structured signal. Callers raise it via
// `verify_completion_judge.max_invocations`, or disable the cap entirely with
// `0`.
pub const COMPLETION_JUDGE_DEFAULT_CAP = 5
fn __verify_completion_judge_cap(
judge_cfg: CompletionJudgeConfig,
review: CompletionReviewJudgePolicy = {},
) -> int? {
const configured = if type_of(judge_cfg) == "dict" {
judge_cfg?.max_invocations
} else {
nil
}
const catalog_cap = review.max_judge_calls
const cap = configured ?? catalog_cap ?? COMPLETION_JUDGE_DEFAULT_CAP
if cap <= 0 {
return nil
}
return cap
}
/**
* Resolve the optional top-level cap for `done_judge`. Unlike
* `done_judge.cadence.max_invocations`, this is a terminal veto-loop cap: the
* judge may fire up to the cap, then the loop finalizes instead of silently
* continuing until the iteration budget expires.
*/
fn __done_judge_cap(judge_cfg: CompletionJudgeConfig) -> int? {
if type_of(judge_cfg) != "dict" {
return nil
}
const cap = judge_cfg?.max_invocations
if cap == nil || cap <= 0 {
return nil
}
return cap
}
/**
* agent_done_judge_cap.
*
* Resolved terminal veto cap for a `done_judge` config. Returns nil when the
* cap is not configured or is disabled with 0.
*
* @effects: []
* @errors: []
* @api_stability: experimental
* @example: agent_done_judge_cap(opts?.done_judge)
*/
pub fn agent_done_judge_cap(judge_cfg: CompletionJudgeConfig) -> int? {
return __done_judge_cap(judge_cfg)
}
/**
* agent_verify_completion_judge_cap.
*
* Resolved completion-judge veto cap for a `verify_completion_judge` config,
* for surfacing in run records. Returns nil when the cap is disabled.
*
* @effects: []
* @errors: []
* @api_stability: experimental
* An explicit `max_invocations` wins. Otherwise the catalog
* `completion_review.max_judge_calls` applies, then the default of 5.
*
* @example: agent_verify_completion_judge_cap(opts?.verify_completion_judge, review)
*/
pub fn agent_verify_completion_judge_cap(
judge_cfg: CompletionJudgeConfig,
review: CompletionReviewJudgePolicy = {},
) -> int? {
return __verify_completion_judge_cap(judge_cfg, review)
}