blob: a3c2bc39724fdc19a7060dc369aa3da78173defd [file]
import assert from 'node:assert/strict';
import test from 'node:test';
import {
sanitizeCuDirectReport,
sanitizeCuModelPlans,
sanitizeCuReport,
} from './cu-report-sanitize.mjs';
test('CU reports keep metrics while dropping typed text, coordinates, URL secrets, and trace payloads', () => {
const secret = 'secret-canary';
const report = sanitizeCuDirectReport({
schemaVersion: 1,
evidenceClass: 'real-runtime',
scenarioId: 'l1-single-click',
model: 'gpt-test',
baseUrl: `https://user:${secret}@example.test/v1?token=${secret}`,
actions: [
{
action: { type: 'type', text: secret, x: 12, y: 34 },
durationMs: 5,
text: `computer.type failed: unsupported_action ${secret}`,
},
],
traces: [
{
type: 'dispatch',
actionType: 'type',
expectedPid: 42,
winnerPid: 84,
title: secret,
raw: { secret },
durationMs: 4,
},
],
});
const serialized = JSON.stringify(report);
assert.equal(report.endpointOrigin, 'https://example.test');
assert.deepEqual(report.actions, [
{
type: 'type',
durationMs: 5,
resultCode: 'unsupported_action',
},
]);
assert.deepEqual(report.traces, [
{
type: 'dispatch',
actionType: 'type',
expectedPid: 42,
winnerPid: 84,
durationMs: 4,
},
]);
assert.doesNotMatch(serialized, new RegExp(secret));
assert.doesNotMatch(serialized, /"x":12|"y":34/);
});
test('model plans expose only turn and action types', () => {
const plans = sanitizeCuModelPlans([
{
turn: 1,
responseId: 'private-response',
actions: [
{ type: 'click', x: 20, y: 40 },
{ type: 'type', text: 'private' },
],
},
]);
assert.deepEqual(plans, [
{
turn: 1,
actionTypes: ['click', 'type'],
},
]);
});
test('report sanitizer preserves validated attribution and drops arbitrary fields', () => {
const report = sanitizeCuReport({
schemaVersion: 1,
evidenceClass: 'real-runtime',
scenarioId: 'l0-observe-only',
producer: 'cu-real-model-launcher',
transportClass: 'live-network',
policyMode: 'bypassed',
qualificationEligible: true,
provider: 'openai',
model: 'gpt-5.4',
status: 'inconclusive',
run: { status: 'waiting_for_user' },
failure: 'private provider body',
loopStatus: { private: true },
turns: [{ text: 'private' }],
state: { private: true },
display: { private: true },
traces: [
{
type: 'dispatch',
actionType: 'click_element',
path: 'private-path',
effect: 'private-effect',
address: 'ax',
tool: 'click',
},
],
});
assert.equal(report.producer, 'cu-real-model-launcher');
assert.equal(report.provider, 'openai');
assert.equal(report.model, 'gpt-5.4');
assert.equal(report.qualificationEligible, true);
assert.equal(report.run.status, 'waiting_for_user');
assert.deepEqual(report.traces, [
{
type: 'dispatch',
actionType: 'click_element',
address: 'ax',
tool: 'click',
},
]);
const serialized = JSON.stringify(report);
assert.doesNotMatch(serialized, /private/);
assert.doesNotMatch(serialized, /loopStatus|turns|display/);
});
test('canonical evidence keeps privacy-safe ownership and observation lineage', () => {
const generatedAt = '2026-07-12T00:00:00.000Z';
const gitRevision = '0123456789abcdef0123456789abcdef01234567';
const report = sanitizeCuReport({
schemaVersion: 1,
runId: 'run-1',
gitRevision,
generatedAt,
contentLineage: {
generator: 'scripts/cu-real-ax-model-e2e.mjs',
gitRevision,
generatedAt,
},
evidenceClass: 'fault-injection',
scenarioId: 'appkit-ax-intervention-recovery',
producer: 'cu-real-ax-model-e2e',
transportClass: 'live-network',
policyMode: 'enforced',
qualificationEligible: false,
fixtureIdentity: {
instances: [
{ pid: 42, windowIds: [7, 7, -1] },
{ pid: 84, windowIds: [9] },
],
},
faultInjection: { layer: 'runtime', kind: 'user_intervened' },
actions: [
{
action: { type: 'set_value', value: 'private' },
toolCallId: 'tool-1',
sourceObservationId: 'observation-1',
resultObservationId: 'observation-2',
targetPid: 42,
targetWindowId: 7,
targetOwned: true,
success: true,
},
],
actionAttempts: 1,
traces: [
{
type: 'dispatch',
toolCallId: 'tool-1',
actionType: 'set_value',
pid: 42,
windowId: 7,
address: 'ax',
tool: 'set_value',
},
],
});
assert.deepEqual(report.fixtureIdentity, {
instances: [
{ pid: 42, windowIds: [7] },
{ pid: 84, windowIds: [9] },
],
});
assert.equal(report.runId, 'run-1');
assert.equal(report.gitRevision, gitRevision);
assert.equal(report.generatedAt, generatedAt);
assert.deepEqual(report.contentLineage, {
generator: 'scripts/cu-real-ax-model-e2e.mjs',
gitRevision,
generatedAt,
});
assert.equal(report.actionAttempts, 1);
assert.deepEqual(report.faultInjection, {
layer: 'runtime',
kind: 'user_intervened',
});
assert.deepEqual(report.actions[0], {
type: 'set_value',
toolCallId: 'tool-1',
sourceObservationId: 'observation-1',
resultObservationId: 'observation-2',
targetPid: 42,
targetWindowId: 7,
success: true,
targetOwned: true,
});
assert.deepEqual(report.traces[0], {
type: 'dispatch',
toolCallId: 'tool-1',
actionType: 'set_value',
pid: 42,
windowId: 7,
address: 'ax',
tool: 'set_value',
});
});