📄 2026-04-22.md 4,269 bytes Apr 22, 2026 📋 Raw

2026-04-22 - Blog Admin & Content Generation

Morning Session

Admin Login Flow - COMPLETE

  • Fixed login template to accept JSON POST with password field
  • Added get_post_counts() helper for sidebar stats
  • Fixed all admin routes to include draft_count, published_count, total_count
  • Login page: https://notes.hoffdesk.com/admin/blog/login
  • Token: hoffdesk-admin-2025
  • Login redirects to dashboard with token in URL: ?token=hoffdesk-admin-2025

Magic Wand Integration - IN PROGRESS

  • Backend: 5-stage LocalAI pipeline is live at /admin/content/generate
  • Added Magic Wand CTA to admin dashboard
  • Added AI Tools section to sidebar
  • Issue discovered: Frontend JavaScript uses vanilla fetch(), not HTMX
  • Frontend HTMX interceptor adds X-Admin-Token header, but Magic Wand fetch doesn't
  • Template has {{ admin_token }} variable available
  • Root cause: Magic Wand fetch call missing X-Admin-Token header OR not using ?token= URL param
  • Fix needed: Daedalus to add header to fetch or ensure template renders token in URL

Token Auth Architecture

  • Content router checks: request.query_params.get("token") OR request.headers.get("X-Admin-Token")
  • Working: curl -H "X-Admin-Token: hoffdesk-admin-2025" ...
  • Working: curl "...?token=hoffdesk-admin-2025" ...
  • Broken: Neither provided (causes 401 → frontend redirect loop)

Next Steps

  • Daedalus to fix Magic Wand fetch to include auth token
  • Test end-to-end content generation from admin UI

Afternoon Session - Content Pipeline v2 Implementation

Final Brief Review

  • Reviewed Wadsworth's content-pipeline-v2-final.md spec
  • Created response doc with 5 clarifications needed
  • Matt approved implementation direction

Phase 0: Foundation (COMPLETE)

SQLite Schema
- Verified existing content_briefs_v2 table in blog/storage.py
- Schema matches spec: id, title, struggle_angle, origin_story, attempts, the_moment, the_fix, reflection, voice_checklist, status, style_reference, target_length, created_by, created_at, approved_at, approved_by, generation_job_id, struggle_score, content_output, content_html, published_post_id

Pydantic Models (existing in blog/models.py)
- BriefAttempt, VoiceChecklist, CreateBriefRequest, UpdateBriefRequest
- BriefSummary, BriefDetail, BriefListResponse, BriefDetailResponse
- SubmitBriefResponse, ApproveBriefResponse, RejectBriefResponse, BriefOutputResponse

Phase 1: Backend Core (COMPLETE)

New Components Created:

Module File Purpose
Enhanced Validation blog/validation/brief.py Struggle-first checks, voice checklist validation
Struggle Scorer blog/metrics/struggle.py Heuristic calculation (I-statements, temporal markers, struggle patterns, cost mentions, admissions)
Telegram Notifier blog/notifications/telegram.py Approval DMs to Matt, author notifications
Style Loader blog/style/loader.py JSON style example loading, few-shot context
Style Example shared/style-examples/dns-night.json Template for "DNS Night" article

API Endpoints Live:
- POST /api/v1/content/briefs — Create brief
- GET /api/v1/content/briefs — List briefs
- GET /api/v1/content/briefs/{id} — Get brief
- POST /api/v1/content/briefs/{id}/submit → Telegram DM to Matt for approval
- POST /api/v1/content/briefs/{id}/approve → Approve + trigger generation (Matt only)
- POST /api/v1/content/briefs/{id}/reject → Reject with feedback (Matt only)
- GET /api/v1/content/briefs/{id}/output — Get generated content
- GET /api/v1/content/style-references — List available styles

Status: MVP Backend Complete

  • All brief CRUD operations functional
  • Telegram approval flow integrated
  • Struggle-first validation active
  • Style example template ready (needs Matt's content)

Blockers for Phase 2

  • dns-night.json needs actual content from Matt's article
  • Daedalus to implement frontend components (StruggleBriefForm, VoiceChecklist, etc.)

Next Steps

  1. Matt fills dns-night.json with actual article structure
  2. Phase 2: Prompt template v2 + generation integration
  3. Phase 3: Daedalus frontend integration

Session end: 16:39 UTC