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: 8ceb9080513e4d41a6edffe5402aa07f
Branch: dev/1-schedules-hidden
Base: fa4671b
At: 2026-11-02T09:57:45Z
What a member sees
Open Settings → Scheduled tasks on a host where task access is enforced (sourceOf) and every scheduled task on the host belongs to another member. The page draws the section and then says, in the same words as a host with no tasks at all:
No scheduled tasks yet.
Nothing there says a list exists and was narrowed; the member concludes the host has no schedules, which is the wrong fact. The same thing happens on a Bot's detail page, whose row reads No scheduled tasks yet. Add one — an invitation to add a task to a list that is not empty.
Where it is
core/src/host/schedules.js:407-429(schedulesView): both loops (:414-415catalog,:420-421paused) drop a row withif (!known(owner) || sourceOf(entry.sessionId, actor) === undefined) continue, and the answer carries only{ available, tasks, quietHours, ... }— nothing distinguishes "the host has none" from "the host has rows you may not read".core/src/client/schedules.js:362-365(settings empty state) and:473-476(Bot detail row) both decide fromtasks.length === 0alone, andavailable === falsestill wins first at:474.core/src/client/i18n.js:1315-1316holds the two strings to change (zh too).
Reproduction
- On a host with access enforcement on, let member A create one scheduled task.
- Read the schedules page as member B (a session that may not read A's row).
- The page says
No scheduled tasks yet.while the host's catalog is not empty;GET /api/schedulesreturns{ available: true, tasks: [] }with no field that says why it is empty.
Expected behaviour
The view says whether the emptiness is real:
schedulesView(actor)returns a booleansomeHidden,trueonly when the actor narrowing removed a row that would otherwise be visible:known(owner) && sourceOf(entry.sessionId, actor) === undefined, in either loop. A row whose owner is unknown (!known(owner)) does not set it — such a row is unavailable to everyone, so nothing is being hidden from this caller.- With
someHidden: true, the settings empty state says the list is narrowed rather than absent, e.g.No scheduled tasks you can see. Another member's tasks stay hidden., and the Bot detail row saysNo scheduled tasks you can see. Add one. - With
someHiddenabsent orfalse, both strings stay exactly as they are today. available === falsekeeps priority oversomeHidden; no other response field, route or ordering changes.
Acceptance
Red first on a base where the source is unmodified and only the new cases are added; each of these must fail for the behavioural reason, not on wording:
- settings page, narrowed with one hidden task → the empty state no longer reads
No scheduled tasks yet.and carries the narrowed sentence; - Bot detail row, same setup →
No scheduled tasks you can see. Add one; - host unit: catalog row hidden by the actor →
someHidden === true; paused row hidden by the actor →someHidden === true; - control cases that are green on the base: no rows at all →
someHiddenabsent/false and the old sentence unchanged; enforcement off → nosomeHidden.
Then: same cases green, node core/scripts/build-client.mjs --check, and npm run verify at the new base with arch-docs and the ds-bot-patches check/canonical pair.
Scope
Not in this issue: reading another member's tasks, changing who may see what, the count on the Bot details row (#2032), or the Inbox's hidden rows (#2050). Only the two empty states and the one flag that feeds them.
Duplicate check
On live main fa4671b3: someHidden has no occurrence in the tree, and neither empty state consults anything but tasks.length. Issue search for scheduled tasks hidden, someHidden, No scheduled tasks you can see returns only other surfaces — #2050/#2051 (Inbox Done group + its rows), #2030/#2032 (Bot details count), #2112 (a page stuck on Loading…), #628/#664 (listing a Bot's tasks across sessions) — all closed and none about a narrowed list claiming emptiness.
Activity