From a4aa86e66dad93f40bce640545d8903f7e6bcb64 Mon Sep 17 00:00:00 2001 From: Adam Malczewski Date: Fri, 16 Oct 2026 15:25:40 +0900 Subject: feat(tabs): confirm dialog that cascades a tab close to its subagents MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closing a tab whose visible subagent group is non-empty now asks ONE daisyUI modal (CloseSubagentsConfirm): 'Yes, close all N' closes the tab plus every transitive descendant tab (sub-sub-agents included, no further prompts), 'No, keep them open' closes only the tab, and Cancel/Escape/ backdrop closes nothing. Plain tabs close directly as before. - cascadeCloseIds (pure, tab-groups.ts): the tab + its transitive visible group descendants in tab order — one decision covers the whole subtree - TabList intercepts tab-close and opens the dialog only when the subtree has >1 tab; ids are snapshotted at open time - each closed conversation goes through the existing onClose port, so every close still POSTs /conversations/:id/close (backend doesn't cascade; it is idempotent) --- notes/assumptions-log.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'notes') diff --git a/notes/assumptions-log.md b/notes/assumptions-log.md index 728f8db..c6daf59 100644 --- a/notes/assumptions-log.md +++ b/notes/assumptions-log.md @@ -2,6 +2,26 @@ > Recorded while working autonomously (user away). Raise these when the user returns. +## 2026-10-16 — Close-tab cascade confirm dialog (subagent groups) + +1. **"Subagents" of a tab = its VISIBLE subagent group (open tabs only).** The confirm dialog + triggers when the closed tab has descendants in the tab grid's grouping + (`tabGroupParentId` forest, transitive). Subagent conversations that were never opened as + tabs are NOT closed — the FE has no knowledge of them (no lineage API consumed here). The + backend's `POST /conversations/:id/close` does not cascade either, so this matches the + visible mental model. + +2. **The cascade issues one `POST /close` per conversation** (via the existing `onClose` → + `store.closeTab` port, unchanged). The backend close is idempotent, so a descendant closed + by another client mid-dialog is a harmless no-op. No new cross-unit contract was needed: + the decision logic is pure (`cascadeCloseIds` in the tabs unit) and the dialog lives inside + `TabList`. + +3. **Dialog offers three outs:** "Yes, close all N" (cascade), "No, keep them open" (close + only the target tab — the pre-change behavior), and Cancel/Escape/backdrop (close nothing). + The user asked for a yes/no prompt; Cancel was added as the safe dismissal path. The + cascade-order snapshot (ids) is taken when the dialog opens. + ## 2026-06-24 — CR-10: workspaceId on conversation.open / statusChanged 1. **Contract version already at 0.19.0 in the backend repo.** The `file:` dep in `package.json` -- cgit v1.2.3