78bf63c209f0306dfd238bd84891ae1ec6967e2c
3
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
00baa83a2c |
a commander's own files, beside its transcript
a commander writes into its own directory — procedures, reports, the loop it armed — and there was no way to look at any of it. /files cannot reach it and never could: the file browser serves two roots, `home` and `user-data`, and a commander lives at $DATA_PATH/<email>/commanders/<dir>, which is under the one /files does not use. so the Plan button becomes a files button on a commander. instead, not beside: plan mode is research-and-propose-until-a-human-approves, and a commander is the case where nobody is watching to approve. the control promised something that cannot happen there, while the thing genuinely missing was any view of what it had written. an EPHEMERAL panel, the same trade /files makes for the file viewer. /command-hq is a locked workspace with a three-item allow-list whose comments are explicit that its structure is code's rather than the user's; a persisted panel would mean unlocking it and widening that list. an ephemeral layout renders beside workspace.value and never enters it, so neither has to change. ?files=1 rather than a route, and a panel rather than a link: the transcript stays mounted and stays the page, and a link on this surface opens a second copy of the whole app in a new tab and loses the conversation you were reading. breadcrumbs stop at the commander for free — Breadcrumb renders relative to basePath and its home crumb IS the base. worth knowing that this is the UI's floor and not the server's: the root really is all of user-data, which is the owner's own data either way, so it bounds the navigation rather than the account. the button reads its state from props rather than useSearchParams. ModelSelector is rendered bare in its own tests and reaching for the router inside it failed all twelve — a control that has to be mounted in a route to render is not a control any more. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Officer-Session: 656f5c85-e49a-4f1f-b9f3-042a04b4d043 |
||
|
|
430f058a6d |
command hq: two columns, with the navigation stacked
It was 16 / 34 / 50 — a category column, a commander column, and the transcript. So half the screen was navigation for a list holding a handful of commanders (one, on this machine) while the only thing anybody reads got the other half. Now the two navigation panels are stacked into one 24% column — commanders on top, categories beneath — and the transcript takes 76%. Categories BELOW the commanders, not above: the commanders are what you came for and the categories are how you narrow them. Above, the filter would push the list down the screen and be read first; below, the list is at the top where a list belongs, and the categories can grow their own scrollbar without taking room from it. The categories panel lost seventy pixels of branding — a Radar tile, "Command HQ", "Watchers & long-running jobs" — which made sense when it owned a column and does not now that it sits at the foot of one. The screen's own header says Command HQ two inches above it. `All commanders` and `Uncategorised` moved INTO the scroll box with the categories. They are the same kind of thing, a filter over the list, and splitting them into a separate nav block above made the second look like a different mechanism. The heading and the + button stay pinned; only the list scrolls — the same rule as the theme dropdown. MIGRATION, and it is the part that could have gone wrong. This key is persisted per account, so the default alone moves nobody who has opened the screen. No appType was retired either, so `hasAppType` cannot see it the way the /chat migration could — the test is structural instead: a horizontal root with three children is the old shape. It terminates because the replacement has two, and replacing outright is safe on a `locked` screen where the only user contribution is column sizes. Same reasoning, and same trap, as ChatHistory/index.tsx. Two of my edits silently did nothing first, because I searched for `officerdb` where the module is `officerdev` and used replace without an assertion. Both are asserted now. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
a9be3a92c9 |
command hq: web frontend v1 — nav, grid, detail
Builds the Workspace/Panel screen the design doc's "Layout, v1" described but nothing had implemented yet: /command-hq and /command-hq/:sessionId, three always-mounted panels (officerdev/src/apps/CommandHQ/) — a flat category nav filtering the grid via ?category=, a commander grid reading GET /commanders, and a detail pane that is either an empty state, the new-commander composer, or the selected commander's resumed transcript. Follows the frontend route conventions in CLAUDE.md throughout: Workspace/Panel framework (locked, three fixed panels, no standalone screen), category and session both addressable in the URL rather than a channel, real <Link>s for every row and card, a route pair (/command-hq + /command-hq/:sessionId) the same shape as /chat's. The composer reuses the exact mechanism /chat already uses to create a commander — an ordinary turn with context: 'command-hq' via useChat/ EmbeddableChat — rather than the mobile-only POST /commanders/new HTTP route. Once the harness reports a real transcript id the URL is replaced onto it (useChat's own permalink writes /chat/<id>, which is the wrong screen here, so that's done by hand). fileAsCommander always files a new commander uncategorised — it has no way to know a category was selected in the composer — so if one was, a client-side PATCH sets it after the fact, the same race POST /commanders/new already resolves server-side for mobile, just resolved here on the client instead. The detail panel's transcript resume mirrors ChatPanelWrapper's fetch-then- mount pattern (GET /chat/sessions/:id first, then useChat with resumeSessionId + initialMessages + paginate) rather than reusing it directly — Command HQ's version is simpler (no dashboard/agent-panel concerns) and scopes rename/category/disarm through Command HQ's own PATCH route rather than /chat's, since a commander lives in a different directory than an ordinary chat session. Card status is the three-state read COMMS/command-hq/mobile-4.md proposed and the design record adopted: green running, amber armed-but-not-running (the watcherArmed && !running pair that makes a silently-dead watcher visible), grey neither. Registered in AppRegistry.tsx, re-exported from officerdev's barrel (route helpers + types, per CLAUDE.md's rule for anything an officer-web screen needs), a CORE_DOCK_ITEMS tile (not in DEFAULT_DOCK_PATHS — opt-in via the Dock settings screen, same as Jobs/Monitor/Activity), and a usePageTitle rule. bunx tsgo clean, suite at its 7 pre-existing baseline failures, none of them this feature's. NOT yet clicked through against a running server — the composer's redirect-on-real-id, the disarm button, the category-race PATCH have all typechecked and nothing more. That's the next real test. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |