"""Deterministic workflow materialized-view projection from canonical events.""" from __future__ import annotations from typing import Any, Callable PROTECTED_FIELDS = ( "quality_gate_status", "quality-gate-status", "release_acceptance_status", "release-acceptance-status", "unresolved_critical_risks", "unresolved-critical-risks", "blocker-open", "blocker_open", "resume-condition", "resume_condition_present", "resume-condition-satisfied", "resume_condition_satisfied", "evidence-grade", "evidence_grade", "human_gate_approved", "human-gate-approved", "current-quality-event-id", "current-quality-event-ids", "current-quality-artifact-id", "current-quality-artifact-sha256", "current-completion-artifact-id", "current-completion-artifact-sha256", "quality-panel-unmet", ) def _latest_artifact_of_kind(artifacts: list[dict[str, Any]], kind: str) -> dict[str, Any] | None: return next((artifact for artifact in reversed(artifacts or []) if isinstance(artifact, dict) and artifact.get("artifact-kind") == kind), None) def project_workflow( ledger: dict[str, Any], *, trusted_artifacts: list[dict[str, Any]], workflow_events: list[dict[str, Any]], initial_stage: Callable[[str], str], quality_panel_unmet: Callable[[str, list[dict[str, Any]], list[dict[str, Any]]], list[str]], default_plan: str, ) -> dict[str, Any]: """Rebuild protected fields; caller-owned data is never accepted as runtime truth.""" projected = dict(ledger) for key in PROTECTED_FIELDS: projected.pop(key, None) projected["artifacts"] = trusted_artifacts quality_events: list[dict[str, Any]] = [] release_events: list[dict[str, Any]] = [] for event in workflow_events: event_type = event.get("event-type") if event_type == "workflow-initialized": projected["stage"] = event.get("stage") or initial_stage(event.get("plan", default_plan)) projected["stage-status"] = "running" projected["last-completed-stage"] = None projected["completed-for-next-stage"] = None projected.pop("blocked-from", None) projected.pop("design-direction-approval", None) projected.pop("experience-foundation-approval", None) for key in ( "plan", "tier", "mode", "evidence-contract-version", "parent-workflow-id", "product-decision-id", "direction-input-brief-ref", "direction-input-brief-sha256", ): if event.get(key) is not None: projected[key] = event.get(key) elif event_type == "state-transition": projected["stage"] = event.get("to") or projected.get("stage") projected["stage-status"] = "running" projected["last-completed-stage"] = event.get("from") projected["completed-for-next-stage"] = None if event.get("to") == "blocked": projected["blocked-from"] = event.get("from") elif event.get("from") == "blocked": projected.pop("blocked-from", None) elif event_type == "stage-completed": if event.get("stage") == projected.get("stage"): projected["stage-status"] = "completed" projected["last-completed-stage"] = event.get("stage") projected["completed-for-next-stage"] = event.get("intended-next-stage") elif event_type == "quality-gate-recorded": quality_events.append(event) elif event_type == "release-decision-recorded": release_events.append(event) elif event_type == "tier-escalated": projected["tier"] = event.get("to-tier") or projected.get("tier") elif event_type == "workflow-blocked": projected["blocked-from"] = event.get("blocked-from") or projected.get("stage") projected["stage"] = "blocked" projected["stage-status"] = "running" projected["completed-for-next-stage"] = None projected["blocker-open"] = True projected["resume-condition"] = event.get("resume-condition") projected.pop("resume-condition-satisfied", None) elif event_type == "workflow-resumed": projected["stage"] = event.get("to") or projected.get("blocked-from") or projected.get("stage") projected["stage-status"] = "running" projected["completed-for-next-stage"] = None projected.pop("blocked-from", None) projected["blocker-open"] = False projected["resume-condition-satisfied"] = True elif event_type == "direction-approval-registered": projected["design-direction-approval"] = { "report-ref": event.get("report-ref"), "report-sha256": event.get("report-sha256"), "child-workflow-id": event.get("child-workflow-id"), } elif event_type == "experience-foundation-registered": projected["experience-foundation-approval"] = { "child-workflow-id": event.get("child-workflow-id"), "product-decision-id": event.get("product-decision-id"), "benchmark-id": event.get("benchmark-id"), "benchmark-ref": event.get("benchmark-ref"), "benchmark-sha256": event.get("benchmark-sha256"), "strategy-id": event.get("strategy-id"), "strategy-ref": event.get("strategy-ref"), "strategy-sha256": event.get("strategy-sha256"), "technical-id": event.get("technical-id"), "technical-ref": event.get("technical-ref"), "technical-sha256": event.get("technical-sha256"), "operational-id": event.get("operational-id"), "operational-ref": event.get("operational-ref"), "operational-sha256": event.get("operational-sha256"), "blueprint-id": event.get("blueprint-id"), "blueprint-ref": event.get("blueprint-ref"), "blueprint-sha256": event.get("blueprint-sha256"), "wireframe-id": event.get("wireframe-id"), "wireframe-ref": event.get("wireframe-ref"), "wireframe-sha256": event.get("wireframe-sha256"), } completion = _latest_artifact_of_kind(trusted_artifacts, "completion-record") if not completion: return projected completion_id = completion.get("artifact-id") completion_sha = completion.get("artifact-sha256") projected["current-completion-artifact-id"] = completion_id projected["current-completion-artifact-sha256"] = completion_sha current_quality = [ event for event in quality_events if event.get("reviewed-artifact-id") == completion_id and event.get("reviewed-artifact-sha256") == completion_sha and any( artifact.get("artifact-id") == event.get("review-artifact-id") and artifact.get("artifact-sha256") == event.get("review-artifact-sha256") for artifact in trusted_artifacts ) ] latest_by_actor = {event.get("actor"): event for event in current_quality} active_quality = list(latest_by_actor.values()) if active_quality: failed = any(event.get("status") != "Passed" or event.get("blocker-open") for event in active_quality) projected["quality_gate_status"] = "Failed" if failed else "Passed" projected["blocker-open"] = bool(projected.get("blocker-open")) or any( bool(event.get("blocker-open")) for event in active_quality) last_quality = active_quality[-1] projected["current-quality-event-id"] = last_quality.get("workflow-event-id") projected["current-quality-event-ids"] = sorted( event.get("workflow-event-id") for event in active_quality if event.get("workflow-event-id") ) projected["current-quality-artifact-id"] = last_quality.get("review-artifact-id") projected["current-quality-artifact-sha256"] = last_quality.get("review-artifact-sha256") panel_unmet = quality_panel_unmet(projected.get("tier"), trusted_artifacts, active_quality) if panel_unmet: projected["quality-panel-unmet"] = panel_unmet projected.pop("quality_gate_status", None) active_event_ids = projected.get("current-quality-event-ids") or [] for event in release_events: if (event.get("reviewed-completion-artifact-id") != completion_id or event.get("reviewed-completion-artifact-sha256") != completion_sha or sorted(event.get("quality-event-set") or []) != active_event_ids): continue if event.get("status") == "Approved" and ( projected.get("quality_gate_status") != "Passed" or projected.get("blocker-open")): continue projected["release_acceptance_status"] = event.get("status") projected["unresolved_critical_risks"] = bool(event.get("unresolved-critical-risks")) return projected