refactor(events): harden V3 String-Only ID vision and fix Session Alert store error

- Standardized Event module logic files to strictly use random string IDs, ensuring frontend consistency and avoiding 'Integer Trap' 404s.
- Refactored 'ae_comp__event_session_alert.svelte' to accept a plain object instead of a store/observable, resolving the 'store_invalid_shape' error in list loops.
- Updated all callers of the alert component to pass unwrapped session objects.
- Cleaned up event-related UI components to remove redundant '_random' field lookups and align with V3 CRUD patterns.
- Updated project metadata (GEMINI.md, TODO.md) to reflect the new memory structure and latest hardened state.
This commit is contained in:
Scott Idem
2026-01-27 12:18:12 -05:00
parent a704779d1b
commit 30413e32d2
15 changed files with 589 additions and 473 deletions

View File

@@ -17,7 +17,7 @@
let sync_results: Record<string, 'success' | 'error' | 'pending'> = $state({});
let sync_stats = $state({ total: 0, cached: 0, missing: 0 });
let last_heartbeat: string | null = $state(null);
// Loop Timings (Visible in UI)
let loop_info = $state({
event: 90000,
@@ -43,12 +43,12 @@
if (info) {
$ae_loc.home_directory = info.home_directory;
$ae_loc.tmp_directory = info.tmp_directory;
// Also sync into native_device for redundancy
if (!$ae_loc.native_device) $ae_loc.native_device = {};
$ae_loc.native_device.home_directory = info.home_directory;
$ae_loc.native_device.tmp_directory = info.tmp_directory;
if (log_lvl) console.log('Sync: Native OS metadata hydrated.', { home: info.home_directory });
}
} catch (err) {
@@ -57,7 +57,7 @@
}
const dev = $ae_loc.native_device || {};
// Load timings from device config
loop_info.event = dev.check_event_loop_period || 90000;
loop_info.device = dev.check_event_device_loop_period || 60000;
@@ -104,7 +104,7 @@
const all_for_ids = [...session_ids, ...presentation_ids, ...presenter_ids, $events_slct.event_id];
const files = await db_events.file.where('for_id').anyOf(all_for_ids).toArray();
sync_stats.total = files.length;
let cached_count = 0;
let missing_count = 0;
@@ -113,8 +113,8 @@
if (!file_obj.hash_sha256) continue;
if (sync_results[file_obj.event_file_id] === 'success') { cached_count++; continue; }
const exists = await native.check_hash_file_cache({
cache_root,
const exists = await native.check_hash_file_cache({
cache_root,
hash: file_obj.hash_sha256,
hash_prefix_length: prefix_len
});
@@ -163,8 +163,8 @@
*/
async function run_device_heartbeat() {
const dev = $ae_loc.native_device;
const device_id = dev?.event_device_id_random || dev?.id_random || dev?.event_device_id || dev?.id;
const device_id = dev?.event_device_id || dev?.id_random || dev?.event_device_id_random || dev?.id;
if (!device_id) {
if (log_lvl) console.warn('Sync: Heartbeat skipped, no device_id found in $ae_loc.native_device.');
$events_sess.launcher.heartbeat_info.status = 'error';
@@ -248,11 +248,11 @@
<span class="font-bold text-primary-400">NATIVE SYNC MONITOR</span>
<button onclick={() => show_monitor = false} class="text-error-500 hover:text-error-400">×</button>
</div>
<div class="grid grid-cols-2 gap-x-4 gap-y-1 mb-2">
<span class="opacity-70 text-primary-300">Room Status:</span>
<span class="text-right">{sync_stats.cached} / {sync_stats.total} Files</span>
<span class="opacity-70 text-primary-300">Prefix Len:</span>
<span class="text-right">{$ae_loc.native_device?.hash_prefix_length || 2} chars</span>
@@ -284,7 +284,7 @@
{/if}
{#if currently_syncing}
<button
<button
onclick={() => show_monitor = !show_monitor}
class="bg-black/80 text-white p-2 rounded-lg text-[10px] border border-primary-500 animate-pulse shadow-2xl pointer-events-auto transition-transform active:scale-95"
>
@@ -299,7 +299,7 @@
</button>
{:else}
<!-- Secret button area to toggle monitor when not syncing -->
<button
<button
onclick={() => show_monitor = !show_monitor}
class="w-8 h-8 opacity-0 hover:opacity-20 bg-primary-500 rounded-full pointer-events-auto flex items-center justify-center transition-opacity"
title="Toggle Sync Monitor"