Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/runtime/supervise/budget-floor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,12 @@ export const WORKER_TOKEN_FLOOR = {
*
* A `null` harness is the router/inline arm: it holds only coordination verbs and re-sends no
* harness scaffolding, so it has no floor of this kind.
*
* Accepts a bare `string` because `AgentProfile.harness` is not exactly `BackendType` — an
* unrecognised name resolves to `null` (no floor) rather than throwing, which keeps an unknown
* harness admissible instead of refusing work on a name this table has not heard of.
*/
export function workerTokenFloor(harness: BackendType | null): number | null {
if (harness === null) return null
export function workerTokenFloor(harness: BackendType | string | null | undefined): number | null {
if (harness === null || harness === undefined) return null
return (WORKER_TOKEN_FLOOR as Record<string, number | null>)[harness] ?? null
}
8 changes: 7 additions & 1 deletion src/runtime/supervise/scope.ts
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,13 @@ export function createScope<Out>(args: ScopeArgs): Scope<Out> {
// `budget-exhausted` invites a caller to retry SMALLER, which here is the exact wrong move.
// Checked after resolution because that is where the harness is known, and refunded the way
// every sibling failure on this path is.
const floor = workerTokenFloor(spec.harness)
// `spec.harness` is null whenever the harness rides in the backend config instead of the
// spec — which is the path that actually spawns workers through the bridge. Reading only it
// made this guard miss the case it was written for: a root authored a 6,000-token child
// against a measured 31,211 floor, the guard never fired, and the child died having produced
// nothing (discovery-lab run proof-bridge-20260801f). The AgentProfile is where a root
// declares its child's harness, so it is the more reliable of the two.
const floor = workerTokenFloor(spec.harness ?? spec.profile.harness ?? null)
if (floor !== null && opts.budget.maxTokens < floor) {
args.pool.reconcile(reservation.ticket, zeroSpend())
permit.release()
Expand Down
22 changes: 22 additions & 0 deletions tests/kernel/budget-floor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,25 @@ describe('worker token floor', () => {
}
})
})

describe('the floor reads the harness a root actually declared', () => {
// The guard originally read only `spec.harness`, which is null whenever the harness rides in the
// backend config rather than the spec — the path that actually spawns workers through the
// bridge. So it missed the case it exists for: run proof-bridge-20260801f authored a
// 6,000-token child against a 31,211 floor, admitted it, and the child produced nothing.
it('resolves a floor from an AgentProfile harness when the spec carries none', () => {
const specHarness = null
const profileHarness = 'pi' as const
expect(workerTokenFloor(specHarness ?? profileHarness)).toBe(31_211)
})

it('still has no floor when neither names a harness (router/inline arm)', () => {
const specHarness = null
const profileHarness = null
expect(workerTokenFloor(specHarness ?? profileHarness)).toBeNull()
})

it('refuses the exact budget that slipped through', () => {
expect(6_000).toBeLessThan(workerTokenFloor('pi')!)
})
})
Loading