# Customers domain

The `customers` domain describes who the organization serves — distinct buyer archetypes modeled
after the Value Proposition Canvas (BMC / VPC). Each segment captures jobs-to-be-done, pains,
gains, firmographics, and a value proposition. Agents use these segments for targeting, outreach
context, and personalization.

## Schema

Source: `packages/core/src/organization-model/domains/customers.ts`

```typescript
CustomersDomainSchema = z.object({
  segments: z.array(CustomerSegmentSchema).default([])
})

CustomerSegmentSchema = z.object({
  id:           z.string().trim().min(1).max(100),             // stable ID, e.g. "segment-smb-agencies"
  name:         z.string().trim().max(200).default(''),        // display name
  description:  z.string().trim().max(2000).default(''),       // who this segment is
  jobsToBeDone: z.string().trim().max(2000).default(''),       // the goal they hire you to accomplish
  pains:        z.array(z.string().trim().max(500)).default([]),
  gains:        z.array(z.string().trim().max(500)).default([]),
  firmographics: FirmographicsSchema.default({}),              // industry, companySize, region
  valueProp:    z.string().trim().max(2000).default('')        // why your offering fits this segment
})

FirmographicsSchema = z.object({
  industry:    z.string().trim().max(200).optional(),  // e.g. "Marketing Agency"
  companySize: z.string().trim().max(100).optional(),  // e.g. "11–50"
  region:      z.string().trim().max(200).optional()   // e.g. "North America"
})
```

## Field reference

| Field           | Type     | Max  | Notes                                                        |
| --------------- | -------- | ---- | ------------------------------------------------------------ |
| `id`            | string   | 100  | Stable key, min 1 char; e.g. `"segment-smb-agencies"`        |
| `name`          | string   | 200  | Display name                                                 |
| `description`   | string   | 2000 | Who this segment is in one or two sentences                  |
| `jobsToBeDone`  | string   | 2000 | The goal they hire you to accomplish, in their terms         |
| `pains`         | string[] | 500  | Each item: a frustration or obstacle                         |
| `gains`         | string[] | 500  | Each item: an outcome or benefit they hope for               |
| `firmographics` | object   | --   | Optional industry, companySize, region filters for targeting |
| `valueProp`     | string   | 2000 | Why your offering uniquely addresses this segment's needs    |

## Validation rules

- `id` is the stable key used by `offerings.products[].targetSegmentIds` references; once set,
  changing the `id` of a segment breaks any offering that references it
- `firmographics` is optional; all three sub-fields (`industry`, `companySize`, `region`) are
  individually optional
- `pains` and `gains` default to empty arrays; agents should treat an empty array as unconfigured
- There is no uniqueness constraint enforced by the schema on `id`, but agents must treat it as
  unique and surface duplicates if found
- Cross-reference: if a segment is removed, any `offerings.products[].targetSegmentIds` that
  reference its `id` become dangling references; surface a warning before removing

## Examples

```typescript
customers: {
  segments: [
    {
      id:           "segment-smb-agencies",
      name:         "SMB Marketing Agencies",
      description:  "Owner-operated agencies with 1–15 employees running campaign delivery for SMB clients.",
      jobsToBeDone: "Deliver consistent client results without adding headcount.",
      pains: [
        "Manual campaign QA eats time",
        "Client reporting takes hours each week",
        "Hard to scale without hiring"
      ],
      gains: [
        "More client capacity without more staff",
        "Predictable delivery timelines"
      ],
      firmographics: {
        industry:    "Marketing Agency",
        companySize: "1–15",
        region:      "North America"
      },
      valueProp: "Automates the repetitive delivery and reporting work so agencies can take on more clients."
    }
  ]
}
```

## Where it lives in the adapter

**Split projects:** `core/config/organization-model/profile.ts` under the `customers` key of
`defineOrganizationModel({...})`.

**Unsplit projects:** `core/config/organization-model.ts` under the same key.

To read current segments: open the appropriate file and inspect the `customers.segments` array,
or use `pnpm exec elevasis-sdk om:cat customers` (external project).

## Write path

To add, edit, or remove a segment, the `/om` skill runs the codify ceremony
(`operations/codify-level-a.md`): snapshot → propose → confirm → write → typecheck → Zod parse →
rollback on failure. Pass `targetFile` as `core/config/organization-model/profile.ts` for split
projects, or `core/config/organization-model.ts` for unsplit projects. Only the `segments` array
is written; no other keys in the target file are touched. When adding, append to the array. When
editing, replace the matching entry by `id`. When removing, filter it out — and surface any
dangling `targetSegmentIds` references first.

---

**Read via `/om`** (legacy `/knowledge` alias also accepted) — natural-language queries like
"who are our customer segments?" or "what pains does the agency segment have?" route to this
domain via the skill's intent classifier.
