fix(cli): route the transcript turn-index handler through the pin choke point - #11047
Conversation
…ke point The #10988 guard fails the build on any direct mention of the runtime-root context runner outside the single choke point; the session turn-index page handler (from #10751) still composed the routing by hand with loadSettingsCached, the exact decision runWithPinnedRuntimeBaseDirForRequest exists to make in one place (transcript pages are listed in the choke point's own doc). Behaviour is identical: same cached settings for the same cwd, same pin; the operation never used the local settings object.
|
Thanks for the PR! Template looks good ✓ Problem: observed, not theoretical — and it is currently main's only red test. On the base commit Direction: aligned. This is a gate repair rather than a feature. The guard landed expecting only the choke point to name Size: not applicable. Approach: minimal, and I do not see a better path. The only smaller diff would be relaxing the guard test, which discards the invariant it pins. No drive-by refactors and no unrelated edits: the removed Risk: Stage 1e matches one high-risk path — Moving on to code review. 🔍 中文说明感谢贡献! 模板完整 ✓ 问题: 是已观测到的问题,不是理论性加固——而且它正是 main 目前唯一红着的测试。在 base commit 方向: 对齐。这是修门禁,不是加功能。守卫测试落地时期望只有 choke point 点名 规模: 不适用。 方案: 足够小,也想不到更好的路径。唯一更小的 diff 是放宽守卫测试,但那等于丢掉它要钉住的不变式。没有顺手重构,也没有夹带无关改动:被删掉的 风险: Stage 1e 命中一个高风险路径—— 进入代码审查 🔍 — Qwen Code · qwen3.8-max-2026-09-02 Reviewed at |
Code reviewWhat I would have done from the title and motivation alone: find the one remaining hand-composed pin in the turn-index handler and replace The diff is exactly that, and the judgement call is right. I checked the cwd provenance independently rather than taking the description's word: Semantic equivalence, traced end to end rather than assumed:
Same settings resolution, same cwd, same pin, same operation. The only deltas are one extra arrow frame and a Things that could have broken and did not:
The guard test now passes — by construction, not by hope. After the change the AST walk finds Findings: none. No correctness bug, no regression, no AGENTS.md violation. One honest observation about coverage, not a defect: the handler's behavioural tests ( Test evidenceThe decisive evidence is on the base, not the head. This PR's base SHA is main's tip So "the guard test is red on main today, and the turn-index handler's direct call is the second mention" is confirmed verbatim from main's own CI log — not from the PR description. The diff deletes precisely the line the assertion names, and nothing else fails on base that this PR could affect. On the head, Not verified: the head's own Final CI results for
One row per check name (latest run); skipped checks omitted; failures sort first. / 每个检查名一行(取最新一次运行),省略 skipped,失败项排在最前。 Sandboxed verification would settle the remaining gap: 中文说明代码审查只看标题和动机时我会怎么做: 找到 turn-index handler 里最后一处手工组合的 pin,把 diff 正是如此,且这个判断是对的。我没有采信 PR 描述,而是自己查了 cwd 的来源: 语义等价(是完整追出来的,不是假设的):改动前后最终都走到同一个 可能出问题但实际没有的地方:
守卫测试现在是构造性通过的。 改动之后,AST 遍历在 acpAgent.ts 里只会在两处遇到 结论:没有发现问题。 无正确性缺陷、无回归、无 AGENTS.md 违规。关于覆盖率有一点如实说明(不是缺陷):该 handler 的行为测试( 测试证据决定性证据在 base 上,不在 head 上。本 PR 的 base SHA 就是 main 的 tip 所以"守卫测试今天在 main 上是红的,且 turn-index handler 的直接调用是第二处点名"这一点,是从 main 自己的 CI 日志里逐字确认的,不是来自 PR 描述。diff 删掉的正是断言点名的那一行,base 上也没有其他失败会受本 PR 影响。 在 head 上, 未验证:head 自身的 沙箱验证可以补上剩下的缺口: — Qwen Code · qwen3.8-max-2026-09-02 Reviewed at |
|
Confidence: 5/5 — about as tight as a review gets: main's own CI log names the exact line this diff deletes, and the replacement is provably the same call. My independent proposal and this diff are the same change, including the one judgement call (per-request form, because the handler's cwd comes from How main actually went red — worth recording, because it changes the story slightly and it is not what the description says. The description frames this as a handler That is a non-blocking observation for whoever owns the gate, not a criticism of this PR: a source-text guard cannot be enforced across concurrent branches, and since On the maintain-it-in-six-months question: thank, not curse. The handler now reads exactly like its two siblings in the same class, and the file has one place that composes the routing instead of two. Being explicit about the pushover check, since this is the profile where a rubber stamp is likeliest — an admin author with 18 open PRs, a 2-line semantic diff, and a description that reads plausibly. The approval does not rest on any of that. It rests on the failing assertion quoted verbatim from main's CI log naming line 9200, the AST-walk arithmetic showing the array collapses to the single expected entry after the change, and a traced call chain. I looked for a reason to say no and the only candidate — that the guard test itself is an unusual thing to ship — is a question about My one real reservation is timing, not content: the head's 中文说明Confidence: 5/5 —— 证据 tight 到几乎没得挑:main 自己的 CI 日志点名的正是本 diff 删掉的那一行,而替换后的调用可证明与原调用完全相同。 我独立想到的方案与这个 diff 是同一个改动,包括那个唯一需要判断的点(用 per-request 形式,因为该 handler 的 cwd 来自 main 究竟是怎么变红的 —— 值得记下来,因为它与描述的说法略有不同。描述把这件事写成 这一点对门禁的负责人来说是一个非阻塞的观察,不是对本 PR 的批评:源码文本级守卫无法在并发分支之间强制执行,而且本仓库的 关于"六个月后维护它"这个问题:会感谢作者,不会骂。该 handler 现在与同类里的两个同级 handler 读起来完全一致,而且文件里组合路由的地方从两处变成一处。 明确说明一下"是否太好说话"这项检查,因为这正是最容易被盖章通过的情形——admin 作者、18 个 open PR、2 行语义改动、描述读起来也很合理。但本次批准不建立在任何这些之上。它建立在:从 main 的 CI 日志里逐字引出的、点名第 9200 行的失败断言;AST 遍历的推导——改动后数组收敛为唯一的期望项;以及完整追出来的调用链。我找过说不的理由,唯一的候选是"守卫测试本身这种东西是否该上线",但那是对已合并的 我唯一真正的保留是时机而非内容:抓取时 head 的 — Qwen Code · qwen3.8-max-2026-09-02 Reviewed at |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Reviewed. Suggestions are inline.
Not explored to full depth (tool budget reached): "agent 6c": running the guard test in packages/cli (vitest) — packages/core/dist is absent in this worktree so the suite's globalSetup guard would block the run, and a ….
中文说明
已审查。 建议见行内评论。
未探索到全部深度(达到工具调用预算):"agent 6c":running the guard test in packages/cli (vitest) — packages/core/dist is absent in this worktree so the suite's globalSetup guard would block the run, and a …。
— qwen3.8-max via Qwen Code /review (v0.23.0)
The choke-point guard permits the scoped-settings shape, so an edit back to this.runWithPinnedRuntimeBaseDir(this.settings, cwd, ...) would stay green without a behavioural test; mirror the six sibling routing tests. Also add the turn-index handler to the choke point's normative handler roster.
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Not reviewed: build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally.
中文说明
未审查(原文为英文):build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally.
— qwen3.8-max via Qwen Code /review (v0.23.0)
qqqys
left a comment
There was a problem hiding this comment.
APPROVE (verified at head dba1ac7)
What this change actually is
At head, runWithPinnedRuntimeBaseDirForRequest resolves settings via loadSettingsCached(cwd) and delegates through the pass-through wrapper runWithPinnedRuntimeBaseDir to the same runWithAcpRuntimeOutputDir(settings, cwd, op) the handler called directly before — so this is a behavior-preserving consolidation, not a semantic fix: it removes the last hand-composed instance of the routing pattern that #10095 established the choke point to eliminate, which is precisely what makes it safe. I verified the equivalence against both definitions at head (acpAgent.ts:4591 and :4609) and confirmed the surrounding InvalidSessionTranscriptCursorError catch, the pre-read flush, and the reader construction are byte-identical inside the moved closure.
Historical items
Round-1's two findings were both Suggestions, and both are fixed in this exact head's code, not just marked resolved: the behavioral per-request routing test now exists (mirroring the six siblings, and it genuinely discriminates — the assertions on loadSettings(cwd) and the pin receiving the per-request settings object would fail on the boot-cache shape the AST guard permits), and the choke point's normative roster comment now lists all seven handlers including "transcript turn index". The round-2 pass at head posted zero findings.
CI at head
- 23 checks green including
Lint & StaticandIntegration Tests (no-AK);Test (ubuntu-latest)is still in progress (never gates per policy); theIntegration Tests (CLI, No Sandbox)and macOS/Windows lanes were route-skipped, and one duplicateroutemeta-run was cancelled while the others succeeded — none attributable to this two-file change.
|
@qwen-code /triage |
|
Sandboxed verification: ✅ passed — merge-ready (agent verdict) - workflow run Ran the PR in an isolated, token-free container: A/B against the base build, mock-free harness assertions, targeted gates. Advisory evidence for human reviewers — not a review, an approval, or a CI check. Scripted assertions: 65 passed · 0 failed · 65 total Flakiness gate: ✅ 1 changed test file(s) x 5 identical rounds, no divergence 中文 — 判定:✅ 通过 · 可合入(agent 判定)沙箱验证在隔离、无凭证的容器中执行了该 PR 的代码(与 base 构建 A/B 对照、无 mock harness 断言、定向门禁)。仅作为评审证据,不构成评审、批准或 CI 检查。 脚本断言:65 通过 · 0 失败 · 65 总计 抖动门:✅ 1 changed test file(s) x 5 identical rounds, no divergence Verification reportPR #11047 — deep verificationVerdict: 中文摘要结论: A/B 结论(核心主张成立):守卫测试 行为不变(端到端实证):起了真实 ACP 子进程(tsx 直跑 TS 源码,零 mock),boot 在 新增测试的定位(重要澄清,非缺陷):新测试在 base 上同样是绿的,因此它并不区分本 PR 的两臂——它不是这次改动的「回归捕手」,守卫测试才是。但它并非空转:更细的变异证明它精确钉住了它名字所声称的 bug 类(用 覆盖普查(正向发现):把同样的 stale-cache pin 逐个注入 choke point 文档列举的全部 7 个 per-request handler,结果 7/7 全被杀。本 PR 之前,turn-index 是七者中唯一没有行为级 pin 的;这个 PR 正好补齐了这个不对称。见图 findings(均非阻塞):新测试 mock 的 未覆盖范围:逐 commit 归因(depth-2 浅克隆,元数据 2 个 commit 只有 Central claim + A/BCentral claim. Per-request runtime-root pinning has one choke point, guarded by a The claim has two halves and they were tested differently: the gate half by A/B on the Cells — the gate flipsThe base worktree could not run vitest at all (the repo's
C2's failure message is the intended expected-vs-actual assertion, not an import or compile Whole-file counts ( C4 is the interesting cell. The new test passes on base too, so it does not Mutation matrix — what each test actually pinsEach mutant changes one thing in
Two conclusions the two-cell A/B alone could not reach:
Real-wire A/B — behaviour preservation, with a positive controlReviewer Test Plan steps 2 and 3 were executed against a real ACP child process driven The oracle is a runtime-root discriminator. The child boots in
Test Plan step 3 (structured errors survive the routed call), identical on all three arms:
Paging with Coverage census — the invariant is now pinned for all seven handlersThe choke point's doc comment enumerates seven per-request handlers that must use the
Every mutant broke exactly the one test named for its handler (M8 aside, which also breaks CorrectionsThe description's local-failure caveat does not reproduce here. It states that "two This is a correction to the description, not a request to change the code. FindingsNon-blocking. None of them affects a single assertion above, and all three were measured 1. Suggestion — the new test's mocked return value is the wrong page shape
{ sessionId, records: [], hasMore: false, gaps: [], startTime: 'start', lastUpdated: 'end' }That is the field set of The neighbouring turn-index test at Impact is limited and worth stating precisely: the test's assertions only inspect which 2. Nit — the doc-comment reflow leaves an orphan lineThe comment edit at
3. Observation, not a defect — the guard test is spelling-onlyRecorded so the invariant is not over-trusted: M2 (pin with Targeted gatesAll run against the two changed files / the affected workspace, each with a live probe first
The first eslint live probe was mis-designed — it planted an exported unused const, which No repo-wide gate is claimed: only Not covered
MethodologyEverything ran in the CI verify container at the merge-ref checkout, against the Flakiness gate logEvidence imagesHarness scripts and raw logs are in the workflow run artifacts (7-day retention). — Qwen Code · sandboxed verification |
|
@qwen-code /resolve |
|
Qwen Code resolved the merge conflicts and pushed the branch update. Merge resolution — PR #11047Root causemain's #11036 ( Textual or semanticSemantic — both sides rewrote the same Resolution keeps main's shape — it matches the sibling handlers ( const readTurnIndexPage = async () => {
if (rawSnapshot === undefined) { /* flush live session recording */ }
return (await new SessionTranscriptReader(cwd).readTurnIndexPage(
sessionId, { /* snapshot/start/limit */ },
)) as unknown as Record<string, unknown>;
};
return await this.runWithPinnedRuntimeBaseDirForRequest(cwd, readTurnIndexPage);What is load-bearing
What I could not verifyNo build/tests were run. Post-merge, 中文说明冲突根因main 上的 #11036( 文本冲突还是语义冲突语义冲突——两边改写了同一段 解决时保留 main 的形态:它与相邻处理器( 关键点
无法验证的部分按指令未运行构建/测试。合并后 |
|
Qwen Code review did not complete successfully. The review pipeline failed before a review could be posted. A transient error is retried automatically; if you are seeing this, retry with |
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
中文说明
— qwen3.8-max via Qwen Code /review (v0.23.0)
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Not reviewed: coverage — could not read the agents' transcripts (no subagent transcripts at /home/github-runner/actions-runner-hk1-3/_work/_temp/qwen-home/projects/-home-github-runner-actions-runner-hk1-3--work-qwen-code-qwen-code/subagents/e4776ba9-11a6-40ca-b1e3-ef788d29ee8a (ENOENT: no such file or directory, scandir '/home/github-runner/actions-runner-hk1-3/_work/_temp/qwen-home/projects/-home-github-runner-actions-runner-hk1-3--work-qwen-code-qwen-code/subagents/e4776ba9-11a6-40ca-b1e3-ef788d29ee8a'). The harness writes one per agent; if there are none, either no agents ran or the harness could not write them.), so this run cannot show that any of the diff was read.
Not reviewed: verification — could not check that Step 4 and Step 5 ran (no subagent transcripts at /home/github-runner/actions-runner-hk1-3/_work/_temp/qwen-home/projects/-home-github-runner-actions-runner-hk1-3--work-qwen-code-qwen-code/subagents/e4776ba9-11a6-40ca-b1e3-ef788d29ee8a (ENOENT: no such file or directory, scandir '/home/github-runner/actions-runner-hk1-3/_work/_temp/qwen-home/projects/-home-github-runner-actions-runner-hk1-3--work-qwen-code-qwen-code/subagents/e4776ba9-11a6-40ca-b1e3-ef788d29ee8a'). The harness writes one per agent; if there are none, either no agents ran or the harness could not write them.).
中文说明
未审查:覆盖情况——无法读取 agent 的运行记录(no subagent transcripts at /home/github-runner/actions-runner-hk1-3/_work/_temp/qwen-home/projects/-home-github-runner-actions-runner-hk1-3--work-qwen-code-qwen-code/subagents/e4776ba9-11a6-40ca-b1e3-ef788d29ee8a (ENOENT: no such file or directory, scandir '/home/github-runner/actions-runner-hk1-3/_work/_temp/qwen-home/projects/-home-github-runner-actions-runner-hk1-3--work-qwen-code-qwen-code/subagents/e4776ba9-11a6-40ca-b1e3-ef788d29ee8a'). The harness writes one per agent; if there are none, either no agents ran or the harness could not write them.),本次运行无法证明 diff 的任何部分被读过。
未审查:验证——无法检查步骤 4 与步骤 5 是否运行(no subagent transcripts at /home/github-runner/actions-runner-hk1-3/_work/_temp/qwen-home/projects/-home-github-runner-actions-runner-hk1-3--work-qwen-code-qwen-code/subagents/e4776ba9-11a6-40ca-b1e3-ef788d29ee8a (ENOENT: no such file or directory, scandir '/home/github-runner/actions-runner-hk1-3/_work/_temp/qwen-home/projects/-home-github-runner-actions-runner-hk1-3--work-qwen-code-qwen-code/subagents/e4776ba9-11a6-40ca-b1e3-ef788d29ee8a'). The harness writes one per agent; if there are none, either no agents ran or the harness could not write them.)。
— qwen3.8-max via Qwen Code /review (v0.23.0)
qwen-code-ci-bot
left a comment
There was a problem hiding this comment.
Not reviewed: build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally.
Not reviewed: reverse audit — stopped before round 3 by the review time budget.
Deferred under the convergence posture (round 4, not a blocker) — recorded, not requested in this round:
packages/cli/src/acp-integration/acpAgent.test.ts:15335 — [probe] turn-index routing test stubs the record-page shape (records/hasMore/gaps) and asserts only toBeDefined(), so the stub is not load-bearingpackages/cli/src/acp-integration/acpAgent.test.ts:15343 — [probe] test witnesses the pin's arguments but never its effect — hoisting the reader construction out of the pinned scope keeps all 622 tests greenpackages/cli/src/acp-integration/acpAgent.test.ts:15352 — [probe] comment claims a live session in the boot workspace; the fixture creates none, so the pre-read flush branch is uncoveredpackages/cli/src/acp-integration/acpAgent.test.ts:15334 — [probe] AST guard permits this.runWithPinnedRuntimeBaseDir(this.settings, cwd, ...), so the invariant rests on one bespoke test per handlerpackages/cli/src/acp-integration/acpAgent.ts:4583 — [probe] PR title and 'Why it's needed' describe a routing change and a red gate this residual diff does not contain — main's #11036 landed both
中文说明
未审查(原文为英文):build-and-test — Integration Tests (CLI, No Sandbox) was skipped in CI and its suite did not run locally.
未审查:反向审计——评审时间预算不足,未能开始第 3 轮。
收敛姿态下延后(第 4 轮,非阻断)——已记录,本轮不要求修改:共 5 条(原文未翻译,列表见上方英文部分)。
— qwen3.8-max via Qwen Code /review (v0.23.0)
|
@qwen-code /triage |
|
Sandboxed verification: ❌ not passed — findings reported (agent verdict) - workflow run Ran the PR in an isolated, token-free container: A/B against the base build, mock-free harness assertions, targeted gates. Advisory evidence for human reviewers — not a review, an approval, or a CI check. Scripted assertions: 70 passed · 0 failed · 70 total Flakiness gate: ✅ 1 changed test file(s) x 5 identical rounds, no divergence 中文 — 判定:❌ 不通过 · 报告了发现(agent 判定)沙箱验证在隔离、无凭证的容器中执行了该 PR 的代码(与 base 构建 A/B 对照、无 mock harness 断言、定向门禁)。仅作为评审证据,不构成评审、批准或 CI 检查。 脚本断言:70 通过 · 0 失败 · 70 总计 抖动门:✅ 1 changed test file(s) x 5 identical rounds, no divergence Verification report<!-- qwen-triage:verify --> Sandboxed verification: Ran the PR in an isolated, token-free container: A/B against the base build, mock-free mutation harnesses, targeted gates. Advisory evidence for human reviewers — not a review, an approval, or a CI check. Scripted assertions: 70 passed · 0 failed · 70 total Verdict: The code in this PR is verified good and safe to merge — but the PR no longer does what its 中文摘要结论: 核心变化(与上一轮不同):本 PR 描述的生产改动已经合入 main。在验证 base( A/B 结论(见「中央 A/B」表与图 新测试的价值(见「变异矩阵」表与图 findings:① PR 的标题/commit 类型( 未覆盖范围:逐 commit 归因( Previous-round findings, re-measured at the new head
Central claim + A/BCentral claim as written by the PR: per-request runtime-root pinning has one choke point guarded What is true at the verified base: the routing is already in The claim therefore splits into a stale half (the fix, already in main) and a live half (the Cells — the gate does not flip, and the gate is provably live
P1 is the control that makes C1 meaningful: without it, "green at base" could have meant a dead gate. Mutation matrix — what the PR's remaining diff is worthEach mutant is a uniqueness-checked single-point edit of
Two conclusions the two-cell A/B could not reach:
Sibling census — the invariant is now pinned for all seven handlersWitness:
Every sibling broke exactly its own named test — no collateral in the filtered collection. At base the Corrections
FindingsNon-blocking unless stated. None affects any assertion above. 1. Suggestion — the PR's title, commit type and stated purpose no longer match its diffThe title is Consequences a reviewer should weigh: a The code itself is not the problem: the added test is verified load-bearing ( Minimal suggested edit (measured against the same harnesses)Retitle to 2. Suggestion (carried from round 1, stands) — the new test's mocked return value is the wrong page shape
3. Nit (carried from round 1, stands) — the doc-comment reflow leaves an orphan line
4. Observation (carried from round 1, stands) — the guard test is spelling-onlyM2 and M3 leave the guard green on both test files because neither names 5. Observation, new, pre-existing — two turn-index error kinds have no assertion anywhere
Not covered
MethodologyEverything ran in the CI verify container at the merge-ref checkout against the already-installed Flakiness gate logEvidence imagesHarness scripts and raw logs are in the workflow run artifacts (7-day retention). — Qwen Code · sandboxed verification |
qqqys
left a comment
There was a problem hiding this comment.
APPROVE (verified at head 2b80865 — re-review of the moved head; the previous approval at dba1ac7b was procedurally dismissed by the merge commit, not by any new finding)
State after the merge
The merge of main brought in #11036, which landed the same production routing this PR introduced — so the PR's net delta against current main is now exactly two items: the normative roster comment (7 handlers enumerated, matching the 7 call sites of runWithPinnedRuntimeBaseDirForRequest at head) and the behavioral per-request routing test for the turn-index handler. I verified at head that the handler routes through the choke point (acpAgent.ts:9219) and that the AST guard's load-bearing property holds: runWithAcpRuntimeOutputDir has exactly one direct call — the shared delegation at :4596 — so the guard the previous main-red satisfied by two merged fixes, not by this PR's diff alone, and nothing here breaks it.
Historical items
Round 1's two Suggestions were both fixed at dba1ac7b (the routing test — still present and passing against the merged shape since the test drives extMethod(sessionTurnIndex) end to end through the same code path #11036 shipped — and the roster completion). The three bot rounds at this exact head posted zero findings (no Critical in any ledger), and a human maintainer approved this head before this pass.
CI at head
23 checks green, zero failures; Test (ubuntu-latest) and web-shell E2E Smoke show this week's recurring shared-pool cancellations (cancellation, not failure, on a diff that is comment + test), non-gating per policy.
yiliang114
left a comment
There was a problem hiding this comment.
Review pass on head 2b80865. Context: the handler routing itself already landed on main via issue#11036 (eaef97e), so after this branch merged main the remaining diff is exactly the two pieces main still lacks — the regression test pinning that sessionTurnIndex resolves settings per request (loadSettings called with the request cwd, and the pin receiving the per-request settings object rather than the boot-workspace cache, the #10095 bug class), and the choke-point doc roster gaining 'transcript turn index'. The test follows the established per-request mock pattern used by the sibling handler tests (loadSettingsCached passes through to loadSettings), so it is consistent with the current main implementation. Note: Test (ubuntu) and web-shell E2E Smoke show cancelled on this head rather than green; the merge queue will re-verify required checks on the merge result.












What this PR does
The per-request runtime-root pinning has a single choke point: one private method that composes the settings-to-cwd routing, with a guard test that fails the build if any other line in the agent names the underlying context runner directly. One handler still composed the routing by hand — the session transcript turn-index page reader — loading the settings for the caller-supplied working directory and calling the context runner itself. This routes that handler through the per-request choke-point form, which resolves the settings for the request's cwd in one place, exactly as the choke point's own documentation lists for transcript page handlers.
Why it's needed
The guard test is red on
maintoday: it enumerates every direct mention and expects only the choke point itself, so every PR inheritingmainfailsTest (ubuntu-latest)on this assertion. The hand-composed call is also the bug class the choke point exists to prevent — a handler deciding by itself which settings pin the operation — so routing it through the per-request form both clears the gate and restores the invariant the guard protects. Behaviour is unchanged: the per-request form resolves the same cached settings for the same cwd and pins identically; the handler's operation never used the locally loaded settings object.Reviewer Test Plan
How to verify
session/transcript/turnIndexPageor the equivalent ACP request) against a daemon with a session that has recorded turns: paging withstart/limitand a snapshot cursor returns the same pages as before this change.Evidence (Before & After)
Before: the choke-point test fails on
mainwith the turn-index handler's direct call listed as a second mention; after: the test passes and the mention list contains only the choke point. The handler's own behaviour is covered by the existing transcript navigation tests, which stay green.Tested on
Environment (optional)
Local unit run of the agent test file plus lint, formatting and type checks.
Risk & Scope
maincheckout in this environment (an env-parsing case and a status-snapshot case) and pass in CI; they are untouched here.Linked Issues
None; clears the red guard test inherited from #10988.
中文说明
这个 PR 做了什么
每次请求的 runtime-root pin 有一个单一 choke point:一个私有方法负责组合 settings 到 cwd 的路由,并有守卫测试——agent 里任何其他行直接点名底层 context runner 即构建失败。仍有一个 handler 手工组合路由:会话 transcript turn-index 分页读取器——它自己为调用方提供的 cwd 加载 settings 并直接调用 context runner。本 PR 让该 handler 走 per-request 形式的 choke point(由它在一处解析请求 cwd 的 settings),与 choke point 自身文档为 transcript page handler 列出的做法一致。
为什么需要
该守卫测试今天在
main上是红的:它枚举所有直接点名并只期望 choke point 自身,因此每个继承main的 PR 都会在Test (ubuntu-latest)上因这条断言失败。手工组合调用也正是 choke point 要防止的 bug 类(handler 自行决定用哪份 settings pin 操作),改走 per-request 形式既清门禁又恢复守卫所保护的不变式。行为不变:per-request 形式对同一 cwd 解析同样的缓存 settings 并同样 pin;handler 的 operation 从未使用本地加载的 settings 对象。审阅测试计划
如何验证
start/limit与 snapshot 游标的分页应返回与本改动前相同的页。证据(前后对比)
改动前:choke point 测试在
main上失败,列出 turn-index handler 的直接调用为第二处点名;改动后:测试通过,点名列表只剩 choke point。handler 自身行为由既有 transcript navigation 测试覆盖,保持绿。测试环境
环境(可选)
本地跑 agent 测试文件,加 lint、格式化与类型检查。
风险与范围
main上本地失败(env 解析与 status 快照用例),在 CI 上通过;此处未触碰。关联 Issue
无;清除继承自 #10988 的红色守卫测试。