mirror of
https://github.com/J3vb/OwnCord.git
synced 2026-09-03 03:50:00 +03:00
fix(bughunt): opus verifiers, args-armed budget, and single-finder floor retune (#1365)
First-live-run fallout (2026-08-13, base 34f2e41):
- Verify moves fable -> opus. An Anthropic outage (Mythos/Fable/Sonnet
elevated errors) mass-nulled the fable verify agents mid-run; opus
verifiers then carried the whole 8-round hunt with 0 nulls / 0 unverified.
- args.budgetTotal fallback. The +25M turn directive left budget.total null
in every probe this session, silently disarming the cost ceiling. The
ceiling now arms from args.budgetTotal when the directive doesn't, computed
from budget.spent(); budget.remaining() stays authoritative when it does.
- ROUND_BUDGET_FLOOR 2M -> 600k. The 2M value was a dual-finder-era anchor
(~2.6M/round); the single opus finder costs ~100-260k/round, so 2M would
zero-out any hunt launched with a budget under 2M - a foot-gun now that
budgetTotal is a first-class arg.
Harness: +s8c (args-armed ceiling announces budget=10M and floor-stops);
s8b/s9 retuned to the 600k floor. 33/33 offline scenarios pass.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -446,11 +446,25 @@ scenarios.s8_budget_floor = async () => {
|
||||
assert.match(result.report, /budget/i)
|
||||
}
|
||||
|
||||
// S8c: budget.total null (directive failed to arm) but args.budgetTotal supplied ->
|
||||
// ceiling armed from args, announced in the config log, computed from spent().
|
||||
scenarios.s8c_budget_args_fallback = async () => {
|
||||
const { result, logs } = await run({
|
||||
args: { budgetTotal: 10000000 },
|
||||
budget: { total: null, spent: () => 9500000, remaining: () => Infinity },
|
||||
agentStub: makeStub({ hunt: () => none, verify: (r, k, c) => confirmAll(c) }),
|
||||
})
|
||||
assert.equal(result.rounds.length, 0)
|
||||
assert.equal(result.stoppedOnBudget, true)
|
||||
assert.ok(logs.some((l) => /budget=10M/.test(l)), 'args-armed ceiling must announce 10M, not NONE')
|
||||
assert.equal(result.runStats.config.budgetTotal, 10000000)
|
||||
}
|
||||
|
||||
// S8b: budget runs low mid-hunt -> finishes the round it started, stops before the next.
|
||||
scenarios.s8b_budget_midrun = async () => {
|
||||
let n = 0
|
||||
const { result } = await run({
|
||||
budget: { total: 10000000, spent: () => 0, remaining: () => (n++ === 0 ? 3000000 : 1000000) },
|
||||
budget: { total: 10000000, spent: () => 0, remaining: () => (n++ === 0 ? 3000000 : 400000) },
|
||||
agentStub: makeStub({
|
||||
hunt: (round, key, model) =>
|
||||
round === 1 && key === 'ws-hub' && model === 'opus' ? { findings: [finding(1)] } : none,
|
||||
@@ -731,13 +745,14 @@ scenarios.s_targeted_retry = async () => {
|
||||
}
|
||||
|
||||
// New (spec Testing #9): the retuned floor must stop a run the old 150k floor let through.
|
||||
// 1M remaining is under the ~2M measured per-round cost - starting a round would overshoot.
|
||||
// A single opus finder round costs ~100-260k (2026-08-13 run); 400k remaining is under the
|
||||
// 600k floor, so starting another round could overshoot the ceiling - stop instead.
|
||||
scenarios.s9_budget_ceiling_retuned = async () => {
|
||||
const { result, logs } = await run({
|
||||
budget: { total: 10000000, spent: () => 9000000, remaining: () => 1000000 },
|
||||
budget: { total: 10000000, spent: () => 9600000, remaining: () => 400000 },
|
||||
agentStub: makeStub({ hunt: () => none, verify: (r, k, c) => confirmAll(c) }),
|
||||
})
|
||||
assert.equal(result.rounds.length, 0, '1M remaining must not start a ~2M round')
|
||||
assert.equal(result.rounds.length, 0, '400k remaining must not start a round under the 600k floor')
|
||||
assert.equal(result.stoppedOnBudget, true)
|
||||
assert.ok(logs.some((l) => /Budget floor/.test(l)))
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
export const meta = {
|
||||
name: 'bughunt',
|
||||
description: 'Converging multi-round bug hunt: rotating lens families, single opus finder, fable refute-by-default verification, dry-threshold stop',
|
||||
description: 'Converging multi-round bug hunt: rotating lens families, single opus finder, opus refute-by-default verification, dry-threshold stop',
|
||||
whenToUse: 'Hunting real bugs across the Go server, Tauri Rust backend, and TS client until consecutive rounds go dry. Not a security-only scan.',
|
||||
phases: [
|
||||
{ title: 'Recon', detail: 'haiku: churn + concurrency-surface inventory' },
|
||||
@@ -20,13 +20,21 @@ const DRY_THRESHOLD = ARGS.dryThreshold || 2
|
||||
// A scoped hunt (args.lenses) replaces the round-1 family outright; later rounds still go
|
||||
// adaptive, so hotspot and explore coverage - and therefore convergence - still work.
|
||||
const CUSTOM_LENSES = Array.isArray(ARGS.lenses) && ARGS.lenses.length ? ARGS.lenses : null
|
||||
// Floor for one round, tuned from the 2026-08-12 run: ~2.6M output tokens per round measured.
|
||||
// The old 150k floor would overshoot the ceiling by nearly a full round.
|
||||
const ROUND_BUDGET_FLOOR = 2000000
|
||||
// Floor for one round. The single opus finder (sonnet retired 2026-08-12) costs ~100-260k per
|
||||
// round, measured across the 8-round 2026-08-13 run. The old 2M floor was a dual-finder-era
|
||||
// anchor (~2.6M/round) that would zero-out any hunt launched with a budget under 2M - now that
|
||||
// budgetTotal is a first-class arg, that cliff is a foot-gun. 600k is ~3x a measured round.
|
||||
const ROUND_BUDGET_FLOOR = 600000
|
||||
// The turn directive failed to arm budget.total on the 2026-08-13 live run (+25M present,
|
||||
// total still null), so args.budgetTotal is the deterministic fallback. budget.spent()
|
||||
// works even when total is null; budget.remaining() stays authoritative when the
|
||||
// directive DID arm, because stubs (and the runtime) may track it statefully.
|
||||
const BUDGET_TOTAL = budget.total || Number(ARGS.budgetTotal) || null
|
||||
const remainingBudget = () => (budget.total ? budget.remaining() : BUDGET_TOTAL ? Math.max(0, BUDGET_TOTAL - budget.spent()) : Infinity)
|
||||
// The args channel has already been observed delivering something the script
|
||||
// could not read; an unnoticed fallback here is an 8x cost surprise, so say out
|
||||
// loud what the run is actually going to do.
|
||||
log(`config: maxRounds=${MAX_ROUNDS} dryThreshold=${DRY_THRESHOLD}${CUSTOM_LENSES ? ` lenses=custom(${CUSTOM_LENSES.length})` : ''} budget=${budget.total ? Math.round(budget.total / 1e6) + 'M' : 'NONE - cost ceiling disarmed'}`)
|
||||
log(`config: maxRounds=${MAX_ROUNDS} dryThreshold=${DRY_THRESHOLD}${CUSTOM_LENSES ? ` lenses=custom(${CUSTOM_LENSES.length})` : ''} budget=${BUDGET_TOTAL ? Math.round(BUDGET_TOTAL / 1e6) + 'M' : 'NONE - cost ceiling disarmed'}`)
|
||||
|
||||
// ---------- schemas: copied VERBATIM from the current bughunt.js ----------
|
||||
const FINDINGS = {
|
||||
@@ -516,9 +524,9 @@ function verifyPrompt(lensKey, candidates) {
|
||||
}
|
||||
|
||||
while (dry < DRY_THRESHOLD && round < MAX_ROUNDS) {
|
||||
if (budget.total && budget.remaining() < ROUND_BUDGET_FLOOR) {
|
||||
if (BUDGET_TOTAL && remainingBudget() < ROUND_BUDGET_FLOOR) {
|
||||
stoppedOnBudget = true
|
||||
log(`Budget floor reached (${Math.round(budget.remaining() / 1000)}k left) - stopping before round ${round + 1}`)
|
||||
log(`Budget floor reached (${Math.round(remainingBudget() / 1000)}k left) - stopping before round ${round + 1}`)
|
||||
break
|
||||
}
|
||||
const family = lensesForRound(round + 1)
|
||||
@@ -552,7 +560,9 @@ while (dry < DRY_THRESHOLD && round < MAX_ROUNDS) {
|
||||
const fresh = dedupe(union, seenAtStart, counts)
|
||||
if (!fresh.length) return { lens, finderFailed, unionCount: union.length, fresh: [], matched: [], unmatched: [] }
|
||||
log(`r${rnd} ${lens.key}: ${fresh.length} fresh candidate(s) -> verification`)
|
||||
const vopts = { phase: `Round ${rnd}`, model: 'fable', effort: 'high', schema: VERDICTS }
|
||||
// opus, not fable: fable verify agents hit usage limits and nulled out en masse on
|
||||
// the 2026-08-13 live run (and were the dominant cost even when they worked)
|
||||
const vopts = { phase: `Round ${rnd}`, model: 'opus', effort: 'high', schema: VERDICTS }
|
||||
// Pair verdicts to candidates as they arrive, then retry ONLY what got no usable verdict.
|
||||
// Retrying the whole batch re-burned every verdict on a partial return, and the old
|
||||
// count-based trigger let N unmatched garbage verdicts skip the retry entirely.
|
||||
@@ -657,7 +667,7 @@ const unverifiedFinal = unverified.filter((u) => !seen.some((p) => isDup(u, p)))
|
||||
const table = convergenceTable(roundStats, converged, stoppedOnBudget)
|
||||
const sum = (k) => roundStats.reduce((n, r) => n + (r[k] || 0), 0)
|
||||
const runStats = {
|
||||
config: { maxRounds: MAX_ROUNDS, dryThreshold: DRY_THRESHOLD, customLenses: !!CUSTOM_LENSES, knownCount: (ARGS.known || []).length, graphRows: GRAPH_ROWS.length, budgetTotal: budget.total },
|
||||
config: { maxRounds: MAX_ROUNDS, dryThreshold: DRY_THRESHOLD, customLenses: !!CUSTOM_LENSES, knownCount: (ARGS.known || []).length, graphRows: GRAPH_ROWS.length, budgetTotal: BUDGET_TOTAL },
|
||||
spentTotal: budget.spent(),
|
||||
rounds: roundStats.length,
|
||||
converged,
|
||||
|
||||
Reference in New Issue
Block a user