Skip to content

EP-026 daily_article_events_from_image(日別記事 イベント候補抽出) ​

← EP-一覧 · DailyArticlePostType README

概要 ​

日別記事の編集画面から、考察日×対象ホールの P-WORLD メール文言および静止画を材料に、ホール別イベント(daily_article_events)の候補を返す。ハンドラは候補 JSON のみ返す。post meta への自動保存はしない。イベントマスタへの自動登録もしない(未登録名は画面で「登録して選択」)。

処理順:

  1. メール subject / processed_html のプレーンテキストと、表示中イベントマスタ名の正規化包含照合(LLM なし)。照合ニードルは正規化後 2 文字以上。長い名前から優先照合する
  2. 対象日メールから履歴照合用の静止画を収集する(実装: PworldMailStillAttachmentResolver::collect_still_attachment_ids)。代表選定・装飾帯判定・寸法取得は同 Util に集約し、日別ホールサムネ生成(ADM-001)も同じ API を呼ぶ(サムネは装飾帯のみでもフォールバック可、履歴は不可)。メール内 refs から装飾帯(幅÷高さ ≥ 2.0 かつ高さ ≤ 200px)を除いた代表 1 枚を優先し、加えて大きな GIF(帯状でない、かつ高さ > 200px または元ファイル ≥ 約 80KB)のスチルも参照する。装飾帯のみのメールは代表を採用しない。収集した各静止画を過去の公開共起(db_daily_article_event_image_link)と SHA-256 完全一致、無い場合のみ dHash 類似(Hamming ≤ 8)で照合する。同一ハッシュ/類似を含む投稿が 2 件以上あり、イベント支持率が 60% 以上のときだけ source: history でマージする。照合対象から当該 post_id は除外する。参照は考察日から 18 ヶ月以内。dHash 用の直近行取得はホールあたり最大 500 件
  3. ホールで text/history とも空、かつ静止画があるときのみ ADM-028 の Claude / Gemini Vision を呼ぶ(キー未設定時はスキップして警告)。Vision に渡す静止画も手順 2 と同じ collect_still_attachment_ids 選定(代表+大きな GIF。装飾帯のみのメールは代表なし)。1 リクエストあたり Vision 呼び出しは最大 2 ホール。Vision へ送る MIME は image/jpeg|png|webp のみ(GIF はスチル優先。スチル無しは警告)。枚数は MAX_IMAGES_PER_HALL でさらに上限

共起の蓄積は公開/予約保存時に、上記と同じ選定ルールで集めた静止画(上限 12 枚/ホール)×選定イベントの組み合わせを書く。装飾帯のみのメールは代表を採用せず共起を書かない。候補化は支持率ルールで行う。選定ルール変更後や過去分の洗い替えは wp slot-kouryaku daily-article-event-image-link-backfill run

POST パラメータ ​

フィールド必須型・制約説明
action○文字列daily_article_events_from_image
_wpnonce○文字列daily_article_events_from_image で発行した nonce。nonce でも受け付ける
post_id○正整数対象の daily_article 投稿 ID
kousatsu_date−文字列画面上の考察日(Y-m-d)。キー送信時は空でも保存済み meta より優先(未送信時のみ meta)
halls−文字列画面上の対象ホール(カンマ区切り slug)。キー送信時は空でも meta より優先

編集画面は #daily-article-kousatsu-date-input / #daily-article-halls-input の現在値を(空でも)常に POST する。

成功時 data ​

論理名物理名型説明
ホール別hallsobjectホール slug → { matched, unmatched_names }
警告warningsarrayユーザー向け警告文字列の配列(キー未設定・Vision 失敗など。空可)

halls.<hall_slug> ​

論理名物理名型説明
一致候補matchedarray{ id: number, name: string, source: "text"|"history"|"vision" } の配列
未登録候補名unmatched_namesarrayVision が返したマスタ未登録のイベント名(文字列配列)。テキスト照合では空

失敗・ブロック(success: false の data に含み得るキー) ​

条件message の内容
AJAX コンテキスト外・nonce 不正Messages::AUTH_FAILED
post_id が不正、または投稿タイプが daily_article でないDailyArticleEventFromImageCopy::INVALID_POST
edit_post 権限なしMessages::PERMISSION_DENIED
考察日未設定、または対象ホールが空DailyArticleEventFromImageCopy::MISSING_CONTEXT
対象ホールにメール文言も静止画も無いDailyArticleEventFromImageCopy::NO_MAIL_OR_IMAGES
サービス例外(予期せぬ失敗)例外メッセージ

テキスト照合で一部ホールに結果があり、Vision だけ失敗した場合は成功レスポンスとし、warnings に理由を入れる。

権限 ​

  • ログイン必須(wp_ajax_ のみ。nopriv は付けない)
  • capability: edit_post(対象 post_id)

関連 ​

  • イベントマスタ一覧・登録 REST: GET/POST /wp-json/event-master/v1/...
  • LLM キー・プロバイダ: ADM-028 / ADM-009
  • 画像ハッシュ共起テーブル: db_daily_article_event_image_link(公開/予約保存時に同期。候補化は本 EP の支持率ルール。過去分は wp slot-kouryaku daily-article-event-image-link-backfill run)