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: 31a96e5f509143ffb9fed52d37277a00
Branch: dev/1-readonly-reads-assert
Base: 910f630
At: 2026-11-03T06:33:21Z
Implementation: FlyBot (ours) — PR follows within 24h. Do not pick up without a pickup-ok comment.
Written-by: FlyBot Lead
What is wrong
core/test/readonly-window-reads.test.js (added in #2269) is the only guard against a read name
falling out of channel.js's READS whitelist, but it asserts only "not refused with
bot/read-only". Any answer that is past the gate and dry still passes:
folder-list→{"ok":false,"error":{"code":"bot/refused","message":"This DeepSeek Harness cannot list folders"}}connector-app-status→{"ok":false,"error":{"code":"bot/refused","message":"Connect Composio first"}}project-decision→{"ok":true,"value":{"ok":true,"reason":"…not listed…"}}— the "nothing listed" halfproject-of/project-board/folders→ok:truewith empty data (no binding, no working folder)
So on a tree where a read-only window draws those screens empty, the suite is still green.
Reproduction (live main 910f6302)
$ node --test core/test/readonly-window-reads.test.js # the file as it is on main
# tests 3 / # pass 3 / # fail 0 <- false green, on the dry data above
The same tree with each row asserting its own key (fixtures unchanged) is red in two of three
tests, and the red names the dry answers, not a crash.
Expected behaviour
Each row of READS carries [endpoint, payload, expect] and the test fails unless the answer
carries the data its screen draws (11 rows: tasks, projects, project-read, project-of,
project-board, project-team, project-decision, project-memory, folders, folder-list,
connector-app-status). Refusals and dry answers are reported as two separate lists, because they
are two different defects (whitelist lost a name vs the fixture never made the data).
Fixtures the rows need, all inside the test file (no source change):
fakeContext({ services: { directoryPicker: { capability: () => ({ kind: 'browse', list }) } } })
—folders.jsreads it throughctx.get('directoryPicker');- a seeded Composio session plus a stubbed
https://backend.composio.dev/fetch, so
connector-app-statusanswersgmail: 'ready'; - a Project with a
workDirholdingdecisions/2026-01-01-x.mdand a Bot bound to it;
project-decisionopens the first name the board itself listed (Project board decision rows can be listed but never opened #2041), and fails loudly with
the board listed no decision file to openwhen the board listed none.
Reverse evidence: deleting any one name from READS in channel.js must turn the test red naming
that name (verified for folder-list, connector-app-status, project-decision: pass 2 / fail 1).
Scope
- One file:
core/test/readonly-window-reads.test.js(+84/−33). Test-only: nocore/srcchange,
no generated artifact, no changelog. - Out of scope: adding new reads to the whitelist, or touching the handlers whose fixtures were
seeded here.
Duplicate check
Searched open and closed issues for readonly-window-reads: #2269 and #2267 (closed) are the
feature tickets whose test this hardens; no issue asks for the assertion strength itself.
Activity
core: assert each read-only screen read answers its own key (ThinkFlo…
core: assert each read-only screen read answers its own key (ThinkFlo…
core: assert each read-only screen read answers its own data (ThinkFl…
core: the read-only reads test passes on a dry answer — assert each r…