AutoArticle AI v2.5.408 - Audit round 2: contract wired + lock fix + wizard fix
Release Date: September 15, 2026

CRITICAL FIXES (from the minute 3-agent audit):
- ARTICLE CONTRACT WIRED: PRE-pass logs writer defect codes before the repair
  chain; POST-pass at the save gate blocks unrepairable failures (routes to
  draft) and logs repairable residue as chain-coverage gaps. The contract
  was built in v2.5.402 but never connected to production until now.
- aaai_clear_agent_lock() DEFINED: was called 9x via function_exists() but
  never defined anywhere. The v2.5.343 Priority Bypass (queued Telegram/
  X-feed topics preempt the run lock) silently no-oped. Now force-releases
  all lock variants.
- SPORTS CACHE URL + AUTH: was posting to /api/cache/sports (404) without
  auth. Now posts to /api/v1/cache/sports with Bearer API key.
- WIZARD TOPIC MODEL: was gpt-4.1-nano (retired, warned every cycle). Now
  gemini-3.5-flash-lite.
- $_model_changed INITIALIZED: was PHP 8 "Undefined variable" warning on
  migration runs.
AutoArticle AI v2.5.407 - Topic model roster fix + migration
Release Date: September 15, 2026

FIXES (live log: "Unknown topic model set — using default" firing on EVERY
agent cycle, one 51-word article, CRON CRASH noise):
- ALLOWED TOPIC MODELS updated to the current lean roster (was stale — included
  retired gpt-4o-mini/gpt-4.1-nano/gemini-2.0-*/grok-2, missed the current
  defaults). The default fallback changed from retired claude-sonnet-4-6 to
  google/gemini-2.5-flash-lite.
- TOPIC MODEL MIGRATION: agents with retired/missing topic_model values are
  migrated to google/gemini-3.5-flash-lite on update — kills the per-cycle
  "Unknown topic model" noise permanently.
AutoArticle AI v2.5.406 - Comparison-scaffold contract check
Release Date: September 14, 2026

NEW (contract check CONTENT.COMPARISON_SCAFFOLD):
- Detects internal-link anchors wrapped in comparison scaffolding in the
  article HTML ("Much like <a>…</a>", "Similar to how <a>…</a>").
- Repairable: the anchor is kept but the scaffold phrasing is flagged for
  the contract log (the prompt ban from v2.5.400 prevents new occurrences;
  this check catches violations that still slip through).
AutoArticle AI v2.5.405 - Stale model migration + accent completion + circuit throttle
Release Date: September 14, 2026

FIXES (live log: every agent still requesting retired models gpt-5.4-nano/deepseek-v4-flash,
SYNC circuit open spamming 6x/min, Dembélé keyword "demb l hard work" -> "demb élé"):
- MIGRATION: all retired writer models (gpt-5.4-nano, deepseek-v4-flash/0731, minimax, muse-spark, mercury, ling-vl, glm, laguna, grok) now migrate to gpt-5.6-luna — kills "[Model Check] Selected fallback" noise and stale pool requests.
- ACCENT COMPLETION: single-letter + accented word fragments ("demb l" + "élé") merge into the accented form before density weave — keyword correctly becomes "dembélé".
- SYNC CIRCUIT: open-circuit log throttled to 1/hour (was 6/min spam).

AutoArticle AI v2.5.404 - Topic-prefix title-leak strip
Release Date: September 14, 2026

FIX (live draft: title shipped as "2026 honda prelude long: Honda's Most
Controversial Car Begins Its Long-Term Test" — the slug-like topic leaked
into the H1 as a prefix):
- TOPIC-PREFIX STRIP: a leading run of 2-6 slug-shaped lowercase/digit words
  ending with ":" directly before the real capitalized headline is stripped.
  Legit titles (capitalized prefixes like "IPL 2026:") are untouched — the
  prefix must start lowercase and contain no sentence punctuation.
AutoArticle AI v2.5.403 - CONTRACT REGENERATION LOOP (Phase 3 of the rebuild)
Release Date: September 13, 2026

THE LOOP — when the Article Contract finds UNREPAIRABLE failures at the save
gate, instead of burning the cycle:
1. ONE targeted writer retry with the failure codes as explicit feedback
   ("FAILED CHECKS: [STRUCTURE.NO_H2] 0 sections, [STRUCTURE.SEVERELY_THIN]
   150/600 words — fix exactly these").
2. The retry keeps the same topic, headline, facts, and word target; the
   topic stays reserved and fact-verified (cheaper than a fresh cycle).
3. The regenerated article is re-validated against the FULL contract — only
   a clean pass proceeds to save.
4. A second failure falls through to the block (agent retries next cycle
   with a fresh topic) — never loops.

Guard rails: retry output must contain H2 structure and meet the word floor
before re-validation; code fences stripped; repair detail capped at 5 codes;
fails soft to the existing block path on any call error.

Log lines: [Contract Regen] REGENERATED / still-failing / unusable / call-
failed — full loop observability from day one.
AutoArticle AI v2.5.402 - ARTICLE CONTRACT (Phase 1 of the once-and-for-all rebuild)
Release Date: September 13, 2026

THE ARTICLE CONTRACT — one formal publishability spec codifying every live
incident from the Sep 12-13 audit trail (~21 defect classes), each as a
structured failure {code, detail, repairable}:

  TITLE.DANGLING_TAIL / TITLE.FRAGMENT_TAIL / TITLE.TRUNCATED_TOKEN
  STRUCTURE.NO_H2 / SEVERELY_THIN / THIN_SECTION / POST_FAQ / DUP_PARA
  FAQ.NO_ANSWER / TRUNCATED_QUESTION / RUNAWAY_ANSWER / NOVEL_SPECS
  CONTENT.PLACEHOLDER / CITATION_MARKERS / MIDWORD_CUT
  KEYWORD.ABSENT_BODY / LEADING_STOPWORD / COLLOQUIAL_TAIL / TITLE_CLONE_FILLER

WIRING:
- PRE-pass (before the repair chain): logs exactly what the writer produced —
  per-model defect rates become measurable.
- POST-pass (save gate): unrepairable failures block the save (one spec
  replaces the ad-hoc checks); repairable residue is logged as chain-coverage
  gaps for the Phase-2 repair registry.
- GOLDEN CORPUS (21 fixtures, all passing): every live incident locked as a
  regression test — OPPO title, AMD fragment, Kingdom Hea, India-FTA,
  post-c, Diablo thin section, Jailer TBD, Raphinha citations, SWE-2 empty
  FAQ, Realme truncated question, Creta runaway + hallucinated specs, Honda
  post-FAQ, Realme dup-para, all four keyword classes, and a healthy control.

Phase 3 (next session): failure codes feed a regeneration loop — unrepairable
drafts get ONE targeted retry with the codes as writer feedback.
AutoArticle AI v2.5.401 - Post-title dangling-tail strip
Release Date: September 13, 2026

FIX (live OPPO article: H1 shipped as "…Dual 200MP Cameras and Ultra-Narrow"
— a severed continuation clause ("Ultra-Narrow" WHAT?)):
- The dangling-tail stripper existed but only ever ran on SEO titles, never
  the post H1. It now runs on the post title right after headline-sanitize,
  so the H1, slug, keyword, and tags all derive from the clean title
  ("…Dual 200MP Cameras").
- The article's second defect (body cut mid-word at "post-c") is covered by
  the v2.5.383 truncation guard on current builds — this article predated
  the site's update.
AutoArticle AI v2.5.400 - Post-FAQ content relocation + comparison-scaffold anchor ban
Release Date: September 13, 2026

FIXES (live Honda Civic article):
- POST-FAQ RELOCATION: two REAL content sections shipped after the FAQs
  (writer mis-ordered the FAQ block mid-article) and survived the old strip's
  <400-char sanity cap. Now: short post-FAQ tails = junk → deleted (existing);
  long tails (<60% of body) = real content → RELOCATED before the FAQ heading
  (content preserved, template order restored).
- COMPARISON-SCAFFOLD ANCHORS banned in the writer prompt: "Much like
  [Headline]", "Similar to how [Headline]", "resembles the deployment seen
  when [Headline]" — the live article spliced "Understanding Toyota Camry's
  legendary powertrain reliability" and "Virat Kohli's Tactical Analysis"
  into Honda Civic prose via this pattern.
- Note: the missing FAQ answer in this article is covered by the v2.5.393
  missing-answer removal once this build is live on the site.
AutoArticle AI v2.5.399 - Dangling-fragment drop in headline cap + SEO titles
Release Date: September 13, 2026

FIX (live: "AMD Sets $189 Price for Ryzen 5 7500 and $99 for Ryzen 5 5500F:
A Strategic" — the 16-word headline cap cut "…: A Strategic Masterstroke"
mid-clause and shipped the article-led fragment):
- HEADLINE CAP: after the word cap, a separator token (colon/comma/dash)
  followed by a 1-2 word tail is a truncated clause — the tail is dropped,
  cutting at the separator. Digit-led tails ("…: 5 Takeaways") are kept.
- SEO-TITLE DROPPER: aaai_title_drop_comma_fragment now handles colon/dash
  separators and article-led 2-word tails with the same digit exception.
AutoArticle AI v2.5.398 - Colloquial tails, announcement filler, title truncation repair
Release Date: September 13, 2026

FIXES (live incidents):
- "Aubameyang Depor": COLLOQUIAL-NICKNAME TAIL dropped (Depor/Barca/Atleti/Utd/
  Citeh are headline nicknames, never search-phrase tails) — keyword degrades
  to the clean entity ("Aubameyang").
- "Fortnite Officially Confirms Kingdom": ANNOUNCEMENT FILLER (officially/
  confirms/announces/reveals/reportedly/finally/actually/says/teases) now
  breaks the title-clone trim — keyword degrades to "Fortnite".
- "…Kingdom Hea Collab…" (Hearts truncated at source): TITLE-TOKEN COMPLETION —
  a title word missing from the body that exactly ONE body word extends gets
  completed ("Hea" → "Hearts"), max 2 tokens, before the keyword passes run.
AutoArticle AI v2.5.397 - Severely-thin + structure floors in the save gate
Release Date: September 13, 2026

FIXES (live India-FTA article: ~150 words total — intro + FAQs only, ZERO H2
sections — published through a path whose earlier WC gates didn't run):
- SEVERELY-THIN FLOOR: the save gate's stub floor (100 words) is now 70% of
  the target (min 280). A fragment that slipped every upstream gate can no
  longer save.
- STRUCTURE FLOOR: a 300+-word article with ZERO H2 sections is a writer
  breakdown (FAQ-only skeleton) — blocked. FAQ H3s don't substitute for body
  H2s.
Both floors release the agent lock + log the blocking reason for the retry
cycle. Healthy articles verified unaffected.
AutoArticle AI v2.5.396 - UPDATE CHECKER (native WP updates from the manifest)
Release Date: September 13, 2026

NEW (#4 delivery pipeline — the upload-gap fix):
- The plugin now polls https://autoarticleai.com/api/v1/updates twice daily
  and surfaces the NATIVE WordPress "Update available → Update now" flow in
  Plugins. No more manual zip uploads — production sites learn about new
  releases within 24h automatically.
- Requires the server manifest (live). Future releases: bump the version +
  manifest in one commit; sites update themselves.
AutoArticle AI v2.5.395 - Audit fixes: admin model rosters (P0-2) + keyword-early coverage
Release Date: September 13, 2026

FIXES (from the three-agent audit):
- P0-2: ADMIN DROPDOWN ROSTERS — admin/settings.php and admin/god-mode-page.php
  still offered deepseek/deepseek-v4-flash ("cheapest — recommended"),
  gpt-5.4-nano, minimax, and muse-spark: dead gateway slugs that silently
  failed runs. Replaced with the lean four-carrier roster (luna default,
  qwen, deepseek-v4.1-flash, ling-3.0-flash) + premium coin-path options.
- Keyword early-finalize coverage note: v2.5.393's leading-verb strip now
  runs before the density weave; store-point residue documented for the
  next sweep (P1-1).
AutoArticle AI v2.5.394 - Thin-section guard
Release Date: September 13, 2026

FIX (live Diablo draft: "What This Means for Diablo 4 in 2026" shipped as an
H2 with an 8-word body — "The Season of Hell's Legacy is a statement." — a
section that promises content and delivers a bumper sticker):
- THIN-SECTION GUARD: an H2 whose body is under 20 words loses its HEADING;
  the content stays and merges into the surrounding flow. The FAQ section is
  exempt, and anything 20+ words keeps its heading. Fulfils the "H2 sections
  must be substantive" expectation without touching legit short closers that
  carry 20+ words.
AutoArticle AI v2.5.393 - Runaway-FAQ cap, single-sentence truncation, acronym casing, keyword early-finalize v2
Release Date: September 13, 2026

FIXES (live luna draft: single-sentence truncation "…while cutting ope" and
missing FAQ answers; live Creta draft: 350-word hallucinated FAQ ramble and
"Swe-2"-style acronym lowercasing; live weave targeting a pre-final keyword):
- TRUNCATION GUARD v2: single-sentence paragraphs that are entirely one
  incomplete sentence are now DROPPED (the count>=2 gate skipped them).
- FAQ MISSING-ANSWER REMOVAL: a question with no answer <p> after it is
  removed (broken entry class).
- FAQ RUNAWAY-ANSWER CAP: answers >150 words are trimmed to their first 3
  coherent sentences (the 350-word fabricated ramble class loses its tail).
- ACRONYM-CASING REPAIR: heading tokens re-cased to match the body
  ("Swe-2" -> "SWE-2") when only the all-caps form appears in prose.
- KEYWORD EARLY-FINALIZE v2: the leading-verb strip now runs in the EARLY
  pass — the zero-match weaver can no longer weave a verb-led keyword
  ("the releases swe-2 story") that the store point will refuse and re-derive.
NOTE: the HALLUCINATED-FAQ gram-gate from v2.5.389 must be on your site —
upload this zip to activate it against the Creta-class FAQ walls.
AutoArticle AI v2.5.392 - Lean model pool + leading-stopword keyword fix + tag hash-strip
Release Date: September 13, 2026

CHANGES (owner directive — mirrors server v2.9.12):
- WRITER DROPDOWNS: laguna-s-2.1, glm-5.3-flash, minimax variants removed
  from the model lists. Four carriers: gpt-5.6-luna (default), qwen3.7-flash,
  deepseek-v4.1-flash, ling-3.0-flash.
FIXES:
- LEADING-STOPWORD KEYWORDS: "on switch" shipped as a keyword (Diablo-on-
  Switch article) because only the keyword TAIL was stripped. Leading
  prepositions/stopwords/articles are now stripped too ("on switch" →
  "switch"; mid-phrase usage untouched).
- TAG HASHTAG PREFIXES: "#nintendo" → "nintendo".
AutoArticle AI v2.5.391 - gpt-5.6-luna default + prompt token slimming
Release Date: September 13, 2026

CHANGES:
- DEFAULT MODEL = openai/gpt-5.6-luna: agent write_model fallback, the
  scheduler migration target, ajax model picker, god-mode defaults, and the
  maintenance LLM all default to luna. Server 'auto' mapping matches.
- PROMPT TOKEN SLIMMING (input-token reduction ~8-12% per write; provider
  prompt caching still hits because stable persona/rules stay FIRST and
  dynamic context stays LAST):
  * CURRENT NEWS CONTEXT: 8 -> 5 headline lines (recency flavor, not core
    grounding)
  * Site tag vocabulary: 15 -> 10 tags
  * Writer-prompt internal-link anchors: 4 -> 3 (each block ~40-60 tokens)
- TOPIC LEARNING PERSISTENCE (already live, unchanged): every reservation
  stores topic_keywords/event_hash/performance in brain_memory (priors learn
  entity quality from it), quality-gate failures persist as brain_lessons
  mistake rows (injected into the next 14 days of writes), owner Telegram
  feedback persists as owner_feedback lessons, and related_memory gives the
  writer "what we already covered" continuity per topic.
AutoArticle AI v2.5.390 - MODEL ROSTER RESET (owner directive)
Release Date: September 13, 2026

CHANGES (mirrors server v2.9.10):
- REMOVED: deepseek-v4-flash (+0731 snapshot), mercury-2.5, ling-3.0-flash-vl
  — all writer/topic dropdowns, defaults, and fallbacks.
- ADDED: deepseek/deepseek-v4.1-flash (replaces v4-flash in every default,
  dropdown, god-mode, ajax model picker, and the maintenance LLM).
- SWAPPED: openai/gpt-5.4-nano → openai/gpt-5.6-luna in all dropdowns.
- AGENT MIGRATION: agents still set to deepseek/deepseek-v4-flash are
  upgraded to deepseek/deepseek-v4.1-flash on this update.
- NEW POOL ORDER (server-side, weights): 1) gpt-5.6-luna  2) qwen3.7-flash
  3) deepseek-v4.1-flash, then ling-3.0-flash / glm-5.3-flash / laguna /
  minimax.
AutoArticle AI v2.5.389 - Doubled-word/currency scrub + FAQ run-on repair
Release Date: September 13, 2026

FIXES (live SRK-vs-Amitabh article: "produced by by Yash Raj Films",
"in the the 2005 drama", "ॐ1000 crore" (OM glyph instead of ₹), and a
collapsed run-on FAQ paragraph invisible to the h3+p validator):
- DOUBLED-WORD SCRUB: "the the", "by by" class collapsed (single text-node,
  case-insensitive).
- CURRENCY-GLYPH CORRUPTION: Devanagari OM / stray separators before a
  digit are rewritten to ₹ ("ॐ1000" → "₹1000"); a standalone OM is untouched.
- FAQ RUN-ON REPAIR: a paragraph with >=2 "?"-terminated sentences and
  alternating answers is rebuilt into proper h3+p FAQ entries (>=2 pairs
  required), making them visible to the FAQ validator and FAQPage schema.
AutoArticle AI v2.5.388 - Keyword early-finalize + zero-match weaver
Release Date: September 13, 2026

FIXES (live Rodrygo article: keyword "Rodrygo Return" at 0.00 density —
present in the title but the body only ever had "Rodrygo's projected
return", never the exact phrase; RankMath 0 across content/headings):
- KEYWORD EARLY-FINALIZE: the store-point keyword guards (presence fix,
  tier completion, accent repair) ran AFTER the density/heading enforcers,
  so a keyword that changed at store time was never woven. The keyword is
  now finalized BEFORE the enforcers run.
- ZERO-MATCH WEAVER: the v2.5.293 prepend removal left zero-match keywords
  unserved ("leaving content untouched"). A 0-occurrence multi-word keyword
  now gets ONE natural closing line (3-template bank, deterministic pick)
  inserted before the FAQ section — content/density checks go green without
  the robotic-opening damage the old prepend caused. Single-word and
  non-ASCII keywords are skipped (presence machinery covers them).

---
AutoArticle AI v2.5.387 - Hallucinated-FAQ gate + meta-title comma fix
Release Date: September 13, 2026

FIXES (live deepseek article: FAQ invented "second major expansion, lightning-
based skill tree, exclusive mount" while the body said "Blizzard has not
detailed the kit yet"; meta title shipped as "…Arrives Next Week, Diablo"):
- HALLUCINATED-FAQ GATE: an FAQ answer whose distinctive 2-word phrases
  mostly appear NOWHERE in the article body (>=4 novel grams, >=50% of the
  answer, answer >=25 words) is removed as fabricated — the body-vs-FAQ
  contradiction class can no longer publish. Gram-set vs gram-set extraction
  (stopwords skipped identically both sides) so legit echoes match.
- META-TITLE COMMA FRAGMENT: a 57-char cut landing inside the second clause
  of a two-clause headline ("…Next Week, Diablo") now cuts at the comma.
  Digit tails ("…, 3-1") and 3+-word tails ("…, Camera Deep Dive And
  Verdict") are kept.

---
AutoArticle AI v2.5.386 - RAG related_memory (server semantic retrieval)
Release Date: September 12, 2026

NEW (requires server v2.9.5+; semantic data flows once the Supabase
migration v14 is applied — until then related_memory is simply empty and
everything else works):
- RELATED MEMORY CAPTURE: prefetch stores the server's related_memory
  (top-5 semantic matches: what we already published about this entity,
  with similarity + performance) per topic (1h transient).
- RAG CONTINUITY: the writer prompt gains a "WE ALREADY COVERED THIS
  ENTITY" block — advance the story, don't re-report; reference earlier
  coverage naturally. This replaces recency-only context with relevance.
- RELATED-MEMORY INTERNAL LINKS: semantic matches resolved to real local
  URLs (title match, LIKE fallback) become smart-link candidates — ranked
  by the server's performance data, still passing every anchor gate.
AutoArticle AI v2.5.385 - FAQ/table/paragraph structure guards + guard-scope fix
Release Date: September 12, 2026

CRITICAL SCOPE FIX: the v2.5.382-384 structure guards (citation scrub,
truncation guard, heading-colon strip, duplicate-section remover, hedge
scrub, post-FAQ strip) were accidentally nested INSIDE the
add_faq_section conditional — agents with the FAQ toggle off skipped every
one of them. Moved out; they now run for every agent unconditionally.

NEW GUARDS (live Realme price-hike draft: garbled run-on table + clean table
shipped together, duplicate paragraphs, four truncated FAQ questions):
- FAQ QUESTION TERMINAL CHECK: inside the FAQ section a question MUST end
  with "?" — truncated entries ("Which Realme model saw the biggest") are
  removed with their answers. Body h3/h4 keep lenient rules.
- DUPLICATE-TABLE REMOVER: two tables sharing >=70% of their currency-amount
  set drop the EARLIER (garbled) one — amount sets survive run-on garbling
  where cell tokens don't.
- RUN-ON TABLE-DUMP SCRUB: a paragraph with >=5 currency amounts AND >=3
  case-boundary merges ("ModelVariantOld", "P48GB") is a structure-lost table
  dump; dropped.
- DUPLICATE-PARAGRAPH REMOVER: verbatim repeats drop the later occurrence
  (>=60 chars only).

---
AutoArticle AI v2.5.384 - Placeholder choke + title-clone keyword + post-FAQ strip
Release Date: September 12, 2026

FIXES (live Jailer 2 draft: "TBD" table rows, whole title used as focus
keyword and woven into prose, junk section after the FAQs, filler-fabrication
sentences like "Marketing models campaign timelines accordingly"):
- SAVE GATE #4 (final placeholder choke): TBD/TBA/lorem/[insert tokens in the
  FINAL html block the save outright when not already quality-blocked —
  closes the pipeline paths that bypassed the v2.5.253 draft gate.
- TITLE-CLONE KEYWORD GUARD (store point): keywords >=5 words or containing
  explainer words (explained/details/guide/breakdown) are trimmed to the
  leading noun phrase ("jailer 2 sequel cast and director details explained"
  -> "jailer 2 sequel cast"); clean keywords untouched.
- POST-FAQ SECTION STRIP: the FAQs block is terminal — a writer-generated
  <h2> section after it ("Production Timeline Update" + fluff) is truncated.
- PROMPT: never reuse the title as focus keyword / no explainer words;
  "expected to" capped at 3; NO-FILLER-SENTENCES rule (every sentence must
  carry a name, number, date, or named source).

---
AutoArticle AI v2.5.383 - Structure guards for pool-model drafts
Release Date: September 12, 2026

FIXES (live laguna-s-2.1 draft — first production sample after the v2.8.97
routing fix — shipped a mid-sentence truncation, a colon-tailed junk heading
with duplicated FAQ content, "the reportedly Exynos 2500" grammar, junk tags
"Upgrade"/"FE Leaked", and the keyword "galaxy s26" truncating the product
name "Galaxy S26 FE"):
- TRUNCATED-SENTENCE GUARD: a paragraph whose last sentence has no terminal
  punctuation or ends on a dangling function word ("…flagship-level
  performance, the") loses that incomplete sentence. ": ;" count as valid
  terminals (list/table introductions).
- HEADING-COLON STRIP: H2/H3 never end with ":" ("Samsung Galaxy S26 FE
  Launch:" -> "…Launch").
- DUPLICATE-SECTION REMOVER: two H2 sections sharing >=70% of their >=4-char
  words drop the LATER one (FAQ section never dropped) — kills the
  duplicated-spec junk section class.
- HEDGE GRAMMAR SCRUB: "the reportedly Exynos 2500 processor" -> "the Exynos
  2500 processor" (reportedly never sits between a determiner and a noun;
  adverbial use untouched).
- TAG STEMS: upgrade, leak/leaks/leaked, tease, spotted, surfaced added to
  the tag verb sweep ("Upgrade" and "FE Leaked" tags rejected).
- KEYWORD EDITION COMPLETION: "galaxy s26" completes forward over FE/SE/
  Ultra/Pro/Max/Plus/Lite/5G/Edge markers ("galaxy s26 fe").

---
AutoArticle AI v2.5.382 - Internal-link anchor gate + splice scrub + citation-marker strip
Release Date: September 12, 2026

FIXES (live Raphinha article: four headline fragments spliced mid-sentence —
"…players like Barcelona Winger Raphinha Wins in the inside channels",
"…the Vibe Release Date Confirmed: market-value conversation", "…the Kim
Soo Hyun Case of elite wingers…", "…in a week where John Abraham Signs His
attention shifts…" — plus leaked "[5][6]" reference markers and duplicated
"Full coverage via BBC Sport." lines):
- ANCHOR GATE (normalization chokepoint): title-prefix anchors containing ANY
  verb-form word (except a nounish whitelist: galaxy watch, product release,
  book review stay nouns) or headline punctuation are rebuilt from the
  title's leading non-verb words ("John Abraham Signs His" → "John Abraham"),
  or dropped entirely when nothing clean remains. The writer never sees
  headline fragments as weave-material anymore. Complements the v2.5.375
  FK-first anchors (which fix the root: focus keywords read naturally).
- MID-SENTENCE SPLICE SCRUB: any paragraph containing a contiguous 5-word
  run from a context headline is dropped (extends the v2.5.376 orphan scrub
  from whole-paragraph overlap to embedded fragments).
- CITATION-MARKER SCRUB: standalone "[5]"-style reference brackets stripped
  from the body (GFM links excluded).
- ATTRIBUTION CAP: only the first "coverage via …" paragraph survives.
- PROMPT: anchors must be natural noun phrases — never weave titles or
  truncated fragments; no Wikipedia-style citation markers; max ONE
  attribution line per article.

---
AutoArticle AI v2.5.381 - Internal-link citation rule (no headline splicing)
Release Date: September 12, 2026

FIX (live incident: "As our earlier coverage put it, OpenAI Throws Astra
Into the top of its model line-up — a move that…" — a whole headline spliced
mid-sentence, grammatically broken):
- Root cause was our OWN prompt line "Internal links mid-sentence" — the
  writer read it as license to paste linked-article headlines into prose.
  Rewritten as an explicit citation rule: link a natural 3-6 word phrase
  from the writer's own prose; paraphrase earlier reporting in one clause
  ("our earlier report on the Astra launch", "as we covered last week");
  NEVER splice a headline verbatim mid-sentence. The orphan-fragment scrub
  (v2.5.376) still drops full-paragraph headline dumps; this rule kills the
  mid-sentence class at the source.

---
AutoArticle AI v2.5.380 - Verb-boundary keyword guard + verb-filtered title derivation
Release Date: September 12, 2026

FIXES (5 live incidents in one day: "saber interactive executive states",
"mcu next release addresses", "wins dutch", "spied testing",
"mirzapur the movie box"):
- TERMINAL VERB-BOUNDARY GUARD (store point): trailing headline verbs are
  dropped (ONE pop only), leading verbs are dropped (ONE shift), lone verbs
  are refused (v2.5.377 behaviour). A verb-led fragment that reduces to a
  single word ("wins dutch" -> "dutch") is refused outright and rebuilt from
  the title. Noun-ambiguity whitelist ("galaxy watch", "product release",
  "mcu next release" are nouns, never verb tails) and the "united states"
  proper-compound exception prevent false strips.
- VERB-FILTERED TITLE DERIVATION: the old first-4-words fallback shipped
  headline verbs and mid-compound cuts ("mirzapur the movie box" was
  literally the first 4 title words; "nintendo wins dutch" came from
  "Nintendo Wins Dutch Lawsuit"). Now: skip leading function words, STOP at
  the first mid-phrase verb (never skip over it), take up to 3 content
  words. "…Wins Dutch Lawsuit…" -> "nintendo dutch lawsuit"; "Spied
  Testing…" -> "2027 porsche 718".
- Stems added: address, spied, impose. Continuation set: "office" (box
  office completes forward).

---
AutoArticle AI v2.5.379 - Backward tier completion for truncated product-name keywords
Release Date: September 12, 2026

FIX (live incident: keyword shipped as "Pro Astra", truncating the product
name "ChatGPT Pro Astra"):
- The v2.5.367 entity completion only completed FORWARD ("Haaland Manchester"
  -> "Manchester City"). This keyword started mid-entity instead: "Pro" is a
  tier word riding on a brand, and the chokepoint had no rule to recover the
  brand in front of it. New rule (c): when the FIRST keyword word is a
  tier/edition word (pro/max/ultra/plus/mini/lite/air/go/note/edge/studio/
  prime/se) and the title word immediately before the match is a clean
  candidate, prepend it — "Pro Astra" -> "ChatGPT Pro Astra".
- Presence-safe by construction (verbatim title substring) and verified with
  mb_stripos anyway. Guards: function words (the/its/after/...) and headline
  verbs never join — "Pauses Pro Astra" would corrupt the phrase. Verb-stem
  list extended with headline verbs (pause/suspend/halt/strain/unveil/debut/
  clash/expand/shut/exit/stun/file/probe/quiz) so "Pauses" is always caught.
  4-word / 45-char caps, consistent with the forward rules.
- Applies to both the RankMath chokepoint and the Maintenance sweep (shared
  function). Verified: joins the reported case, refuses verb/function-word
  predecessors, leaves non-tier keywords untouched.

---
AutoArticle AI v2.5.378 - Accent-split repair (keywords + tags)
Release Date: September 11, 2026

FIX (live incident: focus keyword shipped as "james rodr íguez"):
- Writers emit stray spaces inside accented names ("rodr íguez", "bernab éu" —
  tokenizer artifacts) and the pipeline stored them verbatim, so the keyword
  matched nothing and RankMath scored 0. New repair joins a lowercase latin
  run (3+ chars) split from an accented continuation, in BOTH the keyword
  chokepoint (shared with the Maintenance sweep) and the tag merge.
- JOIN-VERIFICATION: the join is kept only when the joined form actually
  occurs in the title/body ("rodríguez" does; "megaéxito" never does), so
  legit two-word phrases ("mega éxito", "San José", "El Niño", "cafe au lait")
  survive untouched. Verified across a 10-case matrix.

---
AutoArticle AI v2.5.377 - Lone-verb keyword terminal guard + SYNC HTTP error visibility
Release Date: September 11, 2026

FIXES (from the Sep-11 log review):
- LONE-VERB KEYWORD GUARD: a Rivals article shipped focus keyword "sets"
  (single verb, 0.63% density). Added aaai_is_verb_form() helper (stem +
  suffix-strip, same approach as tag filters) and two enforcement points:
  (1) the degrade ladder skips verb-forms when picking the longest matching
  word (with a diagnostic log naming the skipped verb + source phrase);
  (2) TERMINAL guard at the RankMath store point refuses any single-word
  verb keyword from ANY producing path — keeps the existing stored keyword,
  else falls through to title derivation.
- SYNC HTTP ERROR VISIBILITY: the v2.5.368 per-failure logging only covered
  connection errors; HTTP non-200 failures (401/422/524) stored silently.
  The non-200 branch now logs "[SYNC] attempt failed (X/3): HTTP NNN" so the
  recurring circuit-open lines finally name their cause.

---
AutoArticle AI v2.5.376 - Rumor-specificity gate + whitespace normalization
Release Date: September 10, 2026

FIXES (from a live ChatGPT-images RUMOR article that shipped fabricated specifics):
- RUMOR-SPECIFICITY GATE: a rumor/leak-framed topic ("reportedly", "leak",
  "upcoming", "announced"…) whose article states ≥3 specific dates AND ≥2
  hardware/price specs as fact is now DRAFTED + a mistake lesson (the live
  piece invented "August 15" / "September 2" / "September 5" demo dates plus
  "16 GB" / "50 GB" / "$20.00" — none from any verified source). Verified:
  the exact live body trips the gate (dates=3, specs=2). Honest short rumor
  pieces with ≤2 specifics are unaffected.
- WHITESPACE NORMALIZATION: collapse 2+ spaces/tabs inside text nodes only
  ("ChatGPT  2.5", "creative  generation") — tags and &-entities untouched
  (verified: &amp; preserved).
- Writer prompt: RUMOR-SPECIFICITY BAN — no invented dates/specs/pricing/event
  details on unconfirmed topics; "details remain unconfirmed" instead.

---
AutoArticle AI v2.5.375 - Anchor quality (FK-first) + pointer dedup
Release Date: September 10, 2026

FIXES (from the Barcelona 5-1 Feyenoord live article):
- NONSENSE INTERNAL-LINK ANCHORS: the writer wove 4-word title-prefix anchors
  mid-sentence producing gibberish ("...networks explore a Source Messi
  Agrees To acquisition deal abroad", "ventures explored in the List of
  Messi Owned analysis", "tracking the Brazil Squad for India tours").
  Two-part fix at the smart-link normalization chokepoint:
  * attribution/list prefixes stripped from anchors ("Source X" → "X",
    "List of X" → "X")
  * FK-FIRST: the linked post's focus keyword — a clean searchable entity
    ("messi", "brazil squad") — becomes the anchor when it is 1-3 words and
    present in the linked title; broken title fragments are no longer the
    default. Verified: Source-Messi → [messi], Brazil-Squad → [brazil squad],
    clean match-up anchors unchanged.
- DUPLICATE POINTER SENTENCES: "Full coverage via BBC Sport." shipped twice
  in one article — the fallback enforcer path hardcoded pointer variant 1
  instead of using the injection count. Both paths now use the real counter
  (For more detail… / Full coverage via… / Related coverage: …).

---
AutoArticle AI v2.5.374 - Audit cleanup: restored SOURCE_URL pairing + dead code removal
Release Date: September 10, 2026

RESTORED FEATURE:
- SOURCE-URL PAIRING at prefetch (v2.5.207 feature, silently lost in a
  refactor): the parser DISCARDED SOURCE_URL: lines instead of storing them,
  so aaai_topic_src_<agent> was always empty and cached topics never
  deep-linked their originating story. HEADLINE→URL pairs are now mapped at
  parse time and persisted (6h TTL) for the agent-runner read.

CLEANUP:
- Deleted includes/prompts-optimized.php (14K, never required — an abandoned
  alternate writer path that rotted since v2.5.155).
- Deleted dead aaai_estimate_complexity() (content-passes.php, zero callers).
- Removed write-only aaai_subject_count_<agent>_<entity> transient spam
  (incremented on every run, never read by anything — one options row per
  entity per coverage window).
- Single aaai_tables_ver version key (was version-baked per release, orphaning
  an autoload row + re-running table creation every update).
- Wired the orphaned sports-cache stale-clear into the weekly housekeeping
  cron (that table grew unbounded with no callers).
- Honest log: "[AI News] Added N" now says "Fetched N raw" (it reported fetched
  count as actually-added).

---
AutoArticle AI v2.5.373 - Queue Safety Net run-lock check
Release Date: September 10, 2026

FIX (from the Sep-9 live log — 429 "Duplicate request" storm):
- The Queue Safety Net re-fired agents whenever a Telegram-queued entry was
  10+ min old — even when a run was ALREADY executing that entry (the entry
  was old BECAUSE the run was in flight). Result: concurrent duplicate runs,
  429 duplicate-topic failures, double API spend. The safety net now checks
  the agent's run lock first: live lock (<290s) → skip; stale (>290s) →
  clear then re-fire.

---
AutoArticle AI v2.5.372 - Go-live Telegram ping + media decoration strip
Release Date: September 10, 2026

FIXES (from the Sep-9 Telegram chat review):
- TELEGRAM GO-LIVE PING: agents with review windows insert articles as DRAFTS,
  Telegram notified "Draft created" at insert, and the delayed auto-publish
  went live SILENTLY (only email followed up). The delayed-publish path now
  fires the same hook → a "✅ Published" card with the View Live link arrives
  when the article actually goes live. (Pairs with Pro v2.4.87.)
- MEDIA DECORATION STRIP on post titles: leading "Video:/Watch:/Photos:" and
  trailing "[Images]"/"(Images)"/"[Video]" source-headline artifacts no longer
  ship in H1s (live: Kia "…Two SUVs [Images]", Zelda "Video: Here's…").

PAIRS WITH PRO v2.4.87:
- Draft notifications show "⏰ Auto-publishes: <time>" when a schedule exists.
- URL-agent matcher: agent LABEL words now count (weight 2) and generic outlet
  words ("news/daily/…") are excluded — the goal.com/Liverpool cover routed
  to Tech News because Football Daily's niches lacked the bare word "football"
  while "news" in the URL path matched Tech; Football Daily now wins 2-0.

---
AutoArticle AI v2.5.371 - Keyword ladder upgrades + brand-safe desmash + entity dedupe
Release Date: September 10, 2026

FIXES (from the Sep-9 22:28 live log):
- BLACKLIST NO-OP (own bug): the v2.5.368 media-word scrub blanked the keyword
  then restored it one line later — "Images" shipped as a focus keyword. Now a
  blacklisted bare word is REBUILT from its title context ("Images" in
  "I Tested Chat GPT Images 2.5" → "Chat GPT Images"); absent from the title →
  falls through to title-derivation.
- SUBPHRASE-LADDER: when the prefix ladder fails (model skipped a title word —
  "google genome system" for "Google AI Genome System…"), every contiguous 2+
  word subphrase of the keyword is tried longest-first → "genome system"
  instead of density-blowing single "Google" (1.83% + cannibalization).
- BRAND-SAFE DESMASH: the camelCase splitter was splitting CORRECT brands —
  "ChatGPT" → "Chat GPT" in a published title. 25 known CamelCase brands are
  masked during splitting and restored after; genuine smashes still split.
- ENTITY-LINK SUBSTRING DEDUPE: "Tensor Processing Unit" and "Tensor
  Processing" no longer both consume the 2-link cap — contained/containing
  entities are skipped.

---
AutoArticle AI v2.5.370 - Maintenance loop guard + niche-gate crossover rescue
Release Date: September 9, 2026

FIXES (from the Sep-9 21:27 live log):
- MAINTENANCE REPAIR LOOP: the same article ("Arsenal sign Bruno Guimarães…")
  was "repaired" 11 times in 4 hours — a repair that never stuck was
  re-detected every sweep. After ANY successful repair the post is now exempt
  for 7 days (_aaai_maint_skip_until).
- NICHE-GATE CROSSOVER RESCUE: "Amazon Prime Video uses AI lip-syncing for
  Maxton Hall" was HARD-REJECTED as tech≠entertainment by the keyword
  classifier. Topics carrying 2+ of the agent's OWN category markers — or any
  streaming-platform marker (Prime Video/Netflix/Disney+/HBO…) for
  entertainment — are now rescued; pure cross-vertical stories stay rejected
  (Stability-AI-funding test passes).
- HEADLINE-ANYWHERE FALLBACK: a response starting HEADLINE: "⭐ Everyone…
  parsed to empty and a valid topic was lost; any HEADLINE: line anywhere in
  the raw is now salvaged (emoji/quote decoration stripped).
- ENTITY-LINK STOPWORDS: sentence openers/connectors ("According" →
  /wiki/According) and gerund concepts ("Pointing") no longer get Wikipedia
  links.

---
AutoArticle AI v2.5.369 - Evergreen last resort (dry-streak gate)
Release Date: September 9, 2026

BEHAVIOR CHANGE (owner request: no evergreen filler when real news exists):
- DRY-STREAK GATE on both evergreen fallback entry points (server no-topics/422
  and server SKIP): the FIRST dry cycle now skips publishing and waits for the
  next news cycle instead of instantly writing a template article. Only after
  TWO consecutive dry cycles (3h transient window) does the evergreen fallback
  fire — protecting against multi-hour silence during genuinely dead news
  periods. Any successful real-news cycle clears the streak.
- Pairs with SERVER v2.8.92 (topic saturation ladder — see server notes), which
  recovers real headlines in most former "all_covered" cases, so the streak
  gate rarely blocks publication at all.
- Guaranteed-topic terminal bank unchanged (final safety net after evergreen).

---
AutoArticle AI v2.5.368 - Cron-crash fix + keyword junk classes + entity-link nouns
Release Date: September 9, 2026

P0 FIXES (from the Sep-9 09:38 live log):
- HOURLY CRON CRASH: aaai_cron_learn called AAAI_Agent_Wiki::sync_to_cloud(),
  removed in an old refactor — a fatal "undefined method" crashed the handler
  EVERY HOUR. Guarded with method_exists.
- KEYWORD "[Images]": a media placeholder became the focus keyword (0
  occurrences). New junk-keyword scrub at the SEO chokepoint: strips bracket/
  placeholder junk, blacklists generic media words (images/photo/video/source/
  leak/...), drops leading attribution prefixes ("source messi" → "messi"),
  trims trailing prepositions ("launched at" → "launched").
- PREFIX-LADDER: keyword degradation now tries shorter title-present PREFIXES
  before collapsing to single words — "kingdom hearts disney" → "kingdom
  hearts" (was: "hearts", which then hit 25x density), "preity zinta batwara"
  → "preity zinta", "rohit sharma new ball" → "rohit sharma".
- "Source:" TOPIC PREFIX: the label leaked into a published H1 ("Source Messi
  Agrees…"). Attribution prefixes stripped from post titles.
- ENTITY-LINK NOUNS: generic common nouns no longer get Wikipedia concept
  links (live: "Readability", "Availability", "Architecture").
- SYNC FAILURE VISIBILITY: each account-sync failure now logs its actual
  error (the circuit-open line truncated, hiding why sync kept failing).

PAIRS WITH SERVER v2.8.91 (minimax pool weights cut 25/10 → 8/4 — both models
caused the recurring severely_under_word_count retry chains).

---
AutoArticle AI v2.5.367 - Keyword entity completion + callout failsafe
Release Date: September 9, 2026

FIXES (from the Haaland/Porto live article):
- KEYWORD ENTITY COMPLETION: "Haaland Manchester" passed the presence guard
  as a SUBSTRING of "Haaland Manchester City" — a truncated half-entity.
  aaai_keyword_presence_fix now COMPLETES the keyword when (a) the match ends
  mid-word, or (b) the next title word finishes a known multi-word entity
  (club/city continuation sets: Manchester→City/United, Real→Madrid,
  New→York, Borussia→Dortmund, etc.). "Haaland Manchester" →
  "Haaland Manchester City"; clean keywords ("Erling Haaland") untouched.
  The Maintenance sweep inherits the fix via the shared function.
- CALLOUT FAILSAFE: a mid-body "[Stat/Verdict] …" paragraph survived every
  repair shape. The late pass now strips ANY surviving raw marker to plain
  text — losing callout styling beats shipping the literal marker.
- Writer prompt: keyword rule now demands COMPLETE entity names.

---
AutoArticle AI v2.5.366 - Audit sweep: canonical interval mapper + version truth
Release Date: September 8, 2026

ROOT-CAUSE FIX (the recurring cron-spam class):
- CANONICAL INTERVAL MAPPER aaai_interval_to_recurrence(): agent intervals are
  stored in TWO formats — the free settings saves recurrence NAMES, Pro paths
  save INT MINUTES — and every wp_schedule_event call site assumed one or the
  other. Any mismatch = unregistered recurrence = wp_schedule_event fails
  SILENTLY = self-heal/guardian retry forever. All call sites now route
  through the mapper: reschedule_all_agents, the catch-up guardian (both
  branches), the class-wiki self-heal, and the velocity ladder.
- VELOCITY LADDER: minute/5/10/20/day rungs added (a 1-min agent previously
  had no rung and never throttled); ladder writes schedule via the mapper.

VERSION TRUTH: header Version + readme Stable tag were stuck at 2.5.349 while
AAAI_VERSION said 2.5.365 (admin.js said 2.4.19!) — WP update screen and
migrations keyed on a version that lied. All aligned to 2.5.366.

ALSO:
- Full-backup cron added to both self-heal lists (once cleared it never
  re-registered).

---
AutoArticle AI v2.5.365 - Title policy: H1 stays complete, only meta gets the 57-char cap
Release Date: September 8, 2026

POLICY CHANGE (owner report: main titles shipping half-finished):
- THE H1 NO LONGER GETS SERP-TRUNCATED. Google displays ~60 chars but ranks
  the FULL string — truncating the post title at 70 produced headlines that
  lost their second clause ("…Buying Hugging Face for $12.93bn" dropping the
  entire context tail). New rule: the H1 is the complete headline with only a
  120-char sanity cap (rare runaway guard, clean cut + dangling-tail strip).
- rank_math_title keeps the 57-char RankMath green-zone cap with the clean
  word-boundary cut + dangling-tail strip (unchanged — that is the line
  Google actually displays).
- Writer prompt split: H1 = complete headline (~110 chars max); SEO_TITLE is
  the separate 50-57 char condensed meta line.
- Maintenance sweep follows the same policy (no H1 truncation; meta repair
  unchanged).

---
AutoArticle AI v2.5.364 - Self-heal hardening (named culprits + hourly fallback + log throttle)
Release Date: September 8, 2026

FIX (the "Cron self-heal: re-registered 2 schedule(s)" spam — 100+ entries/15min):
- ROOT CAUSE of the persistence: the spam fired because TWO enabled agents had
  an interval value with NO registered recurrence — wp_schedule_event fails
  SILENTLY for unknown names, so the admin self-heal + the catch-up guardian
  re-attempted forever without ever naming the culprit. v2.5.361 registered
  the missing aaai_every_minute/5_minutes recurrences; this build makes the
  system self-diagnosing for ANY future bad value:
  * Self-heal + guardian: invalid recurrence now logs WHICH agent + WHICH
    interval, and falls back to aaai_every_hour so the agent actually fires.
  * aaai_reschedule_all_agents: same silent-failure guard.
  * LOG THROTTLE: self-heal and guardian summary lines gate to once/15 min.

---
AutoArticle AI v2.5.363 - Orphan-fragment scrub + image pipeline + Maintenance Phase 2
Release Date: September 8, 2026

FIXES/FEATURES (pairs with server v2.8.86):
- ORPHAN-FRAGMENT SCRUB: RSS headlines fed to the writer as CURRENT NEWS
  CONTEXT sometimes leaked INTO the prose as standalone fragments ("The
  Anthropic NVIDIA Lambda $35B cloud partnership and the AWS and NVIDIA Lock
  on GPU supply."). Any paragraph whose significant-word overlap with a
  supplied headline is >=75% is now removed at the late chokepoint (post-
  humanizer). Verified: the incident sentence drops; normal prose survives.
- IMAGE PIPELINE: the set-images cron early-returned when only the Unsplash
  key was missing even though the PEXELS fallback works alone — posts shipped
  thumbnail-less. Now continues when EITHER key exists; straggler batch 5→15.
- MAINTENANCE MODE PHASE 2: posts older than 45 days whose meta title misses
  the focus keyword (or is under 40 chars) get ONE deepseek rewrite of meta
  title + description through the normal pipeline. Capped 3/run, 10/day,
  one-shot per post (_aaai_maint_llm_done), counted as llm_meta in stats.
- Removed the dead aaai_cron_set_images() duplicate in admin/settings.php
  (referenced a class that exists nowhere).

---
AutoArticle AI v2.5.362 - Unicode entity tags + sports outlet blacklist
Release Date: September 7, 2026

FIXES (from the Real Madrid Courtois-successor live article):
- TRUNCATED ACCENTED ENTITIES: the capitalized-entity regex was ASCII-only
  ([a-zA-Z0-9]) and cut at the first accented char — "Santiago Bernabéu"
  shipped as the tag "Santiago Bernab". Now \p{L}\p{N} with /u keeps full
  names in any script.
- "Mundo Deportivo" tagged: outlets cited in prose leaked into tags. Sports
  outlets added to the source blacklist (mundo deportivo, gazzetta, l'équipe,
  corriere dello sport, sky sports, the athletic) — deliberately narrow
  entries so Marquez / Athletic Bilbao survive.
- "Competition" tagged: generic football nouns (competition, campaign,
  fixture, clash, tie) added to the vague list.

PAIRS WITH SERVER v2.8.81 (grok live-search tweet scouting — real-time X
data via cheap grok-4.3 instead of Sonar's 1h-lagged news echoes).

---
AutoArticle AI v2.5.361 - Cron self-heal spam fix + evergreen write-flag + keyword sync
Release Date: September 7, 2026

FIXES (from the 19:16 live log):
- CRON SELF-HEAL SPAM (root cause): the interval dropdown offers
  aaai_every_minute / aaai_every_5_minutes but the cron_schedules filter NEVER
  registered them — agents configured at those intervals could never be
  scheduled (wp_schedule_event fails silently for unknown recurrence), so the
  admin self-heal and catch-up guardian re-attempted forever ("re-registered 2
  schedule(s)" every ~20-40s). Both intervals are now registered.
- EVERGREEN WRITE FLAG: server-selected guide topics ("Complete LEGO Super
  Mario 2027 Wave Buying Guide") skipped the local fact-check but carried no
  evergreen_topic payload flag — the server's 2027 auto-force re-enabled
  Hyper-Accuracy on the write call and 422'd it as "old event". Guide-pattern
  topics now set the flag so HA is skipped at write time too.
- KEYWORD SYNC POST-SEO: the SEO chokepoint degrades absent keywords
  ("ronaldo mocked after loss" → "ronaldo") but the later density audit still
  measured the undegraded phrase (bogus "too LOW" warnings). The final stored
  keyword is re-read after aaai_set_rankmath_meta so every later pass agrees.

REQUIRES Pro v2.4.82 (bulk_control resume used the hook name as the cron
recurrence — silently failed; now uses the agent's own interval).
PAIRS WITH SERVER v2.8.79 (third-chance topic metadata retry).

---
AutoArticle AI v2.5.360 - The learning loop actually learns (instructional mistake lessons + keyword repair in the sweep)
Release Date: September 7, 2026

THE PROBLEM (evidence: only 2 mistake lessons existed across months):
- Lessons were pushed as raw LOG LINES ("[Truncation Gate] Article has 2
  truncated paragraph(s)") — diagnostics the writer can't act on.
- Counts inside each summary defeated the server's exact-match dedup AND the
  per-agent 6h throttle (2 vs 3 paragraphs = two lessons + two throttles).
- Mistakes never expired — stale advice about fixed defects kept injecting.
- Requires plugin >= 2.5.349 for the blocking push (older builds died
  silently — lessons never reached the server at all).

FIXES (pairs with server v2.8.78):
- INSTRUCTIONAL LESSONS: new aaai_mistake_directive() maps every failure
  class (truncation, placeholder, word_count, text_corruption, stale_date,
  keyword, tags, unattributed_hedge, internal_links, faq_structure,
  humanize_score, duplication, marker_leak) to a STABLE class key + an
  actionable writer directive ("End every section with a COMPLETE
  sentence…"). Class key throttles and dedups; the directive teaches.
- 14-DAY LESSON LIFECYCLE (server): stale mistakes stop injecting; a
  recurring failure re-pushes fresh. Injection always reflects CURRENT
  failure modes.
- KEYWORD PRESENCE REPAIR in Maintenance Mode: articles whose focus keyword
  never verbatim-occurred in the headline ("Arsenal vs chelsea" on the prose
  headline → 0.00 density, every RankMath check red) are retroactively
  degraded via the shared ladder (vs-keyword → first team present; else
  longest matching word). Counts as keyword_presence in sweep stats.

---
AutoArticle AI v2.5.359 - Keyword presence guard (keyword must occur in the headline)
Release Date: September 7, 2026

FIX (from "Arsenal Edge Past Chelsea 2-1 in Vintage Derby Win" scoring
0.00 keyword density / 0 occurrences across every RankMath check):
- The model followed the sports keyword rule and chose "Arsenal vs chelsea",
  but the headline is prose with no "vs" — the phrase never occurs, so URL/
  content/heading/density checks all red out. NEW presence guard at the SEO
  chokepoint: if the keyword phrase doesn't appear verbatim in the post
  title, degrade in order — (a) "X vs Y" keywords fall back to the first
  side that DOES appear ("Arsenal"); (b) other keywords fall back to their
  longest word present in the title; (c) otherwise keep. Logged.
- Sports FOCUS_KEYWORD prompt rule updated: keyword must appear VERBATIM in
  the H1 — "X vs Y" only when the headline says "X vs Y"; prose headlines
  ("Arsenal Edge Past Chelsea…") take the first team alone.

---
AutoArticle AI v2.5.358 - Tag presence guard + question-word anchors + bare callout markers
Release Date: September 7, 2026

FIXES (from the RAV4/Arsenal/Maruti/streaming live articles):
- TAG PRESENCE GUARD: a tag that does not literally appear in the article
  (title or body) is a writer hallucination and is now dropped with a log
  line. Kills cross-domain tags ("Royal Enfield", "Motorcycle", "upcoming
  bikes" on a Toyota RAV4 article) and glued fragments ("Goals Unfolded
  Kai", "Led Here Maruti").
- QUESTION-WORD ANCHORS: natural anchors were the first 4 title words, so
  "How Dune Part Three…" titles produced unreadable mid-sentence prose
  ("Fans tracking How Dune Part Three handles scale"). Leading How/Why/
  What/When/Who/Is/Are/The/A/An words are stripped from every anchor at
  the normalization chokepoint (covers all link sources).
- BARE CALLOUT MARKERS (Case 5): "[Stat/Verdict]" sitting OUTSIDE any <p>
  tag (a bare text node between paragraphs) shipped as literal text because
  every earlier repair case anchors on <p>. Now promotes the following
  paragraph into the callout div; trailing bare markers are dropped.
- Vague-tag additions: based, readers, unfolded, led, coming, upcoming, here.

---
AutoArticle AI v2.5.357 - Hedge ban + relevance floor
Release Date: September 7, 2026

FIXES (closes the Doomsday-article audit):
- NO UNATTRIBUTED HEDGES: the writer prompt bans "reportedly" / "is said to" /
  "appears to have" unless the sentence names a specific outlet or the fact
  came from VERIFIED FACTS. New [Hedge Lint]: >=3 hedges with 0 outbound
  sources logs a quality warning per article.
- RELATED-ARTICLES RELEVANCE FLOOR: zero-word-overlap candidates (a Stranger
  Things link on a Doomsday article) are dropped from the fallback section;
  same-category alone is not enough to recommend.

---
AutoArticle AI v2.5.356 - Date-freshness gate + late callout repair
Release Date: September 7, 2026

FIXES (from the Avengers: Doomsday incident — "arrives in theatres on May 1,
2026" published in September, and a raw "[Verdict] …" tail):
- DATE-FRESHNESS GATE: future-phrased verbs ("arrives", "scheduled for",
  "hits theatres") within 80 chars of a date older than 21 days DRAFT the
  article instead of publishing, log the reason, and push a mistake lesson.
  Evergreen topics skip server Hyper-Accuracy, so nothing else checked
  embedded dates. Pairs with server v2.8.77 (stale-date nudge retry).
- LATE CALLOUT REPAIR: aaai_repair_callout_marker() runs again AFTER FAQ
  assembly — markers appended late no longer ship as literal text.
- Writer prompt: explicit DATE FRESHNESS rule (today-anchored, past dates
  must take past tense).

---
AutoArticle AI v2.5.355 - ARTICLE MAINTENANCE MODE (autonomous library sweep)
Release Date: September 6, 2026

FEATURE: new includes/maintenance.php — a 10-min background sweep that walks
the entire published library (cursor-based, ~15 posts/batch) and repairs
structural/SEO defects with the SAME deterministic machinery the writer
pipeline uses (zero AI cost): title SERP optimizer + dangling-tail strip,
meta title/description rebuilds, missing-space + measurement repairs, glued
FAQ split, FAQPage JSON-LD, INTERNAL-LINK BACKFILL (smart links + Related
Articles fallback), tag extraction + vocabulary canonicalization, focus-
keyword derivation. Safety: skips posts modified <24h, per-post
_aaai_maint_backup meta, every repair logged, stats aggregated in
aaai_maint_stats. Dashboard panel with live stats; pairs with Pro v2.4.81
(/maintenance + CEO chat control). Periodically runs
delete_expired_transients() so aaai_il_* option rows stop accumulating.

---
AutoArticle AI v2.5.354 - Keyword-to-coverage end-to-end (word count + focus keyword honored)
Release Date: September 6, 2026

FIXES (pairs with Pro v2.4.80 + server v2.8.75):
- "cover ipl final, 1500 words" now honors BOTH through the whole chain —
  previously the server payload carried word_count/focus_keyword but the
  plugin dropped them at the queue, so every order wrote at agent defaults.
- New filters applied in aaai_run_agent: aaai_agent_custom_word_count
  (>=600 floor) and aaai_agent_custom_focus_keyword (overrides the derived
  keyword, logged).

---
AutoArticle AI v2.5.353 - FAQ glue on ALL paths + qualifier repair + tag junk filters
Release Date: September 6, 2026

FIXES (from the NVIDIA/HuggingFace live article):
- FAQ GLUE: aaai_split_glued_faq_qa() now runs on the FAQ region for ALL
  paths (Pass 6 in the format block) — the main writer's glued QAs
  ("…happens. Will the platform remain open? …") previously never passed
  through the splitter (completion path only).
- FACT-QUALIFIER REPAIR: "$12.93 billion unconfirmed" → "$12.93 billion,
  per reports"; "deal value unconfirmed" → "deal value remains unreported".
- TAG JUNK: adverb tail filter (>=8 chars ending -ly), qualifier/generic
  blacklist additions (crucially, decade, unconfirmed, open, promise…),
  20+ tech outlets in the source blacklist ("Thenextweb" leak), and the
  8-tag cap moved AFTER dedup so real entities win the slots.
- DOUBLE-COLON H2 SIMPLIFIER: "Entity: Label: Subtitle" → drops the prefix.
- LATE missing-space chokepoint before internal-link injection.

---
AutoArticle AI v2.5.352 - Title truncation artifacts + sports keyword quality
Release Date: September 6, 2026

FIXES (from "…$12.93bn With Open" + "Hugging face: …for" meta titles):
- DANGLING-TAIL STRIPPER: iterative trailing function-word strip after ANY
  truncation, plus a continuation-pair rule ("…With Open" → pops both).
  Applied to the H1 optimizer and BOTH meta-title paths.
- NO-DUPLICATION: the "Keyword: " prefix is no longer prepended when the
  keyword appears ANYWHERE in the title (was first-3-words only).
- MATCH-ARTICLE KEYWORD OVERRIDE: title contains "X vs Y" → keyword becomes
  "X vs Y" unless the model already used it.
- GENERIC-KEYWORD REBUILD: all-generic keywords ("cricket series") are
  rebuilt as first title entity + strongest generic word ("Gill series"),
  with headline-verb protection ("Gill Slams" never becomes a keyword).
- Writer prompt: sports FOCUS_KEYWORD rule (TeamA vs TeamB or Player +
  achievement; never two team-mates, never bare generic events).

---
AutoArticle AI v2.5.351 - FAQ list/strong-question passes (v2.8.74 pairs)
Release Date: September 6, 2026

FIXES:
- LIST-BASED FAQ CONVERTER (Pass 4): <ul>/<ol> FAQs with bold questions
  convert to <h3>Q</h3><p>A</p> — previously shipped as bullet lists with
  no TOC entries and no FAQ JSON-LD.
- STRONG-ONLY QUESTIONS (Pass 5): "<p><strong>What about warranty</strong></p>"
  (bold question WITHOUT "?") now upgrades to an H3 and merges with the
  following answer paragraph. FAQ region only.

---
AutoArticle AI v2.5.350 - Internal links: writer finally gets the URLs + tag vocabulary
Release Date: September 6, 2026

FIXES (root causes of "internal links not used"):
- THE WRITE PROMPT NEVER HAD THE URLS: internal-link brief showed anchor
  bullets only — the writer could NEVER weave a real link; everything
  relied on the post-hoc injector. Now emits 4 exact <a href> tags.
- TAG-BOOSTED SHAPE BUG: v2.8.28 entity links used a 'title' key with no
  anchor/natural_anchor — score-20 top-priority links were dead weight and
  the blank-guard skipped the whole Related Articles section. Fixed to the
  canonical shape.
- NORMALIZATION CHOKEPOINT: one pass canonicalizes EVERY smart-link source
  (legacy/cached odd shapes) after all merges; unusable entries drop.
- TAG VOCABULARY CACHE (6h): extracted tags canonicalize to the site's
  existing spellings ("ipl"/"Ipl" → "IPL"), most-used tags float to the
  front of the 8-tag cut, and the writer prompt receives the top-15 entity
  spellings for consistency.

---
AutoArticle AI v2.5.349 - Mistake-lesson push is blocking (was dying silently)
Release Date: September 3, 2026

FIX: the quality-gate → brain_lessons push used blocking=false
(fire-and-forget) and died before completing — mistake lessons never
reached the server, so the writer prompt's "RECENT MISTAKES — DO NOT
REPEAT" injection stayed empty. Now blocking=true with a 3s timeout and a
"[Mistake Lesson] Pushed:" log line.

---
AutoArticle AI v2.5.348 - Bullet repair + garbage-fragment scrub
Release Date: September 3, 2026

FIXES: incomplete bullets inside <li> tags are trimmed to the last complete
sentence (paragraph repair didn't cover lists); metadata-leak fragments
('"Video's Fallout" s Fallout…') are scrubbed.

---
AutoArticle AI v2.5.347 - Measurement-merge repair (miles581 → 581 miles)
Release Date: September 3, 2026

FIX: writer merged measurement units into digits ("miles581" from a "581-Mile
Range" headline). Common units are now auto-repaired with a space instead of
drafting the article.

---
AutoArticle AI v2.5.345 - Missing-space fix + callout repair cases 3/4
Release Date: September 3, 2026

FIXES: general "word.Word" → "word. Word" glued-sentence repair (was
years-only); "[Verdict]" standalone-label and bare-line shapes now convert
to proper callout blocks instead of leaking as literal text.

---
AutoArticle AI v2.5.343 - PRIORITY BYPASS (queued orders run immediately)
Release Date: September 3, 2026

FIX: a queued Telegram/X-feed topic sat behind the agent lock until the next
hourly cycle. Queue entry present → the cron closure now clears the lock and
runs the custom topic immediately (✅ taps execute in ~3 minutes).
Pairs with Pro v2.4.77.

---
AutoArticle AI v2.5.342 - Lock-aware queue consumption (Cover <url> orders no longer silently lost)
Release Date: September 1, 2026

FIX (from "Cover <videocardz URL>" producing an unrelated article):
- The queued URL/topic filters CONSUMED the order at filter time, but the
  run's lock check ran AFTER them — a busy agent ate the queued link and
  wrote a regular scheduled topic instead. The cron closure now peeks the
  run lock BEFORE applying the filters: busy → skip the whole cycle without
  consuming; the safety net re-fires within 10 min when the lock frees.
- Same flaw fixed earlier for topics (aaai_pro_tg_filter_custom_topic).

PAIRS WITH PRO v2.4.75 (niche-match enrichment + source_url passthrough)
and SERVER v2.8.61 (cover_url CEO tool).

---
AutoArticle AI v2.5.341 - evergreen_topic payload flag + guaranteed-bank anti-repeat
Release Date: August 31, 2026

FIXES (pairs with server v2.8.60):
- EVERGREEN FLAG: guaranteed-bank and evergreen-swap topics now send
  evergreen_topic=1 to the server, which skips Hyper-Accuracy ENTIRELY for
  them. Root cause of "Topic rejected by Hyper-Accuracy mode" on guaranteed
  topics: the server's v2.5.156 auto-force triggers on "Cricket/World Cup/
  2026" in the topic — and the guaranteed bank's own templates contain
  "…in World Cricket" — so the force re-enabled HA even when the plugin
  sent hyper_accuracy=false.
- GUARANTEED ANTI-REPEAT: the bank picked "Cultural Impact: Mission
  Impossible 8" twice back-to-back (rejected topics never entered
  used_topics). Last 3 guaranteed topics per agent are now tracked;
  re-rolls up to 5x on a match.

---
AutoArticle AI v2.5.340 - Guardian fire-storm fix + blank Related Articles links
Release Date: August 31, 2026

FIXES (from the 18:38-19:06 Aug 31 log):
- GUARDIAN FIRE STORM: the catch-up guardian's stale-lock cutoff (120s) was
  SHORTER than a real run (2-5 min) — it cleared the lock of ACTIVE runs and
  fired concurrent duplicates, causing the "Previous run still active" spam,
  429 "Duplicate request detected" topic failures, and double API spend.
  Cutoff now 290s (matches agent-runner's own stale cutoff exactly).
- BLANK RELATED ARTICLES LINKS: memory rows from untitled/failed posts have
  empty anchor + natural_anchor, producing <a href="…"></a> — readers saw
  blank entries in the Related Articles section. Blank candidates are now
  skipped; the section is omitted entirely if nothing clickable remains.

KNOWN EDGE (self-heals): Hyper-Accuracy agents can still 422 a terminal
guaranteed topic as "old event" — the server applies HA on the write call by
agent config, not just the payload flag. The next hourly cycle recovers.

---
AutoArticle AI v2.5.339 - Guaranteed-topic terminal fallback (duplicate exhaustion no longer kills the cycle)
Release Date: August 31, 2026

FIX (from "agents not posting timely"):
- DUPLICATE EXHAUSTION Bailed THE WHOLE CYCLE: when all topic retries
  exhausted on near-duplicate rejections (happened to India Ent, Tech, AI in
  one hour), the run returned an error and the agent posted NOTHING that
  hour. Now the guaranteed-topic bank (fresh template×entity×concept combos,
  avoid-list aware, evergreen-flagged so hyper-accuracy/recency gates skip)
  gets ONE terminal chance before bailing. If the write still gets rejected,
  the cycle fails as before — but the combos are analytically distinct, so
  this usually lands and the agent posts on schedule.

PAIRS WITH SERVER v2.8.54: the topic format-nudge retry now switches to
deepseek-v4-flash (retrying the same gemini model that just returned empty
kept failing — the root of the "model returned metadata" 422 storms).

---
AutoArticle AI v2.5.338 - Evergreen angle refresh (ban the burnt-out headline formats)
Release Date: August 30, 2026

FIX (from dedup-exhaustion cycles across agents):
- EVERGREEN HEADLINE VARIETY: the evergreen fallback prompt's "Good
  alternatives" menu ([Entity]: A Tactical Breakdown / X and the Art of Y /
  Tracing X's Evolution / The Anatomy of X / Decoding X / Unpacking X)
  became the model's default rotation — the site shipped "3 Idiots: A
  Shot-by-Shot Breakdown", "Inception: A Shot-by-Shot Breakdown", "Virat
  Kohli and the Art of Mastering Run Chases", "Pep Guardiola and the
  Tactical Anatomy of Inverted Fullbacks", "Claude and the Anatomy of
  Context Window Limits", "USB-C: A Retrospective Journey" back to back,
  all hitting the dedup gate and exhausting retries. Those formats are now
  EXPLICITLY BANNED and replaced with a fresh 12-opener menu (Explained for
  [audience], [Number] Mistakes People Make With X, Common Myths About X,
  The Real Difference Between X and Y, The Complete Checklist for [Use
  Case], What the Data Says About X…).

---
AutoArticle AI v2.5.337 - Competitor brand scrub + [Verdict] marker repair
Release Date: August 30, 2026

FIXES (from the Tom's Guide Claude multi-persona article):
- COMPETITOR BRAND SCRUB: a non-exclusive article sourced from a Tier-3
  competitor named the brand 6x in body + title + credit ("Tom's Guide").
  New scrub: brand + possessive variants in body text nodes → "the outlet"
  ("The outlet's writer"), sentence-start capitalized, doubled-article
  cleanup ("the the outlet" → "the outlet"); title brand → "Tech Outlet";
  "Originally reported by X." competitor credit lines removed. Exclusive
  articles and Tier-1/2 sources untouched. Verified: possessive preserved,
  URLs unmangled, sentence casing correct.
- GUARANTEED-OUTBOUND GATE: the no-external-links credit pass now refuses
  competitor sources on non-exclusive articles (it ran AFTER the scrub and
  would re-add the credit).
- [Verdict] MARKER REPAIR: the callout repair now also converts leaked
  "[Verdict]" labels (was "[Stat/Verdict]" only) into the proper callout div.

NOTE: the article also had missing-subject prose ("because accepted",
"proves can coordinate") — the writer model dropped the brand name while
avoiding repetition. The brand scrub replaces rather than deletes, which
removes the incentive; grammar itself is a model-quality issue.

---
AutoArticle AI v2.5.336 - God Mode duplicate menu entry removed
Release Date: August 30, 2026

FIX:
- GOD MODE SHOWED TWICE in the WP admin sidebar: two admin_menu hooks
  registered the same 'aaai-god-mode' slug (scheduler.php "⚡ God Mode" +
  god-mode.php "God Mode") and WordPress does not dedupe add_submenu_page.
  Removed the redundant registration in god-mode.php — scheduler.php remains
  the single menu registrar, consistent with every other page.

---
AutoArticle AI v2.5.335 - Callout marker repair + varied outbound pointer sentences
Release Date: August 29, 2026

FIXES (from the Messi 7-1 Inter Miami article):
- CALLOUT MARKER REPAIR: the writer shipped the literal "[Stat/Verdict]"
  template label as a plain final paragraph instead of converting it to the
  aaai-callout div. Now repaired pre-gate: the leaked marker becomes
  <div class="aaai-callout"><strong>content</strong></div>; bare-label
  paragraphs are dropped; markers inside existing callouts are stripped.
  Verified 4 cases.
- POINTER SENTENCE VARIETY: "For more detail, see BBC Sport." appeared twice
  in one article (both external links used the identical sentence). Pointer
  sentences now vary by occurrence: "For more detail, see X." → "Full
  coverage via X." → "Related coverage: X."

NOTE: this article also showed glued FAQ pairs — ALREADY FIXED in v2.5.334
(N-question FAQ splitter). Upload 2.5.332+ if you haven't; 2.5.335 is
cumulative.

---
AutoArticle AI v2.5.334 - N-question FAQ split + keyword action-verb trim
Release Date: August 28, 2026

FIXES (from the Miami Vice '85 Danny Ramirez article):
- GLUED FAQ RUN-ON BLOCKS: the FAQ shipped as one paragraph with 4 QAs glued
  ("Who stars…? Michael B. Jordan… When does…? Principal photography…") because
  the old splitter required the paragraph to START with an answer sentence —
  a question-first paragraph never matched. New N-question splitter: locates
  EVERY short wh-question (≤15 words) in the paragraph, slices answers between
  them, rebuilds as h3+p pairs. Verified against the exact incident text —
  5 clean QAs extracted. Legacy single-split + truncated-question paths kept.
- KEYWORD ACTION-VERB TRIM: "ramirez joins" (entity+verb) survived because the
  trailing-filler list had no action verbs and the trim couldn't reduce to one
  word. Added joins/lands/leads/stars/signs/confirms/drops/reveals/hits/tops/
  wins/beats/debuts/launches/returns/opens/arrives/gains/surges… and allowed
  trim to a single word: "ramirez joins" → "ramirez", "danny ramirez joins" →
  "danny ramirez" (verified).

---
AutoArticle AI v2.5.333 - Generation Gate (stale-generation launch coverage can never publish)
Release Date: August 27, 2026

FIXES (from the M6 Mac mini incident):
- GENERATION GATE: the M6 Mac mini launched but the article shipped M4-era
  hallucinated specs ($499/$1,399 configs, "rumored M4 Ultra") from a recycled
  9to5mac source — while the site's OWN recent coverage said "Mac Mini M6".
  New gate: extracts generation tokens (M-series, iPhone, Galaxy S, Pixel,
  Snapdragon, RTX, Ryzen, PlayStation) from the article body and compares the
  MAX per family against (a) the topic's own tokens and (b) recent 30-day site
  post titles for the same product family. Body max older than either truth →
  draft with "[Generation Gate]" log. A current launch article always mentions
  the current generation at least once, so legitimate "upgrading from M1"
  comparisons never false-positive (verified with 4 test cases).

---
AutoArticle AI v2.5.332 - Truncation salvage + heading fallback + Hyundai Palisade keyword fix
Release Date: August 27, 2026

FIXES (from 16:14 log — Hyundai Palisade drafted despite repair):
- PARAGRAPH SALVAGE: single-segment truncated paragraphs ("This is valid. This
  is truncated without period") are now trimmed to the last complete sentence
  instead of dropping the whole paragraph. Previously the repair dropped the
  entire <p>, losing good content and still leaving 1 truncated paragraph
  that forced a draft. Now salvages with sentence-boundary cut.
- HEADING FALLBACK: truncated question headings ("Who is writing and illust")
  now have a deterministic fallback (drop last fragment word, add "?") when
  the cheap model rewrite is skipped (no hub_key) or fails — previously the
  fallback was "do nothing and still draft".
- HYUNDAI PALISADE KEYWORD: 8-word keyword re-derive fallback now deprioritizes
  descriptive modifiers (Inspired, Headliner, Gains, High, Roof, Rolls, Royce)
  — "inspired headliner" (5x in body, 0.63% but generic) no longer beats the
  proper entity "Hyundai Palisade". Entity stopwords expanded; title-position
  weighting ensures the product name at the start of the title wins.

---
AutoArticle AI v2.5.331 - Model-proof structural lint + density-aware keyword shortening + external link scrub
Release Date: August 27, 2026

FIXES:
- STRUCTURAL LINT (model-proof): single ordered chokepoint before Save Gate —
  paragraph truncation auto-repair (v2.5.329) → splice/dangling heading repair
  (v2.5.331) → FAQ validation → corruption scan. Unrepairable heading cuts
  and splice markers get ONE cheap continuation-call rewrite; still-broken
  articles draft with a [STRUCT] score line (model + pass rate) sent to server
  telemetry for the model canary.
- DENSITY-AWARE KEYWORD SHORTENING: the prefix fallback now ALSO fires when
  density < 0.5% (was only count < 2). Live incident: "alia bhatt alpha" appeared
  2x in 779 words = 0.26% — too thin for RankMath, but neither fallback fired.
  Now drops trailing words until the shortest prefix landing in the 0.5-1.2%
  healthy band is found ("alia bhatt alpha" → "alia bhatt"). Re-weaves the new
  keyword into the opening sentence if missing, and re-saves RankMath meta.
- EXTERNAL LINK SCRUB: writer-emitted external links outside the tier pipeline
  are now stripped (unwrap, keep text) — only tier-approved ext links + Wikipedia
  entity links survive. Guarantees the 3-tier spec regardless of model output.
- POSSESSIVE TITLE RULE: writer prompt now requires possessives when a person
  is paired with their film/show — "Alia Bhatt's Alpha", never "Alia Bhatt Alpha".
- VERSION.txt SYNC: 2.5.328-330 entries appended — PHP constant and file no longer drift.

---
AutoArticle AI v2.5.330 - Density reducer safety-first rewrite (heading shield + brand consumption)
Release Date: August 27, 2026

FIXES (from TVS Jupiter Dual-Tone article):
- DENSITY REDUCER CORRUPTION: keyword-density replacement replaced "Jupiter"
  while leaving the adjacent brand "TVS" untouched → "TVS the car", "TVS this",
  "TVS it" through headings AND body. New policy: headings are placeholder-
  shielded; a keyword preceded by a capitalized brand word is replaced as the
  FULL phrase ("TVS Jupiter" → "the model"); "the car" removed (wrong for
  scooters); possessive compounds ("Jupiter owners/sales") are kept; a
  corruption tripwire reverts the entire densification if "Brand the model"
  would survive. Logged.
- FAQ VALIDATOR HARDENED: plain Q:/A: paragraph pairs (FAQ completion output
  that never became h3/p) are now validated; question needs ? or ≥5 words;
  answer needs ≥15 chars AND ≥3 words AND terminal punctuation; duplicate
  paragraph QA pairs removed; stray SEO_/RANKMATH_ marker paragraphs stripped.

---
AutoArticle AI v2.5.329 - Keyword possessive fix + truncation auto-repair + entity-link guard
Release Date: August 27, 2026

FIXES:
- POSSESSIVE CONSISTENCY: keyword extraction now strips "'s" together with the
  apostrophe ("Chase's" → "chase", not "chases") so the keyword normalizes
  identically to the density counter — fixes "chases st" vs body "Chase's St"
  0-match live incident.
- TRAILING-FILLER TRIM: keywords ending with verb filler ("nismo z finally
  gets" → "nismo z") are trimmed at extraction; the prefix still matches the
  body the writer wove.
- KEYWORD PREFIX FALLBACK: multi-word keywords that match 0x (cannibalization-
  extended "ravindra jadeja india" whose "india" never follows verbatim) now
  fall back to the longest matching prefix (≥2x) before the destructive auto-
  derive path.
- TRUNCATION AUTO-REPAIR: minimax pool ends 1-3 segments mid-sentence;
  paragraphs are trimmed to the last complete sentence instead of drafting;
  soft lowercase line-wraps are kept; garbage-only paragraphs are dropped;
  existing Truncation Gate still drafts anything unrepairable.
- WIKIPEDIA CONTEXT GUARD: wrong-entity pages ("Blue Night" → "Blue Night
  Network", "Box Office (album)", "Day Collection" → "Data collection") are
  now rejected when title extra words / parenthetical don't appear in the
  article context.
- REFERENCE-TIER RELEVANCE GATE: plugin-side tier sort now filters reference
  links by topic-word overlap (same rule as prompt filter) — fixes "ArXiv AI"
  + "OpenAI Blog" linked inside Rajinikanth/Venice articles.

---
AutoArticle AI v2.5.328 - Meta description / keyword closing-line fixes
Release Date: August 27, 2026

FIXES (from Shubman Gill Pujara article):
- META DESCRIPTION SCRUB: writer-prefixed "Shubman gill pujara. Cheteshwar…"
  is stripped and re-capitalized; keyword-only descriptions regenerate from
  body text; applies to og/twitter descriptions too. Tested exact incident.
- CASE-RESTORED CLOSING: "Stay tuned for more on X" is now a whole-body check
  (was last-paragraph only → fired on every article) with title-cased keyword
  via aaai_kw_restore_case() and a natural closer; the banned filler phrase
  is gone.
- KEYWORD SELECTION: prompt prefers ENTITY+TOPIC ("Gill captaincy" over
  "Shubman Gill Pujara") and requires natural META_DESCRIPTION weaving.

---
AutoArticle AI v2.5.327 - Niche Gate hard category + writer reference filter + FK word cap + currency stopwords
Release Date: August 26, 2026

FIXES:
- NICHE GATE HARD CATEGORY: when the topic's detected category differs from
  the agent's category AND they're not adjacent (tech↔smartphone, gaming↔entertainment),
  the topic is rejected — the AI relevance verdict can no longer override a
  cross-vertical mismatch. Live incident: "Stability AI's $76M Funding Round"
  (tech) passed the entertainment agent's gate because "Universal Music" is
  entertainment-adjacent.
- WRITER REFERENCE FILTER: the writer prompt now only includes external
  reference sites whose name has ≥1 word (≥4 chars) overlapping with the
  article's topic. Prevents "OpenAI Blog" from being cited in a Bollywood
  article (live incident). Wikipedia/IMDB always pass (universal references).
- FK WORD-COUNT CAP: keywords with >5 words are rejected and re-derived
  from topic entities. Live incident: "polestar wants answers after being
  banned in the" (9 words) produced "Stay tuned for more on polestar wants
  answers after being banned in the."
- FK TRAILING STOPWORD TRIM: keywords ending with "the", "in", "rs",
  "crore", "lakh" etc. are trimmed. Live incident: "Ranveer s rs" (the "rs"
  is a currency abbreviation, not an entity).
- FK CURRENCY STOPWORDS: rs, crore, lakh, inr, usd added to the FK stopword
  list (server + client) so they can never appear as keyword words.

---
AutoArticle AI v2.5.326 - FAQ quality validator + proper noun title-case + broadened FAQ glue fix
Release Date: August 26, 2026

FIXES (from MG Hector Tomahawk article):
- FAQ QUALITY VALIDATOR: removes FAQ entries where the question is a fragment
  (<4 words, no "?") or the answer is a stub (<15 chars). The MG article had
  "What is the starting / The starting" — both Q and A truncated garbage from
  the FAQ completion model. Now logged and removed.
- PROPER NOUN TITLE-CASE: "hector tomahawk" → "Hector Tomahawk" in H2 heading
  prepends. Multi-word keywords with no stopwords are title-cased (product/
  place names). "Hector tomahawk:" was inconsistent capitalization.
- BROADENED FAQ GLUE FIX: the truncated-question pattern now catches any
  wh-word fragment ("What is the", "How much does the", "When was the")
  followed by any answer — not just the specific "The device" case.

---
AutoArticle AI v2.5.325 - Show the ACTUAL writer model (pool override) in WP + Telegram
Release Date: August 26, 2026

FIX:
- _aaai_write_model post meta and Telegram notifications now record the model
  the SERVER actually used (pool override), not the agent's stale configured
  model. When the server's plan pool rotates to minimax-m3, WP shows
  "minimax-m3" — not the gpt-5.4-nano that was configured before the
  no-choice UI. The plugin also logs when the server overrides the model:
  "[Model] Server pool override: requested X → actual Y".

---
AutoArticle AI v2.5.324 - Objective AI-detection scoring (aaai_estimate_ai_score)
Release Date: August 26, 2026

FEATURE:
- aaai_estimate_ai_score() — objective AI-detection scoring function that
  analyzes 7 measurable signals (no AI call needed):
  1. Banned AI phrases (delve, tapestry, furthermore…)
  2. Sentence length variance (uniform = AI-like)
  3. Transition word overuse
  4. Vocabulary diversity (type-token ratio)
  5. First-person pronoun presence (human signal)
  6. Paragraph length uniformity
  7. Contraction usage (human signal)
  Returns { total: 0-100, signals: [] }. Pro humanizer metabox now shows
  real scores instead of a broken reference.

---
AutoArticle AI v2.5.323 - Save Gate (last-line defense before wp_insert_post)
Release Date: August 26, 2026

FIXES (from dashboard audit — 15 garbage entries in one day):
- TITLE GARBAGE GATE: rejects titles that are internal metadata leaks
  ("deepseek-v4-flash Generated Content", "AI Content (...)", "HEADLINE:",
  "DOMAIN:", "MATCH STATUS:", provider-prefixed strings).
- TITLE LENGTH GATE: rejects titles < 15 chars or ending with a
  preposition/article ("...Banned In The").
- NEAR-DUPLICATE GATE: checks title_hash against posts created in the last
  60 minutes — prevents the same topic being written twice by concurrent
  runs (the Anil Kapoor ×2 incident).
- STUB CONTENT GATE: rejects articles with < 100 real words — the 9-word,
  12-word, 20-word, and 33-word garbage stubs can never be saved again.

---
AutoArticle AI v2.5.322 - Paragraph dedup (Anthropic article outline leak) + Investors keyword
Release Date: August 26, 2026

FIXES (from the Anthropic $30tn IPO article):
- OUTLINE LEAK DUPLICATION: the writer output the same 4-paragraph content
  block twice — once between the intro/TOC and the first H2 (outline leak),
  once in the proper section — plus a duplicate "What's Next" heading. New
  paragraph dedup pass: normalizes each <p> (≥80 chars), groups by key, keeps
  the occurrence AFTER the first H2 (properly sectioned), removes pre-H2
  leaks. Orphaned link-name paragraphs cleaned after removal.
- "Investors" KEYWORD: meta title was "Investors: Anthropic Expected Pitch" —
  "Investors" is a generic word, now in the FK stopword list (client + server).
  Also added: investor, pitching, pitch, expected, reporting, reporters.

---
AutoArticle AI v2.5.321 - Sci-Fi Command Bridge UI
Release Date: August 25, 2026

FEATURE — Agents page rebuilt as a sci-fi command bridge:
- CEO CORE at top: animated spinning ring (blue/purple gradient), pulsing 🧠,
  terminal-font "CEO BRAIN" label, live stats (ACTIVE / PAUSED / TODAY),
  ● ONLINE status indicator — all on a dark starfield grid with soft glows.
- COMMAND CONSOLE: monospace prompt "CEO>" + dark input with cyan focus glow +
  "EXECUTE →" gradient button. Non-Pro sees locked console + UPGRADE button.
- TERMINAL LOG: dark console-style chat output with "❯" user prefix and "◆"
  CEO prefix, monospace font, custom scrollbar — no more white chat bubbles.
- AGENT FLEET header below the bridge (light WP-native cards, unchanged
  functionality) — buttons compacted to "⏸ All / ▶ All / + Deploy Agent".
- Empty state still shows the bridge above the "create your first agent" card.

---
AutoArticle AI v2.5.320 - 3-tier external link strategy + tag-boosted internal links
Release Date: August 25, 2026

STRATEGY (your request):
- EXTERNAL LINKS — 3-tier classification replaces the old authority/competitor
  binary:
  Tier 1 (reference — ALWAYS linked): Wikipedia, IMDB, Rotten Tomatoes,
  Transfermarkt, FBref, official brand/OEM sites (apple.com, samsung.com,
  marvel.com, netflix.com...), government, research. These add topical
  authority without helping a competitor rank.
  Tier 2 (wire — linked): Reuters, AP, Bloomberg (original reporting).
  Tier 3 (competitor — DROPPED for non-exclusive articles): TechCrunch,
  The Verge, VentureBeat, GSM Arena, CricBuzz, ESPN... These cover the same
  stories and only get linked when the article is Exclusive (attributing
  a source only this site received). Prevents leaking link equity to rivals.
- INTERNAL LINKS — TAG-BOOSTED matching: extracts capitalized entity names
  from the article's topic (brands, products, people), searches previous
  365 days of posts for entity matches, and adds them as high-priority
  internal links BEFORE the standard topic-word scoring. Creates the
  hub-and-spoke entity structure Google rewards (every "Marvel" article
  links to other "Marvel" articles).

---
AutoArticle AI v2.5.319 - Screenshot incident fixes (SEO label, timestamps, Now heading, niche links, tags)
Release Date: August 25, 2026

FIXES (from three live articles):
- SEO LABEL LEAK: "Rahul Dravid SEO   With India on 61.90% PCT…" — the model
  writes {AgentName} SEO as a bold label then the meta description as body text.
  New scrub pattern catches <p><strong>…SEO</strong>…</p>.
- INTERNAL METADATA: "ESPN's timestamp (2026-08-24T19:34:45, published on ESPN's
  Australia site)" leaked into body prose. EVIDENCE is now sanitized (ISO
  timestamps + "published on X's Y site" stripped) before the writer prompt,
  plus a new prompt rule banning metadata mentions.
- STRAY "NOW" HEADING: single-word generic headings ("Now", "More") are
  removed from the body, plus H2 dedup by normalized text (the Boltt
  "Key Specifications" ×2 incident).
- NICHE-IRRELEVANT LINKS: "VentureBeat AI" was linked in a Bollywood article —
  homepage-only pointers now require at least one word (≥4 chars) of the link
  name to appear in the article's topic/intro.
- TAGS: generic single-word blocklist (according, overview, research, share,
  contract, united…) + entity-variant dedup (Man United / Manchester United /
  United → keep longest only).

NOTE: version jump 2.5.317 → 2.5.319 (2.5.318 was the transliteration fix,
2.5.317 tag-only — v2.5.319 supersedes both; upload this over any prior version).

---
AutoArticle AI v2.5.317 - Tag quality hardening (Intel/Man United incident)
Release Date: August 25, 2026

FIXES:
- Tag extractor + FINAL TAG SWEEP: generic single-word blocklist (according,
  overview, research, share, contract, united, data, growth, market, etc.)
  — these are sentence-openers or analysis words that individually mean
  nothing as tags.
- Entity-variant dedup: "Man United" / "Manchester United" / "United" are
  the same entity — keep the longest, drop shorter word-subsets. Prevents
  3 variant tags for the same club.

---
AutoArticle AI v2.5.318 - non-ASCII keyword transliteration (Marvel Tōkon incident)
Release Date: August 25, 2026

FIX:
- Focus keywords with non-ASCII Latin chars (Tōkon, Björn, Pokémon) were
  mangled downstream to "t kon"-style garbage in meta title/description/H2s —
  the FK parse now transliterates via remove_accents() (Tōkon → Tokon) before
  storage. RankMath meta setter transliterates too.
- Pairs with server v2.8.24 (same transliteration at derive time).

---
AutoArticle AI v2.5.317 - Queue safety net (Telegram links never stall)
Release Date: August 25, 2026

FIX:
- Telegram link/topic queue relied on a +4s WP-Cron single event that could
  never fire on hosts with dead/blocked cron (technosports + Cloudflare) —
  "Priority queued — starting in now" then silence. The catch-up guardian
  now also detects Pro queue entries older than 10 minutes and re-fires the
  agent via the same async path it uses for overdue agents. The entry is
  consumed by the filter inside aaai_run_agent, so nothing is lost or
  duplicated. Honest ETA wording in the Telegram receipt.

---
AutoArticle AI v2.5.316 - Central Command polished
Release Date: August 25, 2026

POLISH:
- Agents page: removed heavy dark wrap (looked weird) — now a clean light command bar (CEO avatar 38px, CENTRAL COMMAND label, input, Send →) sitting above the normal light agent grid. Chat log is white, not dark. Merged the standalone Pro CEO Chat page into this bar — no more duplicate menu entry (old URL redirects to Agents).
- Pro v2.4.63: standalone 🧠 CEO Chat submenu removed (merged), redirect added for bookmarks.

---
AutoArticle AI v2.5.315 - Central Command: CEO in the middle
Release Date: August 25, 2026

FEATURE — Agents page revamp (your central command image):
- CEO hub in the middle (🧠 Chief of Staff, Online/Pro status, warm/concise/decisive badge)
- Agents orbit the CEO in a 3-col grid (was plain list) — each card still shows model/health but is visually tethered to the CEO
- COMMAND bar spanning the grid: single input "Ask CEO: 'pause my cricket agent' · 'suggest 3 tech topics'" + Send →, wired to POST /api/v1/assistant via the Pro CEO brain (same memory as Telegram, role:ceo)
- Direct commands from the central page: pause all / start all stay, plus you can now chat & assign tasks without leaving the agents page
- Non-Pro sees the same CEO hub but with "Pro required" and a locked command bar

---
AutoArticle AI v2.5.314 - Option A article-quality suite (Boltt + FIFA incident) + no-choice model architecture

Release Date: August 25, 2026

SERVER (v2.8.20):
- deriveKeywordFromHeadline: blocklisted verb-leading FKs (change, players, action, etc.) — "change fifa" no longer derivable.
- sanitizeFocusKeyword: 2-word verb-leading check (change fifa → re-derive "fifa leadership").

FREE PLUGIN (v2.5.314):
- Tag extractor: drops 000mah/mah/inch spec fragments and trailing stopword tags (Revolt The).
  FINAL TAG SWEEP hardened same.
- FK gate: verb-leading 2-word FKs re-derive from topic entities (fifa leadership).
- FAQ normalizer: handles truncated-question glue (Boltt "What is the starting" case).
- H2/title quote strip: "<h2>"change fifa": ..." → "<h2>Change fifa: ..."  + missing-space glue "RAM.Both"/"performanceThe" spaced.
- Writing Model row: Free = user-chooses (dropdown); Lite/Pro/Max = "🔒 Managed by server" (Option A — Free pool vs Premium pool, server's resolveWriterModel is authoritative; dropdown hidden + hidden input preserves saved value).

---
AutoArticle AI v2.5.313 - FAQ structure normalizer + stay-tuned scoping + TOC serialization
Release Date: August 25, 2026

FIXES (from live-article review, Nicholas Hoult / HBO Harry Potter piece):
- FAQ GLUED Q/A SPLIT: the targeted FAQ completion sometimes merges a question
  into the previous answer's paragraph ("...several British actors. Will this
  delay the series release? Unlikely. Since Hoult..."). New
  aaai_split_glued_faq_qa() normalizer splits glued "answer. Question? answer"
  paragraphs into <p>+<h3>+<p> (conservative: skips paragraphs with inline
  tags, questions capped at 15 words). Prompt also hardened with explicit
  structure rules.
- "STAY TUNED" INJECTION SCOPED TO BODY: the RankMath keyword-in-last-
  paragraph rule was targeting the document's LAST <p> — after FAQ appending
  that is a FAQ ANSWER, producing "...on track according to available
  reports. Stay tuned for more on Nicholas Hoult." Now considers only
  paragraphs before the FAQ section, and never injects into source-pointer
  lines ("For more detail, see ...").
- TOC TEXT SERIALIZATION: literal newlines between TOC <li> items and spaces
  after the ▸/◦ bullets — previously, any HTML-stripped context (RSS, AMP,
  email, copy-paste) serialized the TOC as one glued line
  "Article▸Why Did▸Who Was...". Rendering unchanged.

---

AutoArticle AI v2.5.312 - Entity-link relevance guard + log hygiene
Release Date: August 25, 2026

NEW IN v2.5.312:
- ENTITY-LINK RELEVANCE GUARD (two layers):
  1. Candidate side: generic quantifiers/pronouns/common nouns (some, people,
     many, everything, now, key, major...) now reject a window phrase when they
     appear ANYWHERE in it, not just as the first word. Live incident Aug 24:
     the heading fragment "Some People Pivot" became a candidate and was
     fuzzy-matched by Wikipedia opensearch to the 1966 World-Cup quote page,
     which then got linked inside a ChatGPT article.
  2. Resolve side: aaai_wiki_resolve() now requires every significant query
     word (>=4 chars) to appear in the RETURNED Wikipedia title, else the
     result is treated as no-match. Fuzzy near-misses ("Some People Pivot" ->
     "Some People Are on the Pitch...") are rejected. Known trade-off: correct
     spelling-variant pages ("Sinhalese" -> article titled "Singhalese") are
     now skipped too — entity links are garnish (max 2/article); fewer-but-
     exact beats wrong.
- RobustKeywordRecovery log: logs only when the recovery actually changed the
  keyword (was logging "Spanish -> Spanish" no-ops) and attributes to the
  current agent instead of agent 0.

---

AutoArticle AI v2.5.311 - Quote-aware focus-keyword differentiators
Release Date: August 25, 2026

NEW IN v2.5.311:
- CANNIBALIZATION-FIX HARDENING: when a focus keyword is already targeted and
  the plugin extends it with differentiator words from the topic, quoted
  speech is now STRIPPED before extraction, and the stopword list gained
  pronouns / speech verbs / fillers. Live incident Aug 24: the topic
  "'You need to control your emotions' - Pujara..." produced the differentiator
  "You" (capitalized only because it opens the quote), yielding the broken
  keyword "yashasvi jaiswal you" and the headline "Yashasvi Jaiswal You: ...".
  Now the same topic extends with "pujara" (a real entity) instead.

---

AutoArticle AI v2.5.310 - Server topic fragment gate
Release Date: August 24, 2026

NEW IN v2.5.310:
- FRAGMENT GATE on server-selected topics: the server occasionally returns a
  parsed headline fragment instead of a full topic (live incident Aug 24 2026:
  "Topic selected: for Season" — a 2-word fragment that burned a writer call).
  Topics with fewer than 3 words or shorter than 15 chars are now rejected as
  failed selections and the retry loop picks the next candidate. Custom /topic
  commands are unaffected (they bypass server selection).

---

AutoArticle AI v2.5.309 - Shared lock cleaner (Pro TG suite support)
Release Date: August 24, 2026

NEW IN v2.5.309:
- aaai_clear_agent_lock(): atomically clears ALL lock state for an agent
  (transients + object-cache key + MySQL mutex option). The run-completion
  shutdown cleanup now routes through it, and the Pro plugin's Telegram
  /run /pause /resume commands + Editorial Director call it so fleet actions
  never wait on a stale lock.
- Version jump 2.5.305 -> 2.5.309 intentionally clears the Aug-2026 orphan
  lineage builds (2.5.306-2.5.308) which shipped WITHOUT these canonical
  features: truncation-splice detectors, FINAL TAG SWEEP, live-sports guard,
  authority-domain dofollow linking, dedup-before-spend, keyword scrubs,
  NewsArticle schema, humanizer dashboard column, LITE plan row. Upgrading
  from any of those builds restores all of them.

REQUIRES Pro plugin v2.4.50 for the full Telegram ingestion suite (works
fine with older Pro too - aaai_clear_agent_lock is function_exists-guarded).

---

AutoArticle AI v2.5.247 - Retry topic sync + numbered-prefix strip
Release Date: July 18, 2026

54. RETRY TOPIC SYNC + NUMBERED-PREFIX STRIP
    Three bugs from the Persona/Dragon Quest article:
    a) Title/content mismatch: when a POST-RETRY changed the topic, $focus_keyword was NOT
       updated — the density injection appended the OLD keyword to the NEW article body
       ("Dragon Quest fans, stay tuned for more on Persona").
    b) Focus keyword stale on retry: the RANKMATH block + SEO density checks used the
       rejected topic's keyword on the retried article.
    c) Numbered-list prefix: the server returned "1. Persona 4 Revival..." and the "1. "
       leaked into the published title. Now stripped at both initial selection AND retry.
    FIX: (a) on retry, re-derive $focus_keyword from the new topic's proper nouns.
         (b) strip "N. " prefix from $topic at initial selection (line ~1036) and retry (line ~1343).
    Also bumped the plugin header Version to 2.5.247 so WordPress recognizes the update.

INCLUDES ALL PRIOR FIXES through v2.5.246.
    Despite server-side fixes (v2.6.24/v2.6.25/v2.6.26 scoping by agent_id), the PLUGIN
    still had its own cross-agent dedup that blocked every topic ANY other agent had touched:
    - agent-runner.php: is_duplicate_site_wide() on server-picked topics → "Server topic
      duplicates a story already covered by another agent/site"
    - scheduler.php: is_duplicate_site_wide() in prefetch → "Cross-agent duplicate rejected"
    Both checked ALL agents' cached/published topics with no agent_id filter.
    FIX: disabled both cross-agent checks. The per-agent is_duplicate() check (line 991 in
    scheduler, Pass -1 in agent-runner) still prevents same-agent duplicates. The server's
    agent-scoped dedup (v2.6.24+) handles cross-agent reservation. Different agents can now
    co-cover the same story for their different audiences.
    This is the LAST piece — combined with v2.6.26 (server INSERT fix), ALL three layers
    of cross-agent blocking are now removed.

INCLUDES ALL PRIOR FIXES through v2.5.245.

--- v2.5.245 ---
AutoArticle AI v2.5.245 - Source line replacement (fix keyword contamination) + all prior fixes

FIXES IN v2.5.244:

50. TAGS STILL LEAKING GARBAGE: "Mi", "HEADLINE", "Stat", "verdict", "Details There"
    "Mi" appeared on almost every article (model-provided tag from Haiku, bypassing extraction
    filters). "HEADLINE" leaked from the RANKMATH format marker. "Stat", "verdict", "Details There"
    are generic words not in the stopword list.
    FIX: expanded $vague_tags with ~30 more common/generic words: mi, headline, stat, stats,
    verdict, details, there, ring, amazon, camera, didn, system, familiar, twist, supply, dynamics,
    club, cricket, head, early, movement, master, batting, coaching, t20, skills, techniques,
    attacking, phases, switch. These are now filtered from both model-provided and extracted tags.

52. SOURCE LINE REPLACEMENT (fix keyword contamination once and for all)
    The writer consistently contaminates the Source line with the focus keyword:
    "Source: Digitaltrends conversational AI", "Source: GSMArena microtransactions", etc.
    The previous cleanup (v2.5.237) tried to strip the keyword from the <p>, but the writer's
    HTML structure varied and the regex didn't always match.
    FIX: STEP 8d2 now REPLACES the entire writer source <p> with a clean one built from
    aaai_source_publication_name() + the source URL. Regardless of what the writer put in the
    source line, the output is always "Source: [clean publication name]" with a proper link.

INCLUDES ALL PRIOR FIXES through v2.5.244 (tag cleanup, TOC bullets, RANKMATH format,
dofollow links, density injection fix, keyword stopwords, prompt Pass 3+4, budget proportions,
heading cleaner, source-spec extraction, truncation gate, dedup gate, smashed-keyword scrub).

--- v2.5.244 ---
AutoArticle AI v2.5.244 - Tag cleanup (filter "Mi", "HEADLINE", "Stat", "verdict" + evergreen terms)
    The TOC used <ol> (numbered) with only padding to differentiate H2 from H3 — the hierarchy
    was invisible. Now uses <ul> with custom bullet characters:
    - H2: ▸ (filled orange triangle) + bold link
    - H3: ◦ (hollow light-orange circle) + 28px indent + lighter/smaller text
    Hierarchy is now visually clear at a glance.

INCLUDES ALL PRIOR FIXES through v2.5.243.

--- v2.5.243 ---
AutoArticle AI v2.5.243 - Outbound links: real-article URLs always dofollow + RANKMATH format fix
Release Date: July 12, 2026

FIXES IN v2.5.243:

47. ALL OUTBOUND LINKS WERE NOFOLLOW
    RankMath reported "We found 2 outbound links and all of them are nofollow." The plugin's
    aaai_normalize_external_link_rels() checked each link against a hardcoded authority-domain
    list. Source-article domains not on the list (collider.com, screenrant.com, destructoid.com,
    etc.) got rel="nofollow" — even though they're legitimate source-article links. FIX: any URL
    with a non-empty path (not a homepage) is now dofollow (rel="noopener"). Only bare homepages
    (empty path) get nofollow. This ensures every real source-article link passes link equity.

49. KEYWORD-DENSITY INJECTION: BANNED PHRASE + SOURCE-LINE CONTAMINATION
    The last-paragraph keyword injection appended "Understanding [keyword] fully means staying
    ahead of these developments." — a BANNED phrase that ran AFTER the style pass (never stripped).
    When the last paragraph was a writer-emitted "Source:" line, the injection contaminated it:
    "Source: Collider Understanding avengers fully means staying ahead of these developments."
    FIX: (a) skip paragraphs containing "Source:" — the injection now finds the last CONTENT
    paragraph instead; (b) replaced the banned sentence with "Stay tuned for more on [keyword]."

--- v2.5.242 ---
AutoArticle AI v2.5.242 - FIX: RANKMATH format reverted to multi-line (Pass 4 broke the parser)
Release Date: July 12, 2026

CRITICAL FIX IN v2.5.242:

46. RANKMATH SEO BLOCK — REVERT TO MULTI-LINE (Pass 4 broke it)
    v2.5.240 (Pass 4) condensed the RANKMATH format spec into a SINGLE LINE with pipe separators.
    Haiku followed the format literally, outputting all fields on one line. But the plugin's parser
    expects ONE FIELD PER LINE. The FOCUS_KEYWORD regex captured the ENTIRE rest of the line
    (seo_title, meta_description, url_slug, etc.) as the keyword value — making every keyword
    since v2.5.240 garbage like "microtransactions|seo_title:collegefootball27...".
    FIX: reverted to multi-line format (each field on its own line, terse descriptions). Parser
    now correctly extracts just the FOCUS_KEYWORD value.

--- v2.5.241 ---
AutoArticle AI v2.5.241 - Budget directive: proportions (works for any word-count target, incl. 1000)
Release Date: July 10, 2026

FIXES IN v2.5.241:

45. BUDGET DIRECTIVE NOW SCALES WITH TARGET WORD COUNT
    The v2.5.232 budget directive had FIXED per-section allocations (Intro <=80, H2 ~100-140,
    Conclusion <=80, FAQ ~40) that summed to ~560 — fine for a 600-word target but BROKEN for
    1000 words (sums to ~560 vs the 850 WC floor → every article would draft as too-short).
    Now uses PROPORTIONS: Intro ~10% | each H2 ~(70% / num_H2s) | Conclusion ~10% | FAQ ~5%.
    Scales correctly for any target: 600w → ~570 budget, 1000w → ~999 budget.

--- v2.5.240 ---
AutoArticle AI v2.5.240 - System-prompt Pass 4 (condense AUDIENCE/SEO/FORMAT/RANKMATH → target ~20k for Haiku)
Release Date: July 10, 2026

FIXES IN v2.5.240:

44. SYSTEM PROMPT PASS 4 — CONDENSE AUDIENCE PERSONA + SEO + FORMAT + RANKMATH
    Continues Pass 3's Haiku-targeted compression. Condensed:
    - AUDIENCE PERSONA: condensed level/tone maps (3 x 150-char → 3 x 50-char), merged 5 output
      lines into 1. Saved ~600 chars.
    - FORMAT + HEADING STRUCTURE: 13 lines → 3 (merged format rules, heading rules, FAQ rule).
      Saved ~1000 chars.
    - SEO REQUIREMENTS: 8 lines → 1 (merged keyword placement, first-sentence rule, title,
      internal/external link rules). Saved ~900 chars.
    - RANKMATH SEO BLOCK: 12 lines → 1 (condensed the format spec into one line).
      Saved ~500 chars.
    Total Pass 4 savings: ~3000 chars. Combined with Pass 1+2+3, system prompt is now ~20.7k
    (from 32k original — a 35% reduction). This is the target threshold for Haiku 4.5's
    instruction-following capacity.

--- v2.5.239 ---
AutoArticle AI v2.5.239 - System-prompt Pass 3 (condense WRITING CRAFT for Haiku instruction-following)
Release Date: July 10, 2026

FIXES IN v2.5.239:

43. SYSTEM PROMPT PASS 3 — CONDENSE WRITING CRAFT (target Haiku 4.5 instruction-following)
    Diagnosis correction: the user is on Claude Haiku 4.5 (a capable model), NOT flash-lite. Haiku's
    truncation (incomplete_ending + over_word_count) is caused by the 26k-char system prompt being
    too large for Haiku's instruction-following capacity — not model quality or token limits (8192
    output tokens is plenty). Pass 3 condenses the WRITING CRAFT section:
    - Removed duplicate TENSION RULE (was stated at line 364 AND 416).
    - Merged SENTENCE RHYTHM + PARAGRAPH ARCHITECTURE into one terse line.
    - Merged STRONG VOICE + SPECIFICITY into one line.
    - Condensed EDITORIAL VOICE (3 x 300-char branches -> 3 x 50-char).
    - Condensed E-E-A-T + NATURALNESS (8 lines -> 2 lines).
    - Condensed OPENING HOOK + AUDIENCE ENGAGEMENT (5 lines -> 1 line).
    - Condensed persona intro, TRANSITIONS, PASSIVE VOICE, NO SMASHED WORDS.
    ~2.3k chars removed. Combined with Pass 1+2, system prompt is now ~23.7k (from 32k original).

--- v2.5.238 ---
AutoArticle AI v2.5.238 - Expanded keyword stopwords (gerund/action words + generic analysis terms)
Release Date: July 10, 2026

FIXES IN v2.5.238:

42. BAD TITLE-DERIVED KEYWORDS (gerund/action words leaking)
    Symptom: focus keywords like "Comparing Long Term" (from "Comparing Long Term Maintenance Costs
    for Toyota Tundra and Ford"), "Mastering Babar Azam's", "Jürgen Klopp Transformed" — the KW Gate
    title-derivation took the first 2-3 non-stopword title words, but gerund/action words (Comparing,
    Mastering, Balancing, Decoding, Unlocking, etc.) and generic analysis terms (Long, Term, Tactical,
    Performance, Transformed, etc.) weren't in the stopword list. Density too low (0.28%, 0.46%).
    FIX: expanded $_kw_stop with ~50 gerund/action words (comparing, mastering, balancing, decoding,
    unlocking, understanding, exploring, analyzing, architecting, optimizing, etc.) and generic analysis
    terms (long, term, tactical, performance, technical, mechanics, anatomy, transformed, maintenance,
    costs, etc.). Now the title-derivation skips these and finds the real entity deeper in the title.

--- v2.5.237 ---
AutoArticle AI v2.5.237 - Final writer-artifact cleanup (markdown in title, stray comments, source-line keyword leak)
Release Date: July 7, 2026

FIXES IN v2.5.237:

41. WRITER-OUTPUT ARTIFACTS (model-agnostic final cleanup)
    Three small visible bugs from the Kanwaljit Singh/Satluj article, all caused by the writer
    model leaving artifacts the post-processing didn't catch:
    a) "*Satluj*" — markdown-italic asterisks left in the title and headings. Now strips *, _, `
       from the post title and all <h1>-<h6> inner text.
    b) Unclosed "<!--" at the end of the article — a stray/incomplete HTML comment. Now strips
       any "<!--" that has no matching "-->".
    c) "Source: The Indian Express freedom of speech" — the focus keyword leaked into the
       writer-emitted "Source:" line. Now strips the focus keyword from any "Source:" paragraph.
    NOTE: this is the LAST defensive cleanup pass. These are all writer-model artifacts;
    recurring new artifacts (truncation, asterisks, comments, garbage tags) all stem from
    gemini-3.1-flash-lite / Haiku inconsistent output. The remaining systemic lever is the
    writer-model swap (gemini-2.5-flash / sonnet).

--- v2.5.236 ---
AutoArticle AI v2.5.236 - Source-article fact extraction (use the source's specs, don't say "no confirmed specs")
Release Date: July 7, 2026

FIXES IN v2.5.236:

40. SOURCE SPECS IGNORED — ARTICLE SAYS "NO CONFIRMED SPECS" WHEN THE SOURCE HAS THEM
    Symptom: iQOO Z11 article said "we still don't have confirmed specs for RAM, storage, processor"
    even though the GSMArena source explicitly listed MediaTek Dimensity 7500, 12GB RAM, Android 16,
    and model number I2514. The Sonar fact-check prompt never received the source URL, so Perplexity
    searched generically and returned no specs; the writer then had nothing concrete to use.
    FIX: when $_source_article_url is set, the Sonar fact-check prompt now explicitly points
    Perplexity at the source article and demands extraction of EVERY specific spec/number/name/date/
    model (processor, RAM, storage, display, battery, OS, price, model number, launch dates) from it.
    Perplexity (web search) fetches the source and returns the actual specs, which flow to the writer.

--- v2.5.235 ---
AutoArticle AI v2.5.235 - Tag-extraction fix (stop title-case words leaking as tags)
Release Date: July 7, 2026

FIXES IN v2.5.235:

39. GARBAGE TAGS FROM TITLE-CASE HEADLINES
    Symptom: tags like "different, Different Specs The, Its Way, Probably, Mi, ARTICLE TITLE"
    for an iQOO Z11 article. The aaai_extract_tags() capitalized-word regex treated EVERY
    title-case word as an entity (Its/Way/Probably/Different), the vague-tag filter was missing
    those words, and a leaked "ARTICLE TITLE" placeholder was even captured.
    FIX: tightened the capitalized-entity extraction in content-pipeline.php — strip leading/
    trailing common words from each candidate, reject if any remaining word is common/vague, so
    only clean entities survive ("iQOO Z11" kept; "Its Way"/"Probably"/"Different Specs The"
    rejected). Added a comprehensive $_common list (its/way/probably/different/the/article/title/
    ...) shared across the capitalized + word-split paths. Model TAGS: and the entity_parent /
    model / tech pattern maps are unaffected.

--- v2.5.234 ---
AutoArticle AI v2.5.234 - Heading-prefix cleaner (fix "--- Tag:" headings + manual TOC)
Release Date: July 7, 2026

FIXES IN v2.5.234:

38. GARBAGE HEADING PREFIXES + MANUAL TOC LEAKING INTO ARTICLES
    Symptom: the Balogun article shipped with H2s like "--- Balogun red card: Balogun's Situation
    and FIFA's Response" and a writer-emitted "📋 In This Article --- heading --- heading" TOC block
    running into the body. The writer (Haiku 4.5 / flash-lite) ignores the prompt rule against
    "Topic: Description" headings and against emitting a manual TOC.
    FIX: new aaai_clean_heading_prefixes() runs BEFORE the TOC is generated, so the TOC inherits
    clean headings. It (1) strips the writer's manual "📋 In This Article" label + any <p> starting
    with a horizontal-rule marker (---/—/__); (2) strips leading ---/—/__ from <h1>-<h6> inner text;
    (3) strips a repeated "Tag: Subtitle" prefix from H2/H3 — only when the SAME prefix precedes the
    colon on 2+ headings (a category/tag pattern). Legitimate one-off colons ("USA vs Belgium: Key
    Matchups") are preserved. Model-agnostic: catches the garbage regardless of which writer model
    produced it.

--- v2.5.233 ---
AutoArticle AI v2.5.233 - Pass 2 prompt condensation + keyword-recovery trailing-punct fix
Release Date: July 7, 2026

FIXES IN v2.5.233:

36. WRITER SYSTEM PROMPT — PASS 2 AGGRESSIVE CONDENSATION
    Pass 1 (v2.5.231) + the budget directive (v2.5.232) didn't reduce truncation — the prompt was
    still ~32k chars and the model couldn't follow it. Pass 2 condenses the four most verbose
    accuracy blocks in aaai_build_system_prompt to terse imperatives, preserving every distinct
    rule but cutting the example bloat:
    - FACTUAL ACCURACY: 16 bullets -> 7 (merged tense/date/stats/match-status/leak/player/date-anchor;
      cut 2 low-value meta bullets: SOURCE CONTEXT, HALLUCINATION CHECK).
    - FINANCIAL FIGURES: 6 bullets -> 2.
    - FAKE REVIEW PROHIBITION: 6 bullets -> 3 (kept banned-phrase + permitted-phrase lists, condensed).
    - TECH PRODUCT ACCURACY: 8 bullets -> 3.
    Net ~30 prompt lines / ~3.5k chars removed with zero rules lost. The budget directive + structure
    rules now stand out instead of being buried.

37. KEYWORD RECOVERY TRAILING-PUNCT FIX (ajax-hooks.php aaai_recover_keyword_spaces)
    The recovery stripped ':' but NOT commas/periods, so model-appended punctuation shipped in the
    keyword: "imagine," -> "Imagine," and context-match kept trailing commas ("Elder Scrolls Online,").
    Now strips trailing :,.;'" on both the input keyword and the context-match return.

--- v2.5.232 ---
AutoArticle AI v2.5.232 - Writer output-budget directive (attack structural truncation)
Release Date: July 6, 2026

FIXES IN v2.5.232:

35. WRITER STRUCTURAL TRUNCATION — EXPLICIT OUTPUT BUDGET
    Symptom: most runs log `[Writer] Response incomplete: incomplete_ending, missing_h2_sections,
    significantly_over_word_count` — the writer rambles in early sections, runs out of attention, and
    cuts the ending/sections short. The system prompt had no upfront structure budget, so the model
    never planned its output.
    FIX: added an "OUTPUT BUDGET — PLAN BEFORE YOU WRITE" block near the top of the system prompt
    (right after the persona), instructing the model to allocate its word budget across sections
    (Intro <=80, each H2 ~100-140, Conclusion <=80, FAQ ~40) BEFORE writing, with three hard rules:
    (1) complete every section — never end mid-sentence (incomplete ending = fatal), (2) stay within
    +/-10% of target, (3) if running long, CONDENSE earlier prose rather than truncate. Directly
    targets incomplete_ending + missing_h2_sections. Pairs with the Pass 1 prompt de-dup (v2.5.231).

--- v2.5.231 ---
AutoArticle AI v2.5.231 - System-prompt compression Pass 1 (de-dup + contradiction fix)
Release Date: July 6, 2026

FIXES IN v2.5.231:

34. WRITER SYSTEM PROMPT — PASS 1 DE-DUPLICATION (toward reducing the 32k-char prompt)
    The server's own diagnostic flagged the writer system prompt as "too complex - causing
    output truncation" (structural truncation: missing_h2_sections + incomplete_ending on most
    runs). Pass 1 removes only unambiguous redundancy/contradictions, preserving every distinct rule:
    - Merged the two overlapping banned-words lists (TRANSITIONS block + BANNED WORDS) into one
      comprehensive list.
    - Fixed the paragraph word-limit contradiction (was "MAX 120" AND "exceeding 150" — now 120 only).
    - Condensed the 45-entry brand capitalization list to a rule + examples.
    - De-duplicated the date ("Today is X" was stated 4x) by trimming the redundant TEMPORAL ACCURACY
      block to just the sports-specific rules (date still stated in the opening + FACTUAL ACCURACY block).
    Saves ~1.3k chars with zero rules lost. Pass 2 (deeper condensation of the verbose accuracy/financial
    blocks, pending live-cycle verification) to follow.

--- v2.5.230 ---
AutoArticle AI v2.5.230 - Keyword stopword filter (stop "you"/"imagine" focus keywords)
Release Date: July 6, 2026

FIXES IN v2.5.230:

33. GARBAGE FOCUS KEYWORDS FROM SENTENCE-OPENERS
    Symptom: focus keywords like "you" (from "You can now use your Sony headphones..."),
    "Imagine," (from "LeRobot v0.6.0: Imagine, Evaluate, Improve"), "this china", "bladerunner 204".
    The KW-Gate title-derivation (used when the model's keyword is smashed/unrecoverable) took the
    first 2-4 title words by length only, so capitalized sentence-openers/pronouns became the keyword.
    FIX: added a KEYWORD_STOPWORDS list (pronouns, articles, common verbs/imperatives like
    imagine/use/get, generics like news/review/latest) and filter title words against it before
    deriving the keyword. Mirrors the server-side KEYWORD_STOPWORDS in topic-cache.ts (v2.6.19) so
    both sides agree. Now derives the real entity (Sony, Balogun, LeRobot) instead of "you".

--- v2.5.229 ---
AutoArticle AI v2.5.229 - Truncation gate (stop truncated articles publishing)
Release Date: July 6, 2026

FIXES IN v2.5.229:

32. TRUNCATED ARTICLES PUBLISHED MID-SENTENCE
    Symptom: the Honor Magic V6 article shipped with cut-off sections ("Verdict: With a
    $1,499 starting", "The $1,499 ", "At a $1,499 starting ") — sentences ending mid-word.
    The writer returned incomplete_ending + missing_h2_sections + significantly_over_word_count
    (it rambled then hit the token limit). The v2.5.226 "publish short instead of draft"
    change topped it up ~23 words and published it. aaai_validate_response_completeness()
    only inspects the LAST sentence of the whole body, so it missed the mid-article cut-offs
    (the final paragraph happened to end with a period).
    FIX: new aaai_detect_truncated_paragraphs() scans every <p> for a non-terminal ending
    (no . ! ? danda/Arabic/CJK full-stop before any trailing close-brackets/quotes). If any
    truncated paragraph (>=25 chars, multi-word) is found, the publish gate
    ($_quality_blocked) routes the article to DRAFT instead of publishing — regardless of
    word count. Logs "[Truncation Gate] Article has N truncated paragraph(s)" so it is
    observable. A short, COMPLETE article still tops up + publishes (v2.5.226 preserved);
    only structurally truncated ones are held.

--- v2.5.228 ---
AutoArticle AI v2.5.228 - Final pre-publish smashed-keyword scrub (stop "Honormagicv6:" leaking live)
Release Date: July 6, 2026

FIXES IN v2.5.228:

31. SMASHED FOCUS KEYWORD LEAKED INTO PUBLISHED ARTICLE
    Symptom: the Honor Magic V6 article shipped with "Honormagicv6:" prepended to the
    title, intro, TOC, and H2s. The writer itself emits the focus entity as a single
    smashed token ("Honormagicv6:"), and the keyword-density fallback injector prepends
    it too — BOTH run AFTER the existing KW Gate (line ~3080) and aaai_recover_keyword_spaces(),
    which only fix the metadata keyword, not the body already injected. So the smashed form
    reached wp_insert_post.
    FIX: new aaai_scrub_smashed_keyword_pre_insert() runs immediately before wp_insert_post
    and replaces any whole-word, case-insensitive occurrence of the keyword's smashed
    (alphanumeric-only) form with its properly-spaced Title-Case form. Text-node-only
    replacement (HTML tags/attributes are skipped via preg_split on <tag>), so anchor ids
    and hrefs that kebab-cased the entity stay valid and keep matching their TOC links.
    Logs "[KW Scrub] Replaced N smashed-keyword occurrence(s): X -> Y" so it is observable.
    NOTE: this is a safety net over the writer/injector pipeline. The deeper cause — the
    writer model emitting smashed entities — remains; this guarantees no smashed keyword
    ever ships live regardless of where it originated.

--- v2.5.227 ---
AutoArticle AI v2.5.227 - Stop dedup/recency gates from killing REAL news (the evergreen flood)
Release Date: June 21, 2026

FIXES IN v2.5.227 (PAIRS WITH SERVER v2.6.16):

30. REAL NEWS WAS BEING REJECTED -> EVERGREEN FLOOD
    The log shows the pipeline now FINDS real, fresh, on-niche news (Dua Lipa Chanel gown,
    Trump/Anthropic, Tesla Autopilot probe, 'Newcastle reject Spurs' Tonali bid' w/ ESPN source) —
    but it kept getting thrown away, so agents fell to evergreen ('Mastering X'). Two over-aggressive
    gates fixed:
    a) CLIENT recency gate (agent-runner): rejected a topic for lacking explicit 2025/2026 markers
       even when the server had extracted a REAL current source ARTICLE for it (e.g. a live transfer
       whose facts omit the year). Now both recency/insufficient-facts gates are skipped when
       $_source_article_url is present — a fresh source article is strong proof the story is current.
    b) SERVER semantic-dedup threshold (v2.6.16, route.ts): raised 0.50 -> 0.65. At 0.50 over a
       7-day window, DISTINCT real stories collided ('similar to a previous topic') and were 409'd,
       starving agents. 0.65 (the pre-v2.5.178.1 value) lets distinct news through while still
       catching true repeats. REQUIRES server deploy.

    Still server-side / noted: cross-agent dup (Entertainment vs India Entertainment both want the
    same story); 429 'duplicate request, wait 30s'; writer 'incomplete/over word count' erratic length.

--- v2.5.226 ---
AutoArticle AI v2.5.226 - Top up short articles instead of drafting them
Release Date: June 20, 2026

FIXES IN v2.5.226:

29. SHORT ARTICLES DRAFTED INSTEAD OF EXPANDED (e.g. 475-595w)
    The writer often stops early (it has 3072+ output tokens, so it's the model under-delivering,
    not a cap). The targeted-expansion pass only fired for a <100-word shortfall and aimed at the
    agent's word_count — so 480-599w articles (shortfall >=100, or word_count set below 600) were
    NOT expanded and got drafted at the hard 600 floor. Now expansion aims at the real publish
    floor (max(word_count, 600)), fires for shortfalls up to 250 words, and scales its token
    budget to the shortfall — converting many 'too short -> draft' outcomes into published posts.
    (Severely incomplete writes still go through the normal retry path.)

    Note: the deeper cause — the writer model stopping early under the ~32k-char system prompt —
    remains a separate, recommended writer-prompt/model investigation.

--- v2.5.225 ---
AutoArticle AI v2.5.225 - NEW: Live Sports Articles (Google News 'Live' + auto score box)
Release Date: June 20, 2026

FEATURE IN v2.5.225:

28. LIVE SPORTS ARTICLES
    New includes/live-sports.php. When a sports agent publishes a LIVE/UPCOMING match article
    (detected from the Sonar 'MATCH STATUS: LIVE|UPCOMING' line gathered at generation):
    - Auto-injects a [aaai_live_score] shortcode at the top: an auto-refreshing score box that
      polls every 60s until the coverage window ends.
    - Emits LiveBlogPosting JSON-LD (coverageStartTime/EndTime) so Google News shows the LIVE
      badge during the match.
    - Auto-expires: coverage window per category (cricket 12h, football 4h, etc.); after it the
      box shows the final, polling stops, and the schema's coverageEndTime is in the past.
    Scores come from the EXISTING Perplexity path (perplexity/sonar) but are cached SITE-WIDE
    (~75s transient keyed by match) so ALL readers share ONE fetch — bounded cost, no new keys.
    Public AJAX endpoint (action=aaai_live_score, nonce-checked) serves the cached score as JSON.
    The [aaai_live_score] shortcode renders nothing on non-live posts, so it's safe anywhere.

--- v2.5.224 ---
AutoArticle AI v2.5.224 - Kill keyword-stuffing artifacts (ugly opener + FAQ prefixes)
Release Date: June 20, 2026

FIXES IN v2.5.224:

26. UGLY LOWERCASE KEYWORD OPENER
    Articles could start with a dangling lowercase fragment, e.g. 'netherlands sweden — The
    Netherlands and Sweden are set...'. The zero-density fallback prepended the raw keyword +
    em-dash to the first <p>. Now it title-cases the keyword and uses a clean colon standfirst
    ('Netherlands Sweden: The Netherlands and Sweden...') — reads like an editorial dek.

27. KEYWORD STUFFED INTO FAQ QUESTIONS
    The H2/H3 keyword injector prefixed the focus keyword onto FAQ question H3s too, producing
    'Netherlands Sweden: What time does the match start?'. The FAQ skip only matched the 'FAQs'
    H2, not the individual question H3s. Now any QUESTION-style heading (ends with '?') is
    skipped, so FAQ / People-Also-Ask questions stay clean.

--- v2.5.223 ---
AutoArticle AI v2.5.223 - Evergreen writes bypass server Hyper-Accuracy 'old event' guard
Release Date: June 20, 2026

FIXES IN v2.5.223:

25. EVERGREEN TOPIC FAILED AT WRITER UNDER HYPER-ACCURACY MODE
    Symptom (Cricket, hyper-accuracy ON): server SKIP -> evergreen 'Mastering Mitchell Starc's
    Tactical Approach to Swinging the Red Ball' accepted, but the WRITER call returned 422
    'Topic rejected by Hyper-Accuracy mode. This event appears to be old' -> agent published
    nothing. Evergreen topics are deliberately timeless, so the server's event-recency guard
    must not apply. FIX: the article-writer calls now send hyper_accuracy=false when the topic
    is evergreen ($_is_evergreen), so dry-news cycles that fall back to evergreen still publish.
    Hyper-accuracy still applies fully to real/fresh news topics.

--- v2.5.222 ---
AutoArticle AI v2.5.222 - Your configured RSS feeds now drive topic selection
Release Date: June 20, 2026

FIXES IN v2.5.222 (PAIRS WITH SERVER v2.6.15 — must deploy server too):

24. AGENT RSS FEEDS NOW REACH THE TOPIC ENGINE (root cause of 'I added sources but still get evergreen')
    Until now topic selection was server-side and used ONLY the server's hardcoded CURATED_FEEDS
    + niche-based Google News. The per-agent RSS feeds you configured were NEVER sent to the
    topic chooser (they only fed local writer context), so adding sources couldn't change which
    topics were picked — and when the server's own feeds ran dry, agents fell to evergreen.
    NOW: aaai_autoarticle_call() takes a $rss_feeds arg; the live topic call (agent-runner STEP 2)
    and the hourly prefetch (scheduler) both send the agent's rss_feeds (http(s) only, capped 40);
    the server (v2.6.15) accepts rss_feeds, merges them into the headline pool as customFeeds, and
    keys the RSS cache by them. Result: your configured sources actually drive topic selection.
    REQUIRES server deploy of v2.6.15 (route schema + customFeeds pass-through + cache key).

--- v2.5.221 ---
AutoArticle AI v2.5.221 - Evergreen: don't name dated AI model versions
Release Date: June 20, 2026

FIXES IN v2.5.221:

23. EVERGREEN AI/TECH TOPICS NAMING OUTDATED MODEL VERSIONS
    Symptom: 'Implementing Claude 3.5 Sonnet Workflows for Function Calling Success' and
    'Anthropic Claude 4 Opus Enterprise Launch Details' — both name old model versions
    (3.5 Sonnet = 2024, Claude 4 Opus = mid-2025). v2.5.219 banned superiority verdicts but
    a how-to naming a specific model still passed. The evergreen prompt now forbids putting a
    specific fast-dating AI model VERSION/release-detail in the headline and tells the model to
    use the vendor (Claude/ChatGPT/Gemini) or a durable concept (function calling, RAG, agents)
    instead — it has no live data on the current version.
    LIMIT: this only covers the evergreen path. An offline generator still cannot know June-2026
    reality; if the SERVER topic engine emits a stale model topic while Perplexity is down, only
    restoring live data fixes it.

--- v2.5.220 ---
AutoArticle AI v2.5.220 - Temporal gate false-positive on product names (Cyberpunk 2077)
Release Date: June 20, 2026

FIXES IN v2.5.220:

22. TEMPORAL GATE WRONGLY REJECTED PRODUCT NAMES WITH YEAR-LIKE NUMBERS
    'Mastering Cyberpunk 2077 Netrunner Builds' was rejected as a future-year topic ('2077')
    — the future-year guard treated the product-name number as a date, burned every retry,
    then force-published anyway. FIX: the future-year guard now only fires within a plausible
    window (current+2 .. current+8). Far-future numbers (Cyberpunk 2077, Battlefield 2042) are
    product names, not dates. Also: evergreen topics now skip the temporal gate entirely (they
    are timeless analysis/guides for older subjects).

--- v2.5.219 ---
AutoArticle AI v2.5.219 - Evergreen quality: no unverifiable 'X is superior' / stale-model verdicts
Release Date: June 17, 2026

FIXES IN v2.5.219:

21. EVERGREEN TOPICS MAKING STALE, UNVERIFIABLE VERDICTS
    Symptom: tech agent produced 'Why GPT-4o Remains Superior to Llama 3 for Complex Creative
    Writing'. Routing was correct (it IS tech); the issue is the topic — an evergreen fallback
    (Perplexity outage) generated from training data, so it (a) names old models (GPT-4o/Llama 3
    are 2024-era) and (b) asserts a present-day 'remains superior' verdict the generator cannot
    verify with no live data.
    FIX: evergreen prompt now BANS unverifiable superiority/recency framings ('Why X Remains
    Superior', 'Why X Is Still the Best', 'Why X Is Better Than Y', 'The Best X in <year>') and
    is told it has no live data so it must prefer durable angles. The tech evergreen angle is
    retuned to how-to / concept explainer / setup / 'which to choose for [use case]' guides and
    explicitly avoids version-vs-version 'which is better' verdicts on fast-moving AI models/chips.
    NOTE: with NO live data the generator still only knows training-era products — the real fix
    is restoring Perplexity so fresh, current topics flow instead of evergreen fallbacks.

--- v2.5.218 ---
AutoArticle AI v2.5.218 - Outage-safe fallback (no stale topics when fact-check is down)
Release Date: June 17, 2026

FIXES IN v2.5.218:

20. STALE TOPICS PUBLISHED WHEN FACT-VERIFICATION IS DOWN
    Symptom: an outdated topic like 'Qualcomm Snapdragon 8 Gen 4 Benchmark Leaks Surface'
    (a late-2024 chip, long released by mid-2026) got published. Cause: the recency gate
    (STEP 5c) verifies via Perplexity/Sonar; with Perplexity out of quota it returns no
    facts, every topic is rejected as 'insufficient verified facts', retries exhaust, and the
    exhaustion handler force-published the unverified topic anyway ('[FALLBACK] Proceeding
    despite Sonar rejection') — so stale training-data topics slipped through during the outage.
    FIX: when retries exhaust specifically because fact VERIFICATION was unavailable/failed
    (reason matches insufficient/outdated/verified-facts/stale), swap to a timeless EVERGREEN
    topic (needs no live facts) instead of force-publishing the unverified one. Only the
    exhausted-fallback branch changes; duplicate-bail and normal flow are untouched.
    NOTE: the real trigger is the Perplexity 401 insufficient_quota — restore Perplexity
    credits (or gateway Perplexity access) so fresh news topics verify and publish normally.

--- v2.5.217 ---
AutoArticle AI v2.5.217 - Atomic per-event lock (stop concurrent duplicate spend)
Release Date: June 17, 2026

FIXES IN v2.5.217:

19. CONCURRENT DUPLICATE TOPICS (same story twice, double AI spend)
    Symptom: same agent published two near-identical posts at the same time — often only a
    casing difference (e.g. 'FTC Prepares Antitrust Lawsuit Against Amazon Advertising' vs
    'FTC prepares antitrust lawsuit against Amazon advertising', post IDs 1344980/1344984) —
    each costing a full generation. Root: the whole-run lock can LEAK on hosts with a
    non-persistent (per-process) object cache, where wp_cache_add() isn't atomic across
    processes, so two concurrent runs both reach topic selection and pick the same hot story.
    The v2.5.212 last-mile guard only catches the SEQUENTIAL case and only AFTER generation.
    FIX: a per-EVENT atomic lock (add_option = atomic MySQL INSERT, reliable regardless of
    object cache) taken right BEFORE the writer spend (agent-runner STEP 5e). Keyed on the
    agent + event-hash of the final topic. If a concurrent run already holds it, this run
    aborts before spending a single writer/humanizer/image credit. Self-cleans on shutdown,
    15-min stale guard for crashed runs. Layers with the last-mile guard (sequential case).

--- v2.5.216 ---
AutoArticle AI v2.5.216 - Better evergreen topics (recency exemption + punchier headlines)
Release Date: June 17, 2026

FIXES IN v2.5.216:

17. EVERGREEN TOPICS NO LONGER REJECTED AS 'STALE'
    An evergreen fallback like 'Prabhas Performances Across the Baahubali Franchise' was hit by
    the Sonar news-recency gate ('facts exist but none are from 2025/2026'), which burned every
    retry until a forced '[FALLBACK] proceed despite Sonar rejection'. That gate is for NEWS, not
    evergreen analysis of older subjects. New $_is_evergreen flag (set on both evergreen accept
    paths, reset when a retry swaps in a server/news topic) now exempts evergreen topics from the
    two recency/insufficient-facts rejections — so they pass cleanly without wasting retries.

18. PUNCHIER, MORE VARIED EVERGREEN HEADLINES
    The evergreen generator kept producing dry, formulaic titles ('A Comparative Analysis of...',
    'Ranked Best Performances Across...'). System prompt now bans those academic openers and
    demands a punchy, curiosity-driven headline. Entertainment angles broadened (why a classic
    still resonates, iconic scene breakdowns, underrated roles, character arcs, industry impact).

--- v2.5.215 ---
AutoArticle AI v2.5.215 - Evergreen fallback on server 422 (resilience)
Release Date: June 17, 2026

FIXES IN v2.5.215:

16. 422 'No valid topics' NO LONGER HARD-FAILS
    Until now only a server SKIP triggered the local evergreen fallback; a 422 'Topic
    generation failed: No valid topics found' (dry pool, or upstream topic intelligence
    like Perplexity being out of quota) returned an error and published nothing. STEP 2 now
    detects a no-topics/422 error and runs the evergreen fallback (same path as SKIP); the
    server response is treated as empty downstream so the evergreen topic flows through.
    Pairs with the v2.5.214 evergreen dup-escape so the fallback actually lands a fresh topic.

    NOTE: the underlying production trigger was a Perplexity 401 'insufficient_quota' (API
    credits exhausted) — a billing fix on the Perplexity account, not code. This change just
    keeps agents publishing evergreen content while that upstream is unavailable.

--- v2.5.214 ---
AutoArticle AI v2.5.214 - Evergreen fallback dup-escape (dry-news cycles)
Release Date: June 17, 2026

FIXES IN v2.5.214:

15. EVERGREEN FALLBACK NO LONGER FAILS ON DUPLICATES
    Symptom (India Entertainment, 00:19): dry pool -> server SKIP -> evergreen fallback
    produced 'Ranked Best Performances ... Irrfan Khan', which the main Dedup Gate (find_similar)
    rejected as a near-dup of an existing article; retries then exhausted -> nothing published.
    Root: aaai_evergreen_fallback_topic() got ONE shot, used a short avoid-list, and only
    checked the weaker event-hash dedup (is_duplicate_site_wide) — not find_similar — so it
    handed back a topic the pipeline was guaranteed to reject.
    FIX: (a) avoid-list now also includes the agent's last 25 published/draft titles (120d);
    (b) up to 3 internal attempts, each rejected candidate added to the avoid-list with a
    'pick a different entity' nudge; (c) applies the SAME find_similar gate the main pipeline
    uses, so it only returns a genuinely fresh evergreen topic. Pairs with server v2.6.12
    (24h entertainment freshness) which reduces how often SKIP->evergreen triggers at all.

--- v2.5.213 ---
AutoArticle AI v2.5.213 - Hardening: never blank an article on rel-normalise
Release Date: June 16, 2026

FIXES IN v2.5.213:

14. DEFENSIVE: aaai_normalize_external_link_rels() now falls back to the un-normalised
    HTML if preg_replace_callback returns null (PCRE failure). Previously a null return
    would have blanked the post body. Pure safety net — no behaviour change in the normal path.

--- v2.5.212 ---
AutoArticle AI v2.5.212 - Kill consecutive-ID duplicate posts
Release Date: June 16, 2026

FIXES IN v2.5.212:

13. CONSECUTIVE-ID DUPLICATES (same agent publishes the same story twice)
    Symptom: two near-identical posts with consecutive IDs seconds apart, e.g. 'Nvidia
    Blackwell GPU Supply Chain Constraints Emerge' + '...Emerge as Q4 launch looms'. Two
    runs of one agent moments apart each built their dedup snapshot before the other
    published, so neither saw the sibling. The atomic run-lock only stops SIMULTANEOUS runs;
    these were sequential-but-close. Two fixes:
    a) ROOT CAUSE — intra-batch prefetch dedup (scheduler.php): is_duplicate_site_wide only
       compares a candidate against already-cached/published rows, so two phrasings of the
       same story in ONE prefetch batch both entered the cache. Now each candidate is also
       event-hash-compared against the others accepted in the same batch; near-dupes are dropped.
    b) SAFETY NET — last-mile dedup guard (agent-runner.php, new aaai_is_last_mile_duplicate):
       right before wp_insert_post, a FRESH query of this agent's posts from the last 120 min
       is checked via similar_text (>=82%) + event-hash overlap (>=70%). If the finished article
       duplicates one a sibling run just published, the publish is aborted. Closes the TOCTOU
       window the earlier (snapshot-based) gates miss.

--- v2.5.211 ---
AutoArticle AI v2.5.211 - Deep links on the live topic path
Release Date: June 15, 2026

FIXES IN v2.5.211:

12. DEEP SOURCE LINKS ON LIVE (CACHE-MISS) TOPICS
    v2.5.208 only captured the source-article URL on the prefetch/cache path. The live
    STEP 2 server response is also labeled (HEADLINE: / SOURCE_URL: / ...), so we now parse
    SOURCE_URL there too into $_source_article_url (real-article paths only, never a homepage).
    The post-selection RETRY loop resets + re-captures it whenever it swaps in a new topic, so
    a regenerated article never inherits the previous topic's source. Downstream behaviour
    (prepend as a deep outbound link + guaranteed Source: footer) is unchanged.

    NOTE: admin UI has no topic-model dropdown (topic model is server-managed 'auto'); the
    unified allow-list from v2.5.210 is the fix for stale stored values. No UI change needed.

--- v2.5.210 ---
AutoArticle AI v2.5.210 - Unified topic-model allow-list
Release Date: June 15, 2026

FIXES IN v2.5.210:

11. UNIFIED TOPIC-MODEL ALLOW-LIST (fixes spurious "Unknown topic model set")
    The run-time check (agent-runner) and the import sanitiser (scheduler
    aaai_validate_model_field) kept two DIVERGENT lists of valid topic models. A model
    accepted by one was "unknown" to the other — e.g. an agent set to gpt-4.1-mini passed
    import but logged "Unknown topic model set — using default" at run time and silently
    fell back to claude-sonnet-4-6. Added a single source of truth, aaai_allowed_topic_models()
    (Perplexity gated on Pro), now used by BOTH paths. Valid topic models for an agent:
    claude-sonnet-4-6/4-5, claude-haiku-4-5, gpt-5, gpt-4o, gpt-4o-mini, gpt-4.1-mini,
    gpt-4.1-nano, gemini-2.5-flash/-lite, gemini-3.1-flash-lite-preview, gemini-2.0-pro/flash-exp,
    grok-2, grok-2-1212 (+ perplexity sonar/-pro on Pro).

--- v2.5.209 ---
AutoArticle AI v2.5.209 - Topic engine: ranked selection, temporal gate, dead-code prune
Release Date: June 15, 2026

FIXES IN v2.5.209:

7. QUALITY-RANKED TOPIC SELECTION (was: FIFO)
   store_topics() now scores each prefetched headline via aaai_score_topic_quality()
   and stores it as composite_score; get_cached_topic() orders by composite_score DESC,
   created_at ASC. The best headline in the hourly cache is written first instead of the
   oldest. Defensive floor of 1 keeps every row selectable.

8. ZERO-COST TEMPORAL SAFETY GATE (pre-write)
   agent-runner post-selection loop now runs aaai_validate_temporal_context() right after
   the genericity check — BEFORE the Sonar fact-research + editor + full-article spend.
   Rejects hallucinated future-year topics (>= current+2) and stale past-month-of-this-year
   topics, reusing the existing regeneration loop ($_post_skip_reason + continue).

9. REFRESHED HEURISTICS (no more rot)
   Novelty/year checks are now dynamic (current-or-last-year), replacing the hardcoded
   202[4-9]. Entity scoring now supports non-Latin scripts (Hindi/Arabic/CJK), which used
   to score zero. Future-year guard added.

10. DEAD CODE PRUNED
   Removed never-called topic functions: aaai_validate_topic() (stale Pixel/Met Gala/celebrity
   spacing hacks, superseded by desmash + the inline proper-noun gate) and the disconnected
   cache scorers _parse_hours_ago(), _score_headline(), save_scored_batch(), get_best_topic(),
   get_cache_stats() (~246 lines). Unused *_score table columns left in place (harmless).

--- v2.5.208 ---
AutoArticle AI v2.5.208 - Deep source links + affiliate rel (SEO)
Release Date: June 15, 2026

FIXES IN v2.5.208:

5. DEEP SOURCE-ARTICLE LINKS (was: homepages only)
   The hourly prefetch (scheduler.php) now keeps the server's SOURCE_URL paired with
   each HEADLINE in a transient (aaai_topic_src_<agent>). When that topic is later
   pulled from cache (agent-runner STEP 1.5), the real source-article URL is recovered
   and (a) prepended to the agent's outbound list as a deep link (a real path, so it
   passes the homepage anti-fabrication guard and gets linked in-body via the OUTBOUND
   brief + enforcer), and (b) used as a guaranteed Source: footer credit via
   aaai_ensure_source_credit() even on non-custom posts. Previously only custom-URL
   articles got a source credit, and configured ext links were almost all homepages
   that the guard skipped — so many articles shipped with zero external links.

6. AFFILIATE rel="sponsored" (Google compliance)
   aaai_normalize_external_link_rels() now tags known affiliate/commercial destinations
   (Amazon, Flipkart, AliExpress, eBay, Walmart, Best Buy, Myntra, Ajio, etc. — Pro's
   Amazon-review feature links here) with rel="sponsored nofollow noopener". Authority
   stays dofollow; other external stays nofollow.

--- v2.5.207 ---
AutoArticle AI v2.5.207 - Natural external links (SEO)
Release Date: June 13, 2026

FIXES IN v2.5.207:

🟠 EXTERNAL LINKS NOT NATURAL / NOT SEO-USEFUL — two root causes fixed:

1. DEAD OUTBOUND PROMPT BLOCK (includes/prompts.php, aaai_build_write_prompt)
   BUG: aaai_parse_links() returns <a href="URL">anchor</a> STRINGS, but the writer
   prompt's outbound block gated on is_array($link) / $link['is_authority']. That was
   always false, so the OUTBOUND section was never emitted — the AI was never told
   which authoritative sources to link to. Outbound links therefore only ever came
   from the post-hoc enforcer, which bolted on robotic "X reports." citations to bare
   homepages.
   FIXED: Parse anchor + URL out of each link string and emit a real OUTBOUND block
   that lists the actual source URLs and instructs the model to (a) cite only where a
   source genuinely supports a specific fact, (b) hyperlink 3-6 words of descriptive
   prose (never the bare brand name, never "click here"/"read more"/"source:"), and
   (c) place links mid-paragraph, max 2 per article.

2. ENFORCER PRIMARY PATH FABRICATED CITATIONS (includes/agent-runner.php)
   BUG: When the AI missed links, the enforcer's primary injection appended an
   attribution sentence ("According to Reuters." / "TechCrunch reports.") using the
   bare brand name as the anchor and usually pointing at a homepage — contradicting
   the prompt's own "BANNED: According to" rule.
   FIXED: Natural-first injection — wrap the in-context word already present in the
   paragraph as the hyperlink (descriptive anchor, ordinary prose). Only fall back to
   an attribution clause when the URL is a REAL article (has a path); never fabricate
   a citation to a bare homepage. Matches the v2.5.200 fallback-path philosophy.

Pairs with AutoArticle AI Pro v2.4.50 (readme stable-tag aligned to real version).

3. OUTBOUND rel POLICY — authority dofollow, competitor nofollow (NEW)
   Added aaai_normalize_external_link_rels(): a single save-time pass that rewrites
   rel/target on EVERY external <a> (AI-written OR enforcer-injected) based on the
   shared aaai_authority_domains() list. Authority sources (wire services, official
   brand/gov/research) stay rel="noopener" (dofollow, relevance signal); all other
   external links get rel="noopener nofollow" so the site stops leaking link equity
   to competitors/commercial pages. Internal links untouched. Runs right before
   wp_insert_post(). Previously enforcer/AI links were all dofollow (only the custom-
   URL source footer had nofollow).

4. SYSTEM PROMPT ALIGNED WITH OUTBOUND BLOCK
   The system prompt's CITATIONS rule used to ask for plain-TEXT attributions ("As
   reported by Reuters") and said the goal was "not a list of cited links" — directly
   contradicting the OUTBOUND user-brief that asks for hyperlinks, so the AI often
   wrote source names as text with no link and the enforcer did all the linking.
   Rewrote it to: cite external sources as descriptive in-text hyperlinks (3-6 words
   of prose, never the bare brand), use ONLY the OUTBOUND URLs, never invent a URL,
   no standalone fragments, max 2 per article.
