Files
rose-ash/lib/host/blog.sx
giles fac15d6140
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 1m0s
host: typed Ghost import — POST /import lands old posts as first-class Articles
The genesis-import seam for the loops/radar migration (NOTE-blog-types-for-radar.md):
an old Ghost post lands not as bare sx_content but as a TYPED Article.

- host/blog-import-post!(ghost-dict): put! the {slug,title,sx_content,status} record +
  is-a article + Ghost columns -> article :field-values (custom_excerpt->subtitle,
  feature_image->hero) + tags -> tag-posts with tagged edges. Idempotent. The Ghost body
  is already sx_content ((~kg_cards/kg-*) from the Python lexical_to_sx migration), so we
  carry it as-is. host/blog-import-all! for batches.
- POST /import (guarded): body = a text/sx LIST of Ghost column dicts (radar's Postgres
  reader serialises rows to this); imports each typed; -> {:ok true :data {:imported N
  :slugs (...)}}. Runs in the serving handler (IO resolver installed) so the per-post/
  per-tag loops are JIT-safe.

Verified live-path end-to-end (ephemeral SX_SERVING_JIT=1): POST a fixture Ghost post ->
imported 1; the post's edit form is pre-filled (subtitle='An imported standfirst',
hero=the feature image), its page renders the subtitle standfirst via the article template
+ the body, and its tags (News/SX) land in the graph. Tests added; full blog suite still
blocked by box contention.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 15:05:02 +00:00

86 KiB