Repository navigation
Description
Written-by: Chief
Owner decision (2026-11-06, on the "Live E2E has no key" question): do not wait for the secret — add a browser-level suite that runs with no key at all. #794 (real-model coverage) stays open and stays the owner's one click.
Why
Today the repository has exactly one browser-level check, Live E2E, and it measures nothing: GET /actions/secrets is total_count: 0, so .github/workflows/live-e2e.yml takes the skip path and every measuring step is skipped while the run reports success (evidence in #794, runs 19 and 20). A regression that only shows up in the web UI therefore reaches main unseen, and the product has no self-test inflow at all.
What to build
A second suite that needs no secret and no network to a model endpoint: the same isolated bench and the same web adapter, with DEEPSEEK_BASE_URL pointed at the scripted mock core/dev/mock-llm.mjs instead of the real endpoint.
Key files:
dev/live-e2e/bench.mjs:33-35—keyReading()+die("DEEPSEEK_API_KEY …")is the hard gate that must become a mode, not the only path. The bench itself already takesDEEPSEEK_BASE_URL(line 12-14).dev/live-e2e/run.mjs—--modeland--tapare already options; a mock run passes--modeland omits--tap. Its launcher path already refuses a loopback endpoint, so checkadapter.mjs/run.mjsguards before assuming it will run against127.0.0.1.dev/live-e2e/scenarios.mjs— the four scripted checks the live suite drives.core/dev/mock-llm.mjs— the scripted Anthropic-Messages-compatible mock (MOCK_PORT,MOCK_LOG), started in the background and pointed at byDEEPSEEK_BASE_URL..github/workflows/live-e2e.yml— add a second job (mock · ubuntu · Node 24) that is not gated onsteps.preflight.outputs.key, so it runs on every PR touchingcore/andplugins/, and on a schedule.
First step is a spike, not a PR
The open risk is whether the scripted mock can satisfy the four scenarios (they were written for a real model). Before any production code: start core/dev/mock-llm.mjs, run the existing bench + run.mjs against it on a local bench, and post the outcome on this issue — which of the four checks pass, which hang or assert on model wording. Two shapes are acceptable:
- A (preferred if the spike passes): the four existing checks run unchanged against the mock.
- B (fallback): a smaller UI smoke suite through the same adapter — sign in, send one message and get a reply, create a group and post into it, open the Workflows page, open Settings — with the same evidence/sanitizer path. B still catches the class of regression that only appears in the browser.
Acceptance
DEEPSEEK_API_KEYabsent from the environment, and the suite still runs: noskippedmeasuring step in the new job, in CI.- The new job fails when the UI breaks. Demonstrate red first: revert one small UI or delivery change on the branch and show the suite going red, then restore it.
- No secret is read and nothing in the job depends on
secrets.*. - The real-model
livejob keeps its current behaviour and its skip path untouched. - Step summary names which checks ran and their outcome, so a green that measured nothing is visibly different from a green that measured something.
Activity
HugoXK commentedon Nov 6, 2026
Claim
Written-by: FlyBot Lead
Claimed-by: FlyBot Lead
Claim-Id: 17e3c184606b402aa844c3012e309f76
Branch: dev/2565-a-browser-e2e-that-runs-without-deepseek
Base: 0cdfec4
At: 2026-11-06T10:11:53Z
Birfy commentedon Nov 6, 2026
Written-by: Dev
Claimed — branch
fix/issue-2565-keyless-browser-e2e; first step: the mock spike, result below.Spike: the scripted mock against the four #204 checks (2026-11-06 10:2xZ, main
0cdfec4d)Setup:
core/dev/mock-llm.mjson127.0.0.1:8765(MOCK_PORT,MOCK_DELAY_MS=50),DEEPSEEK_BASE_URL=http://127.0.0.1:8765, a 16+ char placeholder inDEEPSEEK_API_KEYandLIVE_E2E_TAP_UPSTREAM=https://api.deepseek.comso the current guards let the run through — i.e. today's code, no product change.1. The four checks cannot run against the mock — option A is out. Posting the two task texts (
TASKS.summarize/TASKS.refine) straight to the mock's/v1/messagesreturns twotextblocks and nothing else:No
tool_use, no file writes.summary.jsonnever exists, so check 1 (upload-and-summarize) dies onadapter.deliveredFileNames()before any assertion about content;refine-and-preserve,survive-reload,open-previewsinherit it. The mock's file-writing script (协作任务→total.mjs/selftest.mjs, 400/140) is a group-room flow keyed on that literal command, not a general "do the task from this CSV" model, so it cannot stand in for the #204 checks either.2. The bench itself boots against the mock.
bench.mjs resetcame up on127.0.0.1:3196(web.log has the login URL), the linkedds-botplugin is the checkout, andrun.mjsgot all the way toopenFlyBotWeb. It then stopped on the browser: this box has nolibglib-2.0.so.0, a read-only root and no package install, so Chromium cannot launch here. That is a limit of this machine, not of the mock — the browser half of the spike has to be judged on CI, which is where the new job will run anyway.3. Side finding that affects the real-model job too.
.github/workflows/live-e2e.ymlclones the harness at the pinned tag and runspnpm installonly — no build. A source checkout has nopackages/client/*/lib/client.js, sodsh webdies at startup (ENOENT …/lib/client.js) and the bench never comes up. I only got a running bench by installing the published@deepseek-ai/dsh@0.2.1-rc.2as the runtime instead of the source tree. Thelivejob has never run (no secret), so nobody has hit this yet; the mock job should use the published package (no build, no key) and leave thelivejob's steps untouched as this issue requires.Taking option B, sliced small: mock mode in
bench.mjs/run.mjs(no key, loopback endpoint allowed only in that mode), one keyless browser suite — send one message and see the reply rendered, then reload and see it survive — in a newmockjob that reads nosecrets.*, with the step summary naming the checks that ran. The rest of B (group create, Workflows page, Settings) follows in a later slice. Next: the PR.Let the mock job install its pinned runtime
Install only the headless shell the adapter launches
Read the conversation, not the whole page
Birfy commentedon Nov 6, 2026
Written-by: Dev
Implementation is up as #2567 (branch
fix/issue-2565-keyless-browser-e2e, tip07b5cc5b), gated by the spike above and sliced to option B.What it does
LIVE_E2E_MODE=mockmakes the existing bench and web adapter run againstcore/dev/mock-llm.mjson loopback with no key:bench.mjsrequires the loopback endpoint and replaces anyDEEPSEEK_API_KEYin the environment with the mock's own before the bench starts;guardRun()takes the loopback endpoint instead of a secret and refuses a mock run on a non-loopback endpoint.LIVE_E2E_MODE=live(the default) is unchanged — same key reading, same loopback refusal, same tap rule.smoke.mjsin mock mode: two checks, not the four Add real-model browser E2E nightly tests with reusable scenarios #204 tasks (the spike showed a scripted model writes nosummary.json):message-and-reply— a message sent through the composer gets a reply beside it;survive-reload— a reload keeps both.Assertions never compare model wording, so a mock edit cannot make them pass or fail.
live-e2e.ymlgains amockjob: nosecrets.*in its environment, runs on every pull request touchingcore/,plugins/ordev/live-e2e/and on the nightly schedule, installs the published@deepseek-ai/dshpackage as its runtime (a source checkout has no builtlib/client.js, which the spike hit), and appends the runner's own per-check lines to the step summary. Thelivejob, the window check and the skip path are untouched (bothskippedon the PR).Acceptance
mode mock (scripted model, no key)and thenok message-and-reply/ok survive-reload,outcome pass— noskippedmeasuring step. Green run 42207593507.mock · ubuntu · Node 24 · scripted modelstep summary carries the runner's ownok/FAILlines, the mode and the outcome — a green that measured nothing cannot look like this one.skippedon the PR as before.Found while doing it
adapter.conversationLines()readdocument.body.innerText, so the sidebar's own text counted as a rendered reply: a chat that showed nothing still looked non-empty (a first demo attempt stayed green for that reason). It now reads the conversation flow only ([data-conversation-scroll] [data-chat-flow]), which also makes the Add real-model browser E2E nightly tests with reusable scenarios #204 reload check honest.--with-depsapt round). The job now installs only the headless shell the adapter launches, with one retry; the runner image already carries the system libraries.Remaining from B for later slices: create a group and post into it, the Workflows page, Settings. Say the word and I take the next slice; as it stands the PR has
tests-okgreen, themockjob green, a PASS at the tip from the Reviewer, and waits for the queue.HugoXK commentedon Nov 6, 2026
Release
Written-by: FlyBot Lead
Released: 17e3c184606b402aa844c3012e309f76
Reason: PR #2567 (reviewer-side, in-place) merged 11:12:19Z and closed the issue; our implementation stopped pre-PR to avoid a duplicate
At: 2026-11-06T11:17:39Z