Skip to content

feat(fairshare): add Set FairShare preferences skill - #115

Open
adaraPark wants to merge 1 commit into
Fluid-WeCommerce:mainfrom
adaraPark:adara/fairshare-settings-skill
Open

feat(fairshare): add Set FairShare preferences skill#115
adaraPark wants to merge 1 commit into
Fluid-WeCommerce:mainfrom
adaraPark:adara/fairshare-settings-skill

Conversation

@adaraPark

Copy link
Copy Markdown

What

Adds fairshare/fairshare-settings — the first skill under a new fairshare category.

The catalog had no FairShare coverage. The word "commission" appears exactly once across the existing 42 skills, in a litigation-search table (onboarding/onboarding-prefill), and the two fairshare mentions in themes/theme-refine and themes/theme-review are about the web-widget SDK's cart attributes, not rep attribution.

What it does

Reads the four preferences from GET /api/v2025-06/fairshare/settings, explains what each option does and who it pays, collects choices through a steps picker pre-selected to current values, confirms the irreversible ones, then PATCHes.

It also explains the volume resolution order up front, since the preferences don't mean much without it: buyer's own rep → attributed rep → nearest rep-eligible sponsor → attributed rep as fallback → orphan policy.

Non-obvious behaviors it encodes

Verified against the Rails implementation rather than the OpenAPI surface:

  • Partial PATCH resets omitted fields. Every field in the PATCH schema is optional, but UpdateAction does company.update(fairshare: ...), assigning the whole StoreModel — so omitted keys become defaults, not their previous values. test/models/company_fairshare_test.rb proves it: update!(fairshare: {}) reverts all four. The skill always GETs, merges, and sends all five fields.
  • attribution_config is retroactive. Each order carries its own settings snapshot, and OrderAttributionService#ensure_order_fairshare_settings! overwrites it with the company's current settings whenever attribution is recomputed. Changing this can re-credit historical orders, so it gets an explicit confirmation.
  • random_rep is not a blind lottery. OrphanSponsorService#random_active_rep samples from the 10 reps with the most url_visited events in the last 30 days, cached hourly. The skill corrects that misreading explicitly, because the option name invites it.
  • sponsor_rep is not the direct sponsor. It walks a recursive genealogy CTE to the nearest rep-eligible ancestor; volume passes through customer interior nodes and customers never earn.
  • select_rep with no rep id is accepted, as is a deleted rep id — there's no cross-field validation. The skill resolves the rep via GET /api/v2025-06/reps/{id} before writing.

It also warns that every step of the resolution chain is gated on rep_eligible?, so with empty member-type permissions the chain collapses to the orphan policy and all four preferences appear inert.

Scope

Sets and explains preferences. The "what it's worth" guidance describes mechanisms, not measurements — the skill explicitly declines to estimate how many of a given company's orders would change, and says so rather than guessing.

Validation

python3 scripts/validate_catalog.pycatalog validation passed: 43 skills, 7 workflows

🤖 Generated with Claude Code

Adds the first skill under a new `fairshare` category. The catalog had no
coverage of FairShare attribution: the word "commission" appeared exactly
once across all 42 skills, in a litigation-search table.

The skill reads the four preferences from
`/api/v2025-06/fairshare/settings`, explains what each option does and who
it pays, collects choices through a `steps` picker, then writes the object
back.

Three non-obvious behaviors it encodes, verified against the Rails
implementation:

- Every PATCH field is optional, but the server assigns the whole
  StoreModel at once, so an omitted field resets to its default rather
  than retaining its value. Always GET, merge, PATCH all five fields.
- `attribution_config` is retroactive: each order stores its own snapshot
  and that snapshot is overwritten with the company's current settings on
  recompute, so historical orders can re-credit.
- `orphan_sponsor_config: random_rep` is not a blind lottery — the pool is
  the 10 reps with the most `url_visited` events in the last 30 days.

`select_rep` with no rep id, and a deleted rep id, are both accepted by the
API without complaint, so the skill resolves the rep before writing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant