# Implementation Plan: Spec 361 - Report and Evidence Reconciliation Adapters **Branch**: `361-report-evidence-reconciliation` | **Date**: 2026-06-06 | **Spec**: `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/361-report-evidence-reconciliation/spec.md` **Input**: Feature specification from `/Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/361-report-evidence-reconciliation/spec.md` **Note**: This plan is repo-aware and preparation-only. No application implementation is performed in this step. ## Summary Extend the current `OperationRun` reconciliation registry with artifact-backed, read-only adapters for `EvidenceSnapshot` and `ReviewPack`, so queued/running/stale runs can finalize only when current repo-real artifact truth already proves success. Keep generic `StoredReport` families fail-closed and explicitly deferred; Spec 361 does not allow any `StoredReport`-backed success path. ## Technical Context **Language/Version**: PHP 8.4.15 **Primary Dependencies**: Laravel 12.52, Filament 5.2.1, Livewire 4.1.4, Pest 4.3.1 **Storage**: PostgreSQL 16 (`operation_runs`, `evidence_snapshots`, `review_packs`, `stored_reports`) **Testing**: Pest Unit + Feature + one bounded Browser smoke **Validation Lanes**: fast-feedback, confidence, browser **Target Platform**: Laravel monolith in Sail / Dokploy container workflow **Project Type**: single web application (`apps/platform`) **Performance Goals**: no new polling or background family; reconciliation stays bounded to current stale/queued scan paths **Constraints**: no new schema, no new operation type, no new panel/provider, no new Filament asset strategy, no generic stored-report heuristics **Scale/Scope**: narrow `OperationRun` artifact reconciliation extension over two existing artifact families plus explicit unsupported-family handling ## UI / Surface Guardrail Plan - **Guardrail scope**: changed surfaces - **Affected routes/pages/actions/states/navigation/panel/provider surfaces**: - `apps/platform/app/Filament/Pages/Monitoring/Operations.php` - `apps/platform/app/Filament/Pages/Operations/TenantlessOperationRunViewer.php` - `apps/platform/app/Filament/Resources/EvidenceSnapshotResource.php` - `apps/platform/app/Filament/Resources/ReviewPackResource.php` - **No-impact class, if applicable**: N/A - **Native vs custom classification summary**: native Filament surfaces with shared `OperationRun` and artifact-truth helpers - **Shared-family relevance**: `OperationRun` monitoring family plus artifact-truth detail family - **State layers in scope**: page, detail, URL-query - **Audience modes in scope**: operator-MSP, support-platform - **Decision/diagnostic/raw hierarchy plan**: decision-first on operations surfaces, diagnostics-second on run detail, artifact proof on demand through existing detail pages - **Raw/support gating plan**: raw context stays in existing diagnostic sections only - **One-primary-action / duplicate-truth control**: keep current inspect/open paths; do not add a second success summary on artifact pages - **Handling modes by drift class or surface**: review-mandatory - **Repository-signal treatment**: review-mandatory for any attempt to widen scope into generic stored-report success or new artifact lifecycle semantics - **Special surface test profiles**: monitoring-state-page - **Required tests or manual smoke**: functional-core plus one bounded browser smoke - **Exception path and spread control**: none - **Active feature PR close-out entry**: Guardrail / Smoke Coverage - **UI/Productization coverage decision**: no new coverage artifact required; existing monitoring and artifact page families remain sufficient - **Coverage artifacts to update**: none by default - **No-impact rationale**: existing reachable surfaces only; no new route family or navigation entry - **Navigation / Filament provider-panel handling**: no panel or navigation change - **Screenshot or page-report need**: no by default; use bounded browser smoke unless implementation proves a material hierarchy shift ## Shared Pattern & System Fit - **Cross-cutting feature marker**: yes - **Systems touched**: - `App\Services\AdapterRunReconciler` - `App\Services\OperationRunService` - `App\Support\Operations\Reconciliation\OperationRunReconciliationRegistry` - `App\Support\OperationRunLinks` - `App\Support\Ui\GovernanceArtifactTruth\ArtifactTruthPresenter` - `App\Support\OpsUx\GovernanceRunDiagnosticSummaryBuilder` - **Shared abstractions reused**: current adapter contract, current service-owned reconciliation metadata, current monitoring/detail presenters, current artifact-truth presenters and links - **New abstraction introduced? why?**: at most one small proof/helper path if duplicated scope/completeness checks across Evidence Snapshot and Review Pack become noisy; no generic report framework is allowed - **Why the existing abstraction was sufficient or insufficient**: the write seam and presenters already exist, but the registry lacks artifact-backed success for evidence and review-pack runs - **Bounded deviation / spread control**: keep proof logic local to `App\Support\Operations\Reconciliation\`; do not add new persistence or a generalized artifact orchestration engine ## OperationRun UX Impact - **Touches OperationRun start/completion/link UX?**: yes - **Central contract reused**: current `OperationRunService`, registry-backed reconciliation, `OperationRunLinks`, and existing monitoring/detail presenters - **Delegated UX behaviors**: existing queued toast, run link, artifact link, run-enqueued browser event, and terminal notification paths remain unchanged - **Surface-owned behavior kept local**: wording and placement only - **Queued DB-notification policy**: unchanged - **Terminal notification path**: unchanged central lifecycle mechanism - **Exception path**: none ## Provider Boundary & Portability Fit - **Shared provider/platform boundary touched?**: no - **Provider-owned seams**: N/A - **Platform-core seams**: `OperationRun`, artifact truth, current scope-safe links - **Neutral platform terms / contracts preserved**: `operation`, `artifact`, `review pack`, `evidence snapshot`, `reconciliation` - **Retained provider-specific semantics and why**: none - **Bounded extraction or follow-up path**: generic `StoredReport` causality remains a separate future follow-up if ever needed ## Constitution Check *GATE: Must pass before implementation starts. Re-check if scope changes.* - Inventory-first: PASS. The slice reads current artifact truth; it does not create new snapshot truth. - Read/write separation: PASS. Adapters read artifacts only and finalize runs only through `OperationRunService`. - Graph contract path: PASS. No Graph surface change is planned. - Deterministic capabilities: PASS. No new capability derivation is introduced. - Workspace and tenant isolation: PASS. Adapters must use run-owned workspace/environment scope and existing resource policies. - Run observability: PASS. `OperationRun` remains the only lifecycle owner; no shadow truth is introduced. - TEST-GOV-001: PASS. Unit + Feature + bounded Browser are the narrowest honest proof. - PROP-001 / ABSTR-001: PASS only if any new helper stays bounded to the two in-scope artifact families and does not become a generic report framework. - PERSIST-001 / STATE-001: PASS. No new persisted truth or lifecycle family is planned. - XCUT-001 / LAYER-001: PASS. Extend current registry and presenters; do not create parallel operator language. - UI-SEM-001 / UI-FIL-001 / UI-COV-001: PASS. Existing native surfaces only; no new page family or asset strategy. - BADGE-001: PASS. Existing badge and artifact-truth semantics remain authoritative. ## Test Governance Check - **Test purpose / classification by changed surface**: Unit for adapter resolution, proof logic, reconciliation-metadata shape, and idempotency; Feature for run finalization, scope-safe links, and disclosure-layer behavior; Browser for existing Operations or artifact surface wording if it materially changes - **Affected validation lanes**: fast-feedback, confidence, browser - **Why this lane mix is the narrowest sufficient proof**: the feature is primarily service and model coordination with a small amount of operator-visible copy and link fallout; no PGSQL-only schema behavior is introduced - **Narrowest proving command(s)**: - `cd apps/platform && ./vendor/bin/sail php vendor/bin/pest tests/Unit/Support/Operations/Reconciliation tests/Feature/Operations/Spec361*` - `cd apps/platform && ./vendor/bin/sail php vendor/bin/pest tests/Feature/Evidence/GenerateEvidenceSnapshotJobTest.php tests/Feature/Evidence/EvidenceSnapshotResourceTest.php` - `cd apps/platform && ./vendor/bin/sail php vendor/bin/pest tests/Feature/ReviewPack/EnvironmentReviewDerivedReviewPackTest.php tests/Feature/ReviewPack/ReviewPackDownloadTest.php tests/Feature/ReviewPack/Spec347ReviewPackOutputContractTest.php` - `cd apps/platform && ./vendor/bin/sail php vendor/bin/pest tests/Browser/Spec361ArtifactReconciliationSmokeTest.php` - **Fixture / helper / factory / seed / context cost risks**: existing workspace/environment and artifact factories only; no new global defaults should be introduced - **Expensive defaults or shared helper growth introduced?**: no - **Heavy-family additions, promotions, or visibility changes**: one explicit browser smoke only - **Surface-class relief / special coverage rule**: monitoring-state-page - **Closing validation and reviewer handoff**: reviewers should verify that `StoredReport` families stay unsupported in Spec 361, that adapters never mutate artifacts, that `context.reconciliation` stays canonical and idempotent, and that no new operation type or asset strategy slips into scope - **Budget / baseline / trend follow-up**: none expected - **Review-stop questions**: does the feature overclaim generic report success, add persistence, or invent a new artifact lifecycle model? - **Escalation path**: document-in-feature if stored-report proof remains insufficient; reject-or-split if implementation tries to widen scope - **Active feature PR close-out entry**: Guardrail / Smoke Coverage - **Why no dedicated follow-up spec is needed**: Evidence Snapshot and Review Pack already have strong repo-real proof surfaces. Only generic stored-report causality is deferred explicitly to a future follow-up spec if the repo ever gains a direct proof contract. ## Repo-Verified Runtime Surfaces Likely Affected - `apps/platform/app/Services/AdapterRunReconciler.php` - `apps/platform/app/Services/OperationRunService.php` - `apps/platform/app/Models/OperationRun.php` - `apps/platform/app/Models/EvidenceSnapshot.php` - `apps/platform/app/Models/ReviewPack.php` - `apps/platform/app/Models/StoredReport.php` (context only unless proof is stronger than expected) - `apps/platform/app/Support/Operations/Reconciliation/OperationRunReconciliationRegistry.php` - `apps/platform/app/Support/Operations/Reconciliation/OperationRunReconciliationAdapter.php` - `apps/platform/app/Support/OperationRunLinks.php` - `apps/platform/app/Support/Ui/GovernanceArtifactTruth/ArtifactTruthPresenter.php` - `apps/platform/app/Support/OpsUx/GovernanceRunDiagnosticSummaryBuilder.php` - `apps/platform/app/Support/OperationCatalog.php` - `apps/platform/app/Support/OperationRunType.php` - `apps/platform/app/Services/Evidence/EvidenceSnapshotService.php` - `apps/platform/app/Services/ReviewPackService.php` - `apps/platform/app/Filament/Pages/Monitoring/Operations.php` - `apps/platform/app/Filament/Pages/Operations/TenantlessOperationRunViewer.php` - `apps/platform/app/Filament/Resources/EvidenceSnapshotResource.php` - `apps/platform/app/Filament/Resources/ReviewPackResource.php` - `apps/platform/tests/Feature/Operations/*` - `apps/platform/tests/Feature/Evidence/*` - `apps/platform/tests/Feature/ReviewPack/*` - `apps/platform/tests/Browser/Spec360OperationRunCanonicalCutoverSmokeTest.php` and new Spec 361 smoke coverage as needed ## Technical Approach 1. Verify the exact current repo-real operation types, artifact models, and status/fingerprint/scope fields before runtime edits. 2. Reuse the current reconciliation registry and service-owned write seam. 3. Add bounded, read-only adapters for `EvidenceSnapshot` and `ReviewPack` only. 4. Keep generic `StoredReport` families fail-closed in Spec 361 and record any future direct-proof need as a separate follow-up spec instead of widening this package. 5. Reuse current operations and artifact-truth presentation seams for operator-facing fallout. ## Risk Controls - Fail closed on ambiguous, expired, partial, missing, or cross-scope artifacts. - No adapter may write to artifact models or regenerate output. - No new `stored_report.generate` or similar operation type may be introduced. - If generic stored-report proof is still insufficient, the implementation must record an explicit defer note instead of widening scope. - No new panel/provider, global search, asset registration, or destructive action may be added in this slice. ## Implementation Phases ### Phase 1: Baseline and Repo-Truth Inventory Confirm current operation types, adapter seams, and artifact models. Explicitly verify that `StoredReport` is still weaker than `EvidenceSnapshot` and `ReviewPack`. ### Phase 2: Canonical Evidence Snapshot Reconciliation Add the evidence adapter, bounded proof checks, and focused operations/evidence tests. ### Phase 3: Canonical Review Pack Reconciliation Add the review-pack adapter, bounded proof checks, current operations/detail fallout, and focused review-pack tests. ### Phase 4: Unsupported Generic Report-Family Handling Keep `permission.posture.check` and `entra.admin_roles.scan` honest and diagnostic-first. Record defer/follow-up instead of inventing new truth. ### Phase 5: Validation and Close-Out Run scoped Pest and Browser validation, confirm no migration/assets/panel drift, and record which artifact families were reconciled versus explicitly deferred. ## Project Structure ### Documentation (this feature) ```text specs/361-report-evidence-reconciliation/ ├── spec.md ├── plan.md ├── tasks.md └── checklists/requirements.md ``` ### Source Code (repository root) ```text apps/platform/app/Services/ apps/platform/app/Support/Operations/Reconciliation/ apps/platform/app/Support/OpsUx/ apps/platform/app/Support/Ui/GovernanceArtifactTruth/ apps/platform/app/Filament/Pages/ apps/platform/app/Filament/Resources/ apps/platform/tests/Unit/ apps/platform/tests/Feature/ apps/platform/tests/Browser/ ``` ## Assumptions - The merged Spec 359 baseline and current `context.dispatch` seam remain in `platform-dev`. - `EvidenceSnapshot` and `ReviewPack` retain their current status, fingerprint, and scope semantics. - No production-compatibility requirement exists that would justify weak generic stored-report heuristics. ## Open Preparation Decision Generic `StoredReport` reconciliation is intentionally excluded from the initial safe implementation slice because the current model lacks direct `operation_run_id` and readiness truth. This is not a blocker: the spec is explicitly narrowed around `EvidenceSnapshot` and `ReviewPack`, and unsupported report families must remain fail-closed.