TenantAtlas/specs/272-operationrun-phase-composite-progress/plan.md
ahmido b2ec2f032f 272: OperationRun phase composite progress (#330)
Bring feature work for OperationRun phase composite progress into `platform-dev`. This PR contains the merged session commits and spec artifacts.

Notes:
- Session branch was merged into `272-operationrun-phase-composite-progress` locally and pushed.
- Please review specs and tests under `specs/272-operationrun-phase-composite-progress/`.

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #330
2026-05-05 12:54:38 +00:00

260 lines
20 KiB
Markdown

# Implementation Plan: OperationRun Phase & Composite Progress v1
**Branch**: `272-operationrun-phase-composite-progress` | **Date**: 2026-05-05 | **Spec**: [spec.md](./spec.md)
**Input**: Feature specification from `/specs/272-operationrun-phase-composite-progress/spec.md`
## Summary
This plan prepares the bounded non-counted follow-up to Spec 270 and the adjacent counted boundary from Spec 271. The implementation path is to reuse `OperationRunProgressContract`, `OperationUxPresenter`, and `OperationRunService`, add canonical operator-safe phase metadata for `baseline_capture` and `baseline_compare`, and add one bounded composite summary path for `tenant.review.compose` from existing aggregate operation truth. The slice must not invent fake percentages, reopen counted rollout work, add a workflow engine, create a child-run graph, or widen into provider health, support diagnostics, or dashboard work.
## Inherited Baseline / Explicit Delta
### Inherited baseline
- `App\Support\OpsUx\OperationRunProgressContract` already centralizes `none`, `activity`, `counted`, `phased`, and `composite` progress modes.
- The current contract already classifies baseline evidence-capture context as `phased` and aggregate multi-run truth as `composite`, but it currently returns only generic placeholder labels.
- `App\Jobs\CaptureBaselineSnapshotJob` and `App\Jobs\CompareBaselineToTenantJob` already persist repo-real baseline phase-shaped context, including eligibility and evidence-capture stats.
- `App\Services\TenantReviews\TenantReviewService` and `App\Jobs\ComposeTenantReviewJob` already create the canonical `tenant.review.compose` run type, and current evidence snapshot summaries already contain aggregate operation counts used later in tenant review composition.
- The current tenant shell adopter already renders generic phased/composite fallbacks through the shared contract without inventing a percentage.
- Spec 271 already owns truthful counted rollout for stable-unit families and must remain distinct from this slice.
### Explicit delta in this plan
- add canonical operator-safe phase metadata and label derivation for `baseline_capture` and `baseline_compare`
- add one bounded composite summary path for `tenant.review.compose` from current aggregate operation truth
- keep counted, terminal, and generic activity semantics unchanged except for consuming more truthful non-counted detail
- document the narrowed candidate boundary explicitly: review-pack and evidence-snapshot overlap remain with Spec 271, while provider health and support diagnostics remain deferred until repo-real queued progress truth exists
## Technical Context
**Language/Version**: PHP 8.4, Laravel 12, Filament v5, Livewire v4
**Primary Dependencies**: existing Ops-UX contract/presenter classes, current baseline services/jobs, current tenant-review services/jobs, Pest v4
**Storage**: PostgreSQL via existing `operation_runs`, baseline, evidence snapshot, and tenant review tables
**Testing**: Pest Unit + Feature
**Validation Lanes**: fast-feedback, confidence
**Target Platform**: existing Laravel monolith in `apps/platform`
**Project Type**: web application (Laravel monolith with Filament)
**Performance Goals**: no new poller family, no new query family, and no slower-than-current activity feedback disclosure
**Constraints**: no fake percentages, no new `summary_counts` keys, no new persistence, no child-run graph, no dashboard redesign, and no provider-health or support-diagnostics rollout
**Scale/Scope**: one shared contract extension across 3 selected run families plus one UI standards update and focused regression coverage
## Likely Affected Repo Surfaces
- `apps/platform/app/Support/OpsUx/OperationRunProgressContract.php`
- `apps/platform/app/Support/OpsUx/OperationUxPresenter.php`
- `apps/platform/app/Support/OpsUx/OperationStatusNormalizer.php`
- `apps/platform/app/Services/OperationRunService.php`
- `apps/platform/app/Services/Baselines/BaselineCaptureService.php`
- `apps/platform/app/Jobs/CaptureBaselineSnapshotJob.php`
- `apps/platform/app/Jobs/CompareBaselineToTenantJob.php`
- `apps/platform/app/Services/TenantReviews/TenantReviewService.php`
- `apps/platform/app/Jobs/ComposeTenantReviewJob.php`
- `apps/platform/app/Services/TenantReviews/TenantReviewSectionFactory.php`
- `apps/platform/tests/Unit/Support/OpsUx/OperationRunProgressContractTest.php`
- `apps/platform/tests/Feature/OpsUx/ActivityFeedbackSurfaceTest.php`
- `apps/platform/tests/Feature/OpsUx/BulkOperationProgressDbOnlyTest.php`
- `apps/platform/tests/Feature/BaselineDriftEngine/CaptureBaselineContentTest.php`
- `apps/platform/tests/Feature/Baselines/BaselineCaptureTest.php`
- `apps/platform/tests/Feature/Baselines/BaselineCompareExecutionGuardTest.php`
- `apps/platform/tests/Feature/Baselines/BaselineCompareResumeTokenTest.php`
- `apps/platform/tests/Feature/TenantReview/TenantReviewOperationsUxTest.php`
- `apps/platform/tests/Feature/Filament/OperationRunBaselineTruthSurfaceTest.php`
- `apps/platform/tests/Feature/Operations/TenantlessOperationRunViewerTest.php`
- `apps/platform/tests/Feature/TenantReview/TenantReviewRbacTest.php`
- `apps/platform/tests/Feature/Baselines/BaselineProfileAuthorizationTest.php`
- `docs/ui/tenantpilot-enterprise-ui-standards.md`
## UI / Filament & Livewire Fit
- The visible adopter remains the existing tenant-shell activity feedback surface. No new page, dashboard card, widget family, or top-level monitoring surface is introduced.
- Canonical Operations collection/detail routes remain diagnostics-first drill-through targets. They may inherit safer phase/composite disclosure through the shared presenter path, but they do not gain a second progress framework.
- The shell remains decision-first. This slice only improves whether selected runs can describe truthful non-counted phase/composite state.
- Filament stays v5 on Livewire v4. Provider registration remains unchanged in `apps/platform/bootstrap/providers.php`.
## RBAC / Policy Fit
- Existing capability gates for baseline capture, baseline compare, and tenant review remain unchanged.
- Existing `OperationRun` policies remain the only progress-visibility gate.
- No new mutation surface is introduced, so current server-side authorization and confirmation behavior stays on the existing launch/detail surfaces.
## Audit / Logging Fit
- Existing queued toasts and terminal notifications remain authoritative and unchanged.
- Existing audit ownership remains the only audit trail for the covered runs; no new run-local audit channel is introduced.
- Progress detail remains derived execution truth inside the current `OperationRun` ownership model, not a second audit or event stream.
## Data & Query Fit
- Progress truth remains fully derived from existing `operation_runs.context`, `operation_runs.summary_counts`, and current contract logic.
- Selected phase metadata stays inside existing `context` JSON and does not create a new persisted entity.
- Composite progress for `tenant.review.compose` stays bounded to currently available aggregate operation truth from evidence snapshot or review summary data.
- No migration, no new JSON table, no cache layer, and no new persisted user preference or progress mode are planned.
## UI / Surface Guardrail Plan
- **Guardrail scope**: changed surfaces
- **Native vs custom classification summary**: native Filament + existing Livewire/Blade shell surface
- **Shared-family relevance**: Ops-UX activity feedback and current run summaries
- **State layers in scope**: shell, detail compatibility
- **Audience modes in scope**: operator-MSP
- **Decision/diagnostic/raw hierarchy plan**: decision-first on shell, diagnostics-second on Operations detail
- **Raw/support gating plan**: unchanged; raw/support detail remains on diagnostics surfaces only
- **One-primary-action / duplicate-truth control**: keep one dominant `View operation` action and one shared progress contract that now supplies richer non-counted labels
- **Handling modes by drift class or surface**: review-mandatory
- **Repository-signal treatment**: review-mandatory
- **Special surface test profiles**: global-context-shell
- **Required tests or manual smoke**: functional-core, state-contract
- **Exception path and spread control**: none planned
- **Active feature PR close-out entry**: Guardrail / Smoke Coverage
## Shared Pattern & System Fit
- **Cross-cutting feature marker**: yes
- **Systems touched**: Ops-UX progress contract, Ops-UX presenter, baseline jobs/services, tenant-review queue/composition path, shell activity feedback
- **Shared abstractions reused**: `OperationRunProgressContract`, `OperationUxPresenter`, `OperationStatusNormalizer`, `OperationRunService`
- **New abstraction introduced? why?**: no new top-level abstraction planned; extend the current contract/presenter path only
- **Why the existing abstraction was sufficient or insufficient**: classification already exists; what is missing is canonical operator-safe phase/composite detail for selected run families
- **Bounded deviation / spread control**: selected families only; any additional run family without repo-real truthful phase/composite detail stays on current generic fallback
## OperationRun UX Impact
- **Touches OperationRun start/completion/link UX?**: yes, for active progress meaning only
- **Central contract reused**: existing OperationRun Start UX Contract plus `OperationRunProgressContract`
- **Delegated UX behaviors**: queued toast, canonical run links, `run-enqueued` event, and terminal-notification lifecycle remain delegated and unchanged
- **Surface-owned behavior kept local**: current launch inputs, detailed diagnostics, and domain-specific result explanations stay local to their current surfaces
- **Queued DB-notification policy**: `N/A` - 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` truth, Ops-UX contract/presenter, baseline and tenant-review execution truth
- **Neutral platform terms / contracts preserved**: `Operation`, `activity`, `phase progress`, `composite progress`, `terminal outcome`
- **Retained provider-specific semantics and why**: none
- **Bounded extraction or follow-up path**: provider health and support diagnostics remain an explicit later follow-up if queued progress truth exists later
## Constitution Check
*GATE: Must pass before implementation begins and again before merge.*
- Inventory-first: PASS. The slice only enriches current execution feedback over existing operational truth.
- Read/write separation: PASS. No new external write path is introduced; current domain jobs keep their existing product responsibilities and only persist better progress detail in `OperationRun` context.
- Graph contract path: PASS. No new Graph or provider contract is introduced.
- Deterministic capabilities: PASS. Authorization and run visibility remain deterministic and testable.
- RBAC-UX: PASS. Visibility remains on existing tenant/admin boundaries and current `OperationRun` policies.
- Run observability: PASS. Long-running work still flows through current `OperationRun` ownership and current Ops-UX surfaces.
- Ops-UX lifecycle: PASS. `status` and `outcome` ownership remains on `OperationRunService`; this slice only adds richer non-counted detail.
- Ops-UX summary counts: PASS. No new `summary_counts` key is planned.
- Test governance: PASS. Proof remains bounded to Unit plus Feature.
- Proportionality / no premature abstraction: PASS. No new workflow engine, child-run graph, or second presenter path is introduced.
- Persisted truth / behavioral state: PASS. No new table, cache, or lifecycle family is added.
- Shared pattern first / UI semantics / Filament-native UI: PASS. Existing Ops-UX path remains central and the visible adopter is unchanged.
- Provider boundary: PASS. No provider/platform seam change.
- Filament/Laravel panel safety: PASS. Filament v5 stays on Livewire v4, provider registration remains in `apps/platform/bootstrap/providers.php`, and no assets change.
**Gate evaluation**: PASS.
## Test Governance Check
- **Test purpose / classification by changed surface**: Unit for contract precedence and label derivation; Feature for selected baseline and tenant-review writer seams plus current shell adoption
- **Affected validation lanes**: fast-feedback, confidence
- **Why this lane mix is the narrowest sufficient proof**: the shared contract already has a focused unit suite, and the selected run families already have domain feature suites that can prove current context/summary truth without adding new browser or heavy-governance obligations
- **Narrowest proving command(s)**:
- `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Unit/Support/OpsUx/OperationRunProgressContractTest.php`
- `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/OpsUx/ActivityFeedbackSurfaceTest.php tests/Feature/OpsUx/BulkOperationProgressDbOnlyTest.php tests/Feature/BaselineDriftEngine/CaptureBaselineContentTest.php tests/Feature/Baselines/BaselineCaptureTest.php tests/Feature/Baselines/BaselineCompareResumeTokenTest.php tests/Feature/Baselines/BaselineCompareExecutionGuardTest.php tests/Feature/TenantReview/TenantReviewOperationsUxTest.php tests/Feature/Filament/OperationRunBaselineTruthSurfaceTest.php tests/Feature/Operations/TenantlessOperationRunViewerTest.php tests/Feature/TenantReview/TenantReviewRbacTest.php tests/Feature/Baselines/BaselineProfileAuthorizationTest.php`
- **Fixture / helper / factory / seed / context cost risks**: low to moderate; reuse current tenant context helpers, existing baseline helpers, and current tenant-review fixtures instead of adding a new provider-heavy harness
- **Expensive defaults or shared helper growth introduced?**: no
- **Heavy-family additions, promotions, or visibility changes**: none
- **Surface-class relief / special coverage rule**: `global-context-shell`
- **Closing validation and reviewer handoff**: rerun the two proving commands above and verify that selected run families now expose truthful non-counted detail, the full precedence chain `phased > composite > counted > activity` still holds, counted semantics stay counted-only, malformed metadata degrades safely, current `404`/`403` visibility semantics remain intact, no new polling loop was introduced, and excluded families remain excluded
- **Budget / baseline / trend follow-up**: none expected beyond a small feature-local increase
- **Review-stop questions**: did any run family leak raw technical phase labels, did any composite summary masquerade as a percentage, did any excluded family sneak in, and did any new `summary_counts` key or workflow framework appear?
- **Escalation path**: `reject-or-split` for any provider-health/support expansion, dashboard work, child-run graph persistence, or workflow-engine drift
- **Active feature PR close-out entry**: Guardrail / Smoke Coverage
- **Why no dedicated follow-up spec is needed**: this package is itself the bounded non-counted progress follow-up to Spec 270; remaining excluded ideas are already named as explicit later follow-ups.
## Project Structure
### Documentation (this feature)
```text
specs/272-operationrun-phase-composite-progress/
├── spec.md
├── plan.md
├── tasks.md
└── checklists/
└── requirements.md
```
### Source Code (expected implementation surfaces)
```text
apps/platform/app/Support/OpsUx/
apps/platform/app/Services/OperationRunService.php
apps/platform/app/Services/Baselines/BaselineCaptureService.php
apps/platform/app/Jobs/CaptureBaselineSnapshotJob.php
apps/platform/app/Jobs/CompareBaselineToTenantJob.php
apps/platform/app/Services/TenantReviews/TenantReviewService.php
apps/platform/app/Jobs/ComposeTenantReviewJob.php
apps/platform/app/Services/TenantReviews/TenantReviewSectionFactory.php
apps/platform/tests/Unit/Support/OpsUx/
apps/platform/tests/Feature/OpsUx/
apps/platform/tests/Feature/Baselines/
apps/platform/tests/Feature/TenantReview/
apps/platform/tests/Feature/Filament/
docs/ui/tenantpilot-enterprise-ui-standards.md
```
**Structure Decision**: keep the rollout local to current jobs/services plus the existing Ops-UX support family. Do not introduce a workflow engine, child-run graph, or second progress framework.
## Data / Migration Implications
- No migration or schema change is planned.
- No new persisted progress mode or preference is allowed.
- Selected phase/composite detail remains inside existing `operation_runs.context` JSON only.
- No backfill is planned. Historical runs remain historical truth; the rollout affects future execution and active-run rendering only.
## Rollout Considerations
- Filament remains v5 on Livewire v4. Provider registration remains in `apps/platform/bootstrap/providers.php`.
- No global search or asset change is required because the slice changes only current run-progress truth.
- No destructive action or confirmation model changes are planned.
- No deployment step beyond ordinary code deploy, focused tests, and current formatting validation is expected.
## Risk Controls
- Reject any implementation that turns phase/composite labels into fake percentages or a synthetic progress bar.
- Reject any implementation that leaks raw technical step names, exception class names, or transport details into the default operator-facing progress label.
- Reject any implementation that adds a child-run graph or persists `child_run_ids` as a new framework instead of a bounded current-release need.
- Reject any implementation that widens the rollout to provider health, support diagnostics, review-pack, or evidence-snapshot overlap without an explicit follow-up spec.
- Reject any implementation that changes counted precedence or adds a new `summary_counts` key to compensate for missing phase/composite truth.
## Implementation Phases
### Phase 0 - Confirm The Selected Non-Counted Seams
- Verify the current phase and composite fallback behavior in `OperationRunProgressContract`, the current shell adopter, the current baseline jobs, and the current tenant-review queue/composition path.
- Reconfirm that provider health, support diagnostics, review-pack overlap, and child-run graph persistence remain out of scope.
### Phase 1 - Roll Out Baseline Phase Metadata
- Add canonical operator-safe phase metadata for `baseline_capture` and `baseline_compare` over the repo-real lifecycle boundaries that already exist today.
### Phase 2 - Roll Out Tenant Review Composite Summary
- Seed a bounded composite summary for `tenant.review.compose` from current evidence-basis operation truth and keep it explicitly non-counted.
### Phase 3 - Lock The Guardrail And Proof
- Update the UI standards and focused tests so later non-counted progress work extends one contract rather than inventing new semantics.
## Proportionality Review
- **Current operator problem**: current non-counted runs know more than the product currently says, yet the shell still shows vague generic fallback copy.
- **Existing structure is insufficient because**: the shared contract can classify `phased` and `composite`, but it cannot yet explain them with canonical operator-safe detail for selected run families.
- **Narrowest correct implementation**: update only selected repo-real phase/composite families and keep all other work on current generic fallback or counted semantics.
- **Ownership cost created**: selected context writes in existing jobs/services, focused tests, and one standards update.
- **Alternative intentionally rejected**: a workflow engine, child-run graph, or fake percentage model was rejected because all would be structurally heavier and less truthful than the current-release need.
- **Release truth**: current-release truth. The repo already contains the contract, the shell adopter, the baseline phase hints, and the tenant-review aggregate truth needed for this rollout.