diff --git a/docs/ci/runtime_intelligence_gitlab_artifacts.md b/docs/ci/runtime_intelligence_gitlab_artifacts.md index fb1c3a3..7e3cb32 100644 --- a/docs/ci/runtime_intelligence_gitlab_artifacts.md +++ b/docs/ci/runtime_intelligence_gitlab_artifacts.md @@ -171,6 +171,7 @@ packaging runs. That marker set preserves `Runtime Intelligence Risk Summary`, `AIGuard runtime operation anomalies`, `AIGuard remote dispatch event summary`, `AIGuard remote event summary consistency`, +`Remote fallback starter evidence`, `AIGuard producer-lineage guard alignment`, and `Lab remains the final deployment decision owner.`. The smoke also includes the precomputed AIGuard @@ -180,7 +181,7 @@ EdgeEnv handoff summary and AIGuard deterministic evidence agree on producer-lineage guard-alignment run IDs. This keeps the cross-repo marker check file-based and does not make AIGuard a deployment decision owner. -The artifact gate is implemented by `scripts/check_runtime_intelligence_artifact_bundle.py`. It checks the generated Markdown / HTML report for the required Runtime Intelligence rows, including Lab ownership, EdgeEnv comparability, telemetry coverage-gap markers, Orchestrator operation feed context, Orchestrator task event rollup, Lab EdgeEnv preservation context, Orchestrator `operation_risk_summary` navigation context, AIGuard runtime operation anomalies, AIGuard `edgeenv_orchestrator_operation_risk_summary` evidence, AIGuard `edgeenv_orchestrator_task_event_rollup` evidence, remote dispatch starter event summary, `edgeenv_orchestrator_producer_lineage`, `runtime_history_seed_run_config_traceability`, `remote_execution_recovered_by_fallback`, and triggered deployment review rules. +The artifact gate is implemented by `scripts/check_runtime_intelligence_artifact_bundle.py`. It checks the generated Markdown / HTML report for the required Runtime Intelligence rows, including Lab ownership, EdgeEnv comparability, telemetry coverage-gap markers, Orchestrator operation feed context, Orchestrator task event rollup, Lab EdgeEnv preservation context, Orchestrator `operation_risk_summary` navigation context, AIGuard runtime operation anomalies, AIGuard `edgeenv_orchestrator_operation_risk_summary` evidence, AIGuard `edgeenv_orchestrator_task_event_rollup` evidence, remote dispatch starter event summary, `Remote fallback starter evidence`, `edgeenv_orchestrator_producer_lineage`, `runtime_history_seed_run_config_traceability`, `remote_execution_recovered_by_fallback`, and triggered deployment review rules. The CI artifact gate is implemented by `scripts/check_runtime_intelligence_ci_artifacts.py`. It runs in the deployment-risk stage and verifies that the collected optional GitLab artifacts include the manifest gate summary, AIGuard handoff alignment artifact, report gate summary, Runtime Intelligence Risk Summary report, portfolio demo status, and the validated contract markers from the bundle manifest gate. This keeps the final CI gate file-based and deterministic without turning GitLab into a runtime control plane. The same CI artifact gate also checks the copied diff --git a/docs/portfolio/edgeenv_runtime_regression_lab_handoff.md b/docs/portfolio/edgeenv_runtime_regression_lab_handoff.md index 3559b79..69c4a94 100644 --- a/docs/portfolio/edgeenv_runtime_regression_lab_handoff.md +++ b/docs/portfolio/edgeenv_runtime_regression_lab_handoff.md @@ -175,7 +175,7 @@ Expected Lab behavior: - The same gate requires EdgeEnv-preserved Orchestrator producer markers to carry `source_repository=InferEdgeOrchestrator`, `artifact_role=orchestrator-supplemental-operation-context`, and `producer_contract=inferedge-orchestrator-edgeenv-runtime-telemetry-feed-v1`. - When EdgeEnv preservation context is present, Lab renders `Lab EdgeEnv preservation context` with `lab_report_preservation_context_present=True`, `lab_preservation=present`, and `lab_context=present` so the Runtime Intelligence report gate and entrypoint evidence index use the same Lab-owned marker vocabulary. - When an EdgeEnv handoff manifest is provided, the bundle gate requires EdgeEnv-produced file keys, external AIGuard file keys, source repository mapping, artifact roles, producer contracts, and boundary flags to match Lab's Runtime Intelligence bundle contract. -- The same manifest gate requires `expected_report_markers` to preserve these exact Lab-owned report markers: `Runtime Intelligence Risk Summary`, `Orchestrator operation feed context`, `Orchestrator task event rollup`, `Lab EdgeEnv preservation context`, `AIGuard task event rollup evidence`, `AIGuard runtime operation anomalies`, `AIGuard remote dispatch event summary`, `AIGuard remote event summary consistency`, `AIGuard producer-lineage guard alignment`, and `Lab remains the final deployment decision owner.`. +- The same manifest gate requires `expected_report_markers` to preserve these exact Lab-owned report markers: `Runtime Intelligence Risk Summary`, `Orchestrator operation feed context`, `Orchestrator task event rollup`, `Lab EdgeEnv preservation context`, `AIGuard task event rollup evidence`, `AIGuard runtime operation anomalies`, `AIGuard remote dispatch event summary`, `AIGuard remote event summary consistency`, `Remote fallback starter evidence`, `AIGuard producer-lineage guard alignment`, and `Lab remains the final deployment decision owner.`. - The same handoff gate verifies that the referenced `runtime_telemetry_history` artifact exists and preserves EdgeEnv history schema, telemetry coverage, and Runtime history seed ownership markers. - The same handoff gate verifies that missing telemetry entries remain evidence gaps while preserving Orchestrator producer markers, owner boundary flags, and EdgeEnv mapping hints when Orchestrator context is attached. - The same handoff gate validates `edgeenv_report_summary.producer_lineage_guard_alignment_run_ids` against the preserved EdgeEnv regression context so the Orchestrator-declared `edgeenv_orchestrator_producer_lineage` marker cannot disappear between EdgeEnv producer output and Lab bundle ingestion. diff --git a/examples/runtime_intelligence_chain/aiguard_edgeenv_handoff_alignment.json b/examples/runtime_intelligence_chain/aiguard_edgeenv_handoff_alignment.json index 0e1430c..893e2a5 100644 --- a/examples/runtime_intelligence_chain/aiguard_edgeenv_handoff_alignment.json +++ b/examples/runtime_intelligence_chain/aiguard_edgeenv_handoff_alignment.json @@ -8,7 +8,7 @@ "guard_analysis_schema_version": "inferedge-aiguard-diagnosis-v1", "required_evidence_type_count": 7, "guard_evidence_type_count": 8, - "lab_expected_report_marker_count": 10, + "lab_expected_report_marker_count": 11, "lab_expected_report_markers": [ "Runtime Intelligence Risk Summary", "Orchestrator operation feed context", @@ -18,6 +18,7 @@ "AIGuard runtime operation anomalies", "AIGuard remote dispatch event summary", "AIGuard remote event summary consistency", + "Remote fallback starter evidence", "AIGuard producer-lineage guard alignment", "Lab remains the final deployment decision owner." ], diff --git a/examples/runtime_intelligence_chain/aiguard_edgeenv_handoff_alignment.md b/examples/runtime_intelligence_chain/aiguard_edgeenv_handoff_alignment.md index 4cc2b6f..e20bef9 100644 --- a/examples/runtime_intelligence_chain/aiguard_edgeenv_handoff_alignment.md +++ b/examples/runtime_intelligence_chain/aiguard_edgeenv_handoff_alignment.md @@ -4,7 +4,7 @@ - recommendation: alignment_satisfied - decision_owner: lab - diagnosis_owner: aiguard -- lab_expected_report_markers: Runtime Intelligence Risk Summary, Orchestrator operation feed context, Orchestrator task event rollup, Lab EdgeEnv preservation context, AIGuard task event rollup evidence, AIGuard runtime operation anomalies, AIGuard remote dispatch event summary, AIGuard remote event summary consistency, AIGuard producer-lineage guard alignment, Lab remains the final deployment decision owner. +- lab_expected_report_markers: Runtime Intelligence Risk Summary, Orchestrator operation feed context, Orchestrator task event rollup, Lab EdgeEnv preservation context, AIGuard task event rollup evidence, AIGuard runtime operation anomalies, AIGuard remote dispatch event summary, AIGuard remote event summary consistency, Remote fallback starter evidence, AIGuard producer-lineage guard alignment, Lab remains the final deployment decision owner. - report_marker_context_role: lab_report_contract_context - aiguard_validates_expected_report_markers: False - required_evidence_types: runtime_telemetry_context_coverage, edgeenv_orchestrator_producer_lineage, edgeenv_orchestrator_task_event_rollup, runtime_history_seed_run_config_traceability, runtime_queue_overload, runtime_thermal_instability, remote_execution_recovered_by_fallback diff --git a/examples/runtime_intelligence_chain/bundle_manifest.json b/examples/runtime_intelligence_chain/bundle_manifest.json index 69596c8..6647a9b 100644 --- a/examples/runtime_intelligence_chain/bundle_manifest.json +++ b/examples/runtime_intelligence_chain/bundle_manifest.json @@ -54,6 +54,7 @@ "AIGuard runtime operation anomalies", "AIGuard remote dispatch event summary", "AIGuard remote event summary consistency", + "Remote fallback starter evidence", "AIGuard producer-lineage guard alignment", "Lab remains the final deployment decision owner." ] diff --git a/examples/runtime_intelligence_chain/edgeenv_lab_handoff_manifest.json b/examples/runtime_intelligence_chain/edgeenv_lab_handoff_manifest.json index 5b39575..d8291c0 100644 --- a/examples/runtime_intelligence_chain/edgeenv_lab_handoff_manifest.json +++ b/examples/runtime_intelligence_chain/edgeenv_lab_handoff_manifest.json @@ -75,6 +75,7 @@ "AIGuard runtime operation anomalies", "AIGuard remote dispatch event summary", "AIGuard remote event summary consistency", + "Remote fallback starter evidence", "AIGuard producer-lineage guard alignment", "Lab remains the final deployment decision owner." ], diff --git a/inferedgelab/report/runtime_intelligence.py b/inferedgelab/report/runtime_intelligence.py index 24dfc39..a3cb257 100644 --- a/inferedgelab/report/runtime_intelligence.py +++ b/inferedgelab/report/runtime_intelligence.py @@ -36,6 +36,7 @@ "remote_execution_starter_success", REMOTE_RUNTIME_EVENT_SUMMARY_MISMATCH_EVIDENCE_TYPE, } +REMOTE_FALLBACK_LAB_CONTEXT_LABEL = "Remote fallback starter evidence" RUN_CONFIG_MARKER_FIELDS = ( "input_mode", @@ -825,6 +826,19 @@ def _append_aiguard_remote_dispatch_rows( ) ) + fallback_context_label = _remote_fallback_lab_context_label( + remote_dispatch, + evidence_items, + ) + if fallback_context_label: + rows.append( + ( + REMOTE_FALLBACK_LAB_CONTEXT_LABEL, + fallback_context_label, + "Lab-facing remote fallback label matches the entrypoint registry while remaining starter-only review context.", + ) + ) + evidence_types = sorted( { str(item.get("type")) @@ -954,6 +968,38 @@ def _remote_runtime_event_boundary_label(remote_dispatch: dict[str, Any]) -> str return ", ".join(str(part) for part in parts) +def _remote_fallback_lab_context_label( + remote_dispatch: dict[str, Any], + evidence_items: list[dict[str, Any]], +) -> str: + evidence_type = "remote_execution_recovered_by_fallback" + evidence_types = { + str(item.get("type")) + for item in evidence_items + if item.get("type") in REMOTE_DISPATCH_EVIDENCE_TYPES + } + event_summary = remote_dispatch.get("remote_runtime_event_summary") + if not isinstance(event_summary, dict): + event_summary = {} + + fallback_recovered = _first_present( + remote_dispatch.get("remote_runtime_event_summary_fallback_recovered"), + event_summary.get("fallback_recovered"), + remote_dispatch.get("fallback_recovered"), + ) + fallback_final_status = _first_present( + remote_dispatch.get("fallback_final_status"), + event_summary.get("final_status"), + ) + if ( + evidence_type in evidence_types + or fallback_recovered is True + or str(fallback_final_status).lower() == "succeeded" + ): + return f"lab={REMOTE_FALLBACK_LAB_CONTEXT_LABEL}; evidence={evidence_type}" + return "" + + def _first_present(*values: Any) -> Any: for value in values: if value is not None: diff --git a/scripts/check_runtime_intelligence_artifact_bundle.py b/scripts/check_runtime_intelligence_artifact_bundle.py index ffb87ab..3d77b82 100644 --- a/scripts/check_runtime_intelligence_artifact_bundle.py +++ b/scripts/check_runtime_intelligence_artifact_bundle.py @@ -70,6 +70,11 @@ "production_remote_execution=False |" ), "aiguard_remote_dispatch_evidence": "remote_execution_recovered_by_fallback", + "remote_fallback_lab_context": ( + "| Remote fallback starter evidence | " + "lab=Remote fallback starter evidence; " + "evidence=remote_execution_recovered_by_fallback |" + ), "aiguard_orchestrator_handoff": ( "| AIGuard Orchestrator context handoff | feeds=2.0, candidate |" ), @@ -124,6 +129,8 @@ "production_remote_execution=False" ), "aiguard_remote_dispatch_evidence": "remote_execution_recovered_by_fallback", + "remote_fallback_lab_context": "Remote fallback starter evidence", + "remote_fallback_lab_context_marker": "lab=Remote fallback starter evidence", "aiguard_orchestrator_handoff": "AIGuard Orchestrator context handoff", "orchestrator_operation_risk_summary": "Orchestrator operation risk summary", "orchestrator_task_event_rollup": "Orchestrator task event rollup", diff --git a/scripts/check_runtime_intelligence_bundle_manifest.py b/scripts/check_runtime_intelligence_bundle_manifest.py index b3c5e55..53b8de6 100644 --- a/scripts/check_runtime_intelligence_bundle_manifest.py +++ b/scripts/check_runtime_intelligence_bundle_manifest.py @@ -131,6 +131,7 @@ "AIGuard runtime operation anomalies", "AIGuard remote dispatch event summary", "AIGuard remote event summary consistency", + "Remote fallback starter evidence", "AIGuard producer-lineage guard alignment", "Lab remains the final deployment decision owner.", } diff --git a/scripts/check_runtime_intelligence_ci_artifacts.py b/scripts/check_runtime_intelligence_ci_artifacts.py index 630f3b4..f1f09e0 100644 --- a/scripts/check_runtime_intelligence_ci_artifacts.py +++ b/scripts/check_runtime_intelligence_ci_artifacts.py @@ -74,6 +74,7 @@ "AIGuard runtime operation anomalies", "AIGuard remote dispatch event summary", "AIGuard remote event summary consistency", + "Remote fallback starter evidence", "AIGuard producer-lineage guard alignment", "Lab remains the final deployment decision owner.", ) @@ -164,6 +165,8 @@ def _validate_runtime_report(path: Path, errors: list[str]) -> None: "runtime_history_seed_run_config_traceability", "AIGuard remote dispatch event summary", "remote_execution_recovered_by_fallback", + "Remote fallback starter evidence", + "lab=Remote fallback starter evidence", "runtime_telemetry_field_gap", "Inspect telemetry coverage missing fields", "guard_warning_review", @@ -287,6 +290,7 @@ def _validate_aiguard_handoff_alignment( "AIGuard task event rollup evidence, " "AIGuard runtime operation anomalies, AIGuard remote dispatch event summary, " "AIGuard remote event summary consistency, " + "Remote fallback starter evidence, " "AIGuard producer-lineage guard alignment, " "Lab remains the final deployment decision owner.", "report_marker_context_role: lab_report_contract_context", diff --git a/tests/test_report_generators.py b/tests/test_report_generators.py index 6029cd4..1dd5ea1 100644 --- a/tests/test_report_generators.py +++ b/tests/test_report_generators.py @@ -923,6 +923,11 @@ def test_generate_compare_markdown_summarizes_remote_runtime_event_summary(): "| AIGuard remote dispatch evidence | " "remote_execution_recovered_by_fallback |" ) in text + assert ( + "| Remote fallback starter evidence | " + "lab=Remote fallback starter evidence; " + "evidence=remote_execution_recovered_by_fallback |" + ) in text assert "Lab remains the final decision owner" in text @@ -1177,6 +1182,8 @@ def test_generate_compare_html_summarizes_remote_runtime_event_summary(): assert "remote dispatch starter evidence only" in html assert "production_remote_execution=False" in html assert "remote_execution_recovered_by_fallback" in html + assert "Remote fallback starter evidence" in html + assert "lab=Remote fallback starter evidence" in html assert "Lab remains the final decision owner" in html diff --git a/tests/test_runtime_intelligence_ci_template.py b/tests/test_runtime_intelligence_ci_template.py index 0f41b4c..80ad3e3 100644 --- a/tests/test_runtime_intelligence_ci_template.py +++ b/tests/test_runtime_intelligence_ci_template.py @@ -109,6 +109,8 @@ def test_runtime_intelligence_ci_artifact_gate_passes_for_expected_outputs(tmp_p "runtime_history_seed_run_config_traceability", "AIGuard remote dispatch event summary", "remote_execution_recovered_by_fallback", + "Remote fallback starter evidence", + "lab=Remote fallback starter evidence", "runtime_telemetry_field_gap", "Inspect telemetry coverage missing fields", "guard_warning_review", @@ -172,7 +174,7 @@ def test_runtime_intelligence_ci_artifact_gate_passes_for_expected_outputs(tmp_p (report_dir / "aiguard_edgeenv_handoff_alignment.json").write_text( '{"schema_version":"inferedge-aiguard-edgeenv-handoff-alignment-v1",' '"status":"passed","decision_owner":"lab","diagnosis_owner":"aiguard",' - '"lab_expected_report_marker_count":10,' + '"lab_expected_report_marker_count":11,' '"lab_expected_report_markers":[' '"Runtime Intelligence Risk Summary",' '"Orchestrator operation feed context",' @@ -182,6 +184,7 @@ def test_runtime_intelligence_ci_artifact_gate_passes_for_expected_outputs(tmp_p '"AIGuard runtime operation anomalies",' '"AIGuard remote dispatch event summary",' '"AIGuard remote event summary consistency",' + '"Remote fallback starter evidence",' '"AIGuard producer-lineage guard alignment",' '"Lab remains the final deployment decision owner."],' '"lab_report_marker_owner":"lab",' @@ -200,7 +203,7 @@ def test_runtime_intelligence_ci_artifact_gate_passes_for_expected_outputs(tmp_p "- status: passed", "- decision_owner: lab", "- diagnosis_owner: aiguard", - "- lab_expected_report_markers: Runtime Intelligence Risk Summary, Orchestrator operation feed context, Orchestrator task event rollup, Lab EdgeEnv preservation context, AIGuard task event rollup evidence, AIGuard runtime operation anomalies, AIGuard remote dispatch event summary, AIGuard remote event summary consistency, AIGuard producer-lineage guard alignment, Lab remains the final deployment decision owner.", + "- lab_expected_report_markers: Runtime Intelligence Risk Summary, Orchestrator operation feed context, Orchestrator task event rollup, Lab EdgeEnv preservation context, AIGuard task event rollup evidence, AIGuard runtime operation anomalies, AIGuard remote dispatch event summary, AIGuard remote event summary consistency, Remote fallback starter evidence, AIGuard producer-lineage guard alignment, Lab remains the final deployment decision owner.", "- report_marker_context_role: lab_report_contract_context", "- aiguard_validates_expected_report_markers: False", "- handoff_producer_lineage_guard_alignment_run_ids: edgeenv-smoke-candidate, edgeenv-smoke-missing", @@ -307,6 +310,8 @@ def test_runtime_intelligence_ci_artifact_gate_fails_for_missing_lab_marker_cont "runtime_history_seed_run_config_traceability", "AIGuard remote dispatch event summary", "remote_execution_recovered_by_fallback", + "Remote fallback starter evidence", + "lab=Remote fallback starter evidence", "runtime_telemetry_field_gap", "Inspect telemetry coverage missing fields", "guard_warning_review", @@ -445,6 +450,8 @@ def test_runtime_intelligence_ci_artifact_gate_fails_for_missing_contract_marker "runtime_history_seed_run_config_traceability", "AIGuard remote dispatch event summary", "remote_execution_recovered_by_fallback", + "Remote fallback starter evidence", + "lab=Remote fallback starter evidence", "runtime_telemetry_field_gap", "Inspect telemetry coverage missing fields", "guard_warning_review", @@ -524,6 +531,8 @@ def test_runtime_intelligence_ci_artifact_gate_fails_for_missing_coverage_gap_ma "runtime_history_seed_run_config_traceability", "AIGuard remote dispatch event summary", "remote_execution_recovered_by_fallback", + "Remote fallback starter evidence", + "lab=Remote fallback starter evidence", "guard_warning_review", "edgeenv_runtime_regression_review", ] @@ -588,6 +597,8 @@ def test_runtime_intelligence_ci_artifact_gate_fails_for_failed_deployment_risk( "runtime_history_seed_run_config_traceability", "AIGuard remote dispatch event summary", "remote_execution_recovered_by_fallback", + "Remote fallback starter evidence", + "lab=Remote fallback starter evidence", "runtime_telemetry_field_gap", "Inspect telemetry coverage missing fields", "guard_warning_review", @@ -651,7 +662,7 @@ def test_runtime_intelligence_ci_artifact_gate_fails_for_failed_deployment_risk( (report_dir / "aiguard_edgeenv_handoff_alignment.json").write_text( '{"schema_version":"inferedge-aiguard-edgeenv-handoff-alignment-v1",' '"status":"passed","decision_owner":"lab","diagnosis_owner":"aiguard",' - '"lab_expected_report_marker_count":10,' + '"lab_expected_report_marker_count":11,' '"lab_expected_report_markers":[' '"Runtime Intelligence Risk Summary",' '"Orchestrator operation feed context",' @@ -661,6 +672,7 @@ def test_runtime_intelligence_ci_artifact_gate_fails_for_failed_deployment_risk( '"AIGuard runtime operation anomalies",' '"AIGuard remote dispatch event summary",' '"AIGuard remote event summary consistency",' + '"Remote fallback starter evidence",' '"AIGuard producer-lineage guard alignment",' '"Lab remains the final deployment decision owner."],' '"lab_report_marker_owner":"lab",' @@ -679,7 +691,7 @@ def test_runtime_intelligence_ci_artifact_gate_fails_for_failed_deployment_risk( "- status: passed", "- decision_owner: lab", "- diagnosis_owner: aiguard", - "- lab_expected_report_markers: Runtime Intelligence Risk Summary, Orchestrator operation feed context, Orchestrator task event rollup, Lab EdgeEnv preservation context, AIGuard task event rollup evidence, AIGuard runtime operation anomalies, AIGuard remote dispatch event summary, AIGuard remote event summary consistency, AIGuard producer-lineage guard alignment, Lab remains the final deployment decision owner.", + "- lab_expected_report_markers: Runtime Intelligence Risk Summary, Orchestrator operation feed context, Orchestrator task event rollup, Lab EdgeEnv preservation context, AIGuard task event rollup evidence, AIGuard runtime operation anomalies, AIGuard remote dispatch event summary, AIGuard remote event summary consistency, Remote fallback starter evidence, AIGuard producer-lineage guard alignment, Lab remains the final deployment decision owner.", "- report_marker_context_role: lab_report_contract_context", "- aiguard_validates_expected_report_markers: False", "- handoff_producer_lineage_guard_alignment_run_ids: edgeenv-smoke-candidate, edgeenv-smoke-missing", diff --git a/tests/test_runtime_intelligence_evidence_chain_smoke.py b/tests/test_runtime_intelligence_evidence_chain_smoke.py index 2ca1a9c..0bd6ae4 100644 --- a/tests/test_runtime_intelligence_evidence_chain_smoke.py +++ b/tests/test_runtime_intelligence_evidence_chain_smoke.py @@ -435,6 +435,11 @@ def test_runtime_intelligence_chain_smoke_ingests_precomputed_guard_artifact(): "| AIGuard remote dispatch evidence | " "remote_execution_recovered_by_fallback |" ) in bundle["markdown"] + assert ( + "| Remote fallback starter evidence | " + "lab=Remote fallback starter evidence; " + "evidence=remote_execution_recovered_by_fallback |" + ) in bundle["markdown"] assert "Lab remains the final deployment decision owner" in bundle["markdown"] assert all( "raw_context" in item @@ -508,6 +513,8 @@ def test_compare_cmd_runtime_intelligence_chain_writes_markdown_and_html( assert "events=3, final=succeeded, fallback_recovered=True" in markdown assert "AIGuard remote event summary consistency" in markdown assert "remote_execution_recovered_by_fallback" in markdown + assert "Remote fallback starter evidence" in markdown + assert "lab=Remote fallback starter evidence" in markdown assert ( "baseline/candidate=shape=1x640x640, input_mode=dummy, " "input_preprocess=none, power_mode=unknown, jetson_clocks=unknown, " @@ -547,3 +554,5 @@ def test_compare_cmd_runtime_intelligence_chain_writes_markdown_and_html( assert "events=3, final=succeeded, fallback_recovered=True" in html assert "AIGuard remote event summary consistency" in html assert "remote_execution_recovered_by_fallback" in html + assert "Remote fallback starter evidence" in html + assert "lab=Remote fallback starter evidence" in html