Files
gstack/lib/eval-model.ts
T
Garry TanandClaude Fable 5 b9cd094981 fix: housekeeping sweep — telemetry integrity, persistent opt-out, context-bill accuracy, setup hang, dev-server discovery, model resolution (#2136 + v1.63 polish)
Seven small fixes, one theme (claims matching code):
- telemetry-sync strips local-only fields with jq del() (structural) instead
  of quote-fragile sed regexes; unparseable lines are dropped, never
  forwarded unstripped. Sed survives only as a jq-less fallback.
- telemetry-log rejects non-integer durations BEFORE the range caps, whose
  test(1) comparisons silently no-op on non-numerics — a malformed duration
  spliced raw text into the JSONL stream.
- browse's local telemetry honors the persistent tier (config.yaml
  telemetry: off), not just the preamble's env hint — direct $B use and
  embedders now respect the opt-out.
- gstack-context-bill --exact sees GSTACK_-promoted keys inside Conductor
  (conductor-env-shim wired at the CLI entry), and the TOTAL line no longer
  double-counts every nested skill through the root skill's walk (v1.63
  deferred polish; the telemetry-sync HTTP-status outcome deferred alongside
  it turned out already shipped).
- setup's Chromium probe is deadline-bounded (90s, background + poll-kill —
  macOS has no GNU timeout) and prefers Node for the launch probe everywhere
  (the bun --eval hang family behind #2136); the install is single-flight
  behind a lock dir with an actionable stale-lock message. Probe verified
  live on this Mac.
- the review resolver's dev-server check reads CLAUDE.md and the plan file
  before falling back to an expanded port probe, and says how to make
  itself smarter next time.
- eval/harness model IDs resolve through lib/eval-model.ts
  (GSTACK_EVAL_MODEL[_KIND] env overrides, per-kind defaults, tested) at the
  SDK-capture and PTY-warmup sites; the bash-embedded distill snippet
  mirrors the resolution inline.
- memory-ingest's silent-zero shape (staged>0, imported+unchanged==0,
  errors==0) warns even under --quiet — a run that indexes nothing must
  never look healthy again.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-14 13:26:58 -07:00

41 lines
1.6 KiB
TypeScript

/**
* Host-neutral eval/harness model resolution (fork port wave 2, G cluster).
*
* Model IDs were hardcoded at six call sites across the eval helpers and the
* distill bin, so an environment that pins a different model (CI cost
* control, a model migration, an air-gapped proxy alias) had to patch source.
* One resolution point, env-overridable:
*
* GSTACK_EVAL_MODEL_<KIND> (e.g. GSTACK_EVAL_MODEL_WARMUP) — per-kind
* GSTACK_EVAL_MODEL — global
* explicit argument — caller wins
* per-kind default — last resort
*
* Kinds and their defaults:
* capture — AskUserQuestion SDK capture runs (quality matters): opus
* warmup — PTY warm-up ping (cheapest thing that answers): haiku
* distill — free-text distillation (cheap, structured): haiku (pinned)
*/
const DEFAULTS: Record<string, string> = {
capture: "claude-opus-4-7",
warmup: "claude-haiku-4-5",
distill: "claude-haiku-4-5-20251001",
};
export type EvalModelKind = keyof typeof DEFAULTS & string;
export function resolveEvalModel(
kind: EvalModelKind,
explicit?: string | null,
env: NodeJS.ProcessEnv = process.env,
): string {
if (explicit) return explicit;
const perKind = env[`GSTACK_EVAL_MODEL_${kind.toUpperCase()}`];
if (perKind) return perKind;
if (env.GSTACK_EVAL_MODEL) return env.GSTACK_EVAL_MODEL;
const fallback = DEFAULTS[kind];
if (!fallback) throw new Error(`resolveEvalModel: unknown kind "${kind}"`);
return fallback;
}