Skip to content

feat(agent): ship no task limits; the spend gate is opt-in - #8340

Merged
esengine merged 1 commit into
main-v2from
feat/no-default-task-limit
Aug 11, 2026
Merged

feat(agent): ship no task limits; the spend gate is opt-in#8340
esengine merged 1 commit into
main-v2from
feat/no-default-task-limit

Conversation

@esengine

Copy link
Copy Markdown
Owner

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:

  • Money does not survive a model switch. A budget loose enough for DeepSeek lands a frontier model within a couple of answers. There is no portable amount.
  • A long task is as often the job as it is a runaway. An hour of work on a deliberately large task is not a defect, and a default that lands it is a default that fires on real work - worse than no default at all.

That leaves the gate as what it should have been from the start: available, precise, and off until asked for.

The gate is unchanged

[agent]
task_cost_budget = 5.0            # in the model's pricing currency
task_time_budget_minutes = 60     # wall clock across the whole task

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. taskBudgetOrDefault becomes normalizeTaskBudget, which now does nothing but read a negative value as unset.

Verification

  • TestUnconfiguredBudgetNeverCrosses pins the promise directly: eight hours and 55M tokens against an unconfigured budget cross nothing
  • TestTaskBudgetShipsNoLimits - both axes off out of the box
  • TestTaskBudgetAxesSetIndependently - setting one does not imply the other
  • The gate's own tests are unchanged and still green, since they configure a budget explicitly: TestTaskBudgetGateLandsARunawayOnCost, TestTaskBudgetGateFiresOnWallClock, TestTaskBudgetGateKeepsTheWorkAndAsksForASummary, TestTaskBudgetGateIgnoresCostWhenUnpriced
  • TestEffectTaskBudgetLandsARunawayThroughRealBuild still passes through the real boot.Build stack - it configures the budget in TOML, which is now the only way it applies

go 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) and internal/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.md and docs/GUIDE.zh-CN.md now state that a chat task has no default limit of any kind and that the spend gate is opt-in.

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.
@esengine
esengine requested a review from SivanCola as a code owner August 11, 2026 06:18
@github-actions github-actions Bot added v2 Go rewrite (1.x) — main-v2 branch, active development agent Core agent loop (internal/agent, internal/control) config Configuration & setup (internal/config) and removed v2 Go rewrite (1.x) — main-v2 branch, active development labels Aug 11, 2026
@esengine
esengine merged commit ced0eee into main-v2 Aug 11, 2026
23 checks passed
@esengine
esengine deleted the feat/no-default-task-limit branch August 11, 2026 06:51
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent Core agent loop (internal/agent, internal/control) config Configuration & setup (internal/config)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant