Appearance
EP-026 daily_article_events_from_image(日別記事 イベント候補抽出)
← EP-一覧 · DailyArticlePostType README
概要
日別記事の編集画面から、考察日×対象ホールの P-WORLD メール文言および静止画を材料に、ホール別イベント(daily_article_events)の候補を返す。ハンドラは候補 JSON のみ返す。post meta への自動保存はしない。イベントマスタへの自動登録もしない(未登録名は画面で「登録して選択」)。
処理順:
- メール
subject/processed_htmlのプレーンテキストと、表示中イベントマスタ名の正規化包含照合(LLM なし)。照合ニードルは正規化後 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 件 - ホールで 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
| 論理名 | 物理名 | 型 | 説明 |
|---|---|---|---|
| ホール別 | halls | object | ホール slug → { matched, unmatched_names } |
| 警告 | warnings | array | ユーザー向け警告文字列の配列(キー未設定・Vision 失敗など。空可) |
halls.<hall_slug>
| 論理名 | 物理名 | 型 | 説明 |
|---|---|---|---|
| 一致候補 | matched | array | { id: number, name: string, source: "text"|"history"|"vision" } の配列 |
| 未登録候補名 | unmatched_names | array | Vision が返したマスタ未登録のイベント名(文字列配列)。テキスト照合では空 |
失敗・ブロック(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)