Phase B: AI press-release rewrite pipeline
Pluggable rewrite client (Anthropic default, ollama/openrouter stubs)
using claude-opus-4-7 with prompt caching on system prompt + style guide.
Routes the raw submission through:
1. bb.ai_original_submissions — raw never edited
2. bb.ai_rewrite_jobs — every attempt logged with token counts
3. quality gates — AI-tell banned-word check + heuristic
AI-detector score (threshold 0.65)
4. regenerate up to 3x — on banned words or detector trip
5. bb.ai_rewritten_articles — status ai_rewritten_pending_review
6. /admin/review-queue — list + detail page with approve / reject /
needs-human actions; on approve, the
original submission is FK-linked to the
published rewrite
New files only — no existing routes or contributor flow modified.
Persona auto-selection routes by beat keywords; 6 personas seeded
(marcus-halverson, elena-vasquez, darren-okafor, sarah-quinn, mike-trayton,
priya-rao) with SVG monogram avatars in public/assets/images/personas/.
Smoke test (Matrox / ST 2110 sample press release):
- persona auto-routed to darren-okafor (protocols-specs)
- anthropic 22.3s, in=2616 / out=1372 tokens
- gates passed first try, score=0.000, no banned words
- review_queue row created
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
16
public/assets/images/personas/darren-okafor.svg
Normal file
16
public/assets/images/personas/darren-okafor.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" role="img" aria-label="Darren Okafor">
|
||||
<defs>
|
||||
<linearGradient id="do-bg" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0" stop-color="#064e3b"/>
|
||||
<stop offset="1" stop-color="#047857"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="do-ring" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0" stop-color="#6ee7b7"/>
|
||||
<stop offset="1" stop-color="#059669"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="256" height="256" rx="128" fill="url(#do-bg)"/>
|
||||
<circle cx="128" cy="128" r="118" fill="none" stroke="url(#do-ring)" stroke-width="3" opacity="0.45"/>
|
||||
<text x="128" y="148" text-anchor="middle" font-family="Georgia, 'Times New Roman', serif" font-size="92" font-weight="700" fill="#d1fae5" letter-spacing="-2">DO</text>
|
||||
<text x="128" y="200" text-anchor="middle" font-family="Helvetica, Arial, sans-serif" font-size="14" font-weight="600" fill="#6ee7b7" letter-spacing="3">PROTOCOLS / SPECS</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 996 B |
16
public/assets/images/personas/elena-vasquez.svg
Normal file
16
public/assets/images/personas/elena-vasquez.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" role="img" aria-label="Elena Vasquez">
|
||||
<defs>
|
||||
<linearGradient id="ev-bg" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0" stop-color="#3b0764"/>
|
||||
<stop offset="1" stop-color="#9333ea"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="ev-ring" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0" stop-color="#f0abfc"/>
|
||||
<stop offset="1" stop-color="#a21caf"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="256" height="256" rx="128" fill="url(#ev-bg)"/>
|
||||
<circle cx="128" cy="128" r="118" fill="none" stroke="url(#ev-ring)" stroke-width="3" opacity="0.45"/>
|
||||
<text x="128" y="148" text-anchor="middle" font-family="Georgia, 'Times New Roman', serif" font-size="92" font-weight="700" fill="#fae8ff" letter-spacing="-2">EV</text>
|
||||
<text x="128" y="200" text-anchor="middle" font-family="Helvetica, Arial, sans-serif" font-size="14" font-weight="600" fill="#d8b4fe" letter-spacing="3">STREAMING / OTT</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 994 B |
16
public/assets/images/personas/marcus-halverson.svg
Normal file
16
public/assets/images/personas/marcus-halverson.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" role="img" aria-label="Marcus Halverson">
|
||||
<defs>
|
||||
<linearGradient id="mh-bg" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0" stop-color="#0f172a"/>
|
||||
<stop offset="1" stop-color="#1e3a5f"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="mh-ring" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0" stop-color="#60a5fa"/>
|
||||
<stop offset="1" stop-color="#1d4ed8"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="256" height="256" rx="128" fill="url(#mh-bg)"/>
|
||||
<circle cx="128" cy="128" r="118" fill="none" stroke="url(#mh-ring)" stroke-width="3" opacity="0.45"/>
|
||||
<text x="128" y="148" text-anchor="middle" font-family="Georgia, 'Times New Roman', serif" font-size="92" font-weight="700" fill="#e2e8f0" letter-spacing="-2">MH</text>
|
||||
<text x="128" y="200" text-anchor="middle" font-family="Helvetica, Arial, sans-serif" font-size="14" font-weight="600" fill="#94a3b8" letter-spacing="3">INDUSTRY VETERAN</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 998 B |
16
public/assets/images/personas/mike-trayton.svg
Normal file
16
public/assets/images/personas/mike-trayton.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" role="img" aria-label="Mike Trayton">
|
||||
<defs>
|
||||
<linearGradient id="mt-bg" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0" stop-color="#7f1d1d"/>
|
||||
<stop offset="1" stop-color="#dc2626"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="mt-ring" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0" stop-color="#fca5a5"/>
|
||||
<stop offset="1" stop-color="#b91c1c"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="256" height="256" rx="128" fill="url(#mt-bg)"/>
|
||||
<circle cx="128" cy="128" r="118" fill="none" stroke="url(#mt-ring)" stroke-width="3" opacity="0.45"/>
|
||||
<text x="128" y="148" text-anchor="middle" font-family="Georgia, 'Times New Roman', serif" font-size="92" font-weight="700" fill="#fee2e2" letter-spacing="-2">MT</text>
|
||||
<text x="128" y="200" text-anchor="middle" font-family="Helvetica, Arial, sans-serif" font-size="14" font-weight="600" fill="#fca5a5" letter-spacing="3">LIVE / SPORTS</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 991 B |
16
public/assets/images/personas/priya-rao.svg
Normal file
16
public/assets/images/personas/priya-rao.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" role="img" aria-label="Priya Rao">
|
||||
<defs>
|
||||
<linearGradient id="pr-bg" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0" stop-color="#0c4a6e"/>
|
||||
<stop offset="1" stop-color="#0891b2"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="pr-ring" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0" stop-color="#67e8f9"/>
|
||||
<stop offset="1" stop-color="#0e7490"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="256" height="256" rx="128" fill="url(#pr-bg)"/>
|
||||
<circle cx="128" cy="128" r="118" fill="none" stroke="url(#pr-ring)" stroke-width="3" opacity="0.45"/>
|
||||
<text x="128" y="148" text-anchor="middle" font-family="Georgia, 'Times New Roman', serif" font-size="92" font-weight="700" fill="#cffafe" letter-spacing="-2">PR</text>
|
||||
<text x="128" y="200" text-anchor="middle" font-family="Helvetica, Arial, sans-serif" font-size="14" font-weight="600" fill="#67e8f9" letter-spacing="3">POST-PRODUCTION</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 990 B |
16
public/assets/images/personas/sarah-quinn.svg
Normal file
16
public/assets/images/personas/sarah-quinn.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 256 256" role="img" aria-label="Sarah Quinn">
|
||||
<defs>
|
||||
<linearGradient id="sq-bg" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0" stop-color="#451a03"/>
|
||||
<stop offset="1" stop-color="#b45309"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="sq-ring" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0" stop-color="#fcd34d"/>
|
||||
<stop offset="1" stop-color="#d97706"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="256" height="256" rx="128" fill="url(#sq-bg)"/>
|
||||
<circle cx="128" cy="128" r="118" fill="none" stroke="url(#sq-ring)" stroke-width="3" opacity="0.45"/>
|
||||
<text x="128" y="148" text-anchor="middle" font-family="Georgia, 'Times New Roman', serif" font-size="92" font-weight="700" fill="#fef3c7" letter-spacing="-2">SQ</text>
|
||||
<text x="128" y="200" text-anchor="middle" font-family="Helvetica, Arial, sans-serif" font-size="14" font-weight="600" fill="#fcd34d" letter-spacing="3">BUSINESS / M&A</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 995 B |
Reference in New Issue
Block a user