Make every tenth published post a guest post, chosen without a human - #208
Merged
Merged
Conversation
Guest posting was a manual loop: open the project, read the ranked
opportunities, pick a partner, pick one of the crossed topics, click. Every
piece of judgement in that loop was already computed — findGuestPostOpportunities
ranks the partners and crosses the seed keywords — so what the click actually
contributed was a decision to proceed and a choice of the top item. Both are now
automatic and both run on the publishing schedule.
The cadence is counted from articles already on file rather than from a counter
column, so it is self-correcting: a failed generation, a manual post or a
restored backup all move the count and the rhythm follows reality instead of a
number somebody has to remember to increment. Guest posts count toward the ten
themselves — "every 10th post" means every 10th post, not every 10th own-blog
post plus extras.
Three decisions worth arguing with, all tested:
* **A slot is never spent on a guest post that cannot be placed.** No partner,
no unused topic, or everyone written for recently, and the site publishes to
its own blog as it always did. The schedule is what a customer is paying
for; silence would be the worse failure, so this falls through rather than
skipping.
* **Nothing is published outside the network.** A target must be
backlinks_enabled, active and not flagged for inappropriate content — the
same filter the manual matcher applies. Partners opted into receiving guest
posts; strangers did not, and an automated loop must not be the thing that
forgets the difference.
* **A partner is not written for twice inside thirty days.** Ranking is stable
and the matcher is stateless by design, so without a cooldown the
top-ranked partner would receive a post every ten slots for ever. That is
the shape that gets a link network discounted, and it is exactly the failure
mode automation introduces — a human clicking would have noticed.
The manual path's ledger (lx_guest_post_request) is reused rather than
duplicated, so a human and the cron cannot independently commission the same
article.
A cadence count that errors resolves to "not a guest post". That direction is
deliberate: failing closed keeps the customer's own blog publishing, where
failing open would redirect every post on the schedule to somebody else's
domain.
`guest_posts_unavailable` is reported by the cron rather than swallowed. A
number that climbs every day means the partner network has stopped producing
matches, and that is invisible from the article count alone.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ThreatCrush Security Scan35 finding(s) HIGH/CRITICAL: 3 | MEDIUM: 23 | LOW: 9
Snippets are redacted; ThreatCrush never prints matched credential material. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Guest posting was a manual loop: open the project, read the ranked opportunities, pick a partner, pick a crossed topic, click. Every piece of judgement in that loop was already computed —
findGuestPostOpportunitiesranks partners and crosses seed keywords. What the click contributed was a decision to proceed and a choice of the top item. Both are now automatic, on the publishing schedule.Cadence
Counted from articles already on file, not a counter column — so it self-corrects. A failed generation, a manual post, a restored backup all move the count, and the rhythm follows reality rather than a number someone must remember to increment. Guest posts count toward the ten themselves: every 10th post means every 10th post, not every 10th own-blog post plus extras.
Three decisions worth arguing with (all tested)
backlinks_enabled,active, and not flagged for inappropriate content — the same filter the manual matcher applies. Partners opted in; strangers didn't, and an automated loop mustn't be the thing that forgets the difference.Smaller things
lx_guest_post_request) is reused, not duplicated, so a human and the cron can't independently commission the same article.guest_posts_unavailableis reported by the cron rather than swallowed. A number climbing daily means the partner network has stopped producing matches, which is invisible from the article count alone.1,675 tests pass (8 new);
tsc --noEmitclean.🤖 Generated with Claude Code