Repository navigation
fix(sandbox): 尊重调用方超时 + cd 前缀只读命令不再武装 1200s 墙钟 - #7
Merged
Merged
Conversation
…ing 1200s
Field report: shell commands 'always hang at 1200s'. Reproduced from
this session's own tool log — a grep requested with timeout=60 ran the
full 1200s and died with exit 124. Three stacked root causes:
[T-cd-readonly] 'cd' was missing from READ_ONLY_TOKENS (and from
INTERACTIVE_TOKENS), so the most natural agent command shape —
'cd repo && grep … | head' — failed the read-only check, isHeavy
escalated it to forced BATCH, and the wall clock armed at 1200s.
cd/pushd/popd are pure navigation builtins; they now classify exactly
like the pipeline without the cd prefix (INTERACTIVE, fail fast).
[T-timeout-honored] All three execution paths (ExecutionCoordinator,
PersistentShell, ShellExecutor) explicitly IGNORED the caller's
timeout — each logged 'caller timeout ignored' and armed the class
wall. The tool schema promised 'Timeout in seconds (default: 900)'
while the implementation discarded it. The class ceiling stays the
authority (the old maxOf(requested, minimum) bug must not return),
but the caller may now SHORTEN the wall:
armed = max(setup floor, min(requested, class wall)) — the floor
survives because a minis-dev-setup-full killed by a short request
leaves a broken rootfs (setupFloorSurvivesAShortRequest). The guest
watchdog gets the same effective wall so the in-guest sleep and the
host withTimeoutOrNull agree on when to fire.
[T-quote-aware-split] Segment splitting was quote-blind in both
GuestWorkloadPolicy (isObviouslyReadOnly / isDiskRelief) and
BudgetClassifier.classify: a '|' inside quotes ('grep -n "a\|b"')
cut a phantom segment whose garbage leading token failed the
whitelists — read-only pipelines classified as heavy/NORMAL. Quoted
spans are blanked before splitting, the same technique
hasWriteSyntax already used.
Verified: 43-point logic simulation (new behavior + every existing
test case kept green, including the setup floor); new unit tests pin
the reported command shape (INTERACTIVE, not heavy, 60s wall, 30s
request honored), the shorten-never-extend contract, the floor, and
the quote-aware split. findIsNormalAndACallerTimeoutDoesNotChangeIt
is updated to the new contract (find stays NORMAL; a caller may
shorten).
tall-1997
force-pushed
the
fix/shell-timeout-honored
branch
from
October 13, 2026 11:55
4a38251 to
786c288
Compare
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.
用户报告
复现与根因(证据在源码 + 本会话工具日志)
本会话自己的工具日志就是现场:给命令传了
timeout=60,慢命令(大仓库 grep/find)照样跑满 1200 秒才被看门狗杀掉(exit 124)。三个叠加根因:cd不在只读白名单:cd repo && grep … | head这种最自然的命令形态,因cd缺席 READ_ONLY_TOKENS → 判非只读 →isHeavy→ HEAVY 强制升 BATCH → 墙钟 1200s。caller timeout ignored日志直接丢弃 timeout 参数。工具 schema 承诺 "Timeout in seconds (default: 900)",实现却完全不用。grep -n "a\|b"里引号内的|被当管道切出幻影段,垃圾首 token 过不了白名单 → 只读管道被判重负载。修复
cd/pushd/popd补入 READ_ONLY_TOKENS 与 INTERACTIVE_TOKENS——纯导航内建命令,cd X && grep与裸grep分类一致(INTERACTIVE,快速失败)。armed = min(requested, class wall)。类墙钟仍是上限(旧的 maxOf 扩展 bug 不复活),但调用方可以把等待收短。guest 看门狗同步拿到同一生效墙钟,宿主withTimeoutOrNull与 guestsleep一致触发。验证
callerTimeoutIsNotAnInput更新为callerTimeoutShortensButNeverExtends行为变化说明
git clone等长命令不受影响(默认 600s = NORMAL 类墙钟)