test(cu): define provider evidence contract - #913
Conversation
|
@Astro-Han Provider evidence contract is isolated on current main and CI typecheck/test/e2e are green. It makes l0-observe-only the first enabled real-model scenario, rejects hermetic or mismatched reports for real readiness, and adds the new contract tests to test:scripts. It does not modify Runtime/Desktop/executor or claim a real run. Recommended after #910 and #911; the next PR will add only launcher/runtime wiring. |
79b0178 to
69f6574
Compare
|
@astrohan The follow-up real-runtime runner is now proven locally on top of #910/#911/#913/model foundation. Live results: gpt-5.6-sol and claude-sonnet-4-6 each completed real AppKit AX set_value through getAIModel -> AiSdkBackend -> ToolRuntime -> maka_computer -> cua-driver; OpenAI also passed observe-only, user-intervention recovery, process-restart target_missing recovery, and one AX click. All mutation runs had exactly one AX dispatch and zero pixel dispatch. The runner emits only sanitizeCuDirectReport output. One evidence-layer bug found and fixed in the follow-up: sanitizeCuDirectReport hard-coded producer=cu-openai-model-e2e, mislabeling Anthropic runs; it now preserves explicit producer/provider. Kimi/MiniMax have hermetic product-loop coverage but no live credential on this Mac, so they remain contract evidence. |
|
@Astro-Han Final current-main CI is fully green. The launcher now has two qualifying real-runtime OpenAI gpt-5.4 runs through production Desktop/SessionManager/AiSdkBackend/maka_computer/cua-driver: L0 observe-only (one observe, zero interactions) and L1 AX mutation (two observes + one click_element, primary=1, danger=0, duplicate=0; no coordinate/CGEvent action). The run also found and fixes the OpenAI Responses orphan item_reference continuation bug by setting store:false. Sanitized lab evidence passes the no-secrets check. Ready for review/merge after #911 or independently if preferred. |
236679d to
a486283
Compare
|
@Astro-Han Rebased onto current main after #911 and later provider merges; CI typecheck/test/e2e is green. The branch includes both qualifying real-runtime reports: OpenAI gpt-5.4 L0 observe-only and L1 AX click_element, plus the store:false Responses continuation fix. Ready for review. |
a486283 to
8592748
Compare
|
@Astro-Han Rebased #913 onto current main (now includes #918 and Cohere) and force-pushed 8592748. Local test:scripts 56/56, Runtime/Desktop typecheck pass; new CI is queued. The external AppKit/provider follow-up remains isolated in fork PR hqhq1025#10 and does not alter this PR. |
Astro-Han
left a comment
There was a problem hiding this comment.
Approved because I did not find a P0 or P1. The following findings are non-blocking, but they should remain visible as P2/P3 follow-ups.
-
[P2] The two report sanitization paths do not enforce the stated privacy and attribution contract.
sanitizeCuDirectReport()copiesloopStatus,turns,state, anddisplayverbatim, permits arbitrarypath/effecttrace strings, hard-codes the OpenAI producer, and drops the provider identity. The real-model launcher does not use this sanitizer and writes its outererror.messagedirectly. Route every emitted report through one schema-driven sanitizer and preserve only validated attribution fields. -
[P2] The provider matrix does not understand the canonical scenario schema or the launcher status.
normalizeFixture()readsscenario.fixture, while the shipped scenarios definefixtureSetupandexpectedState;rowStatus()also ignoresreport.status. A canonical inconclusive report therefore has no fixture oracle and can still becomepass-policy-bypassed(orpasswith an enforced policy). Evaluate the canonical assertions and require a passing launcher status. -
[P2] Missing forbidden-effect evidence is treated as success. At
cu-provider-matrix.mjs:161-165, an absent value skips the check, and canonical assertions are window-scoped while the lookup reads directly from the report root. A report can omit every forbidden-effect value and receiveforbiddenEffects.status = pass. Missing required evidence should make the row invalid or inconclusive. -
[P2] A real report is accepted after checking only
scenarioIdandevidenceClass. The matrix does not bindschemaVersion, producer, transport, provider/model, report status, action types, allowlist, or action budgets. The same report can satisfy multiple provider rows, and an over-budget or disallowed action sequence is still accepted. Validate the full evidence envelope against both the provider row and scenario. -
[P2] Failed or wrong-target tool calls satisfy minimum action counts.
actionRecords()records every pairedtool_resultwithout checkingisError, the result code, or the bound fixture target. For L0, a failedobserve—or anobserveof another app—can count as the required action while the untouched fixture already satisfies its state oracle. Count only successful actions proven to target the owned fixture. -
[P2] Non-success terminal reasons can qualify a run.
terminalPassedaccepts everycompleteexceptuser_stop, so a run ending inmax_tokens,step_limit,error, or a handoff can qualify after meeting the minimum count. Require the intended successful stop reason, currentlyend_turn. -
[P2] Real-model mode fails open when its policy is missing.
applyComputerUseRealModelPolicy(tools, undefined)returns the complete Computer Use tool set even when the real-model E2E switch is active. Treat a missing policy as a startup error or an empty tool set. -
[P2] The dispatch policy is not bound to the owned fixture and ignores per-action budgets. It checks only the action name and a total count. An allowed click can target an unrelated app/window, and
maxActionCountsfrom the scenario is never enforced before dispatch. Bind allowed actions to the fixture PID/window/observation and enforce each scenario budget. -
[P2] The saved driver evidence cannot distinguish AX, pixel, and page dispatch.
sanitizeCuTrace()removes the dispatchtoolandaddressfields, andqualifiednever consultsdriverTraces. The L1 report can therefore claim semantic AX coverage without evidence that differs from a pixel dispatch. Retain a privacy-safe dispatch class and require the expected path for qualification. -
[P2] The launcher ignores
scenario.runnerandrequiresExecutionCapabilities. L4 and L5 declare dedicated runners, and several scenarios declare required capabilities, but the launcher sends all enabled scenarios through the ordinary model/fixture path without checking either field. Dispatch to the declared runner and fail closed when required capabilities are unavailable. -
[P2] The enabled L3 stale-window scenario cannot reach the model run. The fixture applies the replacement during creation and removes
stalefrom its map, butcu-real-model-fixture.mjs:17-21then iterates the original window list and callsgetWindow("stale"). That throws beforeCU_FIXTURE_READY. Raise the surviving fixture windows instead of the original specs. -
[P3] Partial fixture construction can leave windows alive until process teardown. A failed
loadURLor later window creation rejects before the fixture handle is assigned, so neither the helper nor the caller can destroy already-created windows. Clean up insidecreateCuE2eFixture()on construction failure. -
[P3] Scenario validation accepts contradictory budgets. It does not require count keys to be in
allowedActions, does not require minimum counts to be at most maximum counts, and does not reconcile per-action counts withmaxTotalActions. Reject internally inconsistent scenarios at definition time. -
[P3] A malformed
forbiddenEffects.violationsvalue crashes the entire matrix. The spread atcu-provider-matrix.mjs:171assumes an array. Validate the report shape and mark only that row invalid.
Summary
Current-main real-model Computer Use evidence, launcher, and provider continuation fix.
maka_computerdispatchreal-runtime, hermetic protocol, and static evidencestore:false, fixing orphanitem_referencefailures during tool-result continuation and avoiding provider-side item storageThe E2E-only direct tool exposure narrows the provider surface to the production
maka_computerimplementation. It does not register FakeBackend or replace Runtime/executor behavior.Qualifying real runs
OpenAI
gpt-5.4,l0-observe-only:observecomplete/end_turnOpenAI
gpt-5.4,l1-single-click:click_elementcomplete/end_turnSanitized evidence is stored in the external Computer Use lab:
fixtures/model-tool-surface/maka-openai-gpt-5.4-l0-observe-real-runtime.jsonfixtures/model-tool-surface/maka-openai-gpt-5.4-l1-ax-click-real-runtime.jsonVerification
npm run test:scripts(54/54 current-main)check-no-secrets.mjsgit diff --check