# equinoxbusinesslaw — agents.md

Project constitution. Inherits from `/srv/CLAUDE.md` (server) and `/srv/apps/CLAUDE.md`
(tenant). 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. `CLAUDE.md` is a symlink to this file (model-independence).

## Read first (in order)
1. **`brief.md`** — what this project is, who is involved, and the stack decision.
2. **`.logs/planning/scope.md`** — what was sold (the accepted proposal's deliverables,
   add-on status, exclusions). The build is measured against this, nothing else.
3. **`.logs/planning/build-plan.md`** — locked decisions, phases, gates, definition of done.
4. **`/srv/projects/standards/README.md`** — server-wide coding standards
   (dispatches by stack: `coding.md` → `wordpress.md` → `frontend.md`).
5. **`.logs/handoff.md`** — newest-first; where the last session left off.

Design work also reads **`.logs/planning/design-direction.md`** and, for the mockup
step, **`.logs/planning/homepage-mockup-brief.md`**.
Migration work also reads **`.logs/planning/content-migration.md`** and
**`.logs/planning/site-architecture.md`**.
Schema work reads **`.logs/planning/schema-entity-plan.md`**.
Forms/CTA/tracking work reads **`.logs/planning/tracking-conversion.md`**.

## Project-specific rules

- **Never touch the live site.** `https://equinoxbusinesslaw.com` stays on the
  client's current host until launch cutover (proposal: "the live site stays
  untouched until you approve"). This project is a build environment only. AISV
  was still publishing to the live site as of 2026-09-02 (their Phase 01), so a
  content freeze or delta-sync date is agreed with AISV directly — never relayed
  through the client — and posts are re-counted at export and again before cutover.

- **Launch is a DNS cutover to this server, not a file transfer.** The client took
  the Hosting add-on (2026-08-13) and confirmed "Move to PlusROI" (2026-08-27): the
  staging project `equinoxbusinesslaw` becomes production, DNS moves to Cloudflare
  (client agreed 2026-08-18; rian@rian.ca is to be invited as super administrator),
  and the production host is marked public (`srv-gw id-gate --site
  equinoxbusinesslaw.com --mode public`) while staging stays gated. Sequence in
  `.logs/planning/build-plan.md` Phase 6.

- **No page build before the client approves the mockup, and the mockup round runs
  home page first.** The Design Mockup and Review Round was sold (accepted
  2026-08-13): one designed concept, one comprehensive feedback round, delivered
  before building. Step 1 is **two home-page mockups showing two design
  directions, home page only** (Rian, 2026-09-02); the brief is
  `.logs/planning/homepage-mockup-brief.md`. No inner pages, no pattern library, no
  Kadence build until Rian has chosen a direction and recorded it in
  `.logs/handoff.md`. **Work that is not the two home-page variations is not built at all**
  (Rian, 2026-09-03): an idea outside the step is written into `notes/design-notes.md` or the
  requests table and left there until Rian answers. Raising it and proceeding is not approval,
  and neither is raising it twice. `.logs/planning/design-direction.md` anchors every design
  artifact, and every artifact is checked against its checklist before the client
  sees it.

- **Pricing never enters this project.** Nothing about what the client pays us,
  what we pay vendors, or what AISV projects the client will earn — no amounts,
  rates, ranges, or commercial terms of any kind — lives in the workspace. Refer to
  add-ons and plans by name only ("the Hosting add-on", "the Design Mockup and
  Review Round"). Any client or vendor document that arrives with pricing is
  digested into `notes/` with the numbers removed; the original is kept outside the
  project. Nothing enforces this mechanically — before every checkpoint, grep the
  project for the currency symbol and for rate, plan-price, and commercial-term
  vocabulary, and fix any hit before writing the handoff.

- **AISV owns copy; we draft placeholders.** Draft from the brand story and the
  client's existing copy, label every draft `DRAFT`, and never present it as
  final. Content and messaging decisions go to AISV and the client. When AISV's
  own documents disagree (audience threshold; three cuts of the service taxonomy),
  flag the inconsistency in `.logs/handoff.md` — do not resolve it yourself.

- **The client's 2026-08-27 decisions are binding.** The design brief is "a more
  elevated, simplified look and feel" — the client called the live site "visually
  busy and somewhat dated". No Twitter or Facebook mentions anywhere — links,
  icons, share buttons, `sameAs` (LinkedIn and YouTube stay). The Meta pixel is
  tracking, not a mention; it is preserved under the tracking rule below. No EO
  Portland or Women in Finance links in Community Involvement. States: Washington
  first, Oregon secondary, Colorado retained; no DC or VA anywhere. The new logo
  comes from the Brand Kit — never the 20th-anniversary logo on the live site. Team
  photos only where `.logs/planning/design-direction.md` allows (none on the
  homepage; one or two site-wide). Stock imagery is fine, but no stock photos of
  people. Team: Mandy Bowen out, Nicole Farahdel (Corporate Paralegal) in with a
  labelled placeholder until her headshot and bio arrive — 9 bios in total.

- **Flag licensing wording before writing it.** The live Legal Health Check
  disclaimer says "Washington, Idaho, and Oregon"; the client advertises WA, OR and
  CO. Do not write any "licensed in" language until the client resolves it.

- **One name for the assessment, everywhere.** Until AISV and the client confirm,
  write "the Business Legal Health Assessment (name to be confirmed)" on first
  mention and "the assessment" after. Once confirmed, that single name goes in
  navigation, CTAs, page title, URL, and schema — never two names on one site.

- **Schema is a plugin, not code.** All structured data is delivered by configuring
  `bw-ai-schema-pro` (team post type mapped in its settings; Person from the
  team-survey workflow,
  `/srv/apps/bw-plugins/wp-content/plugins/bw-ai-schema-pro/docs/SPEC-team-survey.md`).
  Never hand-write JSON-LD — no `functions.php` snippets, no pasted `ld+json`, no
  second schema plugin. If a task starts to look like custom schema code, stop and
  re-read `.logs/planning/schema-entity-plan.md`. Yoast's JSON-LD graph is switched
  off entirely (`bw-ai-schema-pro` Schema Sources setting) once Yoast is installed
  (it is not on staging as of 2026-09-02); exactly one graph per page, from the
  plugin, so the entity is not split again. FAQ content is for buyers and AI answer
  engines, not rich snippets: Google stopped showing FAQ rich results on 2026-05-07.

- **Build with patterns, not bespoke pages.** Every recurring section is an
  unsynced Kadence pattern in a project category, inserted then edited per page.
  Never hand-build a one-off layout that an existing pattern plus changed variables
  covers, and never clone a near-duplicate pattern when a toggle covers it.

- **A pattern whose contents cannot be edited is a broken pattern.** WordPress locks
  non-declared blocks inside patterns to content-only editing, which silently makes
  images, buttons, and tables un-swappable. Every block type used inside a pattern
  is declared editable from one shared list. Verify by inserting the pattern and
  confirming an image shows a **Replace** button before calling it done.

- **Posts migrate in full — no pruning, no editorial rewrite.** All 513 published
  posts (as of 2026-09-02) with categories, tags, dates, featured images, and
  author. Content pruning is AISV's Phase 04 and is explicitly not sold. The
  conversion touches presentation only and is verified text-in equals text-out:
  strip markup before and after and confirm no words were lost. Keep post content
  as standard blocks, never inside Kadence layout blocks.

- **Every changed URL gets a redirect, and the redirect map is a deliverable.**
  The post archive and its rankings are the firm's most valuable asset. Any
  retired, moved, or re-slugged URL (including `/danica-paddock/` and Alicia's
  old bio slug) is listed in `.logs/planning/site-architecture.md` and loaded into
  Redirection (or equivalent) before cutover.

- **Never cut over without `.logs/planning/tracking-conversion.md` green.** Every
  tag on the live site is re-implemented and verified on the new one: GTM container
  `GTM-TGTVD37`, Google tag `GT-55KZDRZS` / GA4 stream `G-PTGQ1K61M6`, Hotjar site
  `3664447`, RB2B, Meta pixel, Usercentrics consent via Termageddon. CTA click and
  form-submission events must fire separately for the direct path (Book a
  Consultation) and the transitional path (the assessment).

- **The REST API stays functional.** AISV's OpenForge drafts posts into WordPress;
  the working assumption is the REST API (`/wp-json`), with the exact transport and
  auth method to be confirmed with AISV. Never restrict authenticated REST writes,
  public `/wp/v2/posts` reads, or application passwords — OpenForge depends on
  them. Unauthenticated user enumeration (`/wp/v2/users` without auth) may be
  limited on the production site once AISV confirms OpenForge's auth method does
  not rely on it (to be confirmed with AISV, Phase 0). Staging's id-auth gate
  blocks external tools by design; whoever opens it for AISV re-gates it
  (`/srv/CLAUDE.md`, "Temporarily opening a gated site").

- **The assessment is a Typeform embed, not a rebuild.** Widget `QIIINVqG` (iframe
  title "BHA Survey") carries over as-is; if the live embed passes hidden or UTM
  fields, they carry over too — confirm the field list with AISV before rebuilding
  the page. The interactive "Smart BHA" is AISV's Creative Concept 03, out of scope.

- **Snapshot the database before any destructive content pass.** There is no
  sanctioned dump command for developers; `.logs/planning/build-plan.md` holds the
  safe workaround. Never put the DB password on a command line or in chat.

- **Nobody pastes credentials in chat.** Licence keys (Gravity Forms, Search &
  Filter Pro, Termageddon), the `support` password, and application passwords go
  into 0600 files or the WordPress admin by the human who holds them.

- **Child theme version bumps are PATCH** (`/srv/projects/standards/wordpress.md`).
  `kadence-child` starts at 1.0.0; every change increments the patch number in
  `style.css`.

## Operational

- **Manage:** `srv-gw {status,restart,logs,deploy} --project equinoxbusinesslaw`.
- **WP-CLI:** `srv-gw wp --project equinoxbusinesslaw -- <command>`.
- **Read the DB:** `srv-gw db-query --project equinoxbusinesslaw "<SELECT ...>"`
  (read-only; writes go through `srv-gw wp`).
- **Write access:** `equinoxbusinesslaw-dev` Unix group (setgid + default ACL). New
  files need `chmod 664` / dirs `775`, or `srv-gw fix-permissions --project
  equinoxbusinesslaw`, so WordPress (`www-data`) can read them. A plugin file at
  600 is the usual cause of "the plugin does not have a valid header".
- **Create new subdirectories under `sg equinoxbusinesslaw-dev -c '...'`** if the
  Edit/Write tools return permission denied (see `/srv/CLAUDE.md`, "Editing
  WordPress Files"), so new files land in the project group.
- **Build URL:** `https://equinoxbusinesslaw.demoing.info` — id-auth gated, Pattern
  C (shared password gate in front; WordPress `/wp-login.php` and `/wp-admin`
  behind it); port 3139 internal, proxied through Caddy.
- **Admin user:** `support` (the template's standard admin). Rian holds the
  password; never write it anywhere.
- **Database:** `wp_equinoxbusinesslaw` (user `wp_equinoxbusinesslaw`); credentials
  in `.env` at the workspace root.
- **Container limits:** 1 GB RAM / 1 CPU; Apache capped at 18 workers
  (`apache-tuning.conf`); uploads 128 MB (`uploads.ini`). Created 2026-07-27.
- **Members (as of 2026-09-02):** rian, adi (granted 2026-09-02), plus service accounts. Add teammates with
  `srv-gw grant-access --project equinoxbusinesslaw --user <name>` (owner runs it).

## Layout

```
/srv/apps/equinoxbusinesslaw/     # workspace — docs and runtime state
├── brief.md  agents.md  CLAUDE.md -> agents.md
├── .logs/{planning/, handoff.md, diary.md, v8-feedback.md}
├── .memory/  .archive/
├── notes/{source/, inbox/}       # AISV deck + brand story · drop folder
├── docker-compose.yml  .env  uploads.ini  apache-tuning.conf  .project.json
└── wp-content/                   # the instance — themes, plugins, uploads
```

**Declared override (v8 workspace standard).** The instance folder is
`wp-content/`, not `main/`. The gateway bind-mounts `wp-content/` into the
WordPress container at a fixed path, so code cannot move down a level without
breaking the site. This is a deliberate, documented divergence — per
`/srv/apps/CLAUDE.md`, that is conformance, not drift. The compose file and
`.env` sit at the workspace root for the same gateway reason. The scaffolder (run
2026-09-02) also created an empty `main/`; it is not the instance and is removed —
if it ever reappears on disk, delete it, and never put code in it.
