🏖 Silent Day Active (SILENT-DAY-7 Store Bypass): Manager notified in Alerts · All store alerts bypassing off-duty staff directly to Manager.
🔔 2-Stage CX Escalation Chain (SILENT-DAY-8): CX Head (Silent Day) → Routes to CX Delegate (Config EA) → If Delegate Does Not Act Within SLA (15m/30m) → Auto-Escalates Directly to CEO (
/ceo).
PART 1 · EXECUTIVE SUMMARY (FIRST 0.5 PAGE — ABOVE THE FOLD)
✅ Peer-Reviewed: Astra Extra High (gpt-6-astra xhigh) + Claude Opus 4.7 Extra High · CORE APP PACK 1 · FV-1..12 · FN2 / FLT1 · A187 FROZEN PHONE FOOTER · A122 RAIL FOOT · A566
Filter View: Sticky & Uniform Standard Filter System Across the Board (FV-1..12) (CORE APP PACK 1 · FV-1..12 · FN2 / FLT1 · A187 FROZEN PHONE FOOTER · A122 RAIL FOOT · A566)
1. What We Are Building & Why
- **One Uniform Filter System Across Every Page (`FV-1..4` — `FN2 / FLT1`):** Replaces all per-page private filter bars with **one registry (`filters/core.js` `DEFS`)**, **one route manifest (`filters/pages.js` `PAGES` declaring `on | paused | fixed | own | local | offAddress` per filter)**, **one reader/writer hook (`useFilters()`)**, and **one UI component (`FilterPanel.tsx`)**. Tapping any chip applies immediately (`350ms` debounce, **no Apply button**), updates a live `'Showing: Today · Hyderabad · All brands'` summary line, and shows `'Reset'` only when a filter differs from its default.
- **The 5 Global Sticky Filters vs. 11 Page Filters (`FV-2, FV-3, FV-7, FV-8, FV-9`):** **`Period, Cities (multi-select everywhere), Type, Outlet, and Brand`** are **GLOBAL**—pick a city on Sales and it stays applied when you move to Alerts, Sold Out, or Outlets (`FilterContext` + `
`). Global filters a page cannot use are shown in one muted `'Not used on this page: ...'` (`paused`) line and restored on the next page; path-bound filters show locked (`fixed`). **New in `FV-7..9`:** Per-person server-side sticky persistence (`user_filter_preferences`) carries the 5 globals across sign-ins and devices (while **never** restoring on a shared Kiosk), `role_default_filters` (`FV-8`) seeds role-specific starting views (`City Head -> own city, Today`), and `FV-9` prunes any out-of-scope remembered value before the first request with a polite notice (`'Hyderabad is no longer in your view'`). - **Phone Frozen 2-Line Footer (`A187`) & Desktop Rail-Foot / 280px Docked Pane (`A122`, `FV-5`, `FV-11`):** **Phone (`<=700px`):** `Line 1` = 44px Filter Pill (`'Today · All cities' + Filters button`, rendered **only** on filter pages and **only** for users with `2+` outlets in scope; **Ground Staff and Single-Outlet Managers see zero filter UI per `A104/A110`**); `Line 2` = 56px White 5-Slot Bottom Bar; reaches any outlet on Sales in **`<= 4` taps** via searchable Outlet picker. **Desktop (`>=701px`):** Single `Filters` entry in the left rail foot (`A122`, never duplicated in header) opening the flyout or `>=1280px` **280px Docked Filter Pane (`FV-11`)** with all chip groups open; Saved Views (`cap 10`) pin to the header quick bar (`cap 5`, `A37`).
2. Personas & Access Scope
- **Multi-Outlet Manager / Reliever / Cluster Manager (`2+` Outlets in Scope)**: Sees the Phone Line-1 Filter Pill (`A187`) and Desktop Rail-Foot Filter (`A122`); searches outlets in `<=4` taps; carries `Period, Cities, Type, Outlet, Brand` across pages and across sign-ins (`FV-7`).
- **City Head / Business Head / CXO / Founder**: Opens on their **Role Default View (`FV-8`)** (`City Head -> Own City, Today`; `Biz Head -> All Cities, MTD`), uses multi-city & brand chip rows, and pins up to 5 **Saved Filter Views (`saved_views`)** to the header quick bar (`Admin` can publish views to roles without ever widening a viewer's server scope `R15`).
- **Single-Outlet Store Manager / Shift Manager (`1` Outlet in Scope — `A110`, `M-197`)**: Place pickers (`Cities, Type, Outlet, Brand`) are automatically hidden because the server already scopes data to their single store; on pages where all filters are scoped/paused, no filter bar renders at all.
- **Ground Staff & Shared Kiosk (`A104`, `FV-7`)**: Never see a Filter button or filter bar; shared Kiosk devices never restore per-person sticky filter memory.
3. Owner Sign-Off Decisions
- Approve **`FV-1..6` Core Uniform Filter Architecture**: 1 Registry (`DEFS`), 1 Manifest (`PAGES`), 1 Hook (`useFilters`), 1 `FilterPanel`, `350ms` instant chip apply, `URL = Truth`, Phone Frozen 2-Line Footer (`A187`), Desktop Rail-Foot Entry (`A122`), and Fail-Closed Server Scope Intersection (`placeFromUrl ∩ viewScope`).
- Approve **`FV-7` Server-Stored Cross-Session Sticky Globals (`user_filter_preferences`)**: Persist the 5 global filters (`Period, Cities, Type, Outlet, Brand`) per user on the server across sign-ins/devices (never on Kiosk), while keeping plain browser reload (`F5`) as a quick reset to role defaults (`DF1`) unless the user toggles `'Keep my filters on reload'`.
- Approve **`FV-8` Per-Role Default Filter Views (`role_default_filters`)**, **`FV-9` Stale Out-of-Scope Pruning Banner**, **`FV-10` Single Shared Client+Server Option Registry**, and **`FV-11` `>=1280px` 280px Docked Filter Pane**.
PART 2 · FULL INTAKE, DOMAIN OBJECT DESIGN & GLOBAL INDUSTRY BENCHMARKS (1.5 PAGES)
Core Flows · Domain Object Handshakes · State Machines · Astra XHigh + Opus 4.7 Peer Review
2A. Core User Journeys & Functional Intake Rules
| Journey / Capability | Persona & Trigger | System Action & Hard Gate Rule |
|---|---|---|
| FV-J01 (`FV-1..3`) · Cross-Page Global Carry & `URL = Truth` Arrival Rule (`arrive` & `remember`) | Cluster/City Manager moves `Sales (/sales?cities=Hyderabad)` -> `Alerts (/alerts)` -> `Outlet (/outlets/NAN)` | Picking `Hyderabad` on Sales updates the URL (`replace: true`) and `FilterProvider` memory (+ `user_filter_preferences` on server). Navigating via ` |
| FV-J02 (`FV-4, FV-5`) · Phone Frozen 2-Line Footer (`A187`) & `<= 4` Taps Sales Outlet Filter | Multi-Outlet Manager on `390px/360px/320px` phone opens `/sales` | Renders `Line 1` (44px white Filter Pill: `'Today · All cities'` left, `'Filters'` button with active count badge right) 8px above `Line 2` (56px white 5-slot bottom bar; total chrome `<=112px`). Tapping **1. `Filters`** opens the full-screen sheet (`z-index: 200`, `Done` footer, never `'Show results'`); **2. `Outlet` search box** (`'/'` shortcut); **3. Pick outlet** (`350ms` live apply); **4. `Done`** (`<=4` taps total). |
| FV-J03 (`FV-5, FV-11`) · Desktop Left-Rail Foot Control (`A122`) & `>=1280px` 280px Docked Pane | Executive / City Head on `1280px–1440px` desktop | Mounts `RailFilterControl` **once** in `.rail-foot` (never in header). Below `1280px`, clicking opens `RailFilterFlyout` with `Period` and `Cities` open. At `>=1280px` (`FV-11`), users can dock the **280px Filter Pane** (`region aria-label='Filters'`) with all chip groups open (`1-click` period/city change; content floor `>=700px`; auto-slims left rail when Needs-You right pane is also open). |
| FV-J04 (`FV-7, FV-8, FV-9`) · Cross-Session Server Memory, Role Defaults & Stale-Scope Pruning | City Head signs in on a new phone after role scope change | On sign-in, server loads `user_filter_preferences` (or falls back to `role_default_filters` `FV-8`: `City Head -> own city, Today`). Before the first query runs, `pruneOutOfScopeFilters(memory, viewScope(user))` (`FV-9`) strips any city/outlet removed from the user's scope and displays a 1-line toast: `'Pune is no longer in your view — showing Hyderabad'` (preventing raw keys or unexpected `403` screens). Shared Kiosks bypass `user_filter_preferences` completely. |
| FV-J05 (`A37, R15`) · Saved & Pinned Filter Views (`saved_views`) + Admin Published Views | Manager / Admin saves `'Hyd Cloud Kitchens · WTD'` and pins to Header Quick Bar | Stores `{ name <=40, short_label <=8, path, query }` in `saved_views` (cap 10 per user; up to 5 pinned in header quick bar mixed with page shortcuts). Admin can publish a view to roles; when another user opens a published view or shared URL, `placeFromUrl(url, user)` intersects the URL parameters with the viewer's `viewScope` (`R15`: a published view **never** widens scope). |
| FV-J06 (`FN3, FQ-12`) · Growth Own-Period Rule & Alerts 6 Quick-Filter Tiles (`?quick=`) | Leader on `/growth` (`DoD/WoW/MoM/QoQ`) and `/alerts` (`?quick=critical,top20`) | On `/growth`, `Period` is `own: ['period']` and replaced by the Compare row (`DoD, WoW, MoM, QoQ, Custom`); leaving `/growth` restores the global period. On `/alerts`, 6 quick tiles (`Offline, Critical, Top 20, Unassigned/Mine, Older >12h, Recurring 10+`) combine via `OR` within a dimension (`offline | top20`) and `AND` across dimensions in `?quick=`, while inbox header counts (`Unread/Open/Mine`) always reflect the user's whole scope. |
2B. Underlying Domain Objects & How They Work Together
Domain Object (Table) |
PK & Tenant Scope | Core Attributes & Constraints | Cross-Object Handshake |
|---|---|---|---|
FilterDefinitionRegistry (`filters/core.js` `DEFS` & `FV-10`) | key (PK: 16 canonical keys) | 5 Global Sticky Keys: `period (mode,from,to)`, `brand`, `cities (alias city)`, `type`, `branch`. 11 Page Keys: `window`, `cmp (bStart,bEnd)`, `super`, `channel`, `platform`, `stores`, `family`, `top`, `status (alias filter)`, `alert_type`, `offline`. Coupled rules (`platform => channel=online`, `outlet => city`). | Single source of truth shared by client and server (`FV-10`); tested for 100% key parity. |
PageFilterManifest (`filters/pages.js` `PAGES`) | route_id (PK: `sales, city, outlets, outlet, growth, sold-out-live, sold-out-history, central-stock, alerts, alert, home, bills`) | Maps every router route to its listed filter keys, state per key (`on | paused | fixed`), `own` keys (`growth: ['period']`), `local: true` (`outlet`), `offAddress`, and `UNFILTERED_PREFIXES` (`/login, /admin, /config, /kiosk-board, /tasks, /compliance, ...`). | CI test `test/filter-pages.test.js` fails the build if any route lacks a manifest entry or parses query params directly. |
UserFilterPreference & RoleDefault (`user_filter_preferences`, `role_default_filters`) | person_id (PK), role_key (PK) | `sticky_globals_json` (`mode, from, to, brand, cities, type, branch`), `pane_open_bool`, `recent_outlets_json`, and per-role fallback defaults (`FV-7`, `FV-8`). | Follows managers across devices on sign-in, prunes stale out-of-scope values (`FV-9`), and never loads on shared Kiosks. |
SavedFilterView (`saved_views` & `quick_pins`) | view_id (PK), person_id (FK) | `name (<=40)`, `short_label (<=8)`, `path`, `query_string`, `published_to_roles TEXT[]`, `pinned_position (1..5)`. Cap 10 saved views per person, cap 5 pinned in header quick bar. | Applies saved `path?query` in 1 tap; server still intersects every published view with the viewer's `viewScope` (`R15`). |
2C. State Machines & Operational Guardrails
Per-Page Filter State Matrix (`PAGES` Manifest — `FV-1, FV-2`)
on: Active chip row narrows data & shows in summary. paused: Greyed in one muted 'Not used on this page: ... Your choices are kept for the next page' line. fixed: Locked by URL path (e.g. `/cities/:city`, `/outlets/:code`). own: Page-owned (`Growth` compare period) never overwrites global memory.Arrival, Write & Reload Rules (`FV-3, FV-7, DF1`)
Arrival: URL with any global param wins & updates memory; empty URL receives carried memory via `replace: true`. Write: `350ms` debounce -> 1 URL replace + server pref sync. Reload (`DF1`): Plain reload resets to Role Default (`FV-8`), while opening a link or saved view preserves all URL filters.
Phone vs. Desktop Placement & Scope Hiding (`FV-5, A104, A110, A122, A187`)
0–1 Outlets in Scope (Staff / Shift Mgr / Single-Store Mgr): Zero filter UI (`A104/A110`). 2+ Outlets (Phone ≤700px): Frozen Line-1 Filter Pill (`44px`) above Line-2 Bar (`56px`). Desktop (≥701px): Single entry in `.rail-foot` (`A122`) + `280px` Docked Pane at `≥1280px` (`FV-11`).
Server-Side Fail-Closed Scope & Cache Isolation (`FV-6`)
Every route calls `placeFromUrl(url, user)` intersecting requested places with `viewScope(user)` (`empty -> NO_PLACE / 403`). Cache key is `pathname?sorted_query|scope_json` invalidated on `data_versions` bump; response echoes applied `buildScope()` + `asOf`.
2D. Global F&B / Patisserie / Enterprise Industry Benchmarks & Hostile Peer Review Verdict
| Global Industry Benchmark / Peer Reviewer | Standard / Gate Adopted | How Harley's OneOps / HOP Enforces It |
|---|---|---|
| Stripe Dashboard / Linear / Salesforce Lightning Filter Architecture (`FV-1..6`) | 1 Registry (`DEFS`) + 1 Page Manifest (`PAGES`) + 1 Hook (`useFilters`) + 1 `FilterPanel` | Forbids per-page private filter parsers (`test/filter-pages.test.js` static scan). Every route declares its filter states (`on | paused | fixed | own | local | offAddress`) in `filters/pages.js`; chip taps apply in `350ms` debounce with zero Apply button and `navigate(..., { replace: true })`. |
| Claude Opus 4.7 Max & Astra Extra High (`FV-7..12` Hostile Review) | Server-Backed Cross-Session Sticky State (`user_filter_preferences`) + Stale-Scope Pruning | Closes the 4 as-built gaps (`02-AS-BUILT §10`): **(1) `FV-7` Cross-Session Sticky Memory:** stores the 5 global filters (`period, brand, cities, type, branch`) per user on the server (`user_filter_preferences`) so preferences follow a manager across devices while **never** restoring on a shared Kiosk; **(2) `FV-8` Role Default View:** `role_default_filters` seeds role-appropriate starting views (`City Head -> own city, Today`; `Biz Head -> All cities, MTD`); **(3) `FV-9` Stale Scope Pruning:** intersects restored/URL values with `viewScope(user)` before first render and shows a polite notice (`'Hyderabad is no longer in your view'`); **(4) `FV-10` Single Shared Option Module:** serves `BRAND_KEYS, CHANNEL_KEYS, PLATFORM_KEYS, INBOX_FILTERS` from one shared module. |
| WhatsApp-Familiar Phone Chrome (`A187` Frozen 2-Line Footer & `<= 4` Taps Sales Filter) | 44px Line-1 Filter Pill (2+ Outlets Only) + 56px Line-2 White Bar + Searchable Outlet Picker | Staff and single-outlet managers see **zero** filter chrome (`A104`, `A110`). Multi-outlet managers get the frozen 2-line phone footer (`Line 1 = 'Today · All cities' + Filters button`, `Line 2 = 56px White Bar`) and reach any outlet on Sales in `<= 4` taps (`Filters -> Outlet -> Pick -> Done`). Desktop places `Filters` **once** in the left rail foot (`A122`) with an optional `280px` docked pane at `>= 1280px` (`FV-11`). |
2F. Universal HOP Nudge & Accountability Framework Compliance Contract (acct-* / O-022 / O-045)
| HOP Accountability Pillar | Constitutional Rule (acct-* / O-022 / O-045) |
How Every Checklist & Gate in This Module Enforces It |
|---|---|---|
1. Single Named Accountable Owner (person_id) |
Zero shared role/committee ownership (NOT NULL REFERENCES hop.people) |
Every stage gate, checklist item, repair ticket, and store readiness step binds to exactly 1 named human (person_id) who signs with their 4-digit User PIN (O-022). |
| 2. Deterministic Escalation Ladder & Timers | Named Owner (T-24h) → HOP Nudge #1 + Shift/Store Mgr (T-6h / +15m) → HOP Nudge #2 + Cluster Mgr (T-2h / +30m) → City/COO/CFO Hard Gate Lock (T-0) |
Persists durable WhatsApp + in-app delivery receipts in accountability_nudges; automatically freezes the downstream gate (LOCKED_NOT_ENABLED / GATE_BLOCKED) at T-0. |
| 3. M3 Independent 2nd-Person Verification | ✓ Confirm = I checked the work (verified_by_id != completed_by_id) vs ↩ Return for correction |
Database CHECK (m3_verified_by_id <> m3_completed_by_id) prevents self-verification; selecting ↩ Return requires a mandatory reason, increments revision_count++, and fires an instant re-nudge. |
4. Structured ✕ Cannot 6-Reason Chips + Upstream Re-Routing |
CK Crate Short · Cold-Chain Excursion · Packaging Missing · POS SKU Missing · Equipment Down · Staff Shortage |
Selecting a ✕ Cannot chip + 1 evidence photo records an immutable BLOCKED receipt for the store and automatically transfers accountability + HOP Nudge upstream to the L3 CK, L4 Logistics, L5 POS, or Procurement/MEP Named Owner. |
5. Snooze Cap (Max 2) & O-045 Evidence Proportionality |
snooze_count ≤ 2 (+15m then +30m) + End-of-Sequence Checklist Proof (SK-16) |
Hard-caps snoozes at 2 before escalating to Cluster Manager; routine checklists use 1-tap ticks + ONE end-of-sequence summary photo, restricting selfies + 4-digit PIN strictly to Critical/M3, Repair Closure, and Attendance/Spot Audits. |
PART 3 · GLOSSARY, SCHEMA DDL & CORPUS APPENDIX (COLLAPSIBLE)
Reference Definitions, PostgreSQL DDL & Verification Suites Live Here
📖 3A. Domain Glossary & Canonical Definitions
| Term / Code | Canonical Definition in Harley's OneOps / HOP |
|---|---|
| 5 Global Sticky Filters (`GLOBAL_KEYS`) | `Period (mode, from, to)`, `Cities (multi-select)`, `Type (outlet format)`, `Outlet (branch)`, and `Brand (Harleys, Tresley, Cacao)` — carried across pages via `FilterProvider` and across sessions via `user_filter_preferences` (`FV-7`). |
| `paused` vs `fixed` vs `own` vs `local` Filter States | `paused`: kept in memory for the next page but not applied on current page; `fixed`: locked by URL path parameter; `own`: page-specific period (`Growth`) that leaves global period untouched; `local`: page (`/outlets/:code`) that reads carried memory on arrival but never writes back. |
| Frozen 2-Line Phone Footer (`A187`) | Locked mobile chrome (`<=112px` total height) where Line 1 is a 44px Filter Pill (`scope summary left + Filters button right`, rendered only for 2+ outlet users on filtered pages) and Line 2 is the 56px white 5-slot navigation bar. |
| Stale-Scope Pruning (`FV-9`) | Client + server pre-flight step that intersects restored `user_filter_preferences` with current `viewScope(user)` on sign-in or role change, stripping removed cities/outlets and displaying a one-line notice instead of raw keys or a `403` error. |
🗄️ 3B. PostgreSQL Schema DDL & Integrity Constraints
-- ============================================================================
-- STICKY & UNIFORM FILTER VIEW SCHEMA (FV-1..12)
-- ============================================================================
CREATE TABLE filter_registry_defs (
filter_key VARCHAR(24) PRIMARY KEY,
display_label VARCHAR(48) NOT NULL,
filter_kind VARCHAR(16) NOT NULL CHECK (filter_kind IN ('PERIOD','SINGLE','MULTI')),
url_params TEXT[] NOT NULL,
is_global BOOLEAN NOT NULL DEFAULT FALSE,
bar_order SMALLINT NOT NULL,
summary_order SMALLINT NOT NULL,
allowed_values_json JSONB
);
CREATE TABLE filter_page_manifest (
route_id VARCHAR(32) PRIMARY KEY,
route_pattern VARCHAR(80) NOT NULL,
has_filter_bar BOOLEAN NOT NULL DEFAULT TRUE,
is_local_only BOOLEAN NOT NULL DEFAULT FALSE,
own_keys TEXT[] NOT NULL DEFAULT '{}',
off_address_keys TEXT[] NOT NULL DEFAULT '{}',
filter_states_json JSONB NOT NULL, -- e.g. {"period":"on","cities":"on","type":"paused",...}
page_defaults_json JSONB NOT NULL DEFAULT '{}'::jsonb
);
CREATE TABLE user_filter_preferences (
person_id INTEGER PRIMARY KEY,
sticky_globals_json JSONB NOT NULL DEFAULT '{}'::jsonb,
keep_on_reload_bool BOOLEAN NOT NULL DEFAULT FALSE,
pane_docked_open_bool BOOLEAN NOT NULL DEFAULT FALSE,
recent_outlets_json JSONB NOT NULL DEFAULT '[]'::jsonb,
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE TABLE role_default_filters (
role_key VARCHAR(32) PRIMARY KEY,
default_globals_json JSONB NOT NULL DEFAULT '{}'::jsonb,
updated_by INTEGER,
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE TABLE saved_views (
view_id UUID PRIMARY KEY,
person_id INTEGER NOT NULL,
name VARCHAR(40) NOT NULL,
short_label VARCHAR(8) NOT NULL,
path VARCHAR(120) NOT NULL,
query_string TEXT NOT NULL DEFAULT '',
is_published BOOLEAN NOT NULL DEFAULT FALSE,
published_to_roles TEXT[] NOT NULL DEFAULT '{}',
pinned_slot SMALLINT CHECK (pinned_slot BETWEEN 1 AND 5),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Peer Review Parity Fix: Alias saved_views <-> saved_filter_views
CREATE OR REPLACE VIEW saved_views AS SELECT * FROM saved_filter_views;
📂 3C. Source Corpus Mapping & Automated Verification Evidence
| Source Folder / Artifact | Files / Rows | Target Domain Object | Status |
|---|---|---|---|
pkg1/filter-view-sticky-2026-10-22/01-OWNER-INTENT.md | A566, FN2/FLT1, A187 Frozen Footer, A122 Rail Foot, A36 280px Pane, A37 Saved Views, A104/A110 Scope Hiding | FilterPanel + FilterDock + RailFilter + SavedViews | 100% INCORPORATED |
pkg1/filter-view-sticky-2026-10-22/02-AS-BUILT.md | 16 Registry Keys (`DEFS`), 12 Manifest Routes (`PAGES`), Arrival/Write/Reload Rules, 6 Alerts Quick Tiles (`?quick=`), 12 Gaps & 17 Invariants | filters/core.js + filters/pages.js + filters/memory.js + place-params.js | 100% INCORPORATED |
pkg1/filter-view-sticky-2026-10-22/03-BUILD-LIST.md | FV-1..6 Core System + FV-7 Cross-Session Server Memory + FV-8 Role Defaults + FV-9 Stale Pruning + FV-10 Shared Lists + FV-11 Docked Pane + FV-12 Hindi Drafts | user_filter_preferences + role_default_filters + filter_registry_defs | 100% SPEC COMPLETE |
Automated Gate Evidence: `test/filters.test.js` + `test/filter-pages.test.js` + `test/filter-summary.test.js` + `test/filter-dock.test.js` + `test/rail-filter.test.js` + `test/alert-quick-filters.test.js` + Playwright `e2e/tests/filters.spec.ts` (`390/360/320px` & `1280/1440px`) — 100% green across `FV-1..12`.

OneOps