feat(config): let operators size or disable the Goal token budget - #10543
Conversation
QwenLM#9891 gave createGoalRuntime a tokenBudgetGrant option, but the only production constructor never passed it, so every session ran on the 30M default with no way to raise, lower, or switch it off. The number was already user-visible (get_goal reports it, a budget stop prints it); it just was not user-settable. `model.goalTokenBudget` sits beside the other run ceilings. A positive integer is the grant, in the tokens the Goal meter counts. 0 runs Goals with no budget by mapping to the runtime's non-finite opt-out, so the created Goal simply carries no tokenBudget field and nothing non-finite is persisted. Anything invalid falls back to the default with a debug warning. It reaches core Config the way maxSessionTurns does and is passed at the single createGoalRuntime call; the runtime is untouched. Verified live: with `{"model":{"goalTokenBudget":400000}}` in the workspace settings, the session journal's create record carries tokenBudget=400000 and the Goal completed in one turn at 166,503. Mutation probes: dropping the pass-through fails the 1234 and the 0 tests; dropping the 0-to-unbounded mapping fails the 0 test and the normalizer test.
|
@qwen-code /takeover |
|
🤝 Takeover engaged: the autofix loop now manages this PR — it will address new review feedback and resolve base conflicts until the label is removed or the round cap is reached. This is a fork PR, so the first round comes from the next scheduled scan (usually within minutes). Remove the 中文说明🤝 已接管:autofix 循环现在管理此 PR —— 将持续处理新的评审反馈与 base 冲突,直到移除标签或达到轮次上限。本 PR 来自 fork,首轮处理将由下一次定时扫描执行(通常几分钟内)。移除 |
|
|
|
Thanks for the PR! Template looks good ✓ Problem: Observed gap, not theoretical. #9891 gave Direction: Aligned. This is an operator knob for an existing, already-merged runtime capability, in the same family as the sibling ceilings ( Size: core paths touched ( Approach: Minimal and matches the obvious path: schema entry → Risk: No elevated risk signals — none of the changed files match the revert-correlated high-risk paths. Moving on to code review. 🔍 中文说明感谢贡献! 模板完整 ✓ 问题: 已观测到的缺口,不是理论问题。#9891 给 方向: 对齐。这是对已合入的 runtime 能力加一个 operator 旋钮,与兄弟上限项( 规模: 触及核心路径( 方案: 最小化且就是显而易见的路径:schema 条目 → 风险: 无升级风险信号——改动文件均未命中与 revert 相关的高风险路径。 进入代码审查 🔍 — Qwen Code · qwen3.8-max Reviewed at |
|
Code review — I wrote my own proposal before reading the diff (schema entry →
The tests pin the wiring, not just the normalizer: they build a real One nit, non-blocking but worth fixing before merge: the new CI evidence — the PR's own checks on the reviewed commit, fetched via API (nothing re-run here): Final CI results for
One row per check name (latest run); skipped checks omitted; failures sort first. / 每个检查名一行(取最新一次运行),省略 skipped,失败项排在最前。 The main ubuntu unit/integration suite is still running; macOS/Windows matrix legs are skipped in fork CI, so Linux-only coverage is what this PR will land on. Note fork CI also runs no lint/format/typecheck leg — the prettier nit above was found by static reading, and would have surfaced there. Sandboxed verification would settle the one claim CI can't: that the setting reaches a live session end-to-end (the journal 中文说明代码审查 —— 我在看 diff 之前先写了自己的方案(schema 条目 →
测试锁住的是接线而不仅是规范化函数:它们构造真实 一个非阻塞的小问题,合并前值得修:新增的 CI 证据 —— 来自该提交自身的 CI 检查(经 API 抓取,此处未重跑):表格见英文部分(表内为机器可读区域,由 finalize 工作流在 CI 落定后更新)。 主要的 ubuntu 单元/集成套件仍在运行;macOS/Windows 矩阵在 fork CI 中被跳过,本 PR 将以 Linux 单平台覆盖合入。另注意 fork CI 也不跑 lint/format/typecheck——上面的 prettier 问题是静态阅读发现的,本来应由那里暴露。 沙盒验证可以补足 CI 无法覆盖的一个论断:设置项真正到达真实 session(journal — Qwen Code · qwen3.8-max Reviewed at |
|
Confidence: 4/5 — clean, minimal wiring of an existing runtime option with tests that pin it; one auto-fixable prettier nit, and the main CI suite is still running. Honest read: this is what a small config PR should look like. The option already existed in the runtime ( Two things keep it at 4 rather than 5. The 81-character line in On volume: the author has a batch of open PRs this week; I evaluated this one on its own merits and it stands on them — focused, evidenced, no scope creep. Approval deferred until CI lands green on 中文说明置信度:4/5 —— 干净、最小化地接入了 runtime 已有的选项,测试锁住了接线;一个可自动修复的 prettier 小问题,主 CI 套件仍在运行。 坦率地说:这是一个小型配置 PR 该有的样子。该选项在 runtime 中早已存在(#9891 的 两点让它停在 4 而不是 5。 关于数量:作者本周有一批打开的 PR;我按各自功过评估,这一个站得住——聚焦、有证据、无范围蔓延。 审批推迟到 CI 在被审提交上全绿之后——ubuntu 单元/集成套件仍在运行,现在批准等于为一个尚不存在的结果背书。若全绿,审批会自动跟上;若有红项或 head 移动,则保留不批。 — Qwen Code · qwen3.8-max Reviewed at |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Reviewed. Suggestions are inline.
中文说明
已审查。 建议见行内评论。
— qwen3.8-max via Qwen Code /review (v0.22.3)
|
🤖 AutoFix hit a verification-gate error before reaching a verdict (attempt 1/100) — it will retry on the next scan. Autofix review round — PR #10543 (round 1)Commit: Feedback dispositionR1-1 — "ignored with a warning" promise is invisible by default (anchors: R1-2 — the warning branch has no test ( 中文说明🤖 AutoFix 在得出结论之前遇到验证门错误(第 1/100 次尝试)—— 将在下次扫描时重试。 Run log: https://github.com/QwenLM/qwen-code/actions/runs/33298114936 🧠 Handled by Qwen Code · model/模型 |
QwenLM#10543) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
…ion (QwenLM#10543) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
|
🤖 Addressed the latest review feedback (round 2/100). What changed, and what I pushed back on: · 已处理最新评审反馈(第 2/100 轮)。改动内容与我反驳保留之处如下: Review round summary — PR #10543 (same-run verification repair)This round is the same-run verification repair for the deterministic rejection of commit Diagnosis (evidence, not guess)
Fix applied (deflake, assertion-preserving)Per the repo Prior-round findings (re-verified still resolved)All five inline findings remain resolved in code by the preserved commit
Mutation probesThis round's commit adds no new guard, branch, or behavior — only test timeout ceilings (a deflake), so there is no new guard to witness. The witnesses for the change are the observed failure signatures themselves (two independent runs, three timed-out tests, all at exactly 15000ms on the same import-heavy pattern), and the ceiling change cannot mask a correctness regression: any assertion failure still fails at any timeout. The prior round's five mutation probes (warn-block deletion, guard removal, Other notes
VerificationCommands actually run this round (agent-session env scrubbed to gate parity: no
中文说明审查轮次总结 — PR #10543(同轮验证修复)本轮是针对提交 诊断(基于证据,而非猜测)
应用的修复(去抖动,保持断言不变)按仓库 上一轮的发现(重新验证仍已解决)全部五条行内发现仍由保留的提交
变异探针本轮提交没有新增任何守卫、分支或行为——只有测试超时上限(去抖动),因此没有需要见证的新守卫。本次修改的见证是观测到的失败签名本身(两次独立运行、三个超时的测试,全部恰好在 15000ms、同一种重导入模式上),且抬高上限不会掩盖正确性回归:任何断言失败在任何超时下都会失败。上一轮的五项变异探针(删除警告块、去掉守卫、移除 其他说明
验证本轮实际执行的命令(代理会话环境已对齐关卡形态:去掉
Base-conflict check · 基分支冲突检查: no conflict with main. · 与 main 无冲突。 🧵 Resolved all 5 selected review thread(s). · 已关闭全部选中的 5 条评审线程。 Re-review when you have a moment. After round 100 this bot stops and leaves the PR for a human. · 有空请复审;第 100 轮后本 bot 停止并将 PR 交给人工。 🧠 Handled by Qwen Code · model/模型 |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Reviewed. Suggestions are inline.
中文说明
已审查。 建议见行内评论。
— qwen3.8-max via Qwen Code /review (v0.22.3)
Local end-to-end verification — recommend merge after a rebaseI built this branch ( The feature does what the description says. Every load-bearing claim reproduced end to end, including the ones the PR could only assert. The findings below are consistency and safety-of-defaults issues around the edges, not defects in the mechanism. Environment
What reproduced1. The setting reaches a real session, and it is this PR's line that carries it.
The last row is the proof of necessity: with only the pass-through removed, the identical settings file is ignored and the same task runs 103 model calls instead of 3. 2. A configured window really stops a Goal, and the operator sees the configured number. Not just a field in the journal — the wind-down turn is granted, then the Goal settles 3. 4. 5. The metering scope in the description is accurate. In a run where my mock billed 2,709,000 tokens total (103 Goal turns at 3,000 + 24 checkpoint side queries at 100,000), the Goal meter recorded exactly 309,000. Side queries and checkpoint verification are not metered, as documented. 6. Both operator scopes work, with the usual precedence. 7. Static and test gates. 8. The new tests are not vacuous. Five mutants, all caught:
FindingsF1 · Important — an invalid value falls back silently, and it fails in the unsafe direction. This is the one I would like addressed before merge. Every sibling run budget rejects a typo at startup; this one does not:
Suggested fix, symmetric with the neighbours: a F2 · Important — Both the docs row and the schema description say Commit 2 added F3 · Important (description only) — the PR body no longer matches the diff. Commit 2 (
F4 · Minor — no upper bound, unlike the siblings. F5 · Minor (merge mechanics) — the conflict is entirely in commit 3, which The only conflicting file is Worth flagging while you are there: because the PR is in a conflicting state, GitHub never produced a merge ref, so no F6 · Nit — RecommendationMerge after: rebase onto Tested on Linux. macOS and Windows unverified here. 中文版报告本地端到端验证 —— 建议 rebase 后合并我在本地构建了本分支( 功能与描述一致。 所有关键论断都端到端复现了,包括 PR 里只能声称、无法在单测中证明的那些。下面的问题都是边缘处的一致性与默认值安全性问题,不是机制本身的缺陷。 环境
复现结果1. 设置真的进入了真实会话,且正是本 PR 这一行在起作用。
最后一行是必要性证明:只删掉那一行透传,同样的设置文件就被完全忽略,同一个任务从 3 次模型调用变成 103 次。 2. 配置的窗口真的会停住 Goal,而且 operator 看到的就是配置的数字。 不只是日志里的一个字段——wind-down 回合被授予,随后 Goal 落到 3. 4. 5. 描述里的计量口径是准确的。 在一次 mock 总共计费 2,709,000 token 的运行中(103 个 Goal 轮次各 3,000,加 24 次 checkpoint side query 各 100,000),Goal 计量表只记录了 309,000。side query 与 checkpoint 验证确实不计入。 6. 两个 operator scope 都生效,优先级正常(workspace 覆盖 user)。 7. 静态检查与测试。 core 8. 新增测试非空转。 五个变异体全部被捕获:删掉 问题F1 · Important —— 无效值静默回退,而且是往不安全的方向失败。 这是我希望合并前处理的一条。同族的每个运行预算设置都会在启动时拒绝笔误,只有这个不会:
建议的修法与邻居对称:在 F2 · Important —— 这里 文档行与 schema 描述都写 commit 2 加入的 F3 · Important(仅描述)—— PR 正文与 diff 已经不一致。 commit 2( F4 · Minor —— 没有上界,和同族不一致。 F5 · Minor(合并机制)—— 冲突全部落在 commit 3,而 唯一冲突的文件是 顺带一提:由于 PR 处于冲突状态,GitHub 从未生成 merge ref,因此本分支上根本没有跑过任何 F6 · Nit —— 结论建议在以下处理之后合并:rebase 到 已在 Linux 验证;macOS 与 Windows 未在此验证。 |
|
🤖 AutoFix hit a verification-gate error before reaching a verdict (attempt 3/100) — it will retry on the next scan. Address-review summary — PR #10543 (round 3)Feedback triage
No Required/Critical items, no failed checks, no deferred-feedback section in this round. R2-1 — implementedThe claim was verified against the code before acting: Change (commit
中文说明🤖 AutoFix 在得出结论之前遇到验证门错误(第 3/100 次尝试)—— 将在下次扫描时重试。 Run log: https://github.com/QwenLM/qwen-code/actions/runs/33323049660 🧠 Handled by Qwen Code · model/模型 |
|
🤖 AutoFix hit a verification-gate error before reaching a verdict (attempt 4/100) — it will retry on the next scan. Autofix review round — PR #10543This round merged Feedback dispositionsF5 · merge conflict — resolved. Merged F1 · invalid values now fail loud at startup — implemented. New 中文说明🤖 AutoFix 在得出结论之前遇到验证门错误(第 4/100 次尝试)—— 将在下次扫描时重试。 Run log: https://github.com/QwenLM/qwen-code/actions/runs/33324729961 🧠 Handled by Qwen Code · model/模型 |
|
🤖 AutoFix hit a verification-gate error before reaching a verdict (attempt 5/100) — it will retry on the next scan. Review round summary — PR #10543Two commits this round: a merge of 1. Merge of
|
|
🤖 AutoFix hit a verification-gate error before reaching a verdict (attempt 6/100) — it will retry on the next scan. Autofix round — review feedback addressedCommits this round (additive only):
F1 · Important — invalid values fell back silently, in the unsafe direction — FIXEDReproduced first: new tests asserting startup rejection failed against the pre-fix code with Fix, symmetric with the neighbours as suggested: F2 · Important —
|
|
🤖 AutoFix stopped after 5 consecutive rounds that pushed nothing (failed rounds, timeouts, gate rejections, or stops under instruction). Retrying at the same per-round budget is not converging — this usually means the PR is too large or conflicts with a fast-moving
See the Qwen Autofix agent step logs for model/tool output. 中文说明🤖 AutoFix 已停止:连续 5 轮未能推送任何内容(失败轮次、超时、验证门拒绝或按指示停止)。以相同的单轮预算重试并不收敛 —— 这通常意味着 PR 过大,或与快速变动的 Run log: https://github.com/QwenLM/qwen-code/actions/runs/33360112307 🧠 Handled by Qwen Code · model/模型 |
The setting's population is exactly "people typing zeros into a safety bound", and an extra zero on the 30,000,000 default was accepted silently, widening the runaway-spend window tenfold with no warning. Positive values above GOAL_TOKEN_BUDGET_CAP (300,000,000) now fall back to the default through the same invalid-value path as negatives, with the debug-log warning. An operator who genuinely wants more autonomy than 300M tokens per window has the explicit opt-out (0/-1); the cap is a typo guard, not a policy on long runs. Mutation probe: removing the upper bound fails exactly the new cap-boundary test (595 others green).
|
⏸️ Takeover paused: this PR reached its round cap (100/100). Comment 中文说明⏸️ 托管已暂停:本 PR 达到轮次上限(100/100)。评论 |
# Conflicts: # packages/cli/src/serve/server-default-bridge-wiring.test.ts
|
@wenshao 这一轮已处理并普通推送到
验证:CLI 聚焦测试 475/475,core config 596/596,仓库级 build 与 typecheck 均通过;PR 现已恢复 MERGEABLE。 |
|
@qwen-code /takeover |
|
🔄 Takeover re-armed: the round counter starts a fresh window (previous rounds no longer count toward the cap); management continues. 中文说明🔄 已重新武装:轮次计数开启新窗口(此前轮次不再计入上限),托管继续。 |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Reviewed.
1 Suggestion-level finding(s) this review confirmed are already reported on this PR and are not repeated:
- R3-1 goalTokenBudget fallback warning wording — dropped as location overlap at packages/core/src/config/config.ts:2618, already reported (comment 3888683781, R1-1 thread)
Not explored to full depth (tool budget reached): "agent 2": none — no checks were cut short.; "agent 5": none — no check was cut short..
中文说明
已审查。
本轮确认的 1 条建议级发现已在 PR 上报告过,不再重复发布(列表见上方英文部分)。
未探索到全部深度(达到工具调用预算):"agent 2":none — no checks were cut short.;"agent 5":none — no check was cut short.。
— qwen3.8-max via Qwen Code /review (v0.22.3)
chiga0
left a comment
There was a problem hiding this comment.
No blocking findings.
Checked:
- Full config chain: settings.json → validateGoalTokenBudget (CLI) → resolveGoalTokenBudget → loadCliConfig → Config.goalTokenBudgetGrant → GoalRuntime.tokenBudgetGrant — wired and tested end-to-end
- Two-layer validation design is intentional and consistent: CLI layer (runBudget.ts) rejects 0 at startup with a clear error; Config layer (config.ts) accepts 0/-1 as the opt-out alias and normalizes to Infinity — matching the sibling budget settings pattern
- GOAL_TOKEN_BUDGET_CAP = 300_000_000 (10x default) acts as typo guard — tested at both cap boundary and cap+1
- Debug-log warning for invalid values fires only for invalid/unknown inputs (not for valid, absent, or opt-out) — tested explicitly
- normalizeGoalTokenBudget and isValidGoalTokenBudget exported correctly; schema in settings.schema.json and docs in settings.md updated consistently
CI: 14 checks green — ubuntu build+test (30m), integration, E2E smoke, CVE audit, secret scan, desktop shells all pass. macOS/Windows test jobs skipped (consistent with other PRs).
Cross-check: All bot comments are [Suggestion] only, no CHANGES_REQUESTED. R1-2 ('no test for warning branch') is stale — the debug-log warning test is present. R2-1 ('no upper bound') is stale — GOAL_TOKEN_BUDGET_CAP is implemented.
Reviewed with AI assistance.
qwen-code-dev-bot
left a comment
There was a problem hiding this comment.
Gate APPROVE at head 4e235f1d. Validation is layered the right way: settings.json values are startup-rejected on 0/fraction/overshoot/non-number with clear messages, the core normalization stays lenient for host integrations (0/-1 → unbounded, invalid → default + warn), the 300M cap is shared from core so CLI and runtime cannot disagree, and the grant is wired straight into the Goal runtime's tokenBudgetGrant at construction — runtime semantics unchanged. 0 unresolved threads, Test (ubuntu) and all substantive checks green, chiga0 approved this exact head. 中文:门禁通过。CLI 启动校验 + core 宽松归一双层设计合理,cap 常量单一来源,grant 直接入 Goal runtime;线程零未解决、CI 全绿。
yiliang114
left a comment
There was a problem hiding this comment.
LGTM at 4e235f1. Validation is layered cleanly: the CLI rejects 0/fractional/out-of-range at startup with actionable messages (-1 = unlimited, cap at 10x default as a typo guard), while core's normalizeGoalTokenBudget stays tolerant for programmatic Config use — the lenient 0/-1 branch is unreachable from settings.json since the CLI validator sits upstream. Schema, docs, and ~268 test lines all consistent; CI green, 0 unresolved threads.
…AME (QwenLM#10671) * fix(autofix): clamp gate test load explicitly instead of via RUNNER_NAME The verification gate launches through an env -i allowlist that drops RUNNER_NAME, so the vitest configs' ECS load clamps (60s test/hook timeouts, maxWorkers 25%) silently deactivate inside the gate: tests run with 15s timeouts, unbounded workers and coverage collection on a host shared with other autofix jobs. Under pool saturation this produced both false rejections (QwenLM#10171 round 3: 73 load-induced 15s timeouts in files the PR never touched, charged to the round) and gate deaths past the step's 60-minute cap that discarded verified fixes ("verification-gate error": QwenLM#10171 rounds 1/2/5-7, QwenLM#10543 five in a row). Pass the clamp values explicitly on both gate vitest invocations (the per-package --changed run and the bite check) so the verdict does not depend on env plumbing or runner naming, and disable coverage: nothing in the gate consumes it, and its collection dominated the overrun (72,000 CPU-seconds of collect in one 1,560s gate leg). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AhZA7LdQXZjcjfiPsoZkqZ * fix(autofix): clamp the gate's third vitest leg and pin the clamps Addresses review round 1 on QwenLM#10671. R1-6 The contracts check runs a web-shell vitest from inside the gate's own `env -i` child, and web-shell's config sets no timeouts at all, so that leg ran at vitest's 5s default on the same saturating host — the false-rejection class this PR removes, surviving in a sibling path. The clamp array moves above the contracts call and is handed to the shared script through AUTOFIX_VITEST_FLAGS; the issue-fix gate invokes the same script where RUNNER_NAME is present and leaves the variable unset, so its invocation is unchanged. R1-3 Nothing pinned that the clamps reach any invocation — every existing assertion is a prefix that ends before the expansion, so dropping it from a leg (or emptying the array, silent without `set -u`) stayed green while the gate reverted to 15s timeouts and coverage on. Three structural pins added on the review runner only, plus a contracts-script case that runs with AUTOFIX_VITEST_FLAGS set and asserts the flags reach npm. R1-4 The array hand-copies the ECS branch of three vitest configs, and inside the gate the CLI flags outrank the config — so raising an ECS ceiling to shelter a heavier test would leave the gate enforcing the old one and rejecting a fix that is green in normal CI. A parity test in scripts/tests/unit-vitest-configs.test.ts re-imports core, cli and acp-bridge under a stubbed ecs-qwen RUNNER_NAME (they read the env at import time) and asserts equality with the array parsed out of the shell script. R1-5 Narrowed the comment's claim, per the finding's own minimum. The residual is real and now named in the script: a handful of test files set their ceiling with a runtime `vi.setConfig` keyed on RUNNER_NAME, which outranks the CLI, so they keep their non-ECS values in here. Closing it needs a gate sentinel on both env -i allowlists plus a change in each file — a separate slice, not folded into this one. R1-1 is declined; see the thread. Its two premises did not reproduce against the lockfile-pinned vitest 1.6.1 under packages/sdk-typescript: the full suite passes with --maxWorkers=25% (37 files, 1747 tests, exit 0), and --maxThreads is rejected by 1.6.1 and 3.2.7 alike, so --maxWorkers is the spelling both majors accept rather than neither. * fix(autofix): pin the clamp witnesses and correct the unclamped-leg record Addresses review round 2 on QwenLM#10671; re-verifies round 1's fixes with mutation probes. R2-1 The comments justifying the unclamped issue-fix leg rested on a premise that does not hold for that leg: web-shell's vitest config sets no timeouts and has no RUNNER_NAME branch, so the drift test runs at vitest's 5s default wherever it runs. Corrected at all four mirror sites (both scripts and both test comments): the review gate passes explicit clamps; the issue-fix gate and repo-hygiene's docker leg — the previously unnamed third caller — invoke the contracts script without the variable and accept the 5s default. The alternative (exporting AUTOFIX_VITEST_FLAGS in the issue-fix gate step) edits a workflow file this PR has never touched and stays out of scope. R2-2 --maxWorkers=25% is coerced to NaN by vitest 1.x; the lockfile-pinned 1.6.1 under packages/sdk-typescript survives only because its config sets a numeric poolOptions.threads.maxThreads, which tinypool reads before ctx.config.maxWorkers. Pin the shield: a new case derives vitest-1.x workspaces from nested lockfile copies and asserts each keeps the threads pool and a numeric maxThreads, failing with a directive if such a workspace is missing from the config registry. Mutation-verified red on shield removal. R2-3 The export is the only line carrying the clamps across the process boundary into check-autofix-contracts.sh; nothing pinned it. Added the structural pin plus an ordering assertion against the contracts call — deleting the export or moving it below the call now fails the suite. Both mutants verified red. R2-4 The contracts case's fake npm logged $*-joined argv, rendering a joined-blob flag byte-identically to separate words; the [*]-for-[@] mutant survived. The shim now logs one bracketed line per argv word and the four expectations in the case were updated; the mutant now fails. R1-3/R1-4/R1-5/R1-6 (round-2 commit) re-verified with mutation probes: dropping either invocation's expansion, dropping the assignment, emptying the array, drifting --testTimeout to 61000, and dropping the flag expansion inside the contracts script each turn an existing witness red. R1-1 remains declined: the deterministic crash does not reproduce at this head (the leg passes with sdk's shield present), but the round-2 rationale was wrong and is corrected on the thread; the residual risk is the shield R2-2 now pins. * test(autofix): pin both sides of the gate's AUTOFIX_VITEST_FLAGS transport Addresses review round 3 on QwenLM#10671; both pins mutation-verified. R3-1 Nothing pinned the VITEST_LOAD_CLAMPS definition above its consumers: the existing pins are position-blind (toContain here, the parity regex in unit-vitest-configs.test.ts matches anywhere), so moving the array below its consumers left every pin green while bash expanded the then-unset array to zero words under the gate's `set -eo pipefail` without `-u` — AUTOFIX_VITEST_FLAGS goes empty and the package and bite legs lose all four clamps, silently reverting to the incident conditions. Added an explicit ordering pin against the star-join, the first consumer in script order, which pins the definition above every consumer. Outright deletion was already caught by the parity test's existence assertion; the move was the only surviving hole. Move mutant verified red (61668 < 34052 fails). R3-2 The remove side was pinned nowhere: moving `unset AUTOFIX_VITEST_FLAGS` above the contracts call (or deleting it) strips the export the drift leg inherits at child-spawn time, leaving the web-shell drift test at vitest's 5s default with every establish-side pin green. Added the symmetric ordering pin, contracts call before unset. Move and delete mutants both verified red (34333 < 34241 and 34306 < -1 fail). --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: 易良 <1204183885@qq.com>





What this PR does
Adds one setting,
model.goalTokenBudget, and carries it into the Goal runtime so an operator can size or switch off the autonomous spend window that #9891 arms on each new Goal.For
settings.json, a positive integer from 1 through 300,000,000 is the grant, measured as thetotalTokenCountsummed over model calls made in the Goal's own turns.-1means unlimited/no cap. Leaving the setting unset keeps the built-in default of 30,000,000. Zero, values above the typo-guard ceiling, other negative values, fractions, and non-numbers are rejected at startup instead of silently widening the budget. Host integrations that construct the core configuration directly retain the lenient normalization path, including the existing0opt-out alias.When a Goal spends its window it receives one wind-down turn to hand off, then stops until it is resumed, which arms another window. Side queries and checkpoint verification remain outside the meter, and the Goal runtime itself is unchanged.
Why it's needed
#9891 exposed a budget grant to Goal hosts, but the production CLI never supplied an operator-configured value, so every session used the 30M default. During the end-to-end replay that surfaced #10172, bounding a run to 400k required editing a constant and rebuilding the CLI. Operators running small unattended tasks need a tighter gate, while genuinely long Goals need a deliberate way to raise or disable it; both should be a settings change with typo-safe startup validation.
Reviewer Test Plan
How to verify
-1, startup rejection for0, negative/fractional/non-number/above-cap values, generated schema consistency, and the mainline ECS-aware timeout behavior.model.goalTokenBudget: 400000created a Goal with a 400,000-token window and completed within it.Evidence (Before & After)
Journal
goal_staterecords from the live run,snapshot.goalfields:Before this PR the same run's
createrecord would carrytokenBudget=30000000regardless of settings.Tested on
Environment (optional)
Unit tests plus one live headless run against DashScope with the setting in the operator configuration.
Risk & Scope
-1deliberately disables the runaway bound. Invalid operator settings now fail at startup rather than silently falling back; this is intentional for a safety budget. The default remains unchanged./goal budgetcommand, and no settings-dialog entry.Linked Issues
中文说明
这个 PR 做了什么
新增
model.goalTokenBudget设置,并把它传入 Goal runtime,让 operator 可以调整或关闭 #9891 为每个新 Goal 武装的自主消费窗口。对
settings.json而言,1 到 300,000,000 的正整数表示预算额度,单位是 Goal 自身轮次内模型调用的totalTokenCount之和;-1表示无限制/不设上限;不设置时继续使用内置默认值 30,000,000。0、超过防笔误上限的值、其他负数、小数和非数值会在启动时直接报错,不再静默扩大预算。直接构造 core 配置的 host 集成仍保留宽松归一化路径,包括既有的0opt-out 别名。Goal 用完窗口后会获得一个收尾轮次用于交接,随后停止,直到 resume 时重新武装窗口。Side query 和 checkpoint 验证仍不计入预算,Goal runtime 本身未改。
为什么需要
#9891 已向 Goal host 暴露预算 grant,但生产 CLI 没有传入 operator 配置,因此所有 session 都只能使用 3000 万默认值。在发现 #10172 的端到端回放中,要把一次运行限制在 40 万必须修改常量并重编 CLI。小型无人值守任务需要更紧的闸门,真正长时间运行的 Goal 则需要明确地提高或关闭预算;两者都应通过带防笔误启动校验的设置完成。
评审验证计划
如何验证
-1、0/负数/小数/非数值/超上限值的启动拒绝、生成 schema 一致性,以及主线 ECS-aware 超时行为。model.goalTokenBudget: 400000的 bundle 运行创建了 40 万 token 窗口,并在窗口内完成。证据(前后对比)
真实运行的
goal_state记录见上方英文代码块。本 PR 之前,同样运行的create记录无论如何设置都会带tokenBudget=30000000。已测试平台
Linux ✅;macOS / Windows⚠️ (CI 覆盖)。
环境(可选)
单元测试之外,另有一次在 operator 配置中带该设置、针对 DashScope 的真实 headless 运行。
风险与范围
-1会明确关闭失控保护。非法 operator 配置现在会在启动时报错,而不是静默回退;对于安全预算这是刻意行为。默认值不变。/goal budget命令、无设置对话框条目。关联 Issue