feat: PRAB article JSON-LD emitter + meta reader (v0.8.0)

- PR_Core_Jsonld_Article: meta-triggered emitter for PRAutoBlogger posts
  (trigger: _prab_schema_version=1 on post type). Yoast path retypes page
  node to MedicalWebPage (wpseo_schema_webpage_type priority 10) and enriches
  Article piece with citation[], about[]→Drug @id, lastReviewed, honest
  reviewedBy (wpseo_schema_graph priority 13). No-Yoast fallback emits
  standalone @graph. Posts without trigger meta are byte-unchanged.

- PR_Core_Prab_Meta_Reader: sanitises all _prab_* contract-v1 meta at read
  time. URLs validated (http/https), DOIs normalised to https://doi.org/ URI,
  JSON arrays per-element validated, WP user ID resolved. Malformed values
  degrade gracefully. Honest reviewedBy: Person ONLY when mode=human + valid
  user ID; else Organization. Never a fabricated person.

- Unit tests: JsonldArticleTest.php — 22 assertions covering is_triggered,
  review_mode, reviewed_by Person/Org decision tree, citation sanitization,
  DOI normalisation, about linkage, retype passthrough, enrich, no-new-nodes,
  editorial-system-never-person.

- bootstrap.php: WP_User stub + get_userdata reads pr_test_userdata global.
- ARCHITECTURE.md: updated JSON-LD class tree + PRAB emission section.
- CONVENTIONS.md: PRAB contract v2 extension guide added.
- CHANGELOG.md + version bump to v0.8.0.

Ratified contract: convo/prcore/decisions/2026-06-11-jsonld-contract-v1.md
File sizes: article.php=235L, meta-reader.php=265L (both < 300-line gate).
No duplicate Article/WebPage nodes. uninstall.php unaffected (_prab_* unowned).

Agent-Session: prcore-jsonld-article-20260622
This commit is contained in:
peptiderepo
2026-06-23 04:23:21 +00:00
parent a7a2bb2f6d
commit 1ce471981b
9 changed files with 950 additions and 4 deletions

View File

@@ -215,14 +215,25 @@ Drug schema on single pages increases LLM citation rate. Filter hook allows cons
- **FAQ emission:** `_pr_faq_items` post-meta (JSON array of `{question, answer}` objects). Node emitted only when items exist.
- **Dosing omitted from schema:** YMYL constraint — no dosing data in JSON-LD.
JSON-LD class tree (v0.6.0):
JSON-LD class tree (v0.8.0):
| Class | File | Responsibility |
|---|---|---|
| `PR_Core_Jsonld` | `frontend/class-pr-core-jsonld.php` | Orchestrator: registers hooks, Yoast vs. standalone routing |
| `PR_Core_Jsonld_Drug` | `frontend/class-pr-core-jsonld-drug.php` | Builds Drug (+ MolecularEntity) schema node |
| `PR_Core_Jsonld_Webpage` | `frontend/class-pr-core-jsonld-webpage.php` | MedicalWebPage retype + lastReviewed/reviewedBy enrichment |
| `PR_Core_Jsonld_Webpage` | `frontend/class-pr-core-jsonld-webpage.php` | MedicalWebPage retype + lastReviewed/reviewedBy enrichment (peptide pages) |
| `PR_Core_Jsonld_Faq` | `frontend/class-pr-core-jsonld-faq.php` | FAQPage node (emit-only-when-populated) |
| `PR_Core_Jsonld_Article` | `frontend/class-pr-core-jsonld-article.php` | PRAB article emitter: MedicalWebPage retype + Article citation/about/reviewedBy enrichment |
| `PR_Core_Prab_Meta_Reader` | `frontend/class-pr-core-prab-meta-reader.php` | Reads and sanitises _prab_* meta (contract v1 reader) |
**PRAB article emission (v0.8.0, contract v1):**
- Trigger: `_prab_schema_version=1` on a standard `post`.
- Yoast path (priority 13, after peptide enrichment at 11+12): retypes page node to `MedicalWebPage`; enriches Yoast's existing Article piece with `citation[]`, `about[]` (Drug @id references), `lastReviewed`, honest `reviewedBy`.
- No-Yoast fallback: standalone `@graph` (Article + MedicalWebPage) on `wp_head` priority 99.
- **Honest reviewedBy:** Person only when `_prab_review_mode=human` + valid `_prab_reviewed_by` WP user ID. All other cases: Organization "Peptide Repo". Never a fabricated person.
- **`about` linkage:** Drug stubs reference `{peptide_permalink}#drug` (stable @id from v0.6.0).
- prcore reads `_prab_*` meta only; PRAutoBlogger writes only. uninstall.php unaffected.
- All `_prab_*` meta treated as untrusted at read time.
### #7: PR Core owns the `peptide` CPT and `peptide_category` taxonomy (v0.2.0)
Prior to v0.2.0, PR Core registered `pr_peptide` while Peptide Search AI registered `peptide` — both claimed the public rewrite slug `peptides`, and WP's rewrite resolver picked PR Core's empty CPT, 404'ing all 89 production peptide detail pages. v0.2.0 consolidates both registrations onto a single `peptide` CPT, owned by PR Core. PSA v4.5.0 drops its CPT/taxonomy registration; its meta boxes (`psa_peptide_data`, `psa_extended_data`), directory shortcode, KB article renderer, and search widget continue operating on the shared `peptide` CPT regardless of who registers it. Registration on both sides is guarded with `post_type_exists()` / `taxonomy_exists()` so deploy order is forgiving.