array( 'added' => int[], 'created' => int[] ), * 'attributes' => array( 'keys' => string[] ), * 'image_alt' => array( attachment_id => array( 'previous' => string, 'written' => string ) ) ). * * `image_alt` (4.16.0) is the one entry that OVERWRITES rather than adds, * because the merchant approved replacing each image's alt text after seeing * both. It keeps the value from before the FIRST write, so a revert after two * applies still restores the merchant's own text. * * A ledger and not part of Meta::BACKUP on purpose. BACKUP is a once-only * whole-value snapshot, which is right for scalars this plugin exclusively * owns and wrong for terms: restoring one months later would delete tags the * merchant added by hand in between. See Native_Fields for the full argument. */ const NATIVE_WRITES = '_agencoen_native_writes'; /** * Review-sync bookkeeping (plugin 4.15.0). * * SYNC_DIRTY carries `{ reason, at }`, not merely a flag, and the reason is * load-bearing: `Apply::revert()` puts a product back to STATUS_ENRICHED, so a * reporter that read only the current status would announce a just-reverted * product to Rezolve Ai as a FRESH proposal, and the web review queue would * offer the merchant content they had explicitly taken down. */ const SYNC_DIRTY = '_agencoen_review_dirty'; /** contentType => Rezolve Ai review item id, returned by the last report. */ const REVIEW_IDS = '_agencoen_review_ids'; /** Consecutive failed report attempts, for backoff and for the admin notice. */ const SYNC_ATTEMPTS = '_agencoen_review_attempts'; /** * Merchant edits on the Review screen (plugin 4.18.0). * * EDITED is `field => ISO 8601 time of the last edit`, in plugin-field * vocabulary (see {@see Edit_Values::FIELDS}). It decides which decisions * carry a `value` in the report to Rezolve Ai, and lets {@see Apply_Queue} * hold back an approval that would overwrite an edit not yet reported. * Cleared when a new proposal is ingested, because an edit describes the * proposal it was made to. * * REVIEW_SYNCED_AT is when the last report that carried everything this * product had to say was built. Written only on a successful report. */ const EDITED = '_agencoen_edited'; const REVIEW_SYNCED_AT = '_agencoen_review_synced_at'; /** * Measured quality scores (plugin 4.17.0), cached from Rezolve Ai. * * QUALITY is a JSON string: `{ fetched_at, entries }`, one entry per field * the plugin asked about, exactly as `/api/v1/plugin/quality` described it * (normalised by {@see Quality::normalize_entry()}). It is a cache of a * platform read, never a number this plugin worked out. * * QUALITY_OVERALL and QUALITY_AT are derived from it and written only * alongside it, because a JSON string cannot be sorted or bucketed in SQL: * the Products screen sorts by the first, the dashboard buckets it, and the * background refresh takes the oldest by the second. QUALITY_OVERALL is * ABSENT, not 0, for a product with nothing measured, so "Not scored" can * never be read as a score. */ const QUALITY = '_agencoen_quality'; const QUALITY_OVERALL = '_agencoen_quality_overall'; const QUALITY_AT = '_agencoen_quality_at'; /** * The pre-4.17.0 "score". It was hardcoded to 90 for every enriched product * and measured nothing. Nothing writes or reads it any more; the key is kept * only so the 4.17.0 upgrade can delete what it left behind. */ const LEGACY_SCORE = '_agencoen_score'; const STATUS_QUEUED = 'queued'; const STATUS_ENRICHED = 'enriched'; const STATUS_APPLIED = 'applied'; const STATUS_DISMISSED = 'dismissed'; const STATUS_FAILED = 'failed'; // Content Hub (4.0): posts materialized from Rezolve Ai article briefs. const BRIEF_ID = '_agencoen_brief_id'; // Rezolve Ai brief id backing the post. const ARTICLE_SOURCE = '_agencoen_source'; // 'ace' for plugin-authored posts. const ARTICLE_JSONLD = '_agencoen_article_jsonld'; // Article JSON-LD from the platform. const ARTICLE_PUBLISHED_AT = '_agencoen_published_at'; // when the post went live (ISO 8601). const CONTENT_JOB = '_agencoen_content_job'; // article generation job id. /** * The five fields enrichment can touch, with human labels. * * @return array */ public static function fields() { return array( 'title' => __( 'Title', 'agentic-commerce-engine' ), 'short_description' => __( 'Short description', 'agentic-commerce-engine' ), 'description' => __( 'Description', 'agentic-commerce-engine' ), 'seo_title' => __( 'SEO title', 'agentic-commerce-engine' ), 'seo_description' => __( 'SEO meta description', 'agentic-commerce-engine' ), ); } }