# punchlist — agents.md

Project constitution. Inherits from `/srv/CLAUDE.md` (server scope) and
`/srv/apps/CLAUDE.md` (tenant scope). Only rules meeting the admission rubric
(failure-backed, tool-enforceable, decision-encoding, or triggerable) belong
here — no generic advice a model already applies. Budget: ~200 lines.

Model-independence: this file is the source of truth. `CLAUDE.md` is a symlink
to it so Claude Code loads the same content.

## Read first (in order)
1. **`brief.md`** — what this project is, and the stack decision.
2. **`.logs/planning/`** — the build plan: locked decisions, milestones, gates.
3. **`/srv/projects/standards/README.md`** — server-wide coding standards
   (dispatches by stack: `coding.md` → your stack doc → `frontend.md`).
4. **`.logs/handoff.md`** — newest-first; where the last session left off.

## Project-specific rules
- **The LABEL carries the goal and never changes with the step** (rian,
  2026-08-20): "Check if you can add people at the property level" as an item
  line is the failure — the item stays "Grant us GA4 admin access" and the
  BUTTON becomes "Added at the property level". Spec: title = goal-phrased
  label ({{variables}} ok, fields never); step `instruction` lives behind the
  chevron. When rendering an item title anywhere, use the interpolated `label`
  field, not raw `title` (the queue leaked {{tokens}} once).
- **Button register: short verb-first, 3-4 words max** ("Upload brand
  guide", "Submit ID") — never first-person sentences. Sentences live in menu
  items and instructions. The "or" chip is THE alternatives affordance; don't
  reinvent it per view (rian, 2026-08-20).
- **The client surface stays checklist-simple.** Depth (detail, tutorial,
  alternatives) is progressive disclosure behind subtle affordances — never
  add visible clutter to the item row (plan §2). A team verification step must
  render as "waiting on us" (struck through) to the client, never as their
  problem.
- **Published workflow specs are immutable** — new version, never UPDATE
  (code guard + DB trigger); items pin their version forever. `item_events`
  is append-only; `items.status/current_step` are rebuildable caches.
- **Authoring is AI-first**: the spec doc in plan §6 is the ONE canonical
  format reference; validation errors must name the step and suggest fixes.
  Never make a UI the only way to author a workflow.
- **Conditionals are humans picking buttons** — alternative `jump`s between
  named steps. No expression language, no parallel branches, ever.
- **Frontend API types are hand-kept in `api.ts` for M1** — the backend has no
  Pydantic response models yet, so there is nothing for openapi-typescript to
  generate. When response models land (M2, with the authoring API), switch to
  the generated client per react.md and delete the hand types. Until then,
  api.ts is the one place they live.
- **Caddie seams, not caddie coupling:** `punchlists.external_ref`, the
  six-state rollup mapping, synchronous first `post_status()` (when the
  drop-ins land). Punchlist must lose nothing if caddie's rows vanish.

## Operational
- **Manage:** `srv-gw {deploy,restart,logs,status} --project punchlist`.
- **Deploy confirmation:** the running version is visible (`/api/meta`, UI
  footer, or equivalent). Every change bumps it and adds a newest-first
  CHANGELOG line — the visible version is how you confirm a deploy landed.
- **Write access:** `punchlist-dev` Unix group (setgid + default ACL). New files need
  `chmod 664` / dirs `775`, or `srv-gw fix-permissions --project punchlist`,
  so the service user can read them.
- **Create new subdirectories under `sg punchlist-dev`.** If the session's groups
  don't include `punchlist-dev`, the kernel silently strips setgid on `chmod 2775`
  and files underneath get the wrong group.

## Layout
```
/srv/apps/punchlist/          # workspace — docs and runtime state
├── brief.md  agents.md  CLAUDE.md -> agents.md
├── .logs/{planning/, handoff.md, diary.md}
├── .memory/  .archive/  notes/
└── main/                  # the instance — code only
```
Runtime state (uploads, dumps) belongs at the workspace root, not in
`main/`. The compose file and `.env` sit at the workspace root because
`srv-gw deploy` requires them there — a documented deviation until T3.1.
