# WB Listora 1.2.0 Roadmap (Free + Pro)

Drafted 2026-06-06 from the post-1.1.0 manifests (Free 2026-06-06, Pro 2026-06-06),
derived caches, wppqa baselines, and source verification. Lockstep release: both
plugins ship 1.2.0 together.

Versioning contract reminder (CLAUDE.md production rules): minor releases are
ADDITIVE. New features, new settings, deprecations - no removals.

---

> **Scope decision (owner, 2026-06-06):** 1.2.0 focuses on FUNCTIONALITY
> improvement. HivePress migration is DEFERRED to 1.3.0. Ripple: the
> customer-facing stub string in Pro (`class-competitor-migration.php:242`)
> currently promises "coming in 1.2.0" and MUST be reworded in 1.2.0 wave 1.
> DEC-1 resolved keep-aliases-until-2.0; DEC-2 resolved analytics-lite.
> Execution manifest: `.autovap/plan.yaml`.

## P0 - Public commitments

### 1. HivePress migration (Free pipeline + Pro UX) - DEFERRED to 1.3.0

Pro's REST literally tells customers "HivePress migration is not available in
this version - coming in 1.2.0" (`class-competitor-migration.php:242`). This is
a shipped promise.

- Schema audit already exists: `audit/architecture/competitor-schemas/hivepress.md`.
- Per migrator-ownership rules: new migrator goes to **Free** -
  `includes/import-export/class-hivepress-migrator.php` extending `Migration_Base`
  (implement `detect_source_fields()` + `get_default_mapping()` + `extract_*`).
- Pro's Visual Importer wraps it automatically via `wb_listora_get_migrators()`.
- Fire `wb_listora_listing_submitted` with `context: migration` (regression
  sentinel exists: `docs/qa/journeys/regression/migrator-context-arg.md`).
- QA: new admin journey + runbook row + remove the 1.2.0 stub response.

### 2. Deprecated hook aliases - DECISION NEEDED

P1-8 (1.0.4) renamed 4 Pro hooks to `wb_listora_pro_*` with
`do_action_deprecated` bridges and stated "drop aliases in 1.2.0". But
production rule 9 says removals happen only in MAJOR releases. One bridge
remains in source.

**Recommendation: keep the bridge(s) through 1.x** (cost is one line each) and
schedule removal for 2.0. Update the P1-8 plan note so the two rules stop
contradicting each other. If the owner overrides, removal in 1.2.0 needs the
30-day notice rule applied anyway.

---

## P1 - Half-cooked features (three-entry-point + no-duplicate rules)

### 3. `html_to_text` still triplicated (dedupe rule violation)

Three live copies, verified in source:
- Free `includes/workflow/class-notifications.php:1393` (private)
- Free `includes/workflow/class-email-body-formatter.php:44` (the canonical one)
- Pro `includes/class-email-helpers.php:115`

This was the documented 1.1.0 cleanup backlog item that did not land.
Consolidate Notifications + Pro onto `Email_Body_Formatter::html_to_text()` /
`wb_listora_email_html_to_text()`. Add a duplicate-detect assertion so it
cannot regress (`bin/cleanup-duplicate-detect.php` already flags it).

### 4. `listora_analytics` - Free creates it, only Pro touches it

Free's activator creates the table; Free has ZERO read/write/UI/REST surface
for it (verified: only Pro's Analytics feature + Moderator read/write it, plus
Pro's retention cron). On Free-only sites this is a dead table - exactly the
"half-cooked feature shipping dead weight" the three-entry-point rule targets.

Options (pick one in planning):
- **a) Free analytics-lite (recommended, also a sales surface):** Free records
  listing views and shows a per-listing view count on the owner dashboard +
  one REST read field. Pro keeps charts, sources, retention, exports. Clean
  upsell ladder, and the table earns its place in Free.
- b) Document the intentional exception in Free's manifest (`tables[].notes`)
  and accept the dead weight.

### 5. `coupon_usage` - admin-only surface

Verified: referenced only by `class-coupons.php` + migrator. No REST surface,
no customer-visible usage history. Wire the missing entry points (admin REST
read for the coupons list; show applied-coupon detail on the credit purchase
receipt/history) or document the exception in Pro's manifest.

### 6. `webhook_log` (outgoing webhooks) - no REST surface

Admin list exists (paginated in 1.1.0); zero REST routes mention webhooks
(verified). Add an admin-gated REST read (deliveries + retry trigger) so
headless/admin tooling can audit deliveries, or document the exception.

### 7. Demo import is still synchronous

1.1.0 made it faster and resilient (10s timeout, gallery cap, dedupe) but the
changelog explicitly notes "the import remains synchronous; a background-job
rearchitecture is tracked separately". 1.2.0 is that release: move demo import
(and large CSV imports) onto Action Scheduler batches with a progress UI.
Infra already exists (AS bundled in Free, `Cron_Scheduler` helper).

### 8. Pro cross-namespace fires: 64 sites / 46 unique hooks

Pro still fires 64 hooks under Free's `wb_listora_*` namespace
(`static_analysis.cross_namespace_fires`). P1-8 renamed 4; classify the
remaining 46 hooks into (a) intentional extensions of Free's public surface -
document them as such in the manifest, vs (b) Pro-only internals - rename to
`wb_listora_pro_*` WITH deprecation bridges (additive, allowed in a minor).

---

## P2 - UX / a11y debt (carried warnings)

### 9. Customer-facing `--sm` buttons: 36px vs the 40px floor

AUD-F7 (1.1.0) raised them 32 -> 36px; the ux-foundation tap-target floor is
40px. Either lift to 40px or record a documented exception with rationale.
(wp-admin-context buttons stay exempt per the known-limitation note.)

### 10. INV-14: 2 raw hex fallbacks in `pro-admin.css:723-724`

`var(--listora-fg-default, #1a1a1a)` + `var(--listora-bg-elevated, #ffffff)`.
Pre-existing, queued since the 2026-05-24 refresh; flips Pro back to 14/14
invariants.

### 11. `visual_required_no_enforcement`: 1 per plugin

The featured_image a11y gap flagged in both manifests since schema v2. Enforce
(require alt text / fallback rendering) or downgrade with a documented reason.

### 12. `js_only_activation`: 3 entries in Free

One already has `php_fallback: true` (settings). Close or document the other
two so the detector reads clean.

---

## P3 - Pipeline / manifest hygiene (cheap, do early in the cycle)

| Item | Detail |
|---|---|
| build-release.sh exclude | Add explicit `--exclude='vendor/wbcom-credits-sdk/'` (1.1.0 zip leak came from the untracked submodule leftover; rm was the hotfix, the exclude is the guard). Same defensive exclude in Pro's script. |
| Pro manifest stale table | `{prefix}credit_log` still listed in `tables[]` but dropped in code since the 1.5.0 credit refactor (verified: only DROP-TABLE comments remain). Remove from manifest. |
| Free `manifest.summary.json` size | 6.6 KB vs its declared 3 KB budget - trim the verbose `refresh_kind`/`_last_event` narratives. |
| Stale orphan-listener notes | `wb_listora_need_published`/`_need_rejected` are NOT orphans anymore (fire-sites verified at `class-reverse-listings.php:945,1077`). Refresh `dead-listeners.json` + drop the stale CLAUDE.md claim. |
| Upstream Credits SDK defect | `Transaction_Log::maybe_create_table` early-returns when the table exists, so schema upgrades skip new columns (1.1.0 worked around it for `payment_intent`). Fix upstream in wbcom-credits-sdk and re-sync `libs/`. |
| Firefox business-hours journey | Still a manual gate (Playwright MCP is Chromium-only). Either accept as a documented manual step per release or add a Firefox lane. |

---

## Suggested wave plan (autovap-migrate compatible)

| Wave | Scope | Items |
|---|---|---|
| 1 | Hygiene + decisions | P3 table + P0.2 decision + P2.10/11/12 |
| 2 | Dedupe + entry-point wiring | P1.3, P1.5, P1.6, P2.9 |
| 3 | HivePress migration | P0.1 (Free pipeline -> Pro wrapper -> journeys) |
| 4 | Analytics-lite (Free) | P1.4 option a |
| 5 | Background demo/CSV import | P1.7 |
| 6 | Namespace classification | P1.8 (docs-heavy, code-light) |

Every wave: manifest delta in the same PR, journey + runbook rows per the
self-growth contract, smoke gate before tag. Release per `wp-plugin-release`
with full readme.txt history (convention restored 2026-06-06).

## Explicitly OUT of 1.2.0

- Any symbol/template removals (rule 9 - majors only).
- DB schema changes beyond additive HivePress/analytics needs (rule 4 allows
  them in a minor with `DB_VERSION` bump - keep them additive).
- The 2 author-URL hooks (will NOT ship by design - see Pro plan/roadmap.md).

---

# Phase 2 (added 2026-06-07 - feature-completeness audit)

Source: feature-completeness audit vs GeoDirectory/Directorist/HivePress buyer
expectations (29 Free + 29 Pro features inventoried). Owner approved adding
the items below to 1.2.0; execution manifests:
plan/1.2.0-plan-phase2.yaml (Free) + ../wb-listora-pro/plan/1.2.0-plan-phase2.yaml.

## Approved for 1.2.0 (additive, S/M)

| # | Item | Severity it closes | Plugin | Effort |
|---|---|---|---|---|
| P2-1 | Email-template editor MVP: admin edits subject+body per event, stored in options read by the existing email_subject_{event}/email_content_{event} filters; preview via existing test-send | blocker-for-sale (Directorist/HivePress ship this) | Free | M (scoped from L) |
| P2-2 | Reconcile docs/website/feature-catalog.md with feature-matrix.md: add the 9 missing Pro features (Quick View, Infinite Scroll, Comparison, Audit Log, Outgoing Webhooks, SEO Pages, Google Places, BuddyPress, Visual Importer) | annoying (undersells Pro ~9 features) | Free docs | S |
| P2-3 | Admin "Refund credits" UI wiring the 1.1.0 refund event surface | annoying | Pro | M |
| P2-4 | WP privacy-tools integration: wp_privacy exporter + eraser for reviews/claims/favorites (Free) and leads/audit-log PII (Pro) | annoying (GDPR buyers) | Both | M |
| P2-5 | Pro i18n: generate .pot + wpml-config.xml | annoying (Pro un-translatable) | Pro | S |
| P2-6 | "Open now / Closed" computed badge on listing detail from the hours table | nice-to-have, universal expectation | Free | M |
| P2-7 | Review-reminder email post-engagement (cron + opt-out) | nice-to-have, lifts review volume | Free | S |
| P2-8 | listora_plan UX: trial/free-tier duration field + surface currency (SDK already accepts it) | annoying for non-USD / freemium directories | Pro | S |
| P2-9 | QA journeys for the 8 never-audited Pro features: Quick View, Infinite Scroll, SEO Pages, White Label, Analytics click-tracking, Google Places import, Visual Importer, Services_Pro booking CTA | audit-coverage debt (default-ON features without smoke contracts) | Pro | M |

Already fixed on the integration branch (audit ran on stale notes): the 2
frontend 32px buttons (f2-sm-tap-target shipped the 40px floor, smoke-verified).

## Parked for 1.3.0 (with rationale)

- Search analytics (keyword + zero-result logging) - new data subsystem, pairs
  naturally with the HivePress release.
- Bulk-edit listing actions - WP-native bulk edit partially covers; design the
  custom action set with real owner feedback first.
- PDF invoice/receipt on credit purchase - new PDF dependency; receipts (1.2.0)
  cover the immediate need.
- HivePress migrator - DEC-3 stands; the customer-facing stub no longer
  promises a version (p1-stub-reword).
- Recurring billing/subscriptions - blocker-for-sale but NOT minor-release
  scope (payment architecture); schedule as the 1.3.0/2.0 headline alongside
  a dedicated payments design doc.
- Multi-location per listing - own competitive plan defers (<5% demand).
