experiment(re)!: preserve partial captures and resolve function entries

Keep validated code available when native graph extraction is unavailable, bind output to the actual input/entry, preserve cancellation observations, and share batch source/error semantics. Add filtered function/alias reads and slice field selection across adapters.

Verified 38 focused tests, targeted lint, real stock/native MCP workflows, large SQLite graph-capacity fallback, and real cold/warm MCP reuse. Retain actual model costs and unequal-depth/selection limitations instead of claiming general superiority.

BREAKING CHANGE: Experimental native snapshots may succeed with readable code and an unavailable recovered_ir facet. Inspect facets before graph reads; unavailable graph counts are null/unknown.

Co-authored-by: gensokyo-dev <342580529+gensokyo-dev@users.noreply.github.com>
Co-authored-by: Kaoru0822 <208281322+kaoru0822-kitauji@users.noreply.github.com>
This commit is contained in:
committed 2026-10-16 05:48:03 +00:00
1 parent 4f13bd6733
commit f3f209d03f
16 files changed
+847 -213

No files matched your search

+10 -3
View File
@@ -68,16 +68,23 @@ unknown. Other providers are not yet wired to this experimental service.
The initial [actual model comparison](trials.md) favors the focused traditional
workflow. The seeded value-origin task has lower cumulative input and wall time
through Code Mode, but also exposes an IR-to-machine-path error. An equal-quality
whole-task advantage remains unproven; the representation fix needs a new trial.
through Code Mode, but initially exposes an IR-to-machine-path error. The revised
trial correctly explains that machine path with lower observed task costs;
broader claims still require more than this single seeded task.
`instructions` reads selected machine byte/decode windows through the same
owner. Recovered operations use `origin_address` and blocks `origin_start`;
these locations cannot be substituted for machine branch destinations. The
value-origin trial demonstrates why this boundary matters. The experiment
currently has eleven fact methods, still behind the same four-tool Code Mode
currently has twelve fact methods, still behind the same four-tool Code Mode
catalog.
`functions` provides selected name/alias/entry reads. Native snapshots report
code and recovered-IR facets separately, preserving readable code when graph
extraction is unavailable. Real capacity and cold/warm MCP checks are documented
in [native-engine.md](native-engine.md). Whole-model costs and unequal-depth
comparisons remain separate in the trial report.
Completion requires actual model Code Mode use, independently checked task
answers, shared atomic/direct/Code Mode semantics, needed relation coverage,
failure/cancellation/identity tests, and equivalent completed-task measurements
+29 -4
View File
@@ -41,6 +41,22 @@ const definition = (description, input, method, example) => ({
example,
});
export const methods = {
functions: definition(
"Search retained native callable entries by literal name/alias, exact name, or entry addresses. Names can match several entries, including PLT/import stubs and implementations; preserve all matches and select by address. A name does not establish runtime symbol binding.",
{
query: z.string().default(""),
exact: z.boolean().default(false),
case_sensitive: z.boolean().default(true),
addresses: z.array(hex).max(128).optional(),
fields: z
.array(z.enum(["name", "aliases", "size"]))
.min(1)
.optional(),
...page,
},
"functions",
'await rea.functions({query:"format_error",exact:true})',
),
strings: definition(
"Search retained string inventory by literal text. Paging does not establish artifact completeness.",
{ query: z.string(), ...page },
@@ -54,7 +70,7 @@ export const methods = {
'await rea.references({addresses:["0x2000"]})',
),
snapshot: definition(
"Analyze an explicit function entry once; retain native C and SSA, return its handle and coverage. Reuses the same source within this target lease.",
"Analyze an explicit function entry once; return a retained capture handle, facets and coverage. Reuses the source within this target lease. A valid code facet remains available when recovered IR exceeds capacity or is malformed; inspect facets before graph reads.",
{ entry: hex },
"snapshot",
'await rea.snapshot({entry:"0x1000"})',
@@ -163,12 +179,13 @@ export const methods = {
max_operations: z.number().int().min(1).max(256).default(48),
stop_at: z.array(z.string()).max(128).default([]),
stop_kinds: z.array(kinds).default(["phi", "load"]),
fields,
},
"slice",
"await rea.slice({snapshot:s,seeds:branchIds,max_operations:48})",
),
code: definition(
"Read native reconstructed C retained with this exact SSA source; offset is zero-based. A large limit can read the complete function inside Code Mode: filter locally before returning text. The bridge byte budget, not an arbitrary line count, bounds the result. No additional decompilation.",
"Read reconstructed code from the same retained function capture, even when its graph facet is unavailable. offset is zero-based. A large limit reads the complete code inside Code Mode for local filtering. The bridge byte budget bounds the result. No additional decompilation.",
{
snapshot,
offset: page.offset,
@@ -191,6 +208,8 @@ export const methods = {
// Compact return contracts let code compose before first observing a response.
const returns = {
functions:
"data:{source:{evidence_id,sha256},items:[{address,name,aliases,size}],total,next_offset,coverage}; size is an upper bound, or zero if unmeasured. Multiple matching addresses are retained, never selected by catalog order or display name alone.",
instructions:
"data:{results:[{ok,address,source:{evidence_id,sha256},items:[{address,size,status,bytes?,text?,mnemonic?,operands?}],resume_address,coverage}|{ok:false,address,error}]}; decoded rows describe selected machine bytes, not optimized IR branches. Partial batches retain successful windows.",
strings:
@@ -198,7 +217,7 @@ const returns = {
references:
"data:{results:[{ok,address,source:{evidence_id},items:[{from,to,kind,fromFunction:{address,name}|null,toFunction:{address,name}|null,instruction}],total,next_offset,coverage}|{ok:false,address,error}]}",
snapshot:
"data:{snapshot:string,entry,source:{evidence_id,sha256},coverage:{operations,blocks,control_flow,unrepresented_outgoing_blocks,issues}}",
"data:{snapshot:string,entry,source:{evidence_id,sha256},facets:{code:{availability},recovered_ir:{availability,error?}},coverage}. An unavailable graph has unknown/null counts, never a fabricated empty graph; code remains readable through the same handle.",
operations:
"data:{items:[{id,origin_address,block,source_line,kind,statement,definitions,constants,inputs?,output?,opcode?}],total,next_offset,evidence_id,coverage}. Native inputs:[{input_index,value_id,phi_predecessor,phi_predecessor_edge}], output:value_id|null; definitions:[{definition,use,input_index,value_id,phi_predecessor,phi_predecessor_edge}]. Diagnostic definitions use printed occurrence instead. fields projects columns; identity remains.",
relations:
@@ -209,7 +228,7 @@ const returns = {
"data:{items:[{id,origin_start,operations,predecessors,successors:[{target,index,polarity,condition_value,condition_test}]}],total,next_offset,evidence_id,coverage}; IDs are local to this snapshot.",
slice:
"data:{operations:[operation rows as above],coverage:{status,boundaries:[{id,reason}],missing,source_issues,runtime_reachability,memory_alias_dependencies},evidence_id}",
code: "data:{evidence_id,start_line,text,total_lines,next_offset,coverage}; text is reconstructed C. Use a large limit to inspect/filter the full text within code without returning it all.",
code: "data:{evidence_id,start_line,language:string|null,text,total_lines,next_offset,coverage}; language is native-reported or unknown. Read/filter full reconstructed text within Code Mode without returning it all.",
evidence:
"data:{source:{evidence_id,sha256,bytes,arguments},text,total_code_units,next_offset}; source has complete native output, including code before the SSA graph.",
};
@@ -295,6 +314,12 @@ export class AtomicSession {
const contract = methods[name];
const parsed = contract.input.parse(input);
const data = await this.#owner[contract.method](parsed, signal);
if (signal.aborted)
throw new FactFailure(
"cancelled",
"Request was cancelled after observations were collected",
{ partial_observation: data },
);
return { ok: true, context: this.context, data };
} catch (error) {
return {
+29
View File
@@ -41,6 +41,35 @@ test("named contracts reject extra keys and stale leases before provider admissi
assert.deepEqual(provider.calls, ["close"]);
await session.close();
});
test("cancellation after a completed read retains observations under a cancelled outcome", async () => {
const controller = new AbortController();
const session = new AtomicSession(async () => ({
context: { lease: "late-cancel" },
close: async () => {},
strings: async () => {
controller.abort();
return {
source: { evidence_id: "ev_observed" },
items: [{ value: "retained" }],
};
},
}));
await session.open("target");
const result = await session.call(
"strings",
{ query: "x" },
controller.signal,
);
assert.equal(result.ok, false);
assert.equal(result.error.code, "cancelled");
assert.equal(
result.error.details.partial_observation.items[0].value,
"retained",
);
assert.equal(result.context.lease, "late-cancel");
await session.close();
});
test("close drains admitted reads and a failed cleanup retains ownership for retry", async () => {
let release;
let reads = 0;
+15 -9
View File
@@ -102,6 +102,20 @@ export const executeJavaScript = async (
};
};
const retainEvidence = (response, evidence) => {
const observation =
response.data ?? response.error?.details?.partial_observation;
for (const row of [observation, ...(observation?.results ?? [])]) {
const id =
row?.source?.evidence_id ??
row?.evidence_id ??
row?.error?.details?.evidence_id;
if (id) evidence.add(id);
}
if (response.error?.details?.evidence_id)
evidence.add(response.error.details.evidence_id);
};
const installBridge = (
vm,
session,
@@ -128,15 +142,7 @@ const installBridge = (
combined,
lease,
);
for (const row of [response.data, ...(response.data?.results ?? [])]) {
const id =
row?.source?.evidence_id ??
row?.evidence_id ??
row?.error?.details?.evidence_id;
if (id) state.evidence.add(id);
}
if (response.error?.details?.evidence_id)
state.evidence.add(response.error.details.evidence_id);
retainEvidence(response, state.evidence);
calls[index].status = response.ok ? "ok" : "error";
if (!response.ok) calls[index].error = response.error;
calls[index].elapsed_ms = performance.now() - before;
@@ -48,6 +48,26 @@ test("guest CPU budget is independent from the native-analysis wall deadline", a
assert.ok(performance.now() - before < 2000);
});
test("cancelled reads keep partial-observation Evidence in the execution receipt", async () => {
const result = await executeJavaScript(
{
context: { lease: "partial" },
call: async () => ({
ok: false,
error: {
code: "cancelled",
details: {
partial_observation: { source: { evidence_id: "ev_partial" } },
},
},
}),
},
"return await rea.strings({query:'x'})",
);
assert.deepEqual(result.evidence_ids, ["ev_partial"]);
assert.equal(result.value.error.code, "cancelled");
});
test("failed compositions keep completed facts and their provenance after draining", async () => {
const owner = {
context: { lease: "retained" },
@@ -0,0 +1,59 @@
// Shared read projections and partial batch semantics; no provider protocols.
export const sourceSummary = ({ evidence_id, sha256, bytes, elapsed_ms }) => ({
evidence_id,
sha256,
bytes,
elapsed_ms,
});
export const projectFact = (row, fields, identity) =>
fields
? Object.fromEntries(
[...new Set([...identity, ...fields])]
.filter((key) => Object.hasOwn(row, key))
.map((key) => [key, row[key]]),
)
: row;
export const pageFacts = (rows, input, identity = []) => ({
items: rows
.slice(input.offset, input.offset + input.limit)
.map((row) => projectFact(row, input.fields, identity)),
total: rows.length,
next_offset:
input.offset + input.limit < rows.length
? input.offset + input.limit
: null,
});
export async function readFactBatch(requests, capture, read) {
const results = [];
for (const request of requests) {
let source;
try {
const captured = await capture(request);
source = captured.source;
const facts = await read(captured, request);
results.push({
...facts,
ok: true,
address: request.address,
source: sourceSummary(source),
});
} catch (error) {
results.push({
ok: false,
address: request.address,
error: {
code: error.code ?? "provider_failure",
message: error.message,
details: {
...error.details,
...(source ? { evidence_id: source.evidence_id } : {}),
},
},
});
}
}
return { results };
}
@@ -0,0 +1,36 @@
import { parseKunaInventory } from "../../dist/kuna/KunaProjectFiles.js";
import { requireResult } from "./fact-error.mjs";
import { pageFacts } from "./fact-reads.mjs";
export const parseFunctionFacts = (text) =>
Object.freeze(
requireResult(parseKunaInventory(text), "invalid_provider_output").map(
(entry) =>
Object.freeze({ ...entry, aliases: Object.freeze([...entry.aliases]) }),
),
);
export function selectFunctionFacts(functions, input) {
const addresses = input.addresses && new Set(input.addresses);
const normalize = (name) =>
input.case_sensitive ? name : name.toLowerCase();
const query = normalize(input.query);
const matches = functions.filter(
(entry) =>
(!addresses || addresses.has(entry.address)) &&
[entry.name, ...entry.aliases].some((name) =>
input.exact
? normalize(name) === query
: normalize(name).includes(query),
),
);
return {
...pageFacts(matches, input, ["address"]),
coverage: {
scope: "native callable-entry inventory, including import stubs",
discovery: "unknown",
extents: "upper bounds clipped at the next entry; zero means unmeasured",
symbol_binding_at_runtime: "unknown",
},
};
}
@@ -0,0 +1,93 @@
import test from "node:test";
import assert from "node:assert/strict";
import { parseFunctionFacts, selectFunctionFacts } from "./function-facts.mjs";
import { readFactBatch } from "./fact-reads.mjs";
import { FactFailure } from "./fact-error.mjs";
test("function names retain multiple entries and aliases instead of choosing a PLT or implementation", () => {
const facts = parseFunctionFacts(
JSON.stringify({
functions: [
{
name: "format_error",
address_hex: "0x1000",
aliases: ["format_error@plt"],
size: 16,
},
{
name: "format_error",
address_hex: "0x2000",
aliases: ["FormatError"],
size: 0,
},
],
}),
);
const query = {
query: "format_error",
exact: true,
case_sensitive: true,
offset: 0,
limit: 20,
};
assert.deepEqual(
selectFunctionFacts(facts, query).items.map((item) => item.address),
["0x1000", "0x2000"],
);
assert.equal(
selectFunctionFacts(facts, { ...query, query: "format_error@plt" }).items[0]
.address,
"0x1000",
);
assert.equal(
selectFunctionFacts(facts, {
...query,
query: "FORMAT_ERROR",
case_sensitive: false,
}).total,
2,
);
assert.deepEqual(
selectFunctionFacts(facts, {
...query,
addresses: ["0x2000"],
fields: ["size"],
}).items,
[{ address: "0x2000", size: 0 }],
);
assert.throws(() => {
facts[0].aliases.push("foreign");
});
});
test("batch transport and decoder failures preserve successful items and captured source identity", async () => {
const attempts = [];
const result = await readFactBatch(
[{ address: "0x1" }, { address: "0x2" }, { address: "0x3" }],
async (request) => {
attempts.push(request.address);
if (request.address === "0x2")
throw new FactFailure("capacity", "transport bound");
return {
source: {
evidence_id: `ev_${request.address}`,
sha256: "digest",
bytes: 3,
elapsed_ms: 1,
},
};
},
async (_, request) => {
if (request.address === "0x3")
throw new FactFailure(
"invalid_provider_output",
"decoder rejected source",
);
return { items: [{ value: 1 }] };
},
);
assert.deepEqual(attempts, ["0x1", "0x2", "0x3"]);
assert.equal(result.results[0].items[0].value, 1);
assert.equal(result.results[1].error.code, "capacity");
assert.equal(result.results[2].error.details.evidence_id, "ev_0x3");
});
+31 -5
View File
@@ -73,9 +73,8 @@ Targeted JS checks cover malformed/foreign identities, dangling relations, phi
order, exact hex offsets, immutable facts, loop/exit coverage, resource failure,
and all 64 four-node DAGs against an independent path-enumeration oracle.
Upstream `check-spec` passes. The full upstream corpus, stages and workspace gates
have not run; this patch is not declared upstream-ready. SQLite, more complex
model tasks, paired warm runs and the revised actual model comparison remain
required work.
have not run; this patch is not declared upstream-ready. The model comparisons
and subsequent boundary findings below do not establish wider provider parity.
The value-origin model comparison exposed a representation boundary: optimized
recovered blocks can absorb a machine predecessor, so an IR edge is not an actual
@@ -97,5 +96,32 @@ Windows are capped at 4,096 decoded rows and 16 windows per call, sharing the
returns 4,096 rows in an 842,106-byte source, taking 1.227 family wall seconds,
1.042 CPU seconds and 112.0 MiB kernel memory peak. Both real stock and patched
MCP tests preserve good windows alongside an unmapped-address failure and report
the actual `JA 0xe26d` / `JMP 0xd9c9` bytes. Targeted tests now total 33; the
representation fix still requires a fresh real-model task trial.
the actual `JA 0xe26d` / `JMP 0xd9c9` bytes. The representation revision had 33
targeted tests; its subsequent real-model trial is recorded below.
That fresh trial now verifies the missing machine path correctly; see
[actual task costs](trials.md). The SQLite task then exposes a separate missing
primitive: name/alias lookup across distinct callable entries. `functions` now
reuses the production inventory parser, preserving every matching entry, import
stub ambiguity, original aliases, clipped extents and unknown runtime binding.
The inventory is read/validated once per lease, and query/field/page selection
returns only the requested view. Batch xref and instruction reads share one
partial-outcome owner, retaining good observations and source IDs on failures.
A real `sqlite3VdbeExec` capture at `0xea6d0` also exceeds the graph export's
operation capacity while producing 126,519 characters of valid C. The old adapter
incorrectly rejects the entire capture. The revised owner validates the function
envelope and input identity independently, then models graph availability as a
facet result. Code and its language remain available under the same handle;
graph counts stay unknown and graph reads return their reason and Evidence ID.
The real MCP regression reads 3,654 code lines after the graph failure and verifies
that `sqlite3Fts3ErrMsg` has distinct entries `0x268f0` and `0x5efc0`. Native graph
capacity remains a real limitation, not a resolved scalability claim.
`verify-cache.mjs` measures a real cold/warm pair within one open lease. Cold zlib
snapshot reading takes 6,934.4 ms / 6.928 family CPU seconds; warm reading takes
67.7 ms / 0.068 CPU seconds and preserves the exact snapshot/Evidence ID. The
cumulative kernel memory peak is 275.1 MiB for both phases; the warm number is an
upper bound on its isolated phase peak. This is an API-only measurement, with no
model token result or cross-session cache claim. Targeted tests now total 38,
including late cancellation retaining partial facts and their provenance.
@@ -1,14 +1,15 @@
// Native JSON decoding and resource admission; row-wise validation bounds errors.
import { z } from "zod";
import { FactFailure } from "./fact-error.mjs";
import { ok, err } from "../../dist/domain/result.js";
const requireFact = (condition, reason) => {
if (!condition) throw new FactFailure("invalid_provider_output", reason);
};
const hex = z.string().regex(/^0x[0-9a-f]+$/u);
const ordinal = z.number().int().nonnegative();
const valueId = z.string().regex(/^v[0-9a-f]+$/u);
const operationId = z.string().regex(/^0x[0-9a-f]+:[0-9a-f]+$/u);
const hex = z.string().regex(/^0x(?:0|[1-9a-f][0-9a-f]{0,15})$/u);
const ordinal = z.number().int().nonnegative().max(0x7fffffff);
const valueId = z.string().regex(/^v[0-9a-f]{1,16}$/u);
const operationId = z.string().regex(/^0x[0-9a-f]{1,16}:[0-9a-f]{1,8}$/u);
const edgeId = z.string().regex(/^\d+:\d+$/u);
const edge = z.strictObject({
id: edgeId,
@@ -39,7 +40,7 @@ const value = z.strictObject({
id: valueId,
space: z.string().nullable(),
offset: hex,
size_bytes: z.number().int().positive(),
size_bytes: z.number().int().positive().max(0x7fffffff),
is_constant: z.boolean(),
is_input: z.boolean(),
is_annotation: z.boolean(),
@@ -71,13 +72,18 @@ const factsSchema = z.strictObject({
}),
});
const documentSchema = z.object({
binary: z.string(),
count: z.literal(1),
language: z.string(),
error: z.null(),
functions: z
.array(
z.object({
address_hex: hex,
code: z.string(),
error: z.null(),
atomic_facts: z.unknown(),
atomic_facts: z.unknown().optional(),
atomic_facts_error: z.string().optional(),
}),
)
.length(1),
@@ -115,12 +121,7 @@ const parseFacts = rowParser(factsSchema, {
values: (row) => value.parse(row),
});
function preflight(raw) {
requireFact(
Array.isArray(raw?.functions) && raw.functions.length === 1,
"Native source must describe exactly one function",
);
const facts = raw.functions[0]?.atomic_facts;
function preflight(facts) {
requireFact(
facts && typeof facts === "object",
"Native atomic facts facet is unavailable; inspect the retained source for its reason and C",
@@ -159,36 +160,76 @@ function preflight(raw) {
"Native relationships exceed resource capacity",
);
}
export function parseNativeFunction(text, entry) {
const formatFailure = (error) => {
if (error instanceof FactFailure) return error;
const details =
error instanceof z.ZodError
? {
issues: error.issues.slice(0, 8).map(({ path, code, message }) => ({
path,
code,
message: message.slice(0, 160),
})),
}
: { reason: String(error.message).slice(0, 256) };
return new FactFailure(
"invalid_provider_output",
"Native IR source does not match the declared format",
details,
);
};
const readGraph = (fn) => {
try {
if (fn.atomic_facts_error !== undefined) {
requireFact(
fn.atomic_facts === undefined,
"Native graph is both present and reported unavailable",
);
return err(
new FactFailure(
"capability_unavailable",
"Native recovered IR facet is unavailable",
{
native_error: fn.atomic_facts_error.slice(0, 1024),
native_error_truncated: fn.atomic_facts_error.length > 1024,
},
),
);
}
preflight(fn.atomic_facts);
return ok(parseFacts(fn.atomic_facts));
} catch (error) {
return err(formatFailure(error));
}
};
export function parseNativeFunction(text, entry, expectedInput) {
try {
requireFact(
Buffer.byteLength(text) <= 8 * 1024 * 1024,
"Native JSON source exceeds transport budget",
);
const raw = JSON.parse(text);
preflight(raw);
const fn = documentSchema.parse(raw).functions[0];
requireFact(
fn.address_hex === entry,
"Native function entry differs from requested subject",
Array.isArray(raw?.functions) && raw.functions.length === 1,
"Native source must describe exactly one function",
);
return { code: fn.code, facts: parseFacts(fn.atomic_facts) };
const doc = documentSchema.parse(raw),
fn = doc.functions[0];
if (expectedInput !== undefined && doc.binary !== expectedInput)
throw new FactFailure(
"subject_mismatch",
"Native source names a different command input",
{ expected: expectedInput, observed: doc.binary },
);
if (fn.address_hex !== entry)
throw new FactFailure(
"subject_mismatch",
"Native function entry differs from requested subject",
);
return { code: fn.code, language: doc.language, facts: readGraph(fn) };
} catch (error) {
if (error instanceof FactFailure) throw error;
const details =
error instanceof z.ZodError
? {
issues: error.issues.slice(0, 8).map(({ path, code, message }) => ({
path,
code,
message: message.slice(0, 160),
})),
}
: { reason: String(error.message).slice(0, 256) };
throw new FactFailure(
"invalid_provider_output",
"Native IR source does not match the declared format",
details,
);
throw formatFailure(error);
}
}
+66 -4
View File
@@ -340,8 +340,70 @@ function sliceValues(model, values, input) {
};
}
export function parseNativeIR(text, entry) {
const { code, facts } = parseNativeFunction(text, entry);
freeze(facts);
return createViews(facts, code, indexNative(facts));
const projectedFailure = (error) => ({
code: error.code ?? "invalid_provider_output",
message: error.message,
details: error.details ?? {},
});
export function parseNativeIR(text, entry, expectedInput) {
const capture = parseNativeFunction(text, entry, expectedInput);
let graph = capture.facts;
if (graph.ok) {
try {
freeze(graph.value);
const model = createViews(
graph.value,
capture.code,
indexNative(graph.value),
);
return Object.freeze({
...model,
language: capture.language,
facets: freeze({
code: { availability: "available" },
recovered_ir: { availability: "available" },
}),
});
} catch (error) {
graph = { ok: false, error };
}
}
const error = projectedFailure(graph.error);
const unavailable = () => {
throw new FactFailure(error.code, error.message, {
...error.details,
facet: "recovered_ir",
});
};
return Object.freeze({
code: capture.code,
language: capture.language,
facets: freeze({
code: { availability: "available" },
recovered_ir: { availability: "unavailable", error },
}),
coverage: freeze({
scope: "native reconstructed code; recovered IR facet unavailable",
operations: null,
blocks: null,
control_flow: "unknown",
machine_semantic_equivalence: "unknown",
issues: [error.message],
}),
...Object.fromEntries(
[
"operation",
"block",
"findConstant",
"uses",
"incoming",
"select",
"values",
"blocks",
"edges",
"slice",
].map((name) => [name, unavailable]),
),
});
}
+32 -3
View File
@@ -43,6 +43,10 @@ const op = (block, opcode, inputs, output = null) => ({
function diamond() {
return {
binary: "/private/input",
count: 1,
language: "c",
error: null,
functions: [
{
address_hex: "0x1000",
@@ -180,7 +184,10 @@ test("malformed identities, dangling relationships, foreign entry and phi reorde
]) {
const doc = diamond();
mutate(doc.functions[0].atomic_facts);
assert.throws(() => parseNativeIR(JSON.stringify(doc), "0x1000"));
const model = parseNativeIR(JSON.stringify(doc), "0x1000");
assert.equal(model.facets.recovered_ir.availability, "unavailable");
assert.equal(model.code, "reconstructed C");
assert.throws(() => model.select({}));
}
assert.throws(
() => parseNativeIR(JSON.stringify(diamond()), "0x2000"),
@@ -203,6 +210,28 @@ test("typed slices retain symbolic input frontiers and precise definition bindin
assert.equal(result.coverage.runtime_reachability, "unknown");
});
test("native facet failure preserves C without fabricating an empty graph; source identity still gates both", () => {
const doc = diamond();
delete doc.functions[0].atomic_facts;
doc.functions[0].atomic_facts_error = "atomic operation capacity exceeded";
const model = parseNativeIR(JSON.stringify(doc), "0x1000", "/private/input");
assert.equal(model.code, "reconstructed C");
assert.equal(model.language, "c");
assert.equal(model.coverage.operations, null);
assert.equal(model.facets.code.availability, "available");
assert.equal(model.facets.recovered_ir.availability, "unavailable");
assert.throws(
() => model.select({}),
(error) =>
error.code === "capability_unavailable" &&
error.details.native_error === doc.functions[0].atomic_facts_error,
);
assert.throws(
() => parseNativeIR(JSON.stringify(doc), "0x1000", "/other/input"),
(error) => error.code === "subject_mismatch",
);
});
test("oversized or malformed native arrays fail before diagnostic expansion", () => {
const capacity = diamond();
capacity.functions[0].atomic_facts.operations = Array.from(
@@ -210,7 +239,7 @@ test("oversized or malformed native arrays fail before diagnostic expansion", ()
() => ({}),
);
assert.throws(
() => parseNativeIR(JSON.stringify(capacity), "0x1000"),
() => parseNativeIR(JSON.stringify(capacity), "0x1000").select({}),
/capacity/u,
);
const malformed = diamond();
@@ -219,7 +248,7 @@ test("oversized or malformed native arrays fail before diagnostic expansion", ()
() => ({}),
);
assert.throws(
() => parseNativeIR(JSON.stringify(malformed), "0x1000"),
() => parseNativeIR(JSON.stringify(malformed), "0x1000").select({}),
(error) =>
error.code === "invalid_provider_output" &&
error.details.issues.length <= 8 &&
+111 -113
View File
@@ -11,19 +11,19 @@ import { PrivateRuntimeRoot } from "../../dist/process/PrivateRuntimeRoot.js";
import { parseNativeIR } from "./native-ir.mjs";
import { FactFailure, requireResult } from "./fact-error.mjs";
import { parseInstructions } from "./instruction-facts.mjs";
import {
sourceSummary,
pageFacts,
projectFact,
readFactBatch,
} from "./fact-reads.mjs";
import { parseFunctionFacts, selectFunctionFacts } from "./function-facts.mjs";
import {
parseKunaSsaDump,
backwardSlice,
} from "../atomic-re-tools/kuna-ssa.mjs";
const sha256 = (value) => createHash("sha256").update(value).digest("hex");
const sourceSummary = ({ evidence_id, sha256, bytes, elapsed_ms }) => ({
evidence_id,
sha256,
bytes,
elapsed_ms,
});
export class KunaFactOwner {
#lifetime = new AbortController();
#sources = new Map();
@@ -36,6 +36,7 @@ export class KunaFactOwner {
#installation;
#retainedBytes = 0;
#strings;
#functions;
#captureDirectory;
#nativeIR = false;
context;
@@ -136,16 +137,18 @@ export class KunaFactOwner {
);
const file = join(this.#root.path, id);
await writeFile(file, snapshot.stdout.text, { flag: "wx" });
const source = {
const source = Object.freeze({
evidence_id: id,
sha256: sha256(snapshot.stdout.text),
bytes: Buffer.byteLength(snapshot.stdout.text),
arguments: actualArguments,
display_arguments: actualArguments.map((s) =>
s === snapshot.input ? this.#target.path : s,
arguments: Object.freeze(actualArguments),
display_arguments: Object.freeze(
actualArguments.map((s) =>
s === snapshot.input ? this.#target.path : s,
),
),
elapsed_ms: performance.now() - start,
};
});
this.#sources.set(id, { source, file });
this.#retainedBytes += bytes;
if (this.#captureDirectory) {
@@ -218,15 +221,30 @@ export class KunaFactOwner {
},
};
}
async functions(input, signal) {
const capture = await this.#native(
"functions",
(path) => ["functions", path, "--json"],
signal,
);
this.#functions ??= parseFunctionFacts(
await this.#sourceText(capture.source.evidence_id),
);
return {
source: sourceSummary(capture.source),
...selectFunctionFacts(this.#functions, input),
};
}
async references(input, signal) {
const results = [];
for (const address of input.addresses) {
try {
const capture = await this.#native(
return readFactBatch(
input.addresses.map((address) => ({ address })),
({ address }) =>
this.#native(
`xref:${address}`,
(path) => ["xrefs", path, "--to", address, "--json"],
signal,
);
),
async (capture, { address }) => {
const parsed = requireResult(
parseKunaIncomingReferenceFacts(
await this.#sourceText(capture.source.evidence_id),
@@ -235,33 +253,15 @@ export class KunaFactOwner {
),
"invalid_provider_output",
);
results.push({
ok: true,
address,
source: sourceSummary(capture.source),
items: parsed.facts.slice(input.offset, input.offset + input.limit),
total: parsed.facts.length,
next_offset:
input.offset + input.limit < parsed.facts.length
? input.offset + input.limit
: null,
return {
...pageFacts(parsed.facts, input),
coverage: {
scope: "exact target address; not an object extent",
discovery: "unknown",
},
});
} catch (error) {
results.push({
ok: false,
address,
error: {
code: error.code ?? "provider_failure",
message: error.message,
},
});
}
}
return { results };
};
},
);
}
async snapshot(input, signal) {
const capture = await this.#native(
@@ -281,10 +281,11 @@ export class KunaFactOwner {
if (!this.#snapshots.has(id))
this.#snapshots.set(id, {
entry: input.entry,
input: capture.input,
evidence_id: capture.source.evidence_id,
});
const parsed = await this.#load(id);
if (parsed.block(0).origin_start !== input.entry)
if (!this.#nativeIR && parsed.block(0).origin_start !== input.entry)
throw new FactFailure(
"subject_mismatch",
"Native SSA entry does not match the requested function entry",
@@ -294,14 +295,17 @@ export class KunaFactOwner {
source: sourceSummary(capture.source),
entry: input.entry,
coverage: parsed.coverage,
facets: parsed.facets ?? {
code: { availability: "available" },
recovered_ir: { availability: "available", coverage: "partial" },
},
};
}
async instructions(input, signal) {
const results = [];
for (const request of input.windows) {
let capture;
try {
capture = await this.#native(
return readFactBatch(
input.windows,
(request) =>
this.#native(
`instructions:${request.address}:${request.count}`,
(path) => [
"disassemble",
@@ -315,35 +319,15 @@ export class KunaFactOwner {
"--json",
],
signal,
);
const parsed = parseInstructions(
),
async (capture, request) =>
parseInstructions(
await this.#sourceText(capture.source.evidence_id),
capture.input,
request,
input.fields,
);
results.push({
ok: true,
address: request.address,
source: sourceSummary(capture.source),
...parsed,
});
} catch (error) {
results.push({
ok: false,
address: request.address,
error: {
code: error.code ?? "provider_failure",
message: error.message,
details: {
...error.details,
...(capture ? { evidence_id: capture.source.evidence_id } : {}),
},
},
});
}
}
return { results };
),
);
}
async #load(id) {
const descriptor = this.#snapshots.get(id);
@@ -364,7 +348,7 @@ export class KunaFactOwner {
let parsed;
try {
parsed = this.#nativeIR
? parseNativeIR(text, descriptor.entry)
? parseNativeIR(text, descriptor.entry, descriptor.input)
: parseKunaSsaDump(text);
} catch (error) {
throw new FactFailure(
@@ -383,61 +367,77 @@ export class KunaFactOwner {
}
return this.#loaded.get(id);
}
async operations(input) {
async #query(input, read) {
const model = await this.#load(input.snapshot);
return {
const evidence_id = this.#snapshots.get(input.snapshot).evidence_id;
try {
return { ...read(model), evidence_id };
} catch (error) {
throw new FactFailure(error.code ?? "analysis_failed", error.message, {
...error.details,
evidence_id,
source_retained: true,
});
}
}
async operations(input) {
return this.#query(input, (model) => ({
...model.select(input),
evidence_id: this.#snapshots.get(input.snapshot).evidence_id,
coverage: model.coverage,
};
}));
}
async relations(input) {
const model = await this.#load(input.snapshot);
if (input.kind === "controllers" && !this.#nativeIR)
this.#requireNativeIR();
return {
if (input.kind === "controllers") this.#requireNativeIR(input.snapshot);
return this.#query(input, (model) => ({
...model.edges(input),
evidence_id: this.#snapshots.get(input.snapshot).evidence_id,
coverage: model.coverage,
};
}));
}
async slice(input) {
const model = await this.#load(input.snapshot);
return {
...(model.slice
return this.#query(input, (model) => {
const result = model.slice
? model.slice(input)
: backwardSlice(model, input.seeds, {
maxOperations: input.max_operations,
stopAt: input.stop_at,
stopKinds: input.stop_kinds,
})),
evidence_id: this.#snapshots.get(input.snapshot).evidence_id,
};
});
return {
...result,
operations: result.operations.map((row) =>
projectFact(row, input.fields, [
"id",
"origin_address",
"block",
"source_line",
]),
),
};
});
}
#requireNativeIR() {
#requireNativeIR(snapshot) {
if (!this.#nativeIR)
throw new FactFailure(
"capability_unavailable",
"This relation requires the pinned experimental native IR engine; the diagnostic SSA format does not contain it",
this.#snapshots.has(snapshot)
? { evidence_id: this.#snapshots.get(snapshot).evidence_id }
: {},
);
}
async values(input) {
this.#requireNativeIR();
const model = await this.#load(input.snapshot);
return {
this.#requireNativeIR(input.snapshot);
return this.#query(input, (model) => ({
...model.values(input),
evidence_id: this.#snapshots.get(input.snapshot).evidence_id,
coverage: model.coverage,
};
}));
}
async blocks(input) {
this.#requireNativeIR();
const model = await this.#load(input.snapshot);
return {
this.#requireNativeIR(input.snapshot);
return this.#query(input, (model) => ({
...model.blocks(input),
evidence_id: this.#snapshots.get(input.snapshot).evidence_id,
coverage: model.coverage,
};
}));
}
async code(input) {
const descriptor = this.#snapshots.get(input.snapshot);
@@ -446,16 +446,18 @@ export class KunaFactOwner {
"unknown_snapshot",
"Snapshot is not owned by the current lease",
);
const code = this.#nativeIR
? (await this.#load(input.snapshot)).code
: (await this.#sourceText(descriptor.evidence_id)).split(
"\n0\nBasic Block",
1,
)[0];
const model = this.#nativeIR ? await this.#load(input.snapshot) : null;
const code =
model?.code ??
(await this.#sourceText(descriptor.evidence_id)).split(
"\n0\nBasic Block",
1,
)[0];
const lines = code.split("\n");
return {
evidence_id: descriptor.evidence_id,
start_line: input.offset + 1,
language: model?.language ?? null,
text: lines.slice(input.offset, input.offset + input.limit).join("\n"),
total_lines: lines.length,
next_offset:
@@ -463,21 +465,15 @@ export class KunaFactOwner {
? input.offset + input.limit
: null,
coverage: {
authority: "reconstructed C, not original source",
authority: "native reconstructed code",
scope: "selected display lines",
},
};
}
async evidence(input) {
const record = this.#sources.get(input.evidence_id);
if (!record)
throw new FactFailure(
"unknown_evidence",
"Evidence is not retained by the current lease",
);
const text = await this.#sourceText(input.evidence_id);
return {
source: record.source,
source: this.#sources.get(input.evidence_id).source,
text: text.slice(input.offset, input.offset + input.limit),
total_code_units: text.length,
next_offset:
@@ -494,6 +490,8 @@ export class KunaFactOwner {
this.#sources.clear();
this.#work.clear();
this.#snapshots.clear();
this.#strings = undefined;
this.#functions = undefined;
}
cancel() {
this.#lifetime.abort();
+53
View File
@@ -187,3 +187,56 @@ representation ambiguity needs a structural fix: distinguish IR origin fields
from physical instruction facts and expose selected instruction windows, then
rerun the unchanged question. Private artifacts are `zlib-value-codemode-v1*`
and `zlib-value-traditional-v1*`.
After separating IR origins and adding instruction windows, the unchanged value
question was rerun at `4f13bd673`. The Code Mode answer now reads actual machine
bytes and correctly distinguishes recovered predecessor 38 from the intervening
`0xe26d` / `0xe270` machine path. Both answers recover the same local value
equations, byte-order conditions and unknown invariants. These remain individual
stochastic samples, not a general speedup guarantee.
| Measurement | Code Mode value v2 | Traditional value v2 |
| --- | ---: | ---: |
| MCP attempts / failures | 7 / 0 | 6 / 1 |
| Cumulative input tokens | 296,888 | 573,881 |
| Included cached input | 252,160 | 512,128 |
| Uncached input | 44,728 | 61,753 |
| Output / included reasoning | 3,176 / 594 | 2,830 / 547 |
| Model wall seconds | 96.662 | 124.754 |
| Family wall seconds | 97.654 | 125.410 |
| Family CPU seconds | 19.495 | 44.143 |
| Kernel family peak MiB | 534.4 | 797.4 |
The traditional failure is the client policy rejection of `binary_session`.
Its cost remains included. Both runtime/target digests stay unchanged, cleanup
is verified and OOM kills are zero. This is evidence of a useful seeded
value-tracing case for the revised interface, with the selected-tool and
single-sample qualifications retained.
The initial SQLite diagnostic comparison, also at `4f13bd673`, exposes a further
capability/comparison gap:
| Measurement | Code Mode SQLite v1 | Traditional SQLite v1 |
| --- | ---: | ---: |
| MCP attempts / failures | 14 / 0 | 17 / 8 |
| Cumulative input tokens | 601,445 | 934,237 |
| Included cached input | 535,296 | 831,744 |
| Uncached input | 66,149 | 102,493 |
| Output / included reasoning | 4,790 / 1,668 | 3,878 / 1,121 |
| Model wall seconds | 143.469 | 231.469 |
| Family CPU seconds | 18.996 | 154.132 |
| Kernel family peak MiB | 586.6 | 1,200.2 |
Both answers find the two malformed-message conditions and distinguish the
depth-error, other-status and success paths. The traditional answer additionally
resolves the named formatter implementation at `0x5efc0`, tracing free,
`sqlite3_vmprintf` and pointer storage; Code Mode stops at its PLT stub and
correctly leaves delivery/allocation unknown. These are unequal-depth answers,
so the cost difference is not an equal-completion win.
The selected traditional catalog also omitted `list_procedures`, despite errors
advertising it as the discovery route. The trace retains interior-entry failures,
failed resource discovery, a client approval-policy rejection and ambiguous name
lookups. This selection confound must be corrected in the next focused baseline;
the failed attempts and their costs are not discarded. Both runs still preserve
target/runtime identity, clean up their profiles/payloads and have zero OOM kills.
@@ -0,0 +1,109 @@
// A real MCP cold/warm read benchmark. No model runs in this verifier.
import assert from "node:assert/strict";
import { readFile, writeFile } from "node:fs/promises";
import { resolve } from "node:path";
import { Client } from "@modelcontextprotocol/client";
import { StdioClientTransport } from "@modelcontextprotocol/client/stdio";
import {
createVerifierRun,
completeVerifierRun,
assertVerifierCleanupComplete,
} from "../../scripts/lib/verifier-run.mjs";
const [binary, output, entry = "0xc1e0"] = process.argv.slice(2);
const group = (await readFile("/proc/self/cgroup", "utf8"))
.trim()
.split("\n")
.find((row) => row.startsWith("0::"))
?.slice(3);
assert.ok(group?.includes("rea-efficiency-"), "Run under resource-run.py");
const counters = async () => ({
cpu: Number(
(await readFile(`/sys/fs/cgroup${group}/cpu.stat`, "utf8")).match(
/usage_usec (\d+)/u,
)[1],
),
peak: Number(
(await readFile(`/sys/fs/cgroup${group}/memory.peak`, "utf8")).trim(),
),
});
const verifier = createVerifierRun();
const client = new Client({ name: "rea-cache-verifier", version: "0.1.0" });
const transport = new StdioClientTransport({
command: process.execPath,
args: [resolve("experiments/atomic-codemode/server.mjs")],
env: { ...process.env },
stderr: "pipe",
});
const phases = [],
failures = [];
const call = async (name, args = {}) => {
const reply = await client.callTool(
{ name, arguments: args },
{ timeout: 180000 },
);
const value = JSON.parse(reply.content[0].text);
assert.equal(value.ok, true, JSON.stringify(value));
return value;
};
try {
await client.connect(transport);
await call("open_binary", { path: binary });
for (const phase of ["cold_snapshot", "warm_snapshot"]) {
const before = await counters(),
start = performance.now();
const result = await call("execute_javascript", {
code: `const r=await rea.snapshot({entry:${JSON.stringify(entry)}});if(!r.ok)throw new Error(JSON.stringify(r));return r.data;`,
});
const elapsed = performance.now() - start,
after = await counters();
phases.push({
phase,
elapsed_ms: elapsed,
family_cpu_seconds: (after.cpu - before.cpu) / 1e6,
cumulative_family_memory_peak_bytes: after.peak,
snapshot: result.value.snapshot,
source: result.value.source,
facets: result.value.facets,
});
}
assert.equal(phases[0].snapshot, phases[1].snapshot);
assert.equal(phases[0].source.evidence_id, phases[1].source.evidence_id);
await call("close_binary");
} catch (error) {
failures.push(error.stack ?? String(error));
} finally {
try {
await client.close();
} catch (error) {
failures.push(String(error));
}
try {
await transport.close();
} catch (error) {
failures.push(String(error));
}
}
const lifecycle = await completeVerifierRun(verifier);
assertVerifierCleanupComplete(lifecycle.process_lineage);
await writeFile(
output,
JSON.stringify({
phases,
failures,
lifecycle,
scope:
"Real MCP, no model/token measurement. CPU deltas cover the owned cgroup. Memory peaks are cumulative; the warm value is an upper bound on its isolated phase peak. Both reads share one immutable captured artifact/lease; this is not a cross-session cache benchmark.",
}),
);
console.log(
JSON.stringify({
output,
phases: phases.map(({ phase, elapsed_ms, family_cpu_seconds }) => ({
phase,
elapsed_ms,
family_cpu_seconds,
})),
}),
);
if (failures.length) process.exitCode = 1;
+79 -38
View File
@@ -10,7 +10,8 @@ import {
assertVerifierCleanupComplete,
} from "../../scripts/lib/verifier-run.mjs";
const [binary, output] = process.argv.slice(2);
const [binary, output, scenario = "zlib"] = process.argv.slice(2);
assert.ok(["zlib", "sqlite-partial"].includes(scenario));
const verifier = createVerifierRun();
const client = new Client({ name: "rea-codemode-verifier", version: "0.1.0" });
const transport = new StdioClientTransport({
@@ -48,9 +49,47 @@ try {
const ajv = new Ajv2020({ strict: false });
for (const tool of catalog.tools) ajv.compile(tool.inputSchema);
const opened = await call("open_binary", { path: binary });
await call("reference", { query: "relations" });
const result = await call("execute_javascript", {
code: `
if (scenario === "sqlite-partial") {
assert.equal(opened.context.analysis_model, "experimental-native-ir-v1");
const result = await call("execute_javascript", {
code: `
const read=async(p)=>{const r=await p;if(!r.ok)throw new Error(JSON.stringify(r));return r.data;};
const names=await read(rea.functions({query:"sqlite3Fts3ErrMsg",exact:true}));
const entries=await read(rea.functions({query:"sqlite3VdbeExec",exact:true}));
const entry=entries.items.find(fn=>fn.address==="0xea6d0");if(!entry)throw new Error("fixture entry missing");
const snap=await read(rea.snapshot({entry:entry.address}));
const code=await read(rea.code({snapshot:snap.snapshot,limit:4}));
const graph=await rea.operations({snapshot:snap.snapshot,limit:1});
const evidence=await read(rea.evidence({evidence_id:snap.source.evidence_id,limit:512}));
return {names,snap,code,graph,evidence_source:evidence.source};`,
});
assert.deepEqual(result.value.names.items.map((fn) => fn.address).sort(), [
"0x268f0",
"0x5efc0",
]);
assert.equal(result.value.snap.facets.code.availability, "available");
assert.equal(
result.value.snap.facets.recovered_ir.availability,
"unavailable",
);
assert.equal(result.value.snap.coverage.operations, null);
assert.ok(
result.value.code.text.length > 0 && result.value.code.total_lines > 1000,
);
assert.equal(result.value.graph.ok, false);
assert.equal(result.value.graph.error.code, "capability_unavailable");
assert.equal(
result.value.graph.error.details.evidence_id,
result.value.snap.source.evidence_id,
);
assert.equal(
result.value.evidence_source.sha256,
result.value.snap.source.sha256,
);
} else {
await call("reference", { query: "relations" });
const result = await call("execute_javascript", {
code: `
const found=await rea.strings({query:"incorrect header check",limit:1});
if(!found.ok) throw new Error(JSON.stringify(found));
const literal=found.data.items[0].address;
@@ -62,15 +101,16 @@ const seed=await rea.operations({snapshot:s,constant:literal});
const uses=await rea.relations({snapshot:s,kind:"uses",seeds:seed.data.items.map(x=>x.id)});
const consumers=await rea.operations({snapshot:s,ids:uses.data.items.map(x=>x.use)});
const incoming=await rea.relations({snapshot:s,kind:"incoming",seeds:consumers.data.items.map(x=>x.block)});
const slice=await rea.slice({snapshot:s,seeds:incoming.data.items.map(x=>x.operation).filter(Boolean)});
return {literal,entry,snapshot:s,consumer_blocks:[...new Set(consumers.data.items.map(x=>x.block))],selected:slice.data.operations.length,guards:slice.data.operations.map(x=>x.statement),coverage:slice.data.coverage,evidence_id:slice.data.evidence_id};`,
});
assert.equal(result.value.selected, 19);
assert.equal(result.value.coverage.status, "partial");
assert.ok(result.value.guards.some((s) => s.includes("/ #0x1f")));
if (opened.context.analysis_model === "experimental-native-ir-v1") {
const native = await call("execute_javascript", {
code: `const s=${JSON.stringify(result.value.snapshot)};
const slice=await rea.slice({snapshot:s,seeds:incoming.data.items.map(x=>x.operation).filter(Boolean),fields:["statement"]});
return {literal,entry,snapshot:s,consumer_blocks:[...new Set(consumers.data.items.map(x=>x.block))],selected:slice.data.operations.length,projected:slice.data.operations.every(op=>!("inputs" in op)&&typeof op.origin_address==="string"),guards:slice.data.operations.map(x=>x.statement),coverage:slice.data.coverage,evidence_id:slice.data.evidence_id};`,
});
assert.equal(result.value.selected, 19);
assert.equal(result.value.projected, true);
assert.equal(result.value.coverage.status, "partial");
assert.ok(result.value.guards.some((s) => s.includes("/ #0x1f")));
if (opened.context.analysis_model === "experimental-native-ir-v1") {
const native = await call("execute_javascript", {
code: `const s=${JSON.stringify(result.value.snapshot)};
const read=async(p)=>{const r=await p;if(!r.ok)throw new Error(JSON.stringify(r));return r.data;};
const blocks=await read(rea.blocks({snapshot:s,ids:${JSON.stringify(result.value.consumer_blocks)}}));
const controls=await read(rea.relations({snapshot:s,kind:"controllers",seeds:blocks.items.map(b=>b.id)}));
@@ -78,33 +118,34 @@ const guards=await read(rea.operations({snapshot:s,block_ids:controls.items.map(
const phi=await read(rea.operations({snapshot:s,kind:"phi",fields:["inputs","output"],limit:2}));
const values=await read(rea.values({snapshot:s,ids:phi.items.flatMap(o=>o.inputs.map(i=>i.value_id)).filter(Boolean)}));
return {blocks,controls,guards,phi,values};`,
});
assert.equal(native.value.controls.total, 2);
assert.deepEqual(
native.value.guards.items.map((op) => op.origin_address).sort(),
["0xd9ec", "0xda32"],
);
assert.ok(
native.value.phi.items.every((op) =>
op.inputs.every(
(input) => typeof input.phi_predecessor_edge === "string",
});
assert.equal(native.value.controls.total, 2);
assert.deepEqual(
native.value.guards.items.map((op) => op.origin_address).sort(),
["0xd9ec", "0xda32"],
);
assert.ok(
native.value.phi.items.every((op) =>
op.inputs.every(
(input) => typeof input.phi_predecessor_edge === "string",
),
),
),
);
assert.equal(
native.value.blocks.coverage.control_flow,
"complete-for-recovered-graph",
);
assert.ok(native.value.values.items.length > 0);
);
assert.equal(
native.value.blocks.coverage.control_flow,
"complete-for-recovered-graph",
);
assert.ok(native.value.values.items.length > 0);
}
const machine = await call("execute_javascript", {
code: 'const r=await rea.instructions({windows:[{address:"0xd97e",count:1},{address:"0xe26d",count:2},{address:"0xdeadbeef",count:1}]});if(!r.ok)throw new Error(JSON.stringify(r));return r.data;',
});
assert.equal(machine.value.results[0].items[0].bytes, "0f87e9080000");
assert.match(machine.value.results[0].items[0].text, /e26d/u);
assert.equal(machine.value.results[1].items[1].address, "0xe270");
assert.match(machine.value.results[1].items[1].text, /d9c9/u);
assert.equal(machine.value.results[2].ok, false);
}
const machine = await call("execute_javascript", {
code: 'const r=await rea.instructions({windows:[{address:"0xd97e",count:1},{address:"0xe26d",count:2},{address:"0xdeadbeef",count:1}]});if(!r.ok)throw new Error(JSON.stringify(r));return r.data;',
});
assert.equal(machine.value.results[0].items[0].bytes, "0f87e9080000");
assert.match(machine.value.results[0].items[0].text, /e26d/u);
assert.equal(machine.value.results[1].items[1].address, "0xe270");
assert.match(machine.value.results[1].items[1].text, /d9c9/u);
assert.equal(machine.value.results[2].ok, false);
await call("close_binary");
} catch (error) {
failure = error.stack ?? String(error);