rea-agents 2.4.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +80 -18
- package/bridge/ghidra/ReaGhidraBridge.java +48 -1
- package/bridge/hopper_bridge.py +259 -24
- package/dist/application/AnalysisClientCleanup.js +14 -0
- package/dist/application/ApplicationWorkflowEvidenceResolver.js +31 -13
- package/dist/application/BinarySession.js +15 -4
- package/dist/application/BinarySessionStatus.js +31 -1
- package/dist/application/BrowserEvidence.js +14 -0
- package/dist/application/BrowserScenarioCapturePort.js +1 -0
- package/dist/application/BrowserScenarioCaptureService.js +53 -0
- package/dist/application/BrowserScenarioEvidence.js +40 -0
- package/dist/application/CallPathTracing.js +160 -0
- package/dist/application/CapabilityInventory.js +68 -12
- package/dist/application/CompositeProvider.js +10 -1
- package/dist/application/DirectAnalysis.js +7 -2
- package/dist/application/EnhancedLiteralTracing.js +118 -0
- package/dist/application/EnhancedTools.js +35 -121
- package/dist/application/JavaScriptApplicationWorkflowEvidence.js +13 -0
- package/dist/application/JavaScriptApplicationWorkflowService.js +27 -1
- package/dist/application/JavaScriptRuntimeObservationEvidence.js +34 -0
- package/dist/application/JavaScriptRuntimeObservationPort.js +1 -0
- package/dist/application/JavaScriptRuntimeObservationService.js +46 -0
- package/dist/application/JavaScriptSemanticGraphAsyncProjection.js +147 -0
- package/dist/application/JavaScriptSemanticGraphBuilder.js +34 -6
- package/dist/application/JavaScriptSemanticGraphChildProcessProjection.js +156 -0
- package/dist/application/JavaScriptSemanticGraphConstruction.js +2 -2
- package/dist/application/JavaScriptSemanticGraphDataProjection.js +203 -0
- package/dist/application/JavaScriptSemanticGraphFingerprintProjection.js +25 -0
- package/dist/application/JavaScriptSemanticGraphFlowProjection.js +129 -8
- package/dist/application/JavaScriptSemanticGraphObjectProjection.js +81 -0
- package/dist/application/JavaScriptSemanticGraphProjection.js +14 -7
- package/dist/application/JavaScriptSemanticGraphResourceProjection.js +59 -0
- package/dist/application/JavaScriptSemanticGraphValueProjection.js +77 -0
- package/dist/application/ProcessReactiveEffects.js +6 -0
- package/dist/application/ProcessReactiveHarness.js +16 -1
- package/dist/application/ProjectPermissionStore.js +1 -0
- package/dist/application/ReconstructionObligationAuthority.js +72 -0
- package/dist/application/ReconstructionObligationCandidates.js +265 -0
- package/dist/application/ReconstructionObligationLedgerDiagnostics.js +47 -0
- package/dist/application/ReconstructionObligationLedgerEvaluation.js +263 -0
- package/dist/application/ReconstructionObligationLedgerProjection.js +86 -0
- package/dist/application/ReconstructionObligationLedgerService.js +72 -0
- package/dist/application/ReconstructionObligationOriginalCases.js +33 -0
- package/dist/application/ReconstructionObligationPolicies.js +132 -0
- package/dist/application/ReconstructionReadinessService.js +48 -0
- package/dist/artifacts/ArtifactProvider.js +87 -22
- package/dist/browser/BrowserScenarioSecrets.js +53 -0
- package/dist/browser/BrowserScenarioSessionPort.js +1 -0
- package/dist/browser/CdpBrowserProvider.js +2 -2
- package/dist/browser/CdpCaptureDocuments.js +57 -0
- package/dist/browser/CdpCaptureStorage.js +71 -29
- package/dist/browser/CdpCaptureStorageFingerprints.js +328 -0
- package/dist/browser/CdpEndpoint.js +8 -6
- package/dist/browser/CdpPageCapture.js +2 -0
- package/dist/browser/JavaScriptRuntimeScope.js +38 -0
- package/dist/browser/PlaywrightBrowserScenarioProvider.js +253 -0
- package/dist/browser/PlaywrightExecutionBoundary.js +42 -0
- package/dist/browser/PlaywrightScenarioActions.js +62 -0
- package/dist/browser/PlaywrightScenarioArtifacts.js +238 -0
- package/dist/browser/PlaywrightScenarioBrowser.js +144 -0
- package/dist/browser/PlaywrightScenarioEvents.js +301 -0
- package/dist/browser/PlaywrightScenarioSession.js +300 -0
- package/dist/browser/V8InspectorCaptureProjection.js +110 -0
- package/dist/browser/V8InspectorEndpoint.js +72 -0
- package/dist/browser/V8InspectorProvider.js +267 -0
- package/dist/catalogIdentity.js +8 -0
- package/dist/cli/artifactCommands.js +39 -0
- package/dist/cli/coreAnalysisCommands.js +37 -0
- package/dist/cli.js +4 -0
- package/dist/cliApplicationCommands.js +30 -2
- package/dist/cliBrowserAdvancedCommands.js +17 -5
- package/dist/cliBrowserCommands.js +1 -0
- package/dist/cliBrowserScenarioCommands.js +43 -0
- package/dist/cliCommandNames.js +8 -0
- package/dist/cliJavaScriptRuntimeCommands.js +164 -0
- package/dist/cliObservationOptions.js +4 -0
- package/dist/cliPolicyCommands.js +1 -0
- package/dist/config/environment.js +12 -0
- package/dist/config/parseConfig.js +88 -17
- package/dist/contracts/analysisSearchContract.js +14 -0
- package/dist/contracts/applicationToolContracts.js +86 -2
- package/dist/contracts/applicationWorkflowInputContracts.js +18 -0
- package/dist/contracts/artifactToolContracts.js +22 -0
- package/dist/contracts/browserProviderToolContracts.js +7 -0
- package/dist/contracts/browserScenarioToolContracts.js +81 -0
- package/dist/contracts/browserToolContracts.js +88 -98
- package/dist/contracts/enhancedInputs.js +25 -6
- package/dist/contracts/functionInstructionContract.js +8 -0
- package/dist/contracts/hopperMemoryContracts.js +22 -0
- package/dist/contracts/javascriptApplicationWorkflowExamples.js +42 -0
- package/dist/contracts/javascriptRuntimeObservationToolContracts.js +58 -0
- package/dist/contracts/reconstructionReadinessExample.js +436 -0
- package/dist/contracts/toolContractExamples.js +5 -0
- package/dist/contracts/toolContractTypes.js +1 -0
- package/dist/contracts/toolContracts.js +13 -21
- package/dist/contracts/toolEffects.js +21 -0
- package/dist/contracts/toolOutputSchemaGroups.js +70 -20
- package/dist/contracts/toolOutputSchemaPrimitives.js +37 -0
- package/dist/domain/analysisErrorProjection.js +8 -0
- package/dist/domain/artifactInspection.js +347 -0
- package/dist/domain/browserCaptureComparison.js +82 -0
- package/dist/domain/browserObservation.js +8 -1
- package/dist/domain/browserObservationErrors.js +1 -0
- package/dist/domain/browserObservationSchemas.js +26 -0
- package/dist/domain/browserScenario.js +165 -0
- package/dist/domain/browserScenarioCapture.js +57 -0
- package/dist/domain/browserScenarioCaptureValues.js +204 -0
- package/dist/domain/browserScenarioDiff.js +324 -0
- package/dist/domain/browserScenarioDiffValues.js +157 -0
- package/dist/domain/browserScenarioNormalization.js +45 -0
- package/dist/domain/browserScenarioValues.js +372 -0
- package/dist/domain/hopperValues.js +10 -0
- package/dist/domain/javascriptRuntimeObservation.js +170 -0
- package/dist/domain/javascriptRuntimeReconciliationParsing.js +120 -2
- package/dist/domain/javascriptRuntimeReconciliationResult.js +3 -3
- package/dist/domain/javascriptRuntimeReconciliationRuntime.js +2 -2
- package/dist/domain/javascriptRuntimeReconciliationSchemas.js +1 -1
- package/dist/domain/javascriptSemanticAnalysis.js +5 -4
- package/dist/domain/javascriptSemanticAsyncEffects.js +253 -0
- package/dist/domain/javascriptSemanticChildProcesses.js +237 -0
- package/dist/domain/javascriptSemanticDataEffectHelpers.js +125 -0
- package/dist/domain/javascriptSemanticDataEffects.js +284 -0
- package/dist/domain/javascriptSemanticDerivedAnalysis.js +41 -0
- package/dist/domain/javascriptSemanticFingerprints.js +174 -0
- package/dist/domain/javascriptSemanticIr.js +21 -1
- package/dist/domain/javascriptSemanticObjects.js +115 -0
- package/dist/domain/javascriptSemanticPromises.js +290 -0
- package/dist/domain/javascriptSemanticResources.js +136 -0
- package/dist/domain/javascriptStaticAnalysis.js +4 -3
- package/dist/domain/javascriptStaticAnalysisBundler.js +38 -0
- package/dist/domain/javascriptStaticAnalysisCalls.js +23 -1
- package/dist/domain/javascriptStaticAnalysisHelpers.js +8 -0
- package/dist/domain/processCapture.js +8 -2
- package/dist/domain/processReactiveScenario.js +1 -0
- package/dist/domain/processReactiveTransition.js +9 -4
- package/dist/domain/providerCleanupError.js +11 -0
- package/dist/domain/reconstructionObligationLedgerSchemas.js +278 -0
- package/dist/domain/reconstructionReadiness.js +121 -0
- package/dist/domain/reconstructionReadinessFindingHelpers.js +17 -0
- package/dist/domain/reconstructionReadinessIntegrityFindings.js +118 -0
- package/dist/domain/reconstructionReadinessJourneyFindings.js +193 -0
- package/dist/domain/reconstructionReadinessSchemas.js +240 -0
- package/dist/domain/sourceToBundleComparison.js +335 -0
- package/dist/domain/sourceToBundleComparisonSchemas.js +133 -0
- package/dist/domain/sourceToBundleSignals.js +202 -0
- package/dist/domain/webCaptureDiff.js +141 -27
- package/dist/domain/webScreenshot.js +1 -1
- package/dist/generatedPackageMetadata.js +1 -1
- package/dist/ghidra/GhidraDefaults.js +1 -1
- package/dist/ghidra/GhidraFunctionValues.js +13 -1
- package/dist/ghidra/GhidraProviderCapabilities.js +7 -0
- package/dist/hopper/HopperCleanup.js +158 -0
- package/dist/hopper/HopperClient.js +69 -99
- package/dist/hopper/HopperProvider.js +20 -1
- package/dist/hopper/HopperRequestQueue.js +187 -0
- package/dist/hopper/HopperResponseStream.js +46 -0
- package/dist/hopper/protocol.js +1 -0
- package/dist/main/transport.js +24 -24
- package/dist/main.js +6 -0
- package/dist/mcpDoctor.js +25 -2
- package/dist/process/ProcessCommandIdentity.js +19 -0
- package/dist/process/ProcessOwnership.js +11 -8
- package/dist/server/DynamicToolAvailability.js +70 -0
- package/dist/server/createServer.js +46 -1
- package/dist/server/lifecycleProgress.js +10 -0
- package/dist/server/permissionFailure.js +12 -0
- package/dist/server/registerApplicationTools/compareSourceToBundle.js +35 -0
- package/dist/server/registerApplicationTools/helpers.js +11 -7
- package/dist/server/registerApplicationTools/obligationLedger.js +27 -0
- package/dist/server/registerApplicationTools/readiness.js +55 -0
- package/dist/server/registerApplicationTools.js +6 -0
- package/dist/server/registerArtifactTools.js +9 -1
- package/dist/server/registerBrowserScenarioTool.js +25 -0
- package/dist/server/registerBrowserTools.js +2 -2
- package/dist/server/registerCloseLifecycleTool.js +57 -0
- package/dist/server/registerEnhancedTools.js +16 -5
- package/dist/server/registerEvidenceResources.js +4 -0
- package/dist/server/registerEvidenceTools.js +9 -2
- package/dist/server/registerJavaScriptRuntimeObservationTools.js +37 -0
- package/dist/server/registerReconstructionObligationLedgerResource.js +39 -0
- package/dist/server/registerReconstructionReadinessResource.js +39 -0
- package/dist/server/registerSessionStatusTool.js +11 -8
- package/dist/server/registerSessionTools.js +11 -57
- package/dist/server/sessionAvailabilityPolicy.js +10 -8
- package/package.json +12 -6
- package/skills/reverse-engineer-anything/SKILL.md +2 -2
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
import { parseEvidenceBundle, } from "../domain/evidenceBundle.js";
|
|
2
|
+
import { reconstructionObligationLedgerSchema, } from "../domain/reconstructionObligationLedgerSchemas.js";
|
|
3
|
+
import { evidenceAuthoritySupportsProof, evidenceSupportsOriginalAuthority, proofAuthoritySatisfies, } from "./ReconstructionObligationAuthority.js";
|
|
4
|
+
import { addObligationDiagnostic as addDiagnostic, contradictionDiagnostics, groupManifestBindings, groupManifestContradictions, hasObligationDiagnostic as hasDiagnostic, uniqueObligationDiagnostics as uniqueDiagnostics, } from "./ReconstructionObligationLedgerDiagnostics.js";
|
|
5
|
+
import { originalCaseDiagnostics, originalCasesFor, } from "./ReconstructionObligationOriginalCases.js";
|
|
6
|
+
import { digestObligationLedgerValue, obligationLedgerCoverage, obligationEdgeOrder, obligationLedgerEvidenceLinks, obligationLedgerStatus, obligationReports, summarizeObligations, } from "./ReconstructionObligationLedgerProjection.js";
|
|
7
|
+
export const evaluateReconstructionObligationLedger = ({ candidates: candidatesInput, bundle: bundleInput, manifest, maxObligations, generationLimitations, }) => {
|
|
8
|
+
const bundle = parseEvidenceBundle(bundleInput);
|
|
9
|
+
const allCandidates = [...candidatesInput].sort((left, right) => left.obligation_id.localeCompare(right.obligation_id));
|
|
10
|
+
const orphanManifestIds = findOrphanManifestIds(allCandidates, manifest);
|
|
11
|
+
const candidates = allCandidates.slice(0, maxObligations);
|
|
12
|
+
const omittedCount = allCandidates.length - candidates.length;
|
|
13
|
+
const context = createEvaluationContext(candidates, bundle, manifest);
|
|
14
|
+
const obligations = applyDependencyDiagnostics(candidates.map((candidate) => evaluateObligation(candidate, context)), context);
|
|
15
|
+
const ownershipGraph = obligations
|
|
16
|
+
.flatMap((obligation) => obligation.binding === null
|
|
17
|
+
? []
|
|
18
|
+
: [
|
|
19
|
+
{
|
|
20
|
+
obligation_id: obligation.obligation_id,
|
|
21
|
+
module_path: obligation.binding.owner.module_path,
|
|
22
|
+
symbol: obligation.binding.owner.symbol,
|
|
23
|
+
},
|
|
24
|
+
])
|
|
25
|
+
.sort(obligationEdgeOrder);
|
|
26
|
+
const dependencyGraph = obligations
|
|
27
|
+
.flatMap((obligation) => obligation.dependency_obligation_ids.map((dependencyId) => ({
|
|
28
|
+
obligation_id: obligation.obligation_id,
|
|
29
|
+
depends_on_obligation_id: dependencyId,
|
|
30
|
+
})))
|
|
31
|
+
.sort(obligationEdgeOrder);
|
|
32
|
+
const evidenceLinks = obligationLedgerEvidenceLinks(obligations, manifest);
|
|
33
|
+
const limitations = ledgerLimitations(generationLimitations, allCandidates.length, omittedCount, orphanManifestIds);
|
|
34
|
+
const coverage = obligationLedgerCoverage(omittedCount, maxObligations, limitations.length > 0);
|
|
35
|
+
const semantic = {
|
|
36
|
+
coverage,
|
|
37
|
+
summary: summarizeObligations(obligations),
|
|
38
|
+
reports: obligationReports(obligations),
|
|
39
|
+
ownership_graph: ownershipGraph,
|
|
40
|
+
dependency_graph: dependencyGraph,
|
|
41
|
+
obligations,
|
|
42
|
+
evidence_links: evidenceLinks,
|
|
43
|
+
limitations,
|
|
44
|
+
};
|
|
45
|
+
const evaluatedStatus = obligationLedgerStatus(obligations, omittedCount);
|
|
46
|
+
const status = evaluatedStatus === "failed"
|
|
47
|
+
? evaluatedStatus
|
|
48
|
+
: limitations.length > 0
|
|
49
|
+
? "unknown"
|
|
50
|
+
: evaluatedStatus;
|
|
51
|
+
const closureDigest = digestObligationLedgerValue({
|
|
52
|
+
schema: "rea.reconstruction-obligation-closure/v1",
|
|
53
|
+
status,
|
|
54
|
+
...semantic,
|
|
55
|
+
});
|
|
56
|
+
return reconstructionObligationLedgerSchema.parse({
|
|
57
|
+
schema: "ReconstructionObligationLedger",
|
|
58
|
+
schema_version: 1,
|
|
59
|
+
ledger_id: `rol_${digestObligationLedgerValue({
|
|
60
|
+
schema: "rea.reconstruction-obligation-ledger/v1",
|
|
61
|
+
evidence_ids: bundle.records.map(({ evidence_id: id }) => id),
|
|
62
|
+
obligation_ids: obligations.map(({ obligation_id: id }) => id),
|
|
63
|
+
closure_digest: closureDigest,
|
|
64
|
+
})}`,
|
|
65
|
+
closure_digest: closureDigest,
|
|
66
|
+
status,
|
|
67
|
+
...semantic,
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
const createEvaluationContext = (candidates, bundle, manifest) => ({
|
|
71
|
+
candidates: new Map(candidates.map((candidate) => [candidate.obligation_id, candidate])),
|
|
72
|
+
evidence: new Map(bundle.records.map((evidence) => [evidence.evidence_id, evidence])),
|
|
73
|
+
bindings: groupManifestBindings(manifest),
|
|
74
|
+
contradictions: groupManifestContradictions(manifest),
|
|
75
|
+
});
|
|
76
|
+
const findOrphanManifestIds = (candidates, manifest) => {
|
|
77
|
+
const candidateIds = new Set(candidates.map(({ obligation_id: obligationId }) => obligationId));
|
|
78
|
+
return [
|
|
79
|
+
...new Set([
|
|
80
|
+
...manifest.bindings.map(({ obligation_id: obligationId }) => obligationId),
|
|
81
|
+
...manifest.contradictions.map(({ obligation_id: obligationId }) => obligationId),
|
|
82
|
+
].filter((obligationId) => !candidateIds.has(obligationId))),
|
|
83
|
+
].sort();
|
|
84
|
+
};
|
|
85
|
+
const ledgerLimitations = (generationLimitations, candidateCount, omittedCount, orphanManifestIds) => [
|
|
86
|
+
...new Set([
|
|
87
|
+
...generationLimitations,
|
|
88
|
+
...(candidateCount === 0
|
|
89
|
+
? [
|
|
90
|
+
"No reconstruction obligations were derived; closure cannot be claimed.",
|
|
91
|
+
]
|
|
92
|
+
: []),
|
|
93
|
+
...(omittedCount > 0
|
|
94
|
+
? [
|
|
95
|
+
`${String(omittedCount)} obligation candidates were omitted by max_obligations; closure is unknown.`,
|
|
96
|
+
]
|
|
97
|
+
: []),
|
|
98
|
+
...(orphanManifestIds.length > 0
|
|
99
|
+
? [
|
|
100
|
+
`Manifest entries reference unknown obligations: ${orphanManifestIds.join(", ")}.`,
|
|
101
|
+
]
|
|
102
|
+
: []),
|
|
103
|
+
]),
|
|
104
|
+
].sort();
|
|
105
|
+
const evaluateObligation = (candidate, context) => {
|
|
106
|
+
const bindings = context.bindings.get(candidate.obligation_id) ?? [];
|
|
107
|
+
const binding = bindings.length === 1 ? (bindings[0] ?? null) : null;
|
|
108
|
+
const diagnostics = [];
|
|
109
|
+
if (candidate.definitionCount > 1)
|
|
110
|
+
addDiagnostic(diagnostics, "duplicate-definition", "Multiple candidate definitions share this obligation ID.");
|
|
111
|
+
if (bindings.length === 0)
|
|
112
|
+
addDiagnostic(diagnostics, "missing-owner", "No reconstruction manifest binding owns this obligation.");
|
|
113
|
+
if (bindings.length > 1)
|
|
114
|
+
addDiagnostic(diagnostics, "ambiguous-owner", "Multiple reconstruction manifest bindings claim this obligation.");
|
|
115
|
+
if (binding !== null)
|
|
116
|
+
evaluateBinding(candidate, binding, context, diagnostics);
|
|
117
|
+
diagnostics.push(...originalCaseDiagnostics(candidate, binding, context.evidence));
|
|
118
|
+
evaluateAuthority(candidate, binding, context, diagnostics);
|
|
119
|
+
evaluateDisposition(candidate, diagnostics);
|
|
120
|
+
diagnostics.push(...contradictionDiagnostics(candidate.obligation_id, context.contradictions, context.evidence));
|
|
121
|
+
for (const unknownId of candidate.residual_unknown_ids)
|
|
122
|
+
addDiagnostic(diagnostics, "residual-unknown", `Residual unknown remains visible: ${unknownId}.`);
|
|
123
|
+
for (const unavailable of candidate.unavailable_authority)
|
|
124
|
+
addDiagnostic(diagnostics, "unavailable-authority", unavailable);
|
|
125
|
+
return {
|
|
126
|
+
obligation_id: candidate.obligation_id,
|
|
127
|
+
obligation_version: candidate.obligation_version,
|
|
128
|
+
title: candidate.title,
|
|
129
|
+
origin: candidate.origin,
|
|
130
|
+
application_layer: candidate.application_layer,
|
|
131
|
+
family: candidate.family,
|
|
132
|
+
target: candidate.target,
|
|
133
|
+
authority_references: candidate.authority_references,
|
|
134
|
+
source_state: candidate.source_state,
|
|
135
|
+
observed_cases: originalCasesFor(candidate, binding),
|
|
136
|
+
required: candidate.required,
|
|
137
|
+
required_case_kinds: candidate.required_case_kinds,
|
|
138
|
+
required_original_authority: candidate.required_original_authority,
|
|
139
|
+
required_fixture_authority: candidate.required_fixture_authority,
|
|
140
|
+
required_verifier_authority: candidate.required_verifier_authority,
|
|
141
|
+
requires_parser_type: candidate.requires_parser_type,
|
|
142
|
+
dependency_obligation_ids: candidate.dependency_obligation_ids,
|
|
143
|
+
residual_unknown_ids: candidate.residual_unknown_ids,
|
|
144
|
+
unavailable_authority: candidate.unavailable_authority,
|
|
145
|
+
required_next_evidence: candidate.required_next_evidence,
|
|
146
|
+
binding,
|
|
147
|
+
status: obligationStatus(candidate, binding, diagnostics),
|
|
148
|
+
diagnostics: uniqueDiagnostics(diagnostics),
|
|
149
|
+
};
|
|
150
|
+
};
|
|
151
|
+
const evaluateBinding = (candidate, binding, context, diagnostics) => {
|
|
152
|
+
if (candidate.requires_parser_type && binding.parser_type === null)
|
|
153
|
+
addDiagnostic(diagnostics, "missing-parser-type", "This boundary requires an explicit parser, schema, and domain type.");
|
|
154
|
+
for (const caseKind of candidate.required_case_kinds) {
|
|
155
|
+
const fixtures = binding.fixtures.filter(({ case_kind: fixtureCase }) => fixtureCase === caseKind);
|
|
156
|
+
if (fixtures.length === 0) {
|
|
157
|
+
addDiagnostic(diagnostics, "missing-case", `Required ${caseKind} fixture is missing.`);
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
if (!fixtures.some((fixture) => proofAuthoritySatisfies(fixture.authority, candidate.required_fixture_authority) &&
|
|
161
|
+
fixture.evidence_ids.every((id) => {
|
|
162
|
+
const evidence = context.evidence.get(id);
|
|
163
|
+
return (evidence !== undefined &&
|
|
164
|
+
evidenceAuthoritySupportsProof(evidence, fixture.authority, {
|
|
165
|
+
obligationId: candidate.obligation_id,
|
|
166
|
+
fixtureId: fixture.fixture_id,
|
|
167
|
+
caseKind: fixture.case_kind,
|
|
168
|
+
}));
|
|
169
|
+
})))
|
|
170
|
+
addDiagnostic(diagnostics, "weak-fixture-authority", `${caseKind} fixture lacks ${candidate.required_fixture_authority} authority or authenticated Evidence.`);
|
|
171
|
+
}
|
|
172
|
+
evaluateVerifier(candidate, binding, context, diagnostics);
|
|
173
|
+
};
|
|
174
|
+
const evaluateVerifier = (candidate, binding, context, diagnostics) => {
|
|
175
|
+
const verifier = binding.verifier;
|
|
176
|
+
if (verifier === null) {
|
|
177
|
+
addDiagnostic(diagnostics, "missing-verifier", "No verifier claim is bound to this obligation.");
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
if (!verifier.enumerated_obligation_ids.includes(candidate.obligation_id))
|
|
181
|
+
addDiagnostic(diagnostics, "verifier-does-not-enumerate", "The verifier claim does not enumerate this obligation ID.");
|
|
182
|
+
const resultEvidence = context.evidence.get(verifier.result_evidence_id);
|
|
183
|
+
if (resultEvidence === undefined)
|
|
184
|
+
addDiagnostic(diagnostics, "missing-verifier-result", "The latest verifier result Evidence is absent from the bundle.");
|
|
185
|
+
if (!proofAuthoritySatisfies(verifier.authority, candidate.required_verifier_authority) ||
|
|
186
|
+
(resultEvidence !== undefined &&
|
|
187
|
+
!evidenceAuthoritySupportsProof(resultEvidence, verifier.authority, {
|
|
188
|
+
obligationId: candidate.obligation_id,
|
|
189
|
+
verifierId: verifier.verifier_id,
|
|
190
|
+
claimId: verifier.claim_id,
|
|
191
|
+
})))
|
|
192
|
+
addDiagnostic(diagnostics, "weak-verifier-authority", `Verifier authority does not satisfy ${candidate.required_verifier_authority}.`);
|
|
193
|
+
if (verifier.status !== "pass")
|
|
194
|
+
addDiagnostic(diagnostics, "verifier-failed", `Latest verifier status is ${verifier.status}.`);
|
|
195
|
+
};
|
|
196
|
+
const evaluateAuthority = (candidate, binding, context, diagnostics) => {
|
|
197
|
+
const referenceSatisfied = candidate.authority_references.some((reference) => {
|
|
198
|
+
const evidence = context.evidence.get(reference.evidence_id);
|
|
199
|
+
return (evidence !== undefined &&
|
|
200
|
+
(candidate.required_original_authority === "static"
|
|
201
|
+
? ["candidate", "observed"].includes(reference.state)
|
|
202
|
+
: reference.state === "observed") &&
|
|
203
|
+
evidenceSupportsOriginalAuthority(evidence, candidate.required_original_authority));
|
|
204
|
+
});
|
|
205
|
+
const caseSatisfied = originalCasesFor(candidate, binding).some(({ evidence_id: evidenceId }) => {
|
|
206
|
+
const evidence = context.evidence.get(evidenceId);
|
|
207
|
+
return (evidence !== undefined &&
|
|
208
|
+
evidenceSupportsOriginalAuthority(evidence, candidate.required_original_authority));
|
|
209
|
+
});
|
|
210
|
+
const satisfied = referenceSatisfied || caseSatisfied;
|
|
211
|
+
if (!satisfied)
|
|
212
|
+
addDiagnostic(diagnostics, "static-only", `No ${candidate.required_original_authority} authority characterizes the original finite behavior.`);
|
|
213
|
+
};
|
|
214
|
+
const evaluateDisposition = (candidate, diagnostics) => {
|
|
215
|
+
if (candidate.disposition === "blocked")
|
|
216
|
+
addDiagnostic(diagnostics, "blocked", "Reviewed disposition marks this obligation blocked.");
|
|
217
|
+
if (candidate.disposition === "out-of-scope")
|
|
218
|
+
addDiagnostic(diagnostics, "out-of-scope", "Reviewed disposition marks this obligation out of scope; it remains visible.");
|
|
219
|
+
};
|
|
220
|
+
const applyDependencyDiagnostics = (obligations, context) => {
|
|
221
|
+
let evaluated = [...obligations];
|
|
222
|
+
for (let pass = 0; pass < obligations.length; pass += 1) {
|
|
223
|
+
const statuses = new Map(evaluated.map(({ obligation_id: id, status }) => [id, status]));
|
|
224
|
+
let changed = false;
|
|
225
|
+
evaluated = evaluated.map((obligation) => {
|
|
226
|
+
const diagnostics = [...obligation.diagnostics];
|
|
227
|
+
for (const dependencyId of obligation.dependency_obligation_ids) {
|
|
228
|
+
const missing = !context.candidates.has(dependencyId);
|
|
229
|
+
if (missing || statuses.get(dependencyId) !== "verified")
|
|
230
|
+
addDiagnostic(diagnostics, missing ? "dependency-missing" : "dependency-open", `Dependency obligation is ${missing ? "missing" : "not verified"}: ${dependencyId}.`);
|
|
231
|
+
}
|
|
232
|
+
const normalized = uniqueDiagnostics(diagnostics);
|
|
233
|
+
const status = dependencyStatus(obligation.status, normalized);
|
|
234
|
+
changed ||= status !== obligation.status;
|
|
235
|
+
return { ...obligation, status, diagnostics: normalized };
|
|
236
|
+
});
|
|
237
|
+
if (!changed)
|
|
238
|
+
break;
|
|
239
|
+
}
|
|
240
|
+
return evaluated;
|
|
241
|
+
};
|
|
242
|
+
const obligationStatus = (candidate, binding, diagnostics) => {
|
|
243
|
+
if (hasDiagnostic(diagnostics, "out-of-scope"))
|
|
244
|
+
return "out-of-scope";
|
|
245
|
+
if (hasDiagnostic(diagnostics, "blocked"))
|
|
246
|
+
return "blocked";
|
|
247
|
+
if (hasDiagnostic(diagnostics, "contradiction"))
|
|
248
|
+
return "contradicted";
|
|
249
|
+
if (hasDiagnostic(diagnostics, "duplicate-definition") ||
|
|
250
|
+
hasDiagnostic(diagnostics, "residual-unknown") ||
|
|
251
|
+
hasDiagnostic(diagnostics, "unavailable-authority"))
|
|
252
|
+
return "unknown";
|
|
253
|
+
if (binding === null)
|
|
254
|
+
return "unowned";
|
|
255
|
+
if (diagnostics.length === 0)
|
|
256
|
+
return "verified";
|
|
257
|
+
return "implemented";
|
|
258
|
+
};
|
|
259
|
+
const dependencyStatus = (status, diagnostics) => (hasDiagnostic(diagnostics, "dependency-missing") ||
|
|
260
|
+
hasDiagnostic(diagnostics, "dependency-open")) &&
|
|
261
|
+
!["contradicted", "out-of-scope"].includes(status)
|
|
262
|
+
? "blocked"
|
|
263
|
+
: status;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import canonicalize from "canonicalize";
|
|
3
|
+
export const obligationLedgerCoverage = (omittedCount, maxObligations, incomplete) => ({
|
|
4
|
+
status: incomplete ? "partial" : "complete",
|
|
5
|
+
truncated: omittedCount > 0,
|
|
6
|
+
omitted_count: omittedCount,
|
|
7
|
+
max_obligations: maxObligations,
|
|
8
|
+
});
|
|
9
|
+
export const summarizeObligations = (obligations) => ({
|
|
10
|
+
total: obligations.length,
|
|
11
|
+
required: obligations.filter(({ required }) => required).length,
|
|
12
|
+
verified: obligations.filter(({ status }) => status === "verified").length,
|
|
13
|
+
required_open: obligations.filter(({ required, status }) => required && status !== "verified").length,
|
|
14
|
+
by_status: countBy(obligations, [
|
|
15
|
+
"unowned",
|
|
16
|
+
"characterized",
|
|
17
|
+
"implemented",
|
|
18
|
+
"verified",
|
|
19
|
+
"contradicted",
|
|
20
|
+
"blocked",
|
|
21
|
+
"out-of-scope",
|
|
22
|
+
"unknown",
|
|
23
|
+
], ({ status }) => status),
|
|
24
|
+
by_application_layer: countBy(obligations, [
|
|
25
|
+
"cli",
|
|
26
|
+
"protocol",
|
|
27
|
+
"electron",
|
|
28
|
+
"persistence",
|
|
29
|
+
"process",
|
|
30
|
+
"runtime",
|
|
31
|
+
"packaging",
|
|
32
|
+
"native-abi",
|
|
33
|
+
"application",
|
|
34
|
+
"other",
|
|
35
|
+
], ({ application_layer: layer }) => layer),
|
|
36
|
+
by_evidence_authority: countBy(obligations, ["candidate", "observed", "reviewed", "unknown"], ({ source_state: state }) => state),
|
|
37
|
+
});
|
|
38
|
+
export const obligationReports = (obligations) => ({
|
|
39
|
+
missing_owner_obligation_ids: obligationIdsWith(obligations, "missing-owner"),
|
|
40
|
+
missing_verifier_obligation_ids: obligationIdsWith(obligations, "missing-verifier"),
|
|
41
|
+
contradicted_obligation_ids: obligationIdsWith(obligations, "contradiction"),
|
|
42
|
+
residual_unknown_ids: [
|
|
43
|
+
...new Set(obligations.flatMap(({ residual_unknown_ids: ids }) => ids)),
|
|
44
|
+
].sort(),
|
|
45
|
+
});
|
|
46
|
+
export const obligationLedgerEvidenceLinks = (obligations, manifest) => [
|
|
47
|
+
...new Set([
|
|
48
|
+
...obligations.flatMap(({ authority_references: references }) => references.map(({ evidence_id: id }) => id)),
|
|
49
|
+
...manifest.bindings.flatMap((binding) => [
|
|
50
|
+
...binding.original_cases.map(({ evidence_id: id }) => id),
|
|
51
|
+
...binding.fixtures.flatMap(({ evidence_ids: ids }) => ids),
|
|
52
|
+
...(binding.verifier === null
|
|
53
|
+
? []
|
|
54
|
+
: [binding.verifier.result_evidence_id]),
|
|
55
|
+
]),
|
|
56
|
+
...manifest.contradictions.flatMap(({ evidence_ids: ids }) => ids),
|
|
57
|
+
]),
|
|
58
|
+
].sort();
|
|
59
|
+
export const obligationLedgerStatus = (obligations, omittedCount) => {
|
|
60
|
+
if (obligations.length === 0)
|
|
61
|
+
return "unknown";
|
|
62
|
+
const requiredOpen = obligations.filter(({ required, status }) => required && status !== "verified");
|
|
63
|
+
if (requiredOpen.some(({ status, diagnostics }) => status === "contradicted" ||
|
|
64
|
+
hasDiagnostic(diagnostics, "verifier-failed")))
|
|
65
|
+
return "failed";
|
|
66
|
+
if (omittedCount > 0 ||
|
|
67
|
+
requiredOpen.some(({ status }) => status === "unknown"))
|
|
68
|
+
return "unknown";
|
|
69
|
+
return requiredOpen.length === 0 ? "ready" : "open";
|
|
70
|
+
};
|
|
71
|
+
export const obligationEdgeOrder = (left, right) => JSON.stringify(left).localeCompare(JSON.stringify(right));
|
|
72
|
+
export const digestObligationLedgerValue = (value) => {
|
|
73
|
+
const encoded = canonicalize(value);
|
|
74
|
+
if (encoded === undefined)
|
|
75
|
+
throw new TypeError("Reconstruction obligation ledger is not canonical JSON");
|
|
76
|
+
return createHash("sha256").update(encoded).digest("hex");
|
|
77
|
+
};
|
|
78
|
+
const countBy = (items, values, valueFor) => values.map((value) => ({
|
|
79
|
+
key: value,
|
|
80
|
+
count: items.filter((item) => valueFor(item) === value).length,
|
|
81
|
+
}));
|
|
82
|
+
const obligationIdsWith = (obligations, code) => obligations
|
|
83
|
+
.filter(({ diagnostics }) => hasDiagnostic(diagnostics, code))
|
|
84
|
+
.map(({ obligation_id: id }) => id)
|
|
85
|
+
.sort();
|
|
86
|
+
const hasDiagnostic = (diagnostics, code) => diagnostics.some((diagnostic) => diagnostic.code === code);
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { AnalysisInputError, AnalysisProtocolError, } from "../domain/errors.js";
|
|
3
|
+
import { createEvidence } from "../domain/evidence.js";
|
|
4
|
+
import { jsonObjectSchema, jsonValueSchema } from "../domain/jsonValue.js";
|
|
5
|
+
import { reconstructionObligationLedgerInputSchema, reconstructionObligationLedgerPageSchema, } from "../domain/reconstructionObligationLedgerSchemas.js";
|
|
6
|
+
import { err, ok } from "../domain/result.js";
|
|
7
|
+
import { JAVASCRIPT_APPLICATION_WORKFLOW_PROVIDER } from "./InvestigationProviders.js";
|
|
8
|
+
import { deriveReconstructionObligationCandidates } from "./ReconstructionObligationCandidates.js";
|
|
9
|
+
import { evaluateReconstructionObligationLedger } from "./ReconstructionObligationLedgerEvaluation.js";
|
|
10
|
+
const OPERATION = "build_reconstruction_obligation_ledger";
|
|
11
|
+
/** Parse one portable ledger request for both CLI and MCP adapters. */
|
|
12
|
+
export const resolveReconstructionObligationLedgerRequest = (input) => {
|
|
13
|
+
const parsed = reconstructionObligationLedgerInputSchema.safeParse(input);
|
|
14
|
+
return parsed.success
|
|
15
|
+
? ok(parsed.data)
|
|
16
|
+
: err(new AnalysisInputError(OPERATION, { cause: parsed.error }));
|
|
17
|
+
};
|
|
18
|
+
/** Build one deterministic ledger page and wrap it in portable Evidence v2. */
|
|
19
|
+
export const buildReconstructionObligationLedgerEvidenceValidated = (input) => {
|
|
20
|
+
try {
|
|
21
|
+
const generated = deriveReconstructionObligationCandidates(input.evidence_bundle, input.reviewed_obligations);
|
|
22
|
+
const ledger = evaluateReconstructionObligationLedger({
|
|
23
|
+
candidates: generated.candidates,
|
|
24
|
+
bundle: input.evidence_bundle,
|
|
25
|
+
manifest: input.manifest,
|
|
26
|
+
maxObligations: input.limits.max_obligations,
|
|
27
|
+
generationLimitations: generated.limitations,
|
|
28
|
+
});
|
|
29
|
+
const page = pageLedger(ledger, input.page.offset, input.page.limit);
|
|
30
|
+
return ok(createLedgerEvidence(input, page));
|
|
31
|
+
}
|
|
32
|
+
catch (cause) {
|
|
33
|
+
if (cause instanceof z.ZodError)
|
|
34
|
+
return err(new AnalysisInputError(OPERATION, { cause }));
|
|
35
|
+
return err(new AnalysisProtocolError("Reconstruction obligation ledger generation failed", { cause }));
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
const pageLedger = (ledger, offset, limit) => {
|
|
39
|
+
const obligations = ledger.obligations.slice(offset, offset + limit);
|
|
40
|
+
const nextOffset = offset + obligations.length < ledger.obligations.length
|
|
41
|
+
? offset + obligations.length
|
|
42
|
+
: null;
|
|
43
|
+
const { obligations: _allObligations, ...summary } = ledger;
|
|
44
|
+
return reconstructionObligationLedgerPageSchema.parse({
|
|
45
|
+
...summary,
|
|
46
|
+
page: {
|
|
47
|
+
offset,
|
|
48
|
+
limit,
|
|
49
|
+
total: ledger.obligations.length,
|
|
50
|
+
returned: obligations.length,
|
|
51
|
+
next_offset: nextOffset,
|
|
52
|
+
},
|
|
53
|
+
obligations,
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
const createLedgerEvidence = (input, page) => createEvidence(undefined, JAVASCRIPT_APPLICATION_WORKFLOW_PROVIDER, {
|
|
57
|
+
predicateType: "rea.reconstruction-obligation-ledger/v1",
|
|
58
|
+
operation: OPERATION,
|
|
59
|
+
parameters: jsonObjectSchema.parse({
|
|
60
|
+
ledger_id: page.ledger_id,
|
|
61
|
+
closure_digest: page.closure_digest,
|
|
62
|
+
limits: input.limits,
|
|
63
|
+
page: input.page,
|
|
64
|
+
}),
|
|
65
|
+
result: jsonValueSchema.parse(page),
|
|
66
|
+
rawResult: null,
|
|
67
|
+
confidence: "inferred",
|
|
68
|
+
authority: "analyst-inference",
|
|
69
|
+
environment: null,
|
|
70
|
+
limitations: page.limitations,
|
|
71
|
+
evidenceLinks: page.evidence_links,
|
|
72
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { evidenceSupportsOriginalAuthority } from "./ReconstructionObligationAuthority.js";
|
|
2
|
+
/** Merge generated and manifest-supplied original observations canonically. */
|
|
3
|
+
export const originalCasesFor = (candidate, binding) => [
|
|
4
|
+
...new Map([...candidate.observed_cases, ...(binding?.original_cases ?? [])].map((observed) => [
|
|
5
|
+
`${observed.kind}:${observed.evidence_id}:${observed.location}`,
|
|
6
|
+
observed,
|
|
7
|
+
])).values(),
|
|
8
|
+
].sort((left, right) => `${left.kind}:${left.evidence_id}:${left.location}`.localeCompare(`${right.kind}:${right.evidence_id}:${right.location}`));
|
|
9
|
+
/** Report original cases that are absent or lack comparable Evidence authority. */
|
|
10
|
+
export const originalCaseDiagnostics = (candidate, binding, evidenceById) => {
|
|
11
|
+
const diagnostics = [];
|
|
12
|
+
const originalCases = originalCasesFor(candidate, binding);
|
|
13
|
+
for (const caseKind of candidate.required_case_kinds) {
|
|
14
|
+
const cases = originalCases.filter(({ kind }) => kind === caseKind);
|
|
15
|
+
if (cases.length === 0) {
|
|
16
|
+
diagnostics.push({
|
|
17
|
+
code: "missing-original-case",
|
|
18
|
+
detail: `Original ${caseKind} behavior has not been observed.`,
|
|
19
|
+
});
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
if (!cases.some(({ evidence_id: evidenceId }) => {
|
|
23
|
+
const evidence = evidenceById.get(evidenceId);
|
|
24
|
+
return (evidence !== undefined &&
|
|
25
|
+
evidenceSupportsOriginalAuthority(evidence, candidate.required_original_authority));
|
|
26
|
+
}))
|
|
27
|
+
diagnostics.push({
|
|
28
|
+
code: "weak-original-case-authority",
|
|
29
|
+
detail: `Original ${caseKind} behavior lacks ${candidate.required_original_authority} Evidence.`,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
return diagnostics;
|
|
33
|
+
};
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
const APPLICATION_NODE_POLICIES = {
|
|
2
|
+
package: policy("packaging", "package-lifecycle", "packaged-process", [
|
|
3
|
+
"positive",
|
|
4
|
+
"negative",
|
|
5
|
+
"teardown",
|
|
6
|
+
]),
|
|
7
|
+
installer: policy("packaging", "installer", "packaged-process", [
|
|
8
|
+
"positive",
|
|
9
|
+
"negative",
|
|
10
|
+
"teardown",
|
|
11
|
+
]),
|
|
12
|
+
"context-bridge-api": policy("electron", "context-bridge", "renderer", [
|
|
13
|
+
"positive",
|
|
14
|
+
"negative",
|
|
15
|
+
"malformed",
|
|
16
|
+
]),
|
|
17
|
+
"ipc-channel": policy("electron", "ipc", "renderer", [
|
|
18
|
+
"positive",
|
|
19
|
+
"negative",
|
|
20
|
+
"malformed",
|
|
21
|
+
]),
|
|
22
|
+
"ipc-handler": policy("electron", "ipc", "renderer", [
|
|
23
|
+
"positive",
|
|
24
|
+
"negative",
|
|
25
|
+
"malformed",
|
|
26
|
+
]),
|
|
27
|
+
endpoint: policy("protocol", "endpoint", "protocol", [
|
|
28
|
+
"positive",
|
|
29
|
+
"negative",
|
|
30
|
+
"malformed",
|
|
31
|
+
]),
|
|
32
|
+
storage: policy("persistence", "persistence", "integration", [
|
|
33
|
+
"positive",
|
|
34
|
+
"negative",
|
|
35
|
+
"malformed",
|
|
36
|
+
]),
|
|
37
|
+
worker: policy("process", "worker-lifecycle", "packaged-process", [
|
|
38
|
+
"positive",
|
|
39
|
+
"cancellation",
|
|
40
|
+
"teardown",
|
|
41
|
+
]),
|
|
42
|
+
"service-worker": policy("process", "worker-lifecycle", "packaged-process", [
|
|
43
|
+
"positive",
|
|
44
|
+
"cancellation",
|
|
45
|
+
"teardown",
|
|
46
|
+
]),
|
|
47
|
+
"native-addon": nativePolicy("native-addon"),
|
|
48
|
+
"native-export": nativePolicy("native-export"),
|
|
49
|
+
"managed-pinvoke-import": nativePolicy("managed-pinvoke"),
|
|
50
|
+
"managed-native-implementation": nativePolicy("managed-native"),
|
|
51
|
+
};
|
|
52
|
+
const SEMANTIC_NODE_POLICIES = {
|
|
53
|
+
"child-process": policy("process", "child-process", "packaged-process", [
|
|
54
|
+
"positive",
|
|
55
|
+
"negative",
|
|
56
|
+
"cancellation",
|
|
57
|
+
"teardown",
|
|
58
|
+
]),
|
|
59
|
+
stdio: policy("process", "stdio", "packaged-process", [
|
|
60
|
+
"positive",
|
|
61
|
+
"negative",
|
|
62
|
+
"teardown",
|
|
63
|
+
]),
|
|
64
|
+
signal: policy("process", "signal", "packaged-process", [
|
|
65
|
+
"positive",
|
|
66
|
+
"cancellation",
|
|
67
|
+
"teardown",
|
|
68
|
+
]),
|
|
69
|
+
"config-source": parserPolicy("cli", "configuration", "integration"),
|
|
70
|
+
request: parserPolicy("protocol", "request", "protocol"),
|
|
71
|
+
response: parserPolicy("protocol", "response", "protocol"),
|
|
72
|
+
boundary: parserPolicy("application", "parser-boundary", "integration"),
|
|
73
|
+
resource: policy("persistence", "resource-lifecycle", "integration", [
|
|
74
|
+
"positive",
|
|
75
|
+
"negative",
|
|
76
|
+
"teardown",
|
|
77
|
+
]),
|
|
78
|
+
event: policy("runtime", "event", "packaged-process", [
|
|
79
|
+
"positive",
|
|
80
|
+
"negative",
|
|
81
|
+
"cancellation",
|
|
82
|
+
]),
|
|
83
|
+
timer: policy("runtime", "timer", "packaged-process", [
|
|
84
|
+
"positive",
|
|
85
|
+
"cancellation",
|
|
86
|
+
"teardown",
|
|
87
|
+
]),
|
|
88
|
+
promise: policy("runtime", "promise-ownership", "packaged-process", [
|
|
89
|
+
"positive",
|
|
90
|
+
"negative",
|
|
91
|
+
"cancellation",
|
|
92
|
+
]),
|
|
93
|
+
task: policy("runtime", "task-lifecycle", "packaged-process", [
|
|
94
|
+
"positive",
|
|
95
|
+
"cancellation",
|
|
96
|
+
"teardown",
|
|
97
|
+
]),
|
|
98
|
+
};
|
|
99
|
+
export const applicationObligationPolicy = (nodeKind) => APPLICATION_NODE_POLICIES[nodeKind];
|
|
100
|
+
export const semanticObligationPolicy = (nodeKind) => SEMANTIC_NODE_POLICIES[nodeKind];
|
|
101
|
+
function policy(applicationLayer, family, authority, cases) {
|
|
102
|
+
return {
|
|
103
|
+
applicationLayer,
|
|
104
|
+
family,
|
|
105
|
+
fixtureAuthority: authority,
|
|
106
|
+
verifierAuthority: authority,
|
|
107
|
+
originalAuthority: "runtime",
|
|
108
|
+
cases,
|
|
109
|
+
requiresParserType: false,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
function parserPolicy(applicationLayer, family, authority) {
|
|
113
|
+
return {
|
|
114
|
+
...policy(applicationLayer, family, authority, [
|
|
115
|
+
"positive",
|
|
116
|
+
"negative",
|
|
117
|
+
"malformed",
|
|
118
|
+
]),
|
|
119
|
+
requiresParserType: true,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function nativePolicy(family) {
|
|
123
|
+
return {
|
|
124
|
+
applicationLayer: "native-abi",
|
|
125
|
+
family,
|
|
126
|
+
fixtureAuthority: "native-abi",
|
|
127
|
+
verifierAuthority: "native-abi",
|
|
128
|
+
originalAuthority: "static",
|
|
129
|
+
cases: ["positive", "negative"],
|
|
130
|
+
requiresParserType: false,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { AnalysisInputError, AnalysisProtocolError, } from "../domain/errors.js";
|
|
3
|
+
import { createEvidence } from "../domain/evidence.js";
|
|
4
|
+
import { jsonObjectSchema, jsonValueSchema } from "../domain/jsonValue.js";
|
|
5
|
+
import { createReconstructionReadinessReport } from "../domain/reconstructionReadiness.js";
|
|
6
|
+
import { reconstructionReadinessInputSchema, } from "../domain/reconstructionReadinessSchemas.js";
|
|
7
|
+
import { err, ok } from "../domain/result.js";
|
|
8
|
+
import { JAVASCRIPT_APPLICATION_WORKFLOW_PROVIDER } from "./InvestigationProviders.js";
|
|
9
|
+
const OPERATION = "evaluate_reconstruction_readiness";
|
|
10
|
+
/** Parse one portable readiness request for both CLI and MCP adapters. */
|
|
11
|
+
export const resolveReconstructionReadinessRequest = (input) => {
|
|
12
|
+
const parsed = reconstructionReadinessInputSchema.safeParse(input);
|
|
13
|
+
return parsed.success
|
|
14
|
+
? ok(parsed.data)
|
|
15
|
+
: err(new AnalysisInputError(OPERATION, { cause: parsed.error }));
|
|
16
|
+
};
|
|
17
|
+
/** Evaluate and wrap one deterministic readiness report in Evidence v2. */
|
|
18
|
+
export const evaluateReconstructionReadinessValidated = (input) => {
|
|
19
|
+
try {
|
|
20
|
+
const report = createReconstructionReadinessReport(input);
|
|
21
|
+
return ok(createEvidence(undefined, JAVASCRIPT_APPLICATION_WORKFLOW_PROVIDER, {
|
|
22
|
+
predicateType: "rea.reconstruction-readiness-report/v1",
|
|
23
|
+
operation: OPERATION,
|
|
24
|
+
parameters: jsonObjectSchema.parse({
|
|
25
|
+
source_digest: report.source_digest,
|
|
26
|
+
expected_source_digest: input.replay.expected_source_digest,
|
|
27
|
+
}),
|
|
28
|
+
result: jsonValueSchema.parse(report),
|
|
29
|
+
rawResult: null,
|
|
30
|
+
confidence: "inferred",
|
|
31
|
+
authority: "analyst-inference",
|
|
32
|
+
environment: null,
|
|
33
|
+
limitations: report.status === "pass"
|
|
34
|
+
? []
|
|
35
|
+
: [
|
|
36
|
+
"Aggregate pass is withheld until every required conformance stage passes.",
|
|
37
|
+
],
|
|
38
|
+
evidenceLinks: report.evidence_links,
|
|
39
|
+
}));
|
|
40
|
+
}
|
|
41
|
+
catch (cause) {
|
|
42
|
+
if (cause instanceof z.ZodError)
|
|
43
|
+
return err(new AnalysisInputError(OPERATION, { cause }));
|
|
44
|
+
return err(new AnalysisProtocolError("Reconstruction readiness evaluation failed", {
|
|
45
|
+
cause,
|
|
46
|
+
}));
|
|
47
|
+
}
|
|
48
|
+
};
|