TenantAtlas/specs/361-report-evidence-reconciliation/tasks.md
ahmido 252cd4513d feat: implement report evidence reconciliation (#432)
Implemented report evidence reconciliation.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #432
2026-06-06 22:40:59 +00:00

20 KiB

Tasks: Spec 361 - Report and Evidence Reconciliation Adapters

Input: /Users/ahmeddarrazi/Documents/projects/wt-plattform/specs/361-report-evidence-reconciliation/spec.md, plan.md, and checklists/requirements.md
Prerequisites: spec.md and plan.md
Tests: REQUIRED (Pest). Keep proof bounded to Unit + Feature + one explicit Browser smoke.
Operations: Reuse current OperationRun lifecycle ownership. No new run status column, no new queue family, and no new schema.
RBAC: Reuse current workspace-first OperationRun access plus existing EvidenceSnapshot and ReviewPack policies. No new capability strings and no cross-scope artifact resolution.
Shared Pattern Reuse: Reuse OperationRunService, current operations surfaces, OperationRunLinks, ArtifactTruthPresenter, and current evidence/review-pack detail families. Introduce only bounded artifact-specific adapters plus at most one small derived proof/helper path.
Filament / Panel Guardrails: Filament remains v5 on Livewire v4. Provider registration stays in apps/platform/bootstrap/providers.php. No new panel, global-search change, or asset strategy is allowed.
Organization: Tasks are grouped by user story so Evidence Snapshot reconciliation, Review Pack reconciliation, and honest unsupported-report handling remain independently reviewable.

Repo Baseline At Prep Time

  • Branch: 361-report-evidence-reconciliation
  • HEAD: 840c9bd2 refactor: rename ManagedEnvironment context badge to Environment context (#431)
  • git status --short --branch before Spec 361 prep: clean on platform-dev; Spec Kit created this feature branch and copied the spec/plan templates
  • Merged adapter baseline: 3a750726 feat: implement review compose reconciliation adapter (spec 359) (#430) is already in repo history and remains the adapter-registry baseline
  • Relevant runtime surfaces:
    • 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
    • apps/platform/app/Services/Evidence/EvidenceSnapshotService.php
    • apps/platform/app/Services/ReviewPackService.php
    • apps/platform/app/Support/Operations/Reconciliation/OperationRunReconciliationRegistry.php
    • apps/platform/app/Support/Ui/GovernanceArtifactTruth/ArtifactTruthPresenter.php
    • apps/platform/app/Support/OpsUx/GovernanceRunDiagnosticSummaryBuilder.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
  • Completed-spec context only: Specs 347, 349, 351, 356, and 357 are context only and must not be reopened for rendered-report or disclosure-policy scope
  • Scope guardrail: generic StoredReport causality is context only unless direct proof is stronger than expected during implementation

Test Governance Checklist

  • Lane assignment is named and is the narrowest sufficient proof for the changed behavior.
  • New or changed tests stay in the smallest honest family, and the Browser addition remains explicit.
  • Shared helpers, factories, seeds, fixtures, and context defaults stay cheap by default; any widening is isolated or documented.
  • Planned validation commands cover the change without widening into unrelated lane cost.
  • The declared monitoring/detail surface profile is explicit.
  • Any material budget, baseline, trend, or escalation note is recorded in the active feature close-out.

Phase 1: Setup (Repo Truth Inventory)

Purpose: confirm the current registry baseline, the artifact models, and the exact unsupported report-family boundary before runtime edits begin.

  • T001 Re-read spec.md, plan.md, checklists/requirements.md, .specify/memory/constitution.md, docs/ai-coding-rules.md, docs/architecture-guidelines.md, docs/testing-guidelines.md, docs/security-guidelines.md, docs/filament-guidelines.md, and specs/358-operationrun-queue-truth-foundation/{spec,plan,tasks}.md plus specs/359-operationrun-reconciliation-adapter-framework-review-compose-adapter/{spec,plan,tasks}.md and specs/360-operationrun-canonical-cutover-cleanup/{spec,plan,tasks}.md together before touching runtime code.
  • T002 [P] Confirm the current adapter and write seams in apps/platform/app/Services/AdapterRunReconciler.php, apps/platform/app/Services/OperationRunService.php, apps/platform/app/Models/OperationRun.php, and apps/platform/app/Support/Operations/Reconciliation/OperationRunReconciliationRegistry.php.
  • T003 [P] Confirm the current artifact-truth seams in apps/platform/app/Models/EvidenceSnapshot.php, apps/platform/app/Models/ReviewPack.php, apps/platform/app/Models/StoredReport.php, apps/platform/app/Services/Evidence/EvidenceSnapshotService.php, apps/platform/app/Services/ReviewPackService.php, and apps/platform/app/Support/Ui/GovernanceArtifactTruth/ArtifactTruthPresenter.php.
  • T004 [P] Confirm the current canonical operation types and run-start contexts for tenant.evidence.snapshot.generate, environment.review_pack.generate, permission.posture.check, and entra.admin_roles.scan in apps/platform/app/Support/OperationCatalog.php, apps/platform/app/Support/OperationRunType.php, and the current job/service start paths.
  • T005 Confirm that no new schema, no new panel/provider path, no new asset registration, no new stored_report.generate operation type, and no generic stored-report lifecycle model are required; if any of those are needed, stop and update the spec/plan instead of widening scope silently.

Phase 2: Foundational (Bounded Artifact-Proof and Registry Setup)

Purpose: settle the bounded proof checks and registry shape before story-specific adapter work begins.

Critical: no user-story runtime work should begin until this phase is complete.

  • T006 [P] Add failing Unit coverage in apps/platform/tests/Unit/Support/Operations/Reconciliation/Spec361ArtifactRegistryResolutionTest.php for adapter resolution of tenant.evidence.snapshot.generate, environment.review_pack.generate, and unsupported generic report families.
  • T007 [P] Add failing Unit coverage in apps/platform/tests/Unit/Support/Operations/Reconciliation/Spec361ArtifactProofRulesTest.php for scope checks, completeness checks, expiration handling, canonical related-identity tie-breaking, and fail-closed unsupported-report behavior.
  • T008 No bounded shared helper was needed; evidence and review-pack proof logic stayed local to their adapters.
  • T009 Add EvidenceSnapshotReconciliationAdapter and ReviewPackArtifactReconciliationAdapter (or equivalent bounded names) under apps/platform/app/Support/Operations/Reconciliation/ and register them in OperationRunReconciliationRegistry.
  • T010 Keep generic StoredReport reconciliation out of the registry in Spec 361. Do not add any StoredReport-backed success path in this package; record a named follow-up spec instead of a heuristic adapter.
  • T011 Update or add Unit coverage proving that adapters never mutate EvidenceSnapshot, ReviewPack, or StoredReport, that all lifecycle writes still go through OperationRunService, that context.reconciliation keeps the canonical adapter or reason or previous-state or related-artifact shape, and that rerunning reconciliation is idempotent.

Checkpoint: the registry is ready for artifact-backed extensions, and the unsupported report-family boundary is explicit.


Phase 3: User Story 1 - Reconcile evidence generation against an existing snapshot (Priority: P1)

Goal: tenant.evidence.snapshot.generate runs can finalize against an existing current-scope snapshot when current repo truth already proves success.

Independent Test: run focused Unit and Feature coverage showing that a queued/running/stale evidence-generation run finalizes successfully only when a matching active, non-partial snapshot already exists.

Tests for User Story 1

  • T012 [P] [US1] Add apps/platform/tests/Feature/Operations/Spec361EvidenceSnapshotReconciliationTest.php covering active complete success, partial rejection, failed/expired rejection, wrong-scope rejection, and ambiguous-candidate rejection.
  • T013 [P] [US1] Extend apps/platform/tests/Feature/Evidence/GenerateEvidenceSnapshotJobTest.php or a focused companion file so stale queued/running evidence-generation runs can prove the adapter-backed finalization path without changing artifact generation semantics.

Implementation for User Story 1

  • T014 [US1] Implement EvidenceSnapshotReconciliationAdapter under apps/platform/app/Support/Operations/Reconciliation/ using existing operation_run_id, managed_environment_id, workspace_id, fingerprint, status, and completeness_state truth.
  • T015 [US1] Reuse apps/platform/app/Services/Evidence/EvidenceSnapshotService.php and apps/platform/app/Services/OperationRunService.php without adding a new evidence lifecycle or persistence layer.
  • T016 [US1] Update existing operations/detail presentation paths in apps/platform/app/Support/OpsUx/GovernanceRunDiagnosticSummaryBuilder.php, apps/platform/app/Support/Ui/GovernanceArtifactTruth/ArtifactTruthPresenter.php, apps/platform/app/Filament/Pages/Operations/TenantlessOperationRunViewer.php, apps/platform/app/Filament/Pages/Monitoring/Operations.php, and apps/platform/app/Filament/Resources/EvidenceSnapshotResource.php only as needed so reconciled evidence runs explain the matched snapshot calmly, scope-safely, and without duplicate default-visible truth.

Checkpoint: evidence-generation runs reconcile safely from current snapshot truth and never overclaim partial or wrong-scope success.


Phase 4: User Story 2 - Reconcile review-pack generation against an existing pack (Priority: P1)

Goal: environment.review_pack.generate runs can finalize against an existing ready, non-expired pack when current repo truth already proves success.

Independent Test: run focused Unit and Feature coverage showing that a queued/running/stale review-pack run finalizes successfully only when a matching ready, current-scope pack already exists.

Tests for User Story 2

  • T017 [P] [US2] Add apps/platform/tests/Feature/Operations/Spec361ReviewPackReconciliationTest.php covering ready success plus queued/generating/failed/expired/wrong-scope rejection.
  • T018 [P] [US2] Extend focused review-pack coverage in apps/platform/tests/Feature/ReviewPack/EnvironmentReviewDerivedReviewPackTest.php, apps/platform/tests/Feature/ReviewPack/ReviewPackDownloadTest.php, apps/platform/tests/Feature/ReviewPack/ReviewPackResourceTest.php, or a companion file only as needed to prove canonical related-artifact metadata, current host detail fallout, and no false success on incomplete or non-shareable output.

Implementation for User Story 2

  • T019 [US2] Implement ReviewPackArtifactReconciliationAdapter under apps/platform/app/Support/Operations/Reconciliation/ for environment.review_pack.generate, using existing ReviewPack scope, status, expiration, fingerprint, operation_run_id, and review/evidence linkage where current repo truth exposes it.
  • T020 [US2] Reuse apps/platform/app/Services/ReviewPackService.php, apps/platform/app/Support/OperationRunLinks.php, and apps/platform/app/Support/Ui/GovernanceArtifactTruth/ArtifactTruthPresenter.php so reconciled runs link to the current pack without exposing raw storage or expired artifacts.
  • T021 [US2] Keep customer-safe and operator-safe boundaries intact: no new download mutation, no rendered-report rewrite, no new readiness taxonomy, and no reopening of Specs 347/349/351/356/357 scope.

Checkpoint: review-pack generation runs reconcile safely from current pack truth and never overclaim expired or still-generating output.


Phase 5: User Story 3 - Keep unsupported generic report families honest (Priority: P2)

Goal: report-producing runs backed only by weak StoredReport truth stay fail-closed instead of falsely succeeding from "latest report exists" heuristics.

Independent Test: run focused Unit and Feature coverage showing that permission.posture.check and entra.admin_roles.scan remain unresolved or diagnostic-first because Spec 361 keeps StoredReport success reconciliation out of scope.

Tests for User Story 3

  • T022 [P] [US3] Add focused Unit or Feature coverage in apps/platform/tests/Feature/Operations/Spec361UnsupportedStoredReportReconciliationTest.php proving that retained StoredReport rows alone do not reconcile permission.posture.check or entra.admin_roles.scan.
  • T023 [P] [US3] Add or extend operations-detail coverage in apps/platform/tests/Feature/Operations/TenantlessOperationRunViewerTest.php or a companion Spec 361 file so unsupported report-family runs remain attention-first, keep one dominant default next action, keep diagnostics secondary, and do not expose raw/support evidence in the default-visible layer for ordinary operators.

Implementation for User Story 3

  • T024 [US3] Verify that generic StoredReport families remain excluded from the Spec 361 registry path and record the named follow-up spec in the feature close-out instead of widening this package.
  • T025 [US3] No unsupported-report helper was needed; stored-report families stayed on existing operations diagnostics and artifact-truth paths without a new lifecycle model.
  • T026 [US3] Ensure permission.posture.check, entra.admin_roles.scan, restore, sync, backup, and review-compose semantics remain unchanged except for clearer unsupported or related-artifact diagnostics on current operations surfaces and existing host-gated disclosure paths.

Checkpoint: the feature improves artifact-backed truth where repo proof is strong and explicitly refuses false success where proof is weak.


Phase 6: Polish & Validation

  • T027 [P] Refresh spec.md, plan.md, and checklists/requirements.md only if implementation proves a thinner touched-file boundary or requires an explicit recorded defer for generic stored-report causality.
  • T028 [P] Run the primary in-scope Unit and Feature gate:
    • cd apps/platform && ./vendor/bin/sail php vendor/bin/pest tests/Unit/Support/Operations/Reconciliation tests/Feature/Operations/Spec361*
  • T029 [P] Run the bounded contextual artifact regressions:
    • 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
  • T030 [P] Run the primary browser smoke and verify the changed operations surfaces still show one dominant next action, keep duplicate visible decision truth out of the default layer, and keep deeper diagnostics behind explicit reveal paths:
    • cd apps/platform && ./vendor/bin/sail php vendor/bin/pest tests/Browser/Spec361ArtifactReconciliationSmokeTest.php
  • T031 [P] Run the bounded contextual browser smoke only if visible copy or link behavior changes on related surfaces:
    • cd apps/platform && ./vendor/bin/sail php vendor/bin/pest tests/Browser/Spec360OperationRunCanonicalCutoverSmokeTest.php tests/Browser/Spec337EvidenceReviewPackProductFlowSmokeTest.php
  • T032 [P] Run cd apps/platform && ./vendor/bin/pint --dirty.
  • T033 [P] Run git diff --check.
  • T034 [P] Record the final artifact families reconciled, the explicit unsupported generic report-family decision, validation results, no-migration status, no-asset status, and the final Guardrail / Smoke Coverage note in the active feature close-out.

Close-Out Notes

  • Reconciled artifact families: tenant.evidence.snapshot.generate via EvidenceSnapshotReconciliationAdapter and environment.review_pack.generate via ReviewPackArtifactReconciliationAdapter.
  • Explicit unsupported generic report-family decision: permission.posture.check and entra.admin_roles.scan remain outside the adapter registry because StoredReport still lacks direct lifecycle truth and causal linkage; any future auto-success path needs a follow-up spec.
  • No migration status: no schema or persisted-truth changes were required.
  • No asset / panel status: no Filament panel/provider/global-search/asset changes were required; Laravel 12 provider registration remains in apps/platform/bootstrap/providers.php, and Filament stays on v5 with Livewire v4.
  • Guardrail / Smoke Coverage: Spec 361 added bounded Unit + Feature coverage for registry shape, canonical related IDs, artifact-safe success/fail-closed behavior, and a Browser smoke for evidence snapshot and review-pack drill-through on existing Operations surfaces.
  • Validation results:
    • cd apps/platform && php vendor/bin/pest tests/Unit/Support/Operations/Reconciliation tests/Feature/Operations/Spec359OperationRunAdapterReconciliationTest.php tests/Feature/Operations/Spec360CanonicalReconciliationCutoverTest.php tests/Feature/Operations/Spec361EvidenceSnapshotReconciliationTest.php tests/Feature/Operations/Spec361ReviewPackReconciliationTest.php tests/Feature/Operations/Spec361UnsupportedStoredReportReconciliationTest.php tests/Feature/EnvironmentReview/Spec359ReviewComposeReconciliationTest.php tests/Feature/EnvironmentReview/Spec360ReviewComposeAdapterOwnershipTest.php tests/Feature/Evidence/GenerateEvidenceSnapshotJobTest.php tests/Feature/ReviewPack/EnvironmentReviewDerivedReviewPackTest.php tests/Feature/ReviewPack/ReviewPackDownloadTest.php tests/Feature/ReviewPack/Spec347ReviewPackOutputContractTest.php -> 55 passed, 443 assertions.
    • cd apps/platform && php vendor/bin/pest tests/Browser/Spec361ArtifactReconciliationSmokeTest.php -> 2 passed, 20 assertions.
    • cd apps/platform && php vendor/bin/pint --dirty -> fixed 3 style issues across 19 files.
    • git diff --check -> clean.

Dependencies & Execution Order

Phase Dependencies

  • Setup (Phase 1): no dependencies
  • Foundational (Phase 2): depends on Setup and blocks all story work
  • US1 (Phase 3): depends on Foundational completion
  • US2 (Phase 4): depends on Foundational completion; can land after US1 or in parallel once shared proof rules settle
  • US3 (Phase 5): depends on US1 and US2 because the unsupported-family boundary should be validated against the final in-scope adapter set
  • Polish (Phase 6): depends on all desired user stories

Parallel Opportunities

  • T002, T003, and T004 can run in parallel.
  • T006 and T007 can run in parallel.
  • T012 and T013 can run in parallel.
  • T017 and T018 can run in parallel.
  • T022 and T023 can run in parallel.
  • T028 through T033 can run in parallel once implementation stabilizes, but the primary merge gate should be read out separately from contextual regressions.

Implementation Strategy

  1. Freeze the current registry and artifact-model baseline first.
  2. Land the bounded proof rules and registry setup before story-specific runtime edits.
  3. Land Evidence Snapshot reconciliation first because its proof path is strongest.
  4. Land Review Pack reconciliation second because it is customer-visible and already repo-real.
  5. Finish by locking fail-closed behavior for weak generic report families and recording any explicit defer.

Non-Goals / Must-Not-Do

  • NT001 Do not add a new OperationRun status column, boolean, or separate reconciliation table.
  • NT002 Do not add a stored_report.generate operation type, a generic report-artifact lifecycle model, or a new rendered-report workflow.
  • NT003 Do not mutate EvidenceSnapshot, ReviewPack, or StoredReport from adapters.
  • NT004 Do not widen scope into backup, restore, sync, review-compose, PDF/HTML rendering, disclosure policy, or customer portal work.
  • NT005 Do not add compatibility shims or heuristics only to preserve pre-production historical report behavior.