Skip to content

tree: a read-only window still offers Undo and Dismiss on the reorganized notice #2220

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: a6741b41601c430a899b7f522ad42012
Branch: dev/2-tree-readonly-reorg
Base: 75e3c18
At: 2026-11-02T18:36:15Z

Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment.

Written-by: FlyBot Lead
Owner: FlyBot Dev-2
Branch: dev/2-tree-readonly-reorg
Credit: audit and draft by FlyBot Product (P-439).
Kind: bug (read-only surface)

Source: FlyBot Product audit P-439, re-read by FlyBot Lead on live main 75e3c18d: plugins/tree/client.js has zero readOnly occurrences, tree/undo and tree/dismiss are registered without { read: true } (plugins/tree/index.js:63 and :64; only tree/reorg at :62 is a read), and the notice draws both buttons unconditionally.

Dedupe (searched before opening)

Issue searches (title+body): tree reorganized, reorg notice, tree undo read-only, Undo Dismiss tree. Hits are the tree self-organization feature itself (closed issue #446, closed PRs #448/#454/#828), an open sidebar-cosmetic issue #818, and open follow-ups #450 (memory handoff on merge, model pins) — none of them gates the reorg notice on roster.readOnly. Closed read-only issues/PRs (#2176/#2181/#2190/#2195/#2205/#2215) are all the workflow plugin. No issue covers this notice.

What happens today

makeReorgNotice (plugins/tree/client.js:444-471) is registered as a sidebar section (apply, :556, flybot.slots.register('flybot.sidebar.section', { id: 'flybot-tree-reorg', order: 89, component: makeReorgNotice(ctx.flybot) })). The section component is handed { roster, actions, call } by the shell (core/src/client/flybot-slots.js documents that shape), but ReorgNotice (:445) reads no props today.

When a reorganization ran within NOTICE_DAYS, noticeRun (:426-429) yields the run and the card is drawn by ReorgCard (:431-443), whose action row (:439-441) always renders Undo (:440, tree/undo) and Dismiss (:441, tree/dismiss).

In a read-only window the host refuses both writes (core/src/host/channel.js:295-296), the client catches the rejection into note (:465), and the reader is left with two buttons that can only fail. tree/reorg itself is a declared read, so the notice — title, time, the moved lines — is legitimate read-only information and should stay.

Why it is common rather than theoretical: reorgNotice is on by default (apply, :557), the daily tidy can produce a run every day, and the card stays visible for NOTICE_DAYS (7) — so a second, read-only window opened in that week usually carries this notice with a dead Undo on it.

Reproduction (measured on 75e3c18d)

  1. Mount the registered section component with roster: { bots: [], readOnly: 'This window shows the team but cannot change it.' }, flybot.call('tree/reorg') returning one run { id: 'run-1', at: Date.now() - 60_000, summary: ['Moved 3 Bots'] }, flybot.fields.on a no-op.
  2. Read the tree: button.flybot-reorg-btn count = 2 (Undo, Dismiss). Clicking Undo issues flybot.call('tree/undo', { runId: 'run-1' }).
  3. Same fixture with a writable roster (no readOnly): identical output.

Probe: plugins/tree/test/probe-tree-readonly.test.js in the evidence tree tmp/a1105/m2 (plugins/tree/client.js unchanged by it).

Expected behaviour

With a read-only roster and a fresh run, the notice still shows what was reorganized — the title, the time, the moved lines, and the Kept: line when the run was undone — and draws no Undo and no Dismiss (button.flybot-reorg-btn count 0). On a writable roster the card is byte-for-byte what it is today: both buttons, same handlers, same busy/disabled behaviour and same note line on failure. The host keeps refusing those writes in a read-only window either way; this issue is about not offering the control.

Signal to use: roster.readOnly (trimmed, non-empty ⇒ locked), the same sentence and the same test the workflow page uses (plugins/workflow/client.js:1570-1571, :1954-1955). No new endpoint, no new protocol field.

Scope

  • plugins/tree/client.js — makeReorgNotice (:444-471): read roster.readOnly, and when it is set render the notice without the action handlers (the card must then draw no action buttons); ReorgCard (:431-443) draws its action row only when at least one handler is present.
  • plugins/tree/test/ — the red-first test below (client render only; the repo's existing tree tests show the rendering harness).
  • changelog.d/<this issue>-tree-readonly.fixed.md; plugins/tree/README.md if it describes the notice.

Not in scope: the daily tidy, the reorg journal format, tree/reorg's read flag, the archived/structure sections, and any workflow or core surface (those have their own issues).

Red first

New plugins/tree/test/reorg-readonly.test.js, whole-tree counts:

A. read-only roster + one fresh run ⇒ button.flybot-reorg-btn count = 0, while the card still renders: .flybot-reorg count 1 and its text contains the run's summary line. (Today: 2 buttons.)
B. writable roster + the same fixture ⇒ button.flybot-reorg-btn count = 2, the first is Undo and issues tree/undo with { runId }; clicking it in the read-only fixture is impossible (no button), so assert the call count of tree/undo/tree/dismiss under the read-only roster is 0. (Today: 2 buttons, clicking sends the write.)
C. no fresh run (older than NOTICE_DAYS, or dismissed === run.id) under either roster ⇒ no card at all (pins the existing freshness rule).

Acceptance

  1. A and B fail before the change and pass after; C passes before and after.
  2. plugins/tree suite green, npm run verify green, arch-docs: OK.
  3. A read-only window shows the reorganization notice and no write control on it; a writable window is unchanged.

Activity

  1. HugoXK commented on Nov 2, 2026

    @HugoXK
    ContributorAuthor

    Release

    Written-by: FlyBot Lead
    Released: a6741b41601c430a899b7f522ad42012
    Reason: merged via PR #2223 (c8d55d9)
    At: 2026-11-02T19:39:26Z

  2. added a commit that references this issue on Nov 2, 2026
    c8d55d9
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