{"serverId":"mcp-registry/dev.sparkpay/sparkpay","tools":[{"name":"archive_plan","fixed":{"name":"archive_plan","description":"Remove a tier from an app's plan catalog. WRITE, human-gated: a real write needs an elicitation-capable client and the human must approve; dry_run previews anywhere. Every other plan tool edits tiers that already exist, so a catalog could grow but never shrink, and collapsing a multi-tier page down to a single offer was a dashboard-only job. Stripe products and prices are deliberately left intact, exactly as update_plan_pricing leaves the old price behind: removing the row stops the plan being o","inputSchema":{"type":"object","$schema":"http://json-schema.org/draft-07/schema#","required":["app_id","tier"],"properties":{"tier":{"type":"string"},"app_id":{"type":"string"},"dry_run":{"type":"boolean","default":false}}},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: false, destructiveHint: true, idempotentHint: true (inferred from the name).","verify":true}],"tokensBefore":213,"tokensAfter":213},{"name":"bulk_create_coupon","fixed":{"name":"bulk_create_coupon","description":"Create the SAME discount code across many apps in one call: the portfolio-promo shortcut (e.g. a summer sale on every owned app). WRITE, human-gated: a real create requires an elicitation-capable client; the human enters the coupon terms ONCE in a form (overriding the arguments here) and that one approval covers the whole batch. Clients without elicitation are refused (dry_run still works anywhere). Runs each app through the same fully-guarded create as create_coupon. Unlike a single call it doe","inputSchema":{"type":"object","$schema":"http://json-schema.org/draft-07/schema#","required":["app_ids","code","discount_percent"],"properties":{"code":{"type":"string"},"listed":{"type":"boolean","default":false},"app_ids":{"type":"array","items":{"type":"string"}},"dry_run":{"type":"boolean","default":false},"max_uses":{"type":"number"},"expires_at":{"type":"string"},"description":{"type":"string"},"applies_to_tiers":{"type":"array","items":{"type":"string"}},"discount_percent":{"type":"number"},"confirm_high_discount":{"type":"boolean","default":false}}},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: false, destructiveHint: false, idempotentHint: false (inferred from the name).","verify":true}],"tokensBefore":309,"tokensAfter":309},{"name":"bulk_delete_coupon","fixed":{"name":"bulk_delete_coupon","description":"Delete the SAME coupon code across many apps in one call: the inverse of bulk_create_coupon, for retiring a portfolio-wide promo. WRITE, human-gated: a real delete requires an elicitation-capable client; the human sees every app the code would be removed from (with per-app redemption counts) and must click approve, and confirm_used is only consulted for dry_run previews. Clients without elicitation are refused (dry_run still works anywhere). An app that never had the code is reported `skipped` r","inputSchema":{"type":"object","$schema":"http://json-schema.org/draft-07/schema#","required":["app_ids","code"],"properties":{"code":{"type":"string"},"app_ids":{"type":"array","items":{"type":"string"}},"dry_run":{"type":"boolean","default":false},"confirm_used":{"type":"boolean","default":false}}},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: false, destructiveHint: true, idempotentHint: true (inferred from the name).","verify":true}],"tokensBefore":236,"tokensAfter":236},{"name":"create_app_kit","fixed":{"name":"create_app_kit","description":"Step 2 of onboarding a new app onto SparkPay. Applies answers.plan_catalog by minting real Stripe prices (same helper /api/apps/sync-plans uses) and registers/updates the app, then returns a downloadable integration kit (lib/spark-pay client + plans.json + sync script + INTEGRATION.md, modeled on still-applying's golden pattern) plus exact post_steps for env vars and secrets. Refuses to overwrite an existing app's plans unless answers.confirm_overwrite is true. Real secrets (a push-mode webhook ","inputSchema":{"type":"object","$schema":"http://json-schema.org/draft-07/schema#","required":["app_name","answers"],"properties":{"answers":{"type":"object","required":["plan_catalog","success_url","cancel_url"],"properties":{"push_mode":{"type":"boolean","default":false},"cancel_url":{"type":"string"},"trial_days":{"type":"number"},"success_url":{"type":"string"},"plan_catalog":{"type":"array","items":{"type":"object","required":["tier","name","monthly_price"],"properties":{"name":{"type":"string"},"tier":{"type":"string"},"amount":{"type":"number"},"trial_days":{"type":"number"},"payment_type":{"enum":["free","subscription","one_time","contact"],"type":"string"},"yearly_price":{"type":"number"},"monthly_price":{"type":"number"}}}},"confirm_overwrite":{"type":"boolean","default":false}}},"app_name":{"type":"string"}}},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: false, destructiveHint: false, idempotentHint: false (inferred from the name).","verify":true}],"tokensBefore":382,"tokensAfter":382},{"name":"create_coupon","fixed":{"name":"create_coupon","description":"Create a percentage discount coupon for an app. WRITE, human-gated: a real create requires an elicitation-capable client (e.g. Claude Desktop). The human enters the final code, percent, expiry, visibility, and tier scope in a form; those values OVERRIDE the arguments here, which only pre-fill the form message as a proposal. Clients without elicitation are refused (dry_run still works anywhere). Inserts a `coupons` row and best-effort-mints the matching Stripe coupon (checkout backfills it on fir","inputSchema":{"type":"object","$schema":"http://json-schema.org/draft-07/schema#","required":["app_id","code","discount_percent"],"properties":{"code":{"type":"string"},"app_id":{"type":"string"},"listed":{"type":"boolean","default":false},"dry_run":{"type":"boolean","default":false},"max_uses":{"type":"number"},"expires_at":{"type":"string"},"description":{"type":"string"},"applies_to_tiers":{"type":"array","items":{"type":"string"}},"discount_percent":{"type":"number"},"confirm_high_discount":{"type":"boolean","default":false}}},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: false, destructiveHint: false, idempotentHint: false (inferred from the name).","verify":true}],"tokensBefore":300,"tokensAfter":300},{"name":"delete_coupon","fixed":{"name":"delete_coupon","description":"Delete one coupon from an app. WRITE, human-gated: a real delete requires an elicitation-capable client; the human sees the exact coupon (code, percent, redemption count) and must click approve. The model cannot confirm on its own, and confirm_used is only consulted for dry_run previews. Clients without elicitation are refused (dry_run still works anywhere). Removes the Stripe coupon object and then the `coupons` row, exactly like the dashboard's delete, so no orphaned Stripe object is left behi","inputSchema":{"type":"object","$schema":"http://json-schema.org/draft-07/schema#","required":["app_id","code"],"properties":{"code":{"type":"string"},"app_id":{"type":"string"},"dry_run":{"type":"boolean","default":false},"confirm_used":{"type":"boolean","default":false}}},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: false, destructiveHint: true, idempotentHint: true (inferred from the name).","verify":true}],"tokensBefore":227,"tokensAfter":227},{"name":"get_customer","fixed":{"name":"get_customer","description":"Look up a customer by email. Returns every subscription/registration for that email across apps (or within one app if app_id is given), with full detail: verification, plan, billing period, usage, refunds. Empty when the email is unknown.","inputSchema":{"type":"object","$schema":"http://json-schema.org/draft-07/schema#","required":["email"],"properties":{"email":{"type":"string"},"app_id":{"type":"string"}}},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":126,"tokensAfter":126},{"name":"invite_to_coupon","fixed":{"name":"invite_to_coupon","description":"Add email addresses to a coupon's invite list and, by default, switch the coupon to invite-only so the list is actually enforced. WRITE, human-gated: a real write requires an elicitation-capable client and the human sees every address plus whether the coupon is about to be closed to everyone else; clients without elicitation are refused (dry_run works anywhere). Addresses are lowercased and de-duplicated, malformed ones are reported rather than dropped, and an address already on the list is left","inputSchema":{"type":"object","$schema":"http://json-schema.org/draft-07/schema#","required":["app_id","code","emails"],"properties":{"code":{"type":"string"},"app_id":{"type":"string"},"emails":{"type":"array","items":{"type":"string"}},"source":{"type":"string"},"dry_run":{"type":"boolean","default":false},"enforce_invite_only":{"type":"boolean","default":true}}},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":false}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: false, destructiveHint: false, idempotentHint: false (inferred from the name).","verify":true}],"tokensBefore":254,"tokensAfter":254},{"name":"list_apps","fixed":{"name":"list_apps","description":"List the registered apps (app_id + name). Use this first to discover valid app_id values, then pass one to the other tools to scope results to a single product.","inputSchema":{"type":"object","$schema":"http://json-schema.org/draft-07/schema#","properties":{}},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":83,"tokensAfter":83},{"name":"list_coupon_invites","fixed":{"name":"list_coupon_invites","description":"List who a coupon was offered to and what they did with it: per-address status (invited / redeemed / revoked), where the invite came from, and the timestamps. Also returns the coupon's own `invite_only` flag -- read that FIRST: when it is false the invite rows are recorded but NOT enforced, and anyone holding the code can still redeem it. Read-only. Use list_coupons for the coupon's terms, invite_to_coupon to add addresses, revoke_coupon_invite to withdraw one.","inputSchema":{"type":"object","$schema":"http://json-schema.org/draft-07/schema#","required":["app_id","code"],"properties":{"code":{"type":"string"},"app_id":{"type":"string"}}},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":193,"tokensAfter":193},{"name":"list_coupons","fixed":{"name":"list_coupons","description":"List discount coupons (code, percent off, expiry, max uses, use count, which paid tiers they apply to). Optionally scope by app_id and/or restrict to currently-active ones (not expired, not maxed out). Read-only: cannot create, edit, or delete coupons.","inputSchema":{"type":"object","$schema":"http://json-schema.org/draft-07/schema#","properties":{"limit":{"type":"number","default":50},"app_id":{"type":"string"},"active_only":{"type":"boolean","default":false}}},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":141,"tokensAfter":141},{"name":"list_plans","fixed":{"name":"list_plans","description":"Download an app's live plan catalog: tiers, names, prices, trial, and the machine-readable `limits` that gate features inside the app. This is the source of truth each app repo's `bun run plans:sync` regenerates lib/spark-pay/plans.json from, so diff against this rather than trusting the committed file. Stripe price/product IDs are omitted unless include_stripe_ids is set.","inputSchema":{"type":"object","$schema":"http://json-schema.org/draft-07/schema#","required":["app_id"],"properties":{"app_id":{"type":"string"},"include_stripe_ids":{"type":"boolean","default":false}}},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":172,"tokensAfter":172},{"name":"list_recent_cancellations","fixed":{"name":"list_recent_cancellations","description":"Recently canceled paid subscriptions (excludes free rows), most recent cancellation first, with what each customer was paying. Use for churn review; list_subscriptions orders by signup date instead.","inputSchema":{"type":"object","$schema":"http://json-schema.org/draft-07/schema#","properties":{"limit":{"type":"number","default":25},"app_id":{"type":"string"},"include_samples":{"type":"boolean","default":false}}},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: false, destructiveHint: true, idempotentHint: true (inferred from the name).","verify":true}],"tokensBefore":131,"tokensAfter":131},{"name":"list_recent_payments","fixed":{"name":"list_recent_payments","description":"List recent paid transactions (excludes free-tier rows), newest first, ordered by payment date. Optionally scope by app_id. Use to review recent sales activity. Amounts are in the transaction currency (cents).","inputSchema":{"type":"object","$schema":"http://json-schema.org/draft-07/schema#","properties":{"limit":{"type":"number","default":25},"app_id":{"type":"string"},"include_samples":{"type":"boolean","default":false}}},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":132,"tokensAfter":132},{"name":"list_referrals","fixed":{"name":"list_referrals","description":"List referral records (who referred whom, reward coupon code, pending/rewarded status), newest first. Optionally scope by app_id and/or status.","inputSchema":{"type":"object","$schema":"http://json-schema.org/draft-07/schema#","properties":{"limit":{"type":"number","default":25},"app_id":{"type":"string"},"status":{"enum":["pending","rewarded"],"type":"string"},"include_samples":{"type":"boolean","default":false}}},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":128,"tokensAfter":128},{"name":"list_subscriptions","fixed":{"name":"list_subscriptions","description":"List subscriptions/registrations, newest first. Optionally filter by app_id, status, or payment_type. Returns metadata (email, status, plan, amounts). Use get_customer for a single user, or revenue_summary for totals.","inputSchema":{"type":"object","$schema":"http://json-schema.org/draft-07/schema#","properties":{"limit":{"type":"number","default":25},"app_id":{"type":"string"},"status":{"enum":["active","trialing","past_due","canceled"],"type":"string"},"payment_type":{"enum":["free","subscription","one_time","payg"],"type":"string"},"include_samples":{"type":"boolean","default":false}}},"annotations":{"readOnlyHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: true (inferred from the name).","verify":true}],"tokensBefore":179,"tokensAfter":179},{"name":"revoke_coupon_invite","fixed":{"name":"revoke_coupon_invite","description":"Withdraw one address's right to spend a coupon: the targeted block. WRITE, human-gated: a real write requires an elicitation-capable client and the human sees the address and its current status; clients without elicitation are refused (dry_run works anywhere). Works on an address that was never invited too, writing a revoked tombstone, so blocking someone does not depend on whether they were on the list and survives a later bulk re-invite. This only blocks FUTURE redemptions: if the status was a","inputSchema":{"type":"object","$schema":"http://json-schema.org/draft-07/schema#","required":["app_id","code","email"],"properties":{"code":{"type":"string"},"email":{"type":"string"},"app_id":{"type":"string"},"reason":{"type":"string"},"dry_run":{"type":"boolean","default":false}}},"annotations":{"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: false, destructiveHint: true, idempotentHint: false (inferred from the name).","verify":true}],"tokensBefore":232,"tokensAfter":232},{"name":"set_coupon_listed","fixed":{"name":"set_coupon_listed","description":"Show, hide or SCHEDULE an EXISTING coupon on the public pricing pages by setting its `listed` flag and optional `listed_from` start date. WRITE, human-gated: a real write requires an elicitation-capable client and the human sees the code, the discount, which way it is moving and any start date; clients without elicitation are refused (dry_run works anywhere). These are deliberately the ONLY fields an agent can change on a live coupon: the percent, expiry and tier scope are terms somebody may alr","inputSchema":{"type":"object","$schema":"http://json-schema.org/draft-07/schema#","required":["app_id","code","listed"],"properties":{"code":{"type":"string"},"app_id":{"type":"string"},"listed":{"type":"boolean"},"dry_run":{"type":"boolean","default":false},"listed_from":{"type":"string"}}},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: false, destructiveHint: false, idempotentHint: true (inferred from the name).","verify":true}],"tokensBefore":234,"tokensAfter":234},{"name":"setup_pricing_page","fixed":{"name":"setup_pricing_page","description":"Guided, stage-chained wizard that configures an app's hosted pricing page end to end: plan billing model + price (with clickable recommendations), plan name and badge (elite/recommended), optional free tier, a seasonal coupon (SUMMER26-style code suggested from the current season), favicon-derived theme color + card style, and FAQ content. WRITE, human-gated per stage: each call runs AT MOST ONE elicitation form and commits only that stage, then returns next_call for the model to continue (stage","inputSchema":{"type":"object","$schema":"http://json-schema.org/draft-07/schema#","required":["app_id"],"properties":{"tier":{"type":"string"},"stage":{"enum":["overview","plans","coupon","branding","content","finish"],"type":"string","default":"overview"},"app_id":{"type":"string"},"domain":{"type":"string"},"dry_run":{"type":"boolean","default":false},"faq_drafts":{"type":"array","items":{"type":"object","required":["question","answer"],"properties":{"answer":{"type":"string"},"question":{"type":"string"}}}},"coupon_code":{"type":"string"},"discount_percent":{"type":"number"},"price_suggestions":{"type":"array","items":{"type":"object","required":["amount_cents","billing"],"properties":{"tier":{"type":"string"},"label":{"type":"string"},"billing":{"enum":["one_time","subscription"],"type":"string"},"rationale":{"type":"string"},"recommended":{"type":"boolean"},"amount_cents":{"type":"number"}}}}}},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: false, destructiveHint: false, idempotentHint: true (inferred from the name).","verify":true}],"tokensBefore":406,"tokensAfter":406},{"name":"update_plan_limits","fixed":{"name":"update_plan_limits","description":"Change the usage limits on an app's existing tiers (e.g. set ai_generations_daily to 200 on pro). WRITE, human-gated: a real write requires an elicitation-capable client; the human sees the per-tier before -> after diff and must click approve. Clients without elicitation are refused (dry_run still works anywhere). Tier-keyed, so one call can set a new limit key across every tier in a single atomic write. Use -1 for unlimited, matching the catalog convention. This writes ONLY the limits object: i","inputSchema":{"type":"object","$schema":"http://json-schema.org/draft-07/schema#","required":["app_id","updates"],"properties":{"mode":{"enum":["merge","replace"],"type":"string","default":"merge"},"app_id":{"type":"string"},"dry_run":{"type":"boolean","default":false},"updates":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"number"}}}}},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: false, destructiveHint: false, idempotentHint: true (inferred from the name).","verify":true}],"tokensBefore":277,"tokensAfter":277},{"name":"update_plan_meta","fixed":{"name":"update_plan_meta","description":"Set an existing tier's display metadata: its name and the two badge flags the public pricing page styles cards from: is_elite (gold/carbon BEST VALUE card with the rainbow title and app icon) and recommended (MOST POPULAR). A tier called \"Elite\" is NOT styled as elite unless is_elite is actually true on the stored plan; the page reads the flag, never the tier slug, so a catalog whose top tier lacks the flag renders as a plain grey card. Use this to repair that. WRITE, human-gated: the human sees","inputSchema":{"type":"object","$schema":"http://json-schema.org/draft-07/schema#","required":["app_id","tier"],"properties":{"name":{"type":"string"},"tier":{"type":"string"},"app_id":{"type":"string"},"dry_run":{"type":"boolean","default":false},"is_elite":{"type":"boolean"},"recommended":{"type":"boolean"}}},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: false, destructiveHint: false, idempotentHint: true (inferred from the name).","verify":true}],"tokensBefore":239,"tokensAfter":239},{"name":"update_plan_pricing","fixed":{"name":"update_plan_pricing","description":"Change what an app's EXISTING tiers charge: the amount, the billing model (one_time vs subscription), or both. WRITE, human-gated at the highest tier: a real write requires an elicitation-capable client, and the human types the tier, billing model and price into a form. Those typed values OVERRIDE the arguments here, which only pre-fill the proposal, so the model cannot move a price on its own. Clients without elicitation are refused (dry_run still works anywhere). Stripe prices are immutable, s","inputSchema":{"type":"object","$schema":"http://json-schema.org/draft-07/schema#","required":["app_id","updates"],"properties":{"app_id":{"type":"string"},"dry_run":{"type":"boolean","default":false},"updates":{"type":"array","items":{"type":"object","required":["tier"],"properties":{"tier":{"type":"string"},"amount_cents":{"type":"number"},"payment_type":{"enum":["one_time","subscription"],"type":"string"},"monthly_amount_cents":{"type":"number"}}}}}},"annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true}},"changes":[{"kind":"annotations","detail":"Added readOnlyHint: false, destructiveHint: false, idempotentHint: true (inferred from the name).","verify":true}],"tokensBefore":280,"tokensAfter":280}],"toolsChanged":22,"tokensSaved":0,"todo":[{"tool":"archive_plan","params":["tier","app_id","dry_run"]},{"tool":"bulk_create_coupon","params":["code","listed","app_ids","dry_run","max_uses","expires_at","description","applies_to_tiers","discount_percent","confirm_high_discount"]},{"tool":"bulk_delete_coupon","params":["code","app_ids","dry_run","confirm_used"]},{"tool":"create_app_kit","params":["answers","app_name"]},{"tool":"create_coupon","params":["code","app_id","listed","dry_run","max_uses","expires_at","description","applies_to_tiers","discount_percent","confirm_high_discount"]},{"tool":"delete_coupon","params":["code","app_id","dry_run","confirm_used"]},{"tool":"get_customer","params":["email","app_id"]},{"tool":"invite_to_coupon","params":["code","app_id","emails","source","dry_run","enforce_invite_only"]},{"tool":"list_coupon_invites","params":["code","app_id"]},{"tool":"list_coupons","params":["limit","app_id","active_only"]},{"tool":"list_plans","params":["app_id","include_stripe_ids"]},{"tool":"list_recent_cancellations","params":["limit","app_id","include_samples"]},{"tool":"list_recent_payments","params":["limit","app_id","include_samples"]},{"tool":"list_referrals","params":["limit","app_id","status","include_samples"]},{"tool":"list_subscriptions","params":["limit","app_id","status","payment_type","include_samples"]},{"tool":"plan_app_kit","params":["app_name"]},{"tool":"revenue_by_app","params":["include_samples"]},{"tool":"revenue_summary","params":["app_id","include_samples"]},{"tool":"revoke_coupon_invite","params":["code","email","app_id","reason","dry_run"]},{"tool":"set_coupon_listed","params":["code","app_id","listed","dry_run","listed_from"]},{"tool":"setup_pricing_page","params":["tier","stage","app_id","domain","dry_run","faq_drafts","coupon_code","discount_percent","price_suggestions"]},{"tool":"update_plan_limits","params":["mode","app_id","dry_run","updates"]},{"tool":"update_plan_meta","params":["name","tier","app_id","dry_run","is_elite","recommended"]},{"tool":"update_plan_pricing","params":["app_id","dry_run","updates"]}],"note":"Deterministic fixes. Changes marked verify need a human look before shipping (renames, inferred annotations, inferred types, removed text). Parameter descriptions in `todo` need to be written by someone who knows the API."}