b63ab46f54
Tests / Integration Tests (push) Successful in 1m11s
Tests / Unit Tests (push) Failing after 11m56s
Anti-EAV Lint + Quality Gate / anti-eav-lint (push) Failing after 12m7s
Tests / PHPStan (push) Failing after 14m37s
Tests / PHPCS (push) Failing after 14m46s
Tests / PHP Lint (push) Failing after 14m57s
- readme.txt(WP 外掛目錄格式,隨 ZIP 發佈):Stable tag 對齊 1.0.0, changelog 補 1.0.0 條目 - CONTEXT.md(領域詞彙表):Status 區塊改寫為 v1.0.0 實況; HPCT_INTERCEPTORS 與 HivePress Adapter 兩節標註「已搬到 AddOn,核心無此常數」 - docs/:ENTITY_ADAPTER_COOKBOOK、2 篇 ADR、INTEGRATION_PATTERN_DECISION、 anti-eav-lint.yml.template - cookbook 修掉兩個死連結(ANTI_EAV_PLAYBOOK 在來源外掛就不存在) - INTEGRATION_PATTERN_DECISION 加 v1.0.0 後記:結論已被 AddOn 拆分取代 - template 改 wpdev/2meet-data-optimizer + ref v1.0.0 + wp tmdo lint - README.md 文件索引補上以上 7 個檔案 前綴改寫刻意只動類別/函式/slug(WPDO_→TMDO_、wp-data-optimizer→2meet-...), wpdo_ option/cron/hook/表名與 wpdo/v1 REST namespace 一律保留 —— 這是資料層 零遷移的前提。
86 lines
3.3 KiB
Markdown
86 lines
3.3 KiB
Markdown
# ADR-001: Post Entity Source-of-Truth Contract
|
|
|
|
**Status:** Accepted
|
|
**Date:** 2026-05-15
|
|
**Deciders:** wpdev
|
|
|
|
---
|
|
|
|
## Context
|
|
|
|
Two code paths can intercept `update_post_metadata` / `add_post_metadata`:
|
|
|
|
1. **TMDO_Sync_Bridge** — the original Zone interceptor that dual-writes to
|
|
Hot (Zone A) and Cold (Zone C) flat tables.
|
|
2. **TMDO_Hook_Bus** — the Entity Bridge write path added in v2.9.x that writes
|
|
to `wp_wpdo_post_*` flat tables via Entity Registry groups.
|
|
|
|
When both are active without a clear contract, a single `update_post_meta()` call
|
|
can fan out to three distinct write paths (wp_postmeta + Zone table + entity flat
|
|
table), producing divergent row counts and confusing `TMDO_API::trace_storage()`
|
|
output.
|
|
|
|
The defensive patch `TMDO_Sync_Bridge::is_owned_by_entity_bridge()` (v2.9.2)
|
|
was added to prevent double-writes but left the authoritative contract undocumented.
|
|
|
|
---
|
|
|
|
## Decision
|
|
|
|
**When `post` entity mode is `dual_write`, `shadow_read`, or `aeav_only`,
|
|
Entity Bridge (TMDO_Hook_Bus) is the sole source of truth for keys registered
|
|
in TMDO_Entity_Registry under the `post` entity type.**
|
|
|
|
Sync_Bridge defers to Entity Bridge for those keys via `is_owned_by_entity_bridge()`:
|
|
|
|
```php
|
|
// TMDO_Sync_Bridge — intercept_update() guard:
|
|
if ( self::is_owned_by_entity_bridge( $meta_key ) ) {
|
|
return $check; // pass-through — Entity Bridge owns this key
|
|
}
|
|
```
|
|
|
|
`is_owned_by_entity_bridge()` returns `true` when both conditions hold:
|
|
- `TMDO_Mode_Manager::writes_to_flat('post')` — mode is at least dual_write
|
|
- `TMDO_Entity_Registry::get_field('post', $meta_key)` — key is registered
|
|
|
|
Keys **not** in Entity Registry continue to be owned by Sync_Bridge (Zone path).
|
|
|
|
### Invariants
|
|
|
|
| Condition | Owner |
|
|
|-----------|-------|
|
|
| post mode = `disabled` or `idle` | wp_postmeta (no interception) |
|
|
| post mode ≥ `dual_write` AND key in Entity Registry | **Entity Bridge** |
|
|
| post mode ≥ `dual_write` AND key not in Entity Registry | **Sync_Bridge** (Zone) |
|
|
| post mode = `aeav_only` | Entity Bridge for registered keys; unregistered keys fallthrough to wp_postmeta |
|
|
|
|
---
|
|
|
|
## Consequences
|
|
|
|
**Good:**
|
|
- Developers adding a new post meta key can determine its owner in O(1): check
|
|
whether the key is in `wpdo_register_fields` under `post` entity. If yes →
|
|
Entity Bridge owns it; if no → Zone Sync_Bridge handles it.
|
|
- `TMDO_API::trace_storage()` output reflects this: Entity Bridge keys show the
|
|
flat entity table; Zone keys show the zone table.
|
|
|
|
**Bad / Watch out for:**
|
|
- A key registered in **both** Schema_Registry (Zone) and Entity_Registry (Entity
|
|
Bridge groups) will be captured by Entity Bridge and silently dropped by
|
|
Sync_Bridge. The duplicate registration is a misconfiguration — caught by
|
|
`TMDO_Sync_Bridge` guard and validated by `wp tmdo conflict-scan`.
|
|
- If `TMDO_Mode_Manager` or `TMDO_Entity_Registry` are unavailable (e.g. very
|
|
early bootstrap), `is_owned_by_entity_bridge()` returns `false` and all writes
|
|
fall through to the Zone path — safe degradation.
|
|
|
|
---
|
|
|
|
## Related
|
|
|
|
- `includes/interceptors/class-tmdo-sync-bridge.php` — `is_owned_by_entity_bridge()` (v2.9.2)
|
|
- `includes/engine/class-tmdo-hook-bus.php` — Entity Bridge write path
|
|
- `TMDO_API::trace_storage()` — human-readable storage path diagnostics
|
|
- `wp tmdo conflict-scan` — detects keys registered in both paths
|