- In shadow_read, TMDO_Hook_Bus::intercept_get() returned the flat value.
update_metadata() reads the old value through that filter after the Hook
Bus has upserted the new one, so WP saw old === new and never wrote native
meta: every update in shadow_read was lost on demotion (dev36 2026-09-26).
shadow_read now returns $check (native) and compares flat on a sample of
reads (filter tmdo_shadow_compare_sample_rate, default 0.1). aeav_only is
unchanged; the post query router still routes in shadow_read.
- Live suite shadow_write: xfail markers removed, HivePress listing case
added (new int key hp_rating_count); fixtures gain post() and a
post_type-scoped field()/flat().
- Verify: live shadow_write + serialized 8/8 PASS (old code: 4 FAIL);
unit 685 OK, integration 484 OK, phpcs (phpcs.xml) 0, stan OK
- PR: PR-056
- Add tests/live: a `wp eval-file` runner (PASS/FAIL/XFAIL/XPASS/SKIP) with
fixtures that override entity modes in process (pre_option) and read
native / flat values with plain SQL, so WP core meta flows run for real
- shadow_write suite reproduces the dev36 finding: in shadow_read,
update_*_meta returns false and native meta is never written
(3 XFAIL marked for PR-056); the dual_write control passes
- Move the dev36 integration harness into tests/live/tools; outputs go to
cwd / $TMDO_LIVE_OUT, site URL and path are env-configurable
- Verify: wp --path=<dev36> eval-file tests/live/run.php shadow_write
→ 1 passed, 3 xfail; unit 658 OK, integration 480 OK,
phpcs (phpcs.xml) 0, stan OK
- PR: PR-052