harn-stdlib 0.10.126

Embedded Harn standard library source catalog
Documentation
import { agent_loop_call_reserve, agent_loop_remaining_calls } from "std/agent/control"
import { __inject_feedback_with_tool_repair } from "std/agent/loop_tool_calls"
import { __agent_loop_max_consecutive_recoveries } from "std/agent/loop_turn_scope"
import { agent_emit_event } from "std/agent/state"

/**
 * The three terminal grant allowances, and how many of each this run has left.
 *
 * A "grant" is permission to run one iteration PAST `current_max`. Nothing is
 * withheld from working spend — the loop never shrinks its own budget — so read
 * every number here as "extra iterations this run can still obtain", not as
 * calls held in reserve. The three buckets:
 *
 * - `verification`: a failed terminal verify may re-open the loop, funded from
 *   `stall_config`'s `reserved_terminal_verify_iterations`.
 * - `recovery`: bounded thrash rescues, funded from #7682's bound.
 * - `terminal_report`: the one-shot terminal callback continue.
 *
 * ONE owner. Before this each bucket carried its own counter in a different
 * module, and the projection kept a fourth number describing them from the
 * outside, which is how the reported reserve drifted from what the loop would
 * actually allow.
 *
 * `terminal_report` is 1 whenever a terminal callback is possible, NOT
 * `final_wrapup ? 1 : 0`. The guard that governs it (`loop_terminal.harn`)
 * tests only that no continue has been spent yet, so 1 is the effective
 * allowance and the earlier `final_wrapup` condition mis-reported runs that had
 * wrap-up disabled.
 *
 * @effects: []
 * @errors: []
 */
pub fn __agent_loop_call_budget_new(opts: any, reserve_cfg: dict?) -> dict {
  const verification = if (reserve_cfg?.reserved_terminal_verify ?? false)
    || (reserve_cfg?.zero_write_terminal_verify ?? false) {
    to_int(reserve_cfg?.reserved_terminal_verify_iterations ?? 0) ?? 0
  } else {
    0
  }
  const allowance = agent_loop_call_reserve(
    {
      verification: verification,
      // The recovery allowance has ONE owner (#7682). A literal here would be a
      // second constant that silently drifts from the bound the recovery ladder
      // actually enforces.
      recovery: __agent_loop_max_consecutive_recoveries(),
      terminal_report: 1,
    },
  )
  return {
    reserve: allowance,
    remaining: {
      verification: allowance.verification,
      recovery: allowance.recovery,
      terminal_report: allowance.terminal_report,
    },
    signal: opts?.call_budget_reserve_signal ?? false,
    signalled: false,
    iteration: 0,
    max: nil,
  }
}

/**
 * How many grants this bucket has left.
 *
 * Unknown bucket names return 0 rather than nil: a caller that misspells a
 * bucket gets "no grants available", which fails closed instead of handing out
 * an unbounded one.
 *
 * @effects: []
 * @errors: []
 */
pub fn __agent_loop_grants_remaining(state: dict?, bucket: string) -> int {
  const remaining = state?.remaining
  if bucket == "verification" {
    return to_int(remaining?.verification ?? 0) ?? 0
  }
  if bucket == "recovery" {
    return to_int(remaining?.recovery ?? 0) ?? 0
  }
  if bucket == "terminal_report" {
    return to_int(remaining?.terminal_report ?? 0) ?? 0
  }
  return 0
}

/**
 * May this bucket grant another iteration past the cap?
 *
 * @effects: []
 * @errors: []
 */
pub fn __agent_loop_grant_allowed(state: dict?, bucket: string) -> bool {
  return __agent_loop_grants_remaining(state, bucket) > 0
}

/**
 * Record that a bucket spent one grant.
 *
 * Spending an exhausted bucket is a no-op rather than a negative count, so a
 * caller that records without asking cannot manufacture budget.
 *
 * @effects: []
 * @errors: []
 */
pub fn __agent_loop_record_grant(state: dict, bucket: string) -> dict {
  if !__agent_loop_grant_allowed(state, bucket) {
    return state
  }
  const remaining = state.remaining
  if bucket == "verification" {
    return state + {remaining: remaining + {verification: remaining.verification - 1}}
  }
  if bucket == "recovery" {
    return state + {remaining: remaining + {recovery: remaining.recovery - 1}}
  }
  return state + {remaining: remaining + {terminal_report: remaining.terminal_report - 1}}
}

/**
 * Project the remaining call budget BEFORE the turn spends anything, so a
 * shortfall is visible while the agent can still act on it instead of being
 * discovered in the terminal region.
 *
 * This measures and warns. The emitted `reserve` is the grant allowance this
 * run started with, and a reader of
 * `harn.agent_loop_call_budget_projection.v1` should treat `reserve` and
 * `reserve_shortfall` as a forecast about whether the remaining budget can
 * cover the terminal work.
 *
 * `state` carries the run's allowances and latch plus this turn's `iteration`
 * and `max`, so the loop hands over one value instead of threading four.
 *
 * @effects: [agent]
 * @errors: []
 */
pub fn __agent_loop_project_call_budget(harness: Harness, session: dict, state: dict) -> dict {
  const reserve = state.reserve
  const current_max = state.max
  const remaining_calls = agent_loop_remaining_calls(current_max, state.iteration)
  // Only a run that HAD headroom can lose it. When the whole cap is no larger
  // than the reserve, the shortfall is true from turn zero and carries no
  // information, so signalling it would spend the agent's context to tell it
  // something it could not have acted on.
  const reserve_shortfall = remaining_calls != nil
    && current_max > reserve.total
    && remaining_calls <= reserve.total
    && !state.signalled
  agent_emit_event(
    harness.agent,
    session.session_id,
    "typed_checkpoint",
    {
      schema: "harn.agent_loop_call_budget_projection.v1",
      kind: "call_budget_projection",
      receipt_kind: "call_budget_projection",
      iteration: state.iteration,
      remaining: remaining_calls,
      // `measured` keeps an unavailable measurement distinguishable from a
      // measured zero for every reader of this receipt.
      measured: remaining_calls != nil,
      max_iterations: current_max,
      reserve: reserve,
      grants_remaining: state.remaining,
      reserve_shortfall: reserve_shortfall,
    },
  )
  if reserve_shortfall && state.signal {
    __inject_feedback_with_tool_repair(
      harness.agent,
      session.session_id,
      "call_budget_reserve",
      "Remaining model calls ("
        + to_string(remaining_calls)
        + ") no longer cover the "
        + to_string(reserve.total)
        + " calls reserved for verification, recovery, and terminal reporting. "
        + "Finish and report what you have now rather than starting new work.",
    )
  }
  return state + {signalled: state.signalled || reserve_shortfall}
}