{
  "schema": "leumas.docs.page/1",
  "id": "adapter:domain/lead-scorer",
  "slug": "adapters/domain/lead-scorer",
  "kind": "capabilities",
  "bucket": "package",
  "title": "lead-scorer",
  "name": "Lead Scorer",
  "eyebrow": null,
  "chip": null,
  "summary": "Intelligent lead-scoring microservice for sales & marketing: turn raw lead/contact records into points and an A–D grade using a transparent, rule-based model. Ships a proven default model blending...",
  "keywords": [
    "lead-scorer",
    "lead-scoring",
    "bant",
    "firmographic",
    "meetings",
    "buildmodel",
    "batchscore",
    "defaultmodel"
  ],
  "audience": "both",
  "funnel": {
    "product": null,
    "cta": null
  },
  "body": "# lead-scorer\n\nIntelligent, **explainable** lead-scoring microservice for sales & marketing. Turns raw lead/contact\nrecords into **points + an A–D grade** with a transparent, rule-based model. Ships a proven default\nmodel that blends **BANT** (budget, authority, need, timeline), **firmographic fit** (company size,\nseniority, industry, revenue) and **engagement** (visits, opens, clicks, replies, demo, meetings).\n\nPure deterministic heuristic scoring — there is no LLM in the scoring path on purpose (a score must be\nreproducible and auditable). The model is passed in args (`buildModel` produces one; DB persistence\nlands later). Missing lead fields never throw — they score 0 and are reported.\n\n## Tools\n\n| Tool | Args | Returns |\n|---|---|---|\n| `score` | `{ lead, model? }` | `points`, `percent`, `grade` (A–D), group rollup, `missingFields` |\n| `buildModel` | `{ rules, options? }` | a validated, portable model object |\n| `explain` | `{ lead, model? }` | top drivers, gaps (missed points), plain-English summary + full breakdown |\n| `batchScore` | `{ leads, model?, options.top? }` | ranked leads + grade distribution + averages |\n| `defaultModel` | `{ options.grades? }` | the shipped BANT/fit/engagement model + weights |\n\n### Rule types (for `buildModel`)\n\n`boolean` · `presence` · `map` (value→0..1) · `threshold` (numeric bands, `goal:'min'` to invert) ·\n`scale` (linear min→max, `goal:'min'`) · `contains` (keyword/array membership). Field lookup is\ncase/format-insensitive (`company_size` == `companySize` == `Company Size`).\n\n## Example\n\n```js\nimport pack from './index.js';\n\nconst lead = { budget: 'high', authority: 'decision-maker', need: 'high', timeline: 'this-quarter',\n  companySize: 450, seniority: 'vp', industry: 'SaaS', demoBooked: true, replies: 2, linkClicks: 6, visits: 9 };\n\nconsole.log(pack.adapters.score({ lead }));          // → { points, percent, grade: 'A', ... }\nconsole.log(pack.adapters.explain({ lead }).summary);\n```\n\n## DRY boundaries\n\n- Not `numbers.weightedScoring` (that ranks generic metric objects by a raw weighted sum). This owns\n  the **sales-lead** domain: BANT/fit/engagement semantics, A–D grades, per-field explanations, and a\n  shipped default model.\n- Self-contained: no cross-pack imports.\n",
  "source": {
    "path": "shared/engines/adapters/domain/lead-scorer/README.md",
    "blobSha": "",
    "commit": "",
    "committedAt": "",
    "provenance": "no-git",
    "bytes": 2469,
    "hash": "6bb881cc16fe82b17bb7818856df511205486497"
  },
  "urls": {
    "html": "/p/adapters/domain/lead-scorer",
    "json": "/docs/adapters/domain/lead-scorer.json",
    "md": "/docs/adapters/domain/lead-scorer.md"
  },
  "links": {
    "composes": [],
    "usedBy": [],
    "product": [],
    "howTo": [],
    "skills": []
  }
}
