- Update list_all() to scan cache_dir for legacy files directly
(old files stored as CACHE_DIR/{hash}, not CACHE_DIR/legacy/)
- Update cache listing endpoints to use cache_manager.list_all()
instead of iterating CACHE_DIR.iterdir() directly
- This ensures uploaded files appear in the cache UI regardless
of whether they're in the old or new cache structure
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Run deletion: Handle legacy runs without activity records by
checking L2 shared status directly (instead of failing)
- Cache deletion: Check Redis runs in addition to activity store
to prevent deleting inputs/outputs that belong to runs
- Add find_runs_using_content() helper to check if content_hash
is used as input or output of any run
This fixes the inverted deletion logic where runs couldn't be
deleted but their cache items could.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove symlink hack from cache_file() - no longer needed
- Add get_cache_path() helper for content_hash lookups
- Update all CACHE_DIR / content_hash patterns to use cache_manager
- Fix cache_manager.get_by_content_hash() to check path.exists()
- Fix legacy path lookup (cache_dir not legacy_dir)
- Update upload endpoint to use cache_manager.put()
This ensures cache lookups work correctly for both legacy files
(stored directly in CACHE_DIR) and new files (stored in nodes/).
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update get_cached endpoint to check cache_manager first, then legacy
- Update get_cached_mp4 endpoint similarly
- Make cache_file() create symlink in legacy location for backward compat
Fixes issue where newly cached outputs weren't being served because
they were stored in new location but served from legacy location.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add cache_manager.py with L1CacheManager wrapping artdag Cache
- Add L2SharedChecker for checking published status via L2 API
- Update server.py to use cache_manager for storage
- Update DELETE /cache/{content_hash} to enforce deletion rules
- Add DELETE /runs/{run_id} endpoint for discarding runs
- Record activities when runs complete for deletion tracking
- Add comprehensive tests for cache manager
Deletion rules enforced:
- Cannot delete items published to L2
- Cannot delete inputs/outputs of runs
- Can delete orphaned items
- Runs can only be discarded if no items are shared
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add content negotiation (HTML for browsers, JSON for APIs)
- Clean URLs: /runs, /cache, /run/{id}, /cache/{hash}/detail
- Auth routes: /login, /logout, /register with clean URLs
- Add render_page() helper for consistent page layout
- Add infinite scroll pagination for HTML views
- Add API pagination with ?page=1&limit=20
- Redirect old /ui/* routes to clean URLs
- Update nav links to use clean URLs
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Pin items when published (published, input_to_published)
- Discard endpoint (DELETE /cache/{hash}) refuses pinned items
- UI shows pin status and discard button on cache detail
- Run publish also pins output and all inputs for provenance
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Added /ui/cache/{hash}/meta-form endpoint for HTMX form
- Origin selector (self vs external URL)
- Description and tags fields
- Publish to L2 with asset name
- Update on L2 for already-published items
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
L2 needs to call back to L1 to fetch run details, which can take
longer than 10 seconds especially with network latency.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace custom CSS with Tailwind CSS via CDN
- Consistent dark theme across all pages
- Responsive layouts with mobile-friendly breakpoints
- Updated: home, login/register, runs list, cache list, run detail, cache detail
- Modern card-based UI with hover states and status badges
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add /cache/{hash}/mp4 endpoint that transcodes MKV to MP4
- First request transcodes (using ffmpeg), result cached as {hash}.mp4
- Subsequent requests serve cached MP4 directly
- Detect iOS devices and use MP4 endpoint for video src
- Works with Cloudflare caching for efficiency
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
iOS Safari requires playsinline attribute for inline video playback.
Note: MKV videos still won't play on iOS - only MP4/H.264 is supported.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add L1_PUBLIC_URL environment variable
- UI publish sends L1 URL to L2 so it knows where to fetch run data
- Update .env.example with new config
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add POST /ui/publish-run/{run_id} endpoint for UI publishing
- Add publish form with HTMX to run detail page
- Shows publish button for completed runs with outputs
- Uses existing L2 /registry/record-run endpoint
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add POST /cache/{hash}/publish to publish cache items to L2
- Add PATCH /cache/{hash}/republish to sync metadata updates
- Validates origin is set before publishing
- Tracks publish status in cache metadata (to_l2, asset_name, timestamps)
- Forwards auth token to L2 for authentication
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update save_cache_meta() to support updates (not just create)
- Add GET/PATCH /cache/{hash}/meta endpoints for metadata management
- Add user data storage for folders/collections (per-user .json files)
- Add folder CRUD endpoints (/user/folders)
- Add collection CRUD endpoints (/user/collections)
- Add cache list filtering by folder, collection, and tags
- Support origin tracking (self vs external URL)
- Support tags, description, and organization metadata
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Run detail page requires login and ownership check
- Cache uploads require login and track uploader metadata
- Cache list filtered to show only user's own files (uploaded or from runs)
- Cache detail view requires login and ownership check
- Add helper functions for cache metadata and user hash lookup
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Runs list now requires login, shows only user's own runs
- Cache list now requires login to view
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Filter now matches both plain username and ActivityPub format
(@user@domain) to support runs created before and after the
actor ID change.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add tabbed navigation between Runs and Cache views
- Add /ui/cache-list endpoint to list cached files with thumbnails
- Show media type, file size, and preview for each cached item
- Sort cache items by modification time (newest first)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add infrastructure field to RunStatus model
- Store infrastructure (software/hardware) from task result
- Format username as ActivityPub actor ID (@user@domain)
- Display owner, effects commit, and infrastructure in UI provenance section
- Add artdag commit tracking for identity effect
- Include infrastructure in raw JSON provenance
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Identity effect is part of artdag package on GitHub
- Other effects (dog) link to rose-ash effects repo with commit hash
- Added effect_url field to RunStatus for proper URL storage
- Extract repo_url from provenance instead of building it
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Runs require auth token (verified with L2)
- Store username with each run
- UI login/register/logout via L2
- Filter runs by logged-in user
- Cookie-based auth for UI
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Capture effects repo commit hash at render time
- Store effects_commit in run record
- Effect URLs now link to exact commit, not main branch
- Include commit in raw JSON provenance
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- /ui/cache/{hash} shows image/video inline
- File details: hash, type, size
- Download button
- All cache links now go to view page
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Runs/cards max-width 900px, left-aligned
- Media boxes left-justified, max 400px each
- Increased font sizes throughout
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Click run to see full detail page
- Effect name links to git.rose-ash.com source
- Input/output hashes link to cache downloads
- Full provenance: effect, inputs, output, timestamps
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- /ui endpoint shows runs list
- Auto-detects image vs video content
- HTMX polling for running jobs
- Dark theme
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Dockerfile for L1 server/worker
- docker-compose.yml with Redis
- Environment variables for Redis URL and cache dir
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- FastAPI server on port 8100
- POST /runs to start rendering jobs
- GET /runs/{id} to check status
- Cache and run persistence in Redis
- Auto-generated API docs at /docs
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>