tractatus/docs/CACHE_FIX_V2_PERMANENT.md
TheFlow 2a727a80b8 feat: Complete Phase 2 Agent Lightning website integration
- Added Agent Lightning research section to researcher.html with Demo 2 results
- Created comprehensive /integrations/agent-lightning.html page
- Added Agent Lightning link in homepage hero section
- Updated Discord invite links (Tractatus + semantipy) across all pages
- Added feedback.js script to all key pages for live demonstration

Phase 2 of Master Plan complete: Discord setup → Website completion

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 14:38:20 +13:00

7.3 KiB

Cache Fix v2 - Permanent Solution

Date: November 3, 2025
Status: DEPLOYED AND VALIDATED
Version: 0.1.6


Problem Summary

After deploying Phase 2 (Agent Lightning integration), users experienced:

  • Flickering between old and new content (multiple reloads in quick succession)
  • Stale content persisted even after hard cache clear in private windows
  • Content would "flash" new version then revert to old version

Root Causes Identified

1. auto-reload.js Causing Reload Loops

Located at /js/auto-reload.js, this script listened for two service worker events:

- 'CACHE_CLEARED' message  triggered reload
- 'controllerchange' event  triggered reload

Problem: Service worker activation would trigger BOTH events, causing:

  1. sw-reset.js runs → reloads page
  2. New SW installs → sends CACHE_CLEARED → auto-reload.js reloads page
  3. New SW takes control → fires controllerchange → auto-reload.js reloads page AGAIN
  4. Result: 3+ reloads in rapid succession = flickering

2. Critical Files Cached Without Cache-Busting

Files loaded without ?v= parameters:

  • /js/auto-reload.js - NO cache-busting
  • /js/sw-reset.js - NO cache-busting
  • /js/components/umami-tracker.js - NO cache-busting

Problem: nginx caches these files for 1 year:

location ~ ^/(css|js|images|downloads|fonts)/ {
    expires 1y;
    add_header Cache-Control "public, max-age=31536000" always;
}

Result: Catch-22 - The script designed to clear caches was itself cached!

3. Service Worker Too Aggressive

Old service worker tried to cache everything:

  • Cached critical assets on install
  • Used complex cache-first/network-first strategies
  • Intercepted fetch requests and served stale cached content
  • Conflicted with HTTP cache-busting via ?v= parameters

Permanent Solution Implemented

Fix #1: Removed Reload Loop Scripts

# Removed from ALL HTML files:
- auto-reload.js (was causing multiple reloads)
- sw-reset.js (catch-22: itself was cached)

Fix #2: Simplified Service Worker (v0.1.6)

New minimal service worker:

// NO caching at all - let HTTP/nginx handle caching
self.addEventListener('fetch', (event) => {
  return; // Don't intercept - browser handles normally
});

Benefits:

  • Service worker ONLY does version checking (no caching)
  • All requests go directly to nginx → proper HTTP caching works
  • ?v=timestamp parameters respected by browsers
  • No fetch interception = no stale content served from SW cache

Fix #3: Enhanced nginx Configuration

Added explicit location blocks for critical files:

# Root path - NEVER cache
location = / {
    try_files /index.html @proxy;
    expires -1;
    add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
}

# Service worker - NEVER cache (critical for updates)
location = /service-worker.js {
    expires -1;
    add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
    try_files $uri @proxy;
}

# Version check file - NEVER cache
location = /version.json {
    expires -1;
    add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" always;
    try_files $uri @proxy;
}

# Static files - cache with respect for ?v= parameters
location ~ ^/(css|js|images|downloads|fonts)/ {
    expires 1y;
    add_header Cache-Control "public, max-age=31536000" always;
    # When ?v= changes, browser treats as new URL → fetches fresh
}

How It Works Now

Cache Strategy:

  1. HTML files: Never cached (nginx: no-store, no-cache)
  2. service-worker.js: Never cached (critical for updates)
  3. version.json: Never cached (for update detection)
  4. JS/CSS files: Cached for 1 year BUT with ?v=timestamp parameters
    • When content changes → timestamp changes → browser fetches new file
  5. Service worker: Minimal - NO fetch interception, NO caching

Deployment Flow:

  1. Update code → update-cache-version.js runs
  2. Increments CACHE_VERSION in service-worker.js
  3. Updates all HTML ?v= parameters to new timestamp
  4. Deploys via rsync
  5. nginx reload (automatic in deploy.sh)
  6. Result: Fresh content served immediately, no reload loops

User Experience:

  • Visit site → HTML loaded fresh from nginx (never cached)
  • JS/CSS with ?v= parameters load (cached if timestamp unchanged)
  • Service worker activates (minimal, no caching)
  • No flickering, no reload loops
  • One smooth page load with current content

Verification Commands

# 1. Check HTML is NOT cached
curl -I https://agenticgovernance.digital/index.html | grep -i cache
# Should show: cache-control: no-store, no-cache, must-revalidate

# 2. Check service worker is NOT cached  
curl -I https://agenticgovernance.digital/service-worker.js | grep -i cache
# Should show: cache-control: no-store, no-cache, must-revalidate

# 3. Verify service worker version
curl -s https://agenticgovernance.digital/service-worker.js | grep CACHE_VERSION
# Should show: const CACHE_VERSION = '0.1.6';

# 4. Verify no problematic scripts
curl -s https://agenticgovernance.digital/ | grep -E "(auto-reload|sw-reset)"
# Should return nothing (exit code 1)

# 5. Check Phase 2 content is served
curl -s https://agenticgovernance.digital/ | grep "Join the Community"
# Should show community section HTML

What Was Removed

  • auto-reload.js - Removed from all HTML files
  • sw-reset.js - Removed from all HTML files
  • Service worker fetch interception - No longer intercepts requests
  • Service worker caching - No longer caches any assets
  • CRITICAL_ASSETS caching - Removed from service worker

What Remains

  • version-manager.js - Registers minimal service worker, shows update notifications
  • Service worker - Minimal version for version checking only
  • update-cache-version.js - Updates ?v= parameters on deployments
  • nginx caching - Properly configured with cache-busting support
  • Phase 2 content - All Agent Lightning integration content

Future Deployments

The deployment process is now robust and permanent:

# Deploy (automatically handles cache-busting)
./scripts/deploy.sh --frontend-only

# What happens:
# 1. Detects JS/CSS changes
# 2. Runs update-cache-version.js
# 3. Auto-commits cache version bump
# 4. Deploys via rsync
# 5. Reloads nginx automatically
# 6. Fresh content served immediately

No more:

  • Manual cache clearing
  • Hard refresh requirements
  • Reload loops
  • Flickering between versions
  • Stale content after deployments

Technical Details

Files Modified:

  • /home/theflow/projects/tractatus/public/service-worker.js - Minimal version (v0.1.6)
  • /home/theflow/projects/tractatus/public/version.json - Updated to 0.1.6
  • /home/theflow/projects/tractatus/public/**/*.html - Removed auto-reload.js and sw-reset.js
  • /etc/nginx/sites-available/tractatus - Added explicit location blocks

Commits:

  • Removed auto-reload.js and sw-reset.js from all HTML
  • Simplified service worker to minimal caching-free version
  • Enhanced nginx configuration for critical files

Result: Cache invalidation works reliably, no reload loops, fresh content on every deployment

Status: Production fix deployed and validated - November 3, 2025