feat(sales): subscription gap audit + four workflows - #130
Open
bpalmer77fluid wants to merge 2 commits into
Open
feat(sales): subscription gap audit + four workflows#130bpalmer77fluid wants to merge 2 commits into
bpalmer77fluid wants to merge 2 commits into
Conversation
Finds the products a merchant sells that run out and get rebought but that no customer can put on a schedule — the recurring revenue already sitting in the catalog. Most merchants run half a razor-and-blades business: the refill is on subscription and every other consumable is one-time-only. Folder shape, because the term lists and the SQL are lookup material the agent does not need in context every turn: sales/subscription-gap/SKILL.md sales/subscription-gap/references/replenishment-classes.md sales/subscription-gap/references/measuring-cadence.md workflows/subscription-gap.workflow.json (8 steps, optional) Design notes worth reviewing: - Structure beats text. is_bundle / product_bundles / bundle_config are authoritative; text classification is the fallback, because Fluid returns category: null and tags: [] on a real import. - Text matches are SCORED, not hand-ordered: title evidence outranks description evidence, longer terms outrank shorter. Hand-ordering failed in both directions on a real catalog — it called two wax kits bundles (hiding real revenue) and called a genuine multi-product set a treatment (which would have put a subscription on a bundle). - Anything the title did not decide returns NEEDS REVIEW rather than a guess. - Subscription coverage is checked at product AND variant level; a plan attaches at either, and checking only one under-reports coverage. - The skill refuses to quote a revenue number without an attach rate and buyer count from the merchant's own order history, and gives the defensible SKU-and-list-price version instead. - Add-on is offered BEFORE any skip or pause option: only adding an item creates incremental revenue. Verified against a live 31-SKU Fluid catalog and a 24-SKU personal-care catalog. Catalog validation and the 14 contract tests pass locally.
… SMS
Three channel workflows built and run against a live Fluid company today, added
alongside the subscription-gap skill already in this PR.
- setup-tiktok-shop (8 steps) — screen the catalog against TikTok commerce
policy, pick the category gate and its real timeline, set the creator
qualification gate and commission tiers from live prices, build the enrollment
page and merchant console, close with an honest blocker list.
- setup-instagram-affiliate (7 steps) — Meta commerce policy is a different
ruleset, not TikTok's with the names swapped: Meta ended native checkout in
Aug 2025, so the work is link attribution rather than order reconciliation.
- subscription-sms (10 steps) — detect the messaging rail, clear the two
blockers that actually stop SMS launches (sender registration and consent),
scope the actions, deploy a branded droplet.
What the live runs taught, encoded in the step prompts:
- pin /api/v202604/company/products + /{id}. The shop-host payload embeds the
entire country atlas (~25KB/product) and the admin LIST endpoint has no
variants[] at all. Picking wrong does not error.
- description is an object with .body, not a string; price is null at product
level and lives in variants[].variant_countries keyed by country code. Read
either naively and you get confident, precise-looking, wrong output.
- eligibility and reviewability stay separate numbers — a review flag must never
reduce the eligible count.
- weight-management products are prohibited outright on TikTok Shop, not
restricted.
- drop rank-based creator gating when the company has no distributor ranks
rather than offering a qualification path that does not exist.
- do not recommend on-platform autoship after proving the subscription plans it
needs cannot be created — Fluid has no endpoint for that.
- enrollment belongs on the storefront, never behind admin login: creators have
no admin session.
- a launch checklist that reads clean while a 21-day approval sits unstarted is
worse than no checklist.
Catalog validation and the 14 contract tests pass locally: 43 skills, 11
workflows.
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.
One skill and four workflows, all built and run against a live Fluid company today.
The skill
Subscription gap audit finds the products a merchant sells which run out and get
rebought, but that no customer can put on a schedule. On the personal-care catalog I built
this against, 15 of 26 products were replenishable with zero carrying a subscription
plan — $151 of list price no customer could reorder.
Folder shape because the term lists and the SQL are lookup material the agent doesn't need
in context on every turn.
The workflows
setup-tiktok-shop — screen the catalog against TikTok commerce policy, pick the category
gate and its real timeline, set the creator qualification gate and commission tiers from live
prices, build the enrollment page and merchant console, close with an honest blocker list.
setup-instagram-affiliate — Meta commerce policy is a genuinely different ruleset, not
TikTok's with the names swapped. Meta ended native checkout in August 2025, so every tagged
tap lands on the merchant's own domain and the work is link attribution, not order
reconciliation.
subscription-sms — detect the messaging rail the merchant already has, clear the two
blockers that actually stop SMS launches (sender registration and consent), scope the
actions, deploy a branded droplet.
subscription-gap — the 8-step build that pairs with the skill.
What the live runs taught, and why the prompts look the way they do
Most of these were expensive to learn because nothing errored — the output just came back
confident and wrong.
Pin
/api/v202604/company/products+/{id}. The shop-host/api/productspayloadembeds the entire country atlas — roughly 25KB per product — and the admin list endpoint
carries no
variants[]at all. Only the detail endpoint has everything. Choosing wrongdoesn't fail, it just quietly gives you nothing usable.
descriptionis an object with a.body, not a string.String()coercion yields[object Object], which silently reduces classification to title-only. A 26-product catalogclassified cleanly on half the evidence and looked fine.
priceis null at product level on the shop-host payload; the real value is invariants[].variant_countries, a dict keyed by country code. Reading the product fieldreturns $0.00 for an entire catalog and a gap report quoting "$0 of list price."
Eligibility and reviewability must stay separate numbers. A content-review flag should
never reduce the count of what's eligible to list — they answer different questions.
Weight-management products are prohibited outright on TikTok Shop. Not restricted.
Banned. For a book full of weight-management merchants that's a screening question, not a
footnote.
Drop rank-based creator gating when the company has no distributor ranks rather than
offering a qualification path that doesn't exist. Check
is_mlmand the distributor countinstead of assuming.
Don't recommend on-platform autoship after proving the plans it needs can't be created.
Every documented v2026-04 subscription path is a customer-instance operation — cancel, pause,
skip, retry. There is no endpoint to create a product subscription plan.
Enrollment belongs on the storefront, never behind admin login. Creators have no admin
session. The merchant console is the droplet; the enrollment page is a theme page.
A launch checklist that reads clean while a 21-day approval sits unstarted is worse than no
checklist. The closing step's acceptance criteria enforce that.
Design decisions worth a reviewer's eye
Structure beats text.
is_bundle/product_bundles/bundle_configare authoritativewhen populated. Text classification is only the fallback — necessary because Fluid returns
category: nullandtags: []on a real import.Text matches are scored, not hand-ordered. Title evidence outranks description evidence;
longer terms outrank shorter. This isn't premature generality — a hand-ordered version failed
in both directions at once on a real catalog. It classified two wax kits as bundles, hiding
genuine recurring revenue, while a real multi-product set carrying no bundle word fell through
to
treatmentand would have been offered as a subscription. Subscribing a bundle re-ships adurable the customer already owns, which is how a subscription earns a cancellation.
Word boundaries, case-sensitive acronyms. Substring matching finds
TENSinside"softens", "brightens" and "moistens", which told a skincare merchant their lip balm was a
medical device.
Coverage is checked at product AND variant level. A plan attaches at either. Checking one
under-reports coverage and manufactures a gap that isn't there.
It refuses to invent revenue. The estimate needs an attach rate and a buyer count, both
from order history. With no reporting database connected the skill says so and gives the
defensible version — N products and $X of list price outside any schedule — rather than
borrowing an industry attach rate.
Add-on before skip. Only adding an item creates incremental revenue. A flow that opens
with "want to skip?" reduces the merchant's revenue very efficiently.
Where these apply
Any merchant selling consumables — personal care, supplements, food and beverage, pet,
household, cosmetics. The subscription-gap trigger is computable from the catalog alone:
a replenishable product with no subscription plan. Weak fit on apparel and hardgoods,
which are mostly durables — the skill correctly returns NO GAP rather than inventing one.
The channel workflows need no comp plan and no distributors, which is why they port to
another company in minutes.
Verification
python3 scripts/validate_catalog.py→ 43 skills, 11 workflows, passespython3 -m unittest discover -s scripts -p 'test_*.py'subscription-sms.workflow.json; DAGs sort cleanrepo: removing title weighting fails 2, removing ambiguity flagging fails 3, removing the
structural bundle check fails 2
Open question for maintainers
Four workflows is a lot to land at once. If you'd rather take the skill alone and have the
workflows as a follow-up PR, say so and I'll split it — they're independent.