Read this page in ten minutes. It tells you what we build, what you must decide, and what a person must do by hand.
Status in one line. The PRD is at revision 8 after eight review rounds. The last automatic check reports 0 blockers and 21 major findings, verdict FIX-FIRST. Eight of the 21 ask us to split stories, and we decline them. Thirteen are new and still open. See section 8 before you decide.
What "go" means. If you say go, we run one more fix round on the 13 open findings. Then we convert the PRD, which turns it into otto's task list. otto builds the stories on a feature branch. Nothing reaches production until the release checklist in section 6 is complete. If you say no-go, nothing changes; stage 1 stays live.
We replace the fixed header menu with one menu that editors manage in WordPress. Stage 1 already shows the agreed design as fixed HTML files, which we call the bundle. Stage 2 renders the same HTML from one WordPress menu, item by item. A script, the parity check, compares the two outputs link by link, so Google sees no change. When the missing pages exist, editors un-hide menu items and the full design appears.
In production since 24 September 2026. Tag nav-2026-stage1-v1.1, accessibility hardened. Live links only.
The same design, rendered from one editable menu. Same links, same order, same landmarks as stage 1.
Frozen at ct-nav-full-design-2avs-yn35.pages.dev, tag nav-2026-full-design-v1. Editors reach it by un-hiding items.
Twenty-one stories. One commit each. otto, the build tool, runs them one at a time. The "depends on" column is the run order, not a plan for parallel work. A person does NAV-001 and the release steps. NAV-018 and NAV-020 run after the production switch, in a second conversion. The operator is the person who runs the release, Stevan or Phil.
| ID | Title | Executor | Depends on | Done when |
|---|---|---|---|---|
| NAV-001 | Human prerequisites.user.ini record, Safe SVG choice, Convert pause, hub row id | HUMAN | none | The release checklist file records each item with evidence. |
| NAV-002 | Admin prerequisites and the test runnercore edit walker, Description box, input-limit warning, PHP 7.2/8.3 lint | CODEX | none | The Menus screen shows the Description box and the lint exits 0. |
| NAV-003 | Tree builder and flush primitiveroles, hidden pruning, badges, mobile order | CODEX | NAV-002 | 73 items in, 52 visible out; tests pass on three PHP runtimes. |
| NAV-004 | Item markup, icons, SVG sanitiser | CODEX | NAV-003, NAV-014 | All 15 icons pass the sanitiser; tile markup equals the bundle. |
| NAV-005 | Per-item fields with guarded save | OPUS | NAV-003 | Each field round-trips; a save without the form marker writes nothing. |
| NAV-006 | Media picker for icons and images | OPUS | NAV-005, NAV-010, NAV-017 | An editor picks an icon, saves once, and the tile shows it. |
| NAV-007 | Wide panel markup (1200 px and up) | CODEX | NAV-004, NAV-014 | The parity check and a byte comparison against the bundle both pass for every tab. |
| NAV-008 | Medium panel markup (600 to 1199 px) | CODEX | NAV-004, NAV-014 | The same two checks pass against the bundle's medium blocks. |
| NAV-009 | Phone sheet markup (below 600 px) | CODEX | NAV-004, NAV-014 | The same two checks pass against the sheet; mobile order works. |
| NAV-010 | Render integration on stage 1fragment filter, composition, preview parameters | CODEX | NAV-007, 008, 009, 014, 016, 017 | Switch off: header identical to stage 1. Menu active: the parity check passes. |
| NAV-011 | Cache lifecycleone cached row, gated invalidation, preview bypass | CODEX | NAV-010 | A flush deletes the cached menu HTML. After a flush the first load rebuilds it and the second reuses it. Unrelated edits leave it in place. |
| NAV-012 | Section map for the body class | CODEX | NAV-011 | Sixteen URLs carry the expected section class. |
| NAV-013 | Cloudflare edge purge on every change | CODEX | NAV-011 | One purge per request that flushed; a label change shows on production within 60 seconds. |
| NAV-014 | Harness and baselinesfixtures, checker copy, states port, visual and Lighthouse tools | CODEX | NAV-002 | All fixtures committed; the baseline runs are quoted. |
| NAV-015 | Verification of the rendered menuscreenshots, link states, behaviour, Lighthouse | CODEX | NAV-011, 012, 014, 017, 021 | Screenshots within 1 % of stage 1; 33 link-colour probes pass; Google Lighthouse speed scores stay within tolerance. |
| NAV-016 | Seed the menu from Tools; activate and deactivate | OPUS | NAV-003, NAV-014 | Seed creates 73 items, 21 hidden; Activate and Deactivate set and clear the option. |
| NAV-017 | Icon import, full-design and launch presets | OPUS | NAV-016, NAV-004 | 15 icons imported once; the preset un-hides only targets that exist. |
| NAV-018 | Second critical-CSS set LATER | CODEX | NAV-019 | Seven pruned files hold no legacy menu selectors; first paint unchanged. |
| NAV-019 | Launch gate and release checklist | CODEX | NAV-006, 013, 015, 017, 021 | The gate script reports zero failures on local and staging; the release checklist is written. |
| NAV-020 | Legacy removal and menu export LATER | OPUS | NAV-019, NAV-018 | Legacy render path and CSS gone; three legacy menus exported, none deleted by code. |
| NAV-021 | Full-design stylesheet, printed only when needed | CODEX | NAV-010, 014, 017 | Nothing prints in launch mode; full-design regions within 1 % of the archive. |
Seven decisions. Each one names the recommended answer. Say "agree" or give another answer.
industries. Add that id to the row, or keep the plain hub link. The PRD gives no recommendation. Our view: add the id, a small page-builder edit./product and payplexo.com are not in the menu. The SEO audit accepts this loss. Recommended: accept..user.ini sets max_input_vars=3000 on production and staging. Verified 24 September 2026./home/phil/bin/wp.ctw_nav_v2 switch../deploy purge prod.| Risk | Mitigation |
|---|---|
| The rendered menu drifts from the bundle, so Google sees different links. | Every markup story must pass the parity check against the bundle, link by link. |
| Editors' changes stay invisible for hours because Cloudflare caches whole pages. | Every menu change deletes the cached HTML and sends one Cloudflare purge; a production probe proves it. |
| Unrelated edits, such as autosaves, purge the whole edge cache many times a day. | Only changes to the menu, its pages or its icons trigger a purge; unit tests cover the rest. |
| Code that runs on PHP 7.4 locally fails on PHP 7.2 in production. | Every PHP story runs its tests inside PHP 7.2 and PHP 8.3 containers. |
| A link to a private, missing or redirecting page ships in the menu. | Unpublished targets never render, and the launch gate probes every URL on each environment. |
Eight rounds ran. The checker, otto check, is an adversarial reviewer that reads the PRD as a builder would. FIX-FIRST means it wants changes before the build starts.
| Round | Result | Main change |
|---|---|---|
| 1 · otto check | 1 blocker, 35 major, 1 minor. FIX-FIRST. | Real frames cited; tooling moved into the theme repo; the old save handler unhooked. |
| SEO audit | Stage 2 "pass with fixes". | Tabs stay links; hidden items leave the HTML; the parity check becomes the acceptance test. |
| 2 · otto check | 2 blockers, 37 major. FIX-FIRST. | The PRD now builds on the stage-1 code with one filter line. |
| 3 · otto check | 1 blocker, 32 major. FIX-FIRST. | Symbol anchors; a new story for the full-design styles. |
| 4 · otto check | 1 blocker, 31 major, 1 minor. FIX-FIRST. | One base URL; a phone subline field; safer cache writes. |
| 5 · independent panel | 92 findings: 13 blocker, 42 major, 37 minor. 49 stood after refutation. | Extra editor fields so one menu reproduces the bundle; a race-free cache design. |
| 6 · otto check | 0 blockers, 28 major, 2 minor. FIX-FIRST. | Random cache tokens; a stable section key per tab. |
| 7 · otto check | 0 blockers, 23 major, 2 minor. FIX-FIRST. | Fifteen new findings fixed in revision 8, see below. |
| 8 · otto check (final) | 0 blockers, 21 major, 0 minor. FIX-FIRST. | Eight are repeated split requests, declined. Thirteen are new and open. |
Fifteen findings from round 7, all fixed. The largest: a helper function was called before its story defined it. A WordPress catch-all rule made every path look valid, so missing pages could slip through. A custom link pointed the section map at the wrong id. A plaque without its card had no desktop position. The cache could store stale content during a cold start. The purge could run before the final cache reset.
Thirteen new findings. Most are edge cases in caching and testing. Three matter for the decision. First, the checker doubts the new dependency record still has a race. Second, a tab with no overview loses its link on phones. Third, the release checklist deploys main, but the build lives on a feature branch, so it needs a merge step. None is a blocker. We recommend one more fix round before conversion.
Declined every round since round 2: splitting eight large stories. The task sizer splits stories at conversion time, and each story is one file or one tool set.
Prepared 24 September 2026 from docs/nav-audit-2026-09-22/prd-nav-2026.md, revision 8. Unlisted page: do not index.