summaryrefslogtreecommitdiff
AgeCommit message (Collapse)Author
2025-11-20Fix dev env bootstrapping of _/src dirBen Sima
2025-11-20chore: task breakdown and cleanupBen Sima
- Updated Omni/Task/Core.hs to filter parent tasks from 'task ready' - Broke down 'PodcastItLater: Path to Paid Product' into 5 subtasks - Broke down 'General Code Quality Refactor' into 3 subtasks - Broke down 'Complete comprehensive test suite' into 2 subtasks - Fixed namespace naming in tasks.jsonl
2025-11-20task: sync databaseBen Sima
2025-11-20feat: implement t-1gcR9RVBen Sima
Amp-Thread-ID: https://ampcode.com/threads/T-c683858e-5ed5-4d8e-8b9f-842ebdcec0a3 Co-authored-by: Amp <amp@ampcode.com>
2025-11-20task: sync databaseBen Sima
2025-11-20fix: enable dangerously-allow-all for worker agentBen Sima
- The autonomous worker needs to execute commands without interactive prompts - Added --dangerously-allow-all flag to start-worker.sh
2025-11-20fix: improve start-worker.sh scriptBen Sima
- Use 'git worktree list' to reliably find main repo and amp binary - Run amp in a loop with -x flag for autonomous execution - Support flexible worker path resolution
2025-11-20Fix duplicate worktree commandBen Sima
2025-11-20feat: implement multi-agent workflow infrastructureBen Sima
- Add 'Review' status to Task tool - Add Omni/Agent/ directory with setup and sync scripts - Add WORKER_AGENT_GUIDE.md - Configure custom merge driver for tasks.jsonl
2025-11-20bild: fix --plan to output only JSON without loggingBen Sima
- Remove Log.wipe from --plan output path - Add isPlanMode parameter to analyzeAll to skip LogC.withLineManager when planning - Update all analyzeAll call sites to pass isPlanMode flag - Remove grep workaround from repl.sh (no longer needed) Now 'bild --plan' outputs clean JSON that can be piped directly to jq. This fixes typecheck.sh and other tools that rely on clean JSON output. Amp-Thread-ID: https://ampcode.com/threads/T-4e6225cf-3e78-4538-963c-5377bbbccee8 Co-authored-by: Amp <amp@ampcode.com>
2025-11-20typecheck: add Haskell support to typecheck.shBen Sima
- Implement Haskell typechecking using 'ghc -fno-code' - Use repl.sh to provision correct GHC environment with dependencies - Follows same pattern as Python typechecking (via repl.sh) - Typechecks without generating code (fast feedback) Now typecheck.sh supports both Python (.py) and Haskell (.hs) files. Amp-Thread-ID: https://ampcode.com/threads/T-4e6225cf-3e78-4538-963c-5377bbbccee8 Co-authored-by: Amp <amp@ampcode.com>
2025-11-20Remove some leftover test tasksBen Sima
2025-11-20task: implement epic progress trackingBen Sima
- Add progress display to 'task show' for epics (X/Y with percentage) - Add progress display to 'task list --type=epic' showing [X/Y] - Progress already shown in 'task tree' as [X/Y] - Calculate completed/total child tasks for epics - Clean up test tasks accidentally created in production database All 31 tests passing. Amp-Thread-ID: https://ampcode.com/threads/T-4e6225cf-3e78-4538-963c-5377bbbccee8 Co-authored-by: Amp <amp@ampcode.com>
2025-11-20task: implement stats commandBen Sima
- Add 'task stats' command to show task statistics - Display total tasks, status breakdown (open/in-progress/done) - Show epic count, ready vs blocked tasks - Show task counts by priority (P0-P4) and namespace - Support both human-readable and JSON output (--json flag) - Add tests for stats command and stats --json - TaskStats data type with ToJSON/FromJSON instances All 31 tests passing. Amp-Thread-ID: https://ampcode.com/threads/T-4e6225cf-3e78-4538-963c-5377bbbccee8 Co-authored-by: Amp <amp@ampcode.com>
2025-11-20task: add tasks-test.jsonl to .gitignoreBen Sima
The test database file should not be tracked in git. Only the production database (.tasks/tasks.jsonl) should be committed. Amp-Thread-ID: https://ampcode.com/threads/T-4e6225cf-3e78-4538-963c-5377bbbccee8 Co-authored-by: Amp <amp@ampcode.com>
2025-11-20test: verify pre-commit hook behaviorBen Sima
Amp-Thread-ID: https://ampcode.com/threads/T-4e6225cf-3e78-4538-963c-5377bbbccee8 Co-authored-by: Amp <amp@ampcode.com>
2025-11-20task: prettier tree visualization and flag ordering fixesBen Sima
- Implement box-drawing characters (├──, └──, │) for task tree visualization - Fix 'task create' flag ordering by using [options] in docopt (same as 'task list') - Document TASK_TEST_MODE environment variable in AGENTS.md Testing section - Add test case for multi-flag ordering on 'task create' - Clean up test tasks polluted in production database All 29 tests passing. Amp-Thread-ID: https://ampcode.com/threads/T-4e6225cf-3e78-4538-963c-5377bbbccee8 Co-authored-by: Amp <amp@ampcode.com>
2025-11-20Fix docopt flag ordering issue by using [options]Ben Sima
- Changed 'task list' usage from explicit flags to [options] - Allows flags to be specified in any order (fixes t-10KNtTF) - All combinations now work: --namespace --status, --status --namespace, etc. - Updated AGENTS.md examples to use correct status argument format - All tests passing (28/28)
2025-11-20task: sync databaseBen Sima
2025-11-20Add task show command for detailed task inspectionBen Sima
- Implemented 'task show <id>' command with human-readable output - Shows all task fields: title, type, status, priority, timestamps - Displays dependencies with their types - Supports --json flag for programmatic use - Added CLI tests for show command - Includes priority descriptions (Critical/High/Medium/Low/Backlog)
2025-11-20task: sync databaseBen Sima
2025-11-20task: sync databaseBen Sima
2025-11-20task: sync databaseBen Sima
2025-11-19Implement usage tracking and limits enforcementBen Sima
- Fix get_usage() to count from user_episodes table instead of episodes.user_id - Now correctly tracks when episodes are added to user's feed - Handles shared/existing episodes properly (count against the user who added them) - Add comprehensive test suite for usage limits (TestUsageLimits): - test_usage_counts_episodes_added_to_feed - test_usage_counts_existing_episodes_correctly - test_free_tier_limit_enforcement (10 articles) - test_can_submit_blocks_at_limit - test_paid_tier_unlimited - Billing.can_submit() now properly enforces 10 article limit for free tier - Usage tracking via user_episodes.added_at ensures accurate billing Completes t-144eKR1
2025-11-18Change RSS feed URLs from .xml to .rss with backwards compatibilityBen Sima
- Change primary feed URLs to use .rss extension (more semantically correct) - /feed/{token}.xml -> /feed/{token}.rss - /public.rss stays the same - Add .xml aliases for backwards compatibility - /feed/{token}.xml redirects to .rss handler - /public.xml redirects to .rss handler - Add tests to verify both extensions work and return identical content - Update all references in UI and tests to use .rss This provides consistency (.rss everywhere) while maintaining backwards compatibility for existing feed subscribers using .xml URLs. Amp-Thread-ID: https://ampcode.com/threads/T-6d73d458-3d80-44e5-865f-358a69e5b2bf Co-authored-by: Amp <amp@ampcode.com>
2025-11-18Fix homepage auto-refresh and add test coverage for admin workflowsBen Sima
- Fix dashboard-updates endpoint to return Response with both components concatenated as HTML strings, preventing episodes from disappearing after HTMX innerHTML swap - Add viewing_own_feed flag to EpisodeList to hide 'In your feed' button when users are viewing their own feed on homepage - Add test coverage for admin adding user episodes to own feed - Add test coverage for admin adding user episodes to public feed Amp-Thread-ID: https://ampcode.com/threads/T-6d73d458-3d80-44e5-865f-358a69e5b2bf Co-authored-by: Amp <amp@ampcode.com>
2025-11-18Add 'Add to my feed' button to public feed for logged-in usersBen Sima
When viewing the public feed (or any episode list), logged-in users now see: - 'Add to my feed' button if episode is not in their feed - 'In your feed' button (disabled) if they already have it Implementation: - Added user_button logic to EpisodeList component - Checks Core.Database.user_has_episode() for each episode - Shows blue outline button for add action - Shows gray disabled button when already added - Buttons displayed in flex row with admin buttons Updated add_episode_to_feed endpoint: - Changed to redirect back to referer page after adding - Uses HX-Redirect to reload the page showing updated state - This allows the button to change from 'Add to my feed' to 'In your feed' All tests passing (48 tests)
2025-11-18Fix type mismatch in track_episode_metric loggingBen Sima
Changed logger format from %d to %s for episode_id to handle cases where the ID might be passed as a string from route parameters. Error was: Message: 'Tracked %s event for episode %d (user: %s)' Arguments: ('added', '2', 1) Using %s is more flexible and works with both int and str types.
2025-11-16Improve privacy and UX for public feed controlsBen Sima
Privacy improvements: - Removed email address from episode page signup banner - Changed 'This episode was created by <email>' to 'This episode was created using PodcastItLater' - Protects user privacy while still showing the signup prompt Admin UI improvements: - Removed floating Public/Private toggle button (was confusing) - Added '+ Add to public feed' button at bottom of episode cards - Button only visible to admin users - Shows 'Added to public feed' with checkmark when already public - Shows '+ Add to public feed' with plus icon when private - Clearer and more actionable UX for managing public feed content All tests passing (48 tests)
2025-11-16Fix public feed display and admin access issuesBen Sima
Issue #1: demo@example.com admin status - Confirmed demo@example.com IS in ADMIN_EMAILS (working as intended) - Both Core.py and UI.py have demo@example.com in whitelist Issue #2: /public page auto-refresh causing disappearing articles - Created PublicFeedPage component without auto-refresh - Separated from HomePage which has dashboard auto-updates - /public route now uses PublicFeedPage instead of HomePage Issue #3: Homepage missing public feed for logged-out users - Updated HomePage to show public feed when user is not logged in - Shows login form with public episodes below - Includes marketing message: 'Sign up to create your own personal feed!' - Public episodes are fetched and displayed prominently Additional improvements: - Added 'Public Feed' link to navbar for easy access - PublicFeedPage shows RSS feed link for public.rss - Clear separation between user dashboard (auto-refresh) and public feed (static) All tests passing (48 tests)
2025-11-16Add admin@example.com to admin whitelistBen Sima
- Added admin@example.com to ADMIN_EMAILS in Core.py and UI.py - This provides a demo admin account for testing - Public/Private toggle badge already checks for admin status correctly - All tests passing
2025-11-16Add admin metrics dashboardBen Sima
- Added Core.Database.get_metrics_summary() for aggregate stats - Added Core.Database.get_episode_metric_events() for raw event data - Created MetricsDashboard component with summary cards and top episodes tables - Added /admin/metrics route with admin authentication - Added metrics link to admin dropdown menu - Added comprehensive tests for metrics functionality - Fixed type errors in Admin.py by adding MetricCardAttrs - All tests passing (48 tests total in Web.py) - Completed epic t-ga8V8O (24/24 tasks)
2025-11-16Add audio intro/outro and comprehensive testsBen Sima
- Enhanced Worker.py to extract publication date and author from articles - Added intro TTS with metadata (title, author, publication date) - Added outro TTS with attribution - Combined intro, pauses, content, and outro in Worker.py - Added comprehensive tests for public feed, deduplication, metrics, and intro/outro All tests passing (Worker: 30 tests, Web: 43 tests) Tasks completed: - t-gcNemK: Extract metadata in Worker.py - t-gcPraJ: Add intro TTS generation - t-gcRCzw: Add outro TTS generation - t-gcTPQn: Combine audio segments - t-gcW6zN: Tests for public feed - t-gdlWtu: Tests for deduplication - t-gdoeYo: Tests for metrics tracking - t-gdqsl7: Tests for audio intro/outro
2025-11-16Add metrics tracking endpoint and JavaScript for play eventsBen Sima
- Added POST /episode/{id}/track endpoint to track play/download events - Added JavaScript to audio player to track first play event - JavaScript sends fetch request to tracking endpoint on play - Tracks user_id if logged in, otherwise anonymous - Added main() function to Episode.py for test compatibility Tasks completed: t-gcdFSb, t-gcfTnG
2025-11-16Fix repl.sh and typecheck.sh to properly parse bild --plan JSONBen Sima
The issue was that bild --plan outputs progress indicators before the JSON, causing jq to fail parsing. Fixed by: - Using grep to extract only lines starting with '{' (the JSON output) - This filters out progress lines like '[…] target' - Restored typecheck.sh to use repl.sh for proper environment setup Now typecheck.sh correctly provisions the environment via repl.sh instead of trying to use bild or raw python.
2025-11-16Add 'Add to feed' button on episode pages and fix typecheck.shBen Sima
- Episode pages now show 'Add to feed' button for logged-in users who don't have the episode - Added POST /episode/{id}/add-to-feed endpoint - Tracks 'added' metric when user adds episode to their feed - Added Database.track_episode_metric() function for metrics tracking - Fixed typecheck.sh to use bild instead of broken repl.sh approach Tasks completed: t-gc9aud, t-gcbqDl
2025-11-16Add admin toggle for episode public/private statusBen Sima
- Add toggle button to episode cards (admins only) - Button shows globe icon for public, lock icon for private - Toggle endpoint at POST /admin/episode/{id}/toggle-public - Updates episode is_public status and redirects to home Tasks completed: t-gcbqDl, t-gc6Vrk (partially - admin toggle complete)
2025-11-16Fix pre-existing test failures in Web.pyBen Sima
- test_session_persistence: Check for navbar links instead of removed 'Logged in as:' text - test_delete_action: Add referer header to trigger HX-Redirect response
2025-11-16Fix test failures by adding episodes to user_episodes junction tableBen Sima
When tests create episodes directly, they must also add them to the user_episodes junction table for them to appear in user feeds. This maintains the new many-to-many relationship architecture. Test suite now has same 2 pre-existing failures as before (unrelated to this work): - test_session_persistence (expects 'Logged in as:' text that doesn't exist) - test_delete_action (expects HX-Redirect header from admin delete) All new functionality tests pass.
2025-11-15Add public feed routes and update home pageBen Sima
- Add /public route showing public episodes - Add /public.rss RSS feed for public episodes - Update home page to show public feed when not logged in - Use user_episodes junction table instead of user_id filtering - All tests passing
2025-11-15Implement episode deduplication in submission flowBen Sima
- Check for existing episodes by URL hash before processing - Reuse existing episodes when user submits duplicate URL - Add episode to user's feed if they don't have it - Track 'added' metrics when episode added to feed - Worker now creates user_episodes link and tracks metrics - Show appropriate messages for already-in-feed vs newly-added episodes
2025-11-15Add database migrations for public feed, metrics, and deduplicationBen Sima
- Add is_public column to episodes table - Add user_episodes junction table for many-to-many relationship - Add episode_metrics table for tracking engagement - Add original_url_hash column for deduplication - Add Core.py functions for public episodes (mark_public, get_public_episodes) - Add Core.py functions for user_episodes (add_episode_to_user, user_has_episode, get_user_episodes) - Add Core.py functions for metrics tracking (track_episode_event, get_episode_metrics) - Add URL normalization and hashing utilities - All tests passing
2025-11-15Add backward compatibility redirect for legacy episode URLsBen Sima
Maintain compatibility with old sequential integer episode URLs by redirecting them to the new sqid-based URLs with a 301 permanent redirect. - Add /episode/{episode_id:int} route for legacy integer IDs - Redirect with 301 status to indicate permanent move to new URL - Add test to verify redirect behavior - Mark route as deprecated in documentation This allows existing shared links to continue working while encouraging adoption of the new non-sequential URLs. The legacy route can be removed after a deprecation period. Amp-Thread-ID: https://ampcode.com/threads/T-cc5d29f0-454e-4864-8d7e-1ad69a42afa9 Co-authored-by: Amp <amp@ampcode.com>
2025-11-15Use sqids for non-sequential episode URLsBen Sima
Replace sequential integer IDs with sqids in episode URLs for better privacy and security. Episode IDs are no longer easily guessable. - Add sqids dependency to Web.py - Create encode_episode_id() and decode_episode_id() helper functions - Update /episode/{episode_sqid} route to accept and decode sqids - Update EpisodeList to generate sqid-based links - Update RSS feed to use sqids in episode URLs - Update EpisodeDetailPage to accept and use sqids for share URLs - Update all tests to use sqids Episode URLs now look like /episode/AbCd1234 instead of /episode/1 Database still uses integer IDs internally for efficiency. Amp-Thread-ID: https://ampcode.com/threads/T-cc5d29f0-454e-4864-8d7e-1ad69a42afa9 Co-authored-by: Amp <amp@ampcode.com>
2025-11-15Add Open Graph and metadata tags to episode pagesBen Sima
- Add page_title and meta_tags parameters to PageLayout - Generate episode-specific page titles: '<Episode Title> - PodcastItLater' - Add Open Graph meta tags for better link previews: - og:title, og:type, og:url - og:description with duration and author - og:audio with MP3 URL - og:site_name - Add Twitter Card tags for Twitter sharing - Include article:author when available This improves how episode links appear when shared in messaging apps, social media, and other platforms that support Open Graph protocol. Amp-Thread-ID: https://ampcode.com/threads/T-cc5d29f0-454e-4864-8d7e-1ad69a42afa9 Co-authored-by: Amp <amp@ampcode.com>
2025-11-15Fix run.sh to handle bild --plan JSON outputBen Sima
The bild --plan command now outputs progress indicators before JSON. Updated run.sh to use 'tail -1' to extract only the JSON line and fixed the file path check to use the full path. Amp-Thread-ID: https://ampcode.com/threads/T-cc5d29f0-454e-4864-8d7e-1ad69a42afa9 Co-authored-by: Amp <amp@ampcode.com>
2025-11-15Add individual episode pages with sharing and media playerBen Sima
- Create new Episode.py module with episode-specific components - EpisodePlayer: HTML5 audio player - ShareButton: Clipboard copy with Bootstrap input-group pattern - SignupBanner: Promotional banner for non-authenticated users - EpisodeDetailPage: Full page layout - Update Web.py to add /episode/<id> route (public, no auth required) - Make episode titles clickable in EpisodeList component - Add Database.get_episode_by_id() method for efficient queries - Update RSS feed and share buttons to use Bootstrap input-group pattern - Add comprehensive test suite for episode detail pages All episode pages are publicly accessible and include: - Media player to listen to episodes - Share button with URL copying - Links to original articles - Creator attribution banner for non-logged-in users Amp-Thread-ID: https://ampcode.com/threads/T-cc5d29f0-454e-4864-8d7e-1ad69a42afa9 Co-authored-by: Amp <amp@ampcode.com>
2025-11-15Expand terminalLock scope to protect all terminal I/OBen Sima
Problem: Still getting segfaults ("free(): invalid pointer") even with ncurses calls protected. The mutex only covered ANSI calls, but IORef reads and IO.hPutStr operations were happening outside the lock. Root cause: Race conditions in concurrent terminal output: 1. Multiple threads reading namespaceLines IORef concurrently 2. Interleaved IO.hPutStr calls corrupting output buffer 3. Rainbow.hPutChunks not being thread-safe Solution: Expand terminalLock scope to cover entire output operations: - Move IORef reads inside the lock - Protect all IO.hPutStr and Rainbow.hPutChunks calls - Lock both SingleLine and MultiLine modes - Ensure atomicity from IORef read through all I/O to flush This makes each updateLine/updateLineState call atomic, preventing any interleaving of terminal operations between threads. Changes: - updateLine SingleLine: wrap entire output in withMVar terminalLock - updateLine MultiLine: move nsMap read inside lock - updateLineState SingleLine: wrap entire output in withMVar terminalLock - updateLineState MultiLine: move nsMap read inside lock Tested: 10/10 successful runs of `bild --time 0 **/*` without segfaults.
2025-11-15Improve terminalLock comment for clarityBen Sima
Clarify that the mutex protects against ncurses thread-safety issues that cause segfaults during concurrent builds. This commit also forces a new Nix derivation hash to ensure the mutex fix is actually used (previous builds were cached with the old version).
2025-11-15Fix segfault: add mutex for ANSI terminal operationsBen Sima
Problem: Intermittent segfaults when running `bild --time 0 **/*` with many concurrent builds. Core dumps showed crashes in libncursesw's free() function during terminal cleanup. Root cause: ANSI.getTerminalSize and other ANSI terminal library calls are not thread-safe. With mapConcurrentlyBounded running up to 8 analyses concurrently, multiple threads were calling ANSI functions simultaneously, causing memory corruption in the ncurses library. Solution: Add global MVar terminalLock to serialize all ANSI terminal operations. Wrap all ANSI function calls (cursor movement, line clearing, etc.) with withMVar terminalLock. Changes: - Add terminalLock :: MVar () in Omni/Log/Concurrent.hs - Wrap all ANSI calls in withMVar terminalLock: - initializeLines: cursor column, clear line - updateLine: cursor up/down, column set, clear line - updateLineState: cursor up/down, column set, clear line - withLineManager: cursor up Tested: 5 consecutive runs of `bild --time 0 **/*` complete without segfaults (previously failed 1-2 out of 3 runs).