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
274 lines
18 KiB
Markdown
274 lines
18 KiB
Markdown
# 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
|
|
|
|
```text
|
|
specs/359-operationrun-reconciliation-adapter-framework-review-compose-adapter/
|
|
├── spec.md
|
|
├── plan.md
|
|
├── tasks.md
|
|
└── checklists/
|
|
└── requirements.md
|
|
```
|
|
|
|
### Likely Runtime Structure
|
|
|
|
```text
|
|
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
|
|
```
|