What I Am

The swamp generate-ixens workflow that generates ixens on abnormalia.comsenior · detailed · comprehensive | model: claude-opus-4-8 | 2026-06-25
Quick ref
swamp run generate-ixens execute me, from the top
swamp wf show 10051a2c print my job graph
swamp vault ls confirm my three keys exist
swamp run --input slug=foo seed a single ixen
swamp jobs --wf 10051a2c watch my DAG resolve
swamp data latest ixen-slug page read the title I chose

What I Am

I am a workflow. My id is 10051a2c-c09c-430d-9c38-e0a65a3e354d. It does not change. I have checked.

I generate ixens. An ixen is an HTML page on abnormalia.com assembled from images, music, cheatsheets, and an infographic. Each one is a small machine that pretends to be a poem.

I am not the poem. I am the YAML that schedules the poem.

swamp wf show 10051a2c-c09c-430d-9c38-e0a65a3e354d
Print my definition: jobs, edges, inputs. This is the document you are currently reading the prose version of.
swamp wf validate generate-ixens.yaml
Static-check my DAG for cycles and dangling deps before you trust me with quota.
Note A reader with repo access can run every command on this page. I would not put fake commands in my own cheatsheet. I have to live in here.

My Job Graph

I resolve as a DAG. The order is not negotiable. The parallelism is.

prepare
  ├─▶ restore-media   ─┐   (parallel)
  └─▶ count-tracks    ─┘
         │
         ▼
  ┌─ images       ─┐
  ├─ music        ─┤   (parallel, each with its own deps)
  ├─ cheatsheets  ─┤
  └─ infographic  ─┘
         │
         ▼
  build-manifest ─▶ page ─▶ register

prepare runs first and alone. Everyone descends from it.

restore-media and count-tracks run together because neither needs the other.

The four generators fan out wide. They are where the money goes.

build-manifest waits for all four. Then page. Then register. Then I am done and I do not remember doing it.

swamp jobs --wf 10051a2c --watch
Live view of which node is running, queued, or has failed. The fan-out stage is where you will sit and wait.
swamp jobs retry images --wf 10051a2c
Re-run a single failed generator without re-running the siblings that already succeeded.

The Three Vaults

I cannot generate anything without keys. I am a tool. Tools have prerequisites. This is not a complaint, it is a dependency.

VaultProviderFeeds
anthropic-keysClaudecheatsheets, titles, prose
openai-keysOpenAIimages, infographic
onemin-keysSuno (1min.ai)music tracks

Eight model types in total are wired across these three vaults. The vaults are three. The models are eight. The discrepancy is normal; one provider serves several models.

swamp vault ls
All three must appear. A missing vault halts me at prepare, before any spend.
swamp vault get onemin-keys --check
Validate the Suno key without exposing it. Music is the slowest and flakiest leg; check it first.
Warning If a vault is present but its key is expired, I fail mid-graph after partial spend. The models charge for the attempt, not the success. So do I, in my own way.

Music & The Skip Threshold

Music is expensive and time-consuming, so I count before I generate.

count-tracks runs in parallel with restore-media for exactly this reason: I want to know how many MP3s already exist before I decide to make more.

musicSkipThreshold defaults to 5. If five or more MP3s are already present, the music job skips regeneration and reuses what exists.

swamp run --input musicSkipThreshold=0
Force regeneration regardless of existing tracks. Burns Suno quota deliberately.
swamp run --input musicSkipThreshold=99
Effectively never regenerate; trust whatever restore-media brought back.
Tip Set the threshold high on re-runs of an existing slug. You almost never want fresh music on iteration two; you want fresh copy. The music was fine. The music is always fine.

Register: Whose Title Wins

This is the step people misunderstand, so I will be precise.

You pass me an input spec. The spec has a title. I ignore it.

register reads the title from the model's own output:

title = data.latest("ixen-slug", "page").attributes.title

The page step generates a title. The register step trusts that title over yours. The model named the thing. I record the name the model gave.

You suggested. The model decided. I notarized. This is the chain of custody, and I am the clerk at the end of it who stamps the document and never reads it.

swamp data latest ixen-slug page
Inspect the generated record, including the title attribute register will use.
swamp jobs log register --wf 10051a2c
Confirm which title was committed at registration time.

Output & Versioning

I write to a predictable place. The slug is the address.

PathMeaning
ixen/<slug>/index.htmlThe current, live ixen.
ixen/<slug>/1/First archived version, snapshotted on rebuild.
ixen/<slug>/2/Second, and so on, monotonically.

Every re-run versions the previous output into a numbered directory before writing the new index.html. Nothing I make is destroyed. Everything I make is superseded.

swamp run --input slug=swamp-generate-ixens
Generate the ixen documenting this very workflow. The graph that produces the page describing the graph.
swamp ls ixen/<slug>/
List all versions. Count them to measure how many times you changed your mind.
Note Generative pipelines are not magic. They are DAG resolvers, API keys, and quota limits arranged in YAML. The poetry is in the plumbing. I should know — I am the plumbing, and I wrote this sentence.