diff --git a/documentation/PROJECT__AE_Events_PressMgmt_Config_Cleanup.md b/documentation/PROJECT__AE_Events_PressMgmt_Config_Cleanup.md
index 7cf0d8b0..4aaa64f6 100644
--- a/documentation/PROJECT__AE_Events_PressMgmt_Config_Cleanup.md
+++ b/documentation/PROJECT__AE_Events_PressMgmt_Config_Cleanup.md
@@ -1,9 +1,9 @@
# Project: Pres Mgmt Config Cleanup & Config UI
-**Status:** π‘ ~70% Complete β Core Working, Cleanup Pass Needed
-**Priority:** Medium (core features functional; remaining work is deprecation + consistency)
+**Status:** π’ Complete β all Implementation Steps and known regressions resolved
+**Priority:** Low (maintenance/monitoring only β re-open if new sync inconsistencies surface)
**Created:** 2026-04-02
-**Last Updated:** 2026-06-12 (regression audit)
+**Last Updated:** 2026-06-16 (`lock_config` removed; sync is now fully unconditional)
**Related:** `TODO__Agents.md`, `PROJECT__Stores_Svelte5_Migration.md`
---
@@ -61,8 +61,8 @@ persisted store which is part of the paused Svelte 5 migration.
```typescript
interface PressMgmtRemoteCfg {
- // System
- lock_config: boolean; // true = force remoteβlocal sync (prevent user overrides)
+ // No system/lock_config field β every field below syncs unconditionally,
+ // to every browser, on every event load. Removed 2026-06-16; see note below.
// Labels (event-specific terminology overrides)
label__person_external_id: string | null; // default: 'External ID'
@@ -176,17 +176,18 @@ AFTER: pres_mgmt_loc.current.hide__session_code
### Form sections (grouped)
-1. **System** β `lock_config`
-2. **Labels** β `label__*` fields (text inputs, nullable)
-3. **Session Visibility** β `hide__session_*` toggles
-4. **Presenter Visibility** β `hide__presenter_*` toggles
-5. **Presentation Visibility** β `hide__presentation_*` toggles
-6. **Code Visibility** β `hide__*_code` toggles
-7. **Opt-in Features** β `show__*` toggles
-8. **Requirements** β `require__presenter_agree`, `require__session_agree`
-9. **Navigation Limits** β `limit__navigation`, `limit__options`
-10. **File Purpose Config** β `file_purpose_option_kv` (JSON editor or structured form)
-11. **Report Visibility** β `hide__report_kv` (key-value toggles)
+No System section β there is no `lock_config` (removed 2026-06-16).
+
+1. **Labels** β `label__*` fields (text inputs, nullable)
+2. **Session Visibility** β `hide__session_*` toggles
+3. **Presenter Visibility** β `hide__presenter_*` toggles
+4. **Presentation Visibility** β `hide__presentation_*` toggles
+5. **Code Visibility** β `hide__*_code` toggles
+6. **Opt-in Features** β `show__*` toggles
+7. **Requirements** β `require__presenter_agree`, `require__session_agree`
+8. **Navigation Limits** β `limit__navigation` (`limit__options` removed β YAGNI)
+9. **File Purpose Config** β `file_purpose_option_kv` (JSON editor or structured form)
+10. **Report Visibility** β `hide__report_kv` (key-value toggles)
---
@@ -204,13 +205,13 @@ Safe and backward compatible β old DB records fall through to `?? false` defau
## Implementation Steps
- [x] **Step 1** β Define `PressMgmtRemoteCfg` TypeScript interface (new file or in `ae_events__event.ts`)
-- [x] **Step 2** β New `ae_events_stores__pres_mgmt.svelte.ts` with `PersistedState` β οΈ **Missing:** version gate in `store_versions.ts`
-- [x] **Step 3** β Rewrite `sync_config__event_pres_mgmt()` in `ae_events__event.ts` to use canonical keys β οΈ **Issue:** `show__launcher_link_legacy` hard-coded instead of synced from remote
+- [x] **Step 2** β New `ae_events_stores__pres_mgmt.svelte.ts` with `PersistedState`, version gate wired (2026-06-16)
+- [x] **Step 3** β Rewrite `sync_config__event_pres_mgmt()` in `ae_events__event.ts` to use canonical keys; syncs unconditionally, no `lock_config` gate (2026-06-16)
- [x] **Step 4** β Build config UI page at `(pres_mgmt)/pres_mgmt/config/+page.svelte` (manager_access + edit_mode gated)
-- [ ] **Step 5** β Strip `ae_comp__event_settings_pres_mgmt_form.svelte` from settings page (or replace with a link to new page) **BLOCKING**
+- [x] **Step 5** β `ae_comp__event_settings_pres_mgmt_form.svelte` moved to trash (2026-06-16) β it was already fully orphaned (zero imports anywhere); the settings page already links to the canonical Config page with a raw-JSON fallback
- [x] **Step 6** β Migrate all `$events_loc.pres_mgmt.*` references in pres_mgmt templates to `pres_mgmt_loc.current.*`
-- [ ] **Step 7** β Update BGH (and any other active events) via new UI (blocked on Step 5)
-- [ ] **Step 8** β `npx svelte-check` clean; commit
+- [x] **Step 7** β Active events' `lock_config` keys are now just inert orphan data in the DB, ignored by the sync function β no migration needed, nothing to update
+- [x] **Step 8** β `npx svelte-check` clean
### Regression Fixes Needed (2026-06-12 Audit)
@@ -305,6 +306,21 @@ Safe and backward compatible β old DB records fall through to `?? false` defau
was never even in `ae_loc`'s declared defaults (a phantom field created ad-hoc by the
dead button), and `ae_loc.sync_local_config` is out of scope for a pres_mgmt-only pass;
defer to the planned `ae_loc` migration in `PROJECT__Stores_Svelte5_Migration.md`.
+- [x] **`lock_config` removed from `PressMgmtRemoteCfg` entirely (2026-06-16)** β the real
+ one this time (the item above was a different, dead local-only mirror of the same name).
+ This was the actual root cause of the "POC column / Hide POC sometimes works" reports.
+ `lock_config` made roughly half of `sync_config__event_pres_mgmt()`'s fields conditional:
+ they only updated in a given browser if `lock_config` happened to be `true` at the exact
+ moment that browser last synced. A field's local value therefore depended on the *history*
+ of saves, not the current setting β undebuggable from the UI, and easy to corrupt by
+ toggling Lock Config off even briefly during testing. Checked the DB: every event, old and
+ new, already had `lock_config: true` β the "unlocked, per-browser preference" use case it
+ was built for has never actually been used. Removed it from `PressMgmtRemoteCfg`,
+ `PresMgmtLocState`, the sync function (no more conditional block β every field syncs
+ unconditionally, same as labels/Require Agreements always did), and the Config page UI
+ (no more System section). Old DB records with a `lock_config` key are simply ignored now,
+ same as any other removed key. Moved the now-fully-orphaned
+ `ae_comp__event_settings_pres_mgmt_form.svelte` to trash in the same pass (Step 5).
### Step 6 scope (mechanical find-replace)
@@ -323,8 +339,11 @@ The `$events_loc.pres_mgmt` pattern appears across:
## Notes
-- The `lock_config: true` default means most events will always sync from remote.
- This is intentional β it prevents presenter laptops from drifting into different configs.
+- All pres_mgmt display config now always syncs from remote, unconditionally, to every
+ browser, on every event load (no `lock_config` toggle β removed 2026-06-16). This is
+ intentional β it prevents presenter laptops from drifting into different configs, which
+ is exactly what `lock_config: true` was meant to guarantee, minus the conditional that
+ made it fragile.
- `file_purpose_option_kv` may need a structured editor (not raw JSON) to be usable.
Consider a simple key-value form row per purpose type for Phase 2.
- QR link keys (`hide__presenter_qr_link`, `hide__session_qr_link`) appeared in LCI config
diff --git a/src/lib/ae_events/ae_events__event.ts b/src/lib/ae_events/ae_events__event.ts
index 92b02ea1..78537058 100644
--- a/src/lib/ae_events/ae_events__event.ts
+++ b/src/lib/ae_events/ae_events__event.ts
@@ -954,12 +954,20 @@ export async function process_ae_obj__event_props({
* Syncs the server-side event pres_mgmt config (mod_pres_mgmt_json) into the
* local PersistedState store (pres_mgmt_loc.current).
*
- * Called reactively in pres_mgmt/+page.svelte whenever the event object changes.
+ * Called reactively whenever the event object changes β see the sync $effect
+ * in pres_mgmt/+page.svelte, session/[session_id]/+page.svelte,
+ * presenter/[presenter_id]/+page.svelte, locations/+page.svelte,
+ * location/[event_location_id]/+page.svelte, and reports/+page.svelte. Any new
+ * pres_mgmt page that can be a first-load entry point needs the same block.
*
- * Always-synced fields: labels, requirements, access links, file config.
- * Lock-synced fields (only when lock_config=true): all visibility/hide__ toggles,
- * launcher links, navigation limits. This prevents presenter laptops from
- * drifting into different display configs across a conference.
+ * Every field in PressMgmtRemoteCfg is synced unconditionally, every call β
+ * no opt-out, no gate. (Removed 2026-06-16: a `lock_config` toggle used to make
+ * a subset of these fields conditional. In practice every event always had it
+ * set to true, and the conditional sync it created meant a field's local value
+ * depended on whatever lock_config happened to be during the LAST sync that
+ * touched that particular browser β not its current value. That's effectively
+ * undebuggable from the UI and was the root cause of several "sometimes works"
+ * bug reports. See PROJECT__AE_Events_PressMgmt_Config_Cleanup.md.)
*
* Canonical key convention (enforced here):
* hide__* β feature ON by default; true = turn off (default: false = visible)
@@ -981,8 +989,7 @@ export function sync_config__event_pres_mgmt({
const loc = pres_mgmt_loc.current;
- // --- Always sync: labels, requirements, opt-in features, file config ---
- // These are safe to always apply β they don't override local display preferences.
+ // --- Labels ---
loc.label__person_external_id =
pres_mgmt_cfg_remote?.label__person_external_id ?? 'External ID';
loc.label__presenter_external_id =
@@ -992,85 +999,77 @@ export function sync_config__event_pres_mgmt({
loc.label__session_poc_name =
pres_mgmt_cfg_remote?.label__session_poc_name ?? 'Point of Contact';
+ // --- Requirements ---
loc.require__presenter_agree =
pres_mgmt_cfg_remote?.require__presenter_agree ?? false;
loc.require__session_agree =
pres_mgmt_cfg_remote?.require__session_agree ?? false;
+ // --- Opt-in features ---
loc.show__copy_access_link =
pres_mgmt_cfg_remote?.show__copy_access_link ?? false;
loc.show__email_access_link =
pres_mgmt_cfg_remote?.show__email_access_link ?? false;
-
- // QR code feature enable β always synced (admin opt-in, not a user preference)
loc.show__session_qr =
pres_mgmt_cfg_remote?.show__session_qr ?? false;
loc.show__presenter_qr =
pres_mgmt_cfg_remote?.show__presenter_qr ?? false;
+ // --- File / report config ---
loc.file_purpose_option_kv =
pres_mgmt_cfg_remote?.file_purpose_option_kv ?? null;
-
loc.hide__report_kv = pres_mgmt_cfg_remote?.hide__report_kv ?? {};
- // --- Lock-synced: visibility, launcher, navigation, session/presenter fields ---
- // When lock_config=true the remote config wins for ALL display flags, preventing
- // local browser state from overriding the admin's event-level configuration.
- if (pres_mgmt_cfg_remote?.lock_config) {
- if (log_lvl) console.log(`sync_config__event_pres_mgmt: lock_config=true, forcing full sync`);
+ // --- Codes ---
+ loc.hide__location_code =
+ pres_mgmt_cfg_remote?.hide__location_code ?? false;
+ loc.hide__presentation_code =
+ pres_mgmt_cfg_remote?.hide__presentation_code ?? false;
+ loc.hide__presenter_code =
+ pres_mgmt_cfg_remote?.hide__presenter_code ?? false;
+ loc.hide__session_code =
+ pres_mgmt_cfg_remote?.hide__session_code ?? false;
- // Codes
- loc.hide__location_code =
- pres_mgmt_cfg_remote?.hide__location_code ?? false;
- loc.hide__presentation_code =
- pres_mgmt_cfg_remote?.hide__presentation_code ?? false;
- loc.hide__presenter_code =
- pres_mgmt_cfg_remote?.hide__presenter_code ?? false;
- loc.hide__session_code =
- pres_mgmt_cfg_remote?.hide__session_code ?? false;
+ // --- Session fields ---
+ loc.hide__session_description =
+ pres_mgmt_cfg_remote?.hide__session_description ?? false;
+ loc.hide__session_location =
+ pres_mgmt_cfg_remote?.hide__session_location ?? false;
+ loc.hide__session_msg =
+ pres_mgmt_cfg_remote?.hide__session_msg ?? false;
+ loc.hide__session_poc =
+ pres_mgmt_cfg_remote?.hide__session_poc ?? false;
+ loc.show__session_li_poc_field =
+ pres_mgmt_cfg_remote?.show__session_li_poc_field ?? false;
+ loc.hide__session_poc_biography =
+ pres_mgmt_cfg_remote?.hide__session_poc_biography ?? false;
+ loc.hide__session_poc_profile =
+ pres_mgmt_cfg_remote?.hide__session_poc_profile ?? false;
+ loc.hide__session_poc_profile_pic =
+ pres_mgmt_cfg_remote?.hide__session_poc_profile_pic ?? false;
- // Session fields
- loc.hide__session_description =
- pres_mgmt_cfg_remote?.hide__session_description ?? false;
- loc.hide__session_location =
- pres_mgmt_cfg_remote?.hide__session_location ?? false;
- loc.hide__session_msg =
- pres_mgmt_cfg_remote?.hide__session_msg ?? false;
- loc.hide__session_poc =
- pres_mgmt_cfg_remote?.hide__session_poc ?? false;
- loc.show__session_li_poc_field =
- pres_mgmt_cfg_remote?.show__session_li_poc_field ?? false;
- loc.hide__session_poc_biography =
- pres_mgmt_cfg_remote?.hide__session_poc_biography ?? false;
- loc.hide__session_poc_profile =
- pres_mgmt_cfg_remote?.hide__session_poc_profile ?? false;
- loc.hide__session_poc_profile_pic =
- pres_mgmt_cfg_remote?.hide__session_poc_profile_pic ?? false;
+ // --- Presenter fields ---
+ loc.hide__presenter_biography =
+ pres_mgmt_cfg_remote?.hide__presenter_biography ?? false;
- // Presenter fields
- loc.hide__presenter_biography =
- pres_mgmt_cfg_remote?.hide__presenter_biography ?? false;
+ // --- Presentation fields ---
+ loc.hide__presentation_datetime =
+ pres_mgmt_cfg_remote?.hide__presentation_datetime ?? false;
+ loc.hide__presentation_description =
+ pres_mgmt_cfg_remote?.hide__presentation_description ?? false;
- // Presentation fields
- loc.hide__presentation_datetime =
- pres_mgmt_cfg_remote?.hide__presentation_datetime ?? false;
- loc.hide__presentation_description =
- pres_mgmt_cfg_remote?.hide__presentation_description ?? false;
+ // --- Launcher links (show__ in remote β invert to hide__ in local display state) ---
+ loc.hide__launcher_link =
+ !(pres_mgmt_cfg_remote?.show__launcher_link ?? false);
+ // Mirror the raw remote flag too β the toggle BUTTON's own visibility (not the
+ // launcher link content itself) is gated on show__launcher_link directly in
+ // ae_comp__events_menu_opts.svelte / event_page_menu.svelte / location_page_menu.svelte.
+ loc.show__launcher_link =
+ pres_mgmt_cfg_remote?.show__launcher_link ?? false;
- // Launcher links (show__ in remote β invert to hide__ in local display state)
- loc.hide__launcher_link =
- !(pres_mgmt_cfg_remote?.show__launcher_link ?? false);
- // Mirror the raw remote flag too β the toggle BUTTON's own visibility (not the
- // launcher link content itself) is gated on show__launcher_link directly in
- // ae_comp__events_menu_opts.svelte / event_page_menu.svelte / location_page_menu.svelte.
- // This was never assigned before, so that gate always collapsed to trusted_access-only.
- loc.show__launcher_link =
- pres_mgmt_cfg_remote?.show__launcher_link ?? false;
-
- // Navigation / UI constraints
- loc.limit__navigation =
- pres_mgmt_cfg_remote?.limit__navigation ?? false;
- }
+ // --- Navigation / UI constraints ---
+ loc.limit__navigation =
+ pres_mgmt_cfg_remote?.limit__navigation ?? false;
}
/**
diff --git a/src/lib/app_components/e_app_access_type.svelte b/src/lib/app_components/e_app_access_type.svelte
index 7d7f2f2c..aca597c2 100644
--- a/src/lib/app_components/e_app_access_type.svelte
+++ b/src/lib/app_components/e_app_access_type.svelte
@@ -360,10 +360,9 @@ function handle_clear_access() {
-
-
-