From c47bfe5c56467b5a0caa55bb76f842985e4ddf0b Mon Sep 17 00:00:00 2001 From: hyeokjun32 Date: Fri, 12 Jun 2026 10:28:21 +0900 Subject: [PATCH] Add Runtime Intelligence source traceability smoke --- README.ko.md | 4 +- README.md | 2 +- ci/gitlab/runtime-intelligence-artifacts.yml | 3 + .../runtime_intelligence_gitlab_artifacts.md | 4 + .../edgeenv_runtime_regression_lab_handoff.md | 4 +- ...check_runtime_intelligence_ci_artifacts.py | 37 +++ ...untime_intelligence_source_traceability.py | 284 ++++++++++++++++++ scripts/smoke_runtime_intelligence_chain.sh | 6 + .../test_runtime_intelligence_ci_template.py | 59 ++++ .../test_runtime_intelligence_smoke_script.py | 42 +++ ...untime_intelligence_source_traceability.py | 86 ++++++ 11 files changed, 528 insertions(+), 3 deletions(-) create mode 100644 scripts/check_runtime_intelligence_source_traceability.py create mode 100644 tests/test_runtime_intelligence_source_traceability.py diff --git a/README.ko.md b/README.ko.md index 1ac4580..beb18e7 100644 --- a/README.ko.md +++ b/README.ko.md @@ -278,7 +278,9 @@ bash scripts/smoke_runtime_intelligence_chain.sh \ 또한 `optional_aiguard_source_traceability`가 있으면 Lab bundle gate가 `read_only_optional_source_traceability` source artifact path와 AIGuard 재생성 명령을 검증하되, EdgeEnv가 `guard_analysis`를 생성한다는 의미로 -해석하지 않습니다. +해석하지 않습니다. 이어서 source traceability gate가 EdgeEnv mirror와 +AIGuard optional-present fixture가 같은 source artifact와 명령을 가리키는지 +확인합니다. EdgeEnv나 AIGuard가 Lab의 final deployment decision을 대체하지 않습니다. ## 현재 범위와 future work diff --git a/README.md b/README.md index 348dee9..c7f7fee 100644 --- a/README.md +++ b/README.md @@ -581,7 +581,7 @@ bash scripts/smoke_runtime_intelligence_chain.sh \ --output-dir reports/runtime_intelligence_chain ``` -The smoke gates the EdgeEnv handoff history fixture for preserved device-local Orchestrator `candidate_context.producer` lineage and checks that EdgeEnv-declared external AIGuard evidence requirements are satisfied by the bundled `guard_analysis`. It also carries a precomputed AIGuard handoff-alignment artifact so the EdgeEnv handoff summary and AIGuard producer-lineage raw context agree on the same `producer_lineage_guard_alignment_run_ids`. When the handoff declares `optional_aiguard_evidence_types`, the copied AIGuard alignment artifacts preserve them as `read_only_optional_guard_context` and exercise both missing-optional and present-optional paths without turning optional evidence into required evidence. When it also declares `optional_aiguard_source_traceability`, the bundle gate validates the `read_only_optional_source_traceability` source artifact path and AIGuard reproduction command without making EdgeEnv produce `guard_analysis`. This is an artifact integrity check only; EdgeEnv still owns comparability/regression evidence, AIGuard remains an optional deterministic evidence provider, and Lab still owns the deployment decision. +The smoke gates the EdgeEnv handoff history fixture for preserved device-local Orchestrator `candidate_context.producer` lineage and checks that EdgeEnv-declared external AIGuard evidence requirements are satisfied by the bundled `guard_analysis`. It also carries a precomputed AIGuard handoff-alignment artifact so the EdgeEnv handoff summary and AIGuard producer-lineage raw context agree on the same `producer_lineage_guard_alignment_run_ids`. When the handoff declares `optional_aiguard_evidence_types`, the copied AIGuard alignment artifacts preserve them as `read_only_optional_guard_context` and exercise both missing-optional and present-optional paths without turning optional evidence into required evidence. When it also declares `optional_aiguard_source_traceability`, the bundle gate validates the `read_only_optional_source_traceability` source artifact path and AIGuard reproduction command without making EdgeEnv produce `guard_analysis`; the source traceability gate then checks that the EdgeEnv mirror and AIGuard optional-present fixture reference the same source artifact and command. This is an artifact integrity check only; EdgeEnv still owns comparability/regression evidence, AIGuard remains an optional deterministic evidence provider, and Lab still owns the deployment decision. The committed handoff smoke is documented in [docs/portfolio/edgeenv_runtime_regression_lab_handoff.md](docs/portfolio/edgeenv_runtime_regression_lab_handoff.md) diff --git a/ci/gitlab/runtime-intelligence-artifacts.yml b/ci/gitlab/runtime-intelligence-artifacts.yml index 0227165..0ea132b 100644 --- a/ci/gitlab/runtime-intelligence-artifacts.yml +++ b/ci/gitlab/runtime-intelligence-artifacts.yml @@ -121,6 +121,9 @@ inferedge:deployment-risk-gate: - "$INFEREDGE_REPORT_DIR/runtime_anomaly_gate_summary.md" - "$INFEREDGE_REPORT_DIR/aiguard_edgeenv_handoff_alignment.json" - "$INFEREDGE_REPORT_DIR/aiguard_edgeenv_handoff_alignment.md" + - "$INFEREDGE_REPORT_DIR/aiguard_edgeenv_handoff_alignment_optional_present.json" + - "$INFEREDGE_REPORT_DIR/aiguard_edgeenv_handoff_alignment_optional_present.md" + - "$INFEREDGE_REPORT_DIR/runtime_intelligence_source_traceability_summary.md" - "$INFEREDGE_REPORT_DIR/runtime_intelligence_bundle_manifest_gate_summary.md" - "$INFEREDGE_REPORT_DIR/portfolio_demo_check.json" - "$INFEREDGE_REPORT_DIR/portfolio_demo_check.md" diff --git a/docs/ci/runtime_intelligence_gitlab_artifacts.md b/docs/ci/runtime_intelligence_gitlab_artifacts.md index d3ee3d9..f94268f 100644 --- a/docs/ci/runtime_intelligence_gitlab_artifacts.md +++ b/docs/ci/runtime_intelligence_gitlab_artifacts.md @@ -63,6 +63,7 @@ Expected artifacts are intentionally file-based and local-first: - deterministic Runtime Intelligence summary Markdown / HTML with precomputed AIGuard runtime operation evidence - remote dispatch starter runtime event summary rows derived from precomputed AIGuard evidence - AIGuard EdgeEnv handoff alignment JSON / Markdown summary +- Runtime Intelligence source traceability summary - Runtime Intelligence artifact gate summary - portfolio demo check JSON / Markdown - deployment risk summary JSON @@ -248,6 +249,9 @@ The final CI summary also repeats `Validated Review Path`, the `review_path` marker, the readable fast-path marker, and the artifact gate summary reference marker, so reviewers can follow the same README -> Lab report -> gate-summary reading order from the deployment-risk artifact. +It also repeats `Validated Source Traceability`, confirming that the EdgeEnv +handoff mirror and AIGuard optional-present alignment fixture reference the +same optional stale-drop source artifact and reproduction command. The same CI artifact gate also checks the copied `aiguard_edgeenv_handoff_alignment.json/.md` for Lab report marker context: `lab_expected_report_markers` must match the Lab-owned Runtime Intelligence diff --git a/docs/portfolio/edgeenv_runtime_regression_lab_handoff.md b/docs/portfolio/edgeenv_runtime_regression_lab_handoff.md index 8715a2c..6621580 100644 --- a/docs/portfolio/edgeenv_runtime_regression_lab_handoff.md +++ b/docs/portfolio/edgeenv_runtime_regression_lab_handoff.md @@ -156,7 +156,9 @@ This second smoke uses committed lightweight artifacts to represent the cross-re validates the `read_only_optional_source_traceability` source artifact path and AIGuard reproduction command as read-only metadata. This links the EdgeEnv handoff to the AIGuard optional-present full-evidence fixture without - making EdgeEnv produce `guard_analysis`. + making EdgeEnv produce `guard_analysis`. The source traceability gate also + checks that the EdgeEnv mirror and AIGuard optional-present alignment fixture + reference the same source artifact and command. - `examples/runtime_intelligence_chain/runtime_telemetry_history.json` is the EdgeEnv producer-side telemetry history artifact referenced by the handoff manifest. It includes a missing-telemetry run as an evidence gap and preserves Orchestrator context on that entry without turning Orchestrator into a regression or deployment decision owner. - Orchestrator context is preserved inside the EdgeEnv regression artifact as `orchestrator_operation_context`. - AIGuard deterministic queue/thermal and task-event rollup evidence is passed as a precomputed `guard_analysis` artifact that mirrors the AIGuard producer-side diagnosis v1 evidence shape. diff --git a/scripts/check_runtime_intelligence_ci_artifacts.py b/scripts/check_runtime_intelligence_ci_artifacts.py index 5175128..82d0015 100644 --- a/scripts/check_runtime_intelligence_ci_artifacts.py +++ b/scripts/check_runtime_intelligence_ci_artifacts.py @@ -17,6 +17,7 @@ REQUIRED_SUMMARY_ARTIFACTS = { "aiguard_edgeenv_handoff_alignment.md", "aiguard_edgeenv_handoff_alignment_optional_present.md", + "runtime_intelligence_source_traceability_summary.md", "runtime_intelligence_bundle_manifest_gate_summary.md", "runtime_anomaly_gate_summary.md", } @@ -163,6 +164,16 @@ "aiguard_optional_present_reproduction_command: " f"{REQUIRED_AIGUARD_OPTIONAL_PRESENT_REPRODUCTION_COMMAND_MARKER}", ) +REQUIRED_SOURCE_TRACEABILITY_SUMMARY_MARKERS = ( + "## Validated Source Traceability", + "source_traceability_alignment: EdgeEnv handoff and AIGuard optional-present fixture match", + "edgeenv_optional_source_traceability: read_only_optional_source_traceability preserved", + "aiguard_optional_present_source_artifact: " + f"{REQUIRED_AIGUARD_OPTIONAL_PRESENT_SOURCE_ARTIFACT_MARKER}", + "aiguard_optional_present_reproduction_command: " + f"{REQUIRED_AIGUARD_OPTIONAL_PRESENT_REPRODUCTION_COMMAND_MARKER}", + "ownership: edgeenv_does_not_generate_guard_analysis=true, lab_is_final_decision_owner=true", +) REQUIRED_DURATION_TRACEABILITY_SUMMARY_MARKERS = ( "## Validated Duration Traceability", "duration_handoff_alignment: EdgeEnv/AIGuard report context preserved", @@ -268,6 +279,20 @@ def _validate_bundle_manifest_gate_summary(path: Path, errors: list[str]) -> Non ) +def _validate_source_traceability_summary(path: Path, errors: list[str]) -> None: + label = "Runtime Intelligence source traceability summary" + text = _read_text(path, errors, label) + if not text: + return + _record("- Status: passed" in text, errors, f"{label} must have passed status") + for marker in REQUIRED_SOURCE_TRACEABILITY_SUMMARY_MARKERS: + _record( + marker in text, + errors, + f"{label} missing source traceability marker: {marker}", + ) + + def _validate_runtime_report(path: Path, errors: list[str]) -> None: text = _read_text(path, errors, "Runtime Intelligence Markdown report") if not text: @@ -597,6 +622,14 @@ def _write_summary(path: Path, report_dir: Path, errors: list[str]) -> None: if not marker.startswith("## ") ) lines.append("") + lines.append("## Validated Source Traceability") + lines.append("") + lines.extend( + f"- {marker}" + for marker in REQUIRED_SOURCE_TRACEABILITY_SUMMARY_MARKERS + if not marker.startswith("## ") + ) + lines.append("") path.parent.mkdir(parents=True, exist_ok=True) path.write_text("\n".join(lines), encoding="utf-8") @@ -611,6 +644,10 @@ def main(report_dir: str, summary_out: str = "") -> int: report_path / "runtime_intelligence_bundle_manifest_gate_summary.md", errors, ) + _validate_source_traceability_summary( + report_path / "runtime_intelligence_source_traceability_summary.md", + errors, + ) _validate_runtime_artifact_gate_summary( report_path / "runtime_anomaly_gate_summary.md", errors, diff --git a/scripts/check_runtime_intelligence_source_traceability.py b/scripts/check_runtime_intelligence_source_traceability.py new file mode 100644 index 0000000..6ee5a9a --- /dev/null +++ b/scripts/check_runtime_intelligence_source_traceability.py @@ -0,0 +1,284 @@ +from __future__ import annotations + +import argparse +import json +from pathlib import Path +from typing import Any + + +EXPECTED_HANDOFF_SCHEMA_VERSION = "edgeenv.runtime-intelligence-lab-handoff.v1" +EXPECTED_AIGUARD_ALIGNMENT_SCHEMA_VERSION = ( + "inferedge-aiguard-edgeenv-handoff-alignment-v1" +) +EXPECTED_EDGEENV_TRACEABILITY_CONTEXT_ROLE = ( + "read_only_optional_source_traceability" +) +EXPECTED_AIGUARD_SOURCE_ARTIFACT_MARKER = ( + "InferEdgeAIGuard/examples/runtime_intelligence/" + "aiguard_runtime_operation_guard_analysis_optional_stale_drop.json" +) +EXPECTED_AIGUARD_REPRODUCTION_COMMAND = [ + "python", + "-m", + "inferedge_aiguard.cli", + "build-runtime-intelligence-optional-stale-drop", + "--edgeenv-regression", + ( + "examples/runtime_intelligence/" + "edgeenv_runtime_regression_with_optional_stale_drop_context.json" + ), + "--remote-dispatch", + "examples/runtime_intelligence/remote_dispatch_fallback_recovered_result.json", + "--orchestration-summary", + "examples/runtime_intelligence/orchestrator_multi_workload_sustained_summary.json", + "--save-json", + ( + "examples/runtime_intelligence/" + "aiguard_runtime_operation_guard_analysis_optional_stale_drop.json" + ), +] +EXPECTED_AIGUARD_REPRODUCTION_COMMAND_MARKER = " ".join( + EXPECTED_AIGUARD_REPRODUCTION_COMMAND +) +EXPECTED_AIGUARD_SOURCE_ARTIFACT = { + "repository": "InferEdgeAIGuard", + "path": ( + "examples/runtime_intelligence/" + "aiguard_runtime_operation_guard_analysis_optional_stale_drop.json" + ), + "schema_version": "inferedge-aiguard-diagnosis-v1", + "role": "aiguard-optional-stale-drop-full-evidence-source", + "context_role": "read_only_cross_repo_traceability", + "reproduction_command": EXPECTED_AIGUARD_REPRODUCTION_COMMAND, +} +SUMMARY_MARKERS = ( + "source_traceability_alignment: EdgeEnv handoff and AIGuard optional-present fixture match", + "edgeenv_optional_source_traceability: read_only_optional_source_traceability preserved", + "aiguard_optional_present_source_artifact: " + f"{EXPECTED_AIGUARD_SOURCE_ARTIFACT_MARKER}", + "aiguard_optional_present_reproduction_command: " + f"{EXPECTED_AIGUARD_REPRODUCTION_COMMAND_MARKER}", + "ownership: edgeenv_does_not_generate_guard_analysis=true, lab_is_final_decision_owner=true", +) + + +def _record(condition: bool, errors: list[str], message: str) -> None: + if not condition: + errors.append(message) + + +def _load_json(path: Path, errors: list[str], label: str) -> dict[str, Any]: + try: + payload = json.loads(path.read_text(encoding="utf-8")) + except OSError as exc: + errors.append(f"{label} not found: {path}: {exc}") + return {} + except json.JSONDecodeError as exc: + errors.append(f"{label} is invalid JSON: {path}: {exc}") + return {} + if not isinstance(payload, dict): + errors.append(f"{label} must be a JSON object: {path}") + return {} + return payload + + +def _source_artifact_from_handoff( + handoff: dict[str, Any], + errors: list[str], +) -> dict[str, Any]: + _record( + handoff.get("schema_version") == EXPECTED_HANDOFF_SCHEMA_VERSION, + errors, + f"EdgeEnv handoff schema_version must be {EXPECTED_HANDOFF_SCHEMA_VERSION}", + ) + alignment = handoff.get("lab_bundle_alignment") + _record( + isinstance(alignment, dict), + errors, + "EdgeEnv handoff lab_bundle_alignment must be an object", + ) + if not isinstance(alignment, dict): + return {} + traceability = alignment.get("optional_aiguard_source_traceability") + _record( + isinstance(traceability, dict), + errors, + "EdgeEnv handoff lab_bundle_alignment.optional_aiguard_source_traceability " + "must be an object", + ) + if not isinstance(traceability, dict): + return {} + + _record( + traceability.get("context_role") + == EXPECTED_EDGEENV_TRACEABILITY_CONTEXT_ROLE, + errors, + "EdgeEnv optional source traceability context_role must be " + f"{EXPECTED_EDGEENV_TRACEABILITY_CONTEXT_ROLE}", + ) + _record( + traceability.get("edgeenv_does_not_generate_guard_analysis") is True, + errors, + "EdgeEnv optional source traceability must keep " + "edgeenv_does_not_generate_guard_analysis=true", + ) + _record( + traceability.get("lab_is_final_decision_owner") is True, + errors, + "EdgeEnv optional source traceability must keep " + "lab_is_final_decision_owner=true", + ) + source_artifact = traceability.get("optional_present_source_artifact") + _record( + isinstance(source_artifact, dict), + errors, + "EdgeEnv optional source traceability optional_present_source_artifact " + "must be an object", + ) + return source_artifact if isinstance(source_artifact, dict) else {} + + +def _source_artifact_from_aiguard_alignment( + alignment: dict[str, Any], + errors: list[str], +) -> dict[str, Any]: + _record( + alignment.get("schema_version") + == EXPECTED_AIGUARD_ALIGNMENT_SCHEMA_VERSION, + errors, + "AIGuard alignment schema_version must be " + f"{EXPECTED_AIGUARD_ALIGNMENT_SCHEMA_VERSION}", + ) + _record( + alignment.get("status") == "passed", + errors, + "AIGuard optional-present alignment status must be passed", + ) + _record( + alignment.get("decision_owner") == "lab", + errors, + "AIGuard optional-present alignment decision_owner must be lab", + ) + _record( + alignment.get("diagnosis_owner") == "aiguard", + errors, + "AIGuard optional-present alignment diagnosis_owner must be aiguard", + ) + _record( + alignment.get("aiguard_validates_optional_evidence_as_required") is False, + errors, + "AIGuard optional-present alignment must keep optional evidence " + "read-only", + ) + source_artifact = alignment.get("optional_present_source_artifact") + _record( + isinstance(source_artifact, dict), + errors, + "AIGuard optional-present alignment optional_present_source_artifact " + "must be an object", + ) + return source_artifact if isinstance(source_artifact, dict) else {} + + +def _validate_source_artifact( + source_artifact: dict[str, Any], + *, + label: str, + errors: list[str], +) -> None: + _record( + source_artifact == EXPECTED_AIGUARD_SOURCE_ARTIFACT, + errors, + f"{label} source artifact must match the Lab-known AIGuard optional " + "stale-drop source artifact", + ) + + +def _write_summary(path: Path, errors: list[str]) -> None: + lines = [ + "# Runtime Intelligence Source Traceability Gate", + "", + f"- Status: {'failed' if errors else 'passed'}", + f"- Error count: {len(errors)}", + "", + ] + if errors: + lines.append("## Errors") + lines.append("") + lines.extend(f"- {error}" for error in errors) + lines.append("") + else: + lines.append("## Validated Source Traceability") + lines.append("") + lines.extend(f"- {marker}" for marker in SUMMARY_MARKERS) + lines.append("") + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text("\n".join(lines), encoding="utf-8") + + +def main( + edgeenv_handoff: str, + aiguard_alignment: str, + summary_out: str = "", +) -> int: + errors: list[str] = [] + handoff = _load_json(Path(edgeenv_handoff), errors, "EdgeEnv handoff manifest") + alignment = _load_json( + Path(aiguard_alignment), + errors, + "AIGuard optional-present alignment", + ) + handoff_source_artifact = ( + _source_artifact_from_handoff(handoff, errors) if handoff else {} + ) + aiguard_source_artifact = ( + _source_artifact_from_aiguard_alignment(alignment, errors) + if alignment + else {} + ) + + if handoff_source_artifact: + _validate_source_artifact( + handoff_source_artifact, + label="EdgeEnv handoff", + errors=errors, + ) + if aiguard_source_artifact: + _validate_source_artifact( + aiguard_source_artifact, + label="AIGuard alignment", + errors=errors, + ) + if handoff_source_artifact and aiguard_source_artifact: + _record( + handoff_source_artifact == aiguard_source_artifact, + errors, + "EdgeEnv handoff and AIGuard optional-present alignment must " + "reference the same source artifact and reproduction command", + ) + + if summary_out: + _write_summary(Path(summary_out), errors) + return 2 if errors else 0 + + +def cli() -> int: + parser = argparse.ArgumentParser( + description=( + "Validate Runtime Intelligence optional source traceability between " + "EdgeEnv handoff metadata and AIGuard optional-present alignment." + ) + ) + parser.add_argument("--edgeenv-handoff", required=True) + parser.add_argument("--aiguard-alignment", required=True) + parser.add_argument("--summary-out", default="") + args = parser.parse_args() + return main( + edgeenv_handoff=args.edgeenv_handoff, + aiguard_alignment=args.aiguard_alignment, + summary_out=args.summary_out, + ) + + +if __name__ == "__main__": + raise SystemExit(cli()) diff --git a/scripts/smoke_runtime_intelligence_chain.sh b/scripts/smoke_runtime_intelligence_chain.sh index 432c83d..0321ed7 100755 --- a/scripts/smoke_runtime_intelligence_chain.sh +++ b/scripts/smoke_runtime_intelligence_chain.sh @@ -15,6 +15,7 @@ Usage: This smoke reproduces the local-first Runtime Intelligence artifact chain: bundle manifest gate -> AIGuard EdgeEnv handoff alignment gate fixture + -> EdgeEnv/AIGuard optional source traceability gate -> EdgeEnv regression report -> Runtime Intelligence report with precomputed AIGuard evidence -> report artifact gate @@ -76,6 +77,11 @@ cp examples/runtime_intelligence_chain/aiguard_edgeenv_handoff_alignment_optiona cp examples/runtime_intelligence_chain/aiguard_edgeenv_handoff_alignment_optional_present.md \ "$OUTPUT_DIR/aiguard_edgeenv_handoff_alignment_optional_present.md" +"${PYTHON_CMD[@]}" scripts/check_runtime_intelligence_source_traceability.py \ + --edgeenv-handoff examples/runtime_intelligence_chain/edgeenv_lab_handoff_manifest.json \ + --aiguard-alignment "$OUTPUT_DIR/aiguard_edgeenv_handoff_alignment_optional_present.json" \ + --summary-out "$OUTPUT_DIR/runtime_intelligence_source_traceability_summary.md" + "${LAB_CMD[@]}" compare \ examples/edgeenv_regression/lab_baseline_result.json \ examples/edgeenv_regression/lab_candidate_result.json \ diff --git a/tests/test_runtime_intelligence_ci_template.py b/tests/test_runtime_intelligence_ci_template.py index b924fba..840acad 100644 --- a/tests/test_runtime_intelligence_ci_template.py +++ b/tests/test_runtime_intelligence_ci_template.py @@ -29,6 +29,17 @@ "- review_path_artifact_gate_summary: artifact gate summary reference row validated", ] ) + "\n" +SOURCE_TRACEABILITY_SUMMARY = "\n".join( + [ + "- Status: passed", + "## Validated Source Traceability", + "- source_traceability_alignment: EdgeEnv handoff and AIGuard optional-present fixture match", + "- edgeenv_optional_source_traceability: read_only_optional_source_traceability preserved", + "- aiguard_optional_present_source_artifact: InferEdgeAIGuard/examples/runtime_intelligence/aiguard_runtime_operation_guard_analysis_optional_stale_drop.json", + "- aiguard_optional_present_reproduction_command: python -m inferedge_aiguard.cli build-runtime-intelligence-optional-stale-drop --edgeenv-regression examples/runtime_intelligence/edgeenv_runtime_regression_with_optional_stale_drop_context.json --remote-dispatch examples/runtime_intelligence/remote_dispatch_fallback_recovered_result.json --orchestration-summary examples/runtime_intelligence/orchestrator_multi_workload_sustained_summary.json --save-json examples/runtime_intelligence/aiguard_runtime_operation_guard_analysis_optional_stale_drop.json", + "- ownership: edgeenv_does_not_generate_guard_analysis=true, lab_is_final_decision_owner=true", + ] +) + "\n" RUNTIME_REPORT_REVIEW_PATH_MARKERS = [ "### Review Path", "Review path: start with `Reviewer Focus`, then open `Detailed Evidence Rows`", @@ -79,6 +90,9 @@ def test_runtime_intelligence_gitlab_template_keeps_local_first_artifact_contrac assert "runtime_anomaly_gate_summary.md" in text assert "aiguard_edgeenv_handoff_alignment.json" in text assert "aiguard_edgeenv_handoff_alignment.md" in text + assert "aiguard_edgeenv_handoff_alignment_optional_present.json" in text + assert "aiguard_edgeenv_handoff_alignment_optional_present.md" in text + assert "runtime_intelligence_source_traceability_summary.md" in text assert "smoke_runtime_intelligence_chain.sh --output-dir" in text assert "runtime_intelligence_ci_artifact_gate_summary.md" in text assert "deployment_risk_summary.json" in text @@ -106,6 +120,8 @@ def test_runtime_intelligence_gitlab_doc_states_ownership_boundaries(): assert "Validated Duration Traceability" in text assert "duration_handoff_alignment" in text assert "Validated Review Path" in text + assert "Validated Source Traceability" in text + assert "source traceability summary" in text assert "Review path" in text assert "runtime_intelligence_ci_artifact_gate_summary.md" in text @@ -242,6 +258,10 @@ def test_runtime_intelligence_ci_artifact_gate_passes_for_expected_outputs(tmp_p DURATION_TRACEABILITY_SUMMARY, encoding="utf-8", ) + (report_dir / "runtime_intelligence_source_traceability_summary.md").write_text( + SOURCE_TRACEABILITY_SUMMARY, + encoding="utf-8", + ) (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",' @@ -485,6 +505,45 @@ def test_runtime_intelligence_ci_artifact_gate_passes_for_expected_outputs(tmp_p "aiguard_runtime_operation_guard_analysis_optional_stale_drop.json" in summary ) + assert "## Validated Source Traceability" in summary + assert ( + "source_traceability_alignment: EdgeEnv handoff and AIGuard " + "optional-present fixture match" + in summary + ) + assert ( + "edgeenv_optional_source_traceability: " + "read_only_optional_source_traceability preserved" + in summary + ) + assert ( + "aiguard_optional_present_source_artifact: " + "InferEdgeAIGuard/examples/runtime_intelligence/" + "aiguard_runtime_operation_guard_analysis_optional_stale_drop.json" + in summary + ) + assert ( + "aiguard_optional_present_reproduction_command: " + "python -m inferedge_aiguard.cli " + "build-runtime-intelligence-optional-stale-drop " + "--edgeenv-regression " + "examples/runtime_intelligence/" + "edgeenv_runtime_regression_with_optional_stale_drop_context.json " + "--remote-dispatch " + "examples/runtime_intelligence/remote_dispatch_fallback_recovered_result.json " + "--orchestration-summary " + "examples/runtime_intelligence/" + "orchestrator_multi_workload_sustained_summary.json " + "--save-json " + "examples/runtime_intelligence/" + "aiguard_runtime_operation_guard_analysis_optional_stale_drop.json" + in summary + ) + assert ( + "ownership: edgeenv_does_not_generate_guard_analysis=true, " + "lab_is_final_decision_owner=true" + in summary + ) (report_dir / "runtime_anomaly_gate_summary.md").write_text( "- Status: passed\n", diff --git a/tests/test_runtime_intelligence_smoke_script.py b/tests/test_runtime_intelligence_smoke_script.py index 962a3f3..48c8475 100644 --- a/tests/test_runtime_intelligence_smoke_script.py +++ b/tests/test_runtime_intelligence_smoke_script.py @@ -54,6 +54,7 @@ def test_runtime_intelligence_smoke_script_runs_artifact_chain(tmp_path): "aiguard_edgeenv_handoff_alignment.md", "aiguard_edgeenv_handoff_alignment_optional_present.json", "aiguard_edgeenv_handoff_alignment_optional_present.md", + "runtime_intelligence_source_traceability_summary.md", "edgeenv_runtime_regression.md", "edgeenv_runtime_regression.html", "runtime_anomaly_summary.md", @@ -331,6 +332,47 @@ def test_runtime_intelligence_smoke_script_runs_artifact_chain(tmp_path): "aiguard_runtime_operation_guard_analysis_optional_stale_drop.json" in ci_summary ) + source_traceability_summary = ( + output_dir / "runtime_intelligence_source_traceability_summary.md" + ).read_text(encoding="utf-8") + assert "- Status: passed" in source_traceability_summary + assert "## Validated Source Traceability" in source_traceability_summary + assert ( + "source_traceability_alignment: EdgeEnv handoff and AIGuard " + "optional-present fixture match" + ) in source_traceability_summary + assert ( + "edgeenv_optional_source_traceability: " + "read_only_optional_source_traceability preserved" + ) in source_traceability_summary + assert ( + "aiguard_optional_present_source_artifact: " + "InferEdgeAIGuard/examples/runtime_intelligence/" + "aiguard_runtime_operation_guard_analysis_optional_stale_drop.json" + in source_traceability_summary + ) + assert ( + "aiguard_optional_present_reproduction_command: " + "python -m inferedge_aiguard.cli " + "build-runtime-intelligence-optional-stale-drop " + "--edgeenv-regression " + "examples/runtime_intelligence/" + "edgeenv_runtime_regression_with_optional_stale_drop_context.json " + "--remote-dispatch " + "examples/runtime_intelligence/remote_dispatch_fallback_recovered_result.json " + "--orchestration-summary " + "examples/runtime_intelligence/" + "orchestrator_multi_workload_sustained_summary.json " + "--save-json " + "examples/runtime_intelligence/" + "aiguard_runtime_operation_guard_analysis_optional_stale_drop.json" + in source_traceability_summary + ) + assert ( + "ownership: edgeenv_does_not_generate_guard_analysis=true, " + "lab_is_final_decision_owner=true" + in source_traceability_summary + ) assert "## Validated Duration Traceability" in ci_summary assert ( "duration_handoff_alignment: EdgeEnv/AIGuard report context preserved" diff --git a/tests/test_runtime_intelligence_source_traceability.py b/tests/test_runtime_intelligence_source_traceability.py new file mode 100644 index 0000000..4f920aa --- /dev/null +++ b/tests/test_runtime_intelligence_source_traceability.py @@ -0,0 +1,86 @@ +import json +from pathlib import Path + +from scripts.check_runtime_intelligence_source_traceability import ( + EXPECTED_AIGUARD_REPRODUCTION_COMMAND_MARKER, + EXPECTED_AIGUARD_SOURCE_ARTIFACT_MARKER, + main as source_traceability_gate, +) + + +REPO_ROOT = Path(__file__).resolve().parents[1] +EDGEENV_HANDOFF = ( + REPO_ROOT + / "examples" + / "runtime_intelligence_chain" + / "edgeenv_lab_handoff_manifest.json" +) +AIGUARD_OPTIONAL_PRESENT_ALIGNMENT = ( + REPO_ROOT + / "examples" + / "runtime_intelligence_chain" + / "aiguard_edgeenv_handoff_alignment_optional_present.json" +) + + +def test_runtime_intelligence_source_traceability_gate_passes(tmp_path): + summary_path = tmp_path / "source_traceability_summary.md" + + result = source_traceability_gate( + edgeenv_handoff=str(EDGEENV_HANDOFF), + aiguard_alignment=str(AIGUARD_OPTIONAL_PRESENT_ALIGNMENT), + summary_out=str(summary_path), + ) + + assert result == 0 + summary = summary_path.read_text(encoding="utf-8") + assert "- Status: passed" in summary + assert "## Validated Source Traceability" in summary + assert ( + "source_traceability_alignment: EdgeEnv handoff and AIGuard " + "optional-present fixture match" + ) in summary + assert ( + "edgeenv_optional_source_traceability: " + "read_only_optional_source_traceability preserved" + ) in summary + assert ( + f"aiguard_optional_present_source_artifact: " + f"{EXPECTED_AIGUARD_SOURCE_ARTIFACT_MARKER}" + ) in summary + assert ( + f"aiguard_optional_present_reproduction_command: " + f"{EXPECTED_AIGUARD_REPRODUCTION_COMMAND_MARKER}" + ) in summary + assert ( + "ownership: edgeenv_does_not_generate_guard_analysis=true, " + "lab_is_final_decision_owner=true" + ) in summary + + +def test_runtime_intelligence_source_traceability_gate_fails_for_mismatched_source( + tmp_path, +): + alignment = json.loads(AIGUARD_OPTIONAL_PRESENT_ALIGNMENT.read_text("utf-8")) + alignment["optional_present_source_artifact"]["repository"] = "InferEdgeEnv" + alignment_path = tmp_path / "aiguard_optional_present_alignment.json" + alignment_path.write_text(json.dumps(alignment), encoding="utf-8") + summary_path = tmp_path / "source_traceability_summary.md" + + result = source_traceability_gate( + edgeenv_handoff=str(EDGEENV_HANDOFF), + aiguard_alignment=str(alignment_path), + summary_out=str(summary_path), + ) + + assert result == 2 + summary = summary_path.read_text(encoding="utf-8") + assert "- Status: failed" in summary + assert ( + "AIGuard alignment source artifact must match the Lab-known AIGuard " + "optional stale-drop source artifact" + ) in summary + assert ( + "EdgeEnv handoff and AIGuard optional-present alignment must reference " + "the same source artifact and reproduction command" + ) in summary