# Tasks: Baseline Capture Truthful Outcomes and Upstream Guardrails **Input**: Design documents from `/specs/235-baseline-capture-truth/` **Prerequisites**: `plan.md`, `spec.md`, `research.md`, `data-model.md`, `quickstart.md` **Tests**: Required. This feature changes runtime behavior and operator truth on an existing queued workflow, so Pest coverage must be added or updated in `apps/platform/tests/Feature/Baselines/BaselineCaptureTest.php`, `apps/platform/tests/Feature/Filament/BaselineProfileCaptureStartSurfaceTest.php`, `apps/platform/tests/Feature/Filament/BaselineCompareLandingStartSurfaceTest.php`, `apps/platform/tests/Feature/Filament/BaselineCaptureResultExplanationSurfaceTest.php`, `apps/platform/tests/Feature/Filament/OperationRunBaselineTruthSurfaceTest.php`, `apps/platform/tests/Feature/Monitoring/GovernanceOperationRunSummariesTest.php`, `apps/platform/tests/Feature/Monitoring/AuditCoverageGovernanceTest.php`, `apps/platform/tests/Feature/Notifications/OperationRunNotificationTest.php`, and `apps/platform/tests/Feature/Authorization/OperatorExplanationSurfaceAuthorizationTest.php`. `apps/platform/tests/Feature/Baselines/BaselineSnapshotBackfillTest.php` remains conditional and is only updated if implementation proves historical empty complete snapshots still affect current runtime truth. **Operations**: Existing `baseline_capture` `OperationRun` remains canonical. Tasks below explicitly preserve the Ops-UX 3-surface feedback contract, keep `OperationRun.status` and `OperationRun.outcome` service-owned through `apps/platform/app/Services/OperationRunService.php`, keep `summary_counts` flat and numeric-only, avoid any queued/running DB notification drift, and preserve initiator-null Monitoring-only behavior for scheduled/system runs. **RBAC**: No new authorization model is introduced, but the touched admin `/admin`, tenant-context `/admin/t/{tenant}/baseline-compare`, and Monitoring `/admin/operations/{run}` surfaces must preserve current capability enforcement and `404` versus `403` semantics through existing helpers and regression coverage in `apps/platform/tests/Feature/Authorization/OperatorExplanationSurfaceAuthorizationTest.php`. **UI Naming**: Operator-facing copy must remain baseline-domain specific and centralized through `apps/platform/app/Support/ReasonTranslation/ReasonTranslator.php`, `apps/platform/app/Support/Baselines/BaselineCompareStats.php`, `apps/platform/app/Support/OpsUx/GovernanceRunDiagnosticSummaryBuilder.php`, `apps/platform/app/Support/OpsUx/OperationUxPresenter.php`, and `apps/platform/app/Support/Ui/OperatorExplanation/OperatorExplanationBuilder.php`. No task may introduce page-local copy branches for blocked or no-data baseline capture truth. **Cross-Cutting Shared Pattern Reuse**: This is a shared interaction slice. Extend `apps/platform/app/Support/Baselines/BaselineReasonCodes.php`, `apps/platform/app/Support/ReasonTranslation/ReasonTranslator.php`, `apps/platform/app/Support/Baselines/BaselineCompareStats.php`, `apps/platform/app/Support/OpsUx/GovernanceRunDiagnosticSummaryBuilder.php`, `apps/platform/app/Support/OpsUx/OperationUxPresenter.php`, and `apps/platform/app/Support/Ui/OperatorExplanation/OperatorExplanationBuilder.php` before considering any local UI branching. **UI / Surface Guardrails**: `review-mandatory` slice. Surfaces stay `native` Filament plus shared baseline/Ops UX primitives. Required coverage is `standard-native-filament` plus `monitoring-state-page`; no exception path is planned. **Filament UI Action Surfaces**: No new Resource, Page, or destructive action is introduced. `apps/platform/app/Filament/Resources/BaselineProfileResource/Pages/ViewBaselineProfile.php`, `apps/platform/app/Filament/Pages/BaselineCompareLanding.php`, and `apps/platform/app/Filament/Resources/BaselineSnapshotResource/Pages/ViewBaselineSnapshot.php` keep their current action topology, existing confirmation-gated capture actions, and current global-search-disabled posture. **Badges**: No new badge domain or outcome family is introduced. Existing blocked and `partially_succeeded` semantics remain centralized through current outcome and Ops UX renderers; avoid ad-hoc badge/status mappings in Filament. **Organization**: Tasks are grouped by user story so each slice stays independently testable. Recommended delivery order is `US1` then `US2` then `US3`, because zero-subject and Monitoring truth depend on the shared reason-code and run-context groundwork from the false-green capture fix. ## Test Governance Checklist - [X] Lane assignment is named and is the narrowest sufficient proof for the changed behavior. - [X] New or changed tests stay in the smallest honest family, and any heavy-governance or browser addition is explicit. - [X] Shared helpers, factories, seeds, fixtures, and context defaults stay cheap by default; any widening is isolated or documented. - [X] Planned validation commands cover the change without pulling in unrelated lane cost. - [X] The declared surface test profile or `standard-native-filament` relief is explicit. - [X] Any material budget, baseline, trend, or escalation note is recorded in the active spec or PR. ## Phase 1: Setup (Shared Anchors) **Purpose**: Lock the implementation anchors and proving commands before touching runtime truth. - [X] T001 [P] Verify the feature anchor inventory across `apps/platform/app/Services/Baselines/BaselineCaptureService.php`, `apps/platform/app/Jobs/CaptureBaselineSnapshotJob.php`, `apps/platform/app/Support/Baselines/BaselineReasonCodes.php`, `apps/platform/app/Support/ReasonTranslation/ReasonTranslator.php`, `apps/platform/app/Support/Baselines/BaselineCompareStats.php`, `apps/platform/app/Support/OpsUx/GovernanceRunDiagnosticSummaryBuilder.php`, `apps/platform/app/Filament/Resources/BaselineProfileResource/Pages/ViewBaselineProfile.php`, `apps/platform/app/Filament/Pages/BaselineCompareLanding.php`, and `apps/platform/app/Filament/Resources/BaselineSnapshotResource/Pages/ViewBaselineSnapshot.php` - [X] T002 [P] Verify the narrow proving commands, guardrail class, and validation-lane expectations in `specs/235-baseline-capture-truth/plan.md` and `specs/235-baseline-capture-truth/quickstart.md` **Checkpoint**: Runtime anchors and proof commands are locked before implementation begins. --- ## Phase 2: Foundational (Blocking Truth Boundaries) **Purpose**: Audit the shared boundaries that every story depends on so the implementation does not widen or drift into local fixes. **CRITICAL**: No user story work should begin until this phase is complete. - [X] T003 [P] Audit latest relevant inventory lookup, terminal-outcome interpretation, and no-stale-fallback boundaries in `apps/platform/app/Services/Baselines/BaselineCaptureService.php` and `apps/platform/app/Jobs/CaptureBaselineSnapshotJob.php` - [X] T004 [P] Audit current baseline promotion and consumability boundaries in `apps/platform/app/Models/BaselineProfile.php`, `apps/platform/app/Models/BaselineSnapshot.php`, and `apps/platform/app/Jobs/CaptureBaselineSnapshotJob.php` - [X] T005 [P] Audit shared explanation and copy consumers across `apps/platform/app/Support/Baselines/BaselineCompareStats.php`, `apps/platform/app/Support/ReasonTranslation/ReasonTranslator.php`, `apps/platform/app/Support/OpsUx/GovernanceRunDiagnosticSummaryBuilder.php`, `apps/platform/app/Support/OpsUx/OperationUxPresenter.php`, `apps/platform/app/Support/Ui/OperatorExplanation/OperatorExplanationBuilder.php`, `apps/platform/app/Filament/Resources/BaselineProfileResource/Pages/ViewBaselineProfile.php`, `apps/platform/app/Filament/Pages/BaselineCompareLanding.php`, and `apps/platform/app/Filament/Resources/BaselineSnapshotResource/Pages/ViewBaselineSnapshot.php` - [X] T006 [P] Audit existing `baseline_capture` run-truth enforcement in `apps/platform/app/Services/OperationRunService.php`, `apps/platform/tests/Feature/Filament/OperationRunBaselineTruthSurfaceTest.php`, `apps/platform/tests/Feature/Monitoring/GovernanceOperationRunSummariesTest.php`, and `apps/platform/tests/Feature/Authorization/OperatorExplanationSurfaceAuthorizationTest.php` so service-owned transitions, numeric `summary_counts`, and `404` versus `403` expectations are explicit before story work begins **Checkpoint**: The shared inventory, artifact-truth, Ops-UX, and auth boundaries are explicit and safe to extend. --- ## Phase 3: User Story 1 - Block False-Green Capture Starts (Priority: P1) 🎯 MVP **Goal**: Prevent baseline capture from reporting success when the latest relevant inventory basis is missing, blocked, failed, or otherwise non-credible. **Independent Test**: Seed no inventory, blocked latest inventory, failed latest inventory, unusable coverage, and after-enqueue drift scenarios, then prove capture start or execution never lands on `succeeded` and never advances effective baseline truth. ### Tests for User Story 1 - [X] T007 [P] [US1] Expand `apps/platform/tests/Feature/Baselines/BaselineCaptureTest.php` for no inventory, blocked latest inventory, failed latest inventory, unusable coverage, after-enqueue prerequisite drift, older-success-does-not-fallback, and clean consumable-success scenarios including the success-path run-context and audit metadata contract - [X] T008 [P] [US1] Expand `apps/platform/tests/Feature/Filament/BaselineProfileCaptureStartSurfaceTest.php` for shared preflight blocking copy and preserved confirmation-gated capture action topology on `Capture baseline` and `Capture baseline (full content)` actions - [X] T009 [P] [US1] Expand `apps/platform/tests/Feature/Authorization/OperatorExplanationSurfaceAuthorizationTest.php` to preserve the authorized happy-path access proof plus `404` versus `403` semantics on the profile capture explanation path and related Monitoring/detail surfaces touched by blocked prerequisite truth ### Implementation for User Story 1 - [X] T010 [P] [US1] Extend `apps/platform/app/Support/Baselines/BaselineReasonCodes.php` with deterministic capture-prerequisite reason codes for missing inventory, blocked inventory, failed inventory, unusable coverage, and `baseline.capture.zero_subjects` - [X] T011 [P] [US1] Extend `apps/platform/app/Support/ReasonTranslation/ReasonTranslator.php` with centralized operator-safe wording and next steps for `Run tenant sync first`, `Latest inventory sync failed`, `Latest inventory sync was blocked`, unusable-coverage outcomes, and `No subjects were in scope` - [X] T012 [US1] Implement latest relevant inventory eligibility preflight in `apps/platform/app/Services/Baselines/BaselineCaptureService.php` so known non-credible prerequisites short-circuit before `OperationRun` creation - [X] T013 [US1] Re-check latest relevant inventory inside `apps/platform/app/Jobs/CaptureBaselineSnapshotJob.php` and resolve blocked terminal truth through `apps/platform/app/Services/OperationRunService.php` with numeric `summary_counts`, upstream inventory run reference, chosen eligibility decision, terminal reason code, current-baseline-change flag, and no queued/running DB-notification drift - [X] T014 [US1] Update `apps/platform/app/Filament/Resources/BaselineProfileResource/Pages/ViewBaselineProfile.php` and any capture-result explanation consumers to use the shared translated prerequisite truth while preserving existing confirmation-gated action placement and capability enforcement **Checkpoint**: User Story 1 is independently functional and capture can no longer false-green on non-credible latest inventory truth. --- ## Phase 4: User Story 2 - Keep No-Data Captures Visible but Non-Authoritative (Priority: P2) **Goal**: Let zero-subject captures remain auditable without allowing them to replace the current trustworthy baseline. **Independent Test**: Capture against credible inventory that resolves zero in-scope subjects and verify `partially_succeeded`, no promotion of baseline truth, and clear no-data artifact messaging on affected surfaces. ### Tests for User Story 2 - [X] T015 [P] [US2] Expand `apps/platform/tests/Feature/Baselines/BaselineCaptureTest.php` for zero-subject capture, preserved previous consumable snapshot, and absence of `succeeded` when no usable baseline was captured - [X] T016 [P] [US2] Expand `apps/platform/tests/Feature/Filament/BaselineCaptureResultExplanationSurfaceTest.php` for no-data artifact messaging, current-versus-historical truth on profile and snapshot explanation surfaces, and profile-level compare affordance guidance after blocked or no-data capture outcomes - [X] T017 [P] [US2] Expand `apps/platform/tests/Feature/Filament/BaselineCompareLandingStartSurfaceTest.php` for prior-trustworthy-baseline preservation versus no-current-baseline guidance after blocked latest-inventory and zero-subject capture outcomes ### Implementation for User Story 2 - [X] T018 [US2] Refactor zero-subject handling in `apps/platform/app/Jobs/CaptureBaselineSnapshotJob.php` to short-circuit before existing consumable snapshot reuse or `active_snapshot_id` promotion, emit `OperationRunOutcome::PartiallySucceeded`, and record the no-data reason, `baseline_capture.subjects_total`, `result.snapshot_lifecycle` when present, plus effect on current baseline truth - [X] T019 [US2] Reuse existing lifecycle/usability semantics in `apps/platform/app/Models/BaselineSnapshot.php` and the finalization payloads from `apps/platform/app/Jobs/CaptureBaselineSnapshotJob.php` so any zero-subject artifact stays non-consumable and stores no-data finalization metadata instead of a new lifecycle state - [X] T020 [US2] Preserve `BaselineProfile::resolveCurrentConsumableSnapshot()` behavior in `apps/platform/app/Models/BaselineProfile.php` and update `apps/platform/app/Filament/Resources/BaselineSnapshotResource/Pages/ViewBaselineSnapshot.php` plus `apps/platform/app/Filament/Resources/BaselineProfileResource/Pages/ViewBaselineProfile.php` to distinguish current trustworthy baseline from no-data evidence - [X] T021 [US2] Update `apps/platform/app/Support/Baselines/BaselineCompareStats.php`, `apps/platform/app/Filament/Pages/BaselineCompareLanding.php`, and profile-level compare affordances in `apps/platform/app/Filament/Resources/BaselineProfileResource/Pages/ViewBaselineProfile.php` so compare availability derives from effective consumable baseline truth after blocked, failed, or no-data capture outcomes rather than latest capture completion or snapshot existence alone - [X] T022 [US2] If implementation proves historical empty complete snapshots still influence current runtime truth, adjust the relevant legacy finalization path and `apps/platform/tests/Feature/Baselines/BaselineSnapshotBackfillTest.php` inside the same slice; otherwise record in `specs/235-baseline-capture-truth/quickstart.md` and the active PR close-out note that no compatibility backfill change was required **Checkpoint**: User Story 2 is independently functional and zero-subject capture remains visible without becoming authoritative baseline truth. --- ## Phase 5: User Story 3 - Explain All-Zero Capture Truth On Monitoring Surfaces (Priority: P3) **Goal**: Ensure Monitoring leads with the dominant blocked or no-data explanation before raw counts or JSON. **Independent Test**: Open seeded blocked and zero-subject baseline capture runs in Monitoring and verify the dominant cause and next step appear before diagnostics. ### Tests for User Story 3 - [X] T023 [P] [US3] Expand `apps/platform/tests/Feature/Monitoring/GovernanceOperationRunSummariesTest.php` for blocked latest inventory, failed latest inventory, after-enqueue drift, and zero-subject no-usable-baseline headlines - [X] T024 [P] [US3] Expand `apps/platform/tests/Feature/Filament/OperationRunBaselineTruthSurfaceTest.php`, `apps/platform/tests/Feature/Monitoring/AuditCoverageGovernanceTest.php`, and `apps/platform/tests/Feature/Notifications/OperationRunNotificationTest.php` for consistent blocked or `partially_succeeded` baseline-capture truth, audit summary wording including whether current baseline truth changed, and initiator-aware terminal notification behavior ### Implementation for User Story 3 - [X] T025 [P] [US3] Extend `apps/platform/app/Support/OpsUx/GovernanceRunDiagnosticSummaryBuilder.php` with dominant explanation and next-step branches for blocked latest inventory, after-enqueue drift, failed inventory, unusable coverage, and zero-subject no-data capture - [X] T026 [US3] Reconcile shared run-detail and operator-explanation consumption across `apps/platform/app/Support/ReasonTranslation/ReasonTranslator.php`, `apps/platform/app/Support/Baselines/BaselineCompareStats.php`, `apps/platform/app/Support/OpsUx/OperationUxPresenter.php`, and `apps/platform/app/Support/Ui/OperatorExplanation/OperatorExplanationBuilder.php` so Monitoring, compare landing, and audit prose use the same baseline-domain vocabulary and explicitly communicate whether current baseline truth changed without page-local fallbacks - [X] T027 [US3] Update `apps/platform/app/Notifications/OperationRunCompleted.php` and any baseline-capture completion payload helpers so terminal notification copy reflects the same dominant reason, communicates whether current baseline truth changed, and preserves initiator-aware delivery rules for interactive versus initiator-null runs **Checkpoint**: User Story 3 is independently functional and Monitoring explains blocked/no-data baseline truth before diagnostics. --- ## Phase 6: Polish & Cross-Cutting Validation **Purpose**: Finish formatting, verify there is no local truth drift, and run the narrow proving pack. - [X] T028 [P] Search the touched runtime and surface files `apps/platform/app/Services/Baselines/BaselineCaptureService.php`, `apps/platform/app/Jobs/CaptureBaselineSnapshotJob.php`, `apps/platform/app/Support/ReasonTranslation/ReasonTranslator.php`, `apps/platform/app/Support/Baselines/BaselineCompareStats.php`, `apps/platform/app/Support/OpsUx/GovernanceRunDiagnosticSummaryBuilder.php`, `apps/platform/app/Filament/Resources/BaselineProfileResource/Pages/ViewBaselineProfile.php`, `apps/platform/app/Filament/Pages/BaselineCompareLanding.php`, `apps/platform/app/Filament/Resources/BaselineSnapshotResource/Pages/ViewBaselineSnapshot.php`, `apps/platform/app/Support/OpsUx/OperationUxPresenter.php`, and `apps/platform/app/Support/Ui/OperatorExplanation/OperatorExplanationBuilder.php` to confirm no page-local explanation branches or stale-success fallback logic remain - [X] T029 Run formatting for all touched PHP and test files with `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent` - [X] T030 [P] Run the baseline capture and Filament surface validation pack from `specs/235-baseline-capture-truth/quickstart.md` against `apps/platform/tests/Feature/Baselines/BaselineCaptureTest.php`, `apps/platform/tests/Feature/Filament/BaselineProfileCaptureStartSurfaceTest.php`, `apps/platform/tests/Feature/Filament/BaselineCompareLandingStartSurfaceTest.php`, and `apps/platform/tests/Feature/Filament/BaselineCaptureResultExplanationSurfaceTest.php` - [X] T031 [P] Run the Monitoring, audit/notification, and authorization validation pack from `specs/235-baseline-capture-truth/quickstart.md` against `apps/platform/tests/Feature/Filament/OperationRunBaselineTruthSurfaceTest.php`, `apps/platform/tests/Feature/Monitoring/GovernanceOperationRunSummariesTest.php`, `apps/platform/tests/Feature/Monitoring/AuditCoverageGovernanceTest.php`, `apps/platform/tests/Feature/Notifications/OperationRunNotificationTest.php`, and `apps/platform/tests/Feature/Authorization/OperatorExplanationSurfaceAuthorizationTest.php` - [X] T032 [P] Run `apps/platform/tests/Feature/Baselines/BaselineSnapshotBackfillTest.php` only if `T022` changed legacy empty-snapshot classification behavior - [X] T033 Record the Guardrail close-out entry in `specs/235-baseline-capture-truth/quickstart.md` and the active PR description for `Guardrail` status, `standard-native-filament` plus `monitoring-state-page` coverage, and whether `T022` resolved as `document-in-feature` or required a follow-up --- ## Dependencies & Execution Order ### Phase Dependencies - **Setup (Phase 1)**: Starts immediately and locks anchors plus proving commands. - **Foundational (Phase 2)**: Depends on Setup and blocks all story work until shared truth boundaries are explicit. - **User Story 1 (Phase 3)**: Depends on Foundational and is the MVP cut. - **User Story 2 (Phase 4)**: Depends on User Story 1 because zero-subject truth builds on the new reason-code and eligibility groundwork in the same capture workflow. - **User Story 3 (Phase 5)**: Depends on User Story 1 and User Story 2 because Monitoring must reflect the final blocked and no-data truth contract. - **Polish (Phase 6)**: Depends on all completed story work. ### User Story Dependencies - **US1**: No dependency beyond Foundational. - **US2**: Depends on US1 shared reason-code, run-context, and preflight/runtime truth changes. - **US3**: Depends on US1 and US2 shared truth being complete. ### Within Each User Story - Write the story tests first and confirm they fail before implementation is considered complete. - Keep copy and explanation centralized through shared baseline and Ops UX helpers. - Preserve current confirmation-gated action topology and existing capability enforcement. - Preserve `OperationRunService` ownership of terminal status and outcome transitions. - Finish story-level validation before moving to the next dependent story. ### Parallel Opportunities - `T001` and `T002` can run in parallel during Setup. - `T003`, `T004`, `T005`, and `T006` can run in parallel during Foundational work. - `T007`, `T008`, and `T009` can run in parallel for User Story 1; `T010` and `T011` can also proceed in parallel before `T012` through `T014`. - `T015`, `T016`, and `T017` can run in parallel for User Story 2 before the implementation sequence `T018` through `T022`. - `T023` and `T024` can run in parallel for User Story 3 before `T025` through `T027`. - `T030`, `T031`, and `T032` can run in parallel during final validation when their prerequisites are satisfied. --- ## Parallel Example: User Story 1 ```bash # User Story 1 tests in parallel T007 apps/platform/tests/Feature/Baselines/BaselineCaptureTest.php T008 apps/platform/tests/Feature/Filament/BaselineProfileCaptureStartSurfaceTest.php T009 apps/platform/tests/Feature/Authorization/OperatorExplanationSurfaceAuthorizationTest.php # Shared reason and translation groundwork in parallel T010 apps/platform/app/Support/Baselines/BaselineReasonCodes.php T011 apps/platform/app/Support/ReasonTranslation/ReasonTranslator.php ``` ## Parallel Example: User Story 2 ```bash # User Story 2 tests in parallel T015 apps/platform/tests/Feature/Baselines/BaselineCaptureTest.php T016 apps/platform/tests/Feature/Filament/BaselineCaptureResultExplanationSurfaceTest.php T017 apps/platform/tests/Feature/Filament/BaselineCompareLandingStartSurfaceTest.php ``` ## Parallel Example: User Story 3 ```bash # User Story 3 tests in parallel T023 apps/platform/tests/Feature/Monitoring/GovernanceOperationRunSummariesTest.php T024 apps/platform/tests/Feature/Filament/OperationRunBaselineTruthSurfaceTest.php ``` --- ## Implementation Strategy ### MVP First (User Story 1 Only) 1. Complete Phase 1: Setup. 2. Complete Phase 2: Foundational. 3. Complete Phase 3: User Story 1. 4. Run `T029` and `T030` before widening the slice. ### Incremental Delivery 1. Ship User Story 1 to eliminate false-green capture starts and runtime success on non-credible latest inventory. 2. Ship User Story 2 to keep zero-subject captures visible but non-authoritative. 3. Ship User Story 3 to align Monitoring with the hardened capture truth. 4. Finish with the final formatting, validation, and guardrail close-out tasks. ### Parallel Team Strategy 1. One contributor can prepare the shared reason-code and translation groundwork while another prepares the User Story 1 proof surfaces. 2. After User Story 1 lands, one contributor can take the zero-subject runtime path while another prepares the User Story 2 surface tests. 3. User Story 3 can start once the blocked and no-data run-context truth is stable enough for Monitoring and Ops UX proof. --- ## Notes - `[P]` tasks target different files or independent proof surfaces and can be worked in parallel once upstream blockers are cleared. - `[US1]`, `[US2]`, and `[US3]` map directly to the feature specification user stories. - No `contracts/` artifact is required for this feature because there is no external API or route contract change. - The suggested MVP scope is Phase 1 through Phase 3 only.