---
type: plan
title: "Build plan"
status: active
updated: 2026-09-02
---

# Build plan

The sequence for rebuilding equinoxbusinesslaw.com on Kadence, from the state on 2026-09-02
(proposal accepted 2026-08-13, kickoff call 2026-08-27, staging an untouched template clone,
nothing mocked up or built) to launch on PlusROI hosting. Each phase has a goal, its inputs,
a task list, an exit gate, and an owner. Do not start a phase whose gate-in decision is still
open (see "Decisions still needed before their phase").

What was sold is in `.logs/planning/scope.md`; this file decides how it gets built. The
detail plans it points at: `.logs/planning/site-architecture.md` (pages, URLs, redirects,
nav), `.logs/planning/content-migration.md` (posts, media, users, taxonomy),
`.logs/planning/schema-entity-plan.md` (entity and structured data),
`.logs/planning/design-direction.md` (the mockup brief and checklist),
`.logs/planning/tracking-conversion.md` (tags, CTAs, forms, Pipedrive). The evidence base is
`notes/site-audit-2026-07.md`; the client's words are in `notes/client-correspondence.md`.

Precedence when sources disagree: live-site facts and staging state follow the 2026-09-02
inspection; what was sold follows the proposal; client decisions follow the email thread
(newest wins). Nothing in this file states an amount or a commercial term; add-ons and
plans are referred to by name only.

Naming used here: the assessment is "the Business Legal Health Assessment (name to be
confirmed)" and "the assessment" after. States: Washington first, Oregon secondary, Colorado
retained; DC and VA removed (client decision 2026-08-27). Posts: 513 published as of
2026-09-02 (the proposal's 510 was a July count). Team: 9 bios (8 live plus Nicole
Farahdel).

Server rules are not restated. Before the first code session read
`/srv/projects/standards/README.md` (it dispatches to `coding.md`, `wordpress.md`,
`frontend.md`), then `agents.md` in this workspace.

## Locked decisions

These are settled. Reopening one is a scope conversation with Rian, not a build choice.

| Decision | Why | Source / date |
|---|---|---|
| Block-based WordPress on the Kadence framework (Kadence theme, Kadence Blocks, Kadence Blocks Pro, Kadence Pro on the Gutenberg editor), built as an **unsynced pattern library**: every section type is an unsynced Kadence pattern whose inner blocks are declared editable, so AISV and the client add pages without a developer. Posts stay standard content (classic HTML or core blocks), never inside Kadence layout blocks, so the disclosed Kadence lock-in is confined to pages. | AISV's plan runs on a weekly publishing cadence with execution resting on one person; on a custom build every landing page routes through a developer. AISV's Phase 01 drafts posts into WordPress via OpenForge. Vercel/Next.js was considered and declined for this reason (not for speed or SEO, which were conceded). | Platform-decision reply to the client (digest in `notes/client-correspondence.md`); acceptance 2026-08-13; `/srv/projects/standards/wordpress.md` |
| Schema is delivered by configuring `bw-ai-schema-pro` (v2.6.0, from plugins.bowden.works). No hand-written JSON-LD anywhere: no `functions.php` output, no pasted script blocks, no second schema plugin. Yoast's competing Organization/WebSite output is disabled. | House rule; the plugin renders schema for posts and pages from templates, emits Person schema for detected team members and authors, ships a FAQ block, and has a team-survey workflow for Person fields (whether its templates cover LegalService and Service out of the box is to be confirmed by Rian on install). | `/srv/projects/standards/wordpress.md`; proposal "Advanced AI Schema" 2026-07-30; `/srv/apps/bw-plugins/wp-content/plugins/bw-ai-schema-pro/docs/SPEC-team-survey.md` |
| Keep every post: 513 published as of 2026-09-02, migrated with categories, tags, dates, and featured images intact. No pruning, merging, or rewriting. | Content pruning is AISV's Phase 04; the proposal excludes an editorial review. | Proposal "Post Structure and Blog Migration" and "Not included" 2026-07-30; accepted 2026-08-13 |
| All build work happens on staging at `https://equinoxbusinesslaw.demoing.info` (project `equinoxbusinesslaw`, container `equinoxbusinesslaw-wordpress`, port 3139 behind Caddy, id-auth Pattern C gate). The live site is read from, never written to. | Proposal: "we build on a private staging site and migrate at launch, so the live site stays untouched until you approve." | Project created 2026-07-27; proposal "Things We Need to Confirm" |
| Launch is to PlusROI hosting (this server) with DNS on Cloudflare. Launch is a DNS cutover, not a file transfer: the staging project becomes production. | Client took the Hosting add-on 2026-08-13 and wrote "Hosting: Move to PlusROI" 2026-08-27; said 2026-08-18 they were open to the Cloudflare move and asked what it involved; agreement recorded in the 2026-09-02 ground truth. | Email thread 2026-08-13, 2026-08-18, 2026-08-27 |
| A designed mockup is produced and approved by the client before any page is built (client gate). One comprehensive feedback round. | The Design Mockup and Review Round add-on was accepted 2026-08-13. Rian promised an initial mockup within a week of receiving the design inputs, then a review call. Inputs arrived 2026-08-27. | Email thread 2026-08-13, 2026-08-24, 2026-08-27 |
| States: Washington first, Oregon secondary, Colorado retained; DC and VA removed everywhere (header, footer, contact copy, `areaServed`). No licensing sentence is written until the Idaho/Colorado discrepancy is resolved (see open decisions). | Client decision; the firm's own signature changed to "WA, OR and CO". The proposal had offered to drop Colorado too; the client's answer overrides it. | Email thread 2026-08-27 |
| We draft placeholder copy from the AISV brand story (complete homepage copy), the strategy deck, and existing site copy. Equinox finalizes with AISV's guidance. The build never waits on copy; the client never reviews Lorem Ipsum. Every drafted block is labelled DRAFT in the handoff. | Proposal "Content"; the brand story already contains the full homepage landing-page copy. | Proposal 2026-07-30; accepted 2026-08-13 |
| The assessment carries over as the existing Typeform embed (widget `QIIINVqG`, iframe title "BHA Survey") on a dedicated, prominent page with a clean path in. It is not rebuilt as an interactive tool. | Platform confirmed by inspection 2026-09-02; the AI rebuild is AISV's Creative Concept 03 and excluded by the proposal. | Ground truth 2026-09-02; proposal "Not included" |
| The WordPress REST API stays open and working on the launched site, unauthenticated reads included, for AISV's OpenForge. No hardening plugin or snippet that restricts `/wp-json`, user endpoints, or application passwords. | AISV's Phase 01 sets up OpenForge to draft posts into WordPress; the live API responded on 2026-09-02. | Strategy notes 2026-07-27; proposal "How This Splits With AISV"; AISV deck Phase 01 |
| Paired CTAs site-wide: "Book a Consultation" (direct) and "Take the Business Legal Health Assessment (name to be confirmed)" (transitional), in that order, each firing its own GTM event. Replaces the single "Schedule a Meeting" ask. | Brand story defines the pairing; proposal builds to it. | Brand story; proposal "Calls to Action" 2026-07-30 |
| The tracking stack is preserved and verified, not rebuilt: GTM `GTM-TGTVD37`, Google tag `GT-55KZDRZS`, GA4 `G-PTGQ1K61M6` ("Equinox Website"), Hotjar site `3664447`, RB2B, Meta pixel (presence to be confirmed from the GTM container; only a dns-prefetch was seen in page source), Usercentrics via Termageddon. Google Ads is out of scope. | Proposal "Tracking Preservation"; AISV's Phase 02 onward depends on RB2B and Hotjar data. | Live IDs measured 2026-09-02; email thread 2026-08-24 (Ads) |
| Team: 9 bios on one template (the 8 live bios plus Nicole Farahdel, Corporate Paralegal, placeholder until her headshot and bio arrive). Mandy Bowen removed. Twitter and Facebook removed everywhere; EO Portland and Women in Finance removed from the footer; the anniversary logo replaced with the Brand Kit logo; no team photos on the homepage (the client's ask, qualified "if that works from a design standpoint"; confirm at the mockup review), at most one or two site-wide; stock imagery allowed but no stock photos of people. | Client decisions. | Email thread 2026-08-27 |
| Add-on status: Design Mockup and Review Round ACCEPTED; Hosting ACCEPTED; Fractional General Counsel Landing Page with Tiered Pricing PENDING (do not build until decided); Practice Area and Topic Hub Architecture NOT ACCEPTED (do not build hub templates or a hub URL architecture). | Acceptance email. | Email thread 2026-08-13 |

## Decisions still needed before their phase

### Migration route (Rian decides in Phase 0; G0 requires it recorded)

**Route A (recommended): restore the live site into staging, then strip and rebuild.**
Restore the live site's database and media into the staging install via UpdraftPlus (already
installed on staging), keeping post IDs, slugs, user accounts, Yoast meta, Gravity Forms
forms and entries, and Search & Filter Pro configuration. Then switch the theme to Kadence,
remove `html5blank`, Beaver Builder, UABB, and any host-specific mu-plugins, and rebuild the
pages as blocks. Every post, author, image path, and per-post SEO field arrives exactly as it
is on live, so the redirect map is small (only the URLs we deliberately change) and the author
audit works on the real accounts. Trade-offs: the untouched template clone is discarded (its plugin set is re-applied after
the restore); Beaver Builder page content becomes junk that must be stripped from `wp_posts`
and its meta; the restore needs a full UpdraftPlus backup set from live, which needs live
WordPress admin access (a Route A prerequisite for Phase 0). Snapshot staging before the
restore and again before the theme/plugin swap (see "Database snapshot procedure").

**Route B: keep the template clone and import posts via WXR.** Export posts, pages, media,
and users from live with the WordPress exporter and import into the clean clone. Simpler and
never brings Beaver Builder along, but it loses Yoast meta fidelity (the WXR carries
`_yoast_wpseo_*` meta only if the exporter is run with it, and remapping is manual), loses
Gravity Forms entries and Search & Filter Pro configuration, creates new user accounts and new
post IDs (breaking any ID-based links and the author audit's starting point), and re-downloads
media through the importer, which historically drops files at scale. Choose B only if live
WordPress admin access with backup capability never arrives (Route B works with an export
file alone).

The choice sets what Phase 0 must obtain (Route A: admin access to live WordPress with the
ability to run UpdraftPlus; Route B: an export file), and how `.logs/planning/content-migration.md` is
executed. Record the choice in `.logs/handoff.md` and `.memory/`.

### Other gating questions

Each blocks the phase named. Ask early; do not guess. Full register with context in
`.logs/planning/scope.md` ("Things to confirm").

| Question | Who answers | Blocks | Default until answered |
|---|---|---|---|
| One name for the assessment ("Legal Health Check" on the live site, "Business Health Assessment" / "BHA" in the AISV deck and the Typeform iframe title, "Business Legal Health Assessment" in the brand story). Used in nav, CTAs, page title, URL, and schema. | AISV with the client | Phase 2 (nav label, CTA pattern text), Phase 3 (page title and URL), Phase 5 (schema) | Build with "the Business Legal Health Assessment (name to be confirmed)" as the label and a URL placeholder; global find-and-replace at the answer. Raise at the mockup review call. |
| Canonical legal name and physical address. Live: footer "Equinox Law Group PLLC", form consent "Equinox Business Law Group PLLC", Yoast graph split between "Equinox Law Group" and "Equinox Business Law Group". No address anywhere on the live site. | Alicia Wimmer / Michelle Bomberger | Phase 0 (site title), Phase 3 (contact page), Phase 5 (LegalService entity) | Working assumption "Equinox Business Law Group PLLC"; phone 425-250-0205; address unknown. Ask with the billing-address question. |
| States and licensing wording. Client: advertise WA, OR, CO. The live assessment page disclaimer says the firm is "licensed to practice law in Washington, Idaho, and Oregon". Is Colorado licensed? Is Idaho current? What sentence is legally correct? | Michelle Bomberger | Phase 3 (contact page and assessment page copy), Phase 5 (`areaServed`) | Write no licensing sentence. Serve-area copy names WA, OR, CO only. |
| Author roster: per person, keep the byline, reassign the posts, or retire the account. Inputs: the exported database (Route A) or the REST list (9 users with public posts on 2026-09-02; only Michelle Bomberger, Danica Paddock, and Alicia Wimmer are current staff). | Rian prepares the list; Michelle Bomberger / Alicia Wimmer decide | Phase 4 (author migration, archives, redirects), Phase 5 (Person and author-to-bio binding) | Migrate all accounts as-is; no reassignment until the list is answered. Send the list within Phase 0 if Route A data is available, otherwise at the start of Phase 4. |
| Fractional General Counsel Landing Page with Tiered Pricing add-on: go / no-go. | Alicia Wimmer / Michelle Bomberger with Rian (tier numbers come from the client with AISV) | Phase 1 (whether the mockup shows a landing page), Phase 3 (whether it is built) | Not built. The base-scope General Counsel page is rebuilt with its three tiers (Signature General Counsel, Legal Maintenance, Advisor), with no figures. Raise at the mockup review call. |
| Service taxonomy for the Practice Areas page and the nav: brand story (4 groupings), live site (6 services plus 5 groups plus industries as images), deck (Owner / CFO / HR hubs). | AISV with the client | Phase 2 (nav services entry), Phase 3 (Practice Areas page), Phase 5 (Service schema) | Recommend to AISV: the brand story's 4 groupings, with the live sub-lists folded under them. Build to that if unanswered by Phase 3, labelled DRAFT. |
| "Industries we serve" as text (rendered as images on the live page). | Alicia Wimmer, or read from the exported uploads | Phase 3 (Practice Areas page) | Omit until supplied; do not transcribe graphics. |
| Booking mechanism behind "Book a Consultation": keep the Outlook `bookwithme` link or route to the contact form? | Alicia Wimmer / Michelle Bomberger; Rian recommends | Phase 2 (CTA pattern), Phase 5 (GTM event type) | Keep the Outlook link; track it as an outbound click. |
| Pipedrive transport for form leads (Gravity Forms add-on, Zapier/Make, Pipedrive web forms, Typeform native) and who configures it. Newsletter list platform (Constant Contact inferred from the live HTML) and whether the Gravity Forms feed it. OpenForge's authentication method. | AISV with Alicia Wimmer | Phase 5 (forms and routing) | Build the forms with a source field and UTM hidden fields regardless; connect once answered. |
| Licence status and transfer for Gravity Forms, Search & Filter Pro, Termageddon. | Alicia Wimmer (or the client's current vendor) | Phase 0 (install), Phase 4 (filtering), Phase 5 (consent) | Flag in week one; never buy or renew on the client's behalf. |
| Google Tag Manager access: the Google tag's users are managed in GA4 Admin (the error the client hit), and the GTM container `GTM-TGTVD37` is shared separately at tagmanager.google.com under Admin, User Management. | Alicia Wimmer, guided by Rian | Phase 5 (events, tag verification) | Re-paste the container snippet; events wait for access. Send the client the exact steps now. |
| Nicole Farahdel's headshot, bio, and title confirmation. | Alicia Wimmer | Phase 3 (bio page), Phase 6 (launch checklist) | Placeholder page with a non-person image and drafted text; no Person schema until real details exist. |
| Which policy pages migrate: the live sitemap has five (`/terms-of-service/`, `/privacy-policy/`, `/cookie-policy/`, `/disclaimer/`, `/eula/`); the proposal counted four. | Rian with the client | Phase 3 | Migrate all five. |
| Post-launch plan: the Hosting add-on alone or the Hosting and Support plan. | Alicia Wimmer / Michelle Bomberger | Phase 6 close-out | Deferred by Rian 2026-08-24; decide at launch. |
| Which AI crawlers to allow or block in robots.txt and, once DNS is on Cloudflare, in Cloudflare's bot controls (AISV's Phase 04 tracks AI visibility; a higher Cloudflare tier with bot controls can be added later per Rian's 2026-08-18 email). | AISV | Phase 6 (robots.txt and Cloudflare settings before cutover) | Allow all crawlers; no bot blocking in Cloudflare at launch. |

## Phases

Owner names: Rian (delivery, client and AISV communication, every gate), Adi
(design/development on PlusROI builds), Rob (client relationship). Claude sessions execute
under whoever is driving; the owner listed is accountable for the gate.

### Phase 0: Foundations

**Goal:** everything the build needs is in hand or has a dated blocker, and staging is ready
to receive work.

**Inputs:** the 2026-08-27 client email (access status, SharePoint links, design notes),
`.logs/planning/scope.md`, `notes/site-audit-2026-07.md`, `.logs/planning/tracking-conversion.md`.

**Tasks**

Access
- [ ] Google Analytics: granted 2026-08-27 (Alicia's email does not say for which accounts; Rian requested rian@plusroi.com, adi@plusroi.com, plusroi@gmail.com on 2026-08-24). Confirm each can open property stream "Equinox Website" (`G-PTGQ1K61M6`).
- [ ] Google Search Console: granted 2026-08-27. Confirm the property is the `https://equinoxbusinesslaw.com/` domain or URL-prefix property and note which.
- [ ] Google Tag Manager: not granted. Send Alicia Wimmer the two steps: Google tag users are managed in GA4 Admin (the error "This tag's users are controlled by Google Analytics"), and the GTM container `GTM-TGTVD37` is shared separately at tagmanager.google.com under Admin, User Management. Record the ask date in `.logs/handoff.md`.
- [ ] Cloudflare: client open to the move 2026-08-18, walkthrough sent the same day; on 2026-08-27 waiting on their website/email vendor. Chase via Alicia. Needed: super-administrator invitation for rian@rian.ca on the client's Cloudflare account.
- [ ] Registrar access (GoDaddy delegate or equivalent) so Rian can move the domain, or the vendor's cooperation to change nameservers.
- [ ] Live WordPress admin access (administrator role for an @plusroi.com account) and current hosting access. Route A needs admin with the ability to run UpdraftPlus; Route B needs only an export.
- [ ] Decide the migration route (A or B) once it is known what access will arrive. Record in `.logs/handoff.md` and `.memory/`.

Brand assets
- [ ] A human with SharePoint access (Rian, Rob, or Adi, via the links in the 2026-08-27 email) pulls the Brand Kit folder into `notes/source/` and the 2026 Brand Photo Shoot folder into `notes/source/` (originals) and, once selected, the staging media library.
- [ ] Inventory the kit: logo package (SVG, mono, favicon-ready), colours, fonts, any brand guide. Note gaps in `.logs/planning/design-direction.md` and ask Alicia for what is missing.
- [ ] Ask Alicia again (asked 2026-08-24, unanswered 2026-08-27) for two or three websites the client likes and why. Do not block the mockup on it.

Licences
- [ ] Gravity Forms: staging has it from the template; confirm the licence used on staging is one we may use for the client or the client's own key. Confirm the client's key is active.
- [ ] Search & Filter Pro: obtain the client's licence key and plugin zip (from the live site or the client's account).
- [ ] Termageddon: confirm the client's subscription is active and who holds the login; obtain the embed/site key for the new install.
- [ ] Keys go into 0600 files by the person who holds them, never into chat or `.logs/`. Verify by behaviour (the plugin activates and updates), not by reading the key.

Staging preparation
- [ ] Snapshot the database (see "Database snapshot procedure") before touching plugins.
- [ ] Install and activate: Yoast SEO (`srv-gw wp --project equinoxbusinesslaw -- plugin install wordpress-seo --activate`), Redirection (`... plugin install redirection --activate`), Search & Filter Pro (upload the licensed zip), `bw-ai-schema-pro` (from plugins.bowden.works). Keep Kadence, Kadence Blocks, Kadence Blocks Pro, Kadence Pro, Advanced Custom Fields Pro, BW Dev, Gravity Forms, UpdraftPlus active.
- [ ] Set the site title to the working canonical name "Equinox Business Law Group PLLC" (`srv-gw wp --project equinoxbusinesslaw -- option update blogname "Equinox Business Law Group PLLC"`) and the tagline to one of the brand story taglines as a DRAFT (record which). Revisit when the canonical name is confirmed.
- [ ] Confirm `wp-content/` permissions with `srv-gw fix-permissions --project equinoxbusinesslaw` after plugin uploads.
- [ ] Grant team access: `srv-gw grant-access --project equinoxbusinesslaw --user rob` and `--user adi` (owner runs it; as of 2026-09-02 the group holds rian plus service accounts, no other humans).
- [ ] Accounts on staging: the id-auth gate uses the server default shared password (`/srv/CLAUDE.md`, "Site Access Protection"). Rian creates one WordPress Administrator account per teammate (`srv-gw wp --project equinoxbusinesslaw -- user create <name> <name>@plusroi.com --role=administrator`) and one Editor-role test user (`... user create editor-test editor-test@plusroi.com --role=editor`); each person sets their own password through the wp-login "Lost your password?" flow or Rian sets it out of band. Whether staging can send that reset email is to be confirmed by Rian. The shared `support` login is never handed round.
- [ ] Route A only: run the UpdraftPlus restore of the live database and media into staging, then the theme/plugin swap (Kadence active; `html5blank`, Beaver Builder, UABB, host mu-plugins removed), snapshotting before each step. This must finish before Phase 2 starts, because the pattern library is built on the restored install.

Baselines from the live site (read-only)
- [ ] Core Web Vitals baseline (Lighthouse, mobile and desktop, three runs each) on the live home, `/practice-areas-industry/`, and one blog post. Record scores and LCP/CLS/INP in `notes/site-audit-2026-07.md` with the date. This is the "before" the proposal promises to report against.
- [ ] Full tag inventory from the live HTML and the GTM container (once access exists): every tag, trigger, and the pages it fires on. Record in `.logs/planning/tracking-conversion.md`. Note whether Hotjar records (the AISV deck says "reconnect Hotjar").
- [ ] Export the live Yoast sitemaps (`page-sitemap.xml` 32 URLs, `post-sitemap` set for 513 posts, `author-sitemap.xml` 7, `category-sitemap.xml` 51, `post_tag-sitemap.xml` set for 1,004 tags, `article-type-sitemap.xml` 4) and save the URL lists under `notes/`. These are the redirect-map inputs for `.logs/planning/site-architecture.md`.
- [ ] Pull the top landing pages from GA4 (last 12 months) and the top pages from Search Console to rank the redirect map by traffic.

Coordination
- [ ] Agree the content-freeze protocol directly with AISV (not via the client): either a freeze date after which nothing is published on live, or a delta re-import of anything published after the export, re-counted at export and again at launch. Record the agreement and the AISV contact in `.logs/handoff.md`.
- [ ] Send AISV the open questions that are theirs in one message: assessment name, service taxonomy, audience threshold (no figures written in project files), Pipedrive transport, newsletter platform, OpenForge authentication and fields, the FAQ rich-results fact (Google stopped showing FAQ rich results in Search on 2026-05-07), the AI-crawler allow/block policy for robots.txt and Cloudflare, and which of the deck's two phase calendars governs their dependency dates on us (the roadmap page's Jul-Sep / Oct-Dec / Jan-Mar / Apr onward, or the closing page's Jul-Sep / Oct-Nov / Dec-Feb / Mar onward).

**Exit gate:** every access item is either working or has a dated blocker and an owner in
`.logs/handoff.md`; Brand Kit and photo assets are in `notes/source/`; licence status is known
for all three plugins; the plugin set is installed on staging; the CWV baseline, tag inventory,
and sitemap exports are recorded; the freeze protocol is agreed in writing; the migration route
is chosen. **Owner:** Rian.

### Phase 1: Design direction and mockup (CLIENT GATE)

**Goal:** a designed concept the client approves in writing before any page is built.

**Inputs:** `.logs/planning/design-direction.md` (read it first; it holds the client's
written requirements and the design checklist), Brand Kit and photo shoot from `notes/source/`,
the brand story homepage copy (section map in `.logs/planning/site-architecture.md` and the
source in `notes/source/`), the client's 2026-08-27 notes, "sites you like" if answered.

**Tasks**
- [ ] Produce a designed concept for the key pages: Home (to the brand-story structure, real copy, no team photos), General Counsel (the three existing tiers, Signature General Counsel, Legal Maintenance, Advisor, as a comparison structure with no figures; the figures row and the fixed-versus-by-the-hour comparison block only if the Fractional General Counsel Landing Page with Tiered Pricing add-on is accepted), Contact (address block, map, service area WA/OR/CO, the qualification form), Blog index (cards with author, category, filter controls), single post (author box, breadcrumbs, end-of-post paired CTA), one team bio (headshot, title, bio, LinkedIn, link to author archive).
- [ ] Apply the design checklist in `.logs/planning/design-direction.md`: Brand Kit logo (never the anniversary mark), "elevated, simplified" density, no stock photos of people, LinkedIn and YouTube only, community list of five, states line WA/OR/CO, paired CTAs in the header and page ends.
- [ ] Present the mockup to the client on a call; collect one comprehensive round of feedback (the Design Mockup and Review Round includes one round; more is a scope change).
- [ ] On the same call raise: the Fractional General Counsel add-on go/no-go, the assessment name, the canonical legal name and address, the licensing wording, "sites you like".
- [ ] Revise once; obtain written approval by email.
- [ ] File the approval email in `notes/client-correspondence.md` and the approved mockup files under `notes/`.

**Exit gate:** written client approval of the design direction, filed. **Owner:** Rian
(client); Adi (design).

### Phase 2: Design system and pattern library

**Goal:** the Kadence global styles, header/footer/nav, the full pattern set, and the
templates exist on staging, every pattern editable by a non-developer.

**Inputs:** the direction-checked mockup (Phase 2 may start after the internal direction
check in `.logs/planning/design-direction.md` Process step 1 and run in parallel with the
client round; only Phase 3 waits for written approval, G1), Brand Kit,
`/srv/projects/standards/wordpress.md` and `frontend.md`, `.logs/planning/site-architecture.md`
(nav and templates). Anything built in Phase 2 before G1 is revised to the approved mockup at
no scope change.

**Tasks**
- [ ] Kadence global styles from the Brand Kit: palette, type scale, spacing scale, button styles (primary for the direct CTA, secondary for the transitional CTA). No hard-coded colours in patterns.
- [ ] Header: Brand Kit logo (SVG via BW Dev's SVG upload), primary nav, persistent paired CTA. Exactly one `h1` per page: the logo is not a heading.
- [ ] Footer: "Explore" links, the community list of five (EO Seattle, Women's Presidents Organization, Seattle U Family Business Exchange, Bellevue LifeSpring, CFO Leadership Council), LinkedIn and YouTube icons only, the two-line brand message from the brand story, the states line (WA, OR, CO), the copyright with the canonical name, policy links.
- [ ] Navigation that surfaces the services and the General Counsel offer and the assessment; structure per `.logs/planning/site-architecture.md`.
- [ ] Breadcrumbs (Yoast or Kadence, one, not both) on every page and post template except Home.
- [ ] The pattern set, each an unsynced Kadence pattern with inner blocks declared editable: hero; problem list; stakes; guide; grouped value proposition (four cards); three-step process (Assess / Prioritize / Protect and Grow); transformation list; before/after comparison (two columns); who-it-is-for checklist; objection-handling accordion using the `bw-ai-schema-pro` FAQ block; assessment CTA band; final CTA; paired CTA block; end-of-post CTA; team card; testimonial; event card.
- [ ] Templates: single post (author box bound to the team bio, categories, breadcrumbs, end-of-post CTA), blog index (Search & Filter Pro search plus category filter; author on cards), category archive, author archive (photo, title, bio, link to the bio page), search results, 404 (with the paired CTA), page, team index, team bio.
- [ ] Conditional asset loading: Gravity Forms and Search & Filter Pro CSS/JS enqueue only where a form or filter is present.
- [ ] "Every block declared editable" verification: insert each pattern on a test page, log in as the `editor-test` Editor-role user created in Phase 0, confirm every text, image, link, and button is editable and no layout control is locked that an editor would need. Record the pass in `.logs/diary.md`.
- [ ] Check the child theme stays minimal (`style.css`, `functions.php`, `screenshot.webp`); no PHP templates for anything a pattern can express.

**Exit gate:** all patterns and templates exist and pass the editability check; each template
renders one `h1`; the header/footer content matches the client decisions; Rian has reviewed
on staging. **Owner:** Adi (build); Rian (gate).

### Phase 3: Page build and content

**Goal:** every page in the target sitemap exists on staging with drafted copy.

**Inputs:** `.logs/planning/site-architecture.md` (page inventory and dispositions),
brand story copy, live page content (Route A: already in staging; Route B: from the live site),
the mockup.

**Tasks**
- [ ] Home, to the brand-story structure: hero, problem, stakes, guide, value proposition, three-step plan, transformation, before/after, who it is for, objection handling (FAQ block, four Q&A pairs), assessment, final CTA, footer message. Copy from the brand story, labelled DRAFT in the handoff. The "who it is for" list carries no revenue figure until AISV and the client settle the audience threshold.
- [ ] Core pages: About Us, Our Approach, General Counsel (three tiers, no figures), Practice Areas (structure per the taxonomy decision, DRAFT if unanswered), Contact (address and map once supplied; form placeholder until Phase 5), Blog index, the assessment page (dedicated URL, Typeform embed slot, Spirit / Mind / Body framing retained or replaced per AISV), A La Carte Solutions, Testimonials, Events (confirm what feeds it), Newsletter sign-up, Team index.
- [ ] Team bios, 9, on the bio template: Michelle Bomberger (CEO & Managing Attorney), Laura Doehle (COO & Integrator), Danica Paddock (Corporate Counsel; moves from `/danica-paddock/` to the team path), Dominique Zett (Director of Operations & Project Manager), Devon Maxwell (Corporate Paralegal), Leaf E'kaika (Operations Administrator), Alicia Wimmer (Sales & Marketing Operations Coordinator; one canonical slug, default `alicia-wimmer`), Pamela Franklin (Sales & Customer Experience Officer), Nicole Farahdel (Corporate Paralegal; placeholder, non-person image). Headshots from the 2026 Brand Photo Shoot where available.
- [ ] Policy pages migrated directly: `/terms-of-service/`, `/privacy-policy/`, `/cookie-policy/`, `/disclaimer/`, `/eula/` (five unless the client says four). Cookie policy text is Termageddon's; re-attach in Phase 5.
- [ ] Orphan audit with a written recommendation per page (migrate, or retire with a redirect target): `/covid-19-the-resources-your-business-needs/`, `/recommendations-summary-form/`, `/recommendations-summary-download/`, `/business-health-assessment-download/` (confirm with AISV whether Typeform results land here before retiring), `/categories/`, `/go-boldy-with-equinox/`, plus `/danica-paddock/` (moved, not retired). Recommendations go into `.logs/planning/site-architecture.md`; the client decides.
- [ ] Every mention of Twitter, Facebook, DC, VA, EO Portland, Women in Finance, and the anniversary logo removed from migrated page copy. Grep staging content for the banned-mention list in `.logs/planning/site-architecture.md` (Location and state signals) after the build.
- [ ] Nav populated; every page reachable from the nav or the footer; thin pages (Newsletter sign-up, download/summary pages if kept) set noindex in Yoast.

**Exit gate:** every URL in the target sitemap resolves on staging; no Lorem Ipsum; drafted
copy listed as DRAFT in `.logs/handoff.md`; orphan recommendations sent to the client; Rian
review on staging. **Owner:** Adi (build); Rian (gate).

### Phase 4: Migration

**Goal:** posts, media, taxonomy, authors, SEO meta, and redirects are on staging and
verified by counts against live.

**Inputs:** `.logs/planning/content-migration.md` (the mechanics; follow it), the sitemap
exports from Phase 0, the author decision list, the migration route.

**Tasks**
- [ ] Snapshot the database before starting, and again before any author reassignment and before the taxonomy retirement.
- [ ] Posts: all published posts (513 as of 2026-09-02; re-count from live at export) with categories, tags, dates, featured images, excerpts, and slugs unchanged. Drafts and private posts per `.logs/planning/content-migration.md`.
- [ ] Media: full uploads library with original paths (Route A: already in place; Route B: verify every featured image resolved). Alt text preserved; count alt-text coverage pre/post.
- [ ] Categories and tags: migrate all (68 categories registered, 51 with posts, per the 2026-09-02 REST recount and Yoast sitemap; the 52 in earlier drafts and in the audit register's count table was an error, 51 is correct per the 2026-09-02 ground truth; review all 68; 1,004 tags); fix the double-encoded names ("Charity & Donations", "Policies & Procedures"); no merges unless AISV has signed off a consolidation map, and every merged slug gets a redirect.
- [ ] Authors: apply the client's per-person decisions (keep byline / reassign / retire). Guest and contributor byline mechanism in place; correct attribution on posts found during QA where body text and author data disagree (capped; the rest goes to AISV as a Phase 04 list).
- [ ] Yoast meta: titles, descriptions, canonical, noindex flags per post carried over (Route A: native; Route B: mapped). Verify on a sample of 20 posts across years.
- [ ] Redirect map imported into Redirection: Danica Paddock's root bio URL, Alicia Wimmer's `/about-us/legal-team/alicia-megrath/` bio URL and her `aliciam` author archive (both to the canonical `alicia-wimmer` targets; confirm on the exported site which of the two bio URLs resolves), any retired orphan, any changed category slug, and every URL in the redirect table in `.logs/planning/site-architecture.md`. 301s only. Test each with `curl -sI`.
- [ ] Search & Filter Pro configured on the blog index: keyword search plus category filter, author on cards, pagination.
- [ ] The empty `article-type` taxonomy retired: unregistered and absent from the sitemap index.
- [ ] Verification counts, live vs staging: published posts, media items, featured-image coverage, categories, tags, users with posts, author archives, alt-text coverage. Record the table in `.logs/diary.md`. Any delta explained (the freeze delta is expected and re-imported at launch).
- [ ] Crawl staging with a link checker; zero internal 404s.

**Exit gate:** counts match live within the documented freeze delta; redirects tested; link
check clean; filtering works; Rian sign-off. **Owner:** Rian (Route A restore, author
decisions); Adi (verification).

### Phase 5: Entity, forms, CTAs, tracking, performance

**Goal:** the site is findable as the right entity, converts through instrumented paths, and
carries the tracking stack, with performance measured.

**Inputs:** `.logs/planning/schema-entity-plan.md`, `.logs/planning/tracking-conversion.md`,
the tag inventory from Phase 0, GTM access, the canonical name and address, the assessment
name, the Pipedrive transport answer.

**Tasks**

Entity and schema (all via `bw-ai-schema-pro` configuration)
- [ ] LegalService entity: canonical name, address, phone 425-250-0205, `areaServed` Washington, Oregon, Colorado (Washington first), `sameAs` LinkedIn and YouTube only, Brand Kit logo.
- [ ] Team post type mapped in the plugin settings; Person entities for the 8 confirmed team members via the team-survey workflow (job title, firm association, LinkedIn); Nicole Farahdel's Person waits for real details.
- [ ] Author-to-bio binding so each post author resolves to the team member's bio page, not a bare archive; guest contributors credited as their own Person.
- [ ] Service schema on the Practice Areas content; Article schema on posts; FAQPage from the FAQ block on Home. FAQ markup is for AI answer engines and buyers, not rich snippets (Google stopped showing FAQ rich results in Search on 2026-05-07).
- [ ] Disable Yoast's Organization/WebSite graph output so only one entity name is emitted; align site title, footer copyright, and form consent text to the same string.
- [ ] Validate every template type with Google's Rich Results Test and the Schema.org validator; zero errors; record the results.

Forms and CTAs
- [ ] Contact form rebuilt in Gravity Forms: name, email, company, phone, what they need (light qualification), message, hidden source and UTM fields, the attorney-client privilege disclaimer carried over. Routed to Pipedrive per the transport AISV names, with the source attached. Notifications to the address the client names.
- [ ] Newsletter form migrated and feeding the same list as before (platform to be confirmed; Constant Contact inferred from the live HTML).
- [ ] The assessment page: Typeform embed `QIIINVqG` with hidden fields passing UTM and source from the page URL; the page is the destination of every transitional CTA (no more `#bha-form` anchor as the path in).
- [ ] Paired CTA pattern deployed site-wide: header, page ends, end of every post.

Tracking
- [ ] GTM container `GTM-TGTVD37` snippet on every page; GA4 `G-PTGQ1K61M6`, Hotjar `3664447`, RB2B, Meta pixel, and Usercentrics via Termageddon verified firing on staging with GTM preview and each vendor's debugger. Flag anything found broken (Hotjar) to Rian for a scope call.
- [ ] GTM events: direct CTA click, transitional CTA click, contact form submit, newsletter submit, assessment start (Typeform embed event where exposed, else the CTA click), tracked separately for the direct and transitional paths. Names and parameters per `.logs/planning/tracking-conversion.md`.

Performance
- [ ] Image optimization across migrated media (WebP where supported, sized variants); lazy-load configured natively (Rocket Lazy Load is not carried over); conditional loading of Gravity Forms and Search & Filter Pro assets confirmed.
- [ ] Core Web Vitals measured on staging for Home, Practice Areas, and one post, same method as the Phase 0 baseline; before/after table written for the client report. Report numbers, never a promised score.

**Exit gate:** structured data validates with zero errors on every template; every tag and
event confirmed firing (or GTM access is the recorded blocker); test submissions reach
Pipedrive with a source; CWV table complete. **Owner:** Adi (build); Rian (schema review and
gate).

### Phase 6: Review, launch, training, support

**Goal:** the client has reviewed, the site is live on PlusROI hosting behind Cloudflare,
tracking is confirmed, the client is trained, and the support window is open.

**Inputs:** the launch checklist (Definition of done), Cloudflare super-admin access,
registrar or vendor cooperation, the freeze delta.

**Tasks**
- [ ] Client review on staging: first `srv-gw id-site-set-password --host equinoxbusinesslaw.demoing.info` (owner; prompted, never in argv) to give this site its own guest password, then share that password with Alicia Wimmer, never the server default. (Alternative: `srv-gw id-user-create` accounts for Alicia and Michelle, granted with `srv-gw id-user-grant`, with the site set `srv-gw id-site-set --host equinoxbusinesslaw.demoing.info --account-required true`.) Collect revisions; apply in-scope revisions; log anything out of scope as a change request.
- [ ] Final content delta: re-export anything published on live after the Phase 4 export; import; re-count.
- [ ] Snapshot the database before launch.
- [ ] Pre-launch checklist run (Definition of done); Rian signs it in `.logs/diary.md`.
- [ ] Cloudflare zone check: compare the imported zone against a fresh `dig` of every record type at the current provider, especially MX, TXT (SPF, DKIM, DMARC), and Microsoft 365 autodiscover/CNAME records, before nameservers change. Change nameservers outside business hours; verify mail flow after.
- [ ] Rian sets a unique password on `support` in wp-admin (never in argv or chat), or replaces it with a client-owned administrator account and deletes `support` (reassigning its content); confirm no other account still holds a template or live-site password.
- [ ] Production hostname: add `equinoxbusinesslaw.com` to the project with `srv-gw add-dns --project equinoxbusinesslaw --domain equinoxbusinesslaw.com` (owner runs it; www redirect per the gateway's option for apex domains, documented as `--with-www` on `create-project`; whether `add-dns` accepts it is to be confirmed by Rian), which writes the Caddy site config, never edit `/srv/caddy/` by hand; then mark the host public (Pattern E: `srv-gw id-gate --site equinoxbusinesslaw.com --mode public`), and run `srv-gw wp --project equinoxbusinesslaw -- search-replace` from the staging URL to the live URL. To be confirmed by Rian: how the gateway's DNS step behaves when the zone lives in the client's Cloudflare account rather than rian's (`srv-gw add-dns` creates records in rian's zones); the DNS record itself may need to be set by hand as super-admin, pointed at this server, with the Caddy site config still created through the gateway.
- [ ] Post-launch: crawl live for 404s; test every redirect on live; submit the sitemap in Search Console; confirm robots allows crawling (and the AI crawlers AISV wants); confirm GA4 realtime, Hotjar recordings, RB2B, Meta pixel, and consent banner on live; confirm a test lead reaches Pipedrive; confirm the REST API responds unauthenticated on live for OpenForge.
- [ ] Keep staging gated; decide with Rian whether staging stays as a permanent staging copy or is retired.
- [ ] Training: one 1-hour recorded session on content management, publishing, and the reusable patterns. File the recording link in `notes/`.
- [ ] Support: the 30-day post-launch window opens at material completion; record the date in `.logs/handoff.md`. Ask the client for the post-launch plan decision.
- [ ] Hand AISV the OpenForge user (least role that can draft, Author or Editor, with an Application Password created by the client or Rian and never pasted in chat), the Phase 04 attribution list, and the flagged inconsistencies.

**Exit gate:** live on the production domain, checklist signed, tracking confirmed
post-launch, training delivered, support window dated. **Owner:** Rian.

## Week mapping

The proposal's six-week plan, mapped to phases. The clock starts when Phase 0's inputs are
in hand (access, brand assets, licence status); Rian promised the mockup within a week of
receiving the design inputs (2026-08-24 email), and the inputs arrived 2026-08-27. The held
start date was 2026-08-17 with launch in late September 2026; nothing was built or mocked up
as of 2026-09-02, so the calendar is to be re-baselined and set by Rian, and the client told
the revised window explicitly.

| Proposal week | Phases | Dates |
|---|---|---|
| Week 1: discovery, access, staging, sitemap and redirect map confirmed, AISV requirements aligned, design mockup | Phase 0, Phase 1 | to be set by Rian |
| Week 2: design system and core templates | Phase 2 (may begin during Phase 1 after the direction check) | to be set by Rian |
| Weeks 3 to 4: page build, drafted content, full migration | Phase 3, Phase 4 | to be set by Rian |
| Week 5: structured data, forms, CTAs, tracking, filtering, performance | Phase 5 | to be set by Rian |
| Week 6: review, revisions, launch checklist, training, launch | Phase 6 | to be set by Rian |

Phase 0 and Phase 1 overlap: the mockup can start as soon as the Brand Kit is in hand,
before access and licences are resolved. Phase 4 cannot start before the migration route is
decided and its access is in place. Any client-side hold is logged with its date in
`.logs/handoff.md` (so the timeline effect of client-side holds is on record when the calendar
is re-baselined).

## Gates

| Gate | Evidence required | Who signs |
|---|---|---|
| G0: Foundations complete | Access checklist with a status per item; brand assets in `notes/source/`; licence status for Gravity Forms, Search & Filter Pro, Termageddon; plugin set installed; CWV baseline, tag inventory, sitemap exports recorded; freeze protocol agreed with AISV; migration route recorded | Rian |
| G1: Design approved (client gate) | Written client approval by email, filed in `notes/client-correspondence.md`; the approved mockup filed under `notes/` | Alicia Wimmer or Michelle Bomberger (client); Rian records |
| G2: Pattern library complete | Editability check passed for every pattern as an Editor-role user; one `h1` per template; header/footer match the client decisions; entry in `.logs/diary.md` | Rian |
| G3: Pages built | Every target-sitemap URL resolves on staging; no Lorem Ipsum; DRAFT list in `.logs/handoff.md`; orphan recommendations sent | Rian |
| G4: Migration verified | Count table (posts, media, featured images, categories, tags, authors, alt text) live vs staging in `.logs/diary.md`; redirects tested; link check clean; filtering works | Rian |
| G5: Entity, conversion, tracking, performance | Validator results with zero errors per template; tag and event firing log; a test lead in Pipedrive with source; CWV before/after table | Rian |
| G6: Launch readiness | Definition of done fully checked and signed in `.logs/diary.md`; Cloudflare zone diff clean; client review revisions applied | Rian; client confirms go |
| G7: Project close | Post-launch tracking confirmation; training recording filed; support window dated; post-launch plan decision recorded | Rian |

## Database snapshot procedure

There is no sanctioned gateway dump command: `srv-gw wp --project equinoxbusinesslaw -- db
export` fails because the WordPress image lacks `mysqldump`, and `srv-gw db-query` is
read-only. Two paths exist; the primary one handles no credentials at all. In either path the
password never goes on the command line, on disk outside `.env`, in chat, or in a log.

Snapshot **before**: the theme/plugin swap (Phase 0 and the Route A restore), the Beaver
Builder strip, any author reassignment, the taxonomy retirement, the launch. Name each file
with the date and the reason (`pre-restore`, `pre-theme-swap`, `pre-bb-strip`,
`pre-author-reassign`, `pre-taxonomy-retire`, `pre-launch`).

Once, create the backups folder at the workspace root (outside `wp-content/`, so it is never
web-served), group-writable, under `sg` per `agents.md` so setgid survives:

```
sg equinoxbusinesslaw-dev -c 'mkdir -p /srv/apps/equinoxbusinesslaw/backups && chmod 2770 /srv/apps/equinoxbusinesslaw/backups'
```

1. **Primary (any teammate, no credentials handled).** UpdraftPlus is installed and active on
   staging. In wp-admin, Settings > UpdraftPlus > Backup Now, tick "Database" only. The
   archive lands in `wp-content/updraft/` (plugin-protected). Copy it to
   `backups/wp_equinoxbusinesslaw-<date>-REASON.sql.gz` (rename the UpdraftPlus `-db.gz`
   to that form), then delete the copy in `wp-content/updraft/` so the database does not
   sit inside the instance. Verify with `gzip -t backups/wp_equinoxbusinesslaw-*-REASON.sql.gz`.

2. **Fallback (owner-run) when wp-admin is unusable.** Host `mysqldump` (`/usr/bin/mysqldump`)
   against the shared MariaDB, with the credentials read from the project `.env` through
   process substitution so nothing is written to disk. Run from the workspace root,
   `/srv/apps/equinoxbusinesslaw/`:

   ```
   mysqldump --defaults-extra-file=<(printf '[client]\nhost=127.0.0.1\nport=3306\n'; sed -n 's/^DB_USER=/user=/p; s/^DB_PASSWORD=/password=/p' .env) \
     --single-transaction --quick --routines --triggers wp_equinoxbusinesslaw \
     | gzip > backups/wp_equinoxbusinesslaw-`date +%F-%H%M`-REASON.sql.gz
   gzip -t backups/wp_equinoxbusinesslaw-*-REASON.sql.gz && ls -la backups/
   ```

   If MariaDB refuses the user from 127.0.0.1, use `host=172.17.0.1` instead (the address
   the container connects through). Which host the grant covers is to be confirmed by Rian.

3. Log the snapshot filename and reason in `.logs/diary.md`.

**Restore is Rian-only.** A restore (`mysql --defaults-extra-file=<(...) wp_equinoxbusinesslaw
< file` after `gunzip`, or UpdraftPlus's own restore) is a direct write to the shared database
outside the gateway's audit log, so only Rian runs it, and only after confirming which
snapshot. The `backups/` folder is runtime state, never committed anywhere and never inside
`wp-content/`.

## Risks

| Risk | Mitigation |
|---|---|
| Page rebuild scope grows: 32 URLs in the page sitemap, but Home and Practice Areas are long, and the brand-story homepage is about 12 sections needing 4 patterns the live site lacks. | Page count confirmed against the Phase 0 sitemap export; the four new patterns are built once in Phase 2; orphans are retired rather than rebuilt; anything beyond the sitemap is a change request. |
| A licence has lapsed or cannot transfer (Gravity Forms, Search & Filter Pro, Termageddon). Each is load-bearing: lead capture, blog filtering, cookie consent. | Confirm in Phase 0. If Search & Filter Pro lapses, Rian decides a replacement before Phase 4; if Termageddon lapses, consent is re-attached from a client-owned subscription. Never buy on the client's behalf. |
| Author cleanup balloons if the archive is messier than the sampled post (body credits a guest, data credits Michelle). | Scope is capped: the per-person decision list, a guest-byline mechanism, and corrections on posts found during Phase 4 QA; the rest goes to AISV as a Phase 04 list. |
| The assessment does not carry over cleanly: Typeform account ownership, its Pipedrive and notification integrations, and completion tracking are unknown. | Re-embed the same widget id; confirm ownership and routing with AISV in Phase 0; fire the GTM event on the embed's submit where exposed, else on the CTA click. |
| Content published on live during the build is lost at cutover (AISV publishes weekly; the count already moved from 510 to 513). | Freeze protocol agreed with AISV in Phase 0; re-count at export and at launch; delta re-import in Phase 6. |
| Access never fully arrives (Cloudflare, registrar, live admin, hosting) because it routes through the client's current website/email vendor. | Chase with the exact steps already written (2026-08-18 email); choose Route B if admin access never comes; set a date after which the calendar is formally re-baselined. |
| Kadence lock-in (disclosed to the client): page layouts carry Kadence-specific markup. | Accepted trade-off. Posts stay standard content; the child theme stays minimal; no custom PHP templates for what a pattern can express. |
| Performance weight retained from Gravity Forms (the heaviest single asset on the live site) and Search & Filter Pro. | Deliberately kept. Conditional asset loading so their CSS/JS load only where used; report measured before/after numbers, never a promised score. |
| GTM access does not arrive; CTA and form events cannot be configured and tags cannot be verified in preview. | Escalate in Phase 0 with the exact steps; without it, re-paste the container snippet and verify with vendor debuggers only; record it as a launch-checklist exception signed by Rian. |
| The two-name entity problem persists after launch (Yoast emits one name, the schema plugin another). | Canonical name confirmed; site title, Yoast, footer, form consent text, and `bw-ai-schema-pro` set to the same string; Yoast's Organization/WebSite output disabled; validated in Phase 5. |
| DNS move disrupts email (the client's stated worry, 2026-08-18). | Zone diff before nameserver change (MX, SPF, DKIM, DMARC, Microsoft 365 records); change outside business hours; verify mail after. |
| Timeline slip: start 2026-08-17, nothing built by 2026-09-02, mockup due. | Mockup first; re-baseline the six-week plan from mockup approval; tell the client the revised launch window explicitly. |
| Amounts or commercial terms leak into the project from the proposal, correspondence, or the AISV deck. | Source documents are redacted before filing under `notes/`; before every checkpoint, grep the workspace for currency symbols and commercial-term vocabulary. |
| The staging gate is opened for AISV tooling and not closed. | Prefer post-launch testing; if opened, the same person re-gates in the same session and logs it. |

## Definition of done

The site is done when every item below is checked and the list is signed in `.logs/diary.md`.

- [ ] Every URL in the target sitemap (`.logs/planning/site-architecture.md`) resolves on the production domain with one `h1`, breadcrumbs, and a unique title and meta description.
- [ ] 513 published posts (plus the freeze delta) live with categories, tags, dates, featured images, slugs, and Yoast meta intact; counts match the Phase 4 table.
- [ ] Every redirect in the map returns 301 to a resolving target on live; a crawl of the live site shows zero internal 404s.
- [ ] The empty `article-type` taxonomy is gone from the sitemap index; the XML sitemap is clean and submitted in Search Console; thin pages are noindex; robots allows crawling.
- [ ] Structured data validates with zero errors on Home, a practice-area page, a post, a bio, the contact page, and the assessment page; one entity name everywhere; LegalService with address, phone, `areaServed` WA/OR/CO, LinkedIn and YouTube; Person entities bound to the 8 confirmed bios; Article and author schema on posts; FAQPage on Home.
- [ ] Contact form and newsletter form deliver test submissions with source attached to Pipedrive and the newsletter list; the privilege disclaimer is present.
- [ ] The assessment page carries the Typeform embed with UTM hidden fields and is the destination of every transitional CTA; the paired CTAs appear in the header, page ends, and every post end.
- [ ] GTM `GTM-TGTVD37`, GA4 `G-PTGQ1K61M6`, Hotjar `3664447`, RB2B, and Usercentrics consent fire on live; the Meta pixel fires if the GTM container audit found one and AISV retained it (`.logs/planning/tracking-conversion.md`); the direct and transitional CTA events and form events appear in GA4; data flow confirmed post-launch before close.
- [ ] Core Web Vitals before/after table for Home, a practice-area page, and a post delivered to the client.
- [ ] No mention of Twitter, Facebook, DC, VA, EO Portland, Women in Finance, or the anniversary logo anywhere on the site; states read WA, OR, CO; no stock photos of people; team photos at most two site-wide and none on Home.
- [ ] 9 team bios live (Nicole Farahdel's placeholder status known to the client); author archives resolve to bio pages; the author decision list is fully applied.
- [ ] Blog index filters by keyword and category; author shown on cards.
- [ ] The REST API responds unauthenticated on live; AISV has an OpenForge user with the least drafting role.
- [ ] DNS on Cloudflare with mail records verified; production host public (no id-auth gate); staging still gated.
- [ ] No account on the production site carries the template's shared password; `support` is unique or gone.
- [ ] Recorded 1-hour training delivered and filed; the 30-day support window date recorded; the post-launch plan decision recorded.
- [ ] `srv-gw security-audit` run after launch with no new findings for this project; the workspace grepped for currency symbols and commercial terms with zero hits.

## Build notes captured during design (2026-09-04)

- **The team count on the home page is generated, never typed.** The value appears in the credential bar
  in the value-proposition section. If the team is registered as a custom post type — which
  `bw-ai-schema-pro` already requires for Person schema (`.logs/planning/schema-entity-plan.md`) — the
  number is a published-count query and cannot go stale when someone joins or leaves. Raised by Adi while
  designing the section; recorded here so it is not typed in as a literal during the build.
- **The services accordion must render its panels server-side.** Google indexes accordion content only
  when it is in the HTML on page load, and AI answer engines read only the served HTML. The mockups use
  native `<details>`/`<summary>` with no JavaScript for that reason. Whatever accordion block the build
  uses, check it does not inject panel content on expand — this section is the service list the whole AI
  search strategy depends on being readable.
