mirror of
https://github.com/morluto/rea.git
synced 2026-11-09 16:26:36 +00:00
fix(reconstruction): honor resolved unknown revisions (#9637)
This commit is contained in:
1 parent
694edef951
commit
b394d50943
3 files changed
+117
-2
No files matched your search
@@ -28,6 +28,11 @@ this effective scope. A claim verifier must commit to its own surfaces and
|
||||
their reachable dependencies, including their artifact and implemented-owner
|
||||
digests. Callers do not need to duplicate the transitive closure in the request.
|
||||
|
||||
Listed `residual_unknown_ids` select unknown identities from the Evidence bundle.
|
||||
The evaluator uses each identity's latest revision: resolved questions do not
|
||||
block the boundary, while reopened questions do. An active, unallowed question
|
||||
retains its cited supporting, contradicting and mutation Evidence in the result.
|
||||
|
||||
## Comparable verifier Evidence
|
||||
|
||||
At least one record explicitly cited by the latest verifier observation must
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { reconstructionUnknownHeads } from "./reconstructionUnknowns.js";
|
||||
import type { ReconstructionCoverageScope } from "./reconstructionCoverageScope.js";
|
||||
import type {
|
||||
ReconstructionClosureResult,
|
||||
@@ -396,14 +397,27 @@ const verifierResultMatchesContract = (
|
||||
export const evaluateReconstructionCoverageRisks = (
|
||||
context: ReconstructionEvaluationContext,
|
||||
): void => {
|
||||
for (const unknownId of context.coverage.residual_unknown_ids)
|
||||
if (!context.boundary.allowed_unknown_ids.includes(unknownId))
|
||||
const unknownHeads = reconstructionUnknownHeads(
|
||||
context.coverage.evidence_bundle.unknowns,
|
||||
);
|
||||
for (const unknownId of new Set(context.coverage.residual_unknown_ids)) {
|
||||
const unknown = unknownHeads.get(unknownId);
|
||||
if (unknown?.status === "resolved") continue;
|
||||
if (!context.boundary.allowed_unknown_ids.includes(unknownId)) {
|
||||
if (unknown !== undefined)
|
||||
addEvidence(context, [
|
||||
...unknown.supporting_evidence_ids,
|
||||
...unknown.contradicting_evidence_ids,
|
||||
...unknown.mutation_evidence_ids,
|
||||
]);
|
||||
addReason(
|
||||
context,
|
||||
"active-unknown",
|
||||
unknownId,
|
||||
"Active residual unknown is not permitted by the completion boundary.",
|
||||
);
|
||||
}
|
||||
}
|
||||
for (const contradiction of context.coverage.contradictions)
|
||||
if (
|
||||
contradiction.status === "active" &&
|
||||
|
||||
@@ -9,11 +9,107 @@ import {
|
||||
reconstructionCoverageDataFixture,
|
||||
} from "../../../src/domain/reconstructionCoverage.fixture.js";
|
||||
import { createEvidence } from "../../../src/domain/evidence.js";
|
||||
import {
|
||||
createResidualUnknown,
|
||||
recordUnknownInputSchema,
|
||||
updateResidualUnknown,
|
||||
} from "../../../src/domain/residualUnknown.js";
|
||||
import { createEvidenceBundle } from "../../../src/domain/evidenceBundle.js";
|
||||
import { createTestBinarySession } from "../../fixtures/binarySession.js";
|
||||
import { createServer } from "../../../src/server/createServer.js";
|
||||
import { observed } from "../../fixtures/analysisExecution.js";
|
||||
|
||||
it("uses the latest listed unknown revision when evaluating a boundary", async () => {
|
||||
await withCoverageMcp(async ({ client }) => {
|
||||
const base = currentFixtureCoverage();
|
||||
const [first, second] = base.evidence_bundle.records;
|
||||
if (first === undefined || second === undefined)
|
||||
throw new Error("Missing fixture Evidence");
|
||||
const unknownSource = createEvidence(
|
||||
undefined,
|
||||
{ id: "unknown-source", name: "Unknown source", version: "1" },
|
||||
{
|
||||
operation: "observe_unknown",
|
||||
parameters: {},
|
||||
result: { evidence: true },
|
||||
},
|
||||
);
|
||||
const input = recordUnknownInputSchema.parse({
|
||||
question: "Is the route covered?",
|
||||
supporting_evidence_ids: [unknownSource.evidence_id],
|
||||
domain: "fixture",
|
||||
severity: "medium",
|
||||
required_authority: null,
|
||||
required_confidence: "derived",
|
||||
required_environment: null,
|
||||
recommended_probes: [],
|
||||
relationships: [],
|
||||
});
|
||||
const open = createResidualUnknown(input, first.evidence_id, null);
|
||||
const resolved = updateResidualUnknown(
|
||||
open,
|
||||
{
|
||||
...input,
|
||||
unknown_id: open.unknown_id,
|
||||
expected_revision: 1,
|
||||
status: "resolved",
|
||||
resolution: {
|
||||
disposition: "withdrawn",
|
||||
rationale: "No longer applicable",
|
||||
evidence_ids: [],
|
||||
},
|
||||
},
|
||||
second.evidence_id,
|
||||
);
|
||||
const reopened = updateResidualUnknown(
|
||||
resolved,
|
||||
{
|
||||
...input,
|
||||
unknown_id: open.unknown_id,
|
||||
expected_revision: 2,
|
||||
status: "investigating",
|
||||
resolution: null,
|
||||
},
|
||||
second.evidence_id,
|
||||
);
|
||||
const coverage = (revisions: (typeof open)[]) => ({
|
||||
...base,
|
||||
evidence_bundle: createEvidenceBundle(
|
||||
[...base.evidence_bundle.records, unknownSource],
|
||||
revisions,
|
||||
),
|
||||
residual_unknown_ids: [open.unknown_id, open.unknown_id],
|
||||
});
|
||||
expect(
|
||||
(await evaluate(client, coverage([open]))).structuredContent,
|
||||
).toMatchObject({
|
||||
status: "unknown",
|
||||
evidence_ids: expect.arrayContaining([unknownSource.evidence_id]),
|
||||
reasons: [
|
||||
expect.objectContaining({
|
||||
code: "active-unknown",
|
||||
subject_id: open.unknown_id,
|
||||
}),
|
||||
],
|
||||
});
|
||||
expect(
|
||||
(await evaluate(client, coverage([open, resolved]))).structuredContent,
|
||||
).toMatchObject({ status: "ready", reasons: [] });
|
||||
expect(
|
||||
(await evaluate(client, coverage([open, resolved, reopened])))
|
||||
.structuredContent,
|
||||
).toMatchObject({
|
||||
status: "unknown",
|
||||
reasons: [
|
||||
expect.objectContaining({
|
||||
code: "active-unknown",
|
||||
subject_id: open.unknown_id,
|
||||
}),
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("reconstruction coverage inline Evidence", () => {
|
||||
it("evaluates inline fail-closed coverage without retaining request Evidence", async () => {
|
||||
await withCoverageMcp(async ({ client, session }) => {
|
||||
|
||||
Reference in new issue
Block a user