feat(dream): configurable dream.cycle_timeout (hot) - #32
Open
W4-NERF wants to merge 1 commit into
Open
Conversation
The whole dream cycle ran under a hardcoded CycleTimeout const (700s). Slow reasoning models (Qwen3.8-27B-NVFP4) run eval alone for ~600-690s on full 16-20-candidate prompts, so the enclosing cycle deadline cut the cycle before the recurrence/quality-score/cooldown steps ran — re-picking the same block every cycle. Make it a hot setting, mirroring dream.temporal_timeout (PR GottZ#23): - config.Dream.CycleTimeout `dream.cycle_timeout` / CTX_DREAM_CYCLE_TIMEOUT (default 700 = legacy constant, mut:hot, tenancy:global-only) - Router.CycleTimeout + newRouter wiring - dream.CycleTimeoutFor(r) helper: router value > 0 wins, else the package CycleTimeout constant (0 = documented "package default" sentinel) — the fallback the scheduler's outer cycle context and RunDreamCycle's inner context both read - validate.go V16b budget reads the effective (hot) cycle deadline via temporalTimeoutBudgetOf, so a raised cycle_timeout widens the window instead of warning spuriously Backward compatible: default 700 = the old const; 0/negative fall back to the constant. No migrations. Tests: TestCycleTimeoutFor (nil/empty/override/negative), updated TestValidateTemporalTimeoutBudget (default 400 + 2400->2100). Verified: go build ./... , go vet, go test -short on the 3 touched packages, golangci-lint v2 (repo config) = 0 issues. Docs: docs/operations.md env-table row + temporal_timeout budget clause.
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.
Summary
Make the whole dream cycle timeout configurable via a hot setting (
dream.cycle_timeout), mirroringdream.temporal_timeout(PR #23). Today the cycle runs under a hardcodedCycleTimeoutconst (700s); this PR makes it a live, restart-free knob.Why it matters
The entire dream cycle — pick → temporal → keywords → RRF → eval → recurrence → quality-score → cooldown — runs under a single
context.WithTimeout(ctx, CycleTimeout). On slow reasoning models this const is too tight:700scycle cap, the eval fills the budget, so the remaining steps time out inside the cycle — the cascaderecurrence phase 2 failed→update quality score failed→ (no cooldown set → block re-picks every cycle)./healthis green.The only current fix is a source rebuild (
const700 → 2400). This PR makes it a hot setting, so an operator can raise the cycle deadline without a rebuild.What changed
internal/config/config.goDreamConfig.CycleTimeout—dream.cycle_timeout/CTX_DREAM_CYCLE_TIMEOUT, default700(legacy const),mut:hot,tenancy:global-onlyinternal/dream/router.goRouter.CycleTimeoutfieldinternal/dream/dream.goCycleTimeoutFor(r)helper (router value > 0 wins, else the packageCycleTimeoutconst) +RunDreamCyclereads itinternal/events/scheduler.gonewRouterwiresCycleTimeout; the outer cycle context reads the effective valueinternal/config/validate.gotemporalTimeoutBudgetOf), so a raised cycle widens the window instead of warning spuriouslyinternal/dream/cycle_timeout_test.goTestCycleTimeoutFor(nil / empty / override / negative → default)internal/config/validate_test.goTestValidateTemporalTimeoutBudgetupdated (default 400s; 2400s cycle → 2100s)docs/operations.mdtemporal_timeoutbudget clause updatedPrecedence: the key is the default for the enclosing cycle. A
timeouts.dreamentry on the servingcontext_backendsrow still wins per call (TimeoutFor, walked inllm/chain.go) — it bounds eval/keywords/recurrence per call, whereas this key bounds the whole cycle. On a configured row, raise the row value instead.Backward compatibility
700= the legacyCycleTimeoutconstant — no behavior change for existing deployments.0(and a negative value, rejected at boot / 422s the settings write by V16) falls back to the constant — same contract astemporal_timeout.Tests & verification
go build ./...— cleango vet ./internal/{dream,config,events}/— cleango test -short ./internal/{dream,config,events}/— all pass (incl. the two new/updated tests)golangci-lint v2(repo config) on the 3 touched packages — 0 issuesBase:
root.