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
37 KiB
Feature Specification: OperationRun Reconciliation Adapter Framework & Review Compose Adapter
Feature Branch: 359-operationrun-reconciliation-adapter-framework-review-compose-adapter
Created: 2026-06-06
Status: Draft
Input: User-provided Spec 359 draft, reconciled against current repo truth
Spec Candidate Check (mandatory — SPEC-GATE-001)
- Problem:
environment.review.composeruns can remain queued/running or later appear stale on monitoring surfaces even when matching review truth already exists or a duplicate-fingerprint collision proves the original compose path is no longer the source of truth. - Today's failure: the repo can leave ghost
OperationRunrecords after late compose jobs orenvironment_reviews_fingerprint_mutable_uniquecollisions, forcing operators to reconcile review truth mentally across runs, reviews, and duplicate errors. - User-visible improvement: review-compose work will end in one auditable, scope-safe outcome: matching review reused, still in progress, or attention required, without pretending generic queue truth is business completion.
- Smallest enterprise-capable version: extend the existing
AdapterRunReconcilerseam with one additionalenvironment.review.composepath plus one local decision/result helper that can prove same-scope review truth and complete theOperationRunthrough the existing service-owned lifecycle path. - Explicit non-goals: no new
operation_runsstatus column, no newenvironment_reviewsschema, no report/evidence/sync/backup/alert adapters, no universal operator-center redesign, no destructive cleanup, and no speculative multi-provider framework. - Permanent complexity imported: one bounded review-compose decision/result helper, richer reconciliation metadata, and focused Unit/Feature/Browser/PGSQL coverage.
- Why now: Spec 358 fixed generic queue truth. The remaining repo-real trust gap is domain-truth reconciliation for review composition, especially around duplicate fingerprint collisions and late jobs.
- Why not local: a job-local duplicate catch or a create-review fast-path tweak would not fix late/superseded runs, monitoring detail, audit metadata, or idempotent repeat-trigger behavior consistently.
- Approval class: Core Enterprise
- Red flags triggered: new abstraction and new non-persisted decision/reason family. Defense: queue/job correctness plus auditability justify one bounded second adapter path here, but not a new registry layer.
- Score: Nutzen: 2 | Dringlichkeit: 2 | Scope: 2 | Komplexität: 1 | Produktnähe: 2 | Wiederverwendung: 2 | Gesamt: 11/12
- Decision: approve
Repo Truth Reconciliation
The user draft is directionally correct, but current repo truth narrows the implementation shape:
- The repo already has two reconciliation families:
- scheduled stale-run reconciliation via
App\Services\Operations\OperationLifecycleReconciler - restore-specific adapter reconciliation via
App\Services\AdapterRunReconcilerSpec 359 is therefore a follow-through over existing reconciliation seams, not a greenfield concept.
- scheduled stale-run reconciliation via
App\Services\OperationRunService::updateRunWithReconciliation()andApp\Models\OperationRun::reconciliation()already own current reconciliation writes/reads. Spec 359 must extend or wrap that seam instead of introducing a second persisted reconciliation contract.App\Services\EnvironmentReviews\EnvironmentReviewService::create()already short-circuits to an existing mutable review before dispatch, andApp\Filament\Resources\EnvironmentReviewResourcealready exposesreview_already_available. The remaining gap is late jobs, superseded review lineages, duplicate fingerprint collisions, and staleOperationRunrecords after runtime drift.EnvironmentReviewmutability is already constrained by the partial unique indexenvironment_reviews_fingerprint_mutable_uniqueondraft|ready|failed. No new review state or new schema is justified for this slice.- Current monitoring surfaces already render generic
Automatically reconciledlifecycle language. Spec 359 may add review-compose-specific explanation keys, but it must stay inside the current monitoring/detail families instead of inventing a second operator language. docs/product/spec-candidates.mdcurrently recordsno safe automatic next-best-prep target. This package is therefore an explicit manual promotion from the user and current repo truth, not an automatic queue selection.- Existing restore reconciliation must not be broken. Implementation may either preserve the current restore-specific reconciler or bridge it behind the new contract, but restore business logic expansion remains out of scope.
Spec Scope Fields (mandatory)
- Scope: workspace, tenant, canonical-view
- Primary Routes:
/admin/workspaces/{workspace}/operations/admin/workspaces/{workspace}/operations/{run}- existing environment-scoped review create/refresh entry points via
App\Filament\Resources\EnvironmentReviewResource
- Data Ownership:
operation_runsremain the only persisted lifecycle/reconciliation owner for run stateenvironment_reviewsremain the only domain-truth source for review availability- related
environment_review_sectionsandreview_packsare read-side context only when the chosen review already proves usable truth
- RBAC:
- existing workspace and managed-environment entitlement checks remain authoritative
- non-members remain
404 - review creation/refresh remains capability-gated by
Capabilities::ENVIRONMENT_REVIEW_MANAGE - operation-run inspection remains governed by current workspace-first
OperationRunaccess boundaries
For canonical-view specs, the spec MUST define:
- Default filter behavior when tenant-context is active: the operations hub stays workspace-scoped with explicit environment filters. Adapter decisions must use the run's recorded workspace/environment scope and must not infer broader tenant context from session, remembered tenant, or current page state.
- Explicit entitlement checks preventing cross-tenant leakage: no adapter may reconcile to an
EnvironmentReviewoutside the run's workspace and managed environment. Any reused review link or related-model metadata must stay current-scope only.
UI Surface Impact (mandatory — UI-COV-001)
- No UI surface impact
- Existing page changed
- New page/route added
- Navigation changed
- Filament panel/provider surface changed
- New modal/drawer/wizard/action added
- New table/form/state added
- Customer-facing surface changed
- Dangerous action changed
- Status/evidence/review presentation changed
- Workspace/environment context presentation changed
UI/Productization Coverage (mandatory when UI Surface Impact is not "No UI surface impact")
- Route/page/surface:
- workspace operations hub (
App\Filament\Pages\Monitoring\Operations) - canonical run detail (
App\Filament\Pages\Operations\TenantlessOperationRunViewer) - existing review-create/review-refresh feedback path in
App\Filament\Resources\EnvironmentReviewResource - tenant dashboard recent-operations widget (
App\Filament\Widgets\Dashboard\RecentOperations) - system operations list (
App\Filament\System\Pages\Ops\Runs) - environment dashboard recent/attention summaries (
App\Support\EnvironmentDashboard\EnvironmentDashboardSummaryBuilder)
- workspace operations hub (
- Current or new page archetype: existing monitoring family plus existing review-initiation action feedback
- Design depth: Domain Pattern Surface
- Repo-truth level: repo-verified
- Existing pattern reused: current monitoring reconciliation banners, current
review_already_available/open_operationfeedback, current review-output action affordances - New pattern required: none; extend existing monitoring and review-start feedback only
- Screenshot required: no; one bounded browser smoke is sufficient unless implementation proves a materially new visible hierarchy
- Page audit required: no new page-report identity is required; existing anchors remain
docs/ui-ux-enterprise-audit/page-reports/ui-003-operations.md,ui-011-reviews.md, andui-040-environment-review-detail.md - Customer-safe review required: no; changed copy remains operator-facing
- Dangerous-action review required: no; no destructive or high-risk confirmation flow changes
- Coverage files updated or explicitly not needed:
docs/ui-ux-enterprise-audit/route-inventory.mddocs/ui-ux-enterprise-audit/design-coverage-matrix.mddocs/ui-ux-enterprise-audit/page-reports/...docs/ui-ux-enterprise-audit/strategic-surfaces.mddocs/ui-ux-enterprise-audit/grouped-follow-up-candidates.mddocs/ui-ux-enterprise-audit/unresolved-pages.mdN/A - no reachable UI surface impact
- No-impact rationale when applicable: N/A
Cross-Cutting / Shared Pattern Reuse (mandatory)
- Cross-cutting feature?: yes
- Interaction class(es): status messaging, operation lifecycle explanation, action links, queued/already-available feedback, reconciliation diagnostics
- Systems touched:
OperationRunServicereconciliation metadataOperationRun::reconciliation()- current monitoring list/detail presenters
EnvironmentReviewResourcecreate/refresh feedback- shared review artifact and link readers
- current localization families under
localization.reviewand operation-run detail copy
- Existing pattern(s) to extend: current reconciliation metadata path, current operations monitoring/detail language, current
review_already_availablenotification pattern, and current shared review artifact/link resolution - Shared contract / presenter / builder / renderer to reuse:
OperationRunService::updateRunWithReconciliation(),OperationRun::reconciliation(),OperationUxPresenter,OperationRunLinks,ArtifactTruthPresenter, and existingEnvironmentReviewResource::executeCreateReview()affordances - Why the existing shared path is sufficient or insufficient: existing shared paths already own run status, links, and generic stale truth, but the restore-specific reconciler is hard-coded and cannot safely prove review fingerprint/scope/supersession truth without new feature-local branching.
- Allowed deviation and why: none by default; any new adapter copy or metadata must feed the existing presenter/resource seams rather than local exception prose in jobs or pages.
- Consistency impact: the same review-compose reconciliation outcome must read consistently on start feedback, operations list/detail, and technical diagnostics.
- Review focus: no parallel local reconciliation language, no direct model mutation outside services, and no raw duplicate-key/SQL wording leaking into customer-visible or operator-primary copy.
OperationRun UX Impact (mandatory)
- Touches OperationRun start/completion/link UX?: yes
- Shared OperationRun UX contract/layer reused: current
OperationRunService,OperationRunLinks,OperationUxPresenter, and existing review-create feedback path - Delegated start/completion UX behaviors:
- review creation keeps the current queued toast plus
Open operationlink - adapter reconciliation writes terminal truth through the current service-owned lifecycle path
- operations list/detail continue to consume the canonical
OperationRunreconciliation metadata
- review creation keeps the current queued toast plus
- Local surface-owned behavior that remains: the review-create form input and any review-specific success/blocked body copy
- Queued DB-notification policy: unchanged; remain on the current shared contract
- Terminal notification path: central lifecycle mechanism remains authoritative
- Exception required?: none
Provider Boundary / Platform Core Check (mandatory)
- Shared provider/platform boundary touched?: no
- Boundary classification: N/A
- Seams affected: N/A
- Neutral platform terms preserved or introduced:
operation,reconciliation,review,workspace,managed environment,artifact truth - Provider-specific semantics retained and why: none
- Why this does not deepen provider coupling accidentally: the adapter proves platform-owned
EnvironmentReviewtruth from existing local records only; it does not add new Microsoft- or Graph-shaped platform-core semantics. - Follow-up path: none
UI / Surface Guardrail Impact (mandatory)
| Surface / Change | Operator-facing surface change? | Native vs Custom | Shared-Family Relevance | State Layers Touched | Exception Needed? | Low-Impact / N/A Note |
|---|---|---|---|---|---|---|
| Operations hub reconciliation wording | yes | Native Filament page | shared monitoring family | page, table row | no | no new route or action family |
| Tenantless run detail reconciliation explanation | yes | Native Filament page | shared monitoring detail family | detail | no | explanation only; diagnostics remain secondary |
| Review create / refresh feedback | yes | Native Filament action + notification | shared run-start feedback family | action feedback | no | reuses existing notification/action pattern |
Decision-First Surface Role (mandatory)
| Surface | Decision Role | Human-in-the-loop Moment | Immediately Visible for First Decision | On-Demand Detail / Evidence | Why This Is Primary or Why Not | Workflow Alignment | Attention-load Reduction |
|---|---|---|---|---|---|---|---|
| Operations hub | Primary Decision Surface | Decide whether a stale review-compose run is actually completed, blocked, or needs attention | lifecycle state, review-availability result, one open action | full diagnostics and related review evidence | primary because it is the canonical operations triage queue | aligns to current monitoring workflow | removes mental cross-checking across review and run surfaces |
| Tenantless run detail | Tertiary Evidence / Diagnostics Surface | Confirm why the run was reconciled or blocked before reading raw context | one reconciled/blocked explanation with related review hint | raw context, evidence, lineage, failures | tertiary because the run is already selected | preserves current detail role | removes duplicate/raw-first explanations |
| Review create / refresh feedback | Secondary Context Surface | Decide whether to open the reused review, open the run, or do nothing | already-available vs queued background feedback | monitoring detail or review detail after click | secondary because it supports, not owns, the workflow | follows existing review-start pattern | avoids double-dispatch and duplicate click confusion |
Audience-Aware Disclosure (mandatory)
| Surface | Audience Modes In Scope | Decision-First Default-Visible Content | Operator Diagnostics | Support / Raw Evidence | One Dominant Next Action | Hidden / Gated By Default | Duplicate-Truth Prevention |
|---|---|---|---|---|---|---|---|
| Operations hub | operator-MSP, support-platform | reconciled/blocked review-compose summary | related review ID and reason code secondarily | raw payloads remain on detail | Open operation |
raw SQL/constraint detail stays hidden | list row states the result once |
| Tenantless run detail | operator-MSP, support-platform | calm reconciliation result and related review truth | evidence, related review metadata, reason code | low-level payloads after summary | existing back/open actions | raw duplicate error bodies stay secondary | banner and diagnostics must not restate conflicting truth |
| Review create / refresh feedback | operator-MSP | review reused vs background compose still running | none beyond open link | raw detail stays on operations/review pages | View review or Open operation |
technical duplicate details hidden | reuse one notification family, not separate local wording |
UI/UX Surface Classification (mandatory)
| Surface | Action Surface Class | Surface Type | Likely Next Operator Action | Primary Inspect/Open Model | Row Click | Secondary Actions Placement | Destructive Actions Placement | Canonical Collection Route | Canonical Detail Route | Scope Signals | Canonical Noun | Critical Truth Visible by Default | Exception Type / Justification |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Operations hub | List / Table / Monitoring | Read-only monitoring registry | open the run that now needs review or no action | full-row open | required | existing table controls only | none | /admin/workspaces/{workspace}/operations |
/admin/workspaces/{workspace}/operations/{run} |
workspace scope plus explicit filters | Operation run | whether review truth already exists or still needs attention | none |
| Tenantless run detail | Record / Detail / Monitoring | Diagnostics-first detail | confirm the reconciled or blocked explanation | canonical detail page | N/A | existing header links only | none | /admin/workspaces/{workspace}/operations |
/admin/workspaces/{workspace}/operations/{run} |
workspace scope and entitled environment | Operation run | related review truth before raw diagnostics | none |
| Review create / refresh feedback | Action Feedback | Action result surface | open the review or open the run | action notification link | N/A | existing notification action set | none | current environment review surface | linked review or operation detail | tenant context on the current page | Review composition | already available vs queued/recovered state | none |
Operator Surface Contract (mandatory)
| Surface | Primary Persona | Decision / Operator Action Supported | Surface Type | Primary Operator Question | Default-visible Information | Diagnostics-only Information | Status Dimensions Used | Mutation Scope | Primary Actions | Dangerous Actions |
|---|---|---|---|---|---|---|---|---|---|---|
| Operations hub | workspace operator | decide whether a review-compose run is done, blocked, or needs follow-up | monitoring registry | Do I still need to wait for compose, or is a matching review already the truth? | lifecycle outcome, related review availability, one open action | raw evidence, reason ownership, full context | lifecycle, reconciliation truth, artifact availability | none | open row | none |
| Tenantless run detail | workspace operator | confirm the exact reconciliation decision before technical follow-up | detail surface | Why did this run complete from review truth or remain blocked? | top-level reconciled/blocked explanation, related review summary | evidence array, considered review IDs, failures | lifecycle, reconciliation truth, artifact readiness | none | existing navigation links | none |
Proportionality Review (mandatory when structural complexity is introduced)
- New source of truth?: no
- New persisted entity/table/artifact?: no
- New abstraction?: yes
- New enum/state/reason family?: yes, bounded non-persisted reconciliation decision/reason modeling
- New cross-domain UI framework/taxonomy?: no
- Current operator problem: current runtime can prove generic stale truth but cannot safely prove that review-compose business truth already exists, so ghost runs survive duplicate collisions and late jobs.
- Existing structure is insufficient because: the current scheduled reconciler only fails stale runs generically, and the current restore-only adapter reconciler is hard-coded to
restore.execute; neither can prove review fingerprint, scope, mutable/superseded lineage, or safe auto-success for review composition. - Narrowest correct implementation: extend the existing adapter reconciliation seam with one local review-compose decision/result helper and one review-compose path that reuses existing
OperationRunServicereconciliation writes. - Ownership cost: one new bounded support layer, richer reconciliation metadata, and targeted test coverage across unit, feature, PGSQL, and one bounded browser smoke.
- Alternative intentionally rejected: job-local duplicate catch plus ad hoc review lookups was rejected because it would duplicate logic across job, service, and monitoring surfaces and would not produce one audit-visible reconciliation contract.
- Release truth: current-release queue correctness and auditability, not speculative future multi-artifact preparation.
Compatibility posture
This feature assumes the current pre-production environment. Backward-compatibility aliases or migration shims are not justified unless implementation proves the existing restore adapter needs a bounded bridge to the new contract. No legacy write path should be added for historical rows.
Testing / Lane / Runtime Impact (mandatory for runtime behavior changes)
- Test purpose / classification: Unit + Feature + Browser
- Validation lane(s): fast-feedback, confidence, pgsql, browser
- Why this classification and these lanes are sufficient: Unit coverage proves result/supported-type/adapter decisions; Feature coverage proves service/job/idempotency behavior; the PGSQL lane is required for partial unique-index and locking truth around duplicate fingerprint recovery; one bounded Browser smoke proves the visible operations/review wording without widening into broad UI productization.
- New or expanded test families:
apps/platform/tests/Unit/Support/Operations/Reconciliation/Spec359ReconciliationResultTest.phpapps/platform/tests/Unit/Support/Operations/Reconciliation/Spec359AdapterRunReconcilerSupportedTypesTest.phpapps/platform/tests/Unit/Support/Operations/Reconciliation/Spec359EnvironmentReviewComposeAdapterTest.phpapps/platform/tests/Feature/Operations/Spec359OperationRunAdapterReconciliationTest.phpapps/platform/tests/Feature/EnvironmentReview/Spec359ReviewComposeReconciliationTest.phpapps/platform/tests/Feature/EnvironmentReview/Spec359ReviewComposeIdempotencyTest.phpapps/platform/tests/Browser/Spec359ReviewComposeReconciliationSmokeTest.php
- Fixture / helper cost impact: low to moderate; reuse existing workspace/tenant/review factories and existing operations monitoring fixtures
- Heavy-family visibility / justification: no heavy-governance family added; the browser addition is explicit and bounded to one smoke file
- Special surface test profile: monitoring-state-page plus shared-detail-family
- Standard-native relief or required special coverage: required special coverage for PGSQL duplicate-index proof and one bounded browser smoke; otherwise ordinary Unit/Feature proof is sufficient
- Reviewer handoff: reviewers must confirm that duplicate or superseded review-compose cases end as succeeded/blocked/attention deterministically, never as endless queued/running ghosts, and that customer-facing or operator-primary copy never leaks SQL/constraint details
- Budget / baseline / trend impact: minor feature-local growth only
- Escalation needed:
reject-or-splitif implementation broadens into report/evidence/restore adapter scope, new persisted status, or a universal business reconciliation engine - Active feature PR close-out entry: Guardrail / Smoke Coverage
- Planned validation commands:
cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec359cd apps/platform && ./vendor/bin/sail php vendor/bin/pest -c phpunit.pgsql.xml --filter=Spec359cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec358cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/CustomerReviewWorkspaceSmokeTest.phpcd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Spec357ReportProfilesSmokeTest.phpcd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/ReviewPack/Spec357RenderedReportProfileTest.phpcd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/ReviewPack/ReviewPackDownloadTest.phpcd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/ReviewPack/EnvironmentReviewDerivedReviewPackTest.phpcd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/ReviewPack/EnvironmentReviewExecutivePackTest.phpcd apps/platform && ./vendor/bin/sail bin pint --dirty --format agentgit diff --check
User Scenarios & Testing (mandatory)
User Story 1 - Reuse proven review truth for a stale review-compose run (Priority: P1)
As an operator, I need a stale or late environment.review.compose run to complete from existing review truth when a same-scope ready or published review already proves the result is available.
Why this priority: this is the primary trust gap exposed after Spec 358 removed contradictory generic queue wording.
Independent Test: seed a queued or running review-compose run plus a same-scope ready review and verify that the adapter completes the run as succeeded with audit-visible reconciliation metadata.
Acceptance Scenarios:
- Given a queued or running
environment.review.composerun and a same-workspace, same-environment, same-fingerprint ready review, When adapter reconciliation runs, Then the run becomescompleted/succeededwith related review metadata and no new review is created. - Given a matching published review already exists for the same scope, When the adapter evaluates the run, Then the run may complete from that publishable truth without reopening or mutating the published review.
User Story 2 - Recover duplicate fingerprint and superseded review lineages deterministically (Priority: P1)
As an operator, I need duplicate fingerprint collisions and late jobs against older review rows to end in a deterministic succeeded/blocked/attention outcome instead of an endless active run.
Why this priority: duplicate fingerprint recovery is the observed runtime failure that creates ghost runs and unsafe manual interpretation.
Independent Test: simulate duplicate-key and superseded-successor cases in PGSQL-aware tests and verify that recoverable cases complete from matching review truth while ambiguous or incomplete cases fail closed.
Acceptance Scenarios:
- Given compose attempts to create a mutable review and the DB raises the mutable fingerprint unique constraint while a matching ready successor review already exists, When recovery runs, Then the
OperationRunbecomescompleted/succeededfrom adapter truth. - Given a late job points at an older review while a matching successor review is still draft/failed/in-progress, When the adapter evaluates the lineage, Then the run becomes blocked or attention-required rather than falsely succeeded.
User Story 3 - Keep review-start dispatch idempotent for repeated triggers (Priority: P2)
As an operator, I need repeated create/refresh clicks for the same review fingerprint to reuse the correct review or active run instead of creating competing mutable reviews and duplicate run noise.
Why this priority: repeat-trigger safety is the operator-facing entry point for avoiding the runtime collision in the first place.
Independent Test: trigger the same review composition rapidly and verify that only one active mutable review truth survives for the fingerprint while later requests reuse existing truth or surface the correct active run.
Acceptance Scenarios:
- Given a matching mutable review already exists for the fingerprint, When create/refresh is triggered again, Then the existing review is reused and the current already-available feedback remains truthful.
- Given an active compose run already exists for the fingerprint, When create/refresh is triggered again, Then the operator is directed to the existing run or review instead of silently creating another conflicting path.
User Story 4 - Show calm review-compose reconciliation language on existing operations surfaces (Priority: P3)
As an operator, I need existing monitoring and review feedback surfaces to explain adapter-based review reconciliation without surfacing raw DB or constraint text.
Why this priority: the underlying correctness work still needs one calm visible explanation path.
Independent Test: run the bounded browser smoke and confirm that reconciled review-compose runs show review-available or attention wording instead of generic wait-state copy or raw SQL errors.
Acceptance Scenarios:
- Given a review-compose run was completed from adapter truth, When the operations hub or run detail renders it, Then the visible explanation states that a matching review/result was already available.
- Given a duplicate or ambiguous compose case cannot be auto-completed safely, When the visible surfaces render it, Then the copy asks for attention without showing
SQLSTATE,duplicate key, or the constraint name.
Edge Cases
- Missing
workspace_id,managed_environment_id,review_fingerprint, or snapshot context on the run. - A matching fingerprint exists in another workspace or another managed environment.
- Multiple mutable reviews match the same scope and fingerprint.
- A successor review exists through
superseded_by_review_idbut is not yet ready/published. - The run is already terminal and already carries reconciliation metadata.
- Duplicate-key recovery happens after the job already marked the run
running. - A review is published and a later late job tries to recompose the superseded lineage.
- The existing restore adapter path remains present and must not be broken by the local review-compose seam extension.
Requirements (mandatory)
- FR-359-001: The repo must add one bounded review-compose business-truth reconciliation path by extending the existing adapter reconciliation seam without changing the persisted
OperationRunstatus/outcome schema. - FR-359-002: The seam must recognize supported types explicitly and treat unsupported types safely as unsupported/no-op without introducing a generic registry/resolver layer.
- FR-359-003: A serializable reconciliation result object must distinguish at least
reconciled_succeeded,not_reconciled,blocked,attention_required,failed_unrecoverable, andunsupported. - FR-359-004: Reconciliation results must carry reason code, message key or copy mapping hint, evidence payload, related model metadata, and an explicit
safeForAutoCompletionsignal. - FR-359-005:
OperationRunServicemust remain the only owner of terminal run reconciliation writes. Adapter-driven completion may extend the existing reconciliation seam or wrap it, but must not bypass service-owned lifecycle updates. - FR-359-006: Reconciliation metadata must extend the current
context.reconciliationstructure with source, adapter, decision, reason code, previous status/outcome, timestamp, and related review metadata sufficient for shared artifact/link readers to resolve the canonical review even whenoperation_run_idstill points at an older or losing review row, plus bounded evidence. - FR-359-007: No new
operation_runsstatus column,reconciledboolean, or newenvironment_reviewsstate family may be introduced. - FR-359-008: A review-compose adapter must support only
environment.review.composeand must prove same-scope review truth from existingEnvironmentReviewrecords. - FR-359-009: Same-scope review truth must validate workspace, managed environment, fingerprint, and any explicit review lineage context before reuse.
- FR-359-010: A same-scope ready or published review may reconcile the run to
completed/succeededwhen the adapter can prove the review is usable and unambiguous. - FR-359-011: Missing scope, cross-scope candidates, ambiguous matches, non-ready successors, or unknown review state must fail closed as
not_reconciled,blocked, orattention_required, never as auto-success. - FR-359-012: Superseded or successor review cases must be handled deterministically. A ready successor may prove success; an in-progress or failed successor may only block or require attention.
- FR-359-013:
ComposeEnvironmentReviewJobmust use the adapter seam before or after duplicate-key recovery so recoverable duplicate fingerprint cases do not leave queued/running ghosts. - FR-359-014:
EnvironmentReviewServicemust remain idempotent for repeated create/refresh triggers and must consider existing mutable review truth plus existing active compose runs before dispatching new work. - FR-359-015: Existing restore-specific adapter reconciliation may be preserved or minimally bridged, but Spec 359 must not expand restore, report, evidence, sync, backup, or alert business reconciliation behavior.
- FR-359-016: Operator-facing copy for adapter-reconciled review-compose runs must stay calm and audit-friendly and must not surface raw SQL, duplicate-key, constraint-name, or worker-crash wording.
- FR-359-017: Localization must extend existing EN/DE review/operations copy families rather than inventing a new translation namespace unless repo truth clearly prefers one.
- FR-359-018: The adapter must not mutate unrelated domain records, delete rows, or perform destructive cleanup.
Non-Functional Requirements
- NFR-359-001 Auditability: every adapter-driven reconciliation must be visible in
context.reconciliationand in the terminal audit path. - NFR-359-002 Fail closed: ambiguous or missing proof must never auto-complete as succeeded.
- NFR-359-003 Idempotence: repeating adapter evaluation on the same run must not duplicate context spirals or create new domain side effects.
- NFR-359-004 Minimal invasiveness: reuse current
OperationRunService, current review-compose service/job seams, and current monitoring presenters wherever possible. - NFR-359-005 Livewire v4 posture: no Livewire v3 APIs or panel-provider drift.
- NFR-359-006 No asset/panel change: no new Filament assets, no provider registration move, no new panel path.
Out Of Scope
- Report, evidence snapshot, review-pack, sync, backup, restore, or alert-delivery adapter expansion
- New queue table/job family/schema redesign
- New
OperationRunstatus/outcome persistence shape - Destructive cleanup, delete, purge, or hide flows
- Customer-facing review portal/productization changes
- New PDF or report rendering architecture
- New provider or Graph abstraction work
Acceptance Criteria
- AC-359-001: Existing adapter reconciliation supports both
restore.executeandenvironment.review.composewithout adding a new generic registry layer. - AC-359-002:
environment.review.composeresolves to a dedicated adapter and unknown types remain unsupported safely. - AC-359-003: A same-scope ready or published review can reconcile a queued/running review-compose run to
completed/succeeded. - AC-359-004: Cross-workspace, cross-environment, or wrong-fingerprint reviews are never reused.
- AC-359-005: Duplicate fingerprint collisions end as recovered success, blocked/attention, or failed-unrecoverable, but never as queued/running forever.
- AC-359-006: Superseded review lineages are handled deterministically and fail closed when successor truth is incomplete or ambiguous.
- AC-359-007:
context.reconciliationrecords source, adapter, decision, reason code, previous status/outcome, timestamp, related review metadata, and bounded evidence sufficient for shared review link resolution. - AC-359-008: Existing restore-specific reconciliation behavior is not broken by the new contract shape.
- AC-359-009: No new persistence shape or status column is introduced.
- AC-359-010: Existing operations/review surfaces explain adapter-reconciled review-compose outcomes without raw SQL/constraint wording and can resolve the winning review from reconciliation metadata when needed.
- AC-359-011: Repeated adapter evaluation and repeated review-start triggers remain idempotent.
Success Criteria
- Operators no longer need to infer review truth manually from a stale review-compose run plus a separate ready review row.
- Duplicate fingerprint cases are either safely recovered or explicitly blocked/failed with audit-visible metadata.
- Review-compose reconciliation remains bounded to current repo truth and does not silently widen into universal business completion.
Risks
- The existing restore adapter precedent could tempt a too-broad framework refactor.
- Review lineage rules can overfit mutable vs superseded semantics if the adapter tries to solve report/evidence truth too early.
- PGSQL-only duplicate/locking behavior could be under-tested if the implementation relies only on default fast-feedback coverage.
Assumptions
EnvironmentReviewStatus::ReadyandPublishedare the only review states that may prove immediately usable review truth for this slice.- Existing
workspace_id,managed_environment_id,review_fingerprint, and review lineage metadata are sufficient to prove scope-safe matching without a schema change. - The current
EnvironmentReviewResourcecreate/refresh notification pattern is the correct UX seam for already-available versus queued background work.
Open Questions
- Non-blocking implementation choice only: keep the current restore-specific reconciler as-is or bridge it behind the new contract, provided no restore business behavior changes and no second operator language is introduced.