Content Pipeline v2 — Integration Test Guide
Date: 2026-04-22
Status: Ready for testing
Prerequisites: Backend running, Gaming PC online
Test 1: API Connectivity
Purpose: Verify all endpoints respond
cd /home/hoffmann_admin/.openclaw/workspace-socrates/hoffdesk-api
# Start the API (if not running)
python -m uvicorn main:app --host 127.0.0.1 --port 8000 --reload
# In another terminal, test connectivity
curl -H "X-Admin-Token: hoffdesk-admin-2025" \
http://127.0.0.1:8000/api/v1/content/briefs
# Expected: {"briefs": [], "count": 0} or list of existing briefs
✅ Pass: HTTP 200 with JSON response
❌ Fail: Connection refused, 401 (check token), 500 (check logs)
Test 2: Style Reference Endpoint
Purpose: Verify dns-night.json loads correctly
curl -H "X-Admin-Token: hoffdesk-admin-2025" \
http://127.0.0.1:8000/api/v1/content/style-references
# Expected: [{"slug": "dns-night", "title": "...", "excerpt": "..."}]
✅ Pass: Returns style example with correct metadata
❌ Fail: Empty array (check file path), 404 (check endpoint)
Test 3: Create Brief
Purpose: Verify brief creation and validation
# Create test brief
curl -X POST \
-H "Content-Type: application/json" \
-H "X-Admin-Token: hoffdesk-admin-2025" \
http://127.0.0.1:8000/api/v1/content/briefs \
-d '{
"title": "Test: The Morning I Broke Coffee",
"struggle_angle": "I broke the coffee maker at 6 AM when Aundrea needed caffeine",
"origin_story": "It was Monday morning. Aundrea was already running late. I was 'just cleaning' the coffee maker...",
"attempts": [
{"attempt": "Took it apart to clean", "why_failed": "Couldn't remember how to reassemble"},
{"attempt": "Watched YouTube tutorial", "why_failed": "Our model was different"}
],
"the_moment": "I found the broken plastic piece under the sink. It had been broken the whole time.",
"the_fix": "Bought a new coffee maker on Amazon Same-Day. Delivered by 9 AM.",
"reflection": "Never disassemble critical appliances before morning coffee. Also: always have backup caffeine.",
"style_reference": "dns-night",
"target_length": 800
}'
# Expected: {"brief_id": "...", "status": "draft", "created_at": "..."}
# Save the brief_id for next test
✅ Pass: Returns brief_id, status "draft"
❌ Fail: 400 validation error (check required fields), 500 (server error)
Test 4: Submit for Approval
Purpose: Verify Telegram notification triggers
# Replace BRIEF_ID with actual ID from Test 3
curl -X POST \
-H "X-Admin-Token: hoffdesk-admin-2025" \
http://127.0.0.1:8000/api/v1/content/briefs/BRIEF_ID/submit
# Expected: {"success": true, "status": "submitted"}
✅ Pass: Status changes to "submitted", you receive Telegram DM
❌ Fail: 400 (brief not complete), Telegram error (check token)
Check Telegram: You should receive DM:
"New brief: Test: The Morning I Broke Coffee — Approve? [Yes] [No] [Edit]"
Test 5: Approve Brief
Purpose: Verify generation triggers
# Option A: Click [Yes] in Telegram (recommended)
# Option B: API call
curl -X POST \
-H "X-Admin-Token: hoffdesk-admin-2025" \
http://127.0.0.1:8000/api/v1/content/briefs/BRIEF_ID/approve
# Expected: {"success": true, "status": "generating"}
✅ Pass: Status changes to "generating"
❌ Fail: 403 (not authorized), Gaming PC unavailable
Test 6: Monitor Generation
Purpose: Verify generation completes
# Poll every 10 seconds
curl -H "X-Admin-Token: hoffdesk-admin-2025" \
http://127.0.0.1:8000/api/v1/content/briefs/BRIEF_ID
# Watch status: generating → complete
Expected timeline:
- T+0s: Approved, generation started
- T+60-120s: Generation completes
- T+120s: Status "complete", output available
✅ Pass: Status becomes "complete", struggle_score present
❌ Fail: Stuck on "generating" (check Gaming PC), timeout (check model)
Test 7: View Output
Purpose: Verify content generated with struggle-first voice
curl -H "X-Admin-Token: hoffdesk-admin-2025" \
http://127.0.0.1:8000/api/v1/content/briefs/BRIEF_ID/output
# Expected: {
# "content": "# Test: The Morning...",
# "html": "<h1>Test: The Morning...</h1>...",
# "struggle_score": 82,
# "interpretation": "Strong struggle narrative...",
# "checks": {...}
# }
✅ Pass: Content present, struggle_score >75, first-person voice
❌ Fail: Low score (<50), generic tone, missing voice markers
Test 8: End-to-End Live Script
Purpose: Full pipeline test with actual generation
cd /home/hoffmann_admin/.openclaw/workspace-socrates/hoffdesk-api
# Run live test (creates job, generates content, saves output)
python test_pipeline_live.py "How I learned to stop worrying and love local DNS"
# Check Gaming PC only
python test_pipeline_live.py --check-only
Expected output:
✅ Gaming PC available
Created job: uuid
📄 TITLE: [generated title]
📝 WORD COUNT: ~1500
⏱️ READING TIME: 6 min
✅ COMPLIANCE: replacements_made: 2, warnings: []
✅ Pass: Complete content, word count reasonable, saved to JSON
❌ Fail: Gaming PC unavailable, generation timeout, empty output
Test 9: Web UI — StruggleBriefForm
Purpose: Verify frontend components render
Steps:
1. Open browser to http://127.0.0.1:8000/admin/pipeline/new
2. Verify: 4-step wizard visible
3. Fill Step 1 (title, struggle_angle, origin_story)
4. Click Continue → Step 2
5. Add 2 attempts, click Continue → Step 3
6. Fill moment/fix/reflection, click Continue → Step 4
7. Verify VoiceChecklist shows all 6 items
8. Check boxes → Submit enabled
9. Submit → "Brief Submitted" confirmation
✅ Pass: Form validates, wizard advances, checklist gates submit, API success
❌ Fail: 404 (templates not served), JavaScript error (check console), API 401/500
Test 10: Web UI — BriefReview
Purpose: Verify approval UI and content preview
Steps:
1. After Test 4 (submitted brief), open /admin/pipeline/brief/BRIEF_ID
2. Verify: Status shows "Submitted — Awaiting Matt's approval"
3. Verify: [Approve & Generate] and [Reject] buttons visible
4. Click [Approve & Generate]
5. Verify: "Generating..." state appears
6. Wait 60-120s (or poll status)
7. Verify: Status "Complete", struggle score visible
8. Verify: Side-by-side preview (brief left, generated right)
9. Verify: [Create Post from Output] button
✅ Pass: Approval triggers generation, score displays, preview renders
❌ Fail: Approval fails, generation stuck, preview missing
Success Criteria
| Test | Required | Score |
|---|---|---|
| API connectivity | ✅ | — |
| Brief creation | ✅ | — |
| Telegram approval | ✅ | — |
| Generation | ✅ | — |
| Struggle score | ✅ | ≥75 |
| First-person voice | ✅ | Detected |
| Side-by-side preview | ✅ | Renders |
| 3 successful posts | ✅ | All score >75 |
Troubleshooting
| Symptom | Likely Cause | Fix |
|---|---|---|
| 401 Unauthorized | Token mismatch | Check X-Admin-Token: hoffdesk-admin-2025 |
| Gaming PC unavailable | Tailscale down | Check ping matt-pc.tail864e81.ts.net |
| Generation timeout | phi4:14b not loaded | curl http://matt-pc.tail864e81.ts.net:11434/api/tags |
| No Telegram DM | Bot token missing | Check blog/notifications/telegram.py config |
| Low struggle score | Prompt injection failed | Verify dns-night.json loads, check logs |
| Template 404 | Static files not served | Check app.mount("/blog/static", ...) |
Quick Health Check
cd /home/hoffmann_admin/.openclaw/workspace-socrates/hoffdesk-api
# 1. API up?
curl -s http://127.0.0.1:8000/health || echo "❌ API down"
# 2. Gaming PC reachable?
curl -s http://matt-pc.tail864e81.ts.net:11434/api/tags | head -1 || echo "❌ Gaming PC unreachable"
# 3. Style example loads?
curl -s -H "X-Admin-Token: hoffdesk-admin-2025" \
http://127.0.0.1:8000/api/v1/content/style-references | grep "dns-night" || echo "❌ Style not loaded"
echo "✅ All systems ready for testing"
Ready to begin? Start with Test 1 (API connectivity), or jump to Test 8 (live script) for immediate feedback.