# AnimalTrack Project Instructions ## Project Status Check `PLAN.md` for current progress. Each step has a checkbox to track completion. ## Critical Workflow Rules ### 1. Commit Frequently **ALWAYS commit after completing any step.** Don't let changes accumulate. ### 2. Update Plan After completing work, update `PLAN.md`: - Check off completed items with `[x]` - Add commit hash if significant ### 3. Run Tests ```bash pytest tests/ -v ``` ## Framework Documentation **ALWAYS consult docs before implementing UI.** Use vendored documentation. | Framework | Main Context | Examples | |-----------|-------------|----------| | FastHTML | `docs/vendor/fasthtml/llms-ctx.txt` | API refs in `docs/vendor/fasthtml/` | | MonsterUI | `docs/vendor/monsterui/llms.txt` | `docs/vendor/monsterui/examples/` | ### Idiomatic Patterns - **Always check docs for the idiomatic way** before implementing anything with FastHTML/MonsterUI - MonsterUI components: `Card`, `Alert`, `Grid(cols_sm/md/lg)`, `DivFullySpaced` - Use `AlertT` enums for alerts, `TextPresets` for typography - Forms: Use MonsterUI form components, not raw HTML ## Quick Reference ### Database (APSW + FastLite) This project uses APSW (not standard sqlite3) via fastlite. Key patterns: ```python from fastlite import database db = database('animaltrack.db') # db.execute() returns APSW cursor # Use db.t for table access ``` ### Timestamps All timestamps are ms since Unix epoch, stored as INTEGER: ```python import time ts_utc = int(time.time() * 1000) # Current time in ms ``` ### IDs All entity IDs are ULIDs (26 chars): ```python from ulid import ULID id = str(ULID()) # "01ARZ3NDEKTSV4RRFFQ69G5FAV" ``` ### Money Store all prices as integer cents. Display prices with 2 decimals, cost/egg with 3. ## Project-Specific Rules ### Event Sourcing - Every state change is an event - Events are immutable (edits create revisions, deletes create tombstones) - Projections are updated synchronously in the same transaction ### Selection Context When handling animal selections: 1. Client sends filter + resolved_ids + roster_hash 2. Server re-resolves at ts_utc 3. On mismatch: return 409 with diff, require `confirmed=true` to proceed ### Feed Costing - Block FeedGiven if no FeedPurchased exists <= ts_utc - Store feed amounts in grams (INTEGER) for precision - Display as kg with 3 decimals ### Migrations - Migration files must end with `;` and NO trailing newline - Python's sqlite3.executescript() has a bug: trailing newlines after the final `;` create empty statements that cause SQLITE_MISUSE errors when APSW logging is enabled - Use `animaltrack create-migration "description"` to create new migrations (template handles this correctly) ## Refreshing Docs ```bash # FastHTML curl -s https://www.fastht.ml/docs/llms-ctx.txt -o docs/vendor/fasthtml/llms-ctx.txt # MonsterUI curl -s https://raw.githubusercontent.com/AnswerDotAI/MonsterUI/refs/heads/main/docs/llms.txt -o docs/vendor/monsterui/llms.txt ``` ## E2E Tests The spec defines 8 authoritative acceptance tests in §21. These are the source of truth for correct behavior. When in doubt, refer to the spec. Numeric comparisons on REAL values use tolerance `±0.001`.