You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A coding-agent attempt (#4262's interface, #4266/#4267's implementations) has a real cost — tokens/turns/wall-clock — that needs to be measured per attempt and checked against a budget, both so a single runaway attempt can't burn unbounded spend and so the portfolio/governor layers have real numbers to work with. Two existing pure primitives in gittensory-engine are the natural composition points: packages/gittensory-engine/src/portfolio/queue.ts's PortfolioCaps (globalWipCap/perRepoWipCap, count-based concurrency caps — a different axis but the same "cap enforcement" family) and packages/gittensory-engine/src/governor/rate-limit.ts's evaluateLocalRateLimit/LocalRateLimitConfig (rolling-window rate limiting) plus jitteredBackoffMs (deterministic backoff, injected-random for testability). Neither module currently has any notion of "cost" or "turns" — this issue adds that dimension.
Deliverables
A pure metering module (packages/gittensory-engine/src/miner/attempt-metering.ts or similar, coordinated with feat(miner-hands): define the CodingAgentDriver interface seam #4262's src/miner/ home) that accumulates per-attempt cost/turn counters and evaluates them against a configured ceiling — the same "pure decision, no IO/enforcement" discipline governor/rate-limit.ts's header explicitly calls out ("This module computes numbers only — it does NOT store state, schedule, or gate any write action").
A defined unit for "cost" (tokens? dollars? both, with a per-model conversion table?) and "turns" (one tool-call? one full agent iteration?) — pin this down explicitly, since both CodingAgentDriver implementations (CLI-subprocess vs. Agent-SDK) report usage in different native shapes and need to normalize to the same metered unit.
Unit tests for: normal accumulation under the ceiling, a breach mid-attempt, and the boundary case (exactly at the ceiling) — following evaluateLocalRateLimit's existing test-friendly, injected-clock discipline (nowMs as a parameter, never Date.now() read internally).
References
packages/gittensory-engine/src/portfolio/queue.ts:24-27 (PortfolioCaps — the existing cap-enforcement family, count-based not cost-based)
packages/gittensory-engine/src/governor/rate-limit.ts:1-9 (module header: "computes numbers only... does NOT store state, schedule, or gate any write action" — the discipline this new module should match)
src/selfhost/ai.ts:644-711 (defaultSpawn's timer-based SIGKILL — closest existing hard-cutoff precedent for the CLI-subprocess driver side of a breach)
A coding-agent attempt (#4262's interface, #4266/#4267's implementations) has a real cost — tokens/turns/wall-clock — that needs to be measured per attempt and checked against a budget, both so a single runaway attempt can't burn unbounded spend and so the portfolio/governor layers have real numbers to work with. Two existing pure primitives in
gittensory-engineare the natural composition points:packages/gittensory-engine/src/portfolio/queue.ts'sPortfolioCaps(globalWipCap/perRepoWipCap, count-based concurrency caps — a different axis but the same "cap enforcement" family) andpackages/gittensory-engine/src/governor/rate-limit.ts'sevaluateLocalRateLimit/LocalRateLimitConfig(rolling-window rate limiting) plusjitteredBackoffMs(deterministic backoff, injected-random for testability). Neither module currently has any notion of "cost" or "turns" — this issue adds that dimension.Deliverables
packages/gittensory-engine/src/miner/attempt-metering.tsor similar, coordinated with feat(miner-hands): define the CodingAgentDriver interface seam #4262'ssrc/miner/home) that accumulates per-attempt cost/turn counters and evaluates them against a configured ceiling — the same "pure decision, no IO/enforcement" disciplinegovernor/rate-limit.ts's header explicitly calls out ("This module computes numbers only — it does NOT store state, schedule, or gate any write action").CodingAgentDriverimplementations (CLI-subprocess vs. Agent-SDK) report usage in different native shapes and need to normalize to the same metered unit.src/selfhost/ai.ts:644-711's existing timer-basedSIGKILLpattern is the closest precedent for a hard cutoff) and feat(miner-hands): Agent-SDK CodingAgentDriver (query() loop) #4267'squery()loop (which likely has its own natural stop-iterating point for a graceful cutoff).evaluateLocalRateLimit's existing test-friendly, injected-clock discipline (nowMsas a parameter, neverDate.now()read internally).References
packages/gittensory-engine/src/portfolio/queue.ts:24-27(PortfolioCaps— the existing cap-enforcement family, count-based not cost-based)packages/gittensory-engine/src/governor/rate-limit.ts:1-9(module header: "computes numbers only... does NOT store state, schedule, or gate any write action" — the discipline this new module should match)packages/gittensory-engine/src/governor/rate-limit.ts:53-74(evaluateLocalRateLimit),:84-101(jitteredBackoffMs— injected-random testability pattern)src/selfhost/ai.ts:644-711(defaultSpawn's timer-basedSIGKILL— closest existing hard-cutoff precedent for the CLI-subprocess driver side of a breach)