TenantAtlas/specs/235-baseline-capture-truth/spec.md
ahmido 2752515da5
Some checks failed
Main Confidence / confidence (push) Failing after 54s
Spec 235: harden baseline truth and onboarding flows (#271)
## Summary
- harden baseline capture truth, compare readiness, and monitoring explanations around latest inventory eligibility, blocked prerequisites, and zero-subject outcomes
- improve onboarding verification and bootstrap recovery handling, including admin-consent callback invalidation and queued execution legitimacy/report behavior
- align workspace findings/workspace overview signals and refresh the related spec, roadmap, and spec-candidate artifacts

## Validation
- `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/BaselineDriftEngine/BaselineCaptureAuditEventsTest.php tests/Feature/BaselineDriftEngine/BaselineSnapshotNoTenantIdentifiersTest.php tests/Feature/BaselineDriftEngine/CaptureBaselineContentTest.php tests/Feature/BaselineDriftEngine/CaptureBaselineFullContentOnDemandTest.php tests/Feature/BaselineDriftEngine/CaptureBaselineMetaFallbackTest.php tests/Feature/Baselines/BaselineCaptureTest.php tests/Feature/Baselines/BaselineCompareFindingsTest.php tests/Feature/Baselines/BaselineSnapshotBackfillTest.php tests/Feature/Filament/BaselineCaptureResultExplanationSurfaceTest.php tests/Feature/Filament/BaselineCompareLandingStartSurfaceTest.php tests/Feature/Filament/BaselineProfileCaptureStartSurfaceTest.php tests/Feature/Filament/OperationRunBaselineTruthSurfaceTest.php tests/Feature/Monitoring/AuditCoverageGovernanceTest.php tests/Feature/Monitoring/GovernanceOperationRunSummariesTest.php tests/Feature/Notifications/OperationRunNotificationTest.php tests/Feature/Authorization/OperatorExplanationSurfaceAuthorizationTest.php`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/AdminConsentCallbackTest.php tests/Feature/Filament/WorkspaceOverviewDbOnlyTest.php tests/Feature/Guards/Spec194GovernanceActionSemanticsGuardTest.php tests/Feature/ManagedTenantOnboardingWizardTest.php tests/Feature/Onboarding/OnboardingVerificationTest.php tests/Feature/Operations/QueuedExecutionAuditTrailTest.php tests/Unit/Operations/QueuedExecutionLegitimacyGateTest.php`

## Notes
- browser validation was not re-run in this pass

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #271
2026-04-24 05:44:54 +00:00

265 lines
37 KiB
Markdown

# Feature Specification: Baseline Capture Truthful Outcomes and Upstream Guardrails
**Feature Branch**: `235-baseline-capture-truth`
**Created**: 2026-04-23
**Status**: Draft
**Input**: User description: "Baseline Capture Truthful Outcomes and Upstream Guardrails"
## Spec Candidate Check *(mandatory — SPEC-GATE-001)*
- **Problem**: Baseline capture can still present a green success path when no credible baseline was actually produced because the upstream inventory basis was unusable or because zero in-scope subjects resolved.
- **Today's failure**: Operators can read a completed baseline capture run, an all-zero summary, or an empty/reused artifact as if the baseline was successfully refreshed even when there is no trustworthy baseline to compare against.
- **User-visible improvement**: Capture start surfaces warn early, run detail states the real cause and next action first, and a failed or no-data capture no longer silently replaces the last trustworthy baseline.
- **Smallest enterprise-capable version**: Reuse the existing snapshot lifecycle/usability rules from Spec 159 and the existing governance run-summary path from Spec 220, then harden only inventory eligibility, capture outcome mapping, reason codes, and no-data artifact promotion rules for baseline capture.
- **Explicit non-goals**: No redesign of the whole `OperationRun` platform, no broad rewrite of inventory coverage semantics, no compare-engine redesign, no generic no-data framework for all operation types, no new artifact-lifecycle taxonomy, and no silent stale-inventory fallback.
- **Permanent complexity imported**: A bounded extension of existing `BaselineReasonCodes`, translation/presenter mappings for baseline capture truth, a few targeted start-surface and run-detail states, and focused regression coverage.
- **Why now**: This is a near-term governance hardening item and a direct trust gap in one of TenantPilot's core promises: a captured baseline must be meaningful and safe to reason about.
- **Why not local**: The failure crosses capture execution, capture preflight, snapshot promotion, compare availability, Monitoring run detail, and audit/notification translation. A local copy fix would leave the same false-green semantics active elsewhere.
- **Approval class**: Core Enterprise
- **Red flags triggered**: Cross-cutting status messaging; queued-work truth semantics; current-release operator trust on a core governance artifact. Defense: the slice stays narrow by reusing existing baseline snapshot and Ops UX primitives rather than inventing a new generic framework.
- **Score**: Nutzen: 2 | Dringlichkeit: 2 | Scope: 2 | Komplexität: 1 | Produktnähe: 2 | Wiederverwendung: 2 | **Gesamt: 11/12**
- **Decision**: approve
## Spec Scope Fields *(mandatory)*
- **Scope**: workspace
- **Primary Routes**: `/admin/baseline-profiles/{record}`, `/admin/baseline-snapshots/{record}`, `/admin/t/{tenant}/baseline-compare`, `/admin/operations/{run}`
- **Data Ownership**: workspace-owned `BaselineProfile` and `BaselineSnapshot` truth, tenant-scoped baseline capture and inventory `OperationRun` context, workspace audit entries
- **RBAC**: Existing workspace membership plus current baseline visibility/capture capability on `/admin`, tenant entitlement plus current compare capability on `/admin/t/{tenant}/...`, and existing Monitoring visibility plus tenant entitlement for tenant-bound run detail
## 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, header actions, run-detail explanations, audit prose, reason translation, terminal notification copy
- **Systems touched**: baseline capture start surfaces, baseline compare availability surfaces, snapshot-truth presentation, Monitoring run detail, audit summary text, canonical reason translation
- **Existing pattern(s) to extend**: existing `BaselineCompareStats` preflight reason-code path, existing snapshot lifecycle/usability contract from Spec 159, and the governance run-summary-first path from Spec 220
- **Shared contract / presenter / builder / renderer to reuse**: `App\Support\Baselines\BaselineReasonCodes`, `App\Support\Baselines\BaselineCompareStats`, `App\Services\OperationRunService`, `App\Support\OpsUx\OperationUxPresenter`, `App\Support\OpsUx\GovernanceRunDiagnosticSummaryBuilder`, `App\Support\Ui\OperatorExplanation\OperatorExplanationBuilder`, and the existing `ReasonTranslator`
- **Why the existing shared path is sufficient or insufficient**: The existing shared path already handles compare unavailability, centralized reason translation, and summary-first governance run explanations. The gap is baseline capture truthfulness, not the lack of a shared presentation path.
- **Allowed deviation and why**: none
- **Consistency impact**: The same reason code and operator message must mean the same thing on the profile view, compare landing, snapshot view, Monitoring run detail, audit summary, and any terminal notification derived from the run.
- **Review focus**: Verify that no page-local copy branch or ad-hoc status mapping appears outside the shared baseline reason/summary/explanation path.
## 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 |
|---|---|---|---|---|---|---|
| Baseline profile view capture truth and header actions | yes | Native Filament + shared baseline/Ops UX primitives | header actions, status messaging | page, header action, related detail | no | n/a |
| Baseline compare landing availability and guidance | yes | Native Filament + shared baseline stats | header actions, status messaging, navigation handoff | page, action, explanation | no | n/a |
| Baseline snapshot detail no-data artifact messaging | yes | Native Filament + shared truth presenters | status messaging, related navigation | detail, artifact truth | no | n/a |
| Monitoring run detail for baseline capture | yes | Native Filament + shared Ops UX presenters | status messaging, run summaries, audit-aligned explanation | detail, diagnostics | no | n/a |
## 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 |
|---|---|---|---|---|---|---|---|
| Baseline profile view capture truth and header actions | Secondary Context Surface | Decide whether a new capture is safe to start or whether the current trustworthy baseline should remain in place | Effective current baseline truth, latest capture truth, next safe action | Historical snapshots, raw run context, low-level capture gaps | Not primary because it is one profile's context page, not the tenant-wide decision queue | Follows baseline maintenance workflow | Removes the need to jump to Monitoring just to learn whether capture is safe |
| Baseline compare landing availability and guidance | Primary Decision Surface | Decide whether compare can run now or whether prerequisite work is required first | Assigned profile, consumable baseline truth, dominant block reason, next action | Compare matrix, related run detail, raw artifact history | Primary because it is the tenant-scoped decision entry for compare | Follows tenant baseline review workflow | Stops operators from opening matrix or Monitoring first to discover a prerequisite failure |
| Baseline snapshot detail no-data artifact messaging | Secondary Context Surface | Decide whether a captured artifact is trustworthy, historical, or only an audit trace | Lifecycle/usability, produced-run effect, whether the artifact can become current truth | Raw metadata, counts, related run diagnostics | Not primary because it explains an artifact after the operator chooses to inspect it | Follows artifact review after capture | Prevents operators from reading a zero-item artifact as a normal complete baseline |
| Monitoring run detail for baseline capture | Tertiary Evidence / Diagnostics Surface | Understand why the run did or did not produce a usable baseline after execution | Dominant cause, next step, effect on current baseline truth | Raw JSON, numeric counts, low-level inventory references | Not primary because it is investigation after a run exists | Follows Monitoring and audit review workflow | Keeps investigation focused by stating the real capture truth before raw diagnostics |
## 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 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Baseline profile view capture truth and header actions | Detail / Record | View-first Resource | Capture baseline or keep current trustworthy snapshot | Header-led record view | n/a | Secondary safe actions in existing header grouping order | Existing archive action only, still on detail header with confirmation | `/admin/baseline-profiles` | `/admin/baseline-profiles/{record}` | Workspace context and related tenant assignment context | Baseline profiles / Baseline profile | Whether current baseline truth is still trustworthy and whether a new capture is safe | none |
| Baseline compare landing availability and guidance | Workflow / Start Surface | Explanation-first Action Landing | Run compare or fix the prerequisite first | Single-page workflow entry | forbidden | Pure navigation to compare matrix or related record stays secondary | none | `/admin/t/{tenant}/baseline-compare` | `/admin/t/{tenant}/baseline-compare` | Tenant chip, assigned profile, current baseline state | Baseline compare / Compare | Whether compare is safe to run now and why not if blocked | none |
| Baseline snapshot detail no-data artifact messaging | Detail / Record | Immutable Artifact Detail | Open related record or accept that the artifact is only historical/no-data evidence | Record detail page | required from list | Related-record links only | none | `/admin/baseline-snapshots` | `/admin/baseline-snapshots/{record}` | Workspace context, related profile, producing run | Baseline snapshots / Baseline snapshot | Whether the artifact is consumable current truth, historical, or only a no-data trace | Existing immutable-artifact exemption |
| Monitoring run detail for baseline capture | Detail / Diagnostics | Operation Run Detail | Open related baseline profile or rerun inventory/capture with the right prerequisite | Run detail page | n/a | Related artifact/navigation actions stay secondary | none | `/admin/operations` | `/admin/operations/{run}` | Workspace context plus tenant context when the run is tenant-bound | Operations / Operation run | Why the run did not produce a usable baseline and what effect it had on current baseline truth | Existing Monitoring diagnostics exemption |
## 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 |
|---|---|---|---|---|---|---|---|---|---|---|
| Baseline profile view capture truth and header actions | Workspace baseline manager | Decide whether to start a capture now | Detail / Record | Will a new capture produce a trustworthy baseline or should I fix prerequisites first? | Current effective snapshot truth, latest capture result, prerequisite summary, next step | Raw gap details, low-level inventory run metadata | execution outcome, artifact usability, lifecycle/history | Microsoft tenant + TenantPilot | Capture baseline; Compare now | Archive baseline profile |
| Baseline compare landing availability and guidance | Tenant operator | Decide whether compare can start now | Workflow / Start Surface | Can I trust the current baseline enough to compare this tenant right now? | Assigned profile, baseline availability, blocking reason or readiness message, next action | Compare matrix deep detail, raw run diagnostics | artifact usability, readiness, execution history | simulation only | Compare now; Open compare matrix | none |
| Baseline snapshot detail no-data artifact messaging | Workspace baseline manager | Decide whether a specific artifact can be trusted or safely ignored as historical/no-data evidence | Detail / Record | Is this snapshot a usable current baseline, a historical artifact, or a no-data trace? | Lifecycle/usability, producing run effect, current-vs-historical truth | Raw metadata, raw counts, low-level subject resolution detail | artifact usability, lifecycle/history | TenantPilot only | Open related record | none |
| Monitoring run detail for baseline capture | Workspace operator | Diagnose the real cause of a non-usable capture result | Detail / Diagnostics | Why did this capture not give me a trustworthy baseline? | Dominant reason, next step, whether current baseline changed | Raw JSON, low-level counts, internal IDs | execution outcome, readiness, artifact usability | read-only | Open related profile; Open related snapshot if present | none |
## Proportionality Review *(mandatory when structural complexity is introduced)*
- **New source of truth?**: no
- **New persisted entity/table/artifact?**: no
- **New abstraction?**: no
- **New enum/state/reason family?**: yes, a bounded extension of the existing baseline capture reason-code family
- **New cross-domain UI framework/taxonomy?**: no
- **Current operator problem**: A core governance workflow can report success without a trustworthy baseline, which directly misleads operators and auditors.
- **Existing structure is insufficient because**: The current shape checks capture completion too loosely and lets status/outcome, snapshot existence, and compare availability drift apart across start surfaces, Monitoring, and artifact truth.
- **Narrowest correct implementation**: Reuse existing `BaselineSnapshot` lifecycle/usability semantics and existing Ops UX summary/explanation builders, then add only the missing eligibility rules, reason codes, and promotion guardrails for baseline capture.
- **Ownership cost**: Small ongoing cost in one reason-code family, one translation path, a handful of presenter branches, and focused baseline/Monitoring regression tests.
- **Alternative intentionally rejected**: A page-local copy fix or a generic artifact-truth framework. The first would leave contradictory behavior active elsewhere; the second would import much more structure than the problem needs.
- **Release truth**: current-release truth
### Compatibility posture
This feature assumes a pre-production environment.
Backward compatibility, legacy aliases, migration shims, historical fixtures, and compatibility-specific tests remain out of scope unless implementation proves that one existing historical baseline-capture path must be backfilled deliberately.
Canonical replacement is preferred over preservation.
## Testing / Lane / Runtime Impact *(mandatory for runtime behavior changes)*
- **Test purpose / classification**: Feature
- **Validation lane(s)**: fast-feedback, confidence
- **Why this classification and these lanes are sufficient**: The change is proved by baseline capture outcome mapping, compare-start availability, and Monitoring run-detail truth on existing runtime paths. Focused feature coverage is the narrowest sufficient proof; no browser or heavy-governance lane is needed.
- **New or expanded test families**: Expand baseline capture service/start-surface coverage, compare availability coverage, Monitoring baseline-capture run-detail truth coverage, and one positive plus one negative authorization case on affected surfaces.
- **Fixture / helper cost impact**: Low-to-moderate. Tests can reuse current baseline/inventory fixtures but need explicit seeded inventory-run outcomes for no inventory, blocked inventory, failed inventory, valid-zero-subjects, and previous-good-snapshot preservation.
- **Heavy-family visibility / justification**: none
- **Special surface test profile**: mixed: standard-native-filament + monitoring-state-page
- **Standard-native relief or required special coverage**: Ordinary feature coverage is sufficient, but it must include both profile-level action surfaces and Monitoring run detail so explanation and promotion truth cannot drift apart.
- **Reviewer handoff**: Confirm that no test still encodes "empty capture succeeds", that the last trustworthy snapshot remains current after blocked/no-data capture paths, that Monitoring leads with the dominant explanation before raw JSON, and that 404 vs 403 behavior is preserved on the touched surfaces.
- **Budget / baseline / trend impact**: Low increase in baseline and Monitoring feature assertions only; no new heavy or browser baseline expected.
- **Escalation needed**: none
- **Active feature PR close-out entry**: Guardrail
- **Planned validation commands**:
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Baselines/BaselineCaptureTest.php`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Filament/BaselineProfileCaptureStartSurfaceTest.php tests/Feature/Filament/BaselineCompareLandingStartSurfaceTest.php tests/Feature/Filament/BaselineCaptureResultExplanationSurfaceTest.php`
- `cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Filament/OperationRunBaselineTruthSurfaceTest.php tests/Feature/Monitoring/GovernanceOperationRunSummariesTest.php tests/Feature/Monitoring/AuditCoverageGovernanceTest.php tests/Feature/Notifications/OperationRunNotificationTest.php tests/Feature/Authorization/OperatorExplanationSurfaceAuthorizationTest.php`
## User Scenarios & Testing *(mandatory)*
### User Story 1 - Block false-green capture starts (Priority: P1)
As a baseline manager, I need baseline capture to stop telling me it succeeded when there was no credible inventory basis to build from.
**Why this priority**: This is the core trust repair. If the feature does not eliminate false-green capture outcomes, the main problem remains.
**Independent Test**: Can be fully tested by seeding baseline profiles with no inventory run, blocked inventory run, and failed inventory run, then asserting that capture start/execution returns deterministic blocked truth and never advances effective baseline state.
**Acceptance Scenarios**:
1. **Given** an active baseline profile and no relevant inventory sync for the target tenant, **When** a baseline manager tries to capture a new baseline, **Then** the operator-facing result explains that inventory must run first, and the resulting truth never lands on `succeeded`.
2. **Given** an active baseline profile and the latest relevant inventory sync ended `blocked` or `failed`, **When** capture is started, **Then** the capture result is blocked with a baseline-capture-specific reason code, and the previously effective complete snapshot remains current baseline truth.
---
### User Story 2 - Keep no-data captures visible but non-authoritative (Priority: P2)
As a baseline manager, I need a zero-subject capture to be visible as an auditable event without being treated like a trustworthy current baseline.
**Why this priority**: Zero-subject captures are the sharpest form of silent false reassurance after bad upstream prerequisites.
**Independent Test**: Can be fully tested by capturing against valid inventory that resolves zero in-scope subjects and verifying partial success, no promotion of baseline truth, and no-data artifact messaging where an artifact exists.
**Acceptance Scenarios**:
1. **Given** a credible inventory basis but zero subjects in the effective baseline scope, **When** capture runs, **Then** the run ends `partially_succeeded` with a stable `zero_subjects` reason code and does not replace the current consumable snapshot.
2. **Given** a previous complete snapshot exists and a later capture resolves zero in-scope subjects, **When** operators inspect the profile, snapshot, or compare-start surface, **Then** the product still points to the earlier trustworthy snapshot as current baseline truth and renders the newer result only as no-data evidence.
---
### User Story 3 - Explain all-zero capture truth on Monitoring surfaces (Priority: P3)
As an operator reviewing capture history, I need Monitoring to tell me why a capture produced no usable baseline before showing raw counts or JSON.
**Why this priority**: Even with corrected outcomes, operators will still lose trust if Monitoring forces them to decode all-zero counts manually.
**Independent Test**: Can be fully tested by opening seeded baseline capture runs in Monitoring and asserting that the dominant cause and next step are visible before diagnostics.
**Acceptance Scenarios**:
1. **Given** a baseline capture run was blocked because the latest inventory sync failed, **When** an operator opens the Monitoring run detail page, **Then** the page leads with that blocked prerequisite and the next step before raw diagnostics.
2. **Given** a baseline capture run technically completed processing but resolved zero in-scope subjects, **When** an operator opens the Monitoring run detail page, **Then** the page states that no usable baseline was captured, explains the zero-subject result, and clarifies that current baseline truth was not advanced.
### Edge Cases
- The latest relevant inventory sync is blocked or failed, but an older successful inventory sync still exists. The system must not silently fall back to the older success in V1.
- A zero-subject capture may persist a snapshot row or related artifact for audit purposes. If it does, that artifact must remain non-consumable and visibly marked as no-data evidence.
- A blocked or no-data capture can occur while a prior complete snapshot is still current. Operator surfaces must show that the old trustworthy snapshot remains effective.
- A capture can be preflight-blocked on the start surface and still need the same protection at execution time if prerequisite state changes after page load.
- Scheduled or initiator-null capture runs must keep current Ops UX behavior: no terminal DB notification, Monitoring remains the audit surface, and the same dominant-cause explanation still applies.
## Requirements *(mandatory)*
**Constitution alignment (required):** This feature changes existing baseline capture runtime behavior and operator truth but introduces no new Microsoft Graph endpoint, no new `OperationRun` type, and no new contract-registry object family. Existing capture start actions stay confirmation-gated, execution remains auditable and observable, and tenant/workspace isolation remains unchanged.
**Constitution alignment (PROP-001 / ABSTR-001 / PERSIST-001 / STATE-001 / BLOAT-001):** This feature does not add new persistence or a new abstraction layer. It extends an existing reason-code family because the current baseline capture truth is too weak and because page-local messaging would duplicate semantics across profile, compare, snapshot, and Monitoring surfaces.
**Constitution alignment (XCUT-001):** This is a cross-cutting interaction slice. It must extend the existing baseline reason/translation/stats path and the existing Ops UX run-summary path. No page may introduce a parallel local explanation language for blocked or no-data baseline capture outcomes.
**Constitution alignment (TEST-GOV-001):** Proof stays in focused feature coverage for baseline capture service/start surfaces and Monitoring run detail. No new heavy-governance or browser coverage is required. New fixtures must remain explicit and scenario-driven rather than becoming default test setup.
**Constitution alignment (OPS-UX):** Existing `baseline_capture` runs continue to use the three-surface feedback contract: start-intent feedback, active progress surfaces, and one terminal DB notification for interactive runs. `OperationRun.status` and `OperationRun.outcome` remain service-owned via `OperationRunService`. `summary_counts` remain numeric-only and compliant with existing summary-count rules. Scheduled or initiator-null runs still skip terminal DB notification. Regression coverage must prove that blocked/no-data capture truth does not bypass service-owned transitions.
**Constitution alignment (RBAC-UX):** The affected planes are admin `/admin` for baseline profile/snapshot surfaces, tenant-context `/admin/t/{tenant}/baseline-compare` for compare availability, and canonical `/admin/operations/{run}` Monitoring for capture detail. Non-members or non-entitled tenant viewers continue to receive 404. Members lacking the required current capability continue to receive 403. Server-side enforcement remains authoritative on every touched action/start surface. No raw capability strings or role-name checks may be introduced.
**Constitution alignment (OPS-EX-AUTH-001):** No `/auth/*` behavior is added or broadened.
**Constitution alignment (BADGE-001):** Any changed availability or no-data wording must stay centralized through existing baseline reason/badge/presenter semantics rather than ad-hoc page mappings.
**Constitution alignment (UI-FIL-001):** The feature reuses existing native Filament header actions, detail sections, and shared presenters. No local replacement markup is introduced for badges, alerts, or status language.
**Constitution alignment (UI-NAMING-001):** Primary operator-facing language must stay baseline-domain specific and consistent across buttons, modals, Monitoring summaries, notifications, and audit prose: `Capture baseline`, `Compare now`, `Run tenant sync first`, `Latest inventory sync failed`, `No subjects were in scope`, and `No usable baseline was captured`.
**Constitution alignment (DECIDE-001):** This feature does not add a new primary surface. It hardens one existing primary decision surface (`BaselineCompareLanding`), two secondary context surfaces (profile/snapshot detail), and one tertiary diagnostics surface (Monitoring run detail) so the first decision is based on trustworthy baseline truth rather than inferred success.
**Constitution alignment (UI-CONST-001 / UI-SURF-001 / ACTSURF-001 / UI-HARD-001 / UI-EX-001 / UI-REVIEW-001 / HDR-001):** The action hierarchy stays unchanged. Navigation remains separate from mutation. Existing compare and capture header actions keep their current placement. No new action groups or destructive actions are introduced.
**Constitution alignment (ACTSURF-001 - action hierarchy):** Existing visible safe header actions remain meaningful and bounded: one capture action and one compare action stay peer visible actions, mode-specific full-content labels replace the default labels instead of adding extra peer actions, and additional safe actions stay grouped under `More`. No new mixed catch-all action groups are added.
**Constitution alignment (OPSURF-001):** The default-visible truth on touched surfaces must stay operator-first: current trustworthy baseline, dominant failure/no-data cause, next action, and effect on baseline truth before raw implementation detail.
**Constitution alignment (UI-SEM-001 / LAYER-001 / TEST-TRUTH-001):** The feature extends existing explanation layers because direct mapping from `status = completed` or zero counts to the UI is insufficient. It must not create a second artifact-truth source beside the existing snapshot lifecycle/usability contract.
**Constitution alignment (Filament Action Surfaces):** The Action Surface Contract remains satisfied. Each touched Filament surface keeps one primary inspect/open model, no redundant view actions are added, no empty `ActionGroup` placeholders are introduced, and destructive-action placement remains unchanged.
**Constitution alignment (UX-001 — Layout & Information Architecture):** Existing profile/snapshot view layouts and explanation-first workflow layouts remain in place. This feature changes explanation and availability truth, not overall screen layout.
### Functional Requirements
- **FR-235-001**: Baseline capture eligibility MUST evaluate the most recent relevant inventory sync for the same workspace and target tenant scope using terminal outcome and coverage usability, not `status = completed` alone.
- **FR-235-002**: The system MUST treat each of the following as non-credible capture prerequisites with deterministic baseline-capture reason codes in `BaselineReasonCodes`: no relevant inventory sync exists, the latest relevant inventory sync is `blocked`, the latest relevant inventory sync is `failed`, or the latest relevant inventory sync lacks usable coverage for baseline subject resolution.
- **FR-235-003**: Baseline capture start surfaces MUST preflight known non-credible inventory prerequisites and explain the block with the same reason-code family used at runtime. Server-side capture execution remains authoritative if prerequisite state changes after page load.
- **FR-235-004**: When baseline capture is attempted without a credible inventory basis, the resulting operator truth MUST never land on `succeeded`. The terminal capture truth MUST use a blocked prerequisite outcome with the matching baseline-capture reason code.
- **FR-235-005**: `Succeeded` MUST be reserved for capture runs that produce or reuse a consumable baseline snapshot backed by at least one resolved in-scope subject and that leave effective baseline truth anchored to that consumable snapshot.
- **FR-235-006**: When inventory is credible but zero in-scope subjects resolve, baseline capture MUST finish as `partially_succeeded` with a stable `baseline.capture.zero_subjects` reason code.
- **FR-235-007**: A zero-subject capture MUST NOT advance `active_snapshot_id` or any equivalent effective-baseline pointer. The previously effective complete snapshot, if one exists, remains current baseline truth.
- **FR-235-008**: If implementation persists a snapshot row or related artifact for a zero-subject capture, that artifact MUST reuse the existing snapshot lifecycle/usability contract, remain non-consumable by default, render as a no-data capture artifact on operator surfaces, and never become current baseline truth automatically.
- **FR-235-009**: Capture eligibility in V1 MUST NOT silently fall back to an older successful inventory sync when a newer relevant inventory sync is blocked, failed, or otherwise non-credible. Older successful inventory runs may be shown as historical context only.
- **FR-235-010**: Monitoring run detail for baseline capture MUST lead with one dominant operator-safe explanation and next action before raw JSON, low-level counts, or internal identifiers.
- **FR-235-011**: Baseline capture run context, summary, and audit prose MUST record the chosen eligibility decision, the upstream inventory run reference when present, the terminal baseline-capture reason code, and whether current baseline truth changed.
- **FR-235-012**: Existing baseline compare availability surfaces, including `BaselineCompareLanding` and profile-level compare affordances, MUST derive availability from effective consumable baseline truth after hardened capture outcomes, not from snapshot existence or latest capture completion alone.
- **FR-235-013**: The feature MUST keep copy and translation centralized by extending `BaselineReasonCodes`, `ReasonTranslator`, `BaselineCompareStats`, and the existing Ops UX summary/explanation path rather than adding page-local message branches.
- **FR-235-014**: Existing `Capture baseline` and `Capture baseline (full content)` actions MUST remain confirmation-gated, capability-enforced, and placed on their current surfaces. This feature changes truth and explanation only, not action topology.
- **FR-235-015**: Regression coverage MUST replace existing assumptions that an empty or all-zero baseline capture is a benign success and MUST cover no inventory, blocked inventory, failed inventory, zero-subject capture, and preservation of the previously trustworthy snapshot.
### Assumptions
- Existing snapshot lifecycle/usability semantics from Spec 159 remain the baseline artifact truth source.
- Existing governance run-summary/explanation primitives from Spec 220 remain the Monitoring explanation path.
- The product chooses strict truthful capture behavior in V1: no silent stale-inventory fallback.
- Zero-subject results may remain visible as audit evidence, but they do not become authoritative baseline truth.
### Dependencies and Related Specs
- Spec 159 (`baseline-snapshot-truth`) remains the source of truth for snapshot lifecycle/usability semantics.
- Spec 220 (`governance-run-summaries`) remains the shared Monitoring explanation path for dominant-cause run detail.
- Specs 116-119 remain the shipped baseline drift/cutover foundation that this spec hardens on the capture side.
- Existing baseline compare availability and reason translation paths remain in scope for reuse, not redesign.
## 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 |
|---|---|---|---|---|---|---|---|---|---|---|
| Baseline profile view | `app/Filament/Resources/BaselineProfileResource/Pages/ViewBaselineProfile.php` | One visible capture action (`Capture baseline` or `Capture baseline (full content)` depending on mode), one visible compare action (`Compare now` or `Compare now (full content)` depending on mode), plus secondary safe actions grouped under `More` | Existing list `recordUrl()` to view page | Existing `View` / `Edit` pattern unchanged | None | Existing create CTA unchanged on list | Same visible capture/compare actions plus existing related navigation and grouped secondary actions | Existing save/cancel unchanged | Yes | Capture/compare actions stay confirmation-gated and capability-enforced. Capture baseline remains the primary visible header action; Compare now remains a justified visible secondary safe action on this record page because the operator's same-context decision is whether to refresh baseline truth first or use the current trustworthy snapshot immediately. Mode-specific full-content labels replace the default labels rather than adding extra peer header actions. Existing archive action remains the only destructive action and still requires confirmation. |
| Baseline compare landing | `app/Filament/Pages/BaselineCompareLanding.php` | `Compare now`, `Compare now (full content)` | n/a | None | None | Existing `Open compare matrix` remains the single empty/blocked-state CTA where applicable | n/a | n/a | Yes, via compare run/audit | This feature changes readiness and blocking guidance only. The page remains the primary compare decision/start surface. |
| Baseline snapshot view | `app/Filament/Resources/BaselineSnapshotResource/Pages/ViewBaselineSnapshot.php` | None | Existing clickable list row | Existing related-record navigation only | None | None by design | Existing related-record actions only | n/a | No direct mutation audit | Immutable-resource exemption remains. This feature changes lifecycle/usability explanation for no-data artifacts only. |
| Monitoring run detail | Existing Monitoring run detail surface resolved through `OperationUxPresenter` | Existing related navigation only | n/a | n/a | n/a | n/a | Existing related navigation only | n/a | Yes | No new actions are introduced. The body must show the dominant baseline-capture truth before diagnostics. |
### Key Entities *(include if feature involves data)*
- **BaselineProfile**: The workspace-owned governance definition whose effective baseline truth must remain anchored to the last consumable snapshot.
- **BaselineSnapshot**: The captured baseline artifact whose existing lifecycle/usability semantics determine whether it can become current baseline truth.
- **Inventory Sync OperationRun**: The upstream tenant-scoped execution record whose credibility determines whether baseline capture may trust the current inventory basis.
- **Baseline Capture OperationRun**: The execution record that communicates blocked, partial, or successful capture truth to operators, Monitoring, audit, and notifications.
## Success Criteria *(mandatory)*
### Measurable Outcomes
- **SC-235-001**: In focused regression coverage, 100% of baseline-capture attempts without a credible inventory basis end without `succeeded` and expose a deterministic baseline-capture reason code.
- **SC-235-002**: In focused regression coverage, 100% of valid-zero-subject capture scenarios end `partially_succeeded`, do not advance effective baseline truth, and preserve the previously consumable snapshot when one exists.
- **SC-235-003**: On the default-visible baseline profile, compare landing, snapshot detail, and Monitoring run-detail surfaces touched by this feature, operators can identify the dominant cause and next step without opening raw diagnostics.
- **SC-235-004**: No automated test path or default-visible operator surface treats an all-zero baseline capture as an unconditional successful baseline refresh after this feature lands.
- **SC-235-005**: Compare availability remains aligned to effective consumable baseline truth after every covered blocked or no-data capture regression path.