summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Sima <ben@bsima.me>2025-11-13 14:39:13 -0500
committerBen Sima <ben@bsima.me>2025-11-13 14:39:13 -0500
commit81c46826005a60018c2a4f31675ba1f5eff1c7d8 (patch)
tree822e5d962c29354ace5939bfe747208f27a9d015
parentd0085eca6b6788f6830f472ae5d158aa62fecc8b (diff)
Update agents and plan out next work
-rw-r--r--.tasks/tasks.jsonl20
-rw-r--r--AGENTS.md364
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"}
diff --git a/AGENTS.md b/AGENTS.md
index f70adaf..5b37334 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -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