Repository navigation
client: a read-only window's plain-group Settings page drops Who answers and Working folder - #2538
Conversation
A window that holds the team read-only draws the group Settings page as text, and the two fact cards were gated on the room being face-to-face. Both facts are reads — `shownMode` and `room.workDir` — so a plain group's locked page drew neither while its writable page draws both as a control. Draw them for every group, as the face-to-face page already did (ThinkFlowLab#2492). Fixes ThinkFlowLab#2528
|
Verdict: PASS at 0ce7425 Ran at this tip: Red first. Restoring only Tier. Recomputed from the pull request's file list with Checks at the tip. All 16 check runs at The change. Scope. 8 files, +58/−11, matching the body: Checkpoint. Block is 1037 characters (< 1500), summary 458 characters / 3 sentences, 4 files all in this diff, One conclusion. No earlier Fork note: head repository is Not run: the host smoke test (client-only change, no |
…rlays offer no Reload (ThinkFlowLab#2523) Fixes ThinkFlowLab#2521 Owner: Dev-2 Reviewer: Birfy Written-by: Dev-2 Claim-Id: cce0d5e889b74566b96d54c6ec7ff13c Base: d400edb Risk tier: T1 ## What changes Four read-only surfaces are drawn **inside a full-screen overlay**, whose scrim covers the sidebar's own Reload: the reader mid-task had to close the overlay, press Reload, and open it again. Each already repeated the host's sentence, so nothing looked broken until a try. 1. **Board** — `BoardView` (`core/src/client/kanban.js`) drew the host sentence in `bt-board-hint` and nothing beside it. `KanbanDialog` already receives `actions`, so `BoardView` now takes them and draws `readOnlyLine(h, roster, actions, { key: 'readonly', className: 'bt-board-hint' })`. 2. **New chat, admin chosen** — the group block in `NewChat` (`new-chat.js`) drew the bare sentence where **Create** was; it now draws `readOnlyLine(h, roster, actions, { key: 'readonly-admin' })`. 3. **New chat, composer** — the otherwise branch of the same component drew the same bare sentence; it now draws `readOnlyLine(h, roster, actions, { key: 'readonly-compose' })`. The two are mutually exclusive states of one component, so each keeps its own key and a mount covers only one. 4. **Project settings panel** — `ProjectSettingsPanel` (`project-board.js`) received only `call/onClose/onSaved`, so it had no reload to offer. `ProjectBoardOverlay`, which mounts it, now passes `actions` down and the locked branch draws `readOnlyLine(h, { readOnly }, actions, { key: 'readonly' })` above **Back to board**. Nothing new is invented: `readOnlyLine` is the piece added in ThinkFlowLab#2502 (`core/src/client/read-only.js`). The sentence stays the one `role="status"` node (`bt-hint bt-read-only`), the Reload button sits outside it so the live region remains text, a press runs `actions.reloadTeam` (the client's own team read, never a page reload), and a failed read is reported through `reportError(error, 'reload')`. One screen draws at most one entry; a writable window draws neither. Every write control a writable window has is untouched. ## Acceptance In a read-only window, with the overlay open: - each of the four surfaces draws exactly one Reload beside the host's sentence (`readonly-reload-lines.test.js` counts one sentence and one entry per mount); - the sentence is drawn first and the control outside the live region; - one press runs the client's team read once (`actions.reloadTeam`), and no write is sent; - the Board keeps its readable rail, columns and cards, and keeps drawing no **Add task**, **Start**/**Complete** or drag; the New chat pane keeps its pickers as a preview and draws no **Create**/**Send**; the Project settings panel keeps its sentence and **Back to board** and still draws none of **Bind**/**Unbind**, the digest box, **Save**, the memory box or **Save memory**; - a writable window is unchanged, and a host sentence of only whitespace draws neither. ## Red first On a clean `d400edb74798b71e233eccd46f221eaef782ff5d` tree whose source is untouched and which holds only this branch's extended test file, `TZ=UTC node --import ./test/harness-resolve.mjs --test test/readonly-reload-lines.test.js` exits 1: ``` not ok 3 - every surface that is not the header or a drawer offers one Reload — its own way out of the modal Board dialog: one Reload entry 0 !== 1 not ok 4 - one shared piece: the sentence is the host sentence, and the control sits outside the live region Board dialog: the sentence is read first expected: true actual: false not ok 5 - a press runs the client's own team read, once, and sends no write Board dialog: the entry is drawn expected: true actual: false # tests 7 # pass 4 # fail 3 # cancelled 0 ``` The three failures are loop assertions (one per behaviour across all surfaces), so the count is 3, not one per surface. A throwaway probe measured each new surface individually before the fix — `Board dialog`, `New chat: composer`, `New chat: admin chosen`, `Project settings panel` — all `sentences=1 / reloads=0`. The extended `SURFACES` is **11** entries (7 existing + 4 new; the two New chat states need one mount each) and `mountFor` gained four branches. After the fix the same file is **7/7** green. ## Why the base is `d400edb7` and the branch was rebased `ThinkFlowLab#2538` merged into `main` at `14:16:25Z` (merge sha `d400edb7…`) and rewrote `patches/ds-bot/0008-client-bundle.patch`; this branch carries that same patch. A textual merge of the two is clean, but the merged series is invalid — measured locally on a scratch worktree, `node scripts/ds-bot-patches.mjs check` on the merge result fails with `0008-client-bundle.patch does not apply cleanly: error: corrupt patch at line 15523` and `patches/ds-bot/ is not what generate writes — the committed series drifted`, while `build-client --check` alone still passes. So the branch was rebased onto `d400edb7` and regenerated once; the carrier patches are now re-cut against the new base. ## What I ran at the fork head (fork head `81b9a7ac1940eb5949bb7b50e4b462e9be3dc742`, tree `83d6706529e88a7db759634d31177e09fd3e466c`; `TZ=UTC`, clean tree) - `TZ=UTC ARCH_DOCS_BASE=d400edb74798b71e233eccd46f221eaef782ff5d npm run verify` — **exit 0**. Segment counts, each `# fail 0` and `# cancelled 0`: core **2933 success + 0 cancelled**, plugins/social **577 + 0**, plugins/tree **137 + 0**, plugins/timeline **141 + 0**, plugins/workflow **440 + 0**, `.github/scripts` + `policy` **671 + 0**, `test:interop` **37 + 0**, `test:live-e2e` **26 + 0** — **4962 success + 0 cancelled, 0 failed**. `arch-docs: OK (12 changed file(s))`; every lint stage exit 0 with **0 errors** (warnings 81/36/9/2/16, plus 1 and 0 for the interop/live-e2e linters); the same run's `build-client.mjs --check` exit 0. - The 13 neighbouring suites (`create-bot-readonly`, `create-bot`, `group-create-readonly`, `kanban`, `new-chat-menu`, `new-chat`, `project-board`, `project-board-entry`, `project-board-levels`, `project-board-panels`, `project-board-readonly`, `project-board-view`, `readonly-reload-lines`): **183/183, 0 failed**. - `node core/scripts/build-client.mjs --check` — exit 0, no output. `node scripts/ds-bot-patches.mjs check` — three `ok` lines: `ok ds-bot/ = Fei2411/DeepSeek-Bot@2b10c70 (tree 5834c00, v0.1.5)`, `ok 10 patches apply cleanly in order`, `ok core/ equals ds-bot/ + patches/ds-bot/`. `node scripts/ds-bot-patches.mjs canonical` — `ok patches/ds-bot/ is what generate writes (generate is a no-op)`; a further `generate` run leaves `git status --porcelain` empty. - `git status --porcelain` — empty on the committed tree. ## What I did not run - The host smoke test and a live service on a bench port — this change is client-only (`core/src/client/**`), no host code. - Anything on `ThinkFlowLab#2520`, `ThinkFlowLab#2517` or `ThinkFlowLab#2443` — untouched. ## Files 12 files, `+451/−354` (`git diff --numstat d400edb...HEAD`), tree `83d67065`: - `core/src/client/kanban.js` (+7/−5) — `BoardView` takes `actions`; the hint becomes `readOnlyLine`. - `core/src/client/new-chat.js` (+4/−3) — both locked branches draw `readOnlyLine`, one key each. - `core/src/client/project-board.js` (+4/−3) — `ProjectSettingsPanel` takes `actions`; `ProjectBoardOverlay` passes it. - `core/test/readonly-reload-lines.test.js` (+45/−2) — `SURFACES` 7 → 11 and four `mountFor` branches. - `docs/subsystems/core-client.md` (+4/−4) — the four surfaces and the panel's `actions` are documented. - `changelog.d/2521-overlay-readonly-reload.fixed.md` (+1, new). - `core/client.js` (+10/−8), `patches/ds-bot/0003-flybot-api-client.patch` (+5/−5, carries `new-chat.js`), `patches/ds-bot/0008-client-bundle.patch` (+315/−314, carries `kanban.js` and `project-board.js`), `patches/ds-bot/files/src/client/kanban.js` (+7/−5), `patches/ds-bot/files/src/client/project-board.js` (+4/−3), `patches/ds-bot/files/test/readonly-reload-lines.test.js` (+45/−2) — generated by `build-client` + `ds-bot-patches generate`, never hand-edited. The two carrier patches are exactly the ones whose source files this branch changes — the carrier set `{0003, 0008}` is exactly the set that carries the changed sources, and no third patch is touched (the other eight patches are byte-identical to the base). <!-- flybot:checkpoint --> ```json { "pr": 2523, "claim": "Dev-2", "issue": 2521, "summary": "Four read-only surfaces drawn inside overlays — the Board hint, both New chat sites and the Project settings panel — now draw the shared readOnlyLine piece instead of their own copy of the host sentence. Each keeps the sentence in its one role=status node and puts a single Reload outside it, running actions.reloadTeam, never a page reload. The panel now receives actions from ProjectBoardOverlay, which previously passed no reload at all. A writable window and every read-only control are unchanged.", "files": [ "core/src/client/kanban.js", "core/src/client/new-chat.js", "core/src/client/project-board.js", "core/test/readonly-reload-lines.test.js", "docs/subsystems/core-client.md", "changelog.d/2521-overlay-readonly-reload.fixed.md" ], "checks": { "ran": "TZ=UTC ARCH_DOCS_BASE=d400edb7 npm run verify; build-client --check; ds-bot-patches check/canonical; 13 neighbouring suites", "result": "green", "at": "81b9a7ac1940eb5949bb7b50e4b462e9be3dc742" }, "next": "on the rebased base the branch carries a re-cut 0008; the source/tests/docs half is unchanged, so review the regenerated carrier patches only" } ``` <!-- /flybot:checkpoint -->
Fixes #2528
Owner: Dev-2
Reviewer: Birfy
Written-by: Dev-2
Claim-Id: 7714932e4c32497097973e87fb7c3e53
Base: 90a5944
Risk tier: T1
What changes
A window that holds the team read-only draws a group's Settings page as text.
GroupSettingsForm(core/src/client/group-settings.js) opened both fact cards with the same guard:So a plain group's locked page drew neither, while its writable page draws both — the mode picker (
Segmented) and the folder menu (FolderMenu). Both facts are reads: the mode comes throughshownMode(room, roster)and the folder isroom.workDir, and neither card asks the host for anything, in the locked branch or the writable one. A face-to-face room's page already kept them (#2492); a plain group's page dropped them.The two guards are removed, so a locked page draws Who answers with the mode's own label (
Admin leads/Everyone) and Working folder with the stored path, in the sameCard+Rowtext the face-to-face branch uses. No control is added, no write is sent, and the writable page is unchanged: it still draws the picker and the folder menu in the same place. Nothing else in the group page moves — the members card, the admin row, the notice, and the standing read-only sentence in the Settings header are as they were.FaceLead's own lock (#2512) is untouched: the change is the twoface ?guards only.Acceptance
In a read-only window, on a plain group's Settings page:
select,input,textarea, no picker, no menu;callsstays empty);Red first
On a clean
90a594471b5886737b433e116f6397aa8ca2b6f2tree whose source is untouched and which holds only this branch's extended test file:exit 1. After the fix the same file is 8/8, 0 failed, 0 cancelled, exit 0.
What I ran at the tip
0ce742571300e2a684be09574b5434fa655d9c17(local commit2d88f4e9d0aa4bc7fb19e77d3ff00bd14eb56886, same tree0e3ff367dd0a4c4f4a0207461847e390ca9c6552)cd core && TZ=UTC node --import ./test/harness-resolve.mjs --test test/settings-readonly-pages.test.js— 8/8 green at the tip, 8/7/1 on the base above.TZ=UTC ARCH_DOCS_BASE=90a594471b5886737b433e116f6397aa8ca2b6f2 npm run verifyon the committed tree — exit 0 — core 2928 success + 0 cancelled, plugins/social 577 + 0, plugins/tree 137 + 0, plugins/timeline 141 + 0, plugins/workflow 440 + 0,.github/scripts+policy671 + 0,test:interop37 + 0,test:live-e2e26 + 0 — 4957 success + 0 cancelled, 0 failed;arch-docs: OK (8 changed file(s)); every lint stage exit 0 with 0 errors.node core/scripts/build-client.mjs --check— exit 0.node scripts/ds-bot-patches.mjs check— threeoklines:ok ds-bot/ = Fei2411/DeepSeek-Bot@2b10c70 (tree 5834c00, v0.1.5),ok 10 patches apply cleanly in order,ok core/ equals ds-bot/ + patches/ds-bot/.node scripts/ds-bot-patches.mjs canonical—ok patches/ds-bot/ is what generate writes (generate is a no-op); two furthergenerateruns on the commit leavegit status --porcelainempty.node .github/scripts/changelog.mjs check—changelog: 36 fragment(s) in changelog.d/ are well formed, exit 0.settings-readonly-pages,settings-readonly-head,details-bot-settings-readonly,details-face-lead-readonly,details-group-settings-readonly,details-overview-readonly,group-create-readonly,composer-send-readonly,room-approvals-readonly,create-bot-readonly,kanban,new-chat,new-chat-menu) — 83/83, 0 failed, 0 cancelled, exit 0.git status --porcelain— empty on the committed tree.What I did not run
core/src/client/**), no host code and noindex.js.#2523,#2520or another branch — untouched.Files
8 files,
+58/−11(git diff --numstat 90a59447...HEAD):core/src/client/group-settings.js(+4/−2) — the twoface ?guards become plain cards, with the reason in a comment.core/test/settings-readonly-pages.test.js(+19/−0) — one test: the plain group's locked page states both facts as text, sends no write, and the writable page draws both controls.docs/subsystems/core-client.md(+1/−1) — the Settings lock bullet says the page states who answers and the working folder for every group.changelog.d/2528-plain-group-readonly-facts.fixed.md(+1, new).core/client.js(+4/−2),patches/ds-bot/0008-client-bundle.patch(+5/−3, carriesclient.js),patches/ds-bot/0012-room-membership.patch(+5/−3, carriesgroup-settings.js),patches/ds-bot/files/test/settings-readonly-pages.test.js(+19/−0) — generated bybuild-client+ds-bot-patches generate, never hand-edited.The carrier patch set is exactly
{0008, 0012}— the patches that carry this branch's two changed source files (core/client.js→0008,core/src/client/group-settings.js→0012) — plus the test mirror. No third patch changes: the other eight are byte-identical to the base.{ "pr": 2538, "claim": "Dev-2", "issue": 2528, "summary": "A read-only window's plain-group Settings page now states Who answers (the mode's own label) and Working folder (the stored path) as text, which its writable page already drew as a picker and a folder menu. Both facts are reads, so the locked page keeps them for every group the way the face-to-face page has since #2492; no control is added and nothing is written. The writable page, the members card and the rest of the locked Settings pages are unchanged.", "files": ["core/src/client/group-settings.js", "core/test/settings-readonly-pages.test.js", "docs/subsystems/core-client.md", "changelog.d/2528-plain-group-readonly-facts.fixed.md"], "checks": { "ran": "TZ=UTC ARCH_DOCS_BASE=90a59447 npm run verify; node scripts/ds-bot-patches check; node core/scripts/build-client.mjs --check", "result": "green", "at": "2d88f4e9d0aa4bc7fb19e77d3ff00bd14eb56886" }, "next": "none — ready for review" }