2026-10-10 22:11:14 +08:00
import assert from "node:assert/strict" ;
import { createHash } from "node:crypto" ;
import { mkdir , mkdtemp , readFile , writeFile } from "node:fs/promises" ;
import { homedir , tmpdir } from "node:os" ;
import { join , relative } from "node:path" ;
import { fileURLToPath } from "node:url" ;
2026-10-26 15:34:11 +08:00
import { TOOL_CONTRACTS } from "../dist/contracts/toolContracts.js" ;
2026-10-24 19:38:57 +08:00
import { createVerifierCommands } from "./lib/verify-commands.mjs" ;
import { withVerifierCleanup } from "./lib/verifier-cleanup.mjs" ;
import { saveVerifierCommandOutput } from "./lib/verifier-command-output.mjs" ;
2026-10-26 15:34:11 +08:00
import {
CLIENT_JAVASCRIPT_FIXTURE_SOURCE ,
assertClientJavaScriptFixtureEvidence ,
} from "./verify/clients/javascript-fixture.mjs" ;
2026-10-10 22:11:14 +08:00
import { createVerifierRun , completeVerifierRun } from "./lib/verifier-run.mjs" ;
import { createOpenAiModelFixture } from "./verify/clients/model-fixture.mjs" ;
assert (
process . platform !== "win32" ,
"Native OMP verifier requires POSIX; Windows is unverified" ,
);
const repo = fileURLToPath ( new URL ( ".." , import . meta . url ));
const runtimeRoot = process . env . REA_VERIFY_RUNTIME_ROOT ?? repo ;
const command = process . env . REA_VERIFY_OMP_COMMAND ?? "omp" ;
const mode = process . argv [ 2 ] ?? "call" ;
assert (
[ "chat" , "call" ]. includes ( mode ),
"Usage: verify-omp-client.mjs [chat|call]" ,
);
const verifier = createVerifierRun ();
const lab = await mkdtemp ( join ( tmpdir (), "rea-omp-client-" ));
const account = join ( lab , "account" );
const agent = join ( lab , "selected agent" );
const workspace = join ( lab , "workspace" );
const configPath = join ( agent , "mcp.json" );
const skillDirectory = join (
account ,
".agents" ,
"skills" ,
"reverse-engineer-anything" ,
);
const expectedDevices = TOOL_CONTRACTS . map (
( tool ) => "mcp__rea_" + tool . name ,
). sort ();
2026-10-24 19:38:57 +08:00
let clientVersion = null ;
2026-10-10 22:11:14 +08:00
let expectedSkillBody ;
let skillLoaded = false ;
let contractRead = false ;
let evidenceSeen = false ;
let artifactDigest ;
let finalSeen = false ;
let catalogMounted = false ;
2026-10-24 19:38:57 +08:00
let catalogSize = null ;
2026-10-10 22:11:14 +08:00
let invalidProfileRejected = false ;
2026-10-24 19:38:57 +08:00
let passed = false ;
let fixture ;
const commands = await createVerifierCommands ();
await withVerifierCleanup ( async () => {
await withVerifierCleanup ( async () => {
await Promise . all ([
mkdir ( account ),
mkdir ( agent ),
mkdir ( workspace ),
...[ "data" , "state" , "cache" ]. map (( name ) =>
mkdir ( join ( lab , name , "omp" ), { recursive : true }),
),
]);
await commands . exec ( "git" , [ "init" , "--quiet" , workspace ], {
timeout : 30_000 ,
stdin : "pipe" ,
});
// OMP's global config root uses native homedir independently of the agent override.
// A documented relative PI_CONFIG_DIR redirects it without changing HOME.
const environment = {
PATH : process . env . PATH ,
NODE_OPTIONS : process . env . NODE_OPTIONS ,
USERPROFILE : account ,
PI_CODING_AGENT_DIR : agent ,
PI_CONFIG_DIR : relative ( homedir (), join ( lab , "native-config" )),
OMP_PROFILE : "" ,
XDG_DATA_HOME : join ( lab , "data" ),
XDG_STATE_HOME : join ( lab , "state" ),
XDG_CACHE_HOME : join ( lab , "cache" ),
REA_PROCESS_RUN_ID : verifier . run_id ,
};
const target = join ( lab , "fixture α测试" );
await mkdir ( target );
2026-10-26 15:34:11 +08:00
await writeFile ( join ( target , "app.js" ), CLIENT_JAVASCRIPT_FIXTURE_SOURCE );
2026-10-24 19:38:57 +08:00
const analysisDevice = "xd://mcp__rea_analyze_javascript_application" ;
const containsText = ( value , text ) => {
if ( typeof value === "string" ) return value . includes ( text );
return (
value !== null &&
typeof value === "object" &&
Object . values ( value ). some (( item ) => containsText ( item , text ))
2026-10-10 22:11:14 +08:00
);
2026-10-24 19:38:57 +08:00
};
const call = ( index , name , args ) => ({
role : "assistant" ,
content : null ,
tool_calls : [
{
id : `call_omp_ ${ index } ` ,
type : "function" ,
function : { name , arguments : JSON . stringify ( args ) },
},
],
});
fixture = await createOpenAiModelFixture ({
directory : lab ,
prefix : "omp" ,
onRequest : async ({ body , tools , requestIndex }) => {
assert ( tools . some (( tool ) => tool . name === "read" ));
assert ( tools . some (( tool ) => tool . name === "write" ));
const instructions = body . messages . filter (
( message ) => message . role === "system" ,
);
for ( const device of expectedDevices )
assert (
containsText ( instructions , device ),
`OMP must advertise mounted device ${ device } ` ,
);
if ( mode === "chat" ) {
finalSeen = true ;
return { role : "assistant" , content : "REA_CLIENT_COMPATIBILITY_OK" };
}
const replies = body . messages . filter (
( message ) => message . role === "tool" ,
);
if ( requestIndex === 1 )
return call ( requestIndex , "read" , {
i : "Load REA skill" ,
path : "skill://reverse-engineer-anything:raw" ,
});
assert (
expectedSkillBody !== undefined &&
containsText ( replies , expectedSkillBody ),
"OMP must return the complete installed skill body" ,
);
skillLoaded = true ;
if ( requestIndex === 2 )
return call ( requestIndex , "read" , {
i : "Inspect REA native tool contract" ,
path : analysisDevice ,
});
assert (
containsText ( replies , "# mcp__rea_analyze_javascript_application" ),
);
assert (
containsText ( replies , "input_path" ) &&
containsText ( replies , '"directory"' ),
);
contractRead = true ;
if ( requestIndex === 3 )
return call ( requestIndex , "write" , {
path : analysisDevice ,
content : JSON . stringify ({
input_path : target ,
format : "directory" ,
}),
});
const evidenceReply = replies . find (
( reply ) =>
typeof reply . content === "string" &&
reply . content . startsWith ( '{"evidence_id":' ),
);
assert (
evidenceReply ,
"OMP must deliver the full analysis result to the next model turn" ,
);
2026-10-26 15:34:11 +08:00
const { evidence } = await assertClientJavaScriptFixtureEvidence (
JSON . parse ( evidenceReply . content ),
target ,
2026-10-24 19:38:57 +08:00
);
const bytes = JSON . stringify ( evidence );
artifactDigest = createHash ( "sha256" ). update ( bytes ). digest ( "hex" );
await writeFile ( join ( lab , "omp-evidence.json" ), bytes );
evidenceSeen = true ;
finalSeen = true ;
return { role : "assistant" , content : "REA_CLIENT_COMPATIBILITY_OK" };
},
});
const original = JSON . stringify (
{
mcpServers : { other : { command : "unrelated-server" , enabled : false } },
disabledServers : [ "rea" , "other" ],
},
null ,
2 ,
2026-10-10 22:11:14 +08:00
);
2026-10-24 19:38:57 +08:00
await writeFile ( configPath , original );
await writeFile (
join ( agent , "config.yml" ),
JSON . stringify ({
skills : { customDirectories : [ join ( account , ".agents" , "skills" )] },
retry : { fallbackChains : { default : [] } },
}),
2026-10-10 22:11:14 +08:00
);
2026-10-24 19:38:57 +08:00
await writeFile (
join ( agent , "models.yml" ),
JSON . stringify ({
providers : {
"rea-fixture" : {
baseUrl : fixture . baseUrl ,
apiKey : "local-fixture-key" ,
api : "openai-completions" ,
models : [
{
id : "rea-client-fixture" ,
name : "REA local fixture" ,
reasoning : false ,
input : [ "text" ],
cost : { input : 0 , output : 0 , cacheRead : 0 , cacheWrite : 0 },
contextWindow : 1000000 ,
maxTokens : 4096 ,
},
],
},
},
}),
2026-10-10 22:11:14 +08:00
);
2026-10-24 19:38:57 +08:00
const rea = async ( args , env = environment ) =>
commands . exec (
process . execPath ,
[ join ( runtimeRoot , "scripts/rea.mjs" ), ... args , "--json" ],
{ env , cwd : workspace , timeout : 60_000 , stdin : "pipe" },
);
clientVersion = (
await commands . exec ( command , [ "--version" ], {
env : environment ,
timeout : 30_000 ,
stdin : "pipe" ,
})
). stdout . trim ();
const invalidEnvironment = { ... environment , OMP_PROFILE : "Bad Name" };
const nativeRejected = await commands
. exec ( command , [ "--print" , "--no-session" , "--no-title" , "Hello" ], {
env : invalidEnvironment ,
cwd : workspace ,
timeout : 30_000 ,
stdin : "pipe" ,
})
. then (
() => undefined ,
( cause ) => {
if ( typeof cause ? . code !== "number" || cause . code === 0 ) throw cause ;
return cause ;
},
2026-10-10 22:11:14 +08:00
);
assert (
2026-10-24 19:38:57 +08:00
nativeRejected ? . code === 1 &&
nativeRejected . snapshot . stderr . text . includes (
'Invalid OMP profile "Bad Name"' ,
),
2026-10-10 22:11:14 +08:00
);
2026-10-24 19:38:57 +08:00
await writeFile (
join ( lab , "invalid-profile-native.stderr" ),
nativeRejected . snapshot . stderr . text ,
2026-10-10 22:11:14 +08:00
);
2026-10-24 19:38:57 +08:00
const setupRejected = await rea (
[ "setup" , "--client" , "omp" , "--dry-run" ],
invalidEnvironment ,
). then (
() => undefined ,
( cause ) => {
if ( typeof cause ? . code !== "number" || cause . code === 0 ) throw cause ;
return cause ;
2026-10-10 22:11:14 +08:00
},
2026-10-24 19:38:57 +08:00
);
assert ( typeof setupRejected ? . code === "number" && setupRejected . code !== 0 );
const rejected = JSON . parse ( setupRejected . snapshot . stdout . text );
assert . equal ( rejected . status , "needs_human" );
assert . deepEqual ( rejected . plannedActions , []);
assert . deepEqual ( rejected . appliedActions , []);
assert ( rejected . remediation . includes ( 'Invalid OMP profile "Bad Name"' ));
assert . equal ( await readFile ( configPath , "utf8" ), original );
2026-10-10 22:11:14 +08:00
await writeFile (
2026-10-24 19:38:57 +08:00
join ( lab , "invalid-profile-setup.json" ),
setupRejected . snapshot . stdout . text ,
2026-10-10 22:11:14 +08:00
);
2026-10-24 19:38:57 +08:00
invalidProfileRejected = true ;
for ( const args of [
[ "setup" , "--client" , "omp" , "--dry-run" ],
[ "setup" , "--client" , "omp" , "--yes" ],
[ "doctor" , "--client" , "omp" , "--skill" ],
]) {
const result = await rea ( args );
await writeFile (
join (
lab ,
` ${ args [ 0 ] }${ args . includes ( "--dry-run" ) ? "-plan" : "" } .json` ,
),
result . stdout ,
2026-10-10 22:11:14 +08:00
);
2026-10-24 19:38:57 +08:00
const parsed = JSON . parse ( result . stdout );
if ( args [ 0 ] === "doctor" ) assert . equal ( parsed . healthy , true );
else {
assert . equal (
parsed . status ,
args . includes ( "--dry-run" ) ? "planned" : "ready" ,
2026-10-10 22:11:14 +08:00
);
2026-10-24 19:38:57 +08:00
if ( args . includes ( "--dry-run" )) {
assert (
parsed . plannedActions . some (
( action ) => action . target === configPath ,
),
);
assert (
parsed . plannedActions . some (
( action ) => action . target === skillDirectory ,
),
);
assert (
parsed . plannedActions . every (
( action ) =>
action . target === configPath ||
action . target === skillDirectory ||
action . target . startsWith ( skillDirectory + "/" ),
),
"Refuse setup writes outside the owned config/skill" ,
);
}
2026-10-10 22:11:14 +08:00
}
}
2026-10-24 19:38:57 +08:00
assert . equal ( await readFile ( ` ${ configPath } .rea.backup` , "utf8" ), original );
const configured = await readFile ( configPath , "utf8" );
const registration = JSON . parse ( configured );
assert . equal ( registration . mcpServers . other . command , "unrelated-server" );
assert . deepEqual ( registration . disabledServers , [ "other" ]);
const repeated = JSON . parse (
( await rea ([ "setup" , "--client" , "omp" , "--yes" ])). stdout ,
);
assert . deepEqual ( repeated . appliedActions , []);
assert . equal ( await readFile ( configPath , "utf8" ), configured );
assert . equal ( await readFile ( ` ${ configPath } .rea.backup` , "utf8" ), original );
expectedSkillBody = await readFile (
join ( skillDirectory , "SKILL.md" ),
"utf8" ,
);
const response = await saveVerifierCommandOutput (
() =>
commands . exec (
command ,
[
"--mode" ,
"json" ,
"--print" ,
"--no-session" ,
"--no-title" ,
"--no-lsp" ,
"--no-pty" ,
"--approval-mode" ,
"yolo" ,
"--model" ,
"rea-fixture/rea-client-fixture" ,
mode === "chat"
? "Say hello briefly."
: `Use the REA skill to analyze ${ target } .` ,
],
{
env : environment ,
cwd : workspace ,
timeout : 120_000 ,
maxBuffer : 10 * 1024 * 1024 ,
stdin : "closed-pipe" ,
},
),
{
stdout : join ( lab , ` ${ mode } .stdout` ),
stderr : join ( lab , ` ${ mode } .stderr` ),
},
);
assert . equal ( fixture . failure , undefined );
const events = response . stdout
. trim ()
. split ( "\n" )
. map (( line ) => JSON . parse ( line ));
const mounted = events
. filter (
( event ) =>
event . type === "notice" &&
event . message ? . startsWith ( "xd://: mounted " ),
)
. flatMap (( event ) =>
event . message . slice ( "xd://: mounted " . length ). split ( ", " ),
)
. filter (( name ) => name . startsWith ( "mcp__rea_" ));
catalogSize = mounted . length ;
assert . deepEqual (
mounted . sort (),
expectedDevices ,
"Native OMP must mount the complete REA catalog" ,
);
catalogMounted = true ;
assert (
! events . some (
( event ) => event . type === "tool_execution_end" && event . isError ,
),
);
assert (
events . some (
( event ) =>
event . type === "message_end" &&
event . message ? . role === "assistant" &&
event . message . stopReason === "stop" &&
containsText ( event . message . content , "REA_CLIENT_COMPATIBILITY_OK" ),
),
"OMP must finish with the expected native assistant message" ,
);
assert (
events . some (( event ) => event . type === "agent_end" && event . isTerminal ),
);
assert ( finalSeen );
if ( mode === "call" ) assert ( skillLoaded && contractRead && evidenceSeen );
}, [
() => commands . close (),
async () => {
await fixture ? . close ();
2026-10-10 22:11:14 +08:00
},
2026-10-24 19:38:57 +08:00
]);
passed = true ;
}, [
async () => {
const lineage = await completeVerifierRun ( verifier );
const receipt = {
client : "OMP" ,
clientVersion ,
mode ,
passed ,
artifacts : lab ,
runtimeRoot ,
host : {
platform : process . platform ,
architecture : process . arch ,
node : process . versions . node ,
},
modelFixture :
"loopback OpenAI completions/SSE, caller-declared one-million-token model and synthetic usage; no live model claim" ,
discovery :
"explicit isolated default agent/global config/XDG roots and custom skill directory; named profiles, default OS-home skill discovery and Windows unverified" ,
interface :
"default native xd:// device metadata with read/write dispatch; complete JSON schemas are not forwarded as model functions" ,
catalogMounted ,
catalogSize ,
invalidProfileRejected ,
skillLoaded ,
contractRead ,
evidenceSeen ,
artifactDigest ,
finalSeen ,
requests : fixture ? . requests ,
probes : fixture ? . probes ,
fixtureFailure : fixture ? . failure ,
verifier : lineage ,
};
await withVerifierCleanup (
() =>
writeFile ( join ( lab , "receipt.json" ), JSON . stringify ( receipt , null , 2 )),
[
() => {
console . log ( JSON . stringify ( receipt ));
},
],
);
},
]);