TenantAtlas/specs/359-operationrun-reconciliation-adapter-framework-review-compose-adapter/plan.md
ahmido 3a750726fd feat: implement review compose reconciliation adapter (spec 359) (#430)
Spec 359: add a narrow review-compose reconciliation path, deterministic duplicate/superseded recovery, shared review truth resolution, and bounded unit/feature/browser coverage. PGSQL validation remains locally blocked because the pgsql host/Docker runtime was unavailable.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #430
2026-06-06 14:58:16 +00:00

18 KiB

Implementation Plan: OperationRun Reconciliation Adapter Framework & Review Compose Adapter

Branch: 359-operationrun-reconciliation-adapter-framework-review-compose-adapter | Date: 2026-06-06 | Spec: specs/359-operationrun-reconciliation-adapter-framework-review-compose-adapter/spec.md
Input: Feature specification from specs/359-operationrun-reconciliation-adapter-framework-review-compose-adapter/spec.md

Summary

Implement a narrow business-truth reconciliation seam for OperationRun that reuses existing service-owned lifecycle writes and existing review-compose start/monitoring UX. The slice introduces one typed adapter contract plus one environment.review.compose adapter, proves same-scope EnvironmentReview truth, recovers duplicate fingerprint collisions deterministically, and keeps restore-specific reconciliation behavior intact as existing context rather than reopening it as a second feature.

This plan must stay smaller than a universal reconciliation engine. It extends current repo seams only where current review-compose truth cannot be proven safely by the existing scheduled stale-run reconciler or the hard-coded restore adapter.

Technical Context

Language/Version: PHP 8.4.15, Laravel 12.52, Filament 5.2.1, Livewire 4.1.4
Primary Dependencies: existing OperationRunService, OperationRun, OperationCatalog, current restore adapter reconciler, current review-compose services/jobs/resources, Pest 4.3
Storage: PostgreSQL operation_runs and environment_reviews; no schema change planned
Testing: Pest Unit + Feature + one bounded Browser smoke; PGSQL lane required for duplicate-index/locking proof
Validation Lanes: fast-feedback, confidence, pgsql, browser
Target Platform: Laravel monolith in apps/platform
Project Type: web application
Performance Goals: reuse current DB-only monitoring posture, avoid new render-time Graph work, and keep adapter evaluation to scoped local DB reads only
Constraints: no new OperationRun status/outcome field, no new review status family, no new panel/provider/asset change, no provider-boundary widening, no destructive cleanup, and no broad restore/report/evidence adapter expansion
Scale/Scope: one new review-compose path on the existing adapter reconciliation seam plus the smallest local decision/result helper needed to make adapter reconciliation auditable and repeatable

Likely Affected Repo Surfaces

  • Existing reconciliation and lifecycle seams:
    • apps/platform/app/Services/OperationRunService.php
    • apps/platform/app/Models/OperationRun.php
    • apps/platform/app/Services/Operations/OperationLifecycleReconciler.php
    • apps/platform/app/Services/AdapterRunReconciler.php
    • apps/platform/app/Support/OperationCatalog.php
    • apps/platform/app/Support/OperationRunType.php
    • apps/platform/app/Support/OperationRunStatus.php
    • apps/platform/app/Support/OperationRunOutcome.php
  • Existing review-compose runtime seams:
    • apps/platform/app/Services/EnvironmentReviews/EnvironmentReviewService.php
    • apps/platform/app/Jobs/ComposeEnvironmentReviewJob.php
    • apps/platform/app/Services/EnvironmentReviews/EnvironmentReviewComposer.php
    • apps/platform/app/Services/EnvironmentReviews/EnvironmentReviewFingerprint.php
    • apps/platform/app/Services/EnvironmentReviews/EnvironmentReviewLifecycleService.php
    • apps/platform/app/Models/EnvironmentReview.php
  • Existing operator-facing surfaces likely to consume richer metadata:
    • apps/platform/app/Support/OpsUx/OperationUxPresenter.php
    • apps/platform/app/Support/Ui/GovernanceArtifactTruth/ArtifactTruthPresenter.php
    • apps/platform/app/Support/OperationRunLinks.php
    • apps/platform/app/Filament/Pages/Monitoring/Operations.php
    • apps/platform/app/Filament/Pages/Operations/TenantlessOperationRunViewer.php
    • apps/platform/app/Filament/Resources/OperationRunResource.php
    • apps/platform/app/Filament/Resources/EnvironmentReviewResource.php
    • apps/platform/app/Filament/Widgets/Dashboard/RecentOperations.php
    • apps/platform/app/Filament/System/Pages/Ops/Runs.php
    • apps/platform/app/Support/EnvironmentDashboard/EnvironmentDashboardSummaryBuilder.php
    • apps/platform/lang/en/localization.php
    • apps/platform/lang/de/localization.php
  • Focused tests:
    • apps/platform/tests/Unit/Support/Operations/Reconciliation/
    • apps/platform/tests/Feature/Operations/
    • apps/platform/tests/Feature/EnvironmentReview/
    • apps/platform/tests/Feature/Monitoring/
    • apps/platform/tests/Browser/

Domain And Data Implications

  • operation_runs remains the only persisted run-lifecycle truth. Reconciliation remains a context extension, not a new status model.
  • environment_reviews remains the only domain-truth source for review availability. The adapter proves truth from existing review rows only.
  • The partial unique index environment_reviews_fingerprint_mutable_unique remains the core duplicate-collision constraint. The feature must adapt to it, not replace it.
  • Existing mutable/superseded semantics remain authoritative:
    • mutable: draft, ready, failed
    • historical/terminal lineage: published, archived, superseded
  • No migration is planned. If implementation appears to need one, that is a scope alarm and should stop for review.

UI / Surface Guardrail Plan

  • Guardrail scope: existing operator-facing monitoring surfaces plus existing review-start feedback
  • Affected routes/pages/actions/states/navigation/panel/provider surfaces:
    • /admin/workspaces/{workspace}/operations
    • /admin/workspaces/{workspace}/operations/{run}
    • EnvironmentReviewResource create/refresh notifications and open-link feedback
    • tenant dashboard recent-operations widget
    • system operations list
    • environment dashboard recent/attention summaries
  • No-impact class, if applicable: non-material existing-surface wording/state handling only
  • Native vs custom classification summary: native Filament surfaces plus existing action notifications
  • Shared-family relevance: monitoring-state messaging, reconciliation diagnostics, run-start feedback
  • State layers in scope: page, detail, action feedback
  • Audience modes in scope: operator-MSP, support-platform
  • Decision/diagnostic/raw hierarchy plan: decision-first reconciliation result, diagnostics second, raw evidence third
  • Raw/support gating plan: existing detail/raw context remains secondary and must never become the primary explanation
  • One-primary-action / duplicate-truth control: keep the existing open-run/open-review actions authoritative and avoid a second local “duplicate recovered” surface
  • Handling modes by drift class or surface:
    • review-compose succeeded from domain truth: review-mandatory
    • blocked/attention without safe proof: review-mandatory
    • any raw SQL/constraint leak: hard-stop-candidate
  • Repository-signal treatment: review-mandatory
  • Special surface test profiles: monitoring-state-page, shared-detail-family
  • Required tests or manual smoke: Unit + Feature + PGSQL + one bounded Browser smoke
  • Exception path and spread control: any move toward new operator-center UX, report/evidence adapter copy, or customer-facing surface changes is reject-or-split
  • Active feature PR close-out entry: Guardrail / Smoke Coverage
  • UI/Productization coverage decision: existing surface follow-through only
  • Coverage artifacts to update: none by default; update existing page reports only if final visible hierarchy materially changes
  • No-impact rationale: no route or page identity change
  • Navigation / Filament provider-panel handling: unchanged; provider registration stays in apps/platform/bootstrap/providers.php
  • Screenshot or page-report need: no new page-report identity; one bounded browser smoke screenshot is sufficient only if implementation materially changes visible wording hierarchy

Shared Pattern & System Fit

  • Cross-cutting feature marker: yes
  • Systems touched:
    • scheduled reconciliation path
    • restore-specific adapter reconciliation precedent
    • review-compose start/complete flow
    • monitoring list/detail surfaces
    • review-create notifications
  • Shared abstractions reused:
    • OperationRunService::updateRunWithReconciliation()
    • OperationRun::reconciliation()
    • OperationUxPresenter
    • OperationRunLinks
    • ArtifactTruthPresenter
    • EnvironmentReviewResource::executeCreateReview()
  • New abstraction introduced? why?: yes; one local review-compose decision/result helper is introduced because the current restore-only adapter path is too hard-coded to absorb review fingerprint/scope/supersession proof safely.
  • Why the existing abstraction was sufficient or insufficient: current abstractions already own run lifecycle and generic stale truth, but AdapterRunReconciler currently only knows restore.execute; this slice extends that seam rather than adding a parallel registry.
  • Bounded deviation / spread control: keep the new helper local to adapter reconciliation and explicitly bounded to review-compose plus existing restore context

OperationRun UX Impact

  • Touches OperationRun start/completion/link UX?: yes
  • Central contract reused: current service-owned lifecycle plus current review-create queued-toast/open-run path
  • Delegated UX behaviors:
    • create/refresh keeps the current queued toast and Open operation link
    • adapter completion writes terminal truth through OperationRunService
    • operations list/detail continue to read one reconciliation metadata shape
  • Surface-owned behavior kept local: only review-create body copy and any additional review-available/recovered wording
  • 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 lifecycle truth and EnvironmentReview artifact truth only
  • Neutral platform terms / contracts preserved: operation, reconciliation, review, workspace, managed environment
  • Retained provider-specific semantics and why: none
  • Bounded extraction or follow-up path: none

Authorization, Audit, And Observability

  • Existing workspace-first and managed-environment entitlement checks remain unchanged.
  • Adapter lookup must not widen who can see or use a review; it only determines which local record may prove the run.
  • OperationRunService remains the owner of terminal audit emission.
  • Reconciliation evidence must stay bounded to safe identifiers and state:
    • allowed: workspace ID, managed environment ID, review ID, review status, fingerprint hash, considered review IDs, timestamps
    • forbidden: raw Graph payloads, signed URLs, tokens, raw SQL errors, full snapshot blobs
  • Optional operational logging may emit adapter name, run ID, type, decision, and related review ID only.

Constitution Check

  • Inventory-first: unchanged; EnvironmentReview remains the local artifact truth and still derives from anchored evidence snapshots.
  • Read/write separation: adapter reconciliation mutates only OperationRun, not the provider or remote state.
  • Graph contract path: unchanged; no Graph calls are introduced.
  • Deterministic capabilities: unchanged; current capability checks remain authoritative.
  • Workspace and tenant isolation: unchanged and still mandatory for both runs and reviews.
  • Run observability: strengthened; late or duplicate review-compose work remains visible on OperationRun instead of being silently inferred elsewhere.
  • Proportionality / anti-bloat: pass only if the adapter contract stays narrow and does not become a universal business-reconciliation engine.
  • No premature abstraction: this is allowed only because queue correctness and auditability already justify a typed seam, and the repo already ships one restore-specific adapter precedent.
  • Persisted truth: no new tables or persisted status families.
  • Shared pattern first: reuse current run lifecycle, current monitoring/detail surfaces, and current review-start feedback.
  • Filament v5 / Livewire v4 posture: unchanged; no panel/provider or asset work is allowed.

Test Governance Check

  • Test purpose / classification by changed surface:
    • Unit: reconciliation decisions, supported-type handling, adapter same-scope proof
    • Feature: service/job/idempotency/reconciliation metadata flow
    • Browser: visible operations/review wording smoke
  • Affected validation lanes: fast-feedback, confidence, pgsql, browser
  • Why this lane mix is the narrowest sufficient proof: duplicate fingerprint recovery depends on a PGSQL partial unique index and scope-safe DB truth, while visible monitoring wording needs only one bounded browser smoke rather than a broad productization run.
  • Narrowest proving command(s):
    • cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec359
    • cd apps/platform && ./vendor/bin/sail php vendor/bin/pest -c phpunit.pgsql.xml --filter=Spec359
    • cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec358
    • git diff --check
  • Fixture / helper / factory / seed / context cost risks: reuse existing review/evidence/run factories; do not widen default tenant/workspace setup
  • Expensive defaults or shared helper growth introduced?: none planned
  • Heavy-family additions, promotions, or visibility changes: none
  • Surface-class relief / special coverage rule: monitoring-state-page plus shared-detail-family; one explicit browser smoke only
  • Closing validation and reviewer handoff: reviewers should compare ready-review reuse, ambiguous duplicate collisions, repeated create/refresh triggers, and visible operations detail wording before merge
  • Budget / baseline / trend follow-up: none expected beyond feature-local tests
  • Review-stop questions:
    • Did implementation add a second persisted status shape?
    • Did implementation widen into report/evidence/restore business reconciliation?
    • Can any duplicate/superseded case still remain queued/running forever?
    • Does any visible copy leak SQL/constraint wording?
  • Escalation path: reject-or-split for universal reconciliation scope growth
  • Active feature PR close-out entry: Guardrail / Smoke Coverage
  • Why no dedicated follow-up spec is needed: this slice is already the follow-through over Spec 358 and must remain bounded to review-compose truth only

Implementation Phases

Phase 1 — Lock repo truth and convergence boundaries

  • Reconfirm the current scheduled reconciler, restore-specific adapter reconciler, and review-compose seams.
  • Decide whether the existing restore adapter stays as-is or is bridged behind the new contract without behavioral change.
  • Freeze the current visible operations/review feedback vocabulary that must remain consistent.

Phase 2 — Add the narrow reconciliation contract

  • Extend the existing adapter reconciliation seam with one local review-compose decision/result helper and explicit supported-type handling.
  • Extend or wrap OperationRunService::updateRunWithReconciliation() so richer metadata can be merged idempotently.
  • Keep all persistence shapes unchanged.

Phase 3 — Implement review-compose proof and recovery

  • Add a same-scope review-compose adapter that proves ready/published review truth and fails closed on ambiguity.
  • Integrate duplicate recovery and pre/post compose checks into ComposeEnvironmentReviewJob.
  • Tighten EnvironmentReviewService repeated-trigger behavior so active review truth or active run truth is reused rather than multiplied.

Phase 4 — Retrofit existing operator surfaces

  • Keep current monitoring list/detail surfaces authoritative for reconciled review-compose explanation.
  • Reuse current review-start feedback and current Open operation / View review patterns.
  • Add bounded EN/DE copy only where the existing language is too generic or too technical.

Phase 5 — Validate and hand off

  • Add Unit + Feature + PGSQL + Browser proof.
  • Re-run Spec 358 plus the named review/report regressions.
  • Record final guardrail, smoke, and bounded-scope notes in the feature close-out entry.

Risks and Mitigations

  • Framework creep: mitigate by forbidding new adapter families and by treating restore/report/evidence follow-through as out of scope.
  • Scope-safety mistakes: mitigate with explicit cross-workspace, cross-environment, and wrong-fingerprint negative tests.
  • PGSQL-only blind spots: mitigate with an explicit phpunit.pgsql.xml lane for duplicate-index and lock behavior.
  • Visible copy drift: mitigate by keeping all user-facing wording on current operations/review paths and adding one bounded browser smoke.

Project Structure

Documentation

specs/359-operationrun-reconciliation-adapter-framework-review-compose-adapter/
├── spec.md
├── plan.md
├── tasks.md
└── checklists/
    └── requirements.md

Likely Runtime Structure

apps/platform/app/Services/
├── OperationRunService.php
├── AdapterRunReconciler.php
└── EnvironmentReviews/
    ├── EnvironmentReviewService.php
    ├── EnvironmentReviewComposer.php
    ├── EnvironmentReviewFingerprint.php
    └── EnvironmentReviewLifecycleService.php

apps/platform/app/Jobs/
└── ComposeEnvironmentReviewJob.php

apps/platform/app/Filament/
├── Pages/Monitoring/Operations.php
├── Pages/Operations/TenantlessOperationRunViewer.php
└── Resources/
    ├── OperationRunResource.php
    └── EnvironmentReviewResource.php