mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-11-14 10:39:32 +01:00
test(mobile): the gate checks the File Viewer button's phone default again (#809)
Until #809 a display:none rule in mobile.css and its KNOWN_PHONE_HIDDEN entry kept the File Viewer button off phones, and the gate checked both. With that rule gone, the handheld default in getDefaultSettings() and the html.mobile-init startup rule are the whole lock, and only the browser test saw them, which npm test does not run. The policy test now loads the real getDefaultSettings() on a handheld and on a desktop, checks that every reader of the setting goes through the device default, and that mobile.css keeps the startup hide. Docs: architecture-invariants, src/web/CLAUDE.md and the wiki say the button is off on a phone until it is switched on there, and that a window narrower than 600px on a device that is not a handheld now shows it. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
This commit is contained in:
1 parent
b587ac71f4
commit
d192eb6825
8 files changed
+86
-11
No files matched your search
@@ -1039,7 +1039,7 @@ Further detail: in the Settings section order, the version and the updater lead
|
||||
⚠️ **`Session.lastSubmitAt` is persisted state, not a runtime counter.** `start()` reassigns `_claudeSessionId = resumeSessionId || id` on every launch — including the re-attach path for a mux session that survived the restart — so a recovered pane always points the viewer at its *launch* conversation, even when the CLI moved on via `/clear` hours earlier. The submit anchor is the only thing that can correct that without user input, so it round-trips through `SessionState.lastSubmitAt` and is restored in `restoreMuxSessions()`. Drop it from `toState()` and recovered panes silently show the pre-`/clear` transcript until the user types again. Restoring a *stale* anchor is safe: the resolver's staleness guard rejects any candidate transcript older than the one the pane is currently on, which is exactly the shape of a respawn into a fresh conversation.
|
||||
|
||||
⚠️ **The Claude viewer emits one message per model message and groups them with `turn`; it never concatenates them.** A Claude transcript is an append-only event log, so one logical exchange spans many rows: tool-result rows, meta/image/skill rows, compact summaries, task/team notifications, sidechains, replayed assistant snapshots. Rendering a card per *row* was the original bug (#169) — but the fix overshot to one card per *human turn*, which fused up to 74 distinct model messages into a single card and reported it as one message. One assistant row IS one whole model message: measured across a real `~/.claude/projects` (CLI 2.1.220-2.1.251) no assistant row carries more than one content block and no `message.id` carries more than one text block, so there was never anything to reassemble, and no adjacent pair of assistant rows continues a table, a list, or an open code fence. Each row is therefore its own message carrying `{kind, label, role, text, timestamp, turn}`; the frontend renders a same-role run inside one `turn` as badge-less continuation segments (`.rv-msg-cont`), which is what keeps a p90 of 11 messages per turn from reading as card spam. ⚠️ **A prompt typed while Claude is working is recorded ONLY as an `attachment/queued_command` row** — the CLI never re-emits it as a `user` row — so reading only `user` rows lost 162 of 353 user cards on that corpus AND lost the turn boundary each one carries, which is what let an assistant run fuse in the first place. Take it only when `attachment.origin.kind === 'human'` and `commandMode === 'prompt'`; the CLI's own queue entries (`commandMode: 'task-notification'`) carry no `origin` key at all. The shape is not a documented CLI contract, so every field check must fail closed. ⚠️ **`data.text` (no `?context=full`) is frozen on the last assistant row and must never be derived from `messages.at(-1)`** — agent pollers hash it (`skills/codeman/preamble.sh`), and the last message can be the user's own queued prompt. The BRIEF view therefore does not render `text`: it asks for `?context=turn`, which returns the assistant messages of the last ANSWERED turn (`selectLastAnsweredTurn()` in `src/web/response-viewer-transcript.ts`: the highest `turn` that has an assistant row, so a prompt queued after the answer does not blank the view), and renders them with the same numeric-`turn` continuation gate as the full view. `text` alone was the final row of a median-3-row turn — a "Done." tail with the substance in the rows before it. Readers that emit no `turn` (Codex, the pane parser, an older server) return `text` only, and the brief view falls back to one card for them. Replayed assistant snapshots are still deduped, and the tool/task/skill/compact/team metadata filtering is unchanged. Related: a recovered `restored-<uuid8>` tmux placeholder carries a **stale cwd**, so transcript lookup by working directory finds nothing; it rebinds to the matching top-level Claude transcript UUID instead when that match is unambiguous. Tests: `test/routes/session-routes-claude-last-response.test.ts`, `test/response-viewer-turn-segments.test.ts`. Purely client-side (no `renderIndexHtml` step): the template ships with `btn-response-viewer-header--hidden` and `applyHeaderVisibilitySettings()` (settings-ui.js) toggles it after settings load. Hiding must go through that marker class — the base rule is `display:inline-flex !important`, so an inline style can't override it. `showResponseViewer` is in the `displayKeys` per-device set (settings-ui.js), so it does NOT sync across devices.
|
||||
**File Viewer button** (header, 1.4.1) is **shown by default on desktop** since `211f3c0` (post-1.8.0): toggle under App Settings → Header & Panels → Header buttons → File Viewer (`showFileViewerButton`, in the per-device `displayKeys` set, fallback default `true`). Purely client-side like the response viewer: the template now ships the button VISIBLE (no `--hidden` class) and `applyHeaderVisibilitySettings()` toggles the `btn-file-viewer--hidden` marker class after settings load; phones still hide it via mobile.css. The button toggles the file-browser panel open/closed without opening the settings modal (`panels-ui.js`). The same commit set the **default desktop header** to WS/CPU/MEM + File Viewer + gear: the token-count chip (`showTokenCount`, no settings-UI toggle) and the lifecycle-log button (`showLifecycleLog`) both default **OFF** now (templates ship them hidden; stored prefs still honored). The plan-usage chip default is unchanged (opt-in, see Plan-usage chip). The **Cron toolbar button** joined the same opt-in pattern in 1.6.0: template ships `btn-cron--hidden`, `applyHeaderVisibilitySettings()` toggles it via the per-device `showCronButton` setting (default OFF, App Settings → Header & Panels → Scheduling); cron jobs themselves are unaffected.
|
||||
**File Viewer button** (header, 1.4.1) is **shown by default on desktop** since `211f3c0` (post-1.8.0): toggle under App Settings → Header & Panels → Header buttons → File Viewer (`showFileViewerButton`, in the per-device `displayKeys` set, fallback default `true`). Purely client-side like the response viewer: the template now ships the button VISIBLE (no `--hidden` class) and `applyHeaderVisibilitySettings()` toggles the `btn-file-viewer--hidden` marker class after settings load. **On a phone it is opt-in (#759):** the handheld branch of `getDefaultSettings()` defaults it OFF, `html.mobile-init` in `mobile.css` hides it until the settings have been applied (the template ships it visible, so it would flash otherwise), and switching it on in App Settings on that phone shows it there with a 44px touch target. `mobile.css` no longer hides it at phone width, so that default and the startup rule are the whole lock; `test/mobile-header-buttons-policy.test.ts` pins both in the gate, and `test/mobile/file-browser.test.ts` drives the real page at 390px. The setting never reaches the server (stripped from the PUT, absent from the schema), so a desktop cannot switch it on for a phone. ⚠️ A device that is not a handheld takes the desktop default at any width, so a desktop window or an iPad split view narrower than 600px now shows the button too. The button toggles the file-browser panel open/closed without opening the settings modal (`panels-ui.js`). The same commit set the **default desktop header** to WS/CPU/MEM + File Viewer + gear: the token-count chip (`showTokenCount`, no settings-UI toggle) and the lifecycle-log button (`showLifecycleLog`) both default **OFF** now (templates ship them hidden; stored prefs still honored). The plan-usage chip default is unchanged (opt-in, see Plan-usage chip). The **Cron toolbar button** joined the same opt-in pattern in 1.6.0: template ships `btn-cron--hidden`, `applyHeaderVisibilitySettings()` toggles it via the per-device `showCronButton` setting (default OFF, App Settings → Header & Panels → Scheduling); cron jobs themselves are unaffected.
|
||||
|
||||
### Session list layout (header strip vs. left sidebar)
|
||||
|
||||
|
||||
@@ -45,8 +45,9 @@ target escapes the workspace is already rejected. Ownership is `findSessionOrFai
|
||||
- CSS: `src/web/public/styles.css:9320-9430`. Overlay `z-index: 2000`, window `80vw/80vh`, capped
|
||||
`900x700`. There are **no `.file-preview-*` rules in `mobile.css` at all**.
|
||||
|
||||
**Reachability on phones.** The header File Viewer button is hidden below 430px
|
||||
(`mobile.css:482`, locked by `KNOWN_PHONE_HIDDEN` in `test/mobile-header-buttons-policy.test.ts`), so on a
|
||||
**Reachability on phones.** When this plan was written the header File Viewer button was hidden below 430px
|
||||
(`mobile.css:482`, locked by `KNOWN_PHONE_HIDDEN` in `test/mobile-header-buttons-policy.test.ts`); since
|
||||
#759 it shows on a phone once switched on there, and stays off by default. Without it, on a
|
||||
phone the preview overlay is reached through:
|
||||
|
||||
1. an attachment card's **Preview** button (`panels-ui.js:3451`), which is exactly the "agent just wrote a
|
||||
|
||||
@@ -191,12 +191,14 @@ last answer as scrollable text instead, with a **More** button for additional co
|
||||
Persian, Arabic and Hebrew answers read right to left there.
|
||||
|
||||
The [File Viewer](Working-With-Files) works on phones too, including edit mode, which is
|
||||
enough to fix a typo an agent introduced while you are away from your desk.
|
||||
enough to fix a typo an agent introduced while you are away from your desk. Its header button
|
||||
is off on a phone until you turn on **File Viewer** under **App Settings → Header & Panels**
|
||||
on that phone.
|
||||
|
||||
## What is deliberately not on phones
|
||||
|
||||
- Extra header buttons. New header controls are kept off phones by policy, with a test that
|
||||
enforces it.
|
||||
enforces it. The one exception is File Viewer, which you can switch on (see above).
|
||||
- The Approvals bell. Phones get the NEEDS YOU strips on the home screen instead.
|
||||
- The desktop home tab rail, which needs a wide window.
|
||||
- Lineage lines, which are a desktop overlay.
|
||||
|
||||
@@ -154,7 +154,7 @@ The right side of the header. Almost all of these are off until you enable them
|
||||
| Connection dot | Always on | SSE connection health. Green is connected. |
|
||||
| Font size `-` / `+` | Always on | `Ctrl +` / `Ctrl -` do the same. |
|
||||
| CPU / MEM | On | Server resource use. Drawn as a compact pill by default; see Header Stats Style below. |
|
||||
| File Viewer | On | Toggles the file browser panel. |
|
||||
| File Viewer | On, off on phones | Toggles the file browser panel. |
|
||||
| Settings gear | Always on | App Settings. |
|
||||
| Plan usage chip | On, desktop only | Live subscription usage: Claude (needs its telemetry exporter, which the same setting installs), Codex limits and the Copilot monthly quota. |
|
||||
| Session Manager | Off | The full session list, live and historical. |
|
||||
|
||||
@@ -8,7 +8,8 @@ until you get home.
|
||||
|
||||
A panel that browses the active session's working directory, or the git worktree its agent
|
||||
moved into ([Git Worktrees](Git-Worktrees#when-an-agent-moves-into-a-worktree)). Its header
|
||||
button is on by default; if it is missing, re-enable it in **App Settings → Header & Panels**.
|
||||
button is on by default on a desktop and off on a phone. The setting is per device: switch it
|
||||
in **App Settings → Header & Panels** on the device you want it on.
|
||||
|
||||
The panel and its search list up to 5,000 files and folders per load, shallow levels first and
|
||||
taking turns between folders, so one huge folder cannot use up that limit before the ones after it,
|
||||
|
||||
Reference in new issue
Block a user