feat(evals): three proof primitives (screenshot / validate / photoRoll) + first core-journey specs - #3322
Conversation
…ipping the legacy baseline
… legacy flows (the action is conditionally registered, not phantom)
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Update: readiness + isolation moved into the lifecycle layerPer review feedback, the spec-level state management is gone. Readiness and isolation are now postconditions of acquiring the handle, owned by the lifecycle layer — the same contract await using app = await desktop({ name: "app-smoke" }); // fresh profile, ready, disposable
Deleted, because they only existed to fake isolation on one shared app: Real-run status (Daytona, den stack + per-spec Electron)
Three environmental blockers were fixed along the way to get isolated Electron running inside a container at all: Chromium's SUID sandbox ( CI is unaffected: the |
What
Replaces the bundled proof helper with three independent primitives for evidence, and starts moving the eval suite onto the core user journeys.
Before,
fraimz(annotate)captured a screenshot and recorded it in one call, validated nothing, and coupled proof to vitest. Now:screenshot(app) → Shot— capture only.validate(shot, expectations) → SeenFacts— describe-then-match (the model describes the screen with no knowledge of the expectations, then judges each one with an evidence quote, so it can't rubber-stamp), structured verdict, cached by pixel hash so re-runs are deterministic and free, transport injectable for tests. Throws when no provider key is configured — missing infrastructure is a throw, not a soft pass.photoRoll(name) → Roll— writesindex.html+roll.json, and refuses duplicate pixels within a roll (the anti-fabrication guard the legacy runner had).@openwork/fraimznow contains zero vitest imports, so the same three calls work in a spec, in a support script, or in the legacy runner. That deletes the custom-reporter design entirely.Also in this PR: CI wiring for the spec lanes (
prgates every PR;nightlyruns the app specs), four new behaviour modules (onboarding, composer, models, skills) extracted from legacy flows, three core-journey specs (first-run-local, skills-local, models-available), and an idempotentensureReadyWorkspaceso specs are order-independent.Tests run
Local:
pnpm evals:typecheckclean ·pnpm --dir evals run test91/91 (includes new network-free unit tests forphotoRollandvalidate) ·pnpm --dir evals run spec4/4 (theprlane — real egress labs + shipped product diagnostics) ·rg vitest evals/packages/fraimz/src→ empty.Real app + den stack in a Daytona sandbox (MariaDB + den-api + den-web + seeded org + Electron +
OPENAI_API_KEYfrom the secrets volume), four full runs while iterating.The primitives work end to end —
first-run-localproduced a 5-frame roll, 10/10 expectations passed, with genuine model descriptions:More importantly, on their first real runs the primitives caught two defects that DOM assertions missed:
Duplicate screenshot pixels for "The open Models picker visibly explains that a different model must be selected"; the same pixels were already added as "A Model no longer available warning…"— the spec claimed an interaction it never performed. Fixed by actually opening the picker via the realsession.model_picker.openaction.Failed 1/2 visual expectations: The composer capability menu visibly shows Agents, Commands, Skills, and Extensions — Only centered text reading "Preparing workspace" is visible; no composer capability menu appears.— a premature assertion against a still-loading app.Status of the app-driving specs — honest
The three new core-journey specs and the two retrofitted ones are not green yet against a real app: remaining failures are app-state readiness/restoration (onboarding reset semantics, restoring a deliberately-seeded unavailable model, waiting out "Preparing workspace"). They are nightly-only,
skipIf(!OPENWORK_EVAL_CDP_URL), and the nightly step iscontinue-on-errorwith a comment, so nothing gates on them while they stabilise — they still publish photo rolls as evidence. Theprlane (egress labs) is fully green and now actually gates.Also,
first-run-localdocuments a product truth rather than papering over it: with no cloud and no in-app provider key, a first-run user reaches the task UI but cannot run a task ("Connect a model provider"), so the "runs a task and sees a response" half ofevals/onboarding-welcome-flows.md's review bar is explicitly not proven yet.Note
An earlier commit in this branch refactored 15 legacy flows away from
composer.set_texton my incorrect claim that the action didn't exist. It does exist — it is conditionally registered by the session surface (session-surface.tsx:1381,requiresArgs: true), so my single snapshot was incomplete. That refactor is reverted; the behaviour now prefers the product's own control seam and keeps a DOM fallback.