# leaguelaw — diary

> Session-by-session log: date, what changed, what was verified. Append-only,
> newest first. This is *state*, not summaries — no generated codebase
> overviews (v8 auto-generated-context law).

---

## 2026-08-20 — Rian + Claude — Review of the prototype day; rulings recorded

**Changed**
- `.logs/handoff.md`: new top entry — pause lifted, direction phase reframed
  (direction confirmation before any mockup, anchored on the client's written
  input; replica reclassified as internal measurement artifact; examples
  shortlist is the next client-facing step).
- `agents.md`: three new rules (design-direction.md anchors all design work;
  an approach pivot is a check-in, not a judgment call; direction-before-mockup
  phase discipline). Also fixed two stale facts (schema maps to `lawyers`, not
  `staff`; `testimonials` is registered again, not orphaned).
- `prototype.md`: "Process ruling — 2026-08-20 (Rian)" section + two learnings
  entries superseding the replica-first doctrine for client-facing work.

**Verified**
- Nothing in the served prototype folder was changed or removed; all of Adi's
  artifacts and version history remain exactly as he left them.

**Not done**
- No prototype or design work. The next working session starts from the new
  handoff entry (examples shortlist first).

## 2026-08-10 (DONE) — Claude — Blocks converted, DB cleaned, testimonials restored

**Changed**
- Registered `testimonials` CPT in kadence-child — all 10 rows returned intact,
  no repopulation needed (the Total theme had merely been registering the type).
- Converted **126 ACF blocks across 45 items** to core blocks. Forms became real
  `[gravityform]` shortcodes; testimonial and LaW Facts sliders became quotes and
  image+text; hero slideshow became a gallery.
- Database cleanup: ~18,000 rows. Orphaned postmeta 6,522; rank_math 5,512;
  cmsms_ 3,125; molongui 1,541; wpex_ 906; _wpb_ 99; _easy_image_gallery 56;
  ~170 dead options; `mt_pp`/`law_fact`/`template` post types; dead `author` and
  `post_series` taxonomies; orphaned term relationships; stale theme mods;
  transients. Modernised the legacy `core-embed/youtube` block.
- New `.logs/planning/design-direction.md` capturing the client's design brief.

**Verified**
- **0 items still contain `wp:acf/`.**
- Text-in-equals-text-out passed on every item, using a whitelist of
  content-bearing fields so config values do not produce false positives.
- 46/47 pages render with content; the 47th is the template-driven blog index.
- Post-cleanup integrity: 13 lawyers · 10 testimonials · 47 pages · 272 published
  + 152 draft posts · 9 users · 3,984 GF entries · 1,427 attachments.
- Preserved deliberately: 2 guest authors **and their meta**, and
  `rg_gforms_enable_akismet` (a Gravity Forms option an unanchored `%akismet%`
  pattern would have deleted).

**Gotchas worth remembering**
- `wp eval-file` runs in **function scope**, so a top-level `$var` is not a
  global — a logging array written via `global $log` came back empty even though
  the work completed. Use direct output, not a collected log.
- `parse_blocks`/`serialize_block`: emptying `innerBlocks` without rebuilding
  `innerContent` emits warnings and corrupts output. 57 of the 126 ACF blocks
  were nested, so the converter rebuilds `innerContent`, expanding each null
  placeholder to match how many blocks its child became.
- Environment variables do not cross `srv-gw wp` into the container, so a
  dry-run/apply flag has to live in the script.

---

## 2026-08-10 (DONE) — Claude — Stack swap + lawyers migration executed

**Changed**
- Installed Kadence 1.5.1 + built `kadence-child` (style.css, functions.php with
  ACF Local JSON filters, `includes/post-types.php`, `acf-json/`).
- Registered the `lawyers` CPT; created `group_lawyer_details.json` (one `email`
  field) as Local JSON.
- Migrated 13 `staff` rows to `lawyers` via **direct `$wpdb` update**, not
  `wp_update_post()`, so `post_name` could not be regenerated.
- Extracted emails from the old ACF Link values; dropped `position`/`phone` and
  Total equivalents (66 meta rows); removed the `staff_category` taxonomy
  (3 terms, 12 relationships) and 21 stale primary-term meta rows.
- Activated kadence-blocks / -pro / kadence-pro / bw-dev / bw-ai-schema-pro;
  **removed 14 plugins**; deleted the Total theme and two default themes.
- Deleted all 18 legacy ACF field groups (84 fields, 20 orphan rows) after
  exporting them to `.archive/old-acf-field-groups/old-acf-groups.json`.
- Archived removed plugins, the Total theme, and the old bw-dev under
  `.archive/old-plugins/`.

**Verified**
- 13 lawyers, **0 problems**: every one has a featured image, every permalink is
  still `/lawyers/<slug>/`, 12 clean emails (Joji resolved to `jkawaguchi@`; the
  three malformed `mailto: ` values and the two label-instead-of-address records
  all extracted correctly). "IS IT YOU?" has no email, as expected.
- Data intact after the whole sequence: 272 published + 152 draft posts, 47
  pages, 9 users, **3,984 GF entries**, 1,427 attachments, 0 rows left as `staff`.
- `group_lawyer_details` still resolves from Local JSON after the DB groups were
  deleted — confirming the field survives on disk, not in the database.
- Site returns the expected id-auth 302 to `auth.bowden.works`. No PHP errors.
- All working scripts removed from the web root after each run.

**Found and deliberately not acted on**
- 352 orphaned postmeta rows across 88 deleted post IDs — pre-existing, unrelated.
- Orphaned post types now that their plugins are gone: `testimonials` (10),
  `mt_pp` (8), `guest_author` (2), `law_fact` (1).

**Gotcha worth remembering**
- `staff_category` was registered by the Total theme too, so after the theme swap
  `wp_delete_object_term_relationships()` fatals — the taxonomy API returns
  `WP_Error` for an unregistered taxonomy. Cleaned up with direct SQL instead.

---

## 2026-08-10 (current, later) — Rian + Claude — Migration questions all resolved

**Decided by Rian**
- Joji Kawaguchi: `jkawaguchi@leaguelaw.com` (name change confirmed).
- Janice Williams is not a lawyer — no record; she runs the blog.
- Drop `position`, `phone`, and the `staff_category` taxonomy. The `lawyers` CPT
  keeps a single field: `email`.
- "IS IT YOU?" migrates as-is; becomes a CTA during design, not now.

**Verified — author attribution has a real gap**
- **103 of 272 published posts (38%) are credited to Janice**, a non-lawyer.
- **Molongui adds no correction**: `_molongui_main_author` matches `post_author`
  on every published post (user-6 ×103, user-4 ×96, user-15 ×59, user-9 ×9,
  user-10 ×5). Removing Molongui loses no authorship data.
- **Zero of the 103 posts carry an in-content byline.**
- The posts cluster hard by topic — Estate Law 73, Wills and Estates 70, Estate
  Planning 68, Estate Disputes 38, Personal Injury 31, everything else ≤5 — so
  re-attribution is a by-category question, not a per-article list.

**Changed**
- `lawyers-cpt-migration.md`: fields cut to `email` only; taxonomy section now
  "dropped"; Joji, Janice and "IS IT YOU?" resolved; execution order updated with
  meta cleanup and Molongui removal.
- New `.memory/author-attribution.md` recording the attribution gap, the evidence
  that no hidden data exists, and the cheap path to fixing it.

---

## 2026-08-10 (current) — Rian + Claude — `staff` → `lawyers` migration specified

**Decided by Rian**
- New `lawyers` post type with position, phone, email; migrate `staff` into it.
- Keep `redirection`. Remove Metronet provided lawyer photos survive.
- Migrate content only — no layout preservation.

**Changed**
- New `.logs/planning/lawyers-cpt-migration.md` (full spec).
- Build plan updated: `redirection` moved to Keep; Metronet marked
  cross-checked-safe; the Total-theme section now points at the migration spec.

**Verified**
- **URLs are safe.** `staff_slug` theme mod = `lawyers`, so `/lawyers/<name>/`
  is reproduced exactly by registering the CPT as `lawyers` with
  `rewrite.slug = 'lawyers'` and migrating rows in place. No redirects needed.
- **Trap: the page "Our Lawyers" (14661) has slug `lawyers`**, identical to the
  CPT rewrite slug. Works only because `has_archive => false`. Must stay false.
- **Trap: the slug lives in `theme_mods_Total`** and dies with the theme — the
  new registration must hardcode it.
- **Fields already exist on all 13**: `wpex_staff_position` (clean text),
  `email` and `phone` — but the latter two are **ACF Link fields** storing
  serialized `title`/`url`/`target`.
- **Data-quality issues found**: 6 of 13 phone `url` values are broken
  (`http://250-888-0002`, `http://2508880002`); 3 email urls have a stray space
  after `mailto:`; 2 records put a label ("Email Rob Graham") in `title` rather
  than an address; Joji Kawaguchi's ACF email (`jkawaguchi@`) conflicts with the
  older Total value (`jjordan@`); every phone is the firm's main line.
- **All 13 already have `_thumbnail_id`** — the header-image→featured-image step
  is a no-op. The only header-image setting is the *global* options-page field
  `lawyer_header_image`.
- **Metronet cross-check**: only 4 of 8 `mt_pp` records hold an image. Darren's
  (17175) is the *same attachment* as his lawyer featured image; Andrew
  Broadley's lawyer photo (21502) is newer than the mt_pp one (15825); Georgia's
  mt_pp has no image. **No lawyer loses a photo.** Images not represented on any
  lawyer record: Janice Williams (16894) and "Rob Anderson" (17245).
- **Janice Williams has 103 published posts and a profile picture but no lawyer
  record** — flagged for a decision.
- `staff_category` in use on 12 records (Lawyer ×11, Principal Lawyer ×1,
  Articling Student ×0) — duplicates `position`; recommended for removal.

---

## 2026-08-10 (latest) — Rian + Claude — Stack cleanup specified, snapshot taken

**Decided by Rian**
- Keep all drafts (424 posts total).
- Target stack: Kadence + ACF + Yoast + Gravity Forms; remove everything else.
  No template clone — clean start on the new theme, same database.
- ACF: keep the lawyer post type and its fields; strip all block field groups and
  the settings groups; replace ACF block instances with rebuild placeholders.
- Drop `law_fact`. Replace Molongui with `bw-ai-schema-pro`.

**Changed**
- DB snapshot taken: `.snapshots/leaguelaw-pre-theme-swap-20260810-2020.sql.gz`
  (7.6 MB, mode 640).
- Added §Stack cleanup to the build plan; rewrote Phase 0 in dependency order;
  added gate 2 (lawyers verified before Total is removed).
- New `agents.md` rule about Total owning the `staff` CPT, marked for deletion
  once the swap is verified.
- New `.memory/guest-authors.md` recording the deferred guest-author decision.

**Verified**
- **Total theme registers `staff` and `testimonials`**
  (`themes/Total/framework/classes/PostTypes/Staff.php`, `Testimonials.php`) —
  removing Total before re-registering orphans all 13 lawyers.
- `bw-dev` audited in full: registers `law_fact`; ACF Local JSON path
  (`bw-dev/backup/acf`) is **empty**; `assets/css/main.css` is **37 bytes**
  (sourcemap comment only); sidebar/widget/shortcode files are dead or stubs;
  debug helpers define unprefixed globals `dump()` / `register_cpt()`. **Nothing
  to rebuild.**
- ACF: 18 field groups. `Lawyers Settings` → `post_type == staff` (keep);
  `Lawyer Settings` → options page with the single field `lawyer_header_image`.
- ACF block usage across publish+draft: Icon Text 44, Form 9, Button 7,
  Service 2, Lawyer Grid 2, Hero 1, Image & Slider 1; **Post Grid, Two Column
  Section and Local Bar have zero instances**.
- Guest authors: Grant Hatley (20173), Cedar Dodd (20174), both 2022-10-31.
- Current plugin set re-checked after the fresh pull: 18 active + `db-error.php`
  dropin. The pull removed the previously-inactive plugins and added
  `mcp-adapter` 0.5.0.
- Snapshot integrity: `gzip -t` passes, 126 `CREATE TABLE`, and
  `users`/`posts`/`postmeta`/`gf_entry` all present.

**Substrate note**
- `srv-gw wp -- db export` fails — no `mysqldump` in the WordPress container.
  Worked around with host `mysqldump` + `--defaults-extra-file`. Logged to
  `.logs/v8-feedback.md`.

---

## 2026-08-10 (later) — Rian + Claude — Both open decisions answered

**Decided by Rian**
- **Build environment:** keep this database and swap the theme in place. The
  fresh pull already in `wp-content/` is the build, not a reference copy; the
  live site is the visual "before". Content gets stripped to plain blocks so
  pages, posts, users, forms and entries all survive while the presentation is
  rebuilt in Kadence patterns.
- **AI add-on:** delivered by configuring `bw-ai-schema-pro`, nothing custom
  built. Prerequisite is a mapped team post type; the existing `staff` CPT
  covers it. Client acceptance still outstanding.

**Verified — content conversion is much smaller than assumed**
- Measured the fresh pull: **0 WPBakery/`[vc_*]` content, 0 proprietary theme
  blocks**. 46/47 pages and 171/272 published posts already core Gutenberg;
  210 items with core paragraph, 186 heading, 180 image; 0 group/cover/button
  wrappers.
- Real strip-pass surface is ~70 items: 43 ACF blocks, 32 with shortcodes,
  9 raw HTML blocks, 9 columns, 7 spacers.
- Post statuses: **272 published, 152 draft**, 2 pending, 1 private — the
  proposal's "427 articles" counts every record.
- Gravity Forms holds **3,929 entries** across 8 forms; 9 users in
  `wp_eopoktulnc_users`. Both are reasons the database must be kept, not rebuilt.
- Confirmed `bw-ai-schema-pro` reads its team post type from a setting rather
  than hardcoding one, and already lists `staff` among its default team slug
  patterns. It also ships a team survey workflow matching the proposal's
  "research the team's credentials, client finalizes" deliverable.

**Changed**
- Updated `brief.md`, `.logs/planning/build-plan.md` (new §Content conversion
  with the measurements, revised Phase 0, new Phase 3b for schema), `agents.md`
  (three new rules covering the database, the snapshot/verification discipline,
  and schema-is-a-plugin), and a new `handoff.md` entry unblocking Adi.

---

## 2026-08-10 — Rian + Claude

**Changed**
- Granted `adi` access to the project (`srv-gw grant-access`); now a member
  alongside rian and rob, and granted on `leaguelaw.demoing.info`.
- Scaffolded the v8 workspace (`/srv/projects/standards/new-workspace.sh`).
- Wrote `agents.md`, `brief.md`, `.logs/planning/build-plan.md`, and the first
  `.logs/handoff.md` entry.
- Old project `CLAUDE.md` merged into `agents.md` and moved to
  `.archive/CLAUDE.md.pre-v8`; `CLAUDE.md` is now a symlink to `agents.md`.
- Removed the scaffolder's empty `main/` — the instance here is `wp-content/`,
  which the gateway bind-mounts at a fixed path. Recorded as a declared override
  in `agents.md`.
- Removed all pricing from `notes/Proposal (website) @ League Law.md` at Rian's
  request.

**Verified**
- `adi` present in `.project.json` members and in the `leaguelaw-dev` group.
- `CLAUDE.md -> agents.md` symlink resolves.
- Site inspection against production and the local clone, used for the proposal:
  427 published posts back to 2014-07; 47 pages; 13 staff entries; 10
  testimonials; 1,427 media attachments; Total theme 4.8.4 (PHP compatibility
  warnings on `ResizeImage::__wakeup()`); ~49 script tags on the homepage;
  production `LegalService` schema still carries the old Wilson St address and
  a personal-injury-only description; no Article or Person schema on the
  homepage, lawyers index, a bio page, or a post.

**Not done**
- No build work started. Blocked on two decisions recorded in `handoff.md`:
  where the rebuild gets built, and whether the AI Search Optimization add-on
  is in scope.

**Incident — files missing from `notes/`, cause not established**
- Six files present in `notes/` at the start of the session (five reference
  proposals from other clients, plus `League Law's next phase - time for a new
  website.eml`, the client email thread) were absent from the directory when the
  workspace was verified at the end of it.
- The five reference proposals were **restored** from byte-identical copies in
  `/srv/apps/equinoxbusinesslaw/Notes/` (same sizes and mtimes), then re-grouped
  to `leaguelaw-dev`.
- **The `.eml` was not recoverable** — no copy exists anywhere under `/srv`,
  `/home/rian`, or `/tmp`. Its contents were read earlier in the session and the
  substance is captured in `brief.md`; the original is still in Rian's Gmail
  (delivered to rianbowden@gmail.com and rian@plusroi.com, subject "Re: League
  Law's next phase - time for a new website", from Rob Cooper, 2026-08-04).
- **Cause not established.** `new-workspace.sh` contains no `rm`/`mv` and is
  provably create-only; the logging hooks delete only `*.jsonl` session logs
  under the log dir and `claude-session-*` in `/tmp`. Nothing run this session
  has a delete path that reaches `notes/`. Recorded here rather than guessed at.

## 2026-08-20 00:42 — adi

**Changed** (4 files, detected via mtime):
- `prototype.md`
- `prototyping/wireframe-asis-v1.html`
- `wp-content/prototype/index.html`
- `wp-content/prototype/home.html`

## 2026-08-21 04:32 — adi

**Changed** (39 files, detected via mtime):
- `prototype.md`
- `adi-note.md`
- `agents.md`
- `prototyping/home-v2-footer-v1.html`
- `prototyping/cta-options-v1.html`
- `prototyping/hero-j-options-v1.html`
- `prototyping/hero-options-v1.html`
- `prototyping/header-options-v1.html`
- `prototyping/home-v2-no-git-v3.html`
- `prototyping/home-v9-minimizable-form.html`
- `prototyping/home-v5-megamenu.html`
- `prototyping/home-replica-v3.html`
- `prototyping/wireframe-home-v2-midfi.html`
- `prototyping/header-f3-options-v1.html`
- `prototyping/header-f3d-options-v1.html`
- `prototyping/home-v2-footer-v2-h12.html`
- `prototyping/home-v7-hero-scrollpin.html`
- `prototyping/footer-options-v1.html`
- `prototyping/header-f-options-v1.html`
- `prototyping/footer-hive-options-v1.html`
- `prototyping/home-v4-newheader.html`
- `prototyping/button-options-v1.html`
- `prototyping/home-v8-stickyheader.html`
- `prototyping/home-v2-v4-ctaband.html`
- `prototyping/home-v2-v5-no-cstrip.html`
- `prototyping/home-v6-hero-j2.html`
- `wp-content/prototype/header-f.html`
- `wp-content/prototype/header-f3.html`
- `wp-content/prototype/index.html`
- `wp-content/prototype/header-f3d.html`
- `wp-content/prototype/button.html`
- `wp-content/prototype/header.html`
- `wp-content/prototype/home.html`
- `wp-content/prototype/footer-hive.html`
- `wp-content/prototype/footer.html`
- `wp-content/prototype/hero.html`
- `wp-content/prototype/home-v2.html`
- `wp-content/prototype/cta.html`
- `wp-content/prototype/hero-j.html`

## 2026-09-06 20:03 — adi

**Changed** (40 files, detected via mtime):
- `prototype.md`
- `image.png`
- `adi-note.md`
- `notes/designer-notes-pins-homepage.md`
- `notes/video-narration-homepage-v1-v6.md`
- `prototyping/home_v5-v1-hero-h1.html`
- `prototyping/home-v2-v22-faq.html`
- `prototyping/hero-inner-v3-a1-panels.html`
- `prototyping/injuries-index-v5.html`
- `prototyping/gen_inner_replica_hero.py`
- `prototyping/team-options-v2-dark-cards.html`
- `prototyping/band-options-v9-d3d-locations.html`
- `prototyping/cards-options-v1.html`
- `prototyping/areas-options-v8-m4-live-copy.html`
- `prototyping/injuries-index-v3.html`
- `prototyping/inner-service-v9-home_v1-footer.html`
- `prototyping/inner-service-v11-home_v1-header.html`
- `prototyping/team-index-options-v1.html`
- `prototyping/team-options-v10-careers-b7afa6.html`
- `prototyping/injuries_intro_body.html`
- `prototyping/team_menu.json`
- `prototyping/areas-options-v9-grey-grounds.html`
- `prototyping/gen_svcidx_options.py`
- `prototyping/careers-v1.html`
- `prototyping/home-v2-v16-areas-m4l-g1.html`
- `prototyping/band-options-v3-head-office.html`
- `prototyping/gen_lofi_12.py`
- `prototyping/lofi-home-v2-v5-static.html`
- `prototyping/prototype-index-before-hero-service.html`
- `prototyping/team-options-v5-mail-grey-no-overlay.html`
- `prototyping/service-index-options-v1.html`
- `prototyping/quotes-options-v7-qm-c.html`
- `prototyping/lofi-v2-v3-before-form-crosses.html`
- `prototyping/home-bold-welcome-reduced-hero.html`
- `prototyping/home-v2-v21-before-faq.html`
- `prototyping/inner-service-v12-mega-width.html`
- `prototyping/hero-service-v2-round3.html`
- `prototyping/gen_sidebar.py`
- `prototyping/claims-options-v1.html`
- `prototyping/quotes-options-v2-hexbadge.html`
