Skip to content

fix(work-board): 修正 start-task pending claim 的消费与取消 (C1/L1/T1) - #1

Open
somewan820 wants to merge 10 commits into
feat/work-board-phase3-start-taskfrom
fix/work-board-start-task-pending-claim
Open

somewan820 wants to merge 10 commits into
feat/work-board-phase3-start-taskfrom
fix/work-board-start-task-pending-claim

Conversation

@somewan820

Copy link
Copy Markdown
Owner

背景

apache#2560 Work Board Phase 3「start-task」spike(apache#4598)的待处理(pending)start-task claim 存在三个关联缺陷。本 PR 是 apache#4598 之上的一层修复,合并 apache#4598 后可将 base 重定向到 main

缺陷

C1:既有会话发送会误消费待处理 claim

app-shell-chat-actions.tssend() 有两个分支都会触发 options.onSessionResolved

  • 新会话分支:仅在 submitted.kind === 'projected' 时触发(PR 新增,有守卫)。
  • 既有会话分支:无条件触发onSessionResolved?.(sessionId),PR 未改)。

onSessionResolved 在 app-shell 中被注入为 workbar.commands.onNewTaskSessionResolved,它无条件清空 pending claim 并调用 workBoard:linkSession。后果:用户在 start-task surface 里发了一条消息后,任何既有会话再发一条消息,都会把 Work Board 条目链接到那个无关的既有会话

openNewTaskSurface 总是先 startNewSession(),所以 start-task 的接收 surface 一定是新会话,只有新会话分支才可能合法消费 claim。

L1:pending claim 没有取消路径

  • pendingWorkBoardStartRef 只在「消费」时清空:用户从看板点了 start-task 但放弃/关闭了 surface,或改在新任务 surface 里发消息失败,claim 会残留,之后某个新会话首条消息会把它错误链接进去。
  • onNewTaskSessionResolvedIPC link 完成之前就清空 claim:link 失败则 claim 丢失且无重试语义。

T1:没有任何编排测试

start→send→link 全链路、既有会话不消费、surface 替换清空、link 失败行为均无覆盖;此前只有零散的 IPC 层测试。

修复

  1. C1:移除既有会话分支对 onSessionResolved 的无条件调用(仅保留注释说明绑定关系)。新会话分支行为不变。
  2. L1
    • 新增命令 onNewTaskSurfaceStarted():新任务 surface 启动时清空旧 claim(openNewTaskSurface 通过 workbarTaskClaimRef 接入;顺序安全:startWorkBoardTask 先开 surface 再设 claim)。
    • onNewTaskSessionResolved 改为 link 完成后才释放该 claim(settle()),成功不提示、失败 toast 提示;只清空自己持有的 claim,不误清 link 在途时新产生的 claim。失败后重试 = 从看板重新发起。
  3. T1:新增 5 个测试:
    • workbar-controller:start→send→link 编排且 claim 只消费一次;NotProjected 清空后不链接;新 surface 替换清空后不链接;link 失败 toast 且释放 claim。
    • app-shell-chat-actions:既有会话 projected 发送触发 onSessionResolved(C1 回归)。

验证

  • core 771/771 · storage 1087/1095(8 skip 为既有)· desktop main 1994/1994
  • renderer + main typecheck 0 error · biome lint clean · git diff --check clean

已知残留(不在此 PR 范围)

onNewTaskSessionNotProjected 在每次发送后清空 claim(PR 原有语义):用户 start-task 后若先在既有会话发一条、再回 start-task surface 发送,claim 会先被清空导致该次不自动链接。属 apache#4598 原有行为,修复需给 onNewTaskSessionNotProjected 透传 surface 身份,超出本修复范围。

首发送结果未知时不再触发 onSessionResolved,避免误建 Work Board 持久链接;将 Work Board 编排迁入 workbar 功能,app-shell 仅通过 props 注入;workbar 控制器改用 toastApi 输入以通过主进程 tsconfig 编译;重新生成 renderer-architecture.json。
taskEntryDraftKey 的消费者均从 model/task-entry-selection.js 直接导入,feature index 的 re-export 无外部使用,knip 报未使用导出,删除之。
Work Board 启动任务 spike 在面板中引入原始 textarea 与 40px 高度,如实记录为 polish 项,使 inventory 与生成器输出一致。
- work-board-target: 移除未使用的 preferredHost 参数
- use-workbar-controller: 删除 resolveWorkBoardStartTask 包装,透传底层解析
- work-board-panel: 每行只解析一次 start-task 目标
- use-task-entry-controller: 移除 prepareWorkBoardDraft 中的重复查找与校验
- IPC linkSession 增加 scope 校验,仅允许 project 项(防御纵深)
- core 解码改为宽容模式:丢弃损坏/重复的链接条目,不再隐藏整条记录
- 补充 ambiguous/archived/scope 校验与宽容解码测试
- 修复 ipc-main 测试缩进,操作行支持换行不溢出
…task-pending-claim

# Conflicts:
#	apps/desktop/renderer-architecture.json
#	docs/astryx-surface-file-inventory.md
C1:既有会话发送不再消费绑定到新任务 surface 的 claim,避免把
任务误链接到无关会话(workBoard:linkSession 只由新会话分支触发)。

L1:新任务 surface 启动时清空旧 claim;link 完成后无论成败都释放
本 claim(失败 toast 提示,可重新从看板发起),并避免误清新 claim。

T1:补充 start→send→link 编排、既有会话不消费、surface 替换清空、
link 失败保留语义的测试。
@somewan820
somewan820 force-pushed the feat/work-board-phase3-start-task branch 13 times, most recently from ab595e5 to f96a49c Compare September 5, 2026 07:49
@somewan820
somewan820 force-pushed the feat/work-board-phase3-start-task branch from f96a49c to d88c12b Compare September 14, 2026 02:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant