From b1e0bac1e04881674a23433d77f1d1284a6fb6c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Padez?= Date: Fri, 7 Aug 2026 09:36:27 +0000 Subject: [PATCH] =?UTF-8?q?record=20the=20first=20three=20items=20of=20?= =?UTF-8?q?=C2=A75.9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/workspace-panel-todo.md | 46 ++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/docs/workspace-panel-todo.md b/docs/workspace-panel-todo.md index 71a6a040..bf2d4cd8 100644 --- a/docs/workspace-panel-todo.md +++ b/docs/workspace-panel-todo.md @@ -28,6 +28,9 @@ before deciding what to pick up next. Its conclusions in one paragraph: (§5.1), but inverted: the requirement is that closing a chat panel must _not_ destroy the agent; `normalizeLayout` as framework (§5.4); and the mobile-collapse decision (§6), which swings on one unanswered question. + **§5.9's first three are done** — the bag is a parsed identity (`dbe585f`) and the two file-browser + fields are deleted (`717580f`, `585f234`). What is left there is `promptPrefix` and the + constructed-in-two-places preview context. - **Tier C, orthogonal:** everything else — including **§5.2 (remounts) and §5.3 (drag-to-move), both large downgrades.** A panel is now a pointer to a server-side session, so a remount costs a replay, and the drag hazard is disarmed by resolving identity by name (`e588524` + `bc82086`). @@ -487,18 +490,27 @@ All the same bug: an app guessing "am I being closed?" from an unmount, or payin `WorkspaceContext` is 18 fields, of which the framework itself reads none of the first six. Apps never touch the framework half, so the abstraction holds in one direction; the leak is entirely outbound. -- [ ] **Delete `initialFilePath` and `defaultFileSort`.** Declared `WorkspaceContext.ts:14-15`, plumbed +**Down to 16 as of 2026-08-07**, and the outbound half is now `workspace`, `cwd`, `root`, `promptPrefix`. +Of those, `workspace` and `cwd` are genuinely the framework's to state — where the panel is and what +directory it is over. `promptPrefix` is the one remaining courier job, and it is the next item. + +- [x] **Delete `initialFilePath` and `defaultFileSort`.** Declared `WorkspaceContext.ts:14-15`, plumbed through `WorkspaceView.tsx:19-20,30`, read only by `apps/FileBrowser/FileBrowserApp/FileBrowserPanelWrapper.tsx:7,9,10` — and **set by zero callers**. `DefaultFileSort` (`{field: 'name'|'size'|'type'|'date'}`) is file-browser vocabulary living in the framework's type file, and it is re-exported from the barrel (`Workspace/index.ts:27`). Pure leak, no payoff, entirely deletable. + **Gone in `717580f`**, along with the two barrel re-exports. Deleting them orphaned the props they + were feeding, so `585f234` took out the layer below: `FileBrowserApp`'s `initialPath`/`defaultSort`, + the duplicate `DefaultSort` type in two files, and `useFileBrowserApp`'s `isolated` — which was + `!!initialPath` and so had always been false. No behaviour changed at either level; both were + already running on the defaults. - [ ] **Move `promptPrefix` onto the component, not the context.** `WorkspaceContext.ts:16` → `Chat/ChatPanelWrapper.tsx:78` → `useEmbeddableChat.ts:107`. Set by `EmailScreen.tsx:53` and `BrowserScreen.tsx:35`, each a screen-local ~40-word system prompt. The framework is a courier for a string only one app understands, and the `components` prop already exists for exactly this — Email can supply a pre-configured chat by panel id. -- [ ] **`dashboardId` is a bag whose _format_ three apps parse.** It is literally `workspace.key` +- [x] **`dashboardId` is a bag whose _format_ three apps parse.** It is literally `workspace.key` (`WorkspaceView.tsx:163`). Consumers reverse-engineer meaning from its shape: `Chat/ChatPanelWrapper.tsx:51-56` does `dashboardId === 'email' || dashboardId === 'screens/email'` → email context, and `!startsWith('screens/')` → dashboard context — **so renaming a screen key @@ -509,9 +521,21 @@ touch the framework half, so the abstraction holds in one direction; the leak is `TerminalWrapper.tsx:13-16` regexes it; `HostTerminalWrapper.tsx:12` doesn't (§2). Give the context the parsed facts (`{ kind: 'screen'|'dashboard', id }`) instead of the raw key, and the three parsers collapse. -- [ ] **`WorkspaceLayout.tsx:36` silently omits `root`, `initialFilePath`, `defaultFileSort`** — apps - inside a `DashboardPreview` fall through to the `createContext` defaults. Whatever survives the - three items above should be constructed in one place, not twice by hand. + **Done in `dbe585f`.** `workspace: WorkspaceIdentity | null` replaces `dashboardId`, parsed once in + `WorkspaceView` by `parseWorkspaceKey` and memoised on the key — the identity lands in + `useAgentPanel`'s query key, and a fresh object per render there is the `useClient()` trap that + disabled the Jellyfin playback reports. The identity carries `key` as well as `kind`/`id`, because + the raw key is the address `agent_panels.dashboard_id` stores: parsed halves are for deciding, the + key is for storing. Two behaviours tightened deliberately — an unrecognised key is no longer + treated as a dashboard (the old `!startsWith('screens/')` would have let a panel register an agent + against a workspace with no row to hang it on), and `terminalStateKey` now takes the identity, so + it can no longer nest a key inside itself. Seven tests in `workspace-identity.test.ts`, and the + two live agents on `ws-layout-agent-mvp` were confirmed still addressable after the restart. +- [ ] **`WorkspaceLayout.tsx:36` silently omits `root`** — apps inside a `DashboardPreview` fall through + to the `createContext` defaults. (`initialFilePath` and `defaultFileSort` were on this list too and + are now deleted; `workspace` is omitted there on purpose, since a preview is not a place an agent + can be addressed.) Whatever survives the three items above should be constructed in one place, not + twice by hand. ### 5.10 Channel hygiene — _(found 2026-08-07)_ @@ -660,3 +684,15 @@ Low priority, but each line here is a line someone will read and believe. the day it changes: a move drops `zoom` and `fitContent` (§5.3). **Still untested:** the other eleven files of the framework — `WorkspaceView`, `WorkspaceRenderer`, `PanelSlot`, `normalizeLayout`. §5.5's debounce lost-updates live there, not in `layout-utils`. + +- [x] **A panel is told where it is, instead of being handed a key to reverse-engineer.** _(`dbe585f` + + `717580f` + `585f234`, branch `agent-coordination-mvp`)_ — the first three items of §5.9. The + context field `dashboardId: string` — which was never an id, always the whole `workspace.key` — + is now `workspace: WorkspaceIdentity | null`, parsed once by `parseWorkspaceKey` and memoised on + the key. Three apps had been parsing the format independently, each with its own idea of what a + non-dashboard looks like; they now read `kind` and `id`. The raw `key` rides along because it is + the address `agent_panels.dashboard_id` stores, and a stored address must not depend on which + feature wrote it. + In the same pass, the two file-browser fields the context had grown were deleted, and with them + the prop chain underneath that had no other caller. Net: the context is 16 fields from 18, and + four dead parameters and a permanently-false flag are gone from the file browser.