Repository navigation
fix(evals): saved-app creation opens its verification return tab as a person's tab, not agent browser control - #4779
Conversation
…immediately A freshly created session had no cached snapshot, so deriveSessionRenderModel reported "switching" while the first snapshot round trip ran and the composer disabled Run task. On Daytona that window is ~0.9 s and a click or Enter inside it was silently dropped with the draft intact. Seed the snapshot cache from the create response (stale, so the real fetch still runs as a background refresh).
…ad of wedging A prompt_async answered with 5xx/408 is an uncertain admission (#4635), but the hold it created could never end: the acceptance check treated absence as no evidence, Stop refused while the admission was unknown, and the failure body was dropped, so the person saw a paused composer with no explanation. - Keep the settled response body on PromptAdmissionUnknownError and show it as the session error card right away; the hold still prevents any resend. - readPromptAdmission: after the exact-message GET misses, list the idle conversation; when native lists it without the message the POST is settled and did not admit, so the drain receives admission_rejected and halts like any definite failure (explicit retry only, never an automatic resend). - On release the pending row is removed and the submitted composer is kept as an unsent message to restore; on confirmed acceptance the stale failure card is cleared.
Lexical keeps one empty paragraph in an empty editor, which innerText reports
as "\n". readComposerState now drops that trailing line break so draftText
matches what the person sees; user.see("composer", { text }) already trimmed.
…o e2e/saved-app-browser-requesting-conversation
… new tab returnVerification drove the agent browser entry point (browser.openUrl, the IPC behind browser.open_url) with no requesting conversation. Since #4434 the task host refuses that, and it never accepted an about:blank destination. The tab only stands in for the person's own browser so the openwork:// return link can be navigated without OS protocol registration, so create it the way a person opens a new tab and find its CDP target by diffing the page targets.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Warden review summary — ClearNative findings: 0. Blocking policy matches before consolidation: 0. Full finding text remains in Warden's native checks and review threads. This comment retains only native IDs, severity, skill attribution, and safe locations. Analysis run Reported trigger coverage (not proof of complete repository or context coverage): diff-security-review (82461 ms), confidentiality-review (206220 ms), spec-provenance-review (92582 ms), desktop-den-sync-review (131630 ms). Blockers
Advisories
Needs recheck
Observed review-thread metrics
Thread states are read-only collection snapshots. These metrics are neither lifetime totals nor exact resolution times, and this summary is not clearance authority. |
There was a problem hiding this comment.
Warden security clearance: clear. No blocking findings (security or desktop↔den sync) in this diff (8ced4002cc82eb18fb24c66e844b4f67f988538b). Automated clearance satisfies the required-review gate only — a human still reviews and merges. Analysis run
|
Passed · 12/12 tests · 18/18 assertions · 8 images Commit |
…o e2e/saved-app-browser-requesting-conversation
…requesting-conversation
Deploying openwork with
|
| Latest commit: |
1afdc27
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://a80aba17.openwork.pages.dev |
| Branch Preview URL: | https://e2e-saved-app-browser-reques.openwork.pages.dev |
There was a problem hiding this comment.
Warden security clearance: clear. No blocking findings (security or desktop↔den sync) in this diff (1afdc2757bae3c517d03951dcdaa58860b2199da). Automated clearance satisfies the required-review gate only — a human still reviews and merges. Analysis run
Resync onto
|
| test | result |
|---|---|
create, preview, save and reopen an app without changing already-open results (this PR's spec) |
✓ passed (331.9 s) — all steps ok, including every returnVerification call |
APP-ISOLATION embedded MCP Apps isolate siblings… (added to this file by #4829 today) |
× failed in world provisioning after 53 s, before any assertion: Mock issuer gate failed: health reported https://3979-…, expected https://3979-… |
"passed":1,"failed":1,"skipped":0 → file verdict Failed, but the red test is not this PR's: isolatedMcpApps seeds two seed.mock(...) without explicit ports into one appWeb sandbox, so both get daytonaPort: 3979 (evals/packages/env/src/mock.ts:56); bootRemoteMocks starts them sequentially on the same sandbox and the second mock's pkill -f mock-oauth-mcp-server + rebind on the same port makes the health gate see the first mock's issuer. Reproduced identically 2/2 at this sha (first run also hit a hung mock process cleanup exec on the Den sandbox → 600 s timeout; re-run per policy). #4829 proved that test with --local --engine v1 --case APP-ISOLATION only, never --daytona; the co-located Daytona path is not exercised locally. Attribute to #4829 — give second a distinct port (e.g. 3980). This PR does not touch that world/spec code.
Sandboxes: all created by run 2 deleted by the runner; run 1's leaked openwork-server-20260910-213758-… deleted manually.
Root cause
Triage:
/Users/guillaume/OpenWork Chat/reports/e2e-red-2026-09-09/triage.md—saved-app-creation, failure atworlds/saved-apps.ts:163(returnVerification) withError invoking remote method 'openwork:browser:openUrl': Browser control requires a requesting conversation.(dev nightly @ 52a0288, PR #4757 run @ 564e17c).The spec's world channel, not the product, lacked the origin.
returnVerificationcreated its vehicle tab through the agent entry point —window.__OPENWORK_ELECTRON__.browser.openUrl("about:blank", "builtin"), the same IPC behind thebrowser.open_urlaffordance — without a requesting conversation. Since #4434 (1d2fc5b) the browser task host correctly refuses that (browser-task.mjsmissing_session), and it never accepted anabout:blankdestination either (browserTaskUrlonly allows http(s)); stamping an origin would just have moved the failure toinvalid_urlplus a consent prompt.The tab is only a stand-in for the person's own browser: containers have no OS protocol registration, so the world navigates the real
openwork://den-reauthreturn link in an Electron tab and the main process intercepts it ondid-start-navigationfor any tab, owner or not. The honest channel for that is the person's new-tab path (browser.createTab, a null-owner "shared" tab) — already used byworlds/browser-panel.tsas "explicit human-created initial state, not an automation navigation". No product change; the requesting-conversation requirement is not bypassed or weakened.What changed
evals/worlds/saved-apps.tsreturnVerification: create the return tab withbrowser.createTab("about:blank")and find its CDP target by diffing page targets (that IPC returns onlytabId). Navigation, deep-link interception and tab close are unchanged.origin/e2e/fresh-session-send-gate(564e17c) so the spec gets past the send step (Cluster 1); those commits are not part of this fix.Proof
pnpm evals:e2e saved-app-creation --daytonawithOPENWORK_EVAL_REF=8ced4002cc82eb18fb24c66e844b4f67f988538b(source verified8ced4002cin the sandbox log). Placement line:selection: engine=legacy surface=legacy case=all; placement: daytona (--daytona).Three runs (each provisioned its own Den + two desktop sandboxes and deleted all three):
returnVerificationcalls in "share dashboard apps with a teammate")returnVerification)Verify passwordproduced Better-Auth "Provider not found" (a social sign-in fired) 370 ms after a client-side route changeThe cluster claim is proven: every
returnVerificationcall now completes and the subsequent assertions (unrelated callback rejected, verified link shared 1 app, late callback left#/dashboard, browser-return grant gave the recipient 200) pass. The whole spec is not green yet: verdictFailedat later steps that have different root causes, so this PR does not claimsaved-app-creationPassed.Noticed, not touched
saved-app-creation.e2e.test.ts:523: afterworld.open("/dashboard")(go()only sets the hash and returns) theclick("App options for Team briefing")resolves in ~110 ms — most likely the still-mounted app-page header button — and thenDelete Team briefingis never found; after 30 s the only visible buttons are the shell rail (New session,Dashboard,Library, …), i.e. the main content renders nothing. Looks like a product issue on route change with an open header menu, not just spec ordering; needs a screenshot/error-boundary look./reauth/desktopwith an existing cookie session,type Password+click("Verify password")within ~0.4 s of the client-side nonce change ended in "Provider not found" — a social button received the click. Testkit text click vs. dialog layout race, or the dialog should not shift while opening.pnpm --dir evals typecheckis red ondevindependent of this change (unbuilt@openwork-ee/den-db/@openwork/emailoutputs,Promise.withResolverslib target);worlds/saved-apps.tsitself has no errors andcheck:browserpasses.