All cache-clearing buttons and the IDAA clear-caches page previously
cleared IDB/localStorage but left service worker registrations and Cache
Storage intact. On the next reload the SW re-served the old JS bundle,
leaving users stuck on stale code despite appearing to reload. This
caused recurring stale-state reports from IDAA and other clients for
4+ months.
Two gaps closed:
1. Every clear path (root page buttons, sys bar, help tech, idaa/clear-caches)
now unregisters SW registrations and clears Cache Storage before touching
IDB and localStorage. Order: SW → Cache Storage → IDB → localStorage.
2. Added controllerchange listener in +layout.svelte effect 4. When the new
SW activates and calls clients.claim(), this listener reloads the page so
open tabs run the new JS bundle instead of keeping old code in memory
indefinitely. Without this, skipWaiting + clients.claim work correctly on
the SW side but the page side never picks up the update.
Also added thorough code comments and updated REFERENCE__Common_Agent_Mistakes
(#15) and BOOTSTRAP doc (#8) to document the full root cause so this cannot
be silently re-broken by a future agent or refactor.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Menu: Files moved between People and Data Stores; color tertiary (matches Users/People).
Dashboard: Sites secondary→primary, Files secondary→tertiary, Data Stores + Lookups surface→secondary. All cards now match menu color groupings.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Dashboard: Users + People cards corrected to tertiary (matched menu);
Files card added between People and Data Stores using secondary (matched menu).
Files per-page options extended to 200/400/800/1000/1500/2000.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When orphan filter is active, total was summing all 50 loaded files
rather than the filtered subset shown in the table.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Documents ae_send_message recipient names, the directory-name vs
recipient-name gotcha, and ae_inbox inbox defaults. Mirrors the
equivalent section added to the backend bootstrap.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
DELETE /v3/action/event_file/{id} now handles full atomic cleanup (link
removal, physical file, hosted_file record) in one call — replaces the
multi-step Redis pre-warm workaround. orphan_scan endpoint replaces the
N+1 per-file /links fetch on the admin files page.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two new items in DevOps & Backend: V3 CRUD regression fix for
event_file delete (delete_obj_template ignores cleanup params) and
orphan scan endpoint for hosted_file. Both logged after message to
backend agent 2026-06-18.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Event file delete (Pres Mgmt):
- Re-implement cleanup using /links pre-fetch before delete_hosted_file calls.
The /links endpoint calls get_id_random() per link which populates Redis.
Without this, redis_lookup_id_random('event_file', id) raises 404 in the
delete handler → silent skip → physical file never removed.
Now mirrors the same pattern used by the /core/files/ admin page delete.
/core/files/ admin page:
- Add orphan check mode: "Check Orphans" button batch-fetches links for all
visible results in parallel (reusing links_map cache), then filters table
to show only files with zero links.
- Orphan files get a warning badge in the filename column.
- Results header toggles to show "N orphans of M" when filter is active.
- Unlink icon imported from lucide for orphan UI.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
event_file delete was broken since the module was first created (Oct 2024).
delete_ae_obj_id__event_file passed delete_hosted_file=true + rm_orphan=true to
the generic V3 CRUD endpoint, but delete_obj_template never handled those params —
it only did a raw sql_delete on the event_file row. The hosted_file_link record,
hosted_file DB record, and physical file on disk were never cleaned up.
Fix: call api.delete_hosted_file (the action endpoint) BEFORE deleting the
event_file record so the backend can still resolve link_to_id via Redis.
Pass link_to_type='event_file', link_to_id=event_file_id, rm_orphan=true,
method=delete. hosted_file_id is now an optional param on
delete_ae_obj_id__event_file; component passes event_file_obj.hosted_file_id.
Also fix hosted_file delete in /core/files/ admin page (same root cause):
load links first, then call delete_hosted_file for each link with correct
link_to_type/link_to_id_random and method=delete before removing the record.
Also: add clickable navigation links in the files admin link sub-row.
Direct types (event, journal, archive, post) resolve immediately; nested types
(event_session, event_location, event_presenter, journal_entry, etc.) fetch
their parent ID via the V3 CRUD endpoint and construct the correct route.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Search hosted files across all accounts (including disabled)
- Sortable columns, pagination, per-row delete, download, and SHA-256 copy
- Lazy-load file link records per row via /v3/action/hosted_file/{id}/links
- Fix delete to load links first, remove each via correct link_to_type/link_to_id_random,
then hard-delete with method=delete and rm_orphan=true
- Remove Linked To and Group columns (moved Group/ForType to filter bar only)
- SHA-256 column now visible at lg breakpoint (was xl)
- Added /core/files nav link to /core layout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- TODO__Agents.md: check off completed passcode JWT migration items;
document the three remaining cleanup steps (deferred ~a few days)
- PROJECT__AE_Site_Passcode_Security.md: update status to active/cleanup-deferred,
check off completed implementation checklist items
- GUIDE__SvelteKit2_Svelte5_DexieJS.md: add new section documenting the
async-function-from-$effect guard-reset infinite loop pattern, with the
real example from the passcode auth bug (2026-06-18)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Passcodes are no longer compared locally against cached localStorage data.
Entry now POSTs to /v3/action/auth/authenticate_passcode; on success the
returned JWT (with per-role TTL) is stored in $ae_loc.jwt. Page-load
expiry check in +layout.ts resets access_type to anonymous when the JWT
has expired, targeting only auth_type='passcode' JWTs.
- Debounce (600 ms) auto-fires the check after typing stops; Enter key
fires immediately as a secondary trigger — preserving the original UX
- Inline spinner and error message added to the passcode input
- Silent fallback to local comparison on network error or unresolved
site_id (ghost), so IDAA staff and Electron/Launcher contexts are safe
- USE_API_PASSCODE_AUTH = true (active); local fallback retained while
production is observed; site_access_code_kv cleanup deferred
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Removed invalid two-way bindings to read-only Dexie observables in the test page
- Fixed 'state_referenced_locally' warning in Field Editor by refactoring draft_value initialization
- Cleaned up empty else block in session list to resolve Vite build warning
- Verified successful production build and clean 'npm run check' output
- Completed rewrite of `element_ae_obj_field_editor.svelte` to Svelte 5 + Tailwind v4
- Set `display_modal = true`, `modal_blocking = false`, and `modal_placement = 'center'` as new defaults
- Implemented trigger-relative modal positioning with automatic viewport boundary clamping to prevent off-screen rendering
- Migrated all 12 call sites across core and events modules (Session, Presenter, Location, Exhibit, etc.)
- Removed legacy datetime-to-local manual conversion logic from views as the component now handles it natively
- Retired Skeleton-based legacy component
- Updated testing page and documentation to reflect the new standardized primitive
- Refactored core layout and dashboard to follow AE Firefly guidelines
- Added proper theme-aware backgrounds and transitioned to Skeleton v4 tokens
- Grouped navigation and cards by functional color (Teal: Infra, Indigo: Identity, Amber: Config)
- Reordered items to: Accounts, Sites, Users, People, Data Stores, Lookups, Addresses, Contacts
- Fixed color inconsistency for Activity Logs in dashboard vs navigation
- Enabled non-blocking modal mode for inline field editors in Data Stores table
- New `display_modal` prop opens the edit panel as a native <dialog> anchored
near the pencil trigger instead of shifting inline content
- `modal_placement` (center|above|below|left|right, default center) positions
the dialog relative to the trigger via getBoundingClientRect + CSS transform
- `modal_blocking` (default true) toggles showModal() vs show(); non-modal
mode adds a document pointerdown listener to close on outside click
- `cancel_edit()` now warns "Discard unsaved changes?" when draft differs from
saved value (matches data store form behaviour); skips warning after a
successful save
- Dialog background uses theme CSS vars directly (--color-surface-50/900) via
:global CSS — Skeleton tonal presets are intentionally semi-transparent and
rendered behind table content without explicit position:fixed + z-index
- Extracted edit panel to {#snippet edit_panel()} — shared by inline and
dialog paths with no duplication
- data-stores table: all three inline field editors switched to display_modal
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Edit button now has SquarePen icon + text per button UX standard
- Style guidelines: extract button icon+text rule into its own section 8
(was buried in Accessibility); renumber Accessibility to section 9;
add code examples and context table for the rule
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Row is no longer a giant click target. Code, Name, and Type cells now use
AE_Field_Editor for inline editing (pencil in edit_mode). Edit button opens
the full modal for everything else. Preview column hidden (kept in markup).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- order_by_li was sent as an array; backend expects plain object — fixes sort
- pass enabled/hidden directly to search_ae_obj (was defaulting to 'enabled'/'not_hidden')
- account column now shows code/short_name from Dexie cache via SvelteMap
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
element_data_store_form.svelte is now the single source of truth for
editing data stores — owns the modal, all form fields, change detection,
save/delete API calls, and IDB cache update.
- element_data_store.svelte: remove ~120 lines of duplicated form/handler
code; now delegates to AE_DataStore_Form via bind:open + callbacks
- data_stores/+page.svelte: open_edit/open_new are now 2 lines each;
remove all draft state, submit_status, handle_save/delete; fix label
a11y (wrapping labels on all filter + bulk-rename inputs)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add original_obj prop + has_changes bindable output to element_data_store_form
- Derive has_changes by comparing each draft field to original_obj; null = always dirty (new record)
- Wire bind:has_changes + original_obj={is_new ? null : editing_obj} in management page
- Fix Save button: preset-filled-primary → preset-filled-primary-500 (matches element_data_store)
- Disable Save when !has_changes; block modal outsideclose when changes are pending
- Restore textarea rows 10 → 15 to match element_data_store.svelte
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New element_data_store_form.svelte handles all form fields for creating/
editing a Data Store. Replaces the inline form in the management page modal.
Features vs old inline form:
- Help text on every label (type descriptions, constraint notes, etc.)
- Advanced section (collapsible, hidden by default): Enable, Hide, Priority,
Sort, Group, Notes — each with hint text
- For ID: editable on new, read-only on edit (with explanation why)
- show_account_field / show_for_fields props for embedded widget use later
- html_edit_mode + show_advanced are internal state, reset via {#key} on parent
Management page: drops html_edit_mode state + Code/Eye/editor imports; uses
{#key editing_obj?.id ?? 'new'} to recreate the form on each record change.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- api.ts: remove get_data_store_obj_w_code (hit /data_store/code/, non-V3)
and its export. V3 get_data_store (/v3/data_store/code/) stays.
- ae_core_functions.ts: remove load_ae_obj_code__data_store (wrapper around
the removed function) and its export from core_func.
element_data_store.svelte replaced this with Dexie LiveQuery + V3 API.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Click any column header to sort; click again to toggle ASC/DESC.
Sort re-runs the current search immediately if results are showing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add Bulk Rename panel: code filter (% wildcard), find/replace text,
preview table before apply, sequential PATCH with IDB cache update
- Fix Code filter label/placeholder to show % wildcard syntax
- Add note that API results are scoped to the active account (backend behavior)
- Replace bg-black/5 with bg-surface-500/10 for light/dark compatibility
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Full CRUD for all data_store records: search by code, account_id,
for_type, for_id; create/edit/delete via modal with type-aware content
editor (CodeMirror / TipTap / textarea). Wired into core nav and
dashboard. for_id shown read-only on edit (DB integer FK constraint).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
for_id is an integer FK in the DB but the frontend passes the random
string ID — sending it on update causes a 400. These fields are
parent-context set at creation time and should never change on edit.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two fixes in presenter_view:
1. Name-sync warning (given/family mismatch) was showing even when no
Person was linked. Guard now checks person_id first.
2. Person link replaced the two-step Re-link button flow with on_open
pattern (matches Session POC). Pencil+Re-link button removed; pencil
icon opens the editor and loads the person list in one action.
Admin-only re-link restriction preserved: non-admin staff with a
linked person see a read-only link instead of the editor.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v_event_presenter and v_event_presentation both use INNER JOIN with event
on event_id. Without event_id in the payload the view returns 0 rows after
INSERT, the API falls back to a minimal response, and Dexie save fails
with "Object is missing a valid ID". Pull event_id (and event_session_id
for presenters) from events_slct at creation time.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace pill grid (too tall) with a single-row label + select
- Use <optgroup> to keep System / AE grouping without any extra height
- Prune unused Skeleton system themes: concord, crimson, hamlindigo,
rocket, terminus, vintage removed (6 of 10 — never used in practice)
Remaining: nouveau, cerberus, modern, wintry
- Added comment noting Firefly event-specific variants can be pruned
when their events are no longer active
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Theme picker (e_app_sys_bar.svelte):
- Replace flat <select> dropdown with grouped pill buttons
- Two groups: 'System' (Skeleton defaults) and 'AE' (custom themes)
- Active theme highlighted via bg-primary-500 (shows in the current theme's
own primary color — instant visual confirmation)
- Pill labels shortened where helpful (e.g. 'AE_Firefly_SteelBlue' → 'Steel ✦')
- Rename theme_options → skeleton_themes + ae_themes; extract apply_theme()
shared handler (removes duplicated setAttribute + ae_loc.update pattern)
Orphaned component removal (→ ~/tmp/agents_trash):
- e_app_theme.svelte — only imported by the dead legacy menu; the sys_bar
Appearance section fully covers it
- e_app_sys_menu_legacy.svelte — no consumers anywhere in the codebase;
sys_bar (mounted in +layout.svelte) fully replaces it
- e_app_cfg.svelte — only mounted from the dead legacy menu; its live
functionality (iframe toggle, reload, URL builder) is all in sys_bar's
Dev/Tools section
npx svelte-check: 0 errors (file count drops from 5403 → 5400)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- app.css: import ae-c-lci-new.css alongside existing ae-c-lci.css
- e_app_theme.svelte, e_app_sys_bar.svelte, e_app_url_builder.svelte:
add 'LCI (New ✦)' option pointing to AE_c_LCI_new selector
Both themes coexist — switch between 'LCI' and 'LCI (New ✦)' in the
theme picker to compare old vs brand-guide-accurate colors and fonts.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New parallel theme (data-theme='AE_c_LCI_new') based on the LCI Brand
Guidelines (March 2023, leanconstruction.org). The current ae-c-lci.css
is untouched. Both can coexist.
To activate for review: add @import './ae-c-lci-new.css' to app.css and
add 'AE_c_LCI_new' as a theme option in e_app_theme.svelte /
e_app_sys_bar.svelte / e_app_url_builder.svelte.
Changes vs current theme:
- Primary blue: anchored to #3a5997 (oklch 39% 0.14 264°) — was too
light (47%) and undersaturated (C=0.11). Pantone Surf the Web.
- Secondary: rebuilt from 3-stop LCI scale (#d4e7f7 → #3598dc → #173378),
hue shifted from 264° to 245° (brighter sky-blue direction).
- Tertiary purple: corrected to #8f44ad oklch(43% 0.20 309°) — was too
light (52.73%) and low chroma (0.17). Pantone Dewberry.
- Success teal: minor tweak to #1bbc9d oklch(68% 0.14 175°). Pantone Mint Leaf.
- Error red: corrected to #df3527 oklch(53% 0.27 28°) — was too light
(59.32%) and undersaturated (C=0.21). Pantone Cherry Tomato.
- Typography: heading-font-family → Proxima Nova/Montserrat (brand spec);
base-font-family → Palatino/serif (brand spec). See file for Montserrat
Google Fonts note and app-UI override guidance.
- Heading color: primary-500 (LCI blue) per brand guide PDF.
- Surface: hue shifted from 196° (teal, wrong direction) to 248° (blue).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Updated Element_ae_obj_field_editor_new.svelte with on_open callback support.
- Improved Select field UX in the editor with an inline loading spinner when options are empty.
- Streamlined session_view.svelte by using on_open to trigger person record loading automatically.
- Removed redundant manual 'Select Person' button in favor of automated lazy-loading.
element_data_store.svelte:
- Source/Visual HTML mode toggles: add Code/Eye icons and title attributes
- Cancel button: add X icon and title="Discard changes and close"
- Delete button: add title="Permanently delete this data store — cannot be undone"
- Save button: add title, and Check icon for updated/created success state
(Check was imported but unused; now put to work matching field editor pattern)
- Remove Eraser import (unused)
- Remove ds_submit_results $state (declared but never read in template —
submit status already tracked via $ae_sess.ds.submit_status; drop the
assignment in handle_submit_form too)
element_ae_obj_field_editor_new.svelte:
- Fix duplicate is_editing declaration: user promoted it to a $bindable prop;
remove the now-conflicting local $state declaration
npx svelte-check: 0 errors
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Integrated AE_Comp_Editor_CodeMirror as a supported field_type.
- Enhanced button UX with descriptive Lucide icons and title text (Eraser for Clear, etc.).
- Switched Location View description field to use the CodeMirror editor.
- Updated test playground to include a CodeMirror example.