mark 5.10 resolved

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-07 11:15:00 +00:00
co-authored by Claude Opus 5
parent c9735580fc
commit f2ae10bd36
+23 -5
View File
@@ -703,27 +703,45 @@ parsed identity. The two hand-written copies of the inert half are one named con
Cheap to fix, and prerequisites for the 5.8 migration rather than alternatives to it. Cheap to fix, and prerequisites for the 5.8 migration rather than alternatives to it.
- [ ] **Four channels are bare string literals with no constant.** `'files:refresh-signal'` (repeated in - [x] **Four channels are bare string literals with no constant.** `'files:refresh-signal'` (repeated in
4 files), `'chat:selected-session'` (3 files — plus a module-private `CHANNEL` const in a 4th place 4 files), `'chat:selected-session'` (3 files — plus a module-private `CHANNEL` const in a 4th place
that only one of them uses), `'chat:active-session'`, `'preview:refresh'`. A typo silently yields a that only one of them uses), `'chat:active-session'`, `'preview:refresh'`. A typo silently yields a
fresh channel pinned to `initialData`; nothing errors. Export a constant per channel, next to its fresh channel pinned to `initialData`; nothing errors. Export a constant per channel, next to its
payload type. payload type.
- [ ] **Payload types are per-call-site, not per-channel.** `usePanelChannel<T>` takes `T` from each - [x] **Payload types are per-call-site, not per-channel.** `usePanelChannel<T>` takes `T` from each
caller, so a publisher and a subscriber can disagree and nothing checks. caller, so a publisher and a subscriber can disagree and nothing checks.
`'files:refresh-signal'` is `number` in all four places by convention only. A `'files:refresh-signal'` is `number` in all four places by convention only. A
`defineChannel<T>(name)` helper returning a typed hook would fix both this and the item above. `defineChannel<T>(name)` helper returning a typed hook would fix both this and the item above.
- [ ] **Two write idioms disagree on the same channel.** `files:refresh-signal` is bumped with **Both resolved `c973558`** — `defineChannel<T>(name, initial)` in `hooks/usePanelChannel.ts`
returns the hook, and `officerdev/src/channels.ts` declares the four. Every one of the twenty
remaining `usePanelChannel` call sites in the repo now passes a shared constant; there are no bare
literals left.
- [x] **Two write idioms disagree on the same channel.** `files:refresh-signal` is bumped with
`Date.now()` at the Chat sites and `setRefreshSignal((n) => n + 1)` at the FileViewer sites — and `Date.now()` at the Chat sites and `setRefreshSignal((n) => n + 1)` at the FileViewer sites — and
`useGlobal`'s functional form applies against the **render-time** snapshot (`useGlobal.ts:18`), so `useGlobal`'s functional form applies against the **render-time** snapshot (`useGlobal.ts:18`), so
two increments in one render window collapse into one. Standardise on the nonce. two increments in one render window collapse into one. Standardise on the nonce.
(`useLyricsOpen.ts:19-23` already documents avoiding the functional form for this reason.) (`useLyricsOpen.ts:19-23` already documents avoiding the functional form for this reason.)
- [ ] **`system-settings:run-command` has no writer.** `run-command-channel.ts:6`; the only two writes **Resolved `c973558`**, but not on `Date.now()` — that has the same bug at millisecond scale, and
the four FileViewer bump sites sit close enough together (save, delete, extract, transcribe) to hit
it. `useFilesRefresh()` exposes a `bump` over a module-level counter that never reads React state,
so it is correct however many times it is called between renders. `bump` is also identity-stable
through a ref, because `useGlobal`'s setter is a fresh closure every render and this one goes into
dependency lists.
- [x] **`system-settings:run-command` has no writer.** `run-command-channel.ts:6`; the only two writes
(`SystemSettings.tsx:87,133`) are both _clears_, and the sibling ServerSettings sections never (`SystemSettings.tsx:87,133`) are both _clears_, and the sibling ServerSettings sections never
import it. The panel it drives — a terminal that opens with a command pre-loaded — appears import it. The panel it drives — a terminal that opens with a command pre-loaded — appears
unreachable. Wire it or delete it; add to §8 either way. unreachable. Wire it or delete it; add to §8 either way.
- [ ] **`PanelComponentEntry.component` is typed with no props** (`types.ts:60-62`) but **Deleted `c973558`.** It had a writer once: `7c0b11c` ("sudo commands through ephemeral
terminal") wired the AI harness installer to it. That install moved server-side to
`POST /server-settings/chat-providers/install` and the write went with it, leaving the channel, the
`SystemTerminalPanel`, and a whole second `splitLayout` that nothing could select. Gone — the path
it existed for no longer wants a terminal.
- [x] **`PanelComponentEntry.component` is typed with no props** (`types.ts:60-62`) but
`PanelSlot.tsx:521` passes `panelId` at runtime. `components`-supplied panels get a prop they `PanelSlot.tsx:521` passes `panelId` at runtime. `components`-supplied panels get a prop they
cannot see; registry apps get the honest `{ panelId: string }`. One-line type fix. cannot see; registry apps get the honest `{ panelId: string }`. One-line type fix.
**Resolved `c973558`** — `component`, `header` and `provider` all take `{ panelId: string }` now,
since `PanelSlot` renders all three with it. A no-prop component is still assignable, so no screen
changed.
--- ---