Part 5 · Reference
Contracts and the kill list
Per-channel bounds, the fan-out map, and every deterministic slop pattern.
01What it is
The fifteen schema contracts with their bounds, which artifact type each channel receives, and the nine kill-list patterns with their exact regular expressions.
02Why it exists
The bounds are platform reality, so knowing them tells you why a draft was rejected rather than leaving it as a mystery.
The kill-list patterns are printed in full because a founder should be able to check their own writing against the same rules, and because a rule you cannot read is a rule you cannot argue with.
03How to use it
- 01Find the contract for the channel you are looking at.
- 02Check required and forbidden elements when a draft fails.
- 03Read the kill-list pattern when a violation code appears and the reason is not obvious.
04What good looks like
- You give it
- A LinkedIn post rejected with hook_too_long.
- You get
- The contract shows the hook limit and you can see by how much it missed.
- Why
- Structural limits are part of the contract and printed here.
Derived from the rules in the code
05What weak looks like, and what it costs
- You give it
- Assuming a rejection is the model being fussy.
- You get
- The same rejection repeats, because the rule is deterministic and does not vary.
- Why
- The slop gate is code. It refuses the same construction every time.
Derived from the rules in the code
06Read next
Schema contracts
Per-artifact rules. The length bounds are real platform constraints rather than preferences.
| Name | Value | What it does |
|---|---|---|
| linkedin_post | 300–3000 chars · voice ≥ 0.55 | needs hook, specific_claim · refuses hashtag_wall, engagement_bait, link_in_first_line |
| x_thread | 120–280 chars · voice ≥ 0.5 | needs hook · refuses hashtag_wall, engagement_bait |
| newsletter_item | 400–6000 chars · voice ≥ 0.55 | needs hook, specific_claim · refuses engagement_bait |
| blog_outline | 300–8000 chars · voice ≥ 0.4 | needs headings · refuses engagement_bait |
| short_video_script | 200–1200 chars · voice ≥ 0.45 | needs hook · refuses hashtag_wall |
| cold_email | 180–1200 chars · voice ≥ 0.5 | needs one_ask, dated_signal · refuses flattery_opener, fabricated_familiarity, engagement_bait |
| linkedin_dm | 120–900 chars · voice ≥ 0.5 | needs one_ask · refuses flattery_opener, fabricated_familiarity |
| ad_copy | 60–600 chars · voice ≥ 0.35 | needs one_ask · refuses engagement_bait |
One idea, per channel
Which artifact type each channel receives. Data, so adding a channel is adding a row.
| Name | Value | What it does |
|---|---|---|
| linkedin_organic | linkedin_post | |
| x_organic | x_thread | |
| newsletter | newsletter_item | |
| blog_seo | blog_outline | |
| tiktok | short_video_script |
Slop gate: the kill list
Deterministic patterns, refused on every draft with no model involved. A deterministic check cannot have an off day.
| Name | Value | What it does |
|---|---|---|
| not_just_x_its_y | \bit(?:'s|\s+is)\s+not\s+(just\s+)?(?:a|an|the)?[^.,;\n]{2,60}[,—-]\s*it(?:'s|\s+is)\b | The "it is not X, it is Y" construction. Most recognisable AI tell there is. |
| heres_the_thing | (^|\n|\.\s+)here(?:'s|\s+is)\s+the\s+thing\b | "Here's the thing" is throat-clearing. Delete it and start at the thing. |
| part_everyone_misses | \bthe\s+part\s+(that\s+)?(everyone|most\s+people|nobody)\s+(is\s+)?(missing|misses|gets\s+wrong)\b | Claims a secret the reader is missing. Assert the point instead. |
| lets_dive_in | \blet(?:'s|\s+us)\s+(dive|jump)\s+(in|into)\b | "Let's dive in" is filler before the content starts. |
| in_an_era_where | \bin\s+(an?\s+)?(era|world|age|time)\s+where\b | Opens on a generality nobody disputes. Start with the specific. |
| rhetorical_answered | \?[\s\n]*(it(?:'s|\s+is)\s+not|the\s+truth\s+is|the\s+reality\s+is|simple[.:]|because\b) | A question answered in the next breath. Say the thing. |
| praising_the_reader | \b(you(?:'re| are)\s+(smart|clever|sharp)(er)?\s+(enough|than)|you\s+already\s+know\s+(this|that)|as\s+a\s+savvy\s+\w+|if\s+you(?:'re| are)\s+reading\s+this,\s+you)\b | Flatters the reader instead of telling them something. |
| excited_to_announce | \bwe(?:'re| are)\s+(so\s+|really\s+|incredibly\s+)?excited\s+to\s+(announce|share)\b | Nobody is excited on the reader's behalf. State what shipped. |
| em_dash_connector | (—[^—\n]{1,80}){3,} | Em dash used as the default connector. Vary the punctuation. |