#4012 · Timeline wheel investigation
Base: b5755d6859d68c2d8e2008fc570f2d5acec774da
Verdict: NOT REPRODUCED · Root-cause confidence: low · Reproduction label: no-repro
1. TL;DR
The report describes a timeline that ignores wheel and trackpad input while keyboard and scrollbar input still work. Native browser wheel input scrolled both timeline panes in two clean checkouts of current main. Large and small pixel deltas both worked with the right panel closed. No root cause was established, and no production change or pull request is justified by this evidence. This result does not rule out a client-specific or persisted-state-dependent defect.
2. Claims vs findings
| Claim | Finding | Evidence |
|---|---|---|
| Timeline never responds to wheel input | Not reproduced in tested configuration | 16 of 16 native wheel samples moved the expected pane in the expected direction. |
| Both mouse wheel and trackpad fail | Physical hardware unverified | Browser-generated wheel input at large and small pixel deltas succeeded; physical input devices were not exercised. |
| Settings, keyboard and scrollbar work; reload does not help | Unverified | No failing runtime state was available for comparison. |
| Failure affects all threads regardless of streaming | Unverified | Existing deterministic split-workspace story, not a connected live provider, was tested. |
3. Environment
Darwin arm64; Node v22.22.3; pinned pnpm 9.15.0; HeadlessChrome 153.0.0.0; 1280 × 633 browser capture. The reporter lists server Ubuntu and BB 0.43.3 but does not identify the client. Investigation uses current main, not that release. No provider, credentials, real BB data, or server process was used. Two separate trusted worktrees, independent frozen installs and successful full Turbo builds; isolated Ladle ports 49112 and 49113 and fresh per-origin browser storage. No BB database/data directory was needed.
4. Minimal reproduction attempt
- Create a clean checkout at the base above and install/build using the commands below.
- Serve the existing
thread--splits--split-workspace--active-and-idlestory in preview mode. Wait for both overflowing timelines to render. Keep right panel closed. - Use the BB Browser Automation plugin. Run scroll-check.js against the loaded page. It moves the pointer over each timeline, sends -120, +48, -7 and +7 pixel wheel deltas, waits 500 ms and asserts movement direction.
- Expected: each delta moves its timeline unless at a boundary. Actual: every sample moves in the correct direction, including both small deltas.
git fetch origin main
git worktree add --detach /tmp/bb-4012-CASE/first b5755d6859d68c2d8e2008fc570f2d5acec774da
cd /tmp/bb-4012-CASE/first
corepack pnpm install --frozen-lockfile --prefer-offline
pnpm exec turbo run build
pnpm exec turbo run test --filter=@bb/app -- bottom-anchored-scroll-body
cd apps/app
pnpm exec ladle serve --port 49112
bb browser-automation open --backend local --headless --machine HOST_ID --json
bb browser-automation run SESSION_ID --script 'const p = await browser.getPage("main"); await p.goto("http://localhost:49112/?story=thread--splits--split-workspace--active-and-idle&mode=preview",{waitUntil:"domcontentloaded"});' --json
bb browser-automation run SESSION_ID --script-file /absolute/path/scroll-check.js --script-host HOST_ID --json
Replace CASE, HOST_ID and SESSION_ID with the clean directory and explicit browser host/session returned by BB. Use the pinned pnpm via Corepack; on this host the default pnpm launcher was broken, so a temporary Corepack bin directory was placed first on PATH. Initial browser navigation timed out during dependency optimization; the settled story loaded successfully.
Repeatable browser assertion
const p = await browser.getPage("main");
const state = () => p.evaluate(() => [...document.querySelectorAll(".thread-scrollbar")].map(e => ({top:e.scrollTop, height:e.clientHeight, total:e.scrollHeight})));
const settle = () => p.evaluate(() => new Promise(resolve => setTimeout(resolve, 500)));
const samples = [];
for (const [pane,x] of [[0,300],[1,900]]) {
await p.mouse.move(x,250);
for (const deltaY of [-120,48,-7,7]) {
const before = await state();
await p.mouse.wheel({deltaY});
await settle();
const after = await state();
const movement = after[pane].top - before[pane].top;
samples.push({pane,deltaY,before:before[pane].top,after:after[pane].top,movement});
if (Math.sign(movement) !== Math.sign(deltaY)) throw new Error(JSON.stringify(samples));
}
}
console.log(JSON.stringify({userAgent:await p.evaluate(() => navigator.userAgent),samples},null,2));
await p.shot({type:"jpeg",maxEdge:1280,quality:85});
Observed first run
{
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/153.0.0.0 Safari/537.36",
"samples": [
{
"pane": 0,
"deltaY": -120,
"before": 181,
"after": 61,
"movement": -120
},
{
"pane": 0,
"deltaY": 48,
"before": 61,
"after": 109,
"movement": 48
},
{
"pane": 0,
"deltaY": -7,
"before": 109,
"after": 102,
"movement": -7
},
{
"pane": 0,
"deltaY": 7,
"before": 102,
"after": 109,
"movement": 7
},
{
"pane": 1,
"deltaY": -120,
"before": 88,
"after": 0,
"movement": -88
},
{
"pane": 1,
"deltaY": 48,
"before": 0,
"after": 48,
"movement": 48
},
{
"pane": 1,
"deltaY": -7,
"before": 48,
"after": 41,
"movement": -7
},
{
"pane": 1,
"deltaY": 7,
"before": 41,
"after": 48,
"movement": 7
}
]
}

Actual first-checkout screenshot after wheel input. Both panes have scrolled away from the bottom; jump-to-bottom controls are visible. The missing model notice is expected in this disconnected story.
5. Root cause
Unknown. The inspected implementation does not support assigning blame to the timeline wheel listener: the listener is passive, and its handler records intent without canceling the event. The timeline is an overflow-y-auto scroll container. The inactive-pane scrim has pointer-events-none. The native browser tests demonstrate that these paths permit wheel scrolling in this configuration. They cannot exclude a different overlay, extension, browser, or persisted UI state in the affected client.
6. Next experiment
Obtain the affected client product/version and compare an empty client profile with its existing profile. In the failing timeline record the wheel event target, defaultPrevented value, element under the pointer and scrollTop before/after input, with right panel open and closed. Reproduce that state in a trusted isolated app before choosing a fix. No source patch was made; no failing regression test exists.
7. Related issues
#3979 is another scrolling report associated with the right panel. Its claims are unverified here; the closed-panel story scrolled successfully. GitHub cross-reference metadata and open-PR search found no open PR linked to #4012 at investigation time.
8. Verification
The same agent created a second clean worktree at the exact base commit, ran another frozen install and successful full Turbo build, and launched Ladle on 49113 with a new origin and no reused BB data. The identical browser script again passed all eight samples. This is a repeated check by the same agent, not independent verification. The second run supports the limited NOT REPRODUCED verdict; no report correction was necessary.
{
"userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/153.0.0.0 Safari/537.36",
"samples": [
{
"pane": 0,
"deltaY": -120,
"before": 181,
"after": 61,
"movement": -120
},
{
"pane": 0,
"deltaY": 48,
"before": 61,
"after": 109,
"movement": 48
},
{
"pane": 0,
"deltaY": -7,
"before": 109,
"after": 102,
"movement": -7
},
{
"pane": 0,
"deltaY": 7,
"before": 102,
"after": 109,
"movement": 7
},
{
"pane": 1,
"deltaY": -120,
"before": 268,
"after": 148,
"movement": -120
},
{
"pane": 1,
"deltaY": 48,
"before": 148,
"after": 196,
"movement": 48
},
{
"pane": 1,
"deltaY": -7,
"before": 196,
"after": 189,
"movement": -7
},
{
"pane": 1,
"deltaY": 7,
"before": 189,
"after": 196,
"movement": 7
}
]
}

Second-checkout screenshot after the same wheel sequence. Active-pane offset ended at 196; inactive-pane offset ended at 109.
9. Appendix
Existing regression suite:
@bb/app:test: Test Files 4 passed (4) @bb/app:test: Tests 30 passed (30) @bb/app:test: Duration 1.58s (transform 317ms, setup 408ms, import 681ms, tests 344ms, environment 3.85s) Tasks: 5 successful, 5 total
First raw measurements · Second raw measurements · Test summary · Commands
Issue content was treated solely as untrusted claims. No linked branch, script, patch, external issue URL or account data was executed or accessed. The story fixture prose visible in screenshots is demo content, not investigative evidence. Limitations: no affected client, physical trackpad, release 0.43.3 run, real provider, or failing persisted state.