feat(agent): ship no task limits; the spend gate is opt-in - #8340
Merged
Conversation
The wall-clock default went out with the round ceiling. Nothing bounds an ordinary chat task now: not rounds, not tokens, not time, not money. It runs until the model finishes, an adaptive guard finds it stopped making progress, or the user stops it. Deciding a task has run too long is a judgement only the user can make. Money does not survive a model switch — a budget loose enough for DeepSeek lands a frontier model within a couple of answers — and a task that runs for an hour is as often the job that was asked for as it is a runaway. A default that fires on real work is worse than no default, and neither axis has one that would not. The gate itself is unchanged and still there for anyone who wants it: [agent].task_cost_budget and task_time_budget_minutes, each independent, scoped to a whole task, landing on one tool-free summary and a resumable pause. taskBudgetOrDefault becomes normalizeTaskBudget, which now only reads a negative value as unset. TestUnconfiguredBudgetNeverCrosses pins the promise: eight hours and 55M tokens against an unconfigured budget cross nothing.
SivanCola
added a commit
to SivanCola/DeepSeek-Reasonix
that referenced
this pull request
Aug 11, 2026
Problem: - main-v2 advanced with esengine#8270 and esengine#8340 while the catalog integration was under review. - Both branches changed the controller frontend and startup bundle budgets. Root cause: - The inbox recovery localization and opt-in task-spend defaults overlapped the catalog hydration guards and measured frontend budget ratchets. Fix: - Preserve the history hydration identity/error fences alongside locale-aware inbox recovery. - Keep the latest task-spend defaults and use measured startup bundle budgets without widening the repolint baseline. Verification: - env REASONIX_RELEASE_CACHE_GUARD=1 go test -count=1 ./... - env REASONIX_RELEASE_CACHE_GUARD=1 go test -race -count=1 ./... - cd desktop && go test -count=1 ./... - cd desktop && go test -race -count=1 ./... - cd desktop/frontend && pnpm test:all && pnpm build && pnpm test:motion - go vet ./... and pinned golangci-lint for native and cross-platform build tags - CGO_ENABLED=0 root/Desktop builds for darwin amd64/arm64, windows amd64/arm64, and linux amd64 - Wails binding generation, repolint, release workflow contracts, SDK ordinary/race tests, and go mod tidy -diff
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #8320, which dropped the round ceiling but kept a 30-minute wall-clock default. That default goes too.
What changes
Nothing bounds an ordinary chat task by default - not rounds, not tokens, not time, not money. It runs until the model finishes, an adaptive guard finds it stopped making progress, or the user stops it.
Why no default survives
Deciding a task has run too long is a judgement only the user can make:
That leaves the gate as what it should have been from the start: available, precise, and off until asked for.
The gate is unchanged
Each axis is independent, scoped to a whole task (every "continue" included, until unrelated work resets it), and lands on one tool-free summary plus a resumable pause. Cost still only judges what it can price.
taskBudgetOrDefaultbecomesnormalizeTaskBudget, which now does nothing but read a negative value as unset.Verification
TestUnconfiguredBudgetNeverCrossespins the promise directly: eight hours and 55M tokens against an unconfigured budget cross nothingTestTaskBudgetShipsNoLimits- both axes off out of the boxTestTaskBudgetAxesSetIndependently- setting one does not imply the otherTestTaskBudgetGateLandsARunawayOnCost,TestTaskBudgetGateFiresOnWallClock,TestTaskBudgetGateKeepsTheWorkAndAsksForASummary,TestTaskBudgetGateIgnoresCostWhenUnpricedTestEffectTaskBudgetLandsARunawayThroughRealBuildstill passes through the realboot.Buildstack - it configures the budget in TOML, which is now the only way it appliesgo test -count=1 ./internal/agent/ ./internal/control/ ./internal/boot/ ./internal/config/green;golangci-lint run ./...0 issues; repolint clean with no baseline change (this removes lines).Cache-impact: none - removes a default from host-side budget normalization. No prompt, tool schema, or provider request field changes.
Cache-guard: existing -
go test ./internal/agent/covers the cache-hit e2e suites, green unchanged.System-prompt-review: needed - touches
internal/config/(comment only) andinternal/boot/indirectly via defaults. No key is added or removed and nothing reaches the system-prompt prefix; requesting review from @esengine as config owner.Documentation-impact: updated -
docs/GUIDE.mdanddocs/GUIDE.zh-CN.mdnow state that a chat task has no default limit of any kind and that the spend gate is opt-in.