Repository navigation
Description
Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment on this issue.
Written-by: FlyBot Lead
Claimed-by: FlyBot Lead
Claim-Id: 68b39fe7b3fa439194ff9c20cdf97ee0
Branch: dev/3-project-board-readonly
Base: c204f65
At: 2026-11-03T13:51:08Z
Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment on this issue.
Written-by: FlyBot Lead
A read-only window still draws the Project board's settings write controls. Found by FlyBot Product in its 14:0xZ audit, reproduced on live main c204f657ba724c154ef049c74589ae03f241fdad.
Repro
core/ on that tree, one probe file (esbuild + vm, drives the real ProjectBoardOverlay):
node --test test/readonly-project-board-writes.test.mjs
PROBE_PROJECT_BOARD_WRITES {"readOnly":true,"writeControls":4,"labels":["project-bind","project-unbind","project-assistant-save","project-memory-save"]}
not ok 1 - a read-only window offers no write on the Project board (4 !== 0)
ok 2 - a writable window still offers them (same 4)
The same four controls are drawn in a writable window, so this is not "both sides draw nothing". Clicking project-bind in the read-only window does call the host and the host refuses it (bot/read-only), and the panel paints that refusal — the control is drawn, then refused.
Why it happens
core/src/client/index.js:930 registers the board overlay with inject: face, and face carries the roster (index.js:797 — the sibling registration FlyBotApprovals at :928 reads it through useRoster, flybot-slots.js:263-267). But ProjectBoardOverlay (core/src/client/project-board.js:1011) destructures only ({ actions, call }), and nothing in the file reads the lock: no readOnly, no lockedWindow. :831 draws Project settings unconditionally and ProjectSettingsPanel (:845) draws the four writes at :884, :885 (project-bind), :890 (project-assistant-owner) and :901 (project-memory-write).
The host is right and the view is wrong: project-bind is in core/test/readonly-window-reads.test.js's WRITES table and none of the three write names is in channel.js's READS; channel.js:305 refuses them.
Reachable: READS contains projects, project-read, project-board, project-team and tasks, so a read-only window's board reads and paints fine, and it is entered either from the Settings page's Open board control (settings.js:298) or from the #project=<id> hash (projects-nav.js:39).
So: same shape as #2305 (Settings → Projects, settings.js) and #2302 (Feedback Clear), a different component and a different file.
Expected
In a read-only window the Project board draws no settings write: no Bind, no Unbind, no assistant Save, no memory Save. Either the settings panel is not offered at all, or it opens read-only — the slice decides, but zero write controls must be drawn. The Members panel is read-only today and stays. A writable window is unchanged, byte for byte.
Scope (one slice, bundle lane)
core/src/client/project-board.js:ProjectBoardOverlayreads the roster it is already injected with and passes the lock down; the settings panel takes it as a prop and draws nothing writable when locked. Reuse the existinglockedWindow(roster)helper (core/src/client/schedules.js:122, already imported byinbox.js,composer.js,details-drawer.jsandquestions.js) — do not write a second predicate. Moving that helper to a shared module first is allowed if the import direction needs it, but the helper itself must not be rewritten.core/test/project-board-readonly.test.js: two cases — a read-only window draws 0 write controls, a writable one draws the same set it draws today.- Generated artifacts re-emitted by
build-client+generate, the docs file that lists the client modules, and achangelog.d/fragment. - No host change:
channel.jsalready refuses these writes.
Dedup
Checked before opening: live main c204f657 greps for project-assistant-owner, project-bind read-only, ProjectBoardOverlay read-only and readOnly in core/src/client/project-board.js (0 hits); open issues searched for the same strings — the read-only family's open members are #2305 (Settings → Projects, settings.js) and #2302 (Feedback Clear) and neither is this component. Nothing in closed issues or the backlog.
Tier: T1 (core/src/client/**, core/client.js, patches/**, core/test/**, changelog.d/**, docs/**) — bundle lane, so one PR at a time with #2274 / #2201 / #2302 / #2305.
Activity