262 lines
17 KiB
Markdown
262 lines
17 KiB
Markdown
# Implementation Plan: Counted Progress Rollout v1
|
|
|
|
**Branch**: `271-counted-progress-rollout` | **Date**: 2026-05-05 | **Spec**: [spec.md](./spec.md)
|
|
**Input**: Feature specification from `/specs/271-counted-progress-rollout/spec.md`
|
|
|
|
## Summary
|
|
|
|
This plan prepares one bounded writer-rollout slice on top of the existing shared progress contract from Spec 270. The implementation path is to reuse `OperationRunProgressContract` and `OperationRunService`, add truthful `total` plus `processed` writes only where the repo already exposes deterministic work units, and leave baseline capture/compare on their current phased path. The slice must not invent totals, widen into phase/composite work, add new `summary_counts` keys, or redesign current Ops-UX surfaces.
|
|
|
|
## Inherited Baseline / Explicit Delta
|
|
|
|
### Inherited baseline
|
|
|
|
- `App\Support\OpsUx\OperationRunProgressContract` already centralizes `none`, `activity`, `counted`, `phased`, and `composite` progress modes.
|
|
- `App\Services\OperationRunService` already owns `updateRun()`, `incrementSummaryCounts()`, and `maybeCompleteBulkRun()` as the authoritative summary-count mutation path.
|
|
- The current tenant shell adopter already consumes the shared progress contract and can render determinate counted progress when trustworthy counts exist.
|
|
- Inventory sync, review-pack generation, evidence-snapshot generation, `AddPoliciesToBackupSetJob`, `BulkBackupSetRestoreJob`, and `BackupSetRestoreWorkerJob` are already repo-real workflows with current tests.
|
|
- Baseline capture and baseline compare already expose evidence-capture phase hints, which the current progress contract classifies as `phased` before `counted`.
|
|
|
|
### Explicit delta in this plan
|
|
|
|
- roll out truthful counted inputs for selected stable-unit run families only
|
|
- standardize parent and child count discipline across `AddPoliciesToBackupSetJob`, `BulkBackupSetRestoreJob`, and `BackupSetRestoreWorkerJob`
|
|
- keep current shell and Operations detail surfaces unchanged except for consuming newly truthful count data
|
|
- document the narrowed scope deviation from the original candidate wording: baseline capture/compare remain deferred because repo truth now places them on the phased/composite path
|
|
|
|
## Technical Context
|
|
|
|
**Language/Version**: PHP 8.4, Laravel 12, Filament v5, Livewire v4
|
|
**Primary Dependencies**: current Ops-UX support classes, native Filament/Livewire shell feedback, Pest v4
|
|
**Storage**: PostgreSQL via existing `operation_runs`, review-pack, evidence-snapshot, backup-set, and restore 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 query families, no new polling loops, and no slower-than-current active-operation feedback
|
|
**Constraints**: no new `summary_counts` keys, no new persistence, no contract-precedence change, and no broad writer sweep
|
|
**Scale/Scope**: one shared contract reused across 4 selected run families plus one standards update and focused regression coverage
|
|
|
|
## Likely Affected Repo Surfaces
|
|
|
|
- `apps/platform/app/Support/OpsUx/OperationRunProgressContract.php`
|
|
- `apps/platform/app/Support/OpsUx/SummaryCountsNormalizer.php`
|
|
- `apps/platform/app/Support/OpsUx/OperationSummaryKeys.php`
|
|
- `apps/platform/app/Services/OperationRunService.php`
|
|
- `apps/platform/app/Jobs/RunInventorySyncJob.php`
|
|
- `apps/platform/app/Services/Inventory/InventorySyncService.php`
|
|
- `apps/platform/app/Jobs/GenerateReviewPackJob.php`
|
|
- `apps/platform/app/Services/ReviewPackService.php`
|
|
- `apps/platform/app/Jobs/GenerateEvidenceSnapshotJob.php`
|
|
- `apps/platform/app/Services/Evidence/EvidenceSnapshotService.php`
|
|
- `apps/platform/app/Jobs/AddPoliciesToBackupSetJob.php`
|
|
- `apps/platform/app/Jobs/BulkBackupSetRestoreJob.php`
|
|
- `apps/platform/app/Jobs/Operations/BackupSetRestoreWorkerJob.php`
|
|
- `apps/platform/tests/Unit/Support/OpsUx/OperationRunProgressContractTest.php`
|
|
- `apps/platform/tests/Feature/Inventory/RunInventorySyncJobTest.php`
|
|
- `apps/platform/tests/Feature/ReviewPack/ReviewPackGenerationTest.php`
|
|
- `apps/platform/tests/Feature/Evidence/GenerateEvidenceSnapshotJobTest.php`
|
|
- `apps/platform/tests/Feature/BackupSets/AddPoliciesToBackupSetJobTest.php`
|
|
- `apps/platform/tests/Unit/BulkBackupSetRestoreJobTest.php`
|
|
- `apps/platform/tests/Feature/OpsUx/ActivityFeedbackSurfaceTest.php`
|
|
- `apps/platform/tests/Feature/OpsUx/BulkOperationProgressDbOnlyTest.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, widget family, or dashboard card is introduced.
|
|
- The shell stays decision-first. This slice changes only whether selected runs can legitimately enter the already-existing counted mode.
|
|
- Operations collection/detail pages remain diagnostics-first drill-through targets. They inherit more truthful count data but no new layout or action model.
|
|
- No panel registration, asset registration, or global-search changes are planned.
|
|
|
|
## RBAC / Policy Fit
|
|
|
|
- Existing capability gates for the initiating surfaces 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 remains on the existing launch and detail surfaces.
|
|
|
|
## Audit / Logging Fit
|
|
|
|
- Existing queued toasts and terminal notifications remain authoritative and unchanged.
|
|
- Existing run audit remains the only audit trail for the counted rollout. No new run-local audit channel is introduced.
|
|
- Parent/child bulk completion still flows through existing `OperationRunService` helpers instead of feature-local completion code.
|
|
|
|
## Data & Query Fit
|
|
|
|
- Progress truth remains fully derived from `operation_runs.summary_counts` plus existing contract logic.
|
|
- Determinate progress stays limited to work with deterministic units known before or during processing.
|
|
- Outcome counters remain summary truth and do not replace `processed`.
|
|
- No migration, no new JSON schema, no cache layer, and no new persisted 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 run summaries
|
|
- **State layers in scope**: shell
|
|
- **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 progress mode derived from the shared contract
|
|
- **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, summary-count service helpers, inventory/review/evidence/backup writers, shell adopter
|
|
- **Shared abstractions reused**: `OperationRunProgressContract`, `OperationRunService`, `SummaryCountsNormalizer`, `OperationSummaryKeys`
|
|
- **New abstraction introduced? why?**: none planned
|
|
- **Why the existing abstraction was sufficient or insufficient**: rendering semantics are already centralized; the missing piece is writer-side counted input for specific repo-real workflows
|
|
- **Bounded deviation / spread control**: keep all count mutation on `OperationRunService`; any run family without deterministic units stays out of scope rather than adding a local exception
|
|
|
|
## OperationRun UX Impact
|
|
|
|
- **Touches OperationRun start/completion/link UX?**: yes, for progress truth 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**: launch inputs and current domain-specific validation only
|
|
- **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, progress contract, shell feedback
|
|
- **Neutral platform terms / contracts preserved**: `Operation`, `progress`, `counted progress`, `activity`, `terminal outcome`
|
|
- **Retained provider-specific semantics and why**: none
|
|
- **Bounded extraction or follow-up path**: none
|
|
|
|
## Constitution Check
|
|
|
|
*GATE: Must pass before implementation begins and again before merge.*
|
|
|
|
- Inventory-first: PASS. The slice only enriches execution feedback over current `OperationRun` truth.
|
|
- Read/write separation: PASS. No new external write path is introduced; current domain jobs keep their existing behavior and only improve run-count truth.
|
|
- Graph contract path: PASS. No new Graph/provider seam is introduced.
|
|
- Deterministic capabilities: PASS. Authorization and progress eligibility stay deterministic and testable.
|
|
- RBAC-UX: PASS. Visibility remains on existing tenant/admin boundaries and `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`; only count truth is enriched.
|
|
- Ops-UX summary counts: PASS. The rollout stays on current whitelist semantics and numeric-only values.
|
|
- Test governance: PASS. Proof remains bounded to Unit plus Feature.
|
|
- Proportionality / no premature abstraction: PASS. No new abstraction or persistence is introduced.
|
|
- Persisted truth / behavioral state: PASS. No new table, cache, or status 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 safeguards; Feature for selected writer rollouts and current shell adoption
|
|
- **Affected validation lanes**: fast-feedback, confidence
|
|
- **Why this lane mix is the narrowest sufficient proof**: domain feature suites already exist for the in-scope writer families, and the shared contract already has a focused unit suite. Browser proof remains owned by Spec 268 because this slice does not alter layout or clickability.
|
|
- **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/Inventory/RunInventorySyncJobTest.php tests/Feature/ReviewPack/ReviewPackGenerationTest.php tests/Feature/Evidence/GenerateEvidenceSnapshotJobTest.php tests/Feature/BackupSets/AddPoliciesToBackupSetJobTest.php tests/Unit/BulkBackupSetRestoreJobTest.php tests/Feature/OpsUx/ActivityFeedbackSurfaceTest.php tests/Feature/OpsUx/BulkOperationProgressDbOnlyTest.php`
|
|
- **Fixture / helper / factory / seed / context cost risks**: low to moderate; reuse current tenant context helpers and current job-specific fixtures instead of introducing new provider-heavy harnesses
|
|
- **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 families now emit truthful counts, excluded phased families remain excluded, and no writer bypasses `OperationRunService`
|
|
- **Budget / baseline / trend follow-up**: none expected beyond a small feature-local increase
|
|
- **Review-stop questions**: did any excluded run family sneak in, did any writer invent totals, did `processed` stay bounded by `total`, and did any new summary key or local progress helper appear?
|
|
- **Escalation path**: `reject-or-split` for any baseline phased/composite widening, dashboard redesign, or persisted progress model
|
|
- **Active feature PR close-out entry**: Guardrail / Smoke Coverage
|
|
- **Why no dedicated follow-up spec is needed**: this package is itself the bounded writer-rollout follow-through on Spec 270; any remaining excluded families are already named as future follow-ups.
|
|
|
|
## Project Structure
|
|
|
|
### Documentation (this feature)
|
|
|
|
```text
|
|
specs/271-counted-progress-rollout/
|
|
├── 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/Jobs/RunInventorySyncJob.php
|
|
apps/platform/app/Services/Inventory/InventorySyncService.php
|
|
apps/platform/app/Jobs/GenerateReviewPackJob.php
|
|
apps/platform/app/Services/ReviewPackService.php
|
|
apps/platform/app/Jobs/GenerateEvidenceSnapshotJob.php
|
|
apps/platform/app/Services/Evidence/EvidenceSnapshotService.php
|
|
apps/platform/app/Jobs/AddPoliciesToBackupSetJob.php
|
|
apps/platform/app/Jobs/BulkBackupSetRestoreJob.php
|
|
apps/platform/app/Jobs/Operations/BackupSetRestoreWorkerJob.php
|
|
apps/platform/tests/Unit/Support/OpsUx/
|
|
apps/platform/tests/Feature/Inventory/
|
|
apps/platform/tests/Feature/ReviewPack/
|
|
apps/platform/tests/Feature/Evidence/
|
|
apps/platform/tests/Feature/BackupSets/
|
|
apps/platform/tests/Feature/OpsUx/
|
|
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 new progress rollout framework or a second writer abstraction.
|
|
|
|
## Data / Migration Implications
|
|
|
|
- No migration or schema change is planned.
|
|
- No new persisted progress mode or preference is allowed.
|
|
- No backfill is planned. Historical runs remain historical truth; the rollout affects future execution 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 run-count truth.
|
|
- No destructive action or confirmation model changes are planned.
|
|
- No deployment step beyond ordinary code deploy and current test validation is expected.
|
|
|
|
## Risk Controls
|
|
|
|
- Reject any implementation that changes progress-contract precedence to force phased runs into counted mode.
|
|
- Reject any implementation that adds new `summary_counts` keys or uses outcome counters as hidden progress substitutes.
|
|
- Reject any implementation that sets totals from speculative estimates instead of deterministic current work sets.
|
|
- Reject any implementation that initializes parent totals multiple times or allows child retries to double-increment `processed`.
|
|
- Reject any implementation that broadens the rollout to unrelated run families not named in the spec and tasks.
|
|
|
|
## Implementation Phases
|
|
|
|
### Phase 0 - Confirm Selected Stable-Unit Writer Seams
|
|
|
|
- Verify current counted and terminal-only seams in inventory sync, review-pack generation, evidence-snapshot generation, `AddPoliciesToBackupSetJob`, `BulkBackupSetRestoreJob`, and `BackupSetRestoreWorkerJob`.
|
|
- Reconfirm that baseline capture/compare remain phased under the current contract and stay out of scope.
|
|
|
|
### Phase 1 - Roll Out Inventory And Artifact Writer Counts
|
|
|
|
- Add or standardize `total` plus `processed` writes for inventory sync, review-pack generation, and evidence-snapshot generation.
|
|
|
|
### Phase 2 - Standardize Enumerated Backup/Restore Fan-Out Counts
|
|
|
|
- Align `AddPoliciesToBackupSetJob`, `BulkBackupSetRestoreJob`, and `BackupSetRestoreWorkerJob` on one total/processed discipline and current `maybeCompleteBulkRun()` semantics.
|
|
|
|
### Phase 3 - Lock The Guardrail And Proof
|
|
|
|
- Update the UI standards and focused tests so later run families do not re-open fake or partial counted rollout.
|
|
|
|
## Proportionality Review
|
|
|
|
- **Current operator problem**: determinable long-running work still looks indeterminate because selected writers do not persist counts early enough or consistently enough.
|
|
- **Existing structure is insufficient because**: the shared contract already exists and cannot invent counted progress from terminal summaries alone.
|
|
- **Narrowest correct implementation**: update only repo-verified stable-unit writers and leave all other families on their current truthful modes.
|
|
- **Ownership cost created**: targeted job/service tests and one standards update.
|
|
- **Alternative intentionally rejected**: broad all-writers rollout or phased-precedence changes were rejected because they would widen into a second spec.
|
|
- **Release truth**: current-release truth. The repo already contains the contract, the visible adopter, and the selected writers needed for this rollout.
|