# Use-Case Catalog Skill

## Purpose

Provide the **static** half of the 4-layer use-case model used to classify and prioritise provider APIs in Phase 1 research:

| Layer | Source | Owned by |
|---|---|---|
| 1. Universal | `references/universal.yaml` | This skill |
| 2. Category (12 categories) | `references/categories/<category>.yaml` | This skill |
| 3. Category dynamic | Generated at runtime | `discover-dynamic-use-cases.md` |
| 4. Provider dynamic | Generated at runtime | `discover-dynamic-use-cases.md` |
| 0. User-supplied | Interactive prompt | `connector-research` command |

The catalog is **read-only data**. The active skills (`list-provider-apis`, `discover-dynamic-use-cases`, `identify-provider-category`) load from here.

## Layout

```
use-case-catalog/
├── SKILL.md                                (this file — schema + extension guide)
├── references/
│   ├── universal.yaml                      (Layer 1 — applies to all providers)
│   └── categories/                         (Layer 2 — one file per StackOne unified vertical)
│       ├── messaging.yaml                  (Gmail, Attentive, Braze, Customer.io, Discord, GoogleMeet)
│       ├── crm.yaml                        (HubSpot, Pipedrive, Affinity, Apollo, Attio, Bullhorn)
│       ├── hris.yaml                       (BambooHR, Deel, 7shifts, BreatheHR, HiBob, Personio)
│       ├── ats.yaml                        (Ashby, Greenhouse, Lever, BreezyHR, Factorial)
│       ├── ticketing.yaml                  (Freshdesk, FreshService, Front, Aha, Asana, ClickUp)
│       ├── payments.yaml                   (Stripe, PayPal, Square, GoCardless, QuickbooksOnline)
│       ├── scheduling.yaml                 (Cal.com, Calendly, GoogleCalendar, OutlookCalendar)
│       ├── marketing.yaml                  (ActiveCampaign, Airship, BigCommerce, Bitly, CampaignMonitor)
│       ├── documents.yaml                  (Box, Dropbox, DocuSign, AdobePDFServices, Confluence)
│       ├── iam.yaml                        (1Password, Auth0, AzureDevOps, Contentful, Databricks)
│       ├── lms.yaml                        (360Learning, AdobeLearningManager, Cornerstone, Coursera, Docebo)
│       └── accounting.yaml                 (ApprovalMax, Chargebee, FreshBooks, FreeAgent, Harvest)
└── scripts/
    └── validate_catalog.js                 (schema validator — run after edits)
```

## Use case schema (same shape across all layers)

Each use case entry follows this exact YAML shape:

```yaml
- id: read_inbox                           # required, snake_case, globally unique within layer
  name: Read Inbox                         # required, human-readable label
  description: List and read incoming messages   # required, one sentence
  mapping_hints:                           # required, used by list-provider-apis Step 2
    action_pattern: ^(list|get)_(messages|mails|inbox)
    path_pattern: ^(messages|mail|inbox)
    method_pattern: ^GET$
  example_apis:                            # optional, documentation only
    - list_messages
    - get_message
```

### Field details

| Field | Type | Purpose |
|---|---|---|
| `id` | string (snake_case) | Stable identifier referenced from `api_coverage.json` `use_cases[]` |
| `name` | string | Display label used in `_index.md` summary and coverage reports |
| `description` | string (1 sentence) | What the use case enables |
| `mapping_hints.action_pattern` | regex | Matched against each API's `action_id` |
| `mapping_hints.path_pattern` | regex | Matched against each API's `logical_path` (after `path_prefix_strip`) |
| `mapping_hints.method_pattern` | regex | Matched against each API's `method` |
| `example_apis` | string[] | Documentation; not used by the classifier |

### Mapping rules used by `list-provider-apis` Step 2

For each API, the classifier loops through every use case in every layer. The API is **mapped** to a use case if **at least 2 of the 3** `mapping_hints` patterns match.

This gives some tolerance for irregular provider naming while still requiring positive evidence.

## File structure

### `universal.yaml`

```yaml
layer: universal
description: Use cases that apply to every provider regardless of category
use_cases:
  - id: entity_search
    name: ...
    ...
```

### `categories/<category>.yaml`

```yaml
category: messaging
layer: category
description: Messaging providers covering email, SMS, push notifications, chat, and voice (Gmail, Outlook, etc.)
use_cases:
  - id: send_message
    name: ...
    ...
```

## Extending the catalog

### Adding a new use case to an existing file

1. Add a new entry under `use_cases:` following the schema above
2. Run `node ${CLAUDE_PLUGIN_ROOT}/scripts/research/validate_catalog.js` to confirm it parses
3. Verify `id` is unique within the file (validator checks)
4. The change takes effect on the next `/connector:research` run

### Adding a new category

1. Create `references/categories/<new_category>.yaml` following the template above
2. Pick 5–10 use cases that represent the core integration surface for that category
3. Run `node ${CLAUDE_PLUGIN_ROOT}/scripts/research/validate_catalog.js` to verify schema
4. Update `identify-provider-category.md`'s category list to include the new category
5. Reference the file from the v3 plan's category list

### When NOT to add to the static catalog

- Provider-specific use cases → those go into Layer 4 (`dynamic_provider.yaml`) generated by `use-case-discoverer` at runtime
- Refinements of an existing category use case for one specific provider → Layer 3 (`dynamic_category.yaml`)
- One-off use cases for a specific build → Layer 0 (user-supplied via interactive prompt)

## Validation

Run the validator after any edit:

```bash
node ${CLAUDE_PLUGIN_ROOT}/scripts/research/validate_catalog.js
```

It checks:
- All required fields present (`id`, `name`, `description`, `mapping_hints` with all 3 patterns)
- `id` values are unique within each file
- Regex patterns compile cleanly
- File-level `layer` and `category` fields present and correct
- No accidental duplication of use case IDs across multiple categories (warning, not error)

Exit 0 on clean catalog, 1 on any failure.

## Catalog identity

Weights are applied by `classify_priority.js` Pass 2.

- **Layer 0 (user_supplied) is the highest** — the user is signalling explicit intent for this specific build, so their preferences override automatic classification.
- **Layer 3 (category_dynamic) is the strongest automated signal** — provider-specific refinements of category use cases reflect the deepest understanding of what this particular provider does that matters for its category.
- The static layers (universal + category) are stable baselines; universal is intentionally near-zero (0.25) — universal use cases match on every provider regardless of category, so several weak universal matches must never out-score a single category-relevant match. Universal breaks ties; it never decides priority on its own.

| Layer | Source | Default weight |
|---|---|---|
| 0 — user supplied (interactive) | `user_supplied.yaml` | **4.0 (highest)** |
| 3 — category dynamic (generated per provider) | `dynamic_category.yaml` | 3.5 |
| 4 — provider dynamic (generated per provider) | `dynamic_provider.yaml` | 2.5 |
| 2 — category static (this catalog) | `references/categories/<category>.yaml` | 2.0 |
| 1 — universal (this catalog) | `references/universal.yaml` | **0.25 (lowest)** |

Per-file table:

| File | Layer | Category |
|------|-------|----------|
| `references/universal.yaml` | universal | n/a (3 use cases: `entity_search`, `get_authenticated_user`, `tags_management`) |
| `references/categories/messaging.yaml` | category | messaging |
| `references/categories/crm.yaml` | category | crm |
| `references/categories/hris.yaml` | category | hris |
| `references/categories/ats.yaml` | category | ats |
| `references/categories/ticketing.yaml` | category | ticketing |
| `references/categories/payments.yaml` | category | payments |
| `references/categories/scheduling.yaml` | category | scheduling |
| `references/categories/marketing.yaml` | category | marketing |
| `references/categories/documents.yaml` | category | documents |
| `references/categories/iam.yaml` | category | iam |
| `references/categories/lms.yaml` | category | lms |
| `references/categories/accounting.yaml` | category | accounting |

Weights are applied by `list-provider-apis` Step 2 when computing `priority_score`. The catalog itself does not embed weights.
