Embedding locally rather than by API
sentence-transformers runs inside the Actions job, so embedding costs nothing and adds no rate limit to the critical path. The trade is that the embedding dimension becomes load-bearing infrastructure: all-mpnet-base-v2 emits 768 dimensions and the articles.embedding column must match it, so changing model is a migration and a re-embed of every row, not a config change.