Skip to main content

kernel_conformance/
reference_interpreters.rs

1use constitutional_memory::{
2    evaluate_amendment, evaluate_archive_compaction, AmendmentDecisionV1, AmendmentProposalV1,
3    ArchiveManifestV1, CharterBundleV1, CompactionReceiptV1, HistoricalQueryGuaranteeV1,
4};
5use constraint_compiler::{compile_batch, CompileOutput, CompilerPolicy};
6use discovery_portfolio::{
7    evaluate_portfolio_plan, CampaignDecisionTraceV1, DiscoveryProgramV1, ExperimentCampaignV1,
8    InformationValueEstimateV1, PortfolioPlanV1, ProgramHypothesisSetV1, VerificationLoadBudgetV1,
9};
10use federated_settlement::{
11    evaluate_divergence_or_suspension, evaluate_settlement, evaluate_shared_replay,
12    SettlementCaseV1, SettlementReceiptV1, SharedDivergenceReportV1, SharedReplaySliceV1,
13    TreatySuspensionV1,
14};
15#[allow(deprecated)]
16use forge_memory_bridge::{transform_envelope_v2, transform_envelope_v3, ProjectionImportBatchV3};
17use kernel_execution::{schedule_execution, ExecutionBudget, ScheduledExecution};
18use kernel_oracles::{
19    evaluate_causal_refuter, evaluate_conservative, evaluate_exact_bounded,
20    evaluate_temporal_replay, minimal_perturbation_witness, OracleRefutationResult,
21    TemporalReplayAssessment, TemporalReplaySnapshot,
22};
23use mechanism_runtime::{
24    evaluate_fit_run, FitRunV1, MechanismBundleV1, RolloutStabilityReportV1, SimulationContractV1,
25    TheoryRefuterSuiteV1, TheoryVersionV1,
26};
27use semantic_memory_forge::{ExportEnvelopeV2, ExportEnvelopeV3};
28use spec_execution::{
29    establish_veto_challenge_baseline, generate_companion_bundles, generate_schema_bundle,
30    GeneratedCompanionBundles, GeneratedSchemaBundleV1, HumanVetoBundleV1, MetaChallengeBundleV1,
31    NormativeASTV1, ProofEvaluationReceiptV1, ProofObligationSetV1, SelfHostingBuildReceiptV1,
32    SpecBundleV1,
33};
34use verification_control::{replay_case, LedgerEntry, ReplayedCaseState};
35
36#[derive(Debug, Clone)]
37pub struct BridgeReferenceInterpretation {
38    pub source_schema_version: String,
39    pub record_count: usize,
40    pub preserved_execution_context: bool,
41    pub preserved_evidence_bundle: bool,
42}
43
44impl BridgeReferenceInterpretation {
45    /// Interprets a V3 Forge export envelope through the reference bridge path.
46    pub fn from_v3(envelope: &ExportEnvelopeV3) -> Result<Self, forge_memory_bridge::BridgeError> {
47        let batch = transform_envelope_v3(envelope)?;
48        Ok(Self {
49            source_schema_version: envelope.schema_version.clone(),
50            preserved_execution_context: batch.execution_context.is_some(),
51            preserved_evidence_bundle: batch.evidence_bundle.is_some(),
52            record_count: batch.records.len(),
53        })
54    }
55
56    #[allow(deprecated)]
57    /// Interprets a deprecated V2 Forge export envelope through the reference bridge path.
58    pub fn from_v2(envelope: &ExportEnvelopeV2) -> Result<Self, forge_memory_bridge::BridgeError> {
59        let batch = transform_envelope_v2(envelope)?;
60        Ok(Self {
61            source_schema_version: envelope.schema_version.clone(),
62            preserved_execution_context: false,
63            preserved_evidence_bundle: false,
64            record_count: batch.records.len(),
65        })
66    }
67}
68
69#[derive(Debug, Clone)]
70pub struct BitemporalReferenceInterpretation {
71    pub assessment: TemporalReplayAssessment,
72    pub compiled: CompileOutput,
73}
74
75/// Replays the newest snapshot before a cutoff and returns both assessment and compiled graph.
76pub fn interpret_bitemporal_replay(
77    snapshots: &[TemporalReplaySnapshot],
78    cutoff_recorded_at: &str,
79    policy: &CompilerPolicy,
80    expected_hash: &stack_ids::ContentDigest,
81) -> Option<BitemporalReferenceInterpretation> {
82    let assessment =
83        evaluate_temporal_replay(snapshots, cutoff_recorded_at, policy, expected_hash)?;
84    let selected = snapshots
85        .iter()
86        .find(|snapshot| snapshot.recorded_at == assessment.selected_recorded_at)?;
87    let compiled = compile_batch(&selected.batch, policy);
88    Some(BitemporalReferenceInterpretation {
89        assessment,
90        compiled,
91    })
92}
93
94#[derive(Debug, Clone)]
95pub struct BoundedKernelSliceInterpretation {
96    pub compiled: CompileOutput,
97    pub scheduled: ScheduledExecution,
98    pub exact_supported: bool,
99}
100
101/// Interprets a batch through compilation, oracle support, and scheduler selection.
102pub fn interpret_bounded_kernel_slice(
103    batch: &ProjectionImportBatchV3,
104    policy: &CompilerPolicy,
105    budget: &ExecutionBudget,
106) -> BoundedKernelSliceInterpretation {
107    let compiled = compile_batch(batch, policy);
108    let exact_supported = evaluate_exact_bounded(&compiled).is_some();
109    let scheduled = schedule_execution(&compiled, budget);
110    BoundedKernelSliceInterpretation {
111        compiled,
112        scheduled,
113        exact_supported,
114    }
115}
116
117#[derive(Debug, Clone)]
118pub struct RepairReplayInterpretation {
119    pub replayed: ReplayedCaseState,
120}
121
122/// Replays a repair ledger into the reference replay state.
123pub fn interpret_repair_replay(
124    entries: &[LedgerEntry],
125) -> Result<RepairReplayInterpretation, String> {
126    replay_case(entries).map(|replayed| RepairReplayInterpretation { replayed })
127}
128
129/// Interprets a settlement case into its bounded admissibility receipt.
130pub fn interpret_settlement_admissibility(
131    case: &SettlementCaseV1,
132    generated_at: &str,
133) -> SettlementReceiptV1 {
134    evaluate_settlement(case, generated_at)
135}
136
137/// Interprets the shared replay slice for a settlement case.
138pub fn interpret_shared_replay(case: &SettlementCaseV1, generated_at: &str) -> SharedReplaySliceV1 {
139    evaluate_shared_replay(case, generated_at)
140}
141
142/// Interprets divergence reporting and optional suspension for a settlement case.
143pub fn interpret_divergence_or_suspension(
144    case: &SettlementCaseV1,
145    replay: &SharedReplaySliceV1,
146    divergence_summary: &str,
147    generated_at: &str,
148) -> (SharedDivergenceReportV1, Option<TreatySuspensionV1>) {
149    evaluate_divergence_or_suspension(case, replay, divergence_summary, generated_at)
150}
151
152/// Interprets the bounded mechanism-fit decision for a theory and contract.
153pub fn interpret_mechanism_fit(
154    mechanism: &MechanismBundleV1,
155    theory: &TheoryVersionV1,
156    contract: &SimulationContractV1,
157    refuter_suite: &TheoryRefuterSuiteV1,
158    stability_report: &RolloutStabilityReportV1,
159    fit_score: f64,
160    generated_at: &str,
161) -> FitRunV1 {
162    evaluate_fit_run(
163        mechanism,
164        theory,
165        contract,
166        refuter_suite,
167        stability_report,
168        fit_score,
169        generated_at,
170    )
171}
172
173/// Interprets portfolio budgeting and campaign-selection pressure for a program.
174pub fn interpret_portfolio_budget(
175    program: &DiscoveryProgramV1,
176    hypotheses: &ProgramHypothesisSetV1,
177    plan: &PortfolioPlanV1,
178    campaigns: &[ExperimentCampaignV1],
179    value_estimates: &[InformationValueEstimateV1],
180    budget: &VerificationLoadBudgetV1,
181    generated_at: &str,
182) -> CampaignDecisionTraceV1 {
183    evaluate_portfolio_plan(
184        program,
185        hypotheses,
186        plan,
187        campaigns,
188        value_estimates,
189        budget,
190        generated_at,
191    )
192}
193
194/// Interprets a constitutional amendment proposal into its bounded decision artifact.
195pub fn interpret_constitutional_change(
196    proposal: &AmendmentProposalV1,
197    migration_obligations_satisfied: bool,
198    archive_manifest: Option<&ArchiveManifestV1>,
199    historical_query_guarantee: Option<&HistoricalQueryGuaranteeV1>,
200    decided_at: &str,
201) -> AmendmentDecisionV1 {
202    evaluate_amendment(
203        proposal,
204        migration_obligations_satisfied,
205        archive_manifest,
206        historical_query_guarantee,
207        decided_at,
208    )
209}
210
211/// Interprets archive compaction into manifest, guarantee, and receipt artifacts.
212pub fn interpret_archive_compaction(
213    charter: &CharterBundleV1,
214    preserved_refs: Vec<String>,
215    dropped_detail_refs: Vec<String>,
216    guaranteed_query_modes: Vec<String>,
217) -> (
218    ArchiveManifestV1,
219    HistoricalQueryGuaranteeV1,
220    CompactionReceiptV1,
221) {
222    evaluate_archive_compaction(
223        charter.charter_bundle_id.clone(),
224        preserved_refs,
225        dropped_detail_refs,
226        guaranteed_query_modes,
227    )
228}
229
230/// Interprets generated schema integrity for a spec surface.
231pub fn interpret_generated_artifact_integrity(
232    spec: &SpecBundleV1,
233    ast: &NormativeASTV1,
234    obligations: &ProofObligationSetV1,
235    schema_family: &str,
236    generated_at: &str,
237) -> (GeneratedSchemaBundleV1, ProofEvaluationReceiptV1) {
238    generate_schema_bundle(spec, ast, obligations, schema_family, generated_at)
239}
240
241/// Interprets the generated companion bundles for a spec surface.
242pub fn interpret_generated_companion_bundles(
243    spec: &SpecBundleV1,
244    ast: &NormativeASTV1,
245    obligations: &ProofObligationSetV1,
246    schema_family: &str,
247    generated_at: &str,
248) -> GeneratedCompanionBundles {
249    generate_companion_bundles(spec, ast, obligations, schema_family, generated_at)
250}
251
252/// Interprets veto/challenge governance for generated surface artifacts.
253pub fn interpret_generated_surface_governance(
254    spec: &SpecBundleV1,
255    bundles: &GeneratedCompanionBundles,
256    human_veto: Option<&HumanVetoBundleV1>,
257    meta_challenge: Option<&MetaChallengeBundleV1>,
258    generated_at: &str,
259) -> SelfHostingBuildReceiptV1 {
260    establish_veto_challenge_baseline(
261        spec,
262        &bundles.schema_bundle,
263        &bundles.interpreter_bundle,
264        &bundles.conformance_corpus,
265        &bundles.migration_plan,
266        &bundles.proof_evaluation_receipt,
267        human_veto,
268        meta_challenge,
269        generated_at,
270    )
271}
272
273#[derive(Debug, Clone)]
274pub struct CausalWorkflowInterpretation {
275    pub compiled: CompileOutput,
276    pub exact_supported: bool,
277    pub conservative_supported: bool,
278    pub causal_refutation: OracleRefutationResult,
279    pub minimal_perturbation: OracleRefutationResult,
280}
281
282/// Interprets a causal workflow through oracle and refutation reference paths.
283pub fn interpret_causal_workflow(
284    batch: &ProjectionImportBatchV3,
285    policy: &CompilerPolicy,
286    target_node_id: &str,
287    search_budget: usize,
288) -> CausalWorkflowInterpretation {
289    let compiled = compile_batch(batch, policy);
290    let exact_supported = evaluate_exact_bounded(&compiled).is_some();
291    let conservative_supported = evaluate_conservative(&compiled).supported;
292    let causal_refutation = evaluate_causal_refuter(&compiled, target_node_id, search_budget);
293    let minimal_perturbation =
294        minimal_perturbation_witness(&compiled, target_node_id, search_budget);
295    CausalWorkflowInterpretation {
296        compiled,
297        exact_supported,
298        conservative_supported,
299        causal_refutation,
300        minimal_perturbation,
301    }
302}
303
304#[cfg(test)]
305mod tests {
306    use super::*;
307    use semantic_memory_forge::{
308        ConstraintSeedKind, ExportAuthority, ExportClaim, ExportConfidenceClass, ExportEnvelopeV2,
309        ExportEnvelopeV3, ExportRecord, ExportRecordSemanticsV3, ExportRecordV3, ForgeExportMeta,
310        ProjectionVisibilityClass,
311    };
312    use stack_ids::{
313        AssertionGroupId, AttemptId, ClaimFamilyId, ClaimId, ClaimVersionId, EntityId, EnvelopeId,
314        ScopeKey, TraceCtx,
315    };
316    use verification_control::{
317        CaseRegion, CheckMethod, CheckPlan, ControlReceipt, LedgerEntry, LedgerEvent,
318        PromotionClass, ReversibilityClass, TerminalDisposition, VerificationAttempt,
319        VerificationAttemptState, VerificationCase, VerificationCaseClass,
320    };
321
322    fn sample_v3_envelope() -> ExportEnvelopeV3 {
323        let scope = ScopeKey::namespace_only("interp");
324        let export_meta = ForgeExportMeta {
325            authority: ExportAuthority::Forge,
326            run_id: Some("run-1".into()),
327            direct_write: false,
328            comparability_snapshot_version: None,
329            exported_at: "2026-03-12T00:00:00Z".into(),
330        };
331        let records = vec![ExportRecordV3 {
332            record: ExportRecord::Claim(ExportClaim {
333                claim_id: None,
334                claim_version_id: Some(ClaimVersionId::new("claim-v1")),
335                subject_entity_id: EntityId::new("entity-1"),
336                predicate: "supports".into(),
337                object_anchor: serde_json::json!("result"),
338                valid_from: None,
339                valid_to: None,
340                confidence: 1.0,
341                content: "claim-v1 supports result".into(),
342                projection_family: "forge_verification".into(),
343                supersedes_claim_id: None,
344                supersedes_claim_version_id: None,
345                metadata: None,
346            }),
347            semantics: Some(ExportRecordSemanticsV3 {
348                claim_family_id: Some(ClaimFamilyId::new("family-1")),
349                assertion_group_id: Some(AssertionGroupId::new("group-1")),
350                relation_group_id: None,
351                joint_evidence_group_id: None,
352                constraint_seed_kind: Some(ConstraintSeedKind::Hyperedge),
353                treatment_hint: None,
354                outcome_hint: None,
355                confounder_hint: None,
356                instrument_hint: None,
357                effect_modifier_hint: None,
358                contradiction_candidate_group_id: None,
359                mutual_exclusion_group_id: None,
360                comparability_snapshot_version: None,
361                nuisance_snapshot: None,
362                projection_visibility_class: ProjectionVisibilityClass::Standard,
363                export_confidence_class: ExportConfidenceClass::Verified,
364                derivation_seed_ids: vec![],
365                review_priority_hint: None,
366            }),
367        }];
368        let digest =
369            ExportEnvelopeV3::compute_digest("forge", &scope, &records, Some(&export_meta), None)
370                .unwrap();
371        ExportEnvelopeV3 {
372            envelope_id: EnvelopeId::new("env-v3"),
373            schema_version: semantic_memory_forge::EXPORT_ENVELOPE_V3_SCHEMA.into(),
374            content_digest: digest,
375            source_authority: "forge".into(),
376            scope_key: scope,
377            trace_ctx: Some(TraceCtx::generate()),
378            exported_at: "2026-03-12T00:00:00Z".into(),
379            export_meta: Some(export_meta),
380            evidence_bundle: None,
381            support_sets: vec![],
382            contradiction_witnesses: vec![],
383            retraction_records: vec![],
384            claim_states_v13: vec![],
385            intervention_bundles_v14: vec![],
386            outcome_schemas_v14: vec![],
387            cohort_contracts_v14: vec![],
388            counterfactual_slices_v14: vec![],
389            experiment_cases_v14: vec![],
390            comparability_matrices_v14: vec![],
391            decision_traces_v14: vec![],
392            refuter_suites_v14: vec![],
393            refuter_results_v14: vec![],
394            experiment_budgets_v14: vec![],
395            rollout_decisions_v14: vec![],
396            rollback_decisions_v14: vec![],
397            attestation_envelopes_v15: vec![],
398            trust_root_sets_v15: vec![],
399            artifact_admission_policies_v15: vec![],
400            transparency_receipts_v15: vec![],
401            attestation_revocations_v15: vec![],
402            attestation_supersessions_v15: vec![],
403            remote_oracle_leases_v15: vec![],
404            remote_slice_requests_v15: vec![],
405            remote_slice_results_v15: vec![],
406            cross_runtime_replay_tickets_v15: vec![],
407            dispute_bundles_v15: vec![],
408            disclosure_policies_v15: vec![],
409            disclosure_budgets_v15: vec![],
410            records,
411        }
412    }
413
414    fn sample_v2_envelope() -> ExportEnvelopeV2 {
415        let scope = ScopeKey::namespace_only("interp");
416        let export_meta = ForgeExportMeta {
417            authority: ExportAuthority::Forge,
418            run_id: Some("run-2".into()),
419            direct_write: false,
420            comparability_snapshot_version: None,
421            exported_at: "2026-03-12T00:00:00Z".into(),
422        };
423        let records = vec![ExportRecord::Claim(ExportClaim {
424            claim_id: Some(ClaimId::new("claim-1")),
425            claim_version_id: Some(ClaimVersionId::new("claim-v1")),
426            subject_entity_id: EntityId::new("entity-1"),
427            predicate: "supports".into(),
428            object_anchor: serde_json::json!("result"),
429            valid_from: None,
430            valid_to: None,
431            confidence: 1.0,
432            content: "claim-v1 supports result".into(),
433            projection_family: "forge_verification".into(),
434            supersedes_claim_id: None,
435            supersedes_claim_version_id: None,
436            metadata: None,
437        })];
438        let digest =
439            ExportEnvelopeV2::compute_digest("forge", &scope, &records, Some(&export_meta), None)
440                .unwrap();
441        ExportEnvelopeV2 {
442            envelope_id: EnvelopeId::new("env-v2"),
443            schema_version: semantic_memory_forge::EXPORT_ENVELOPE_V2_SCHEMA.into(),
444            content_digest: digest,
445            source_authority: "forge".into(),
446            scope_key: scope,
447            trace_ctx: Some(TraceCtx::generate()),
448            exported_at: "2026-03-12T00:00:00Z".into(),
449            export_meta: Some(export_meta),
450            evidence_bundle: None,
451            records,
452        }
453    }
454
455    #[test]
456    fn bridge_reference_interpreter_handles_v2_and_v3() {
457        let v3 = BridgeReferenceInterpretation::from_v3(&sample_v3_envelope()).unwrap();
458        let v2 = BridgeReferenceInterpretation::from_v2(&sample_v2_envelope()).unwrap();
459        assert_eq!(v3.record_count, 1);
460        assert_eq!(v2.record_count, 1);
461        assert_eq!(
462            v3.source_schema_version,
463            semantic_memory_forge::EXPORT_ENVELOPE_V3_SCHEMA
464        );
465        assert_eq!(
466            v2.source_schema_version,
467            semantic_memory_forge::EXPORT_ENVELOPE_V2_SCHEMA
468        );
469    }
470
471    #[test]
472    fn bounded_kernel_slice_reference_interpreter_is_deterministic() {
473        let batch = transform_envelope_v3(&sample_v3_envelope()).unwrap();
474        let policy = CompilerPolicy {
475            policy_version: "interp".into(),
476            include_hyperedges: true,
477        };
478        let a = interpret_bounded_kernel_slice(&batch, &policy, &ExecutionBudget::default());
479        let b = interpret_bounded_kernel_slice(&batch, &policy, &ExecutionBudget::default());
480        assert_eq!(a.compiled.graph_hash, b.compiled.graph_hash);
481        assert_eq!(
482            a.scheduled.execution.execution_mode,
483            b.scheduled.execution.execution_mode
484        );
485    }
486
487    #[test]
488    fn bitemporal_reference_interpreter_selects_latest_snapshot_before_cutoff() {
489        let policy = CompilerPolicy {
490            policy_version: "interp".into(),
491            include_hyperedges: true,
492        };
493        let older = transform_envelope_v3(&sample_v3_envelope()).unwrap();
494        let mut newer = older.clone();
495        newer.source_envelope_id = "env-v3-new".into();
496        let expected = compile_batch(&older, &policy).graph_hash;
497        let snapshots = vec![
498            TemporalReplaySnapshot {
499                recorded_at: "2026-03-11T00:00:00Z".into(),
500                batch: older,
501            },
502            TemporalReplaySnapshot {
503                recorded_at: "2026-03-13T00:00:00Z".into(),
504                batch: newer,
505            },
506        ];
507        let replay =
508            interpret_bitemporal_replay(&snapshots, "2026-03-12T00:00:00Z", &policy, &expected)
509                .unwrap();
510        assert_eq!(
511            replay.assessment.selected_recorded_at,
512            "2026-03-11T00:00:00Z"
513        );
514        assert!(replay.assessment.matched_expected_hash);
515    }
516
517    #[test]
518    fn repair_replay_reference_interpreter_rebuilds_case_state() {
519        let case = VerificationCase::new(
520            VerificationCaseClass::UnverifiedClaimVersion,
521            CaseRegion {
522                namespace: "interp".into(),
523                scope_key: Some(ScopeKey::namespace_only("interp")),
524                target_key: "claim-v1".into(),
525                region_id: None,
526                region_digest_id: None,
527                claim_version_id: Some(ClaimVersionId::new("claim-v1")),
528                as_of_recorded_at: None,
529            },
530            TraceCtx::generate(),
531            AttemptId::new("attempt-1"),
532            "2026-03-12T00:00:00Z",
533            false,
534            false,
535        );
536        let plan = CheckPlan::new(
537            case.case_id.clone(),
538            CheckMethod::ExactBoundedOracle,
539            vec!["oracle".into()],
540            PromotionClass::P1,
541            ReversibilityClass::ReversibleScoped,
542            true,
543            false,
544            false,
545            "interp",
546            serde_json::json!({}),
547        );
548        let attempt = VerificationAttempt::completed(
549            case.case_id.clone(),
550            plan.plan_id.clone(),
551            case.attempt_id.clone(),
552            Some(stack_ids::TrialId::new("trial-1")),
553            VerificationAttemptState::Succeeded,
554            false,
555            false,
556            "2026-03-12T00:00:00Z",
557            "2026-03-12T00:00:01Z",
558            Some("supported".into()),
559        );
560        let receipt =
561            ControlReceipt::new_case_execution(&case, &plan, &attempt, true, serde_json::json!({}));
562        let replayed = interpret_repair_replay(&[
563            LedgerEntry::new(
564                case.case_id.clone(),
565                1,
566                LedgerEvent::CaseOpened { case: case.clone() },
567            ),
568            LedgerEntry::new(
569                case.case_id.clone(),
570                2,
571                LedgerEvent::PlanAdopted { plan: plan.clone() },
572            ),
573            LedgerEntry::new(
574                case.case_id.clone(),
575                3,
576                LedgerEvent::AttemptRecorded { attempt },
577            ),
578            LedgerEntry::new(
579                case.case_id.clone(),
580                4,
581                LedgerEvent::ReceiptAppended {
582                    receipt: Box::new(receipt),
583                },
584            ),
585            LedgerEntry::new(
586                case.case_id.clone(),
587                5,
588                LedgerEvent::CaseClosed {
589                    case_id: case.case_id.clone(),
590                    disposition: TerminalDisposition::EligibleForPromotion,
591                },
592            ),
593        ])
594        .unwrap();
595        assert_eq!(replayed.replayed.plan_count, 1);
596        assert_eq!(
597            replayed.replayed.terminal_disposition,
598            Some(TerminalDisposition::EligibleForPromotion)
599        );
600    }
601
602    #[test]
603    fn causal_workflow_reference_interpreter_is_advisory_only() {
604        let batch = transform_envelope_v3(&sample_v3_envelope()).unwrap();
605        let policy = CompilerPolicy {
606            policy_version: "interp".into(),
607            include_hyperedges: true,
608        };
609        let interpretation = interpret_causal_workflow(&batch, &policy, "claim-v1", 1);
610        assert!(interpretation.conservative_supported);
611        assert_eq!(interpretation.causal_refutation.target_node_id, "claim-v1");
612    }
613}