record the close of §5.9

This commit is contained in:
2026-08-07 09:43:30 +00:00
parent ca046a3876
commit fed2badd28
+34 -8
View File
@@ -28,9 +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.
**§5.9 is closed** (`dbe585f`, `717580f`, `585f234`, `d3922bd`, `ca046a3`) — the bag is a parsed
identity, the app-config fields are deleted or moved onto the app, and the inert context is built
once. Tier B is now panel lifecycle (§5.1), `normalizeLayout` (§5.4) and the mobile decision (§6).
- **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`).
@@ -490,9 +490,11 @@ 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.
**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.
**§5.9 is closed as of 2026-08-07.** The context is 15 fields, and the outbound half is `workspace`,
`cwd`, `root` — all three facts about *where the panel is*, which is the one thing a framework of this
shape genuinely owes an app. Nothing left on it is an app's vocabulary: the file-browser pair is
deleted, the chat's system prompt is a prop on the chat, and the key three apps used to parse is a
parsed identity. The two hand-written copies of the inert half are one named constant.
- [x] **Delete `initialFilePath` and `defaultFileSort`.** Declared `WorkspaceContext.ts:14-15`, plumbed
through `WorkspaceView.tsx:19-20,30`, read only by
@@ -505,11 +507,17 @@ directory it is over. `promptPrefix` is the one remaining courier job, and it is
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` →
- [x] **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.
**Done in `d3922bd`**, exactly that way: both screens put their own `ChatPanelWrapper` in
`components` under the chat panel's id and pass the prefix as a prop. `PanelSlot` prefers a
`components` entry over the registry for the *body* only, so the panel keeps its registry header —
the screens did not have to reproduce any chrome. `ChatPanelWrapper` is exported from the barrel
for it. The same prop came off `WorkspaceLayout`, where it had no callers at all: every settings
pane and job detail rendering through it had always been passing its chat panels `undefined`.
- [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'`
@@ -531,11 +539,16 @@ directory it is over. `promptPrefix` is the one remaining courier job, and it is
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
- [x] **`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.
**Done in `ca046a3`.** The eleven interaction fields — everything a panel uses to rearrange the
workspace, plus the state those interactions run on — are one exported `inertInteraction`, spread
by `WorkspaceLayout` and by the `createContext` default. `root` stays omitted, and that is now a
stated decision rather than an oversight: it is only ever read when `cwd` is scoped, and no caller
of `WorkspaceLayout` passes a `cwd` at all, so there is nothing for it to be the root *of*.
### 5.10 Channel hygiene — _(found 2026-08-07)_
@@ -696,3 +709,16 @@ Low priority, but each line here is a line someone will read and believe.
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.
- [x] **The framework stopped carrying things only one app understands.** _(`d3922bd` + `ca046a3`,
branch `agent-coordination-mvp`)_ — the last two items of §5.9, and with them the section. A
screen's ~40-word system prompt used to travel screen → `WorkspaceView` → context →
`ChatPanelWrapper`, three of those four steps by a framework that has no idea what the string is.
It is now a prop on the chat panel the screen mounts itself through `components` — the prop that
already existed for supplying a panel's component, and which `PanelSlot` honours for the body
while still taking header and provider from the registry entry, so nothing about the panel's
chrome had to be reproduced.
The second half is the inert context: `WorkspaceLayout` and the `createContext` default had each
written out the same eleven switched-off fields by hand. `inertInteraction` names the idea once.
Net across all of §5.9: the context is 15 fields from 18, and everything still on it answers
"where is this panel" rather than "what should this panel do".