TenantAtlas/specs/360-operationrun-canonical-cutover-cleanup/spec.md
ahmido 840c9bd28d refactor: rename ManagedEnvironment context badge to Environment context (#431)
Renames ManagedEnvironment context badge to Environment context as requested.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #431
2026-06-06 20:30:26 +00:00

38 KiB

Feature Specification: OperationRun Canonical Cutover Cleanup

Feature Branch: 360-operationrun-canonical-cutover-cleanup
Created: 2026-06-06
Status: Draft
Input: User-provided Spec 360 draft, reconciled against current repo truth after merged Spec 359

Spec Candidate Check (mandatory — SPEC-GATE-001)

  • Problem: the merged Spec 359 runtime works, but the OperationRun reconciliation foundation is still split across a growing type-match reconciler, job-local review-compose recovery logic, heterogeneous failed-job correlation, broad legacy operation-type aliases, and reader fallbacks that still treat historical linkage as first-class truth.
  • Today's failure: the repo can reconcile review-compose functionally, yet future adapter work would still deepen the wrong seams: AdapterRunReconciler grows by type matching, ComposeEnvironmentReviewJob still owns business-specific fallback behavior, new queued runs do not record a canonical dispatch contract, and some readers still fall back to legacy linkage rather than canonical reconciliation metadata.
  • User-visible improvement: review-compose, restore, and future adapter-backed runs can rely on one canonical reconciliation extension point, one service-owned write seam, one dispatch/correlation contract, and one operator-facing related-artifact truth path instead of parallel heuristics.
  • Smallest enterprise-capable version: consolidate the current restore and review-compose paths behind one canonical adapter extension seam, move remaining review-compose reconciliation decisions out of the job, add canonical context.dispatch, align queue/failure correlation, cut back legacy operation-type alias reads/writes, and update existing operations/readers without adding new product features.
  • Explicit non-goals: no new persisted entity, no new OperationRun status or outcome family, no report/evidence/sync/backup/restore business adapter expansion, no repo-wide queue identity or correlation cleanup beyond the current OperationRun dispatch/failure-bridge path, no new queue console, no panel/provider changes, no asset changes, no destructive cleanup actions, and no compatibility layer for pre-production historical data.
  • Permanent complexity imported: one bounded adapter contract/registry-orchestrator seam over two real concrete cases, one shared job-correlation contract, one canonical dispatch metadata shape, and focused tests that lock the cutover in place.
  • Why now: Spec 359 is merged on platform-dev (3a750726) and proved the domain behavior, but further adapter work would multiply drift unless the foundation is canonicalized now.
  • Why not local: fixing only ComposeEnvironmentReviewJob, only OperationCatalog, or only reader fallbacks would leave the other seams inconsistent and would entrench a second generation of compatibility logic right before Spec 361.
  • Approval class: Cleanup
  • Red flags triggered: new abstraction, shared cross-cutting run semantics, and canonicalization work that spans multiple existing files. Defense: the repo already has two real adapter cases (restore.execute and environment.review.compose), and queue correctness plus audit-visible operator truth justify one bounded consolidation instead of continued growth by exceptions.
  • Score: Nutzen: 2 | Dringlichkeit: 2 | Scope: 2 | Komplexität: 1 | Produktnähe: 1 | Wiederverwendung: 2 | Gesamt: 10/12
  • Decision: approve

Repo Truth Reconciliation

The user draft is directionally correct, but current repo truth sharpens the exact scope:

  1. platform-dev already contains merged Spec 359 runtime changes at 3a750726 feat: implement review compose reconciliation adapter (spec 359) (#430). Spec 360 is therefore a post-merge cleanup and cutover package, not a refresh of an unmerged branch.
  2. docs/product/spec-candidates.md still says there is no safe automatic next-best-prep target. This package is a direct user-provided manual promotion, not an auto-selected candidate.
  3. The repo already has two real adapter-backed reconciliation cases in App\Services\AdapterRunReconciler: restore.execute and environment.review.compose. That satisfies the constitution threshold for extracting one bounded canonical extension seam now.
  4. App\Services\OperationRunService::updateRunWithReconciliation() already owns canonical reconciliation writes, but dispatchOrFail() does not yet persist canonical dispatch metadata.
  5. App\Jobs\Middleware\TrackOperationRun and App\Jobs\Concerns\BridgesFailedOperationRun still use different correlation heuristics (operationRun object vs mixed operationRunId / bulkRunId / runId property scanning).
  6. App\Support\OperationCatalog still carries broad read-side legacy alias inventory, while App\Support\OperationRunType and Database\Factories\OperationRunFactory already show that most current writers can emit canonical values directly.
  7. specs/355-platform-sellable-smoke-matrix/ contains historical roadmap references to a different placeholder Spec 360, but no specs/360-* package exists. Those old references are context only and do not block using 360 for this user-requested cutover package.

Spec Scope Fields (mandatory)

  • Scope: workspace, tenant, canonical-view
  • Primary Routes:
    • /admin/workspaces/{workspace}/operations
    • /admin/workspaces/{workspace}/operations/{run}
    • existing environment-scoped review start or refresh entry points in App\Filament\Resources\EnvironmentReviewResource
  • Data Ownership:
    • operation_runs remain the only persisted execution and reconciliation truth for run lifecycle
    • context.reconciliation remains the canonical reconciliation metadata container
    • context.dispatch becomes the canonical dispatch and correlation metadata container
    • environment_reviews, review_packs, evidence_snapshots, and restore records remain domain truth only; no new persisted adapter registry or migration is introduced
  • RBAC:
    • existing workspace-first OperationRun access rules remain authoritative
    • non-members and out-of-scope tenant viewers remain 404
    • review initiation remains governed by the current review capabilities
    • this spec changes orchestration, correlation, metadata, and operator explanation only; it does not widen any surface or capability

For canonical-view specs, the spec MUST define:

  • Default filter behavior when tenant-context is active: the operations hub remains workspace-scoped with explicit environment filters. This spec must not silently reintroduce tenant-context ownership into the canonical operations route or into adapter selection.
  • Explicit entitlement checks preventing cross-tenant leakage: adapter resolution, related-model links, and artifact truth readers must use the run's stored workspace and managed-environment scope. No reader may resolve or reveal an artifact outside the run's authorized scope.

UI Surface Impact (mandatory — UI-COV-001)

Does this spec add, remove, rename, or materially change any reachable UI surface?

  • 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)
    • shared implementation seam only: App\Filament\Resources\OperationRunResource
    • existing review start feedback path in App\Filament\Resources\EnvironmentReviewResource
  • Current or new page archetype: existing monitoring/detail family and existing review-start action feedback
  • Design depth: Domain Pattern Surface
  • Repo-truth level: repo-verified
  • Existing pattern reused: current operations monitoring family, current review-start feedback family, current artifact-truth/read-side link patterns
  • New pattern required: none; this is a canonicalization follow-through inside existing families
  • 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 monitoring and review anchors remain sufficient
  • Customer-safe review required: no; touched copy remains operator-facing
  • Dangerous-action review required: no; no new destructive or high-risk execution action is introduced
  • Coverage files updated or explicitly not needed:
    • docs/ui-ux-enterprise-audit/route-inventory.md
    • docs/ui-ux-enterprise-audit/design-coverage-matrix.md
    • docs/ui-ux-enterprise-audit/page-reports/...
    • docs/ui-ux-enterprise-audit/strategic-surfaces.md
    • docs/ui-ux-enterprise-audit/grouped-follow-up-candidates.md
    • docs/ui-ux-enterprise-audit/unresolved-pages.md
    • N/A - no reachable new UI surface; existing monitoring/review families only
  • No-impact rationale when applicable: no new surface family, route, or navigation entry is created; the work stays inside existing operations and review-start patterns

Cross-Cutting / Shared Pattern Reuse (mandatory when the feature touches notifications, status messaging, action links, header actions, dashboard signals/cards, alerts, navigation entry points, evidence/report viewers, or any other existing shared operator interaction family; otherwise write N/A - no shared interaction family touched)

  • Cross-cutting feature?: yes
  • Interaction class(es): status messaging, action links, reconciliation metadata, monitoring/detail explanation, artifact-viewer linkage, queued-run correlation
  • Systems touched:
    • App\Services\OperationRunService
    • App\Services\AdapterRunReconciler
    • App\Support\Operations\Reconciliation\EnvironmentReviewComposeDecision
    • App\Support\OperationRunLinks
    • App\Support\Ui\GovernanceArtifactTruth\ArtifactTruthPresenter
    • App\Support\OperationCatalog
    • App\Jobs\Middleware\TrackOperationRun
    • App\Jobs\Concerns\BridgesFailedOperationRun
  • Existing pattern(s) to extend: existing OperationRunService lifecycle ownership, existing operations monitoring/detail family, existing review-start feedback family, and existing artifact-truth/read-side helpers
  • Shared contract / presenter / builder / renderer to reuse: OperationRunService, OperationRun::reconciliation(), current monitoring/detail presenters, OperationRunLinks, ArtifactTruthPresenter, and the current review-start notification family
  • Why the existing shared path is sufficient or insufficient: the shared write seam already exists, but the repo still lacks a canonical adapter registration contract, a canonical queued dispatch metadata path, and a shared correlation resolver between middleware and failed-job bridging.
  • Allowed deviation and why: one bounded adapter contract/registry or orchestrator abstraction plus one bounded job-correlation resolver are allowed because two concrete adapter cases already exist and the current heuristics are materially inconsistent.
  • Consistency impact: reconciliation outcome, dispatch truth, link resolution, operation labels, and failed-job correlation must stay consistent across jobs, services, operations surfaces, and artifact readers.
  • Review focus: no second reconciliation write path, no new job-local review business logic, no broadened legacy alias protection, and no parallel reader fallback language.
  • Touches OperationRun start/completion/link UX?: yes
  • Shared OperationRun UX contract/layer reused: OperationRunService, OperationUxPresenter, OperationRunLinks, and the current operations hub/detail surfaces
  • Delegated start/completion UX behaviors:
    • queued review-compose runs continue to use the shared queued feedback path
    • adapter finalization continues to write terminal lifecycle state only through OperationRunService
    • canonical related-artifact and open-run links stay on the shared helper paths
  • Local surface-owned behavior that remains: review-start form inputs and any review-specific secondary explanation copy
  • Queued DB-notification policy: unchanged; queued notifications remain explicit opt-in only
  • Terminal notification path: unchanged central lifecycle mechanism
  • Exception required?: none by default

Provider Boundary / Platform Core Check (mandatory when the feature changes shared provider/platform seams, identity scope, governed-subject taxonomy, compare strategy selection, provider connection descriptors, or operator vocabulary that may leak provider-specific semantics into platform-core truth; otherwise write N/A - no shared provider/platform boundary touched)

  • Shared provider/platform boundary touched?: no
  • Boundary classification: N/A
  • Seams affected: N/A
  • Neutral platform terms preserved or introduced: operation, dispatch, correlation, reconciliation, related artifact, workspace, managed environment
  • Provider-specific semantics retained and why: none
  • Why this does not deepen provider coupling accidentally: the cutover is entirely inside platform-owned OperationRun lifecycle, metadata, and read-side truth
  • Follow-up path: none

UI / Surface Guardrail Impact (mandatory when operator-facing surfaces are changed; otherwise write N/A)

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 and related-artifact explanation yes Native Filament page shared monitoring family page, table row no no new route or action family
Tenantless run detail canonical related metadata and dispatch explanation yes Native Filament page shared monitoring detail family detail no no new diagnostics family
Review start feedback for reused review or existing active run yes Native Filament action + notification shared run-start feedback family action feedback no reuses current notification/action pattern

Decision-First Surface Role (mandatory when operator-facing surfaces are changed)

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 run still needs attention or already has reconciled proof lifecycle outcome, canonical related artifact hint, one inspect action full diagnostics and raw context on detail primary because it is the canonical operations triage queue follows existing operations workflow removes cross-checking across run, review, and artifact surfaces
Tenantless run detail Tertiary Evidence / Diagnostics Surface confirm why the run reconciled, blocked, or failed after selection one canonical reconciliation or dispatch summary before raw context evidence, failures, and related artifact detail tertiary because the run is already selected preserves the current detail role removes duplicate or fallback-first explanations
Review start feedback Secondary Context Surface decide whether to open the reused review, open the run, or stop already-available vs queued state, one safe link full diagnostics only after drill-through secondary because it supports, not owns, the workflow follows current review-start action flow prevents duplicate clicks and ghost-run interpretation

Audience-Aware Disclosure (mandatory when operator-facing surfaces are changed)

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 or blocked summary plus related artifact hint reason code and supporting metadata secondarily raw payloads remain on detail Open operation SQL, duplicate-key, and raw failure payloads stay hidden from the list one row states one canonical outcome
Tenantless run detail operator-MSP, support-platform canonical lifecycle and reconciliation summary evidence, related artifact metadata, and dispatch metadata lower on page raw context stays secondary existing navigation and related links debug payloads remain progressive disclosure dispatch, reconciliation, and artifact truth do not restate conflicting summaries
Review start feedback operator-MSP review reused vs active compose still running none beyond shared run or artifact links raw diagnostics remain off-surface View review or Open operation technical duplicate details hidden one notification family states one result

UI/UX Surface Classification (mandatory when operator-facing surfaces are changed)

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 still needs interpretation 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 proof already exists or follow-up is still required none
Tenantless run detail Record / Detail / Monitoring Diagnostics-first detail surface confirm the canonical result before deeper diagnosis 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 one canonical dispatch/reconciliation summary none
Review start feedback Action Feedback Action result surface open the artifact or the run notification link N/A current feedback actions only none current review surface linked artifact or operation detail current workspace or tenant page context Review composition reused review vs queued operation truth none

Operator Surface Contract (mandatory when operator-facing surfaces are changed)

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 an operation still needs monitoring or already has reconciled proof monitoring registry Is this run still active work, or is the related artifact already the truth? lifecycle status, related artifact hint, calm explanation raw context and lineage lifecycle, reconciliation truth, artifact availability none open row none
Tenantless run detail workspace operator confirm why the run reconciled, blocked, or failed detail surface Why should this run now be trusted, blocked, or investigated? top-level reconciliation or dispatch summary, related artifact hint evidence, failure summary, raw context lifecycle, reconciliation truth, correlation truth, artifact availability none existing links none
Review start feedback tenant operator decide whether to wait, open the run, or open the already available review action feedback Did the system queue new work or reuse existing truth? one canonical action result diagnostics after drill-through only queued vs reused truth none view run or view review 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?: no new persisted family; only bounded canonical adapter/correlation semantics over existing fields
  • New cross-domain UI framework/taxonomy?: no
  • Current operator problem: current repo truth would force future adapter work to deepen a type-match reconciler, job-local business fallbacks, and heterogeneous correlation logic that already disagree about what an OperationRun means.
  • Existing structure is insufficient because: AdapterRunReconciler, ComposeEnvironmentReviewJob, TrackOperationRun, BridgesFailedOperationRun, and OperationCatalog each currently own a different part of the same canonicality problem.
  • Narrowest correct implementation: extract one adapter extension seam and one job-correlation contract over the existing runtime, keep OperationRunService as the only write seam, and remove broad legacy compatibility where the repo already writes canonical values.
  • Ownership cost: one bounded adapter contract/registry or orchestrator, one bounded correlation resolver, reduced legacy alias inventory, and new unit or feature coverage that must stay explicit.
  • Alternative intentionally rejected: continuing with a growing match block plus job-local review logic was rejected because it would multiply exceptions before Spec 361 and would keep dispatch and correlation truth fragmented.
  • Release truth: current-release cleanup and consolidation before new adapter families, not speculative future preparation without active consumers.

Compatibility posture

This feature assumes a pre-production environment.

Backward compatibility, legacy aliases, migration shims, historical fixtures, and compatibility-specific tests are out of scope unless explicitly required by this spec.

Canonical replacement is preferred over preservation.

Testing / Lane / Runtime Impact (mandatory for runtime behavior changes)

  • Test purpose / classification: Unit + Feature + Browser
  • Validation lane(s): fast-feedback, confidence, browser, pgsql
  • Why this classification and these lanes are sufficient: Unit coverage proves adapter resolution, canonical metadata shapes, and operation-type canonicalization; Feature coverage proves service, job, and correlation behavior; PGSQL coverage proves duplicate-index and lock-sensitive paths; one bounded Browser smoke proves the visible operations surfaces without expanding into broader UI productization.
  • New or expanded test families:
    • apps/platform/tests/Unit/Support/Operations/Reconciliation/Spec360CanonicalAdapterRegistryTest.php
    • apps/platform/tests/Unit/Support/Operations/Reconciliation/Spec360ReconciliationContextFormatTest.php
    • apps/platform/tests/Unit/Support/OperationTypeCanonicalizationTest.php
    • apps/platform/tests/Unit/Support/OperationRunDispatchContextTest.php
    • apps/platform/tests/Feature/Operations/Spec360CanonicalReconciliationCutoverTest.php
    • apps/platform/tests/Feature/Operations/Spec360DispatchCorrelationTest.php
    • apps/platform/tests/Feature/EnvironmentReview/Spec360ReviewComposeAdapterOwnershipTest.php
    • apps/platform/tests/Browser/Spec360OperationRunCanonicalCutoverSmokeTest.php
  • Fixture / helper cost impact: low to moderate; reuse current operation-run, workspace, environment, and review fixtures only
  • Heavy-family visibility / justification: no heavy-governance family is introduced
  • Special surface test profile: monitoring-state-page plus shared-detail-family
  • Standard-native relief or required special coverage: one bounded Browser smoke and PGSQL proof are required; otherwise ordinary Unit and Feature coverage is sufficient
  • Reviewer handoff: reviewers must confirm that the cutover removes type-match growth, keeps OperationRunService service-owned, writes canonical dispatch and reconciliation metadata, and keeps operations surfaces calm and scope-safe
  • Budget / baseline / trend impact: small feature-local growth only
  • Escalation needed: reject-or-split if implementation expands into new business adapters, new persistence, or a broad product feature
  • Active feature PR close-out entry: Guardrail / Smoke Coverage
  • Planned validation commands:
    • Primary merge gate
      • cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec360
      • cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec359
      • cd apps/platform && ./vendor/bin/sail artisan test --compact --filter=Spec358
      • cd apps/platform && ./vendor/bin/sail php vendor/bin/pest -c phpunit.pgsql.xml --filter=Spec360
      • cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Spec360OperationRunCanonicalCutoverSmokeTest.php
    • Contextual regressions
      • cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/CustomerReviewWorkspaceSmokeTest.php
      • cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Spec357ReportProfilesSmokeTest.php
      • cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/ReviewPack/Spec357RenderedReportProfileTest.php
      • cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/ReviewPack/ReviewPackDownloadTest.php
      • cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/ReviewPack/EnvironmentReviewDerivedReviewPackTest.php
      • cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/ReviewPack/EnvironmentReviewExecutivePackTest.php
    • Separate external probes
      • cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/Spec347ReviewPackOutputReadinessSmokeTest.php
      • cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/EnvironmentReviewHeaderDisciplineTest.php
    • Hygiene
      • cd apps/platform && ./vendor/bin/pint --dirty
      • git diff --check

Known external probes remain explicit and separately reviewable. They must not be silently folded into the primary Spec 360 merge gate unless an in-scope failure proves that this cutover itself regressed them.

User Scenarios & Testing (mandatory)

User Story 1 - Canonicalize the adapter-owned reconciliation seam (Priority: P1)

As a maintainer, I need one canonical adapter extension point so that review-compose reconciliation no longer depends on a growing type-match block or job-local business fallback.

Why this priority: this is the direct architectural blocker before further adapter work and the highest-risk drift left after Spec 359 merged.

Independent Test: run focused Unit and Feature coverage that proves restore and review-compose resolution go through one canonical adapter seam, that unsupported types stay unsupported, and that OperationRunService remains the only reconciliation write owner.

Acceptance Scenarios:

  1. Given a restore.execute or environment.review.compose run, When reconciliation resolves it, Then one canonical adapter seam selects the business-specific path without adding a new central type-match branch for future adapters.
  2. Given a review-compose duplicate or superseded lineage case, When the system finalizes the run, Then the adapter or decision path owns the business decision and ComposeEnvironmentReviewJob does not write reconciliation directly.

User Story 2 - Align queued dispatch and failed-job correlation truth (Priority: P1)

As an operations maintainer, I need queued dispatch metadata and failed-job correlation to use one canonical contract so that active and failed runs can be traced without hidden heuristics.

Why this priority: current middleware and failed-job bridging still resolve runs differently, and no canonical context.dispatch payload exists yet.

Independent Test: run focused Unit and Feature coverage that proves new queued runs write canonical dispatch metadata and that middleware plus failed-job bridging resolve the same OperationRun.

Acceptance Scenarios:

  1. Given a newly queued review-compose run, When the dispatch seam executes successfully, Then the run records canonical dispatch metadata with job class, queue, connection, timestamp, correlation version, and operation run id.
  2. Given a queued job fails after dispatch, When the failed-job bridge runs, Then it resolves the same OperationRun as middleware would resolve for normal execution.

User Story 3 - Cut readers and operation-type truth over to canonical metadata (Priority: P2)

As an operator, I need related-artifact links, operation labels, and operations detail wording to rely on canonical metadata instead of legacy alias and fallback behavior.

Why this priority: the underlying runtime can be canonical only if the read side also stops treating historical fallback behavior as equal truth.

Independent Test: run focused Unit, Feature, and one bounded Browser smoke to prove canonical operation types, canonical reconciliation related metadata, and calm operations wording across current monitoring surfaces.

Acceptance Scenarios:

  1. Given a reconciled review-compose run with canonical context.reconciliation.related, When the operations hub or detail page renders it, Then the related review link resolves from that canonical metadata rather than from loose operation_run_id fallback.
  2. Given a run or factory writes a new operation type, When the type is stored or rendered, Then canonical write values are used and unnecessary legacy aliases are not emitted as new truth.

Edge Cases

  • A queued or failed job has an operationRunId but no in-memory operationRun object.
  • A run already became terminal before middleware or a failed-job bridge touches it.
  • context.dispatch can record queue, connection, and job class, but no framework-supplied queue job id is available.
  • context.reconciliation.related points to a review id that no longer matches workspace or environment scope.
  • A run still carries a historical raw type alias in storage while canonical writers already emit the new value directly.
  • Review-compose duplicate recovery remains ambiguous or blocked even after the adapter decision evaluates lineage.

Requirements (mandatory)

Functional Requirements

  • FR-360-001: The system MUST provide exactly one canonical adapter extension seam for adapter-backed OperationRun reconciliation across the current restore.execute and environment.review.compose cases.
  • FR-360-002: The canonical adapter seam MUST support explicit unsupported handling and MUST NOT require future adapters to extend a central match or switch block in AdapterRunReconciler.
  • FR-360-003: OperationRunService MUST remain the only service that writes reconciliation lifecycle state, context.reconciliation, summary counts, or failures for adapter-driven finalization.
  • FR-360-004: New reconciliation writes MUST use only canonical context.reconciliation metadata and MUST include source, adapter, decision, reason code, previous status, previous outcome, reconciled timestamp, bounded evidence, and canonical related metadata when available.
  • FR-360-005: ComposeEnvironmentReviewJob MUST remain orchestration-only and MUST NOT contain business-specific review selection, cross-scope matching, duplicate recovery finalization, or direct reconciliation metadata writes.
  • FR-360-006: Duplicate fingerprint or superseded review recovery for environment.review.compose MUST flow through the canonical adapter or decision path and MUST remain deterministic, scope-safe, and idempotent.
  • FR-360-007: Newly queued runs affected by this feature MUST write canonical context.dispatch metadata through the shared dispatch seam and MUST NOT invent synthetic queue job ids when the framework cannot provide them.
  • FR-360-008: TrackOperationRun and BridgesFailedOperationRun MUST resolve the target run through the same canonical correlation contract or resolver for the current OperationRunService::dispatchOrFail() lifecycle path touched by this spec, and unsupported or out-of-scope jobs MUST fail closed without false correlation claims.
  • FR-360-009: Canonical operation-type writes MUST come from one clear source of truth across OperationRunType, OperationCatalog, model canonicalization, factories, and touched writers.
  • FR-360-010: Unnecessary legacy operation-type alias compatibility MUST be removed from current writers and prep artifacts; any alias kept on the read side MUST be justified by repo-verified active need rather than pre-production caution.
  • FR-360-011: OperationRunLinks, ArtifactTruthPresenter, and related helpers MUST prefer context.reconciliation.related as the canonical source for adapter-resolved related artifacts.
  • FR-360-012: Existing operations and review-start surfaces MUST keep calm operator wording and MUST NOT expose raw SQL, duplicate-key, or legacy alias detail as primary visible truth.
  • FR-360-013: specs/359-operationrun-reconciliation-adapter-framework-review-compose-adapter/tasks.md MUST be updated so the merged runtime status, deferred Spec 360 follow-through, and blocked PGSQL validation state are explicit and no implementation-looking open tasks remain misleading.

Non-Functional Requirements

  • NFR-360-001: No new database migration, table, column, or persisted lifecycle field is allowed.
  • NFR-360-002: No new business adapter for report, evidence, sync, backup, restore, or alert delivery is allowed in this spec.
  • NFR-360-003: No new destructive runtime action, cleanup console, or delete or purge workflow is allowed.
  • NFR-360-004: The feature MUST remain Livewire v4 compatible and MUST NOT introduce Livewire v3 APIs.
  • NFR-360-005: No Filament panel/provider move, no asset registration change, and no deployment asset strategy change is allowed.
  • NFR-360-006: The cutover MUST assume the current pre-production posture: canonical replacement is preferred over legacy compatibility for historical rows, tests, or fixtures unless repo truth proves an active need.
  • NFR-360-007: Evidence stored in context.reconciliation and context.dispatch MUST stay bounded, audit-safe, and free of secrets, signed URLs, raw credential payloads, or oversized copied domain objects.
  • NFR-360-008: Repo-wide normalization of unrelated legacy bulkRunId, runId, or other non-operationRunId job identity conventions is out of scope unless a job already sits on the current OperationRun dispatch/failure-bridge path touched by this cutover.

UI Action Matrix (mandatory when Filament is changed)

Surface Location Header Actions Inspect Affordance (List/Table) Row Actions (max 2 visible) Bulk Actions (grouped) Empty-State CTA(s) View Header Actions Create/Edit Save+Cancel Audit log? Notes / Exemptions
Operations hub apps/platform/app/Filament/Pages/Monitoring/Operations.php existing only row click to canonical detail existing only existing only unchanged N/A N/A existing run terminal audit only no new action
Run detail apps/platform/app/Filament/Pages/Operations/TenantlessOperationRunViewer.php existing only N/A N/A N/A unchanged existing navigation only N/A existing run terminal audit only no new action
Review start feedback apps/platform/app/Filament/Resources/EnvironmentReviewResource.php existing only notification link notification action only N/A unchanged N/A existing form actions only existing audit and run terminal audit only no new mutation surface

Key Entities (include if feature involves data)

  • OperationRun: persisted execution and reconciliation truth; holds canonical type, status, outcome, summary_counts, and context
  • Reconciliation metadata: bounded context.reconciliation payload describing canonical adapter-owned finalization
  • Dispatch metadata: bounded context.dispatch payload describing queued dispatch and correlation truth
  • EnvironmentReview: domain artifact that may already prove review-compose truth and may be linked canonically through context.reconciliation.related

Success Criteria (mandatory)

Measurable Outcomes

  • SC-360-001: restore and review-compose reconciliation both resolve through one canonical extension seam, and adding a future adapter no longer requires extending a central type-match branch in AdapterRunReconciler.
  • SC-360-002: newly queued review-compose runs write canonical dispatch metadata with job class, queue, connection, dispatched timestamp, correlation version, and operation run id in automated coverage.
  • SC-360-003: middleware and failed-job bridge coverage prove the same OperationRun correlation path for queued review-compose runs and fail closed for unsupported jobs.
  • SC-360-004: canonical read-side coverage proves that reconciled review links resolve from context.reconciliation.related, operation-type writes are canonical-only on touched paths, and primary operator surfaces no longer depend on raw SQL or legacy alias messaging.

Assumptions

  • Spec 359 is already merged and is the functional baseline for this cleanup package.
  • Existing restore behavior remains in scope only as a current adapter consumer, not as a new restore product feature.
  • No production customer data or migration compatibility requirement exists for old raw operation-type aliases or historical test fixtures.

Risks

  • The adapter registry or orchestrator cutover could over-abstract if it grows beyond the two repo-real adapter cases. Tasks and review must keep it bounded.
  • Dispatch metadata can drift if writers outside OperationRunService continue to enqueue jobs directly without using the shared seam.
  • Reader fallback removal can break historical fixtures unless tests and browser smoke are rebased deliberately to canonical truth.

Open Questions

  • None blocking prep. The only known uncertainty is the locally blocked PGSQL validation state from Spec 359, which this spec carries forward explicitly into the implementation validation gate rather than treating as preparation ambiguity.