Command Center Flash-Persistence Integration Proposal
Architectural proposal to add flash-persistence to command-center UI for data continuity and debugging
๐พ Command Center Flash-Persistence Integration
๐ฏ Problem Statement
The command center UI currently relies entirely on in-memory signals. When a user refreshes the page:
- โ Recent decisions are lost (breaks debugging continuity)
- โ Event log history is cleared (loses troubleshooting context)
- โ User preferences (like
isPaused) reset - โ Cannot analyze past events after refresh
โจ Proposed Solution
Integrate the @storage-system flash-persistence system (similar to theme-system integration) to persist critical UI state to IndexedDB.
Benefits
- Debugging Continuity: Recent decisions persist across refreshes
- Historical Analysis: Event log available for troubleshooting
- User Preferences:
isPausedstate persists - Data Recovery: Can flush/clear data when needed
- Performance: Instant load via IndexedDB (< 1ms)
- Cross-Tab Sync: State syncs across browser tabs
๐ Data Persistence Strategy
What to Persist
| Signal | Persist? | Priority | TTL | Reason |
|---|---|---|---|---|
recentDecisions |
โ Yes | High | 7 days | Debugging continuity |
eventLog |
โ Yes | Normal | 24 hours | Historical analysis |
isPaused |
โ Yes | High | 30 days | User preference |
liveDecisions |
โ Yes | Normal | 7 days | Decision history |
learningStats |
โ Yes | Low | 7 days | Analytics |
activeTask |
โ No | - | - | Real-time, should be fresh |
activeAgents |
โ No | - | - | Real-time, should be fresh |
isConnected |
โ No | - | - | Connection state |
pendingApprovals |
โ No | - | - | Real-time workflow |
currentApproval |
โ No | - | - | Real-time workflow |
isRecording |
โ No | - | - | Session state |
recordedEvents |
โ ๏ธ Maybe | Low | 24 hours | Could be useful for replay |
๐๏ธ Implementation Plan
1. Add Storage System Import
// At top of command-center.component.ts
import { autoFlashState } from '@storage-system';
2. Convert Signals to Flash-Persisted
Recent Decisions (High Priority - 7 Days)
Before:
readonly recentDecisions = signal<DecisionEvent[]>([]);
After:
readonly recentDecisions = autoFlashState<DecisionEvent[]>('recent-decisions', [], {
database: 'command-center',
collection: 'ui-state',
priority: 'high',
ttl: 7 * 24 * 60 * 60 * 1000, // 7 days
debounceMs: 500,
maxItems: 50 // Limit to last 50 decisions
});
Event Log (Normal Priority - 24 Hours)
Before:
readonly eventLog = signal<EventLog[]>([]);
After:
readonly eventLog = autoFlashState<EventLog[]>('event-log', [], {
database: 'command-center',
collection: 'logs',
priority: 'normal',
ttl: 24 * 60 * 60 * 1000, // 24 hours
debounceMs: 1000,
maxItems: 200 // Limit to last 200 events
});
isPaused (High Priority - 30 Days)
Before:
readonly isPaused = signal(false);
After:
readonly isPaused = autoFlashState<boolean>('is-paused', false, {
database: 'command-center',
collection: 'preferences',
priority: 'high',
ttl: 30 * 24 * 60 * 60 * 1000, // 30 days
debounceMs: 100 // Very fast for user preference
});
Live Decisions (Normal Priority - 7 Days)
Before:
readonly liveDecisions = signal<LiveDecision[]>([]);
After:
readonly liveDecisions = autoFlashState<LiveDecision[]>('live-decisions', [], {
database: 'command-center',
collection: 'decisions',
priority: 'normal',
ttl: 7 * 24 * 60 * 60 * 1000, // 7 days
debounceMs: 500,
maxItems: 100
});
Learning Stats (Low Priority - 7 Days)
Before:
readonly learningStats = signal<LearningStats>({ totalDecisions: 0, goldenDecisions: 0, embeddings: 0 });
After:
readonly learningStats = autoFlashState<LearningStats>('learning-stats',
{ totalDecisions: 0, goldenDecisions: 0, embeddings: 0 },
{
database: 'command-center',
collection: 'analytics',
priority: 'low',
ttl: 7 * 24 * 60 * 60 * 1000, // 7 days
debounceMs: 2000 // Less frequent updates
}
);
๐๏ธ Storage Key Structure
Following the pattern from theme-system:
[database]:[namespace]:[collection]:[key]
Command Center Keys
| Key | Description | Priority | TTL |
|---|---|---|---|
command-center:flash:ui-state:recent-decisions |
Recent decisions list | High | 7 days |
command-center:flash:logs:event-log |
Event log history | Normal | 24 hours |
command-center:flash:preferences:is-paused |
Pause state | High | 30 days |
command-center:flash:decisions:live-decisions |
Live decision feed | Normal | 7 days |
command-center:flash:analytics:learning-stats |
Learning statistics | Low | 7 days |
๐งน Flush/Clear Functionality
Add Clear Methods
/**
* Clear all persisted command-center data
* Useful for debugging or resetting state
*/
clearAllPersistedData() {
this.recentDecisions.set([]);
this.eventLog.set([]);
this.liveDecisions.set([]);
this.learningStats.set({ totalDecisions: 0, goldenDecisions: 0, embeddings: 0 });
// isPaused intentionally NOT cleared - it's a user preference
}
/**
* Clear logs only (preserve decisions and preferences)
*/
clearLogs() {
this.eventLog.set([]);
}
/**
* Clear decisions only (preserve logs and preferences)
*/
clearDecisions() {
this.recentDecisions.set([]);
this.liveDecisions.set([]);
}
Add UI Buttons
In command-center.component.html:
<!-- Add to header controls -->
<div class="admin-controls">
<button
(click)="clearLogs()"
class="btn-clear"
title="Clear event logs">
๐๏ธ Clear Logs
</button>
<button
(click)="clearDecisions()"
class="btn-clear"
title="Clear decision history">
๐๏ธ Clear Decisions
</button>
<button
(click)="clearAllPersistedData()"
class="btn-clear-all"
title="Clear all persisted data">
โ ๏ธ Clear All
</button>
</div>
๐ Performance Expectations
Before Flash-Persistence
- Page Load: All state cleared, empty UI
- Debugging: Must reproduce issue to see events
- Cross-Tab: No synchronization
After Flash-Persistence
- Page Load: < 1ms instant state restore โจ
- Debugging: Full history available immediately ๐
- Cross-Tab: Automatic sync < 50ms ๐
- Persistence: Automatic background save ๐พ
๐ ๏ธ Implementation Steps
Phase 1: Core Signals (30 mins)
- Add
autoFlashStateimports - Convert
recentDecisionsto flash-persisted - Convert
eventLogto flash-persisted - Convert
isPausedto flash-persisted - Test page refresh behavior
- Add
Phase 2: Additional Signals (20 mins)
- Convert
liveDecisionsto flash-persisted - Convert
learningStatsto flash-persisted - Verify storage keys in DevTools
- Convert
Phase 3: Clear Functionality (15 mins)
- Add
clearAllPersistedData()method - Add
clearLogs()method - Add
clearDecisions()method - Add UI buttons to template
- Style clear buttons
- Add
Phase 4: Testing (15 mins)
- Test instant load on refresh
- Test TTL expiration (simulate time)
- Test clear functionality
- Test cross-tab sync
- Verify maxItems limiting works
Total Estimated Time: ~80 minutes
๐ฏ Success Criteria
- Recent decisions persist across page refreshes
- Event log persists for 24 hours
- isPaused state persists for 30 days
- Data loads in < 1ms on page load
- Clear buttons work correctly
- Cross-tab sync works (open 2 tabs, verify sync)
- TTL expiration works (old data clears automatically)
- No performance regression (check with DevTools)
โ ๏ธ Considerations
Data Size Management
- Limit array sizes: Use
maxItemsoption to prevent unbounded growth - Monitor IndexedDB: Check storage usage in DevTools
- TTL Cleanup: Flash-persistence auto-cleans expired data
Migration Path
- Existing in-memory signals will seamlessly upgrade
- No data migration needed (starts fresh)
- Gradual rollout: Convert signals one at a time
Debugging
// Check flash-persisted states
import { getAutoDiscoveredStates } from '@storage-system';
console.log('Command Center States:', getAutoDiscoveredStates().filter(s => s.database === 'command-center'));
// Inspect IndexedDB
// Open DevTools > Application > IndexedDB > gg-storage > command-center:*
๐ References
๐ Next Steps
- Get user approval on this proposal
- Implement Phase 1 (core signals)
- Test and verify instant load behavior
- Implement remaining phases
- Update documentation with new functionality
Status: ๐ Awaiting approval
Estimated Effort: 80 minutes
Priority: Medium
Dependencies: None (storage-system already in use)