# AGENTS.md — Sis Project Conventions ## Project Overview Sis is a shared household chore/task tracker written entirely in Haskell using Hyperbole, a serverside web framework. There is zero application JavaScript. ## Build & Tooling - **Haskell container:** `./hs ` runs Haskell tools inside the flipstone/haskell-tools Docker image. Use for `stack build`, `stack test`, `hpack`, `fourmolu`, `hlint`. - **Build script:** `./scripts/build` — formats (fourmolu), lints (hlint), builds with stack, copies binary to `build/`. - **Test script:** `./scripts/test` — hlint, `stack test`. - **Run script:** `./scripts/run` — starts server in Docker via `stack exec`. - **hpack:** `package.yaml` is the source of truth for dependencies. After editing it, run `./hs hpack` to regenerate `sis-server.cabal`. (If `hpack` is unavailable, edit `sis-server.cabal` manually in parallel.) ## Haskell Conventions - **Style:** fourmolu-formatted. Run `./hs fourmolu --mode inplace app/ src/ test/` before committing. - **Lint:** hlint clean required — MUST run `./hs hlint app/ src/ test/` and fix all hints before committing. Zero hints is the standard. Do not suppress or ignore hlint suggestions. - **Pre-commit checklist:** Before every commit, run: 1. `./hs fourmolu --mode inplace app/ src/ test/` — format code 2. `./hs hlint app/ src/ test/` — fix ALL hints (must output "No hints") 3. `./hs stack build --fast` — must compile with zero errors 4. `./hs stack test --fast` — all tests must pass - **Warnings:** `-Wall -Werror` in `package.yaml`. All warnings are fatal. - **Module qualifiers:** Use qualified imports with descriptive aliases (e.g., `import Data.Text qualified as T`). - **Architecture:** The backend uses [Hyperbole](https://github.com/seanhess/hyperbole) for serverside HTML rendering and interactivity via WebSocket. Pages are Haskell functions returning `Page es '[ViewId]`, with interactive components as `HyperView` instances. - **Database:** Custom `effectful` `DB` effect in `Sis.Database`. All DB operations go through the effect (use the lowercase convenience functions like `findUserByEmail`, not the raw constructors). ## Frontend Conventions - **Framework:** [Hyperbole](https://github.com/seanhess/hyperbole) — Haskell serverside web framework. All HTML rendered in Haskell. - **CSS:** [Neo Brutalism](https://github.com/matifandy8/NeoBrutalismCSS) CDN via jsdelivr + `frontend/static/style.css` for custom styles. - **Build:** No npm/build step for frontend. All pages rendered in Haskell. - **Interactive components:** HyperViews with typed Actions and server-side updates via VirtualDOM over WebSocket. ## Project Structure ``` sis/ ├── app/Main.hs # Hyperbole app entry, Warp setup, route dispatch ├── src/ │ ├── Sis.hs # Top-level re-exports │ ├── Sis/Route.hs # Route ADT with Route instance │ ├── Sis/Types.hs # Core domain types │ ├── Sis/Database.hs # effectful DB effect, SQLite operations │ ├── Sis/Auth.hs # Password hashing │ ├── Sis/Page/ │ │ ├── Login.hs # Login page │ │ ├── Signup.hs # Signup page │ │ ├── Dashboard.hs # Dashboard with stats + due/completed items │ │ ├── Chores.hs # Chore list + create/edit form │ │ ├── Household.hs # Members, invites, household management │ │ └── Activity.hs # Activity log with pagination │ ├── Sis/View/ │ │ └── Layout.hs # Shell: document head, navbar, page wrapper │ └── Sis/Style.hs # Neo Brutalism class helpers ├── frontend/ │ └── static/ │ ├── style.css # Custom CSS │ └── manifest.json # PWA manifest ├── test/Spec.hs # Hspec test suite ├── docs/ │ ├── specs/ # Design specs │ └── plans/ # Implementation plans ├── scripts/ # build, test, run ├── package.yaml # Haskell deps (hpack source of truth) ├── sis-server.cabal # Generated by hpack ├── stack.yaml # Stack resolver config └── Dockerfile # Production image ``` ## Commit Style - Conventional commits: `feat:`, `deps:`, `test:`, `chore:`, `docs:`. - Each commit should be a self-contained logical change. - Run `./scripts/test` before committing. Tests must pass. ## Agent Autonomy - Run `./hs hlint app/ src/ test/` and fix ALL hints before committing. - As changes are completed then verify functionality using Playwright - Once functionality is confirmed then commit and push changes