## Summary <!-- Kurz: Was ändert sich und warum? --> ## Spec-Driven Development (SDD) - [ ] Es gibt eine Spec unter `specs/<NNN>-<feature>/` - [ ] Enthaltene Dateien: `plan.md`, `tasks.md`, `spec.md` - [ ] Spec beschreibt Verhalten/Acceptance Criteria (nicht nur Implementation) - [ ] Wenn sich Anforderungen während der Umsetzung geändert haben: Spec/Plan/Tasks wurden aktualisiert ## Implementation - [ ] Implementierung entspricht der Spec - [ ] Edge cases / Fehlerfälle berücksichtigt - [ ] Keine unbeabsichtigten Änderungen außerhalb des Scopes ## Tests - [ ] Tests ergänzt/aktualisiert (Pest/PHPUnit) - [ ] Relevante Tests lokal ausgeführt (`./vendor/bin/sail artisan test` oder `php artisan test`) ## Migration / Config / Ops (falls relevant) - [ ] Migration(en) enthalten und getestet - [ ] Rollback bedacht (rückwärts kompatibel, sichere Migration) - [ ] Neue Env Vars dokumentiert (`.env.example` / Doku) - [ ] Queue/cron/storage Auswirkungen geprüft ## UI (Filament/Livewire) (falls relevant) - [ ] UI-Flows geprüft - [ ] Screenshots/Notizen hinzugefügt ## Notes <!-- Links, Screenshots, Follow-ups, offene Punkte --> Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #223
201 lines
13 KiB
Markdown
201 lines
13 KiB
Markdown
# Implementation Plan: Baseline Compare Matrix: High-Density Operator Mode
|
|
|
|
**Branch**: `191-baseline-compare-operator-mode` | **Date**: 2026-04-11 | **Spec**: `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/191-baseline-compare-operator-mode/spec.md`
|
|
**Input**: Feature specification from `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/191-baseline-compare-operator-mode/spec.md`
|
|
|
|
**Note**: This plan formalizes the existing 191 spec slice and keeps the work strictly inside the already-shipped Spec 190 matrix surface.
|
|
|
|
## Summary
|
|
|
|
Refactor the existing workspace baseline compare matrix into an adaptive operator-density surface. The route, baseline reference, visible-set-only truth, compare-start behavior, and drilldowns stay unchanged, but the page gains local presentation-mode state, dense multi-tenant scanning, compact single-tenant rendering, staged heavy-filter application, grouped legends, and clearer separation between blocking refresh, passive auto-refresh, and last-updated status.
|
|
|
|
## Technical Context
|
|
|
|
**Language/Version**: PHP 8.4.15
|
|
**Primary Dependencies**: Laravel 12, Filament v5, Livewire v4, Pest v4, Tailwind CSS v4, existing `BaselineCompareMatrixBuilder`, `BadgeCatalog`, `CanonicalNavigationContext`, and `UiEnforcement` patterns
|
|
**Storage**: PostgreSQL via existing baseline, assignment, compare-run, and finding tables; no new persistence planned
|
|
**Testing**: Pest feature tests and browser smoke coverage run through Laravel Sail
|
|
**Target Platform**: Laravel monolith web application under `apps/platform`
|
|
**Project Type**: web application
|
|
**Performance Goals**: Improve scan throughput without increasing query shape beyond Spec 190, keep heavy filter changes non-chatty, and preserve DB-only render-time matrix surfaces
|
|
**Constraints**: No compare-logic change, no new persistence, no hidden-tenant leakage, no generalized density framework, no provider or panel changes, and no new asset pipeline
|
|
**Scale/Scope**: One existing matrix page, one existing Blade view, one existing builder, one logical contract file, and focused feature plus browser regressions
|
|
|
|
## Constitution Check
|
|
|
|
*GATE: Passed before Phase 0 research. Re-checked after Phase 1 design and still passing.*
|
|
|
|
| Principle | Pre-Research | Post-Design | Notes |
|
|
|-----------|--------------|-------------|-------|
|
|
| Inventory-first / snapshots-second | PASS | PASS | The spec changes presentation only and keeps Spec 190 truth sources intact. |
|
|
| Read/write separation | PASS | PASS | `Compare assigned tenants` remains the only mutation and is unchanged. |
|
|
| Graph contract path | N/A | N/A | No new Graph behavior or contract-registry work is introduced. |
|
|
| Deterministic capabilities | PASS | PASS | Existing capabilities remain canonical and unchanged. |
|
|
| Workspace + tenant isolation | PASS | PASS | Visible-set-only aggregation and drilldown scope remain unchanged. |
|
|
| RBAC-UX authorization semantics | PASS | PASS | Existing `404` vs `403` semantics and server-side enforcement remain unchanged. |
|
|
| Run observability / Ops-UX | PASS | PASS | Compare-run truth is reused exactly as in Spec 190; this spec only clarifies the visual cues around it. |
|
|
| Data minimization | PASS | PASS | No new data copies, exports, or persisted UI artifacts are introduced. |
|
|
| Proportionality / anti-bloat | PASS | PASS | The work stays local to one page and does not add a new abstraction or stored artifact. |
|
|
| Persisted truth / behavioral state | PASS | PASS | Presentation mode and staged filter state remain request-scoped only. |
|
|
| UI semantics / few layers | PASS | PASS | Existing state, trust, freshness, and severity semantics are reused rather than redefined. |
|
|
| Filament v5 / Livewire v4 compliance | PASS | PASS | The work remains inside the existing Filament page and Livewire-backed route. |
|
|
| Provider registration location | PASS | PASS | No provider changes are required; Laravel 11+ registration remains in `bootstrap/providers.php`. |
|
|
| Global search hard rule | PASS | PASS | No new searchable resource or page is introduced. |
|
|
| Destructive action safety | PASS | PASS | No destructive action is added. Existing confirmation behavior for compare-start remains unchanged. |
|
|
| Asset strategy | PASS | PASS | No new assets are required. Existing deployment behavior for `cd apps/platform && php artisan filament:assets` remains unchanged. |
|
|
|
|
## Filament-Specific Compliance Notes
|
|
|
|
- **Livewire v4.0+ compliance**: This plan remains on Filament v5 + Livewire v4 and does not introduce legacy APIs.
|
|
- **Provider registration location**: No panel or provider changes are needed; Laravel 11+ provider registration remains in `bootstrap/providers.php`.
|
|
- **Global search**: The feature does not add a new globally searchable resource. Existing baseline-resource search behavior is unchanged.
|
|
- **Destructive actions**: No new destructive action is introduced. Existing compare-start actions remain confirmation-gated where already defined.
|
|
- **Asset strategy**: No new global or on-demand asset registration is planned. Deployment handling of `cd apps/platform && php artisan filament:assets` remains unchanged.
|
|
- **Testing plan**: Extend the existing matrix feature, builder, guard, and browser suites to cover presentation mode, staged filter application, and non-blocking status surfaces.
|
|
|
|
## Phase 0 Research
|
|
|
|
Research outcomes are captured in `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/191-baseline-compare-operator-mode/research.md`.
|
|
|
|
Key decisions:
|
|
|
|
- Keep the existing matrix route and truth model and change presentation only.
|
|
- Resolve `auto`, `dense`, and `compact` mode from visible tenant count, with a route-local override only.
|
|
- Make dense mode state-first rather than action-first.
|
|
- Render single-tenant review as a compact compare list rather than a one-column matrix.
|
|
- Convert heavy filters to staged apply/reset semantics.
|
|
- Replace the long policy-type checkbox stack with a more compact operator-first selector.
|
|
- Group legends into compact support context and separate blocking refresh from passive auto-refresh and last-updated cues.
|
|
- Reuse existing drilldown and visible-set semantics unchanged.
|
|
|
|
## Phase 1 Design
|
|
|
|
Design artifacts are created under `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/191-baseline-compare-operator-mode/`:
|
|
|
|
- `research.md`: decisions and rejected alternatives for local operator-density work
|
|
- `data-model.md`: request-scoped presentation models for mode state, staged filters, dense rows, compact results, and support-surface state
|
|
- `contracts/baseline-compare-operator-mode.logical.openapi.yaml`: internal logical contract for adaptive rendering and staged filter application
|
|
- `quickstart.md`: implementation and verification sequence for the follow-up spec
|
|
|
|
Design decisions:
|
|
|
|
- `auto` remains the default requested mode and resolves to `dense` for multiple visible tenants and `compact` for exactly one visible tenant.
|
|
- Manual mode override remains route-local and must never become stored product truth.
|
|
- Dense mode reuses existing compare truth but condenses cell content to state, trust, freshness, and attention.
|
|
- Compact mode reuses the same truth but removes pseudo-matrix structure once only one visible tenant remains.
|
|
- Heavy filter inputs stage locally and apply explicitly; lightweight route-state changes may remain immediate.
|
|
- Grouped legends, passive auto-refresh, and last-updated signals become support context rather than competing top-level content.
|
|
|
|
## Project Structure
|
|
|
|
### Documentation (this feature)
|
|
|
|
```text
|
|
specs/191-baseline-compare-operator-mode/
|
|
├── plan.md
|
|
├── research.md
|
|
├── data-model.md
|
|
├── quickstart.md
|
|
├── spec.md
|
|
├── tasks.md
|
|
├── contracts/
|
|
│ └── baseline-compare-operator-mode.logical.openapi.yaml
|
|
└── checklists/
|
|
└── requirements.md
|
|
```
|
|
|
|
### Source Code (repository root)
|
|
|
|
```text
|
|
apps/platform/
|
|
├── app/
|
|
│ ├── Filament/
|
|
│ │ └── Pages/
|
|
│ │ └── BaselineCompareMatrix.php
|
|
│ └── Support/
|
|
│ └── Baselines/
|
|
│ └── BaselineCompareMatrixBuilder.php
|
|
├── resources/views/filament/pages/
|
|
│ └── baseline-compare-matrix.blade.php
|
|
└── tests/
|
|
├── Browser/
|
|
│ └── Spec190BaselineCompareMatrixSmokeTest.php
|
|
├── Feature/
|
|
│ ├── Baselines/
|
|
│ │ └── BaselineCompareMatrixBuilderTest.php
|
|
│ ├── Filament/
|
|
│ │ └── BaselineCompareMatrixPageTest.php
|
|
│ └── Guards/
|
|
│ └── ActionSurfaceContractTest.php
|
|
└── Unit/
|
|
└── Badges/
|
|
```
|
|
|
|
**Structure Decision**: Keep the work inside the existing Spec 190 matrix implementation surface. This is a presentation refactor of one existing page and its supporting builder/view behavior, not a new domain slice or a new application area.
|
|
|
|
## Complexity Tracking
|
|
|
|
| Violation | Why Needed | Simpler Alternative Rejected Because |
|
|
|-----------|------------|-------------------------------------|
|
|
| None | N/A | The follow-up stays within the existing page, builder, and test surfaces and introduces no new structural violation. |
|
|
|
|
## Proportionality Review
|
|
|
|
- **Current operator problem**: The matrix already answers the right governance question, but not with enough density or calmness for repeated operator scanning.
|
|
- **Existing structure is insufficient because**: The current single rendering shape tries to serve both multi-tenant and single-tenant workflows, so supporting context, action repetition, and cell chrome are too heavy in both cases.
|
|
- **Narrowest correct implementation**: Keep the same route, truth sources, drilldowns, and compare semantics while adding route-local presentation state, denser rendering, and staged filter application.
|
|
- **Ownership cost created**: Additional view-state logic, a logical contract file, and focused regression coverage for mode resolution, filter workflow, and status visibility.
|
|
- **Alternative intentionally rejected**: A generalized density framework, a separate dense-report route, or a stored matrix artifact were rejected because the problem is local to the existing matrix surface.
|
|
- **Release truth**: current-release operator workflow compression
|
|
|
|
## Implementation Strategy
|
|
|
|
### Phase A — Presentation Mode Contract
|
|
|
|
- Add route-local `auto`, `dense`, and `compact` mode state.
|
|
- Resolve the active mode from visible tenant count unless manually overridden.
|
|
- Expose `lastUpdatedAt`, `hasStagedFilterChanges`, and passive auto-refresh state to the page.
|
|
|
|
### Phase B — Dense Multi-Tenant Surface
|
|
|
|
- Keep the subject column sticky during horizontal scroll.
|
|
- Condense dense cells to state, trust, freshness, and attention signals.
|
|
- Move repeated actions into compact secondary affordances without breaking drilldown continuity.
|
|
|
|
### Phase C — Compact Single-Tenant Surface
|
|
|
|
- Replace pseudo-matrix rendering with a compact subject-result list when only one visible tenant remains.
|
|
- Remove repeated tenant headers and duplicated secondary metadata.
|
|
- Preserve subject focus and the existing compare/finding/run destinations.
|
|
|
|
### Phase D — Supporting Context Compression
|
|
|
|
- Convert heavy matrix filters to staged apply/reset behavior.
|
|
- Replace the current long policy-type control with a more compact selector.
|
|
- Group or collapse legends.
|
|
- Separate blocking refresh from passive auto-refresh and last-updated status.
|
|
|
|
### Phase E — Verification
|
|
|
|
- Extend focused feature coverage for mode resolution, staged filter behavior, and support-surface state.
|
|
- Extend browser smoke coverage for one dense-mode path and one compact-mode path.
|
|
- Keep existing Spec 190 matrix truth, drilldown continuity, and RBAC guarantees green.
|
|
|
|
## Risk Assessment
|
|
|
|
| Risk | Impact | Likelihood | Mitigation |
|
|
|------|--------|------------|------------|
|
|
| Dense mode becomes another framework | Medium | Low | Keep presentation logic local to the matrix page and avoid generalized shared abstractions. |
|
|
| Compact mode hides too much follow-up value | Medium | Medium | Preserve one clear primary drilldown per subject and keep existing follow-up destinations intact. |
|
|
| Staged filtering feels slow or unclear | Medium | Medium | Show explicit staged/applied state and keep reset obvious. |
|
|
| Manual override confuses operators | Low | Medium | Keep `auto` as the default and surface the resolved mode clearly. |
|
|
| Last-updated and auto-refresh cues drift out of sync | Medium | Low | Derive both cues from the same rendered matrix payload and active-run state. |
|
|
|
|
## Test Strategy
|
|
|
|
- Extend `BaselineCompareMatrixPageTest` for requested vs resolved mode, active filter application, compact vs dense rendering, and non-blocking refresh cues.
|
|
- Extend `BaselineCompareMatrixBuilderTest` for any new derived presentation metadata required by the page.
|
|
- Keep `ActionSurfaceContractTest` green so calmer actions do not regress the surface contract.
|
|
- Extend `Spec190BaselineCompareMatrixSmokeTest` to prove one dense-mode and one compact-mode operator path on the Livewire page.
|
|
- Run the focused Sail verification pack from `quickstart.md` and re-run `update-agent-context.sh copilot` after the plan is finalized.
|