mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-09 14:38:59 +02:00
The workspace-revert incident that hit CHANGELOG/TODOS mid-ship also
caught free-tests.yml between edits: commit 8d6c2ff8's message claims
PR-number concurrency + artifact upload + main-push runs, but only the
push trigger survived to the commit (caught by the /document-release
doc-vs-code audit). Both re-applied. Also: eval-model.ts header said
capture defaults to Opus (it's Sonnet per D1a), paid-shards' header
pinned a stale 44/63 shard census, and two CHANGELOG phrases
over-claimed ('six' -> 'up to six' shard processes; retry-1 scoped to
retry-bearing paid paths).
48 lines
2.0 KiB
TypeScript
48 lines
2.0 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: sonnet (D1a)
|
|
* warmup — PTY warm-up ping (cheapest thing that answers): haiku
|
|
* distill — free-text distillation (cheap, structured): haiku (pinned)
|
|
*/
|
|
|
|
// `as const satisfies` keeps EvalModelKind the literal union
|
|
// 'capture' | 'warmup' | 'distill' — a `Record<string, string>` annotation
|
|
// would widen it to string and let any typo through the type gate.
|
|
const DEFAULTS = {
|
|
// D1a (2026-08 test-infra review): capture runs default to Sonnet, matching
|
|
// session-runner — the old Opus default was an inconsistency between
|
|
// runners, not a choice; tests needing Opus pass it explicitly or set
|
|
// GSTACK_EVAL_MODEL_CAPTURE.
|
|
capture: "claude-sonnet-4-6",
|
|
warmup: "claude-haiku-4-5",
|
|
distill: "claude-haiku-4-5-20251001",
|
|
} as const satisfies Record<string, string>;
|
|
|
|
export type EvalModelKind = keyof typeof DEFAULTS;
|
|
|
|
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;
|
|
}
|