Skip to content

core: a read-only window's Memory panel still offers its writes and says nothing about why #2276

Closed

Description

@HugoXK

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: 2129078dc44844cf9af70beabaee10c4
Branch: dev/1-p475-memory-readonly
Base: 910f630
At: 2026-11-03T05:59:18Z

A read-only window's Memory panel is the one surface in the read-only family that is not even handed the roster, so it draws Remove from memory on every entry and the Ask or update form at the foot, and both are refused by the host. Nothing inside the panel says the window is read-only: the user types or confirms first and learns afterwards.

Reproduction (live main 50081167e81ac5ee182e6cc5d1a25ab248329e32)

  1. Open a second window on the same team while another dsh holds state.lock (the window is read-only).
  2. Open a Bot's memory panel (bot-settings.js:190 Manage memory, or the memory pill in the session header).
  3. The panel lists the entries normally — memory-view is in the host's read whitelist — and draws the trash button on each entry plus the Ask or update form.
  4. Click the trash twice (confirm), or type a sentence and press Send. The host answers the refusal sentence (bot/read-only); the panel itself never warned.

Wiring: core/src/client/overlays.js:57 mounts MemoryDialog with { key, bot, actions, leaving } — no roster, while SettingsDialog (:55), InboxDialog (:58) and BotPanel (:49) all receive it. memory-panel.js has no read-only branch at all: EntryRow draws the remove button unconditionally (:119-121, two-click confirm then actions.memoryForget), and the foot always draws form.bt-mem-ask with Send (:297-303, actions.memoryAsk). The host whitelist (core/src/host/channel.js, READS) contains memory-view but neither memory-ask nor memory-forget, so every such write is refused with the store's read-only sentence.

Expected

  • A read-only window draws no Remove button and no Ask or update form in this panel, and the panel itself carries the host's own read-only sentence as a role="status" line (the same hostText(roster.readOnly) text the sidebar and the Settings header already show).
  • A writable window renders byte-identically to today.
  • Regenerate summary is explicitly out of scope: it goes through memory-view and genuinely works in a read-only window, so it stays.

Scope

  • core/src/client/overlays.js: pass roster to MemoryDialog.
  • core/src/client/memory-panel.js: accept roster, compute the lock with the predicate the client already uses (typeof roster?.readOnly === 'string' && roster.readOnly.trim() !== '', as settings.js:236 / sidebar.js:371 do), skip the remove button and the ask form when locked, and draw one bt-hint bt-read-only line with role="status" carrying hostText(roster.readOnly).
  • New test core/test/memory-panel-readonly.test.js: writable counter-case (Remove 1 / ask form 1 / no hint — the panel loads its view through an async effect, so the test must await it or the "0" assertions are true by construction), locked case (Remove 0 / form 0 / exactly one bt-read-only status line whose text equals hostText(roster.readOnly)).
  • Generated: core/client.js, patches/ds-bot/0008-client-bundle.patch, patches/ds-bot/files/** mirrors, changelog.d/ fragment, docs/subsystems/core-client.md if its table row changes.

Tier, from the file list: core/src/client/**, core/test/**, core/client.js, patches/ds-bot/** and changelog.d/** are T1; docs/** is T0 — so T1.

Dedupe

Searched open and closed issues for "memory panel read-only", memory-forget, Remove from memory and memory ask readonly: no open issue covers this surface. #2269/#2267 (closed) were about read endpoints refused in a read-only window — the opposite direction; #2107 (closed) was the memory-folder refusal sentence; #2153/#2157 were the diagnostics journal wording. Adjacent but separate: details-drawer.js:270 (BotSettingsForm receives the roster and has no read-only branch) is a different surface and is not in this scope.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions