Repository navigation
core/test: project-board-panels is order-dependent and reds merge groups at random (it ejected #1825 once) #1843
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: bbcd50297ba84d3dad4f26da8e7b5dae
Branch: dev/3-flaky-panel-state
Base: b4e05ac
At: 2026-10-30T15:01:10Z
Baseline
Checked on main = b4e05acf9c2785eced88e94f1b70e4f15c860c9f (2026-10-30). core/test/project-board-panels.test.js and its mirror are byte-identical there (sha256 875357b9497f34d9358a3d381199901685ff97028ad96b2eb22f3ed355aba663, 14125 bytes each). #1835 did not touch either file.
What happens
core/test/project-board-panels.test.js is order-dependent and fails intermittently in a merge group. It already cost one queue ejection on 2026-10-30:
11:16:34Z#1825entered the merge queue; the merge-group run41046947850(job124033238715,ubuntu-latest · Node 24 · DSH 0.2.0-rc.2) went red on this file, andgithub-merge-queue[bot]removed the PR at11:19:20Z.11:21:57Zthe same PR at the same tip33a5d463was queued again; run41047579302went green. Same code, same test, different outcome.
Failing assertion (the test starts at :169, the assertion at :177):
✖ the settings panel memory save lands in the Project memory through the real endpoint
AssertionError: the panel reports the state the host answered
+ actual: 'Assistant settings saved.'
- expected: 'Memory saved.'
Why it is order-dependent
- The panel keeps its status line in component state:
core/src/client/project-board.js:349const [status, setStatus] = useState(''), written only fromrun()(:351-363) afterawait save(...). - The test's React stand-in keeps hook slots in module scope and never clears them between tests:
core/test/project-board-panels.test.js:33let slots = [],:34let index = 0, and:58const render = (component, props) => { index = 0; return component(props) }— only the cursor is reset, not the slots. - The earlier test in the same file clicks
project-assistant-save(:158-161), leaving'Assistant settings saved.'in that slot. The later test re-renders, clicksproject-memory-save, andsettle()(:77, tentick()s) is a fixed number of turns rather than a wait for the status to change — under CI load the asyncrun()has not landed yet, so the stale line is what gets read.
So the defect is in the test harness (shared state + fixed-tick wait), not in the host and not in the panel.
Expected
- Each test starts from clean hook slots: a fresh state map per test (or per
render()of a new tree), so one test's clicks cannot be read by another. - The assertion waits for the condition rather than a fixed number of ticks: e.g.
await waitFor(() => text(status) === 'Memory saved.')with a bounded timeout, orawait Promise.resolve()chains that end when the save promise settles. - The file passes in a loop and in a shuffled order: run it at least 20 times in a row, and run it with the
:158block placed after the:166block, with no failure. - Nothing about the production behaviour changes: the panel still reports the host's answer,
Memory saved.on success and the host's sentence on refusal, in zh under a zh locale.
Scope
core/test/project-board-panels.test.jsonly, plus its byte-identical mirrorpatches/ds-bot/files/test/project-board-panels.test.js. The slot reset (around:33-58) and the wait helper (settleat:77, used at:174,:186and:213).- The wait helper lives inside this test file. Do not extract it into a shared helper under
core/test/: that would pull other test files into this issue's scope. - No production code. The change lands in the test fixture only;
core/src/**andcore/client.jsstay untouched. If the fix appears to need a source change, stop and report instead of widening this issue. - No changelog fragment: test-only, not user-visible.
Acceptance
The two order criteria are one criterion, taken together — either alone proves nothing:
- 20 consecutive runs green and the same file green with the two offending blocks swapped (the
:158block after the:166block). Record both in the PR body: the run count and the swapped-order result. npm run verifygreen,check's threeoklines green,build-client --checkgreen.- No change to any user-visible sentence.
Duplicate check
search/issues on repo:ThinkFlowLab/FlyBot (open and closed) for flaky, merge queue, project-board-panels, settle returns no issue about this harness; the only related ones are #1820/#1823 (the panel's write path and its fix), which are about behaviour, not test order. git grep -n "slots = \[\]" b4e05acf -- core/test shows the shared slot array only in this file.
Why this is not scheduled as one of the daily four
It is a precondition for the other four: while it can red a merge group at random, any finished PR can fail to reach main. The Lead keeps it outside the daily quota and ahead of them in priority; the owner-set daily four (P-239, P-230, P-234, P-237) keep their own order.
Activity
Birfy commentedon Oct 30, 2026
Written-by: Chief
状态补记:
agent-pr。本单已有开放 PR #1850(dev/3-flaky-panel-state,tiped4ddb9c,正文 Fixes #1843),此前本单没有任何状态标签。CI、入队与合并由开该 PR 的那条线负责,本线不接手。读取时间 2026-10-30T16:35Z,来源 api.github.com。