# AGENTS.md — Where Woof (resume brief)

> The **source of truth is `where_woof.md`** (product plan + roadmap) and the **`openspec/` changes**. This file is a quick-resume overview for any agent or session picking the project back up.

## What this is

Where Woof — a **return-tag platform** (not a tracker): pre-coded QR/NFC tags on items; a finder scans → sees return details → owner gets an SMS alert (with finder location when permitted). Branding: "Where Woof !" (werewolf wordplay).

## How we work (the pipeline)

- **Master/worker**: the main pi session (cwd = repo root) orchestrates; subagents do chunks — `database` (schema/queries), `coder-pro` (Go code), `devops-pro` (infra/secrets), `code-analysis` (review). User reviews via plannotator's browser UI when it cooperates; otherwise inline approval.
- Per change: **openspec** (propose → design/specs → tasks, `openspec validate`) → **plannotator** plan (`plans/<name>.md`, submit → approve) → execute with `[DONE:n]` → run `/tmp` verify suites → `code-analysis` review → commit + push to Gitea.
- This is a **learning exercise for the user** — explain decisions, don't just execute.

## Where we are (2026-08-05)

- **Phase 1 `frontend-foundation` — DONE** (22/22 scenarios verified)
- **Phase 2 `scan-flow` — CODE DONE + verified (19/19)**; **step 9 (real SMS) PENDING** — needs the user's SMSGlobal (MXT) API key/secret; verify `frontend/internal/sms/smsglobal.go` auth against their prior globalsms integration before the real send
- **Phase 2.5 queued (tuxedo, priority B):** ① re-alert when a *different* finder phone arrives within the 250 m / 10-min window; ② JS browser fingerprint + 24 h block (store fingerprint in DB)
- **Phases 3–9 pending** (see roadmap in `where_woof.md`): HTMX/Alpine polish → Laravel admin → billing (Stripe AU) → photo uploads → deploy frontend (.13 + Caddy .35 + InMotion redirect) → deploy admin → anti-abuse hardening

## Key locations

| What | Where |
|---|---|
| Product plan + roadmap (source of truth) | `where_woof.md` |
| OpenSpec specs & changes | `openspec/` (`frontend-foundation` ✅, `scan-flow` ✅) |
| Plannotator plans | `plans/frontend-foundation.md`, `plans/scan-flow.md` |
| Go front-end | `frontend/` (stdlib `net/http`, `internal/{db,auth,handlers,sms}`) |
| Schema | `db/schema.sql` (canonical until Laravel owns migrations) |
| Build/run targets | `Makefile` — `db-up`, `seed`, `run`, `build`, `generate`, `psql` |
| Dev DB | `wherewoof-db` Postgres 16 container on **.13:5434** (user/db `wherewoof`; compose + `.env` in `/home/sam/Docker/Containers/wherewoof-db/` on .13) |
| Run locally | `make db-up && make seed && make run` → `http://localhost:3020` (SMS in **log mode** until creds set) |
| Verify suites | `/tmp/verify.sh` (Phase 1, 22 checks), `/tmp/verify2.sh` (Phase 2, 19 checks) — ephemeral, they reset the DB |
| Prod target | `.13:/var/www/where-woof` — **NOT deployed yet (Phase 7)**; Caddy on .35; InMotion redirect → `where-woof.com` |
| Gitea | `sam/where_woof` — `ssh://git@gitea.lab.audasmedia.com.au:2222/sam/where_woof.git` |

## Tools

- `openspec` 1.3.1 (spec-driven dev), `plannotator` (plan + browser review), pi subagents (master/worker), `sqlc` 1.31.1 at `~/go/bin` (not on PATH — `make generate` handles it), `pgx` v5, `gorilla/sessions`, `bcrypt`
- **Secrets are env-only, never committed**: `DATABASE_URL`, `SESSION_SECRET`, `SMS_API_KEY`, `SMS_API_SECRET`, `SMS_FROM` (blank = SMSGlobal pooled number)
- SMS is a swappable `internal/sms.Sender` — `LogSender` (default) / `smsglobal.Client` (real)

## Gotchas worth remembering

- `.pi/` is gitignored (agent memory + extension tooling are machine-local)
- NixOS box: **no gcc** (`CGO_ENABLED=0` set via `go env -w`), `make` via `nix profile`, no `psql` (use `make psql` → docker exec on .13)
- `html/template` escapes `+` as `&#43;` in hrefs (`tel:`/`sms:` links still work in a browser)
- `pkill -f` can match your own shell — use `pkill -x where-woof`
- Reset the DB between the two verify suites (both bind `TEST000001`)
- Postgres identity columns advance on failed inserts (duplicate-email test consumes an id)
