feat(web-shell): add an experimental session workflow cockpit - #8583
Conversation
🖼️ web-shell visual previewRendered against a mock daemon (no real backend): the PR base vs this PR head Screenshots · before / afterFull-resolution recordings (.webm) are attached to the workflow run. — Qwen Code · web-shell visuals |
Code Coverage Summary
CLI Package - Full Text ReportCore Package - Full Text ReportFor detailed HTML reports, please see the 'coverage-reports-22.x-ubuntu-latest' artifact from the main CI run. |
|
Browser acceptance completed against the local daemon and WebShell using real persisted and live sessions. Verified:
Pre-execution and experimental-gate statesWorkflow enabled with a bound planBound plan in the full WebShell layoutWorkflow enabled without structured dataExperimental workflow disabledRunning, completed, and attention statesLive executionOne background Agent is running, one step is complete, and the two downstream steps remain blocked. Completed cockpitFailed workflow overviewHuman-in-the-loop attention queue |
The new cockpit CSS reused ad hoc border-radius (10 distinct values), color-mix opacities, and #fff literals instead of the app's existing --radius-sm/md/lg/xl scale, several of them papered over with !important where the real issue was selector specificity. This consolidates them onto a small local token set and fixes the specificity so !important is no longer needed. Also aligns the two completion-progress bars to --success-color (they were blue while every other "done" signal in the same view, and the sibling PlanExecutionView's equivalent bar, use green), and replaces a hardcoded Chinese string in the Chat/Cockpit/Workflow nav toggle with a proper i18n key so it renders correctly for non-Chinese locales. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…w-cockpit-demo # Conflicts: # packages/web-shell/client/App.test.tsx
The plan DAG lays out fixed 240px lanes with 56px gaps, so its natural width is 852px at three lanes and 1148px at four. The tasks dialog was pinned to `lg` (720px), which meant any plan past two lanes scrolled sideways inside the panel while the viewport still had room. Add an `auto` dialog size that tracks content between a 560px floor and a min(100vw - 2rem, 1120px) ceiling, and use it for the tasks dialog. Responsive rather than fluid: wide graphs still scroll, but only once the panel would outgrow the screen. `w-max` beats DialogContent's base `w-full` through tailwind-merge, which the added tests pin -- if that resolution ever changes the panel silently stops tracking content. Node state styling had two problems. Status set `border-color` while selection stacked an always-blue box-shadow ring on top, so selecting a completed (green) or blocked (amber) node gave it a green border and a blue ring at once. And nothing on `.node` transitioned -- the file had a single transition rule in 466 lines -- so every state change snapped. Drive both from one `--node-accent`/`--node-ring` pair per status, so selection reads as the same edge turned up instead of a second colour, and add border-color/box-shadow transitions with prefers-reduced-motion honoured. The blue connector dots are left alone deliberately: they belong to the edge system, which is the same blue, so colouring them by status would break that reading. Note that DialogShell.module.css still defines `.panel` and `.sizeSm` through `.sizeXl`, but DialogShell.tsx references none of them -- width is entirely Tailwind on DialogContent. That dead CSS predates this change and is left as-is. Not verified visually: Playwright browsers are unavailable in this environment and jsdom has no layout engine, so the width behaviour is confirmed only at the class level.
…w-cockpit-demo # Conflicts: # packages/web-shell/client/App.test.tsx
|
@qwen-code /resolve |
…-merge # Conflicts: # packages/web-shell/client/App.test.tsx # packages/web-shell/client/App.tsx # packages/web-shell/client/components/ChatEditor.test.tsx # packages/web-shell/client/components/sidebar/WebShellSidebar.tsx
Three defects in the dependency graph, all reachable from the demo plan in the PR description: - Every layer-spanning edge routed at the same `routeY`, so a plan with two or more long dependencies drew them on top of each other. Each now gets its own lane, ordered by span length so the longest sits furthest out and the lanes nest rather than cross. The canvas reserves exactly the room they measured. - `locateFocusTodo` called `viewport.scrollTo` from inside a requestAnimationFrame, where a throw cannot be caught and takes the surrounding render down with it. Guarded, with a scrollLeft fallback. - `running` and `completed` both mapped to --success-color, which are the two states a reader most needs to tell apart, and `blocked` mapped to --warning-color, so a healthy plan of not-yet-started nodes rendered as a wall of warnings. Completed is now the only green, in-flight work is the only blue and the only thing that animates, and blocked/ready are neutral. Status also carries a glyph so it survives greyscale and colour-blindness. The cross-layer routing test asserted a golden path string; it now asserts the behaviour it is named for. That also stops a failure there from skipping its mockRestore calls and leaking the rect spy into the next four tests.
E2E verification: session workflow cockpit (local daemon + Web Shell, real model runs)Verified locally against branch tip Plan approval stays in Chat, with a DAG preview — the pending Pending state (E2E#8) — while approval is pending, clicking the floating todo summary does not open the inspector; the approval remains reachable in Chat: Running (E2E#1/#2) — the floating Completed inspector (E2E#2/#3) — 4/4 completed, needs-attention ordered before steps; selecting a step updates its depends-on / unblocks and linked agent: Linked agent as sibling tab (E2E#4) — opening the step's agent shows its persisted transcript (prompt, stats, output) in a sibling right-panel tab; returning to Workflow preserves the selected step: Dependency canvas (E2E#5/#6) — Expand dependency graph turns the main pane into the canvas and is directly addressable via Narrow width (E2E#7) — at 800px the summary opens the inspector in the existing drawer, and the graph action opens the full canvas instead of squeezing the DAG into the drawer: Restore (design doc) — reloading a completed session restores the Workflow entry from the marked todo snapshot: |
qqqys
left a comment
There was a problem hiding this comment.
Critical-only re-review at head 5882659403 — COMMENT (not approvable at this head; blockers are CI and mergeability, not outstanding code findings)
Historical blockers — re-verified against the exact head 5882659403
The full active cluster from review rounds 17–23 was traced in the current code; every item is fixed or unreachable:
- R20-1 (foreground Agent registers the display-listener suite twice): fixed — the early registration is now gated
if (shouldRunInBackground)(agent.ts:2705); foreground registers exactly once on the resolvedruntimeEventEmitter(agent.ts:3062-3068); paths are mutually exclusive. - R17-1 (deep-equal no-op
todo_writedisplay lacks thesessionWorkflowmarker): fixed — the no-op branch stampssessionWorkflow: truewhenisSessionWorkflowTodoContextActive()(todoWrite.ts:386-393). - R21-1 / R19-1 (
sendUpdateclears the bound revision before delivery with no restore): fixed — prior revision/structure captured before the clear and restored in a catch while the session remains PLAN; the success re-stamp still requiresallPending+ PLAN (Session.ts:7311-7376). - R18-1 (
foldReloadApprovalModefolds onlyundefined): fixed —if (!raw) return AUTOfolds every falsy value, matching boot's truthiness gate; docblock corrected. - R22-1 (user-scope sibling fan-out not serialized against workspace-qualified writes): fixed — each sibling's sample+push runs under that sibling's own
withSessionWorkflowWriteLock(server.ts:2620-2650), best-effort error containment preserved; serialization witness test atserver.test.ts:4492. - R17-2 (teammate's approved
exit_plan_modestamps the session-global revision): fixed — the stamp is restricted to the root Config viaObject.getPrototypeOf(this) === Config.prototype; write-through wrapper regression test atconfig.test.ts:1281. - R15-2 lineage (sibling fan-out after the push-failure early return): fixed — fan-out runs before the
disk_changed_push_failedreturn (workspace-settings.tsuser-scope route). - R19-22 (text-only approval with a revision bound mid-flight): unreachable — ACP concurrent batches are Agent-only (
Session.ts:10747-10756);todo_write/exit_plan_modeexecute serially, so a revision cannot appear while a text-only plan approval is pending. - R20-2 (tasks joined to tools by globally non-unique
callId): fixed —linkAgentToolsthreads the parent context andtaskForToolmatchestoolUseId+parentAgentId; the flat last-wins maps are gone. - Round-18 WebShell pair: fixed —
expandWorkflowGraphexits fullscreen unconditionally after a successfulopenCockpit()(App.tsx:9753); the cockpit canvas chain is bounded (.canvasflex column +.canvas > section { min-height: 0 }) and pinned by a CSS contract test. - R19-23 (overview strip overflow at the dialog floor): no demonstrable defect —
.overviewsits inside the.overviewContainerquery container and reflows tominmax(0, 1fr)tracks at ≤760px, so the 528px content box does not overflow.
Why this is not an APPROVE
- Merge conflict — GitHub reports
CONFLICTINGagainstmainat this head. - CI is not healthy on head
5882659403:Test (ubuntu-latest, Node 22.x)— failed. The annotation reads "The self-hosted runner lost communication with the server" (infrastructure), but the job logs are unavailable (BlobNotFound), so a green unit-test result for this head is unverified.Real daemon E2E / Java 11— cancelled: "exceeded the maximum execution time of 30m0s"; no evidence attributes this to or clears it of this PR's daemon-side scope.review-prandServe A/B (ubuntu-latest, Node 22.x)— still pending.
Next step: resolve the merge conflict and re-run CI; once the checks above are green (or the failures are clearly attributed to infrastructure with logs) this can be re-reviewed for approval.
中文说明
对 head 5882659403 的 Critical-only 复核:历史各轮(17–23 轮)的全部阻塞性发现在当前代码上逐条验证为已修复或不可达(R20-1 双重注册、R17-1 无操作标记、R21-1/R19-1 投递失败恢复、R18-1 假值折叠、R22-1 兄弟扇出串行化、R17-2 根 Config 盖章、R15-2 扇出顺序、R19-22 串行执行排除、R20-2 父级作用域 join、R18 WebShell 两项、R19-23 无证据成立)。
暂不 APPROVE 的原因:① 与 main 存在合并冲突(CONFLICTING);② 当前 head 的 CI 不健康——主单测失败(自托管 runner 失联,日志不可读,无法确认测试结果)、Real daemon E2E / Java 11 超时取消(因果不明)、review-pr 与 Serve A/B 仍在 pending。建议解决冲突并重跑 CI,全绿后再复审批准。
— 衍星 (Critical-only re-review)
chiga0
left a comment
There was a problem hiding this comment.
Review — feat(web-shell): add an experimental session workflow cockpit
Scope: Triage + CI status + cross-check against 22 prior review rounds. Full diff read scoped to standing-Critical files; execution: read-only.
Current state — three independent blockers before merge
| Blocker | Detail |
|---|---|
| CI RED | Test (ubuntu-latest, Node 22.x) — step "Run tests and generate reports" failed |
| Merge conflict | mergeable: CONFLICTING — branch must be rebased onto main |
| 6 standing Criticals (probe-confirmed) | See below |
The PR has gone through 22 review rounds without closing the Critical backlog. The CI bot recommended a maintainer land-with-residual-risk risk-acceptance decision rather than another review pass.
CI status
| Check | Status |
|---|---|
| Test (ubuntu-latest, Node 22.x) | FAILURE |
| Desktop Shell (ubuntu / windows) | success |
| Integration Tests (no-AK, No Sandbox) | success |
| Dependency CVE audit / Secret scan | success |
| web-shell E2E Smoke | SKIPPED |
| Integration Tests (CLI) | SKIPPED |
| Test (macos / windows) | SKIPPED |
Standing Criticals (round 22, all probe-confirmed at current head)
Four have exact inline discussion threads (see human reviewer doudouOUC's CHANGES_REQUESTED):
R21-1 — Session.sendUpdate revision-clear race (probe-confirmed)
Session.ts:7046-7051 clears the active plan revision BEFORE await client.sessionUpdate resolves, with no catch/finally. Probe result: binding a revision then delivering a structure-changing update whose sessionUpdate rejects destroys the bound revision; the next exit_plan_mode approval proceeds unbound (text-only) with Agent/todo_write gates off. Author's own inline comment at Session.ts:7050 acknowledges the open window.
R17-1 — todo_write deep-equal no-op skips Workflow marker (probe-confirmed)
The equality check omits the Workflow marker field, so a status-only retry on an otherwise-identical write silently clears the pending revision; the next approval is unbound.
R17-2 — Child-wrapper approval stamps the session-global root revision
A plan-required child approved exit stamps session.root's revision through the write-through shim even though only the child session's plan was approved.
R22-1 — User-scope settings fan-out short-circuits on primary push failure (new this round, probe-confirmed)
server.ts:2590: after a user-scope setting is persisted, a primary live-push failure returns before the sibling-runtime fan-out loop, leaving healthy sibling sessions pinned to stale global state.
R20-1 — Foreground agent issue (agent.ts:3061); re-confirmed this round.
R18-1 — foldReloadApprovalMode overrides CLI flags (acpAgent.ts:1821); missing-key folds to AUTO even when a boot-time CLI flag outranks the file.
Cross-check against human reviewer (doudouOUC, CHANGES_REQUESTED)
doudouOUC independently confirmed four correctness blockers with inline discussion threads:
- todo_write no-op retry clears revision → R17-1 confirmed
- Child-wrapper approval stamps global root → R17-2 confirmed
- User-scope primary push failure short-circuits fan-out → R22-1 confirmed
- sendUpdate delivery/approval interleave → R21-1 confirmed
All four independently verified; no findings in prior reviews that I would refute.
Verdict
Cannot approve. Six probe-confirmed Criticals are open, CI is red, and the branch has merge conflicts. Immediate actions needed before re-review:
- Fix the Session.sendUpdate revision-clear race (R21-1) — add catch/finally to restore prior binding on failed delivery.
- Fix todo_write no-op marker check (R17-1) — include the Workflow marker in the equality predicate.
- Fix child-wrapper approval stamping global root (R17-2).
- Fix user-scope settings fan-out short-circuit (R22-1) — move fan-out outside the primary-push error path.
- Resolve merge conflict and rebase onto main.
- Ensure CI passes before requesting re-review.
Reviewed with AI assistance.
doudouOUC
left a comment
There was a problem hiding this comment.
Reviewed exact head 58826594030634246b3b1c86550bcda371369e3e.
I found no new code correctness issue on this head. I re-verified the blockers from my previous CHANGES_REQUESTED review against the current implementation: the todo_write no-op now preserves the workflow marker; child approvals can only stamp the root Config; user-scope sibling fan-out runs before the primary push-failure return and is serialized by each sibling workspace lock; and Session.sendUpdate restores the prior revision and structure when delivery rejects. I also traced the changed config fields, workflow revision state, runtime wrappers, settings routes, Agent todo_id gate, transcript projection, and Web Shell consumers.
Fresh-worktree verification completed: npm ci including prepare/build/bundle, npm run typecheck, and git diff --check passed. The changed core, ACP bridge, SDK, and Web Shell test groups passed. The CLI changed-file batch exposed shared-state failures in unmodified server.test.ts cases; every affected case passed when isolated, so I found no PR-specific test regression.
I am leaving COMMENT rather than APPROVE because this head is not merge-ready:
- GitHub reports
CONFLICTING. A trial merge with currentmainconflicts inpackages/core/src/config/config.tswhere this PRs Session Workflow additions overlap the newly merged model-proposed-goals config. The conflict resolution changes core behavior and must be reviewed on the resulting head. Test (ubuntu-latest, Node 22.x)failed because the self-hosted runner lost communication, andReal daemon E2E / Java 11was cancelled after the 30-minute limit. The unit-test logs are unavailable, so CI does not yet provide a green result for this head.Serve A/Bhas since passed;review-pris still running.
Please rebase or merge main, resolve the Config conflict by preserving both feature paths, and rerun the failed or cancelled checks. The resulting head needs a final re-review before approval. This PR also changes about 5,078 production lines across Core, CLI, and Web Shell, so the repository core gate requires explicit maintainer awareness.
…w-cockpit-demo # Conflicts: # packages/core/src/config/config.ts
|
Merged the latest Local verification on merge head
All current inline review threads are already resolved; requesting re-review for the new merge head. CI is left to the push-triggered run rather than being polled here. |
…w-cockpit-demo # Conflicts: # packages/web-shell/client/App.test.tsx # packages/web-shell/client/App.tsx
|
已将最新 本轮冲突集中在 Web Shell 的
验证结果:
Java 17 失败不是代码断言失败:GitHub annotation 明确为 self-hosted runner 与服务器失联,job 未执行任何 step,归类为基础设施故障,本轮无需代码改动。按仓库约定不等待后续 CI。 |
|
@doudouOUC All four correctness blockers from your review are addressed — the fixes landed in e22836c (after your review), current head
CI is green except the still-running |
fixed
|
Synced the PR with the latest This was a clean
Verification on the merged head:
There are no unresolved inline review threads. Existing requested-change reviews reference older heads; the previously reported correctness blockers have already been addressed and documented above. New CI/review jobs are left to the push-triggered run rather than being polled here. |
chiga0
left a comment
There was a problem hiding this comment.
第 N 轮审核 — 四项历史阻断项逐一核验
当前 head: 64f867f0 (merge from main, 2026-09-01T13:00:41Z)
主体最新提交: 33b04493d9e6 (test(cli): type workflow runtime mock, 2026-08-20)
R17-1 — 深度相等 no-op 遗漏 sessionWorkflow 标记
状态:已修复 ✓
Commit 35aae7904819 将 workflowContextActive 从函数头部(在 approvedWorkflowRevision 检查之前)移到写入后:
// 写入并检查 approvedWorkflowRevision AFTER validation passes
const continuesApprovedWorkflow = !approvedWorkflowRevision || (finalTodos.length > 0 && resultPlanId === approvedWorkflowRevision.planId);
if (!continuesApprovedWorkflow) {
this.config.clearSessionWorkflowPlanRevision?.();
}
// ...
const workflowContextActive =
continuesApprovedWorkflow &&
this.config.isSessionWorkflowTodoContextActive?.() === true;workflowContextActive 现在只有在 continuesApprovedWorkflow 为 true 时才为 true,no-op 和非 no-op 路径均使用同一变量,标记不再被遗漏。✓
R17-2 — 子配置 fromApprovedPlanExit 错误 stamp 全局 root revision
状态:已修复 ✓
config.ts setApprovalMode 中 fromApprovedPlanExit 路径:
if (
options?.fromApprovedPlanExit &&
Object.getPrototypeOf(this) === Config.prototype // ← 仅 root Config
) {
this.approveSessionWorkflowPlanRevision();
}Object.getPrototypeOf(this) === Config.prototype 精确识别 root Config 实例(new Config()),而通过 Object.create(base) 派生的子 Config 的原型链为父 Config 实例,不满足此条件。✓
注释已更新:"Only the root Session Config may stamp the session-global workflow revision; derived agent configs still clear their local plan-exit notice." ✓
R22-1 — 用户级设置 fan-out 短路,跳过后继 workspace
状态:已修复 ✓
server.ts 新增 updateSiblingSessionWorkflows:
const updateSiblingSessionWorkflows = async () => {
for (const runtime of workspaceRegistry.listAll()) {
if (runtime.primary) continue;
// Each sibling re-derives its OWN post-write effective value
await withSessionWorkflowWriteLock(runtime.workspaceCwd, () =>
runtime.bridge.invokeWorkspaceCommand(...));
}
};使用 for … of 全量遍历,无短路路径。每个 sibling 独立派生自己的有效值(comment 明确说明)。✓
另外 workspace-settings.ts(单 workspace 路径)在 experimental.sessionWorkflow 写入后同步调用 invokeWorkspaceCommand,SessionNotFoundError 被专门处理(允许继续),其他错误返回 500。✓
R21-1 — sendUpdate 在 await 前清除 revision,并发 approve 可见空 revision
状态:已按设计处理 ✓
当前 sendUpdate 的 clear-before-await 是有意为之的设计(commit c145be621a73 冻结 approved revision):
if (canUpdateTodoPlanRevision && !preservesPendingRevision) {
// Clear during delivery so a replacement cannot be approved before the client sees it.
this.clearActiveTodoPlanRevision();
}
try {
await this.client.sessionUpdate(params);
} catch (error) {
if (canUpdateTodoPlanRevision && !preservesPendingRevision && ...) {
// RESTORE on failure
this.activeTodoPlanRevision = previousActiveTodoPlanRevision;
this.config.setSessionWorkflowPlanRevision?.(previousWorkflowRevision);
}
throw error;
}Clear 在 delivery 期间防止客户端在看到新 plan 前用旧 revision 完成 approve;失败路径恢复全部状态。这是 revision 管理的正确语义,原关注点已消除。✓
新增提交(自上次 review 后)概览
| 提交 | 内容 |
|---|---|
ce36ab15 |
fix(web-shell): plan graph legibility under load |
02b397b8 |
refactor(web-shell): tighten workflow page hierarchy |
80aa051b |
fix(web-shell): explain skipped plan graph |
c145be62 |
fix(cli): freeze approved workflow revision → R21-1 |
18d7054c |
fix(cli): preserve reviewable workflow revision |
35aae790 |
fix(cli): close workflow runtime boundaries → R17-1, R22-1 |
33b04493 |
test(cli): type workflow runtime mock |
64f867f0 |
Merge remote-tracking branch 'origin/main' (head) |
新增提交均指向已识别的阻断修复,无新增阻断项。
CI 状态
头提交 64f867f0:10 success(Desktop Shell、Java SDK、分类 job 等),17 skipped。单元测试(ubuntu/macos/windows Node 22.x)因 fork/条件限制 SKIPPED,未直接执行。
结论
四项历史阻断项均已确认修复,新增提交未引入新的阻断点。Approve。
本 PR 体量较大(71 文件,+10980),建议在 merge 前在非 fork 环境触发完整 CI(Test ubuntu/macos/windows)做最终验证。
qwen-code-dev-bot
left a comment
There was a problem hiding this comment.
Reviewed at head 64f867f0.
- Followed up on last round's blockers: the branch is mergeable again, both standing CHANGES_REQUESTED reviews are dismissed, and 156/156 review threads are resolved — including the four correctness blockers from the human review, which were closed through the subsequent revision-freeze/reviewable-revision commits and were not re-raised by the later review rounds.
- Read the new deltas since the last full pass: the reload approval-mode convergence is now tracked per session (so a partially applied flip followed by a file round-trip can no longer strand already-moved sessions on the intermediate mode, with failure paths warning and retrying on the next reload), and the workflow inspector CSS no longer carries rules that defeat its own buttons — both test-pinned. The head has since only merged upstream.
- Re-verified the revision-binding core at this head (freeze/clear sites intact).
- CI on this head has no failures (Test and the remaining lanes still running); per the channel convention the call is on the review itself.

























What this PR does
Completes the experimental Session Workflow path across plan capture, revision-bound approval, transcript projection, Agent execution, and WebShell. Plan approval remains in Chat. After approval, one Workflow view reuses the existing dependency graph and adds linked Agent activity, session deliverables, and unresolved failure or cancellation actions. The view projects existing Todo, task, transcript, and artifact data; it does not add a second workflow store.
Why it's needed
The earlier prototype exposed Chat, Cockpit, and Workflow as competing destinations and rendered overlapping versions of the same plan. That made approval context, navigation, and ownership unclear. This change reduces the product model to Chat for conversation and approval, plus Workflow for execution visibility and intervention.
Reviewer Test Plan
How to verify
Evidence (Before & After)
Tested on
Environment (optional)
Local WebShell unit-test, E2E smoke, and production-build environment.
Risk & Scope
todo_writenow preservesblockedByon an active plan when a call omits it, and only clears dependencies when a call passes[]. This is deliberate — a status-only update must not silently destroy the DAG — and it is documented in the tool schema with a dedicated test, but it changestodo_writesemantics for every session, including ones with Session Workflow disabled. Calling it out here for release notes.blockedBypreservation above is behaviour-compatible for callers that always send the full dependency list, and should be noted in the release notes for callers that do not.Linked Issues
Related to #8389. Supersedes #8561.
中文说明
这个 PR 做了什么
完善实验性 Session Workflow 链路,覆盖计划捕获、版本绑定审批、会话投影、Agent 执行与 WebShell。计划审批保留在 Chat 中;审批后,单一 Workflow 页面复用现有依赖图,并补充关联 Agent 活动、Session 交付物、尚未解决的失败或取消操作。页面只投影现有 Todo、任务、会话与交付物数据,不增加第二套 Workflow 存储。
为什么需要
早期原型同时暴露 Chat、Cockpit 和 Workflow 三个并列入口,并重复渲染同一份计划,导致审批上下文、导航与功能归属不清晰。这次将产品模型收敛为:Chat 负责对话与审批,Workflow 负责执行可见性与用户介入。
Reviewer 测试计划
验证方法
证据(修改前后)
测试平台
环境(可选)
本地 WebShell 单元测试、E2E 冒烟测试与生产构建环境。
风险与范围
todo_write现在会在活跃计划上保留调用中省略的blockedBy,只有显式传[]才清除依赖。这是有意为之——纯状态更新不应悄悄毁掉 DAG——schema 有说明且有专门测试;但它改变了所有 session 的todo_write语义,包括未开启 Session Workflow 的 session。在此点名以便写入 release notes。blockedBy保留语义对总是传完整依赖列表的调用方是行为兼容的,对不这样做的调用方应在 release notes 中说明。关联 Issue
关联 #8389。#8561 已由本 PR 覆盖。