diff options
| -rw-r--r-- | .tasks/tasks.jsonl | 20 | ||||
| -rw-r--r-- | AGENTS.md | 364 |
2 files changed, 180 insertions, 204 deletions
diff --git a/.tasks/tasks.jsonl b/.tasks/tasks.jsonl index dd93d90..9e1fec6 100644 --- a/.tasks/tasks.jsonl +++ b/.tasks/tasks.jsonl @@ -45,3 +45,23 @@ {"taskCreatedAt":"2025-11-13T16:32:17.411379982Z","taskDependencies":[],"taskId":"t-12ZeUsG","taskNamespace":null,"taskParent":"t-12YqUKr","taskStatus":"Done","taskTitle":"Update success/cancel URLs to redirect to / instead of /billing","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T16:36:41.808119038Z"} {"taskCreatedAt":"2025-11-13T16:32:17.557115348Z","taskDependencies":[],"taskId":"t-12Zfwnf","taskNamespace":null,"taskParent":"t-12YqUKr","taskStatus":"Done","taskTitle":"Remove 'Billing' button from navbar (paid users will use Stripe portal link in callout)","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T16:34:44.628587871Z"} {"taskCreatedAt":"2025-11-13T16:32:17.738052991Z","taskDependencies":[],"taskId":"t-12ZghrB","taskNamespace":null,"taskParent":"t-12YqUKr","taskStatus":"Done","taskTitle":"Test the complete flow and verify all changes","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T16:37:49.356932049Z"} +{"taskCreatedAt":"2025-11-13T19:38:07.804316976Z","taskDependencies":[],"taskId":"t-1f9QP23","taskNamespace":null,"taskParent":null,"taskStatus":"Open","taskTitle":"General Code Quality Refactor","taskType":"Epic","taskUpdatedAt":"2025-11-13T19:38:07.804316976Z"} +{"taskCreatedAt":"2025-11-13T19:38:08.01779309Z","taskDependencies":[],"taskId":"t-1f9RIzd","taskNamespace":null,"taskParent":null,"taskStatus":"Open","taskTitle":"Account Management Page","taskType":"Epic","taskUpdatedAt":"2025-11-13T19:38:08.01779309Z"} +{"taskCreatedAt":"2025-11-13T19:38:08.176692694Z","taskDependencies":[],"taskId":"t-1f9SnU7","taskNamespace":null,"taskParent":null,"taskStatus":"Open","taskTitle":"Queue Status Improvements","taskType":"Epic","taskUpdatedAt":"2025-11-13T19:38:08.176692694Z"} +{"taskCreatedAt":"2025-11-13T19:38:08.37344762Z","taskDependencies":[],"taskId":"t-1f9Td4U","taskNamespace":null,"taskParent":null,"taskStatus":"Open","taskTitle":"Navbar Styling Cleanup","taskType":"Epic","taskUpdatedAt":"2025-11-13T19:38:08.37344762Z"} +{"taskCreatedAt":"2025-11-13T19:38:32.95559213Z","taskDependencies":[],"taskId":"t-1fbym1M","taskNamespace":null,"taskParent":"t-1f9QP23","taskStatus":"Open","taskTitle":"Remove BLE001 noqa for bare Exception catches - use specific exceptions","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T19:38:32.95559213Z"} +{"taskCreatedAt":"2025-11-13T19:38:33.139120541Z","taskDependencies":[],"taskId":"t-1fbz7LV","taskNamespace":null,"taskParent":"t-1f9QP23","taskStatus":"Open","taskTitle":"Fix PLR0913 violations - refactor functions with too many parameters","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T19:38:33.139120541Z"} +{"taskCreatedAt":"2025-11-13T19:38:33.309222802Z","taskDependencies":[],"taskId":"t-1fbzQ1v","taskNamespace":null,"taskParent":"t-1f9QP23","taskStatus":"Open","taskTitle":"Extract format_duration utility to shared UI or Core module (used only in Web.py)","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T19:38:33.309222802Z"} +{"taskCreatedAt":"2025-11-13T19:38:33.491331064Z","taskDependencies":[],"taskId":"t-1fbABoD","taskNamespace":null,"taskParent":"t-1f9QP23","taskStatus":"Open","taskTitle":"Extract extract_og_metadata and send_magic_link to Core module for reusability","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T19:38:33.491331064Z"} +{"taskCreatedAt":"2025-11-13T19:38:33.674140035Z","taskDependencies":[],"taskId":"t-1fbBmXa","taskNamespace":null,"taskParent":"t-1f9QP23","taskStatus":"Open","taskTitle":"Review and fix type: ignore comments - improve type safety","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T19:38:33.674140035Z"} +{"taskCreatedAt":"2025-11-13T19:38:33.85804778Z","taskDependencies":[],"taskId":"t-1fbC8Nq","taskNamespace":null,"taskParent":"t-1f9QP23","taskStatus":"Open","taskTitle":"Remove PLR2004 magic number - use constant for month check","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T19:38:33.85804778Z"} +{"taskCreatedAt":"2025-11-13T19:38:34.035597081Z","taskDependencies":[],"taskId":"t-1fbCSZd","taskNamespace":null,"taskParent":"t-1f9RIzd","taskStatus":"Open","taskTitle":"Implement cancel subscription functionality","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T19:38:34.035597081Z"} +{"taskCreatedAt":"2025-11-13T19:38:34.194926176Z","taskDependencies":[],"taskId":"t-1fbDyr2","taskNamespace":null,"taskParent":"t-1f9RIzd","taskStatus":"Open","taskTitle":"Implement delete account functionality","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T19:38:34.194926176Z"} +{"taskCreatedAt":"2025-11-13T19:38:34.384489707Z","taskDependencies":[],"taskId":"t-1fbElKv","taskNamespace":null,"taskParent":"t-1f9RIzd","taskStatus":"Open","taskTitle":"Implement change email address functionality","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T19:38:34.384489707Z"} +{"taskCreatedAt":"2025-11-13T19:38:34.561871604Z","taskDependencies":[],"taskId":"t-1fbF5Tv","taskNamespace":null,"taskParent":"t-1f9RIzd","taskStatus":"Open","taskTitle":"Add logout button to account page","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T19:38:34.561871604Z"} +{"taskCreatedAt":"2025-11-13T19:38:34.777721397Z","taskDependencies":[],"taskId":"t-1fbG02X","taskNamespace":null,"taskParent":"t-1f9RIzd","taskStatus":"Open","taskTitle":"Replace Coming Soon placeholder with full account management UI","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T19:38:34.777721397Z"} +{"taskCreatedAt":"2025-11-13T19:38:34.962196629Z","taskDependencies":[],"taskId":"t-1fbGM2m","taskNamespace":null,"taskParent":"t-1f9SnU7","taskStatus":"Open","taskTitle":"Add remove button to queue status items","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T19:38:34.962196629Z"} +{"taskCreatedAt":"2025-11-13T19:38:35.119686179Z","taskDependencies":[],"taskId":"t-1fbHr0w","taskNamespace":null,"taskParent":"t-1f9Td4U","taskStatus":"Open","taskTitle":"Remove button classes from navbar links (make them regular nav links)","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T19:38:35.119686179Z"} +{"taskCreatedAt":"2025-11-13T19:38:35.311151364Z","taskDependencies":[],"taskId":"t-1fbIeOF","taskNamespace":null,"taskParent":"t-1f9Td4U","taskStatus":"Open","taskTitle":"Remove 'Logged in as' text from navbar","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T19:38:35.311151364Z"} +{"taskCreatedAt":"2025-11-13T19:38:35.476139354Z","taskDependencies":[],"taskId":"t-1fbIVJL","taskNamespace":null,"taskParent":"t-1f9Td4U","taskStatus":"Open","taskTitle":"Left-align navbar links instead of right-aligned buttons","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T19:38:35.476139354Z"} +{"taskCreatedAt":"2025-11-13T19:38:35.65125955Z","taskDependencies":[],"taskId":"t-1fbJFic","taskNamespace":null,"taskParent":"t-1f9Td4U","taskStatus":"Open","taskTitle":"Remove logout button from navbar (will be in account page)","taskType":"WorkTask","taskUpdatedAt":"2025-11-13T19:38:35.65125955Z"} @@ -1,8 +1,53 @@ -# Task Manager for AI Agents +# Omni -This document describes the task tracking system for AI coding agents working in this codebase. +The Omni project is to leverage automation and asymmetries to create wealth. The +target of the wealth is Bitcoin. The means: write everything down, first +in English, then in code. -## Overview +This document describes how AI agents should interact with this repo, the "omnirepo". + +## About Omnirepo + +Resources defined in the repo can be used to quickly create and release +products. New technology shall be prototyped and developed as needed. + +### Source Layout + +The source tree maps to the module namespace, and roughly follows the Haskell +namespace hierarchy. This is true of all languages: Python, Scheme, Rust, C, +etc. + +Namespaces are formatted either as file paths, like `Omni/Dev`, or +dot-separated, like `Omni.Dev`. Parts of the namespace should always be +capitalized. + +The namespace for all products that we own is `Biz`, this includes proprietary +applications, products, and related infrastructure. + +The `Omni` namespace is used for internal development tooling and infrastructure +that are shared between all other projects. + +Stuff that can be open sourced or otherwise externalized should be outside of +`Biz` or `Omni`. + +Related code should be kept close together. This means that you should start +with small namespaces: use `Omni/Thing.hs` before `Omni/Thing/Service.hs`. Try +to keep all related code in one spot for as long as possible. + +Re-use code from the `Omni/` namespace as much as possible. For example, use +`Omni/Cli.hs` or `Omni/Test.py` instead of trying to roll your own code for cli +parsing or running test suites. If the the namespace doesn't have the feature +you need, then add the feature. + +Boundaries and interfaces between namespaces should be singular and +well-defined. Likewise, the functionality and purpose of a particular +namespace should be singular and well-defined. Follow the unix principle +of "do one thing and do it well." + +Namespaces are always capitalized. In Scheme and Python this actually translates +quite well and helps distinguish between types/classes/modules and values. + +## Task Manager for AI Agents The task manager is a dependency-aware issue tracker inspired by beads. It uses: - **Storage**: Local JSONL file (`.tasks/tasks.jsonl`) @@ -10,7 +55,7 @@ The task manager is a dependency-aware issue tracker inspired by beads. It uses: - **Dependencies**: Tasks can block other tasks - **Ready work detection**: Automatically finds unblocked tasks -## Quick Reference +**IMPORTANT**: This project uses `task` for ALL issue tracking. Do NOT use markdown TODOs, task lists, or other tracking methods. ### Create a Task ```bash @@ -39,7 +84,7 @@ task create "Fix type errors" --namespace="Omni/Task" ``` **Task Types:** -- `epic` - Container for related tasks (replaces the old "project" concept) +- `epic` - Container for related tasks - `task` - Individual work item (default) **Dependency Types:** @@ -104,7 +149,7 @@ task tree [<id>] Shows task hierarchy with visual status indicators: - `[ ]` - Open -- `[~]` - In Progress +- `[~]` - In Progress - `[✓]` - Done Examples: @@ -140,9 +185,9 @@ task init Creates `.tasks/` directory and `tasks.jsonl` file. -## Common Workflows +### Common Workflows -### Starting New Work +#### Starting New Work 1. **Find what's ready to work on:** ```bash @@ -159,7 +204,7 @@ Creates `.tasks/` directory and `tasks.jsonl` file. task update t-20241108120000 done ``` -### Creating Dependent Tasks +#### Creating Dependent Tasks When you discover work that depends on other work: @@ -175,7 +220,7 @@ task create "Implement API client" --deps=t-20241108120000 --dep-type=blocks The dependent task won't show up in `task ready` until the blocker is marked `done`. -### Discovered Work Pattern +#### Discovered Work Pattern When you find work during implementation, use the `--discovered-from` flag: @@ -189,7 +234,7 @@ task create "Fix memory leak in parser" --deps=t-abc123 --dep-type=discovered-fr The `discovered-from` dependency type maintains context but **doesn't block** the ready work queue. This allows AI agents to track what work was found during other work while still being able to work on it immediately. -### Working with Epics +#### Working with Epics ```bash # Create an epic for a larger feature @@ -208,68 +253,49 @@ task list --parent=t-abc123 task list --type=epic ``` -### Breaking Down Large Work - -```bash -# Create parent epic -task create "Complete authentication system" --type=epic -# Note ID: t-20241108120000 - -# Create subtasks that depend on planning -task create "Backend auth service" --parent=t-20241108120000 -task create "Frontend login UI" --parent=t-20241108120000 -task create "Integration tests" --parent=t-20241108120000 -``` - -## Agent Best Practices +### Agent Best Practices -### 1. Always Check Ready Work First +#### 1. Always Check Ready Work First Before asking what to do, check `task ready` to see unblocked tasks. -### 2. Create Tasks for Discovered Work +#### 2. Create Tasks for Discovered Work When you encounter work during implementation: ```bash task create "Fix type error in auth module" --discovered-from=t-abc123 task create "Add missing test coverage" --discovered-from=t-abc123 ``` -### 3. Track Dependencies +#### 3. Track Dependencies If work depends on other work, use `--deps`: ```bash # Can't write tests until implementation is done task create "Test auth flow" --deps=t-20241108120000 --dep-type=blocks ``` -### 4. Use Descriptive Titles +#### 4. Use Descriptive Titles Good: `"Add JWT token validation to auth middleware"` Bad: `"Fix auth"` -### 5. Use Epics for Organization +#### 5. Use Epics for Organization Organize related work using epics: - Create an epic for larger features: `task create "Feature Name" --type=epic` - Add tasks to the epic using `--parent=<epic-id>` - Use `--discovered-from` to track work found during implementation -## Task Lifecycle - -``` -[open] ──update in-progress──> [in-progress] ──update done──> [done] - │ │ - └─────────update open───────────────┘ -``` - -States: -- **open**: Not started, available for work (if not blocked) -- **in-progress**: Currently being worked on -- **done**: Completed +#### 6. Store AI planning docs in `_/llm` directory +AI assistants often create planning and design documents during development: +- PLAN.md, DESIGN.md, TESTING_GUIDE.md, tmp, and similar files +- **Best Practice: Use a dedicated directory for these ephemeral files.** +- Store ALL AI-generated planning/design docs in `_/llm` +- The `_` directory is ignored by git and all of our temporary files related to the omnirepo go there -## Dependency Rules +### Dependency Rules - A task is **blocked** if any of its dependencies are not `done` - A task is **ready** if all its dependencies are `done` (or it has no dependencies) - `task ready` only shows tasks with status `open` or `in-progress` that are not blocked -## File Structure +### File Structure ``` .tasks/ @@ -286,7 +312,7 @@ Each line in `tasks.jsonl` is a JSON object representing a task. **Git Hooks**: This repository uses hooks from `Omni/Ide/hooks/` (configured via `core.hooksPath`). Do NOT add hooks to `.git/hooks/` - they won't be version controlled and may cause confusion. -## Testing and Development +### Testing and Development **IMPORTANT**: When writing or testing code that modifies tasks, use the test database: @@ -306,7 +332,40 @@ unset TASK_TEST_MODE **Never run destructive tests against the production database** (`.tasks/tasks.jsonl`) as this will delete real task data. -## Example Session +## Integration with Git + +The `.tasks/tasks.jsonl` file is git-tracked. When you: +- Create/update tasks locally +- Commit and push +- Other machines/agents get the updates on `git pull` + +**Important**: Add to `.gitignore`: +``` +.tasks/*.db +.tasks/*.db-journal +.tasks/*.sock +``` + +But **do** track: +``` +!.tasks/ +!.tasks/tasks.jsonl +``` + +### Troubleshooting + +#### "Task not found" +- Check the task ID is correct with `task list` +- Ensure you've run `task init` + +#### "Database not initialized" +Run: `task init` + +#### Dependencies not working +- Verify dependency IDs exist: `task list` +- Check dependency tree: `task deps <id>` + +### Example Session ```bash # First time setup @@ -341,7 +400,19 @@ task ready # Shows: "Write storage tests" and "Fix edge case in ID generation" ``` -## Build and Test Commands +### Important Rules + +- Use `task` for ALL task tracking +- Link discovered work with `discovered-from` dependencies +- Check `task ready` before asking "what should I work on?" +- Store AI planning docs in `_/llm` directory +- Do NOT create markdown TODO lists +- Do NOT put TODOs or FIXMEs in code comments +- Do NOT use external issue trackers +- Do NOT duplicate tracking systems +- Do NOT clutter repo root with planning documents + +## Development Guide and Tools ### bild @@ -354,6 +425,15 @@ bild --time 0 Omni/Cloud.nix # Build with no timeout bild --plan Omni/Test.hs # Analyze build without building ``` +When the executable is built, the output will go to `_/bin`. Example: + +```bash +# build the example executable +bild Omni/Bild/Example.py +# run the executable +_/bin/example +``` + ### run.sh `run.sh` is a convenience wrapper that builds (if needed) and runs a namespace. @@ -369,46 +449,51 @@ This script will: 2. Build it if it doesn't exist (exits on build failure) 3. Execute the binary with any additional arguments -### Test Commands +### lint -Run tests: +Universal lint and formatting tool. Errors if lints fail or code is not formatted properly. + +Examples: ```bash -task test # Run task manager tests -bild --test Omni/Task.hs # Build and test a namespace +lint Omni/Cli.hs # Lint a namespace +lint --fix **/*.py # Lint and fix all Python files ``` -## Integration with Git +### repl.sh -The `.tasks/tasks.jsonl` file is git-tracked. When you: -- Create/update tasks locally -- Commit and push -- Other machines/agents get the updates on `git pull` +Like `nix-shell` but specific to this repo. Analyzes the namespace, pulls dependencies, and starts a shell or repl. -**Important**: Add to `.gitignore`: -``` -.tasks/*.db -.tasks/*.db-journal -.tasks/*.sock +Examples: +```bash +repl.sh Omni/Bild.hs # Start Haskell repl with namespace loaded +repl.sh --bash Omni/Log.py # Start bash shell for namespace ``` -But **do** track: -``` -!.tasks/ -!.tasks/tasks.jsonl +### typecheck.sh + +Like `lint` but only runs type checkers. Currently just supports Python with `mypy`, but eventually will support everything that `bild` supports. + +Examples: +```bash +typecheck.sh Omni/Bild/Example.py # Run the typechecker and report any errors ``` -## Troubleshooting +### Test Commands -### "Task not found" -- Check the task ID is correct with `task list` -- Ensure you've run `task init` +Run tests: +```bash +bild --test Omni/Task.hs # Build and test a namespace +``` -### "Database not initialized" -Run: `task init` +The convention for all programs in the omnirepo is to run their tests if the first argument is `test`. So for example: -### Dependencies not working -- Verify dependency IDs exist: `task list` -- Check dependency tree: `task deps <id>` +```bash +# this will build a the latest executable and then run tests +bild --test Omni/Task.hs + +# this will just run the tests from the existing executable +_/bin/task test +``` ## Adding New Dependencies @@ -431,39 +516,6 @@ import stripe The package name must match the nixpkgs python package name (usually the PyPI name). Check available packages: `nix-env -qaP -A nixpkgs.python3Packages | grep <name>` -## Development Tools - -### bild - -`bild` is the universal build tool. It can build and test everything in the repo. - -Examples: -```bash -bild --test Omni/Bild.hs # Build and test a namespace -bild --time 0 Omni/Cloud.nix # Build with no timeout -bild --plan Omni/Test.hs # Analyze build without building -``` - -### lint - -Universal lint and formatting tool. Errors if lints fail or code is not formatted properly. - -Examples: -```bash -lint Omni/Cli.hs # Lint a namespace -lint --fix **/*.py # Lint and fix all Python files -``` - -### repl.sh - -Like `nix-shell` but specific to this repo. Analyzes the namespace, pulls dependencies, and starts a shell or repl. - -Examples: -```bash -repl.sh Omni/Bild.hs # Start Haskell repl with namespace loaded -repl.sh --bash Omni/Log.py # Start bash shell for namespace -``` - ## Coding Conventions 1. **Test interface**: Every program must accept `test` as a first argument to run its test suite @@ -501,7 +553,7 @@ git commit -m "Your commit message" ```bash # Make additional changes git add . -git commit --amend --no-edit +git amend ``` **Move/restack commits:** @@ -510,12 +562,6 @@ git move -s <source> -d <destination> git restack ``` -**Submit changes:** -```bash -# After commits are ready -git submit -``` - ### When to Record Changes in Git **DO record in git:** @@ -548,93 +594,3 @@ lint Omni/YourNamespace.hs ``` **Fix all reported errors** related to your changes before marking the task as complete. This ensures code quality and prevents breaking the build for other contributors. - -## Database Migrations - -### SQLite Limitations - -When writing migrations for SQLite databases: - -1. **Cannot add UNIQUE constraints via ALTER TABLE** - SQLite's ALTER TABLE doesn't support adding constraints. Add columns without UNIQUE and rely on application logic to enforce uniqueness. - - ```python - # Wrong - will fail silently - cursor.execute("ALTER TABLE users ADD COLUMN email TEXT UNIQUE") - - # Correct - add without UNIQUE - cursor.execute("ALTER TABLE users ADD COLUMN email TEXT") - ``` - -2. **Always log migration failures** - Don't silently swallow exceptions. Use `logger.debug()` to log when columns already exist. - -3. **Migrations run on startup** - `Database.init_db()` should be called in the `main()` function of web services to ensure migrations run every time the service starts. - -## Testing External API Integrations - -When integrating with external services like Stripe, payment processors, or other APIs: - -### Mock Webhooks in Tests - -Instead of calling real APIs, mock the webhook payloads: - -```python -class TestWebhookHandling(Test.TestCase): - def test_subscription_created(self): - # Mock the webhook payload structure - subscription = { - "id": "sub_test123", - "customer": "cus_test123", - "status": "active", - # ... other fields - } - _handle_webhook(subscription) - # Assert expected database changes -``` - -### Local Webhook Testing - -For services like Stripe that send webhooks: - -1. **Use CLI tools** - Most services provide CLI tools for local testing: - ```bash - stripe listen --forward-to localhost:8000/webhook - stripe trigger checkout.session.completed - ``` - -2. **Bypass signature verification in test mode** - Check if secret is configured before verifying signatures: - ```python - if WEBHOOK_SECRET: - event = verify_signature(payload, signature, WEBHOOK_SECRET) - else: - logger.warning("Signature verification skipped (test mode)") - event = json.loads(payload) - ``` - -3. **Handle API version differences** - External APIs change over time. Use fallbacks for field names: - ```python - # Try multiple field names for compatibility - period_start = ( - subscription.get("current_period_start") - or subscription.get("billing_cycle_anchor") - or subscription.get("start_date") - ) - ``` - -### Verify with Database Inspection - -When debugging integrations, check the database directly: -```bash -sqlite3 path/to/db.db "SELECT * FROM table WHERE condition;" -``` - -This confirms whether webhooks/integrations actually updated the data. - -## Future Enhancements - -Planned features (not yet implemented): -- Task priorities -- Due dates -- Task labels/tags -- Search/filter capabilities -- Assignees -- Multi-repo support |
