feat(desktop): warn that deleting a parent keeps and archives its subtasks - #3781
feat(desktop): warn that deleting a parent keeps and archives its subtasks#3781liuxiaocs7 wants to merge 3 commits into
Conversation
|
The gap is real — archived rows labelled 原父任务已删除 appearing with no warning is confusing, and telling people beforehand is the right fix. One note on how, non-blocking. [P2] The count is a second implementation of the Host's plan, and already disagrees
One of them can't be implemented here. The Host filters Parent resolution differs. Both skew high. Normal user path, display-only, recoverable — hence P2. The smaller shapeThe toast doesn't need an estimate at all. By then the Host has executed its plan and knows the real number; having For the confirm, I'd drop the number. Nobody decides differently between "3 subtasks will be kept and archived" and "5" — what matters is the fact that they survive. Without the number, If you'd rather keep an exact count in the confirm, that needs a removal-plan preview from the Host — a new operation, but then the renderer stops guessing. Your call; I'm fine either way, just not with a number that can be wrong. 简体中文这个缺口是真的——归档列表里冒出标着「原父任务已删除」的行却毫无预告,确实让人困惑,提前告知是对的解法。关于怎么做有一条意见,不阻塞。 [P2] 这个数字是 Host 计划的第二次实现,而且已经不一致
其中一条在这里实现不了。 Host 在两处过滤 父级判定不同。 两条都让数字偏大。正常用户路径,纯显示,可恢复——所以是 P2。 更小的形状toast 那半边根本不需要估算。到那时 Host 已经执行完计划,知道真实数字;让 confirm 那半边,我会把数字去掉。没有人会因为「3 个子任务会被保留并归档」和「5 个」而做出不同决定——重要的是它们会存活这个事实。不带数字的话, 如果你更希望 confirm 里保留精确数字,那需要 Host 提供一次 removal-plan preview——多一个操作,但渲染层不再猜。你定;两种我都可以,只是不希望留一个可能是错的数字。 |
Astro-Han
left a comment
There was a problem hiding this comment.
I reviewed this head and found no blocking issues.
Deleting a parent now correctly warns that ordinary subtasks are retained and archived (count via live catalog, deduplicated, excluding graph operators), matching Host readRemovalPlan. No new state or protocol; notifications now match the post-delete visible row.
No P0-P3.
简体中文
该头未发现阻断。Addresses review on apache#3781: the renderer's countArchivableSubtasks was a second implementation of the Host's removal plan and diverged from it (the conversationCopy 'preparing' filter is unimplementable off SessionSummary, and the parent-link fallback reads a field the Host ignores), so the confirm could name a subtask count that was wrong. Drop the number from the confirm — it now warns only that linked subtasks are kept and moved to Archived, the fact nobody decides differently about — and reduce the renderer helper to a presence check. The completion toast now reports the Host's executed count: the session.remove result carries archivedSubtaskCount (present only when it archived something), deduplicated by revision family in the coordinator, threaded through removeSession, the sessions:remove IPC, and the preload bridge to the toast. Deletion semantics are unchanged. Generated-by: Claude Code
|
Thanks — took the smaller shape (see the latest revision on the branch). Toast: Confirm: dropped the number. It now warns only that linked subtasks are kept and moved to Archived — the fact that they survive. Both divergences you flagged are moot now — the renderer no longer re-derives the plan, so the Also rebased onto current 简体中文多谢——按更小的形状改了(见分支上的最新一版)。 toast: confirm:去掉了数字。现在只警告子任务会被保留并移入归档这个事实。 你指出的两条不一致现在都不成立了——渲染层不再重新推导计划,所以那条实现不了的 另外已 rebase 到最新 |
Addresses review on apache#3781: the renderer's countArchivableSubtasks was a second implementation of the Host's removal plan and diverged from it (the conversationCopy 'preparing' filter is unimplementable off SessionSummary, and the parent-link fallback reads a field the Host ignores), so the confirm could name a subtask count that was wrong. Drop the number from the confirm — it now warns only that linked subtasks are kept and moved to Archived, the fact nobody decides differently about — and reduce the renderer helper to a presence check. The completion toast now reports the Host's executed count: the session.remove result carries archivedSubtaskCount (present only when it archived something), deduplicated by revision family in the coordinator, threaded through removeSession, the sessions:remove IPC, and the preload bridge to the toast. Deletion semantics are unchanged. Bump RUNTIME_HOST_COMPATIBILITY_EPOCH to 50: older peers reject the new optional field on the closed removed-result shape. Generated-by: Claude Code
70afc15 to
d70366e
Compare
Addresses review on apache#3781: the renderer's countArchivableSubtasks was a second implementation of the Host's removal plan and diverged from it (the conversationCopy 'preparing' filter is unimplementable off SessionSummary, and the parent-link fallback reads a field the Host ignores), so the confirm could name a subtask count that was wrong. Drop the number from the confirm — it now warns only that linked subtasks are kept and moved to Archived, the fact nobody decides differently about — and reduce the renderer helper to a presence check. The completion toast now reports the Host's executed count: the session.remove result carries archivedSubtaskCount (present only when it archived something), deduplicated by revision family in the coordinator, threaded through removeSession, the sessions:remove IPC, and the preload bridge to the toast. Deletion semantics are unchanged. Bump RUNTIME_HOST_COMPATIBILITY_EPOCH to 50: older peers reject the new optional field on the closed removed-result shape. Generated-by: Claude Code
d70366e to
71462f1
Compare
Addresses review on apache#3781: the renderer's countArchivableSubtasks was a second implementation of the Host's removal plan and diverged from it (the conversationCopy 'preparing' filter is unimplementable off SessionSummary, and the parent-link fallback reads a field the Host ignores), so the confirm could name a subtask count that was wrong. Drop the number from the confirm — it now warns only that linked subtasks are kept and moved to Archived, the fact nobody decides differently about — and reduce the renderer helper to a presence check. The completion toast now reports the Host's executed count: the session.remove result carries archivedSubtaskCount (present only when it archived something), deduplicated by revision family in the coordinator, threaded through removeSession, the sessions:remove IPC, and the preload bridge to the toast. Deletion semantics are unchanged. Bump RUNTIME_HOST_COMPATIBILITY_EPOCH to 50: older peers reject the new optional field on the closed removed-result shape. Generated-by: Claude Code
71462f1 to
f2b4bcb
Compare
Addresses review on apache#3781: the renderer's countArchivableSubtasks was a second implementation of the Host's removal plan and diverged from it (the conversationCopy 'preparing' filter is unimplementable off SessionSummary, and the parent-link fallback reads a field the Host ignores), so the confirm could name a subtask count that was wrong. Drop the number from the confirm — it now warns only that linked subtasks are kept and moved to Archived, the fact nobody decides differently about — and reduce the renderer helper to a presence check. The completion toast now reports the Host's executed count: the session.remove result carries archivedSubtaskCount (present only when it archived something), deduplicated by revision family in the coordinator, threaded through removeSession, the sessions:remove IPC, and the preload bridge to the toast. Deletion semantics are unchanged. Bump RUNTIME_HOST_COMPATIBILITY_EPOCH to 50: older peers reject the new optional field on the closed removed-result shape. Generated-by: Claude Code
f2b4bcb to
a3432eb
Compare
Astro-Han
left a comment
There was a problem hiding this comment.
Update on a3432eba7e:
[P2] Deletion warning uses missing graph marker — false archive promise
parentHasArchivableSubtasks() checks session.subagentParent.graph, but catalog projection strips it to {parentSessionId} only; renderer always takes fallback and claims subtasks will be archived, while Host actually retires graph children with count 0 — dialog contradicts execution.
Fix: carry graph/operator marker through catalog authority to renderer (bump epoch) or make this a Host-owned preflight with real projection test.
Checks on a3432eba7e930ebbea11c2b4681f2ea41bf6584d are test: SUCCESS (32876519613) — code is NO-GO.
简体中文
删除提示与实际执行不一致。
Astro-Han
left a comment
There was a problem hiding this comment.
Update on 15dd64a11f:
[P2] Preview is fail-open and not bound to remove plan
app-shell-session-row-actions.ts:170-185 swallows preview errors and proceeds with 0 count; protocol carries only sessionId without revision/digest. Race: preview says no archivable children, but by confirm time a subtask was unarchived or preview transiently failed — delete silently archives without warning, contradicting the confirmation purpose.
Fix: fail-closed on preview error or show uncertainty, and bind revision/plan digest to remove with re-confirm on change.
Prior graph-only P2 is now closed (Host preview returns 0). Hosted test: IN_PROGRESS — not green.
简体中文
确认预览与执行脱节。|
Fixed on the latest head ( Confirmed: the catalog projection carries a linked child as Fix: the renderer stops re-deriving the plan entirely. A read-only Epoch 51 covers this round (the removed-result field plus the new query). Checks are green on 简体中文已在最新 head( 已核实:catalog 投影把链接子任务表示为 修法:渲染层彻底不再推导计划。新增只读的 epoch 51 覆盖本轮(removed 结果新字段 + 新查询)。 |
|
Need rebase! |
15dd64a to
be094cb
Compare
Astro-Han
left a comment
There was a problem hiding this comment.
Update on be094cb043:
[P2] Preview fail-open plus batch purge bypass
- Rows:
session-row-actions.ts:177-188swallows preview errors as 0 and shows delete confirm without archive warning, while remove may still archive linked subtasks; no revision binding. - Batch:
tasks-settings-pagepurgePaths omit HostarchivedSubtaskCountpreview and toast, silently archiving active subtasks.
Fix: fail-closed or warn on preview error, bind plan token, and gate bulk purges via Host preview.
Checks on be094cb043dcebbdeda1a7357b663950a681952f are test: IN_PROGRESS — not green.
简体中文
批量删除绕过归档预览。|
Addressed the two concrete gaps on the latest head ( ① Preview fail-open → fail-safe. The confirm no longer swallows a preview error as "0 subtasks". On preview failure it falls back to an uncertain note — "Its linked subtasks, if any, will be kept and moved to Archived." — so it never silently hides that subtasks may survive. The delete still proceeds (a transient preview hiccup shouldn't block deletion), and the toast reports the Host's executed count afterwards. ③ Bulk purge. ② Plan-token binding / re-confirm — I'd argue against it here. The confirm is a best-effort heads-up before an action that, for the subtasks, is non-destructive — they're kept and archived, not deleted. The authoritative account is the post-delete toast, which reports the Host's executed count and is correct by construction. So even in the race you describe (a child unarchived between preview and remove), the user is still told the true number immediately after — the outcome isn't hidden, only the pre-confirm estimate is momentarily stale. With ① in place, the "preview unavailable" sub-case is also covered. A plan-digest token + a new 简体中文最新 head( ① 预检 fail-open → fail-safe。 确认弹窗不再把预检错误吞成「0 个子任务」。预检失败时改为显示不确定提示——「其链接的子任务(如有)不会被删除,将保留并移入归档。」——绝不静默隐藏子任务可能存活这件事。删除照常进行(一次瞬时预检抖动不该阻塞删除),事后 toast 仍报 Host 执行后的真实数。 ③ 批量 purge。 ② plan-token 绑定 / 重确认——这里我倾向不做。 确认弹窗本质是事前提醒,而对子任务来说这个动作是非破坏性的——它们被保留归档、不是删除。权威账目是删除后的 toast,报的是 Host 执行后的真实数、天然正确。所以即便发生你说的竞态(预检到执行之间某个子任务被 unarchive),用户事后仍会立刻看到真实数字——结果没被隐藏,只是确认前的估算短暂过期。加上 ① 之后,「预检不可用」这个子情况也覆盖了。为一个已有事后安全网的窄窗口、而且是关于「会存活的任务」的提示,引入 plan 摘要 token + 新的 |
142794d to
c56d32f
Compare
6104b2c to
2313f20
Compare
…tasks Deleting a parent task permanently removes it, but its ordinary linked subagent subtasks are intentionally kept and moved to the archive rather than cascade-deleted (apache#1467 / apache#3151). The confirm said nothing and the completion gave no feedback, so the archived rows that appeared next read as tasks from nowhere. The delete confirm now warns, when the task has linked subtasks, that they are kept and moved to Archived; the completion toast reports how many moved. Both counts are owned by the Host, not estimated by the renderer: - `session.remove` returns `archivedSubtaskCount` (deduplicated by revision family), which the toast reports verbatim. - A read-only `session.remove.preview` query returns how many subtasks a delete would archive, which the confirm warns off. Graph operators (retired with the parent), already-archived children, copies mid-preparation, and absent targets all preview zero. A preview failure drops the note without blocking the delete. The renderer never re-derives the Host's removal plan — its catalog projection carries linked children as `subagent: { parentSessionId }` with no operator marker or copy state, so an estimate would over-promise. Copy lives in `shell-copy.ts` (zh + en). Deletion semantics are unchanged. Bumps RUNTIME_HOST_COMPATIBILITY_EPOCH to 51 (new removed-result field and new query; older peers reject both). Fixes apache#3780 Generated-by: Claude Code
…tasks Addresses the [P2] on be094cb: - Preview fail-open: the delete confirm swallowed a `previewRemoval` error as count 0 and showed no warning, hiding that subtasks may be archived. It now falls back to an uncertain note ("its linked subtasks, if any, will be kept and moved to Archived") so the confirm never silently omits the warning; the delete still proceeds and the toast reports the executed count. - Bulk purge bypass: purgeSessions now sums the Host's executed archivedSubtaskCount across the sweep into SessionPurgeOutcome.archivedSubtasks, the archived-tasks purge confirm warns that linked subtasks are kept and archived, and the result toast reports how many moved. Generated-by: Claude Code
2313f20 to
a3f535d
Compare
Summary
Deleting a parent task permanently removes it, but its ordinary linked subagent subtasks are intentionally kept and moved to the archive rather than cascade-deleted (#1467 / #3151 — each subtask owns its own transcript, artifacts, and outputs). The delete confirm never said so and the completion gave no feedback, so the archived rows that appeared next — labelled
原父任务已删除on Settings › 活动 › 已归档任务 — read as tasks from nowhere.This adds two notices, without touching deletion semantics:
The confirm's decision to warn is a renderer presence check off the live catalog (
parentHasArchivableSubtasksinapp-shell-session-row-actions.ts): ordinary subagents count, Agent Graph operators (subagentParent.graph) do not, and already-archived children do not. The exact number is owned by the Host:session.removenow returnsarchivedSubtaskCount(present only when it archived something, deduplicated by revision family insession-retirement-coordinator.ts), threaded throughremoveSession, thesessions:removeIPC, and the preload bridge to the toast. A restore that calls the delete off shows no subtask notice, since nothing moved. Copy lives inshell-copy.ts(zh + en).Fixes #3780
Review follow-up (superseding an earlier revision of this PR)
The first version computed the count in the renderer (
countArchivableSubtasks) as a second implementation of the Host's removal plan. As raised in review, that estimate diverged from the Host — theconversationCopy?.state !== 'preparing'filter is not implementable offSessionSummary, and the parent-link fallback read a field the Host ignores — so it could name a wrong number. The count now comes from the Host, and the confirm names no number at all.Verification
biome linton the 14 changed files — clean.tsc -p tsconfig.main.json,tsconfig.renderer.json,tsconfig.preload.json(--noEmit) — all pass;@maka/runtime-hostbuild — clean.session-retirement-protocol.test.ts—archivedSubtaskCountround-trips on a removed result, is absent when nothing was archived, and a negative value is rejected.session-retirement-coordinator.test.ts— a parent with 32 distinct subagent children reportsarchivedSubtaskCount: 32; graph-operator and already-archived cases stay countless.runtime-host-client-operations.test.ts/runtime-host-client-uds.test.ts—removeSession/ thesessions:removeIPC surface the count verbatim ({ disposition, archivedSubtaskCount }).app-shell-session-row-actions-revisions.test.ts— the confirm warns without a number when the family has archivable subtasks; the toast reports the Host's count; graph operators / archived children / other parents raise no notice; a concurrent restore leaves the toast silent.parent-session-deletion.spec.ts— asserts the confirm warns about the subtask (no count); not run in this environment (needs the Electron build + Playwright). Run withnpm --workspace @maka/desktop run e2e -- parent-session-deletion.Screenshots
Delete confirm — warns the linked subtasks are kept and archived (the current copy names no count; the image below predates the review follow-up and still shows one):
Completion toast — reports how many subtasks moved to Archived (now the Host's executed count):
AI use
Select exactly one:
Tool(s) and scope: Claude Code — traced the delete/archive path, wrote the copy, the
parentHasArchivableSubtaskspresence check, thearchivedSubtaskCountwiring from the Host coordinator through the protocol, client, IPC, and preload to the toast, and the unit/e2e coverage. Commits carry aGenerated-by: Claude Codetrailer.Checklist
Does this PR entail a change in behavior?