fix(native)!: preserve value-flow absence semantics (#8785)

* fix(native)!: preserve value-flow absence semantics

* test(native): compare value-flow reasons with their owners

Stop freezing the unrecorded and Kuna unavailable sentences. Assert the
procedure-scoped unknown and that an explicit provider reason is preserved.

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
This commit is contained in:
morlutoandCursor Agent authored and GitHub committed 2026-11-05 02:32:15 +08:00
1 parent dd4b83c220
commit 1ff5a655bc
8 files changed
+81 -8

No files matched your search

@@ -13,6 +13,9 @@ export const workflowAnalysisProfile = (
createAnalysisProfile(REA_WORKFLOW_PROVIDER, {
upstream_analysis_profile: upstream,
source_limitations: "provider-operation-caveats-v1",
...(operation === "trace_native_values"
? { value_flow_absence: "recorded-versus-unavailable-v1" }
: {}),
...(operation === "binary_overview"
? { workflow_revision: 5 }
: operation === "batch_decompile"
@@ -1357,3 +1357,15 @@ it("revises the trace_feature workflow profile so earlier results are not replay
"other workflows keep their profile",
).toEqual(workflowAnalysisProfile(profile));
});
it("binds native value-trace absence semantics without changing other workflows", () => {
const profile = ANALYSIS_SNAPSHOT_PROFILE;
const valueTrace = workflowAnalysisProfile(profile, "trace_native_values");
expect(valueTrace.parameters.value_flow_absence).toBe(
"recorded-versus-unavailable-v1",
);
expect(valueTrace.digest).not.toBe(workflowAnalysisProfile(profile).digest);
expect(workflowAnalysisProfile(profile, "trace_call_path")).toEqual(
workflowAnalysisProfile(profile),
);
});
@@ -1,6 +1,9 @@
import { createAnalysisExecutionEvidence } from "../../domain/analysisObservation.js";
import { describe, expect, it } from "vitest";
import { traceNativeValues as traceNativeValuesCore } from "./NativeValueTrace.js";
import {
traceNativeValues as traceNativeValuesCore,
UNRECORDED_NATIVE_VALUE_FLOW,
} from "./NativeValueTrace.js";
import { executeComposedWorkflow } from "../WorkflowEvidence.js";
import {
createAnalysisExecution,
@@ -190,12 +193,47 @@ describe("native value trace seed admission", () => {
expect.objectContaining({ address: base.procedure.address }),
],
unknowns: [
expect.objectContaining({
reason: "Provider has no native def-use model",
}),
{
procedure: base.procedure.address,
address: null,
reason: UNRECORDED_NATIVE_VALUE_FLOW,
},
],
});
});
it("preserves an explicit unavailable reason for that procedure", async () => {
const base = functionDossierSchema.parse(ghidraFunctionDossier());
const providerReason = "selected procedure has no p-code model";
const result = await traceNativeValues(
{
execute: async () =>
ok(
createAnalysisExecution(
{
...base,
native_value_flow: {
available: false,
reason: providerReason,
limitations: [],
},
},
provider,
{ subject },
),
),
},
{ procedure: base.procedure.address },
);
if (!result.ok) throw result.error;
expect(nativeValueTraceSchema.parse(result.value).unknowns).toEqual([
{
procedure: base.procedure.address,
address: null,
reason: providerReason,
},
]);
});
});
describe("native value parameter-use node membership", () => {
+5 -1
View File
@@ -28,6 +28,10 @@ import { createValueTraceBudget } from "./NativeValueTraceBudget.js";
export const CLEANUP_STOPPED_VALUE_TRACE =
"Trace stopped because the provider did not confirm cleanup of resources it owns";
/** Fallback when a dossier has no native value-flow facet for this procedure. */
export const UNRECORDED_NATIVE_VALUE_FLOW =
"Native def-use was not recorded for this procedure.";
/** Compose bounded high-p-code def-use graphs across exactly referenced call destinations. */
export const traceNativeValues = async (
analysis: AnalysisOperationPort,
@@ -181,7 +185,7 @@ export const traceNativeValues = async (
unknowns.push({
procedure: address,
address: null,
reason: flow?.reason ?? "Provider has no native def-use model",
reason: flow?.reason ?? UNRECORDED_NATIVE_VALUE_FLOW,
});
continue;
}