@indexnetwork/protocol 4.17.0-rc.360.1 → 4.18.0-rc.362.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/dist/index.d.ts +13 -2
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +8 -2
  5. package/dist/index.js.map +1 -1
  6. package/dist/negotiation/negotiation.graph.d.ts.map +1 -1
  7. package/dist/negotiation/negotiation.graph.js +25 -0
  8. package/dist/negotiation/negotiation.graph.js.map +1 -1
  9. package/dist/opportunity/discriminator/discriminator.adjustments.d.ts +10 -1
  10. package/dist/opportunity/discriminator/discriminator.adjustments.d.ts.map +1 -1
  11. package/dist/opportunity/discriminator/discriminator.adjustments.js +12 -4
  12. package/dist/opportunity/discriminator/discriminator.adjustments.js.map +1 -1
  13. package/dist/opportunity/discriminator/discriminator.question.d.ts +2 -0
  14. package/dist/opportunity/discriminator/discriminator.question.d.ts.map +1 -1
  15. package/dist/opportunity/discriminator/discriminator.question.js +1 -0
  16. package/dist/opportunity/discriminator/discriminator.question.js.map +1 -1
  17. package/dist/opportunity/feed/feed.graph.js +2 -2
  18. package/dist/opportunity/feed/feed.graph.js.map +1 -1
  19. package/dist/opportunity/negotiation-evidence/negotiation-evidence.env.d.ts +44 -0
  20. package/dist/opportunity/negotiation-evidence/negotiation-evidence.env.d.ts.map +1 -0
  21. package/dist/opportunity/negotiation-evidence/negotiation-evidence.env.js +45 -0
  22. package/dist/opportunity/negotiation-evidence/negotiation-evidence.env.js.map +1 -0
  23. package/dist/opportunity/negotiation-evidence/negotiation-evidence.extractor.d.ts +25 -0
  24. package/dist/opportunity/negotiation-evidence/negotiation-evidence.extractor.d.ts.map +1 -0
  25. package/dist/opportunity/negotiation-evidence/negotiation-evidence.extractor.js +189 -0
  26. package/dist/opportunity/negotiation-evidence/negotiation-evidence.extractor.js.map +1 -0
  27. package/dist/opportunity/negotiation-evidence/negotiation-evidence.miner.d.ts +27 -0
  28. package/dist/opportunity/negotiation-evidence/negotiation-evidence.miner.d.ts.map +1 -0
  29. package/dist/opportunity/negotiation-evidence/negotiation-evidence.miner.js +113 -0
  30. package/dist/opportunity/negotiation-evidence/negotiation-evidence.miner.js.map +1 -0
  31. package/dist/opportunity/negotiation-evidence/negotiation-evidence.shadow.d.ts +20 -0
  32. package/dist/opportunity/negotiation-evidence/negotiation-evidence.shadow.d.ts.map +1 -0
  33. package/dist/opportunity/negotiation-evidence/negotiation-evidence.shadow.js +62 -0
  34. package/dist/opportunity/negotiation-evidence/negotiation-evidence.shadow.js.map +1 -0
  35. package/dist/opportunity/negotiation-evidence/negotiation-evidence.types.d.ts +192 -0
  36. package/dist/opportunity/negotiation-evidence/negotiation-evidence.types.d.ts.map +1 -0
  37. package/dist/opportunity/negotiation-evidence/negotiation-evidence.types.js +19 -0
  38. package/dist/opportunity/negotiation-evidence/negotiation-evidence.types.js.map +1 -0
  39. package/dist/opportunity/negotiation-evidence/negotiation-evidence.verifier.d.ts +35 -0
  40. package/dist/opportunity/negotiation-evidence/negotiation-evidence.verifier.d.ts.map +1 -0
  41. package/dist/opportunity/negotiation-evidence/negotiation-evidence.verifier.js +92 -0
  42. package/dist/opportunity/negotiation-evidence/negotiation-evidence.verifier.js.map +1 -0
  43. package/dist/opportunity/opportunity.graph.d.ts +9 -1
  44. package/dist/opportunity/opportunity.graph.d.ts.map +1 -1
  45. package/dist/opportunity/opportunity.graph.js +64 -31
  46. package/dist/opportunity/opportunity.graph.js.map +1 -1
  47. package/dist/questioner/questioner.types.d.ts +2 -0
  48. package/dist/questioner/questioner.types.d.ts.map +1 -1
  49. package/dist/questioner/questioner.types.js.map +1 -1
  50. package/dist/shared/agent/model.config.d.ts +5 -0
  51. package/dist/shared/agent/model.config.d.ts.map +1 -1
  52. package/dist/shared/agent/model.config.js +1 -0
  53. package/dist/shared/agent/model.config.js.map +1 -1
  54. package/dist/shared/schemas/question.schema.d.ts +21 -0
  55. package/dist/shared/schemas/question.schema.d.ts.map +1 -1
  56. package/dist/shared/schemas/question.schema.js +6 -0
  57. package/dist/shared/schemas/question.schema.js.map +1 -1
  58. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"discriminator.adjustments.js","sourceRoot":"/","sources":["opportunity/discriminator/discriminator.adjustments.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Pool-adjustment domain logic (IND-419) — pure functions, no I/O.\n *\n * When a user answers a pool_discovery question, every candidate the mining\n * pass assigned to a side gets a multiplicative adjustment written to\n * `opportunities.metadata.poolAdjustments`. The home feed (flag-gated) orders\n * by `confidence × Π factor`, floored so demoted candidates stay visible.\n *\n * Invariants:\n * - Deterministic and O(pool): no LLM at answer time — the applyPlan was\n * computed (and evidence-verified) at mining time.\n * - Reversible: entries are keyed by questionId; re-answering replaces them,\n * dismissal-driven reversal removes them.\n * - `detail` carries the template chip text built from the user's OWN answer\n * (\"Hands-on builders vs advisors: you chose Advisor\") — never LLM\n * reasoning (opportunity-presentation-safety).\n */\nimport { POOL_ADJUSTMENT_FACTOR_OTHER, POOL_ADJUSTMENT_FACTOR_UNKNOWN, POOL_ADJUSTMENT_FLOOR } from \"./discriminator.env.js\";\nimport type { QuestionPoolDiscriminator } from \"../../shared/schemas/question.schema.js\";\n\n/** Recipient and intent provenance that scopes one pool preference. */\nexport interface PoolAdjustmentProvenance {\n recipientUserId: string;\n intentId: string;\n}\n\n/** One applied adjustment on an opportunity (stored in metadata.poolAdjustments). */\nexport interface PoolAdjustment extends PoolAdjustmentProvenance {\n /** The answered question that produced this adjustment (reversal key). */\n questionId: string;\n /** Discriminator label, e.g. \"Hands-on builders vs advisors\". */\n label: string;\n /** Side this candidate was assigned to (or \"unknown\"). */\n side: string;\n /** Multiplicative factor: chosen 1.0, other 0.6, unknown 0.9. */\n factor: number;\n /** Template chip text from the user's own answer. Set on demotions only. */\n detail?: string;\n /** ISO-8601 apply timestamp. */\n appliedAt: string;\n}\n\n/** Reads valid adjustments, optionally narrowed to one recipient + intent. */\nexport function readPoolAdjustments(\n metadata: Record<string, unknown> | null | undefined,\n provenance?: PoolAdjustmentProvenance,\n): PoolAdjustment[] {\n const raw = metadata?.poolAdjustments;\n if (!Array.isArray(raw)) return [];\n return raw.filter((a): a is PoolAdjustment => {\n if (\n typeof a !== \"object\" || a === null ||\n typeof (a as PoolAdjustment).questionId !== \"string\" ||\n typeof (a as PoolAdjustment).recipientUserId !== \"string\" ||\n typeof (a as PoolAdjustment).intentId !== \"string\" ||\n typeof (a as PoolAdjustment).factor !== \"number\"\n ) return false;\n return provenance === undefined || (\n (a as PoolAdjustment).recipientUserId === provenance.recipientUserId &&\n (a as PoolAdjustment).intentId === provenance.intentId\n );\n });\n}\n\n/**\n * Cumulative adjustment multiplier for an opportunity, floored at\n * {@link POOL_ADJUSTMENT_FLOOR}. 1 when no scoped adjustments exist.\n */\nexport function poolAdjustmentMultiplier(\n metadata: Record<string, unknown> | null | undefined,\n provenance: PoolAdjustmentProvenance,\n): number {\n const adjustments = readPoolAdjustments(metadata, provenance);\n if (adjustments.length === 0) return 1;\n const product = adjustments.reduce((acc, a) => acc * (Number.isFinite(a.factor) && a.factor > 0 ? a.factor : 1), 1);\n return Math.max(POOL_ADJUSTMENT_FLOOR, product);\n}\n\n/** Adjusted confidence: `confidence × Π factor`, floored. */\nexport function adjustedConfidence(\n confidence: number,\n metadata: Record<string, unknown> | null | undefined,\n provenance: PoolAdjustmentProvenance,\n): number {\n return confidence * poolAdjustmentMultiplier(metadata, provenance);\n}\n\n/** Deterministic provenance signal stored alongside one adjustment. */\nexport interface PoolAdjustmentSignal extends PoolAdjustmentProvenance {\n type: \"pool_discriminator\";\n weight: 1 | -1 | 0;\n detail: string;\n questionId: string;\n}\n\n/** Pure helper input shared by Tier-0 answers and newborn stamping. */\nexport interface BuildPoolAdjustmentInput extends PoolAdjustmentProvenance {\n questionId: string;\n label: string;\n /** Verified side assignment, or null when the candidate is unassigned. */\n assignedSide: string | null;\n chosenSide: string;\n appliedAt: string;\n}\n\n/**\n * Build one P3-compatible adjustment and signal. This is the only place that\n * defines chosen/other/unknown factors, weights, and safe template details.\n */\nexport function buildPoolAdjustment(input: BuildPoolAdjustmentInput): {\n adjustment: PoolAdjustment;\n signal: PoolAdjustmentSignal;\n} {\n const isUnknown = input.assignedSide === null;\n const isChosen = !isUnknown && input.assignedSide === input.chosenSide;\n const factor = isUnknown ? POOL_ADJUSTMENT_FACTOR_UNKNOWN : isChosen ? 1 : POOL_ADJUSTMENT_FACTOR_OTHER;\n const weight = isUnknown ? 0 : isChosen ? 1 : -1;\n const side = input.assignedSide ?? \"unknown\";\n return {\n adjustment: {\n questionId: input.questionId,\n recipientUserId: input.recipientUserId,\n intentId: input.intentId,\n label: input.label,\n side,\n factor,\n ...(!isChosen && !isUnknown ? { detail: `${input.label}: you chose ${input.chosenSide}` } : {}),\n appliedAt: input.appliedAt,\n },\n signal: {\n type: \"pool_discriminator\",\n weight,\n recipientUserId: input.recipientUserId,\n intentId: input.intentId,\n detail: isUnknown ? `${input.label}: unassigned` : `${input.label}: ${input.chosenSide}`,\n questionId: input.questionId,\n },\n };\n}\n\n/** Plan entry: what to write on one opportunity for one answer. */\nexport interface PoolAdjustmentPlanEntry {\n opportunityId: string;\n adjustment: PoolAdjustment;\n signal: PoolAdjustmentSignal;\n}\n\n/**\n * Computes the write plan for one answered discriminator. Pure: the caller\n * loads/patches rows. \"Both matter\" (or any label not in `sides`) yields an\n * empty plan — no preference, no adjustments.\n *\n * @param discriminator The asked discriminator (from detection.pool).\n * @param chosenSide The selected option label (chip label = side label).\n * @param questionId Reversal key.\n * @param recipientUserId User whose answer produced the preference.\n * @param intentId Intent whose candidate pool was ranked.\n * @param now ISO-8601 timestamp.\n */\nexport function planPoolAdjustments(\n discriminator: QuestionPoolDiscriminator,\n chosenSide: string,\n questionId: string,\n recipientUserId: string,\n intentId: string,\n now: string,\n): PoolAdjustmentPlanEntry[] {\n // Chip labels are word-capped side labels; match on the capped prefix too.\n const matchesSide = (side: string): boolean =>\n side === chosenSide || side.startsWith(chosenSide) || chosenSide.startsWith(side);\n const chosen = discriminator.sides.find(matchesSide);\n if (!chosen) return []; // \"Both matter\" or unrecognized option → no adjustments.\n\n const plan: PoolAdjustmentPlanEntry[] = [];\n for (const a of discriminator.assignments) {\n plan.push({\n opportunityId: a.opportunityId,\n ...buildPoolAdjustment({\n questionId,\n recipientUserId,\n intentId,\n label: discriminator.label,\n assignedSide: a.side,\n chosenSide: chosen,\n appliedAt: now,\n }),\n });\n }\n return plan;\n}\n\n/**\n * Merges one adjustment into an opportunity's existing metadata, replacing\n * only the entry for the same question + recipient + intent provenance.\n * Returns the NEW metadata object (caller persists it wholesale).\n */\nexport function mergePoolAdjustment(\n metadata: Record<string, unknown> | null | undefined,\n adjustment: PoolAdjustment,\n): Record<string, unknown> {\n const existing = readPoolAdjustments(metadata).filter((a) => !(\n a.questionId === adjustment.questionId &&\n a.recipientUserId === adjustment.recipientUserId &&\n a.intentId === adjustment.intentId\n ));\n return { ...(metadata ?? {}), poolAdjustments: [...existing, adjustment] };\n}\n\n/** Latest scoped user-explainable demotion detail for card presentation. */\nexport function latestPoolDemotionDetail(\n metadata: Record<string, unknown> | null | undefined,\n provenance: PoolAdjustmentProvenance,\n): string | undefined {\n return [...readPoolAdjustments(metadata, provenance)]\n .reverse()\n .find((adjustment) => adjustment.factor < 1 && typeof adjustment.detail === 'string' && adjustment.detail.length > 0)\n ?.detail;\n}\n\n/** Removes one question adjustment for exact recipient + intent provenance. */\nexport function removePoolAdjustment(\n metadata: Record<string, unknown> | null | undefined,\n questionId: string,\n provenance: PoolAdjustmentProvenance,\n): Record<string, unknown> {\n const remaining = readPoolAdjustments(metadata).filter((a) => !(\n a.questionId === questionId &&\n a.recipientUserId === provenance.recipientUserId &&\n a.intentId === provenance.intentId\n ));\n return { ...(metadata ?? {}), poolAdjustments: remaining };\n}\n"]}
1
+ {"version":3,"file":"discriminator.adjustments.js","sourceRoot":"/","sources":["opportunity/discriminator/discriminator.adjustments.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,4BAA4B,EAAE,8BAA8B,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AA6B7H,8EAA8E;AAC9E,MAAM,UAAU,mBAAmB,CACjC,QAAoD,EACpD,UAAqC;IAErC,MAAM,GAAG,GAAG,QAAQ,EAAE,eAAe,CAAC;IACtC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IACnC,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAuB,EAAE;QAC3C,IACE,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI;YACnC,OAAQ,CAAoB,CAAC,UAAU,KAAK,QAAQ;YACpD,OAAQ,CAAoB,CAAC,eAAe,KAAK,QAAQ;YACzD,OAAQ,CAAoB,CAAC,QAAQ,KAAK,QAAQ;YAClD,OAAQ,CAAoB,CAAC,MAAM,KAAK,QAAQ;YAChD,CAAE,CAAoB,CAAC,KAAK,KAAK,SAAS,IAAK,CAAoB,CAAC,KAAK,KAAK,IAAI,CAAC;YACnF,OAAO,KAAK,CAAC;QACf,OAAO,UAAU,KAAK,SAAS,IAAI,CAChC,CAAoB,CAAC,eAAe,KAAK,UAAU,CAAC,eAAe;YACnE,CAAoB,CAAC,QAAQ,KAAK,UAAU,CAAC,QAAQ,CACvD,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,yBAAyB,CACvC,QAAoD,EACpD,UAAqC;IAErC,OAAO,mBAAmB,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC;AACrG,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CACtC,QAAoD,EACpD,UAAoC;IAEpC,MAAM,WAAW,GAAG,yBAAyB,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IACpE,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IACvC,MAAM,OAAO,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACpH,OAAO,IAAI,CAAC,GAAG,CAAC,qBAAqB,EAAE,OAAO,CAAC,CAAC;AAClD,CAAC;AAED,6DAA6D;AAC7D,MAAM,UAAU,kBAAkB,CAChC,UAAkB,EAClB,QAAoD,EACpD,UAAoC;IAEpC,OAAO,UAAU,GAAG,wBAAwB,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;AACrE,CAAC;AAsBD;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAA+B;IAIjE,MAAM,SAAS,GAAG,KAAK,CAAC,YAAY,KAAK,IAAI,CAAC;IAC9C,MAAM,QAAQ,GAAG,CAAC,SAAS,IAAI,KAAK,CAAC,YAAY,KAAK,KAAK,CAAC,UAAU,CAAC;IACvE,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,8BAA8B,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,4BAA4B,CAAC;IACxG,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACjD,MAAM,IAAI,GAAG,KAAK,CAAC,YAAY,IAAI,SAAS,CAAC;IAC7C,OAAO;QACL,UAAU,EAAE;YACV,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,eAAe,EAAE,KAAK,CAAC,eAAe;YACtC,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,IAAI;YACJ,MAAM;YACN,GAAG,CAAC,CAAC,QAAQ,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC,KAAK,eAAe,KAAK,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC/F,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,GAAG,CAAC,KAAK,CAAC,iBAAiB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,KAAK,CAAC,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACjG;QACD,MAAM,EAAE;YACN,IAAI,EAAE,oBAAoB;YAC1B,MAAM;YACN,eAAe,EAAE,KAAK,CAAC,eAAe;YACtC,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,cAAc,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,KAAK,KAAK,CAAC,UAAU,EAAE;YACxF,UAAU,EAAE,KAAK,CAAC,UAAU;SAC7B;KACF,CAAC;AACJ,CAAC;AASD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,mBAAmB,CACjC,aAAwC,EACxC,UAAkB,EAClB,UAAkB,EAClB,eAAuB,EACvB,QAAgB,EAChB,GAAW,EACX,iBAA0B;IAE1B,2EAA2E;IAC3E,MAAM,WAAW,GAAG,CAAC,IAAY,EAAW,EAAE,CAC5C,IAAI,KAAK,UAAU,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IACpF,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACrD,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC,CAAC,yDAAyD;IAEjF,MAAM,IAAI,GAA8B,EAAE,CAAC;IAC3C,KAAK,MAAM,CAAC,IAAI,aAAa,CAAC,WAAW,EAAE,CAAC;QAC1C,IAAI,CAAC,IAAI,CAAC;YACR,aAAa,EAAE,CAAC,CAAC,aAAa;YAC9B,GAAG,mBAAmB,CAAC;gBACrB,UAAU;gBACV,eAAe;gBACf,QAAQ;gBACR,KAAK,EAAE,aAAa,CAAC,KAAK;gBAC1B,YAAY,EAAE,CAAC,CAAC,IAAI;gBACpB,UAAU,EAAE,MAAM;gBAClB,SAAS,EAAE,GAAG;gBACd,GAAG,CAAC,iBAAiB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,iBAAiB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aAClE,CAAC;SACH,CAAC,CAAC;IACL,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CACjC,QAAoD,EACpD,UAA0B;IAE1B,MAAM,QAAQ,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAC5D,CAAC,CAAC,UAAU,KAAK,UAAU,CAAC,UAAU;QACtC,CAAC,CAAC,eAAe,KAAK,UAAU,CAAC,eAAe;QAChD,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAC,QAAQ,CACnC,CAAC,CAAC;IACH,OAAO,EAAE,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,eAAe,EAAE,CAAC,GAAG,QAAQ,EAAE,UAAU,CAAC,EAAE,CAAC;AAC7E,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,wBAAwB,CACtC,QAAoD,EACpD,UAAoC;IAEpC,OAAO,CAAC,GAAG,yBAAyB,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;SACxD,OAAO,EAAE;SACT,IAAI,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,UAAU,CAAC,MAAM,KAAK,QAAQ,IAAI,UAAU,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;QACrH,EAAE,MAAM,CAAC;AACb,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,oBAAoB,CAClC,QAAoD,EACpD,UAAkB,EAClB,UAAoC;IAEpC,MAAM,SAAS,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAC7D,CAAC,CAAC,UAAU,KAAK,UAAU;QAC3B,CAAC,CAAC,eAAe,KAAK,UAAU,CAAC,eAAe;QAChD,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAC,QAAQ,CACnC,CAAC,CAAC;IACH,OAAO,EAAE,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,EAAE,eAAe,EAAE,SAAS,EAAE,CAAC;AAC7D,CAAC","sourcesContent":["/**\n * Pool-adjustment domain logic (IND-419) — pure functions, no I/O.\n *\n * When a user answers a pool_discovery question, every candidate the mining\n * pass assigned to a side gets a multiplicative adjustment written to\n * `opportunities.metadata.poolAdjustments`. The home feed (flag-gated) orders\n * by `confidence × Π factor`, floored so demoted candidates stay visible.\n *\n * Invariants:\n * - Deterministic and O(pool): no LLM at answer time — the applyPlan was\n * computed (and evidence-verified) at mining time.\n * - Reversible: entries are keyed by questionId; re-answering replaces them,\n * dismissal-driven reversal removes them.\n * - `detail` carries the template chip text built from the user's OWN answer\n * (\"Hands-on builders vs advisors: you chose Advisor\") — never LLM\n * reasoning (opportunity-presentation-safety).\n */\nimport { POOL_ADJUSTMENT_FACTOR_OTHER, POOL_ADJUSTMENT_FACTOR_UNKNOWN, POOL_ADJUSTMENT_FLOOR } from \"./discriminator.env.js\";\nimport type { QuestionPoolDiscriminator } from \"../../shared/schemas/question.schema.js\";\n\n/** Recipient and intent provenance that scopes one pool preference. */\nexport interface PoolAdjustmentProvenance {\n recipientUserId: string;\n intentId: string;\n}\n\n/** One applied adjustment on an opportunity (stored in metadata.poolAdjustments). */\nexport interface PoolAdjustment extends PoolAdjustmentProvenance {\n /** The answered question that produced this adjustment (reversal key). */\n questionId: string;\n /** Discriminator label, e.g. \"Hands-on builders vs advisors\". */\n label: string;\n /** Side this candidate was assigned to (or \"unknown\"). */\n side: string;\n /** Multiplicative factor: chosen 1.0, other 0.6, unknown 0.9. */\n factor: number;\n /** Template chip text from the user's own answer. Set on demotions only. */\n detail?: string;\n /** ISO-8601 apply timestamp. */\n appliedAt: string;\n /** Full intent fingerprint authoritative when this adjustment was created. */\n intentFingerprint?: string;\n /** Audit-only marker: stale adjustments remain stored but have no ranking effect. */\n stale?: true;\n}\n\n/** Reads valid adjustments, optionally narrowed to one recipient + intent. */\nexport function readPoolAdjustments(\n metadata: Record<string, unknown> | null | undefined,\n provenance?: PoolAdjustmentProvenance,\n): PoolAdjustment[] {\n const raw = metadata?.poolAdjustments;\n if (!Array.isArray(raw)) return [];\n return raw.filter((a): a is PoolAdjustment => {\n if (\n typeof a !== \"object\" || a === null ||\n typeof (a as PoolAdjustment).questionId !== \"string\" ||\n typeof (a as PoolAdjustment).recipientUserId !== \"string\" ||\n typeof (a as PoolAdjustment).intentId !== \"string\" ||\n typeof (a as PoolAdjustment).factor !== \"number\" ||\n ((a as PoolAdjustment).stale !== undefined && (a as PoolAdjustment).stale !== true)\n ) return false;\n return provenance === undefined || (\n (a as PoolAdjustment).recipientUserId === provenance.recipientUserId &&\n (a as PoolAdjustment).intentId === provenance.intentId\n );\n });\n}\n\n/** Reads valid, non-stale adjustments for ranking and presentation behavior. */\nexport function readActivePoolAdjustments(\n metadata: Record<string, unknown> | null | undefined,\n provenance?: PoolAdjustmentProvenance,\n): PoolAdjustment[] {\n return readPoolAdjustments(metadata, provenance).filter((adjustment) => adjustment.stale !== true);\n}\n\n/**\n * Cumulative adjustment multiplier for an opportunity, floored at\n * {@link POOL_ADJUSTMENT_FLOOR}. 1 when no scoped adjustments exist.\n */\nexport function poolAdjustmentMultiplier(\n metadata: Record<string, unknown> | null | undefined,\n provenance: PoolAdjustmentProvenance,\n): number {\n const adjustments = readActivePoolAdjustments(metadata, provenance);\n if (adjustments.length === 0) return 1;\n const product = adjustments.reduce((acc, a) => acc * (Number.isFinite(a.factor) && a.factor > 0 ? a.factor : 1), 1);\n return Math.max(POOL_ADJUSTMENT_FLOOR, product);\n}\n\n/** Adjusted confidence: `confidence × Π factor`, floored. */\nexport function adjustedConfidence(\n confidence: number,\n metadata: Record<string, unknown> | null | undefined,\n provenance: PoolAdjustmentProvenance,\n): number {\n return confidence * poolAdjustmentMultiplier(metadata, provenance);\n}\n\n/** Deterministic provenance signal stored alongside one adjustment. */\nexport interface PoolAdjustmentSignal extends PoolAdjustmentProvenance {\n type: \"pool_discriminator\";\n weight: 1 | -1 | 0;\n detail: string;\n questionId: string;\n}\n\n/** Pure helper input shared by Tier-0 answers and newborn stamping. */\nexport interface BuildPoolAdjustmentInput extends PoolAdjustmentProvenance {\n questionId: string;\n label: string;\n /** Verified side assignment, or null when the candidate is unassigned. */\n assignedSide: string | null;\n chosenSide: string;\n appliedAt: string;\n /** Full intent fingerprint authoritative when this adjustment was created. */\n intentFingerprint?: string;\n}\n\n/**\n * Build one P3-compatible adjustment and signal. This is the only place that\n * defines chosen/other/unknown factors, weights, and safe template details.\n */\nexport function buildPoolAdjustment(input: BuildPoolAdjustmentInput): {\n adjustment: PoolAdjustment;\n signal: PoolAdjustmentSignal;\n} {\n const isUnknown = input.assignedSide === null;\n const isChosen = !isUnknown && input.assignedSide === input.chosenSide;\n const factor = isUnknown ? POOL_ADJUSTMENT_FACTOR_UNKNOWN : isChosen ? 1 : POOL_ADJUSTMENT_FACTOR_OTHER;\n const weight = isUnknown ? 0 : isChosen ? 1 : -1;\n const side = input.assignedSide ?? \"unknown\";\n return {\n adjustment: {\n questionId: input.questionId,\n recipientUserId: input.recipientUserId,\n intentId: input.intentId,\n label: input.label,\n side,\n factor,\n ...(!isChosen && !isUnknown ? { detail: `${input.label}: you chose ${input.chosenSide}` } : {}),\n appliedAt: input.appliedAt,\n ...(input.intentFingerprint !== undefined ? { intentFingerprint: input.intentFingerprint } : {}),\n },\n signal: {\n type: \"pool_discriminator\",\n weight,\n recipientUserId: input.recipientUserId,\n intentId: input.intentId,\n detail: isUnknown ? `${input.label}: unassigned` : `${input.label}: ${input.chosenSide}`,\n questionId: input.questionId,\n },\n };\n}\n\n/** Plan entry: what to write on one opportunity for one answer. */\nexport interface PoolAdjustmentPlanEntry {\n opportunityId: string;\n adjustment: PoolAdjustment;\n signal: PoolAdjustmentSignal;\n}\n\n/**\n * Computes the write plan for one answered discriminator. Pure: the caller\n * loads/patches rows. \"Both matter\" (or any label not in `sides`) yields an\n * empty plan — no preference, no adjustments.\n *\n * @param discriminator The asked discriminator (from detection.pool).\n * @param chosenSide The selected option label (chip label = side label).\n * @param questionId Reversal key.\n * @param recipientUserId User whose answer produced the preference.\n * @param intentId Intent whose candidate pool was ranked.\n * @param now ISO-8601 timestamp.\n * @param intentFingerprint Full intent fingerprint authoritative at apply time.\n */\nexport function planPoolAdjustments(\n discriminator: QuestionPoolDiscriminator,\n chosenSide: string,\n questionId: string,\n recipientUserId: string,\n intentId: string,\n now: string,\n intentFingerprint?: string,\n): PoolAdjustmentPlanEntry[] {\n // Chip labels are word-capped side labels; match on the capped prefix too.\n const matchesSide = (side: string): boolean =>\n side === chosenSide || side.startsWith(chosenSide) || chosenSide.startsWith(side);\n const chosen = discriminator.sides.find(matchesSide);\n if (!chosen) return []; // \"Both matter\" or unrecognized option → no adjustments.\n\n const plan: PoolAdjustmentPlanEntry[] = [];\n for (const a of discriminator.assignments) {\n plan.push({\n opportunityId: a.opportunityId,\n ...buildPoolAdjustment({\n questionId,\n recipientUserId,\n intentId,\n label: discriminator.label,\n assignedSide: a.side,\n chosenSide: chosen,\n appliedAt: now,\n ...(intentFingerprint !== undefined ? { intentFingerprint } : {}),\n }),\n });\n }\n return plan;\n}\n\n/**\n * Merges one adjustment into an opportunity's existing metadata, replacing\n * only the entry for the same question + recipient + intent provenance.\n * Returns the NEW metadata object (caller persists it wholesale).\n */\nexport function mergePoolAdjustment(\n metadata: Record<string, unknown> | null | undefined,\n adjustment: PoolAdjustment,\n): Record<string, unknown> {\n const existing = readPoolAdjustments(metadata).filter((a) => !(\n a.questionId === adjustment.questionId &&\n a.recipientUserId === adjustment.recipientUserId &&\n a.intentId === adjustment.intentId\n ));\n return { ...(metadata ?? {}), poolAdjustments: [...existing, adjustment] };\n}\n\n/** Latest scoped user-explainable demotion detail for card presentation. */\nexport function latestPoolDemotionDetail(\n metadata: Record<string, unknown> | null | undefined,\n provenance: PoolAdjustmentProvenance,\n): string | undefined {\n return [...readActivePoolAdjustments(metadata, provenance)]\n .reverse()\n .find((adjustment) => adjustment.factor < 1 && typeof adjustment.detail === 'string' && adjustment.detail.length > 0)\n ?.detail;\n}\n\n/** Removes one question adjustment for exact recipient + intent provenance. */\nexport function removePoolAdjustment(\n metadata: Record<string, unknown> | null | undefined,\n questionId: string,\n provenance: PoolAdjustmentProvenance,\n): Record<string, unknown> {\n const remaining = readPoolAdjustments(metadata).filter((a) => !(\n a.questionId === questionId &&\n a.recipientUserId === provenance.recipientUserId &&\n a.intentId === provenance.intentId\n ));\n return { ...(metadata ?? {}), poolAdjustments: remaining };\n}\n"]}
@@ -31,6 +31,8 @@ export interface SynthesizePoolQuestionInput {
31
31
  /** Remaining ranked eligible discriminators (interview-mode chain stash). */
32
32
  alternates: QuestionPoolDiscriminator[];
33
33
  poolSize: number;
34
+ /** Exact bounded candidate opportunity IDs supplied to this synthesis pass. */
35
+ opportunityIds: string[];
34
36
  /** ISO-8601 timestamp of the mining pass. */
35
37
  minedAt: string;
36
38
  /** Discovery run id, when known. */
@@ -1 +1 @@
1
- {"version":3,"file":"discriminator.question.d.ts","sourceRoot":"/","sources":["opportunity/discriminator/discriminator.question.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAkB,yBAAyB,EAAE,oBAAoB,EAAE,MAAM,yCAAyC,CAAC;AAEzI,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEpE,+EAA+E;AAC/E,eAAO,MAAM,iBAAiB,gBAAgB,CAAC;AAQ/C;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,mBAAmB,GAAG,yBAAyB,CAqBzF;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,cAAc,EAAE,mBAAmB,EAAE,GAAG,mBAAmB,EAAE,CAIzG;AAkED,wCAAwC;AACxC,MAAM,WAAW,2BAA2B;IAC1C,qEAAqE;IACrE,aAAa,EAAE,yBAAyB,CAAC;IACzC,6EAA6E;IAC7E,UAAU,EAAE,yBAAyB,EAAE,CAAC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mEAAmE;IACnE,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,mEAAmE;AACnE,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,QAAQ,CAAC;IAClB,IAAI,EAAE,oBAAoB,CAAC;CAC5B;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,2BAA2B,GAAG,uBAAuB,GAAG,IAAI,CA0CzG"}
1
+ {"version":3,"file":"discriminator.question.d.ts","sourceRoot":"/","sources":["opportunity/discriminator/discriminator.question.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAkB,yBAAyB,EAAE,oBAAoB,EAAE,MAAM,yCAAyC,CAAC;AAEzI,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAEpE,+EAA+E;AAC/E,eAAO,MAAM,iBAAiB,gBAAgB,CAAC;AAQ/C;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,mBAAmB,GAAG,yBAAyB,CAqBzF;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,cAAc,EAAE,mBAAmB,EAAE,GAAG,mBAAmB,EAAE,CAIzG;AAkED,wCAAwC;AACxC,MAAM,WAAW,2BAA2B;IAC1C,qEAAqE;IACrE,aAAa,EAAE,yBAAyB,CAAC;IACzC,6EAA6E;IAC7E,UAAU,EAAE,yBAAyB,EAAE,CAAC;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,6CAA6C;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,mEAAmE;IACnE,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,mEAAmE;AACnE,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,QAAQ,CAAC;IAClB,IAAI,EAAE,oBAAoB,CAAC;CAC5B;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,2BAA2B,GAAG,uBAAuB,GAAG,IAAI,CA2CzG"}
@@ -143,6 +143,7 @@ export function synthesizePoolQuestion(input) {
143
143
  },
144
144
  pool: {
145
145
  poolSize,
146
+ opportunityIds: [...input.opportunityIds],
146
147
  minedAt: input.minedAt,
147
148
  ...(input.runId ? { runId: input.runId } : {}),
148
149
  ...(snippet.length > 0 ? { intentText: snippet.slice(0, 160) } : {}),
@@ -1 +1 @@
1
- {"version":3,"file":"discriminator.question.js","sourceRoot":"/","sources":["opportunity/discriminator/discriminator.question.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Deterministic pool_discovery question synthesis (IND-418).\n *\n * A mined discriminator already carries everything a question needs: a label,\n * a question seed, 2–3 sides, and verified per-candidate assignments. This\n * module turns the top discriminator into a `Question` payload + server-side\n * pool snapshot with ZERO generation-time LLM calls — the phrasing was\n * produced (and evidence-verified) at mining time, so synthesis is pure,\n * auditable, and cheap to re-run for interview-mode chaining.\n */\nimport type { Question, QuestionOption, QuestionPoolDiscriminator, QuestionPoolSnapshot } from \"../../shared/schemas/question.schema.js\";\nimport { POOL_DISCRIMINATOR_MIN_POOL_SIZE, POOL_QUESTION_MAX_DISCRIMINATORS, POOL_QUESTION_MIN_EVIDENCE_RATE, POOL_QUESTION_MIN_VOI } from \"./discriminator.env.js\";\nimport type { ScoredDiscriminator } from \"./discriminator.types.js\";\n\n/** Fixed option appended to every pool question — the no-preference escape. */\nexport const BOTH_MATTER_LABEL = \"Both matter\";\n\n/** Max words in a chip-style option label (prototype voice: terse, glanceable). */\nconst MAX_LABEL_WORDS = 5;\n\n/** Question title (≤12 chars, per QuestionSchema). */\nconst POOL_QUESTION_TITLE = \"Matches\";\n\n/**\n * Converts a scored discriminator into the compact snapshot form stored on\n * the question row (verified assignments only; unknowns dropped).\n */\nexport function toQuestionDiscriminator(d: ScoredDiscriminator): QuestionPoolDiscriminator {\n const sideCounts: Record<string, number> = {};\n for (const side of d.sides) sideCounts[side] = 0;\n const assignments: Array<{ opportunityId: string; side: string }> = [];\n for (const a of d.assignments) {\n if (a.side === null || !a.verified) continue;\n if (!(a.side in sideCounts)) continue;\n sideCounts[a.side] += 1;\n assignments.push({ opportunityId: a.id, side: a.side });\n }\n return {\n label: d.label,\n questionSeed: d.questionSeed,\n sides: d.sides,\n sideCounts,\n voi: d.voi,\n evidenceRate: d.evidenceRate,\n ...(d.embedding ? { embedding: d.embedding } : {}),\n ...(d.embeddingModel ? { embeddingModel: d.embeddingModel } : {}),\n assignments,\n };\n}\n\n/**\n * Filters a mining pass down to question-eligible discriminators:\n * VoI ≥ {@link POOL_QUESTION_MIN_VOI}, evidenceRate ≥\n * {@link POOL_QUESTION_MIN_EVIDENCE_RATE}, capped at\n * {@link POOL_QUESTION_MAX_DISCRIMINATORS}. Input is already VoI-sorted.\n */\nexport function selectQuestionDiscriminators(discriminators: ScoredDiscriminator[]): ScoredDiscriminator[] {\n return discriminators\n .filter((d) => d.voi >= POOL_QUESTION_MIN_VOI && d.evidenceRate >= POOL_QUESTION_MIN_EVIDENCE_RATE)\n .slice(0, POOL_QUESTION_MAX_DISCRIMINATORS);\n}\n\n/** Truncates a side label to the chip word budget. */\nfunction chipLabel(side: string): string {\n const words = side.trim().split(/\\s+/);\n return words.slice(0, MAX_LABEL_WORDS).join(\" \");\n}\n\n/**\n * Miner seeds are sometimes written from the intent owner's POV (\"Do I\n * prefer…\"). The question is asked TO the owner, so normalize to second\n * person. Conservative verb-pair map + bare pronoun/possessive swaps.\n */\nfunction toSecondPerson(seed: string): string {\n return seed\n .replace(/\\b(do|should|would|could|can|will) I\\b/gi, (_, verb: string) => `${verb.toLowerCase()} you`)\n .replace(/\\bam I\\b/gi, \"are you\")\n .replace(/\\bI\\b/g, \"you\")\n .replace(/\\bmy\\b/gi, \"your\")\n // Third-person seeds (\"Is the user primarily involved…\") — the question is\n // asked TO the owner, never ABOUT them.\n .replace(/\\b(is|was) (?:the|this) (user|owner|discoverer|client)\\b/gi, \"are you\")\n .replace(/\\bdoes (?:the|this) (user|owner|discoverer|client)\\b/gi, \"do you\")\n .replace(/\\b(?:the|this) (user|owner|discoverer|client)'s\\b/gi, \"your\")\n .replace(/\\b(?:the|this) (user|owner|discoverer|client)\\b/gi, \"you\");\n}\n\n/**\n * Catch-all: after normalization the prompt must be second-person. Any\n * residual third-person reference to the owner means an unanticipated seed\n * shape slipped through — the deterministic two-sided template (always\n * second-person) is the safe fallback.\n */\nfunction isStillThirdPerson(prompt: string): boolean {\n return /\\b(?:the|this|a) (?:user|owner|discoverer|client)\\b/i.test(prompt);\n}\n\n/**\n * A good discriminator prompt names BOTH sides so the chips read as a real\n * choice. When the seed mentions fewer than two sides (e.g. \"Do you prefer\n * hands-on prototyping?\"), fall back to a deterministic two-sided template.\n */\nfunction mentionsSide(seed: string, side: string): boolean {\n const lowerSeed = seed.toLowerCase();\n return side\n .toLowerCase()\n .split(/[^a-z0-9-]+/)\n .filter((w) => w.length > 3)\n .some((w) => lowerSeed.includes(w));\n}\n\n/** Ensures the prompt reads as one second-person, two-sided question. */\nfunction toPrompt(questionSeed: string, sides: string[]): string {\n let p = toSecondPerson(questionSeed.trim().replace(/\\s+/g, \" \"));\n const sidesMentioned = sides.filter((s) => mentionsSide(p, s)).length;\n if (sidesMentioned < 2 || isStillThirdPerson(p)) {\n const last = sides[sides.length - 1];\n const head = sides.slice(0, -1).join(\", \");\n p = `Which matters more here: ${head} or ${last}`;\n }\n // Sentence-case the first character (template + normalization can lowercase it).\n p = p.charAt(0).toUpperCase() + p.slice(1);\n if (!/[?]$/.test(p)) p = p.replace(/[.!]+$/, \"\") + \"?\";\n return p.slice(0, 400);\n}\n\n/** Input for one question synthesis. */\nexport interface SynthesizePoolQuestionInput {\n /** The discriminator to ask about (already eligibility-filtered). */\n discriminator: QuestionPoolDiscriminator;\n /** Remaining ranked eligible discriminators (interview-mode chain stash). */\n alternates: QuestionPoolDiscriminator[];\n poolSize: number;\n /** ISO-8601 timestamp of the mining pass. */\n minedAt: string;\n /** Discovery run id, when known. */\n runId?: string;\n /**\n * Intent payload snippet — folded into the evidence chip so the question\n * self-identifies on any surface (\"based on 16 people matching ‘…’\").\n */\n intentText?: string;\n /** Stable hash of the full normalized intent payload + summary. */\n intentFingerprint?: string;\n}\n\n/** Synthesized question: client payload + server-side snapshot. */\nexport interface SynthesizedPoolQuestion {\n payload: Question;\n pool: QuestionPoolSnapshot;\n}\n\n/**\n * Builds the pool_discovery question. Returns null when the pool is below\n * the k-anonymity floor or the discriminator shape is unusable (guards are\n * duplicated here so no caller can bypass them).\n */\nexport function synthesizePoolQuestion(input: SynthesizePoolQuestionInput): SynthesizedPoolQuestion | null {\n const { discriminator: d, poolSize } = input;\n if (poolSize < POOL_DISCRIMINATOR_MIN_POOL_SIZE) return null;\n if (d.sides.length < 2 || d.sides.length > 3) return null;\n\n // Evidence chip: aggregate count + the intent it belongs to, so the card is\n // self-identifying on every surface (QuestionSchema caps evidence at 160).\n const snippet = input.intentText?.trim().replace(/\\s+/g, \" \") ?? \"\";\n const evidence = snippet.length > 0\n ? `based on ${poolSize} people matching “${snippet.slice(0, 110)}${snippet.length > 110 ? \"…\" : \"\"}”`\n : `based on ${poolSize} people matching this intent`;\n\n const sideOptions: QuestionOption[] = d.sides.map((side) => ({\n label: chipLabel(side),\n description: `${d.sideCounts[side] ?? 0} of your ${poolSize} current matches lean this way`,\n }));\n const options: QuestionOption[] = [\n ...sideOptions,\n {\n label: BOTH_MATTER_LABEL,\n description: \"No preference — keep the current ranking\",\n },\n ];\n\n return {\n payload: {\n title: POOL_QUESTION_TITLE,\n prompt: toPrompt(d.questionSeed, d.sides),\n options,\n multiSelect: false,\n evidence,\n },\n pool: {\n poolSize,\n minedAt: input.minedAt,\n ...(input.runId ? { runId: input.runId } : {}),\n ...(snippet.length > 0 ? { intentText: snippet.slice(0, 160) } : {}),\n ...(input.intentFingerprint ? { intentFingerprint: input.intentFingerprint } : {}),\n discriminator: d,\n alternates: input.alternates,\n },\n };\n}\n"]}
1
+ {"version":3,"file":"discriminator.question.js","sourceRoot":"/","sources":["opportunity/discriminator/discriminator.question.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Deterministic pool_discovery question synthesis (IND-418).\n *\n * A mined discriminator already carries everything a question needs: a label,\n * a question seed, 2–3 sides, and verified per-candidate assignments. This\n * module turns the top discriminator into a `Question` payload + server-side\n * pool snapshot with ZERO generation-time LLM calls — the phrasing was\n * produced (and evidence-verified) at mining time, so synthesis is pure,\n * auditable, and cheap to re-run for interview-mode chaining.\n */\nimport type { Question, QuestionOption, QuestionPoolDiscriminator, QuestionPoolSnapshot } from \"../../shared/schemas/question.schema.js\";\nimport { POOL_DISCRIMINATOR_MIN_POOL_SIZE, POOL_QUESTION_MAX_DISCRIMINATORS, POOL_QUESTION_MIN_EVIDENCE_RATE, POOL_QUESTION_MIN_VOI } from \"./discriminator.env.js\";\nimport type { ScoredDiscriminator } from \"./discriminator.types.js\";\n\n/** Fixed option appended to every pool question — the no-preference escape. */\nexport const BOTH_MATTER_LABEL = \"Both matter\";\n\n/** Max words in a chip-style option label (prototype voice: terse, glanceable). */\nconst MAX_LABEL_WORDS = 5;\n\n/** Question title (≤12 chars, per QuestionSchema). */\nconst POOL_QUESTION_TITLE = \"Matches\";\n\n/**\n * Converts a scored discriminator into the compact snapshot form stored on\n * the question row (verified assignments only; unknowns dropped).\n */\nexport function toQuestionDiscriminator(d: ScoredDiscriminator): QuestionPoolDiscriminator {\n const sideCounts: Record<string, number> = {};\n for (const side of d.sides) sideCounts[side] = 0;\n const assignments: Array<{ opportunityId: string; side: string }> = [];\n for (const a of d.assignments) {\n if (a.side === null || !a.verified) continue;\n if (!(a.side in sideCounts)) continue;\n sideCounts[a.side] += 1;\n assignments.push({ opportunityId: a.id, side: a.side });\n }\n return {\n label: d.label,\n questionSeed: d.questionSeed,\n sides: d.sides,\n sideCounts,\n voi: d.voi,\n evidenceRate: d.evidenceRate,\n ...(d.embedding ? { embedding: d.embedding } : {}),\n ...(d.embeddingModel ? { embeddingModel: d.embeddingModel } : {}),\n assignments,\n };\n}\n\n/**\n * Filters a mining pass down to question-eligible discriminators:\n * VoI ≥ {@link POOL_QUESTION_MIN_VOI}, evidenceRate ≥\n * {@link POOL_QUESTION_MIN_EVIDENCE_RATE}, capped at\n * {@link POOL_QUESTION_MAX_DISCRIMINATORS}. Input is already VoI-sorted.\n */\nexport function selectQuestionDiscriminators(discriminators: ScoredDiscriminator[]): ScoredDiscriminator[] {\n return discriminators\n .filter((d) => d.voi >= POOL_QUESTION_MIN_VOI && d.evidenceRate >= POOL_QUESTION_MIN_EVIDENCE_RATE)\n .slice(0, POOL_QUESTION_MAX_DISCRIMINATORS);\n}\n\n/** Truncates a side label to the chip word budget. */\nfunction chipLabel(side: string): string {\n const words = side.trim().split(/\\s+/);\n return words.slice(0, MAX_LABEL_WORDS).join(\" \");\n}\n\n/**\n * Miner seeds are sometimes written from the intent owner's POV (\"Do I\n * prefer…\"). The question is asked TO the owner, so normalize to second\n * person. Conservative verb-pair map + bare pronoun/possessive swaps.\n */\nfunction toSecondPerson(seed: string): string {\n return seed\n .replace(/\\b(do|should|would|could|can|will) I\\b/gi, (_, verb: string) => `${verb.toLowerCase()} you`)\n .replace(/\\bam I\\b/gi, \"are you\")\n .replace(/\\bI\\b/g, \"you\")\n .replace(/\\bmy\\b/gi, \"your\")\n // Third-person seeds (\"Is the user primarily involved…\") — the question is\n // asked TO the owner, never ABOUT them.\n .replace(/\\b(is|was) (?:the|this) (user|owner|discoverer|client)\\b/gi, \"are you\")\n .replace(/\\bdoes (?:the|this) (user|owner|discoverer|client)\\b/gi, \"do you\")\n .replace(/\\b(?:the|this) (user|owner|discoverer|client)'s\\b/gi, \"your\")\n .replace(/\\b(?:the|this) (user|owner|discoverer|client)\\b/gi, \"you\");\n}\n\n/**\n * Catch-all: after normalization the prompt must be second-person. Any\n * residual third-person reference to the owner means an unanticipated seed\n * shape slipped through — the deterministic two-sided template (always\n * second-person) is the safe fallback.\n */\nfunction isStillThirdPerson(prompt: string): boolean {\n return /\\b(?:the|this|a) (?:user|owner|discoverer|client)\\b/i.test(prompt);\n}\n\n/**\n * A good discriminator prompt names BOTH sides so the chips read as a real\n * choice. When the seed mentions fewer than two sides (e.g. \"Do you prefer\n * hands-on prototyping?\"), fall back to a deterministic two-sided template.\n */\nfunction mentionsSide(seed: string, side: string): boolean {\n const lowerSeed = seed.toLowerCase();\n return side\n .toLowerCase()\n .split(/[^a-z0-9-]+/)\n .filter((w) => w.length > 3)\n .some((w) => lowerSeed.includes(w));\n}\n\n/** Ensures the prompt reads as one second-person, two-sided question. */\nfunction toPrompt(questionSeed: string, sides: string[]): string {\n let p = toSecondPerson(questionSeed.trim().replace(/\\s+/g, \" \"));\n const sidesMentioned = sides.filter((s) => mentionsSide(p, s)).length;\n if (sidesMentioned < 2 || isStillThirdPerson(p)) {\n const last = sides[sides.length - 1];\n const head = sides.slice(0, -1).join(\", \");\n p = `Which matters more here: ${head} or ${last}`;\n }\n // Sentence-case the first character (template + normalization can lowercase it).\n p = p.charAt(0).toUpperCase() + p.slice(1);\n if (!/[?]$/.test(p)) p = p.replace(/[.!]+$/, \"\") + \"?\";\n return p.slice(0, 400);\n}\n\n/** Input for one question synthesis. */\nexport interface SynthesizePoolQuestionInput {\n /** The discriminator to ask about (already eligibility-filtered). */\n discriminator: QuestionPoolDiscriminator;\n /** Remaining ranked eligible discriminators (interview-mode chain stash). */\n alternates: QuestionPoolDiscriminator[];\n poolSize: number;\n /** Exact bounded candidate opportunity IDs supplied to this synthesis pass. */\n opportunityIds: string[];\n /** ISO-8601 timestamp of the mining pass. */\n minedAt: string;\n /** Discovery run id, when known. */\n runId?: string;\n /**\n * Intent payload snippet — folded into the evidence chip so the question\n * self-identifies on any surface (\"based on 16 people matching ‘…’\").\n */\n intentText?: string;\n /** Stable hash of the full normalized intent payload + summary. */\n intentFingerprint?: string;\n}\n\n/** Synthesized question: client payload + server-side snapshot. */\nexport interface SynthesizedPoolQuestion {\n payload: Question;\n pool: QuestionPoolSnapshot;\n}\n\n/**\n * Builds the pool_discovery question. Returns null when the pool is below\n * the k-anonymity floor or the discriminator shape is unusable (guards are\n * duplicated here so no caller can bypass them).\n */\nexport function synthesizePoolQuestion(input: SynthesizePoolQuestionInput): SynthesizedPoolQuestion | null {\n const { discriminator: d, poolSize } = input;\n if (poolSize < POOL_DISCRIMINATOR_MIN_POOL_SIZE) return null;\n if (d.sides.length < 2 || d.sides.length > 3) return null;\n\n // Evidence chip: aggregate count + the intent it belongs to, so the card is\n // self-identifying on every surface (QuestionSchema caps evidence at 160).\n const snippet = input.intentText?.trim().replace(/\\s+/g, \" \") ?? \"\";\n const evidence = snippet.length > 0\n ? `based on ${poolSize} people matching “${snippet.slice(0, 110)}${snippet.length > 110 ? \"…\" : \"\"}”`\n : `based on ${poolSize} people matching this intent`;\n\n const sideOptions: QuestionOption[] = d.sides.map((side) => ({\n label: chipLabel(side),\n description: `${d.sideCounts[side] ?? 0} of your ${poolSize} current matches lean this way`,\n }));\n const options: QuestionOption[] = [\n ...sideOptions,\n {\n label: BOTH_MATTER_LABEL,\n description: \"No preference — keep the current ranking\",\n },\n ];\n\n return {\n payload: {\n title: POOL_QUESTION_TITLE,\n prompt: toPrompt(d.questionSeed, d.sides),\n options,\n multiSelect: false,\n evidence,\n },\n pool: {\n poolSize,\n opportunityIds: [...input.opportunityIds],\n minedAt: input.minedAt,\n ...(input.runId ? { runId: input.runId } : {}),\n ...(snippet.length > 0 ? { intentText: snippet.slice(0, 160) } : {}),\n ...(input.intentFingerprint ? { intentFingerprint: input.intentFingerprint } : {}),\n discriminator: d,\n alternates: input.alternates,\n },\n };\n}\n"]}
@@ -22,7 +22,7 @@ import { buildHomeCardPresentationCacheKey, buildHomeCategoryPresentationCacheKe
22
22
  import { protocolLogger } from '../../shared/observability/protocol.logger.js';
23
23
  import { timed } from '../../shared/observability/performance.js';
24
24
  import { requestContext } from "../../shared/observability/request-context.js";
25
- import { adjustedConfidence, latestPoolDemotionDetail, readPoolAdjustments } from '../discriminator/discriminator.adjustments.js';
25
+ import { adjustedConfidence, latestPoolDemotionDetail, readActivePoolAdjustments } from '../discriminator/discriminator.adjustments.js';
26
26
  import { poolQuestionsRanking } from '../discriminator/discriminator.env.js';
27
27
  const logger = protocolLogger('HomeGraph');
28
28
  const checkCategorizerCacheLog = protocolLogger('HomeGraph:checkCategorizerCache');
@@ -140,7 +140,7 @@ const getPoolRankingProvenance = (state) => {
140
140
  return null;
141
141
  return { recipientUserId: state.userId, intentId: state.scopeId };
142
142
  };
143
- const hasPoolAdjustment = (opp, provenance) => readPoolAdjustments(opp.metadata, provenance).length > 0;
143
+ const hasPoolAdjustment = (opp, provenance) => readActivePoolAdjustments(opp.metadata, provenance).length > 0;
144
144
  const getConfidence = (opp, provenance) => {
145
145
  const raw = getRawConfidence(opp);
146
146
  if (!provenance)
@@ -1 +1 @@
1
- {"version":3,"file":"feed.graph.js","sourceRoot":"/","sources":["opportunity/feed/feed.graph.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Home Graph: Build the opportunity home view with dynamic sections.\n *\n * Independent of ChatGraph. Flow:\n * loadOpportunities → checkPresenterCache → [generateCardText if misses] → cachePresenterResults\n * → checkCategorizerCache → [categorizeDynamically if miss] → cacheCategorizerResults → normalizeAndSort\n *\n * Uses OpportunityPresenter for card text and an LLM to categorize cards into dynamic sections\n * with titles and Lucide icon names. Caches presenter and categorizer results via OpportunityCache.\n */\n\nimport { createHash } from 'crypto';\n\nimport { StateGraph, START, END } from '@langchain/langgraph';\n\nimport type { HomeGraphDatabase, OpportunityStatus } from '../../shared/interfaces/database.interface.js';\nimport type { OpportunityCache } from '../../shared/interfaces/cache.interface.js';\nimport { HomeGraphState, type HomeCardItem, type HomeSection, type HomeSectionProposal, type HomeSectionItem } from './feed.state.js';\nimport { OpportunityPresenter, gatherPresenterContext, type PresenterDatabase } from '../opportunity.presenter.js';\nimport { loadNegotiationContext } from '../negotiation-context.loader.js';\nimport { HomeCategorizerAgent } from './feed.categorizer.js';\nimport { canUserSeeOpportunity, isActionableForViewer, selectByComposition } from '../opportunity.utils.js';\nimport { resolveHomeSectionIcon, DEFAULT_HOME_SECTION_ICON } from '../../shared/ui/lucide.icon-catalog.js';\nimport { getPrimaryActionLabel, SECONDARY_ACTION_LABEL } from '../opportunity.labels.js';\nimport { safeFallbackSummary } from '../opportunity.safe-presentation.js';\nimport { buildHomeCardPresentationCacheKey, buildHomeCategoryPresentationCacheKey } from '../opportunity.presentation-cache.js';\nimport type { DebugMetaAgent } from '../../chat/chat-streaming.types.js';\nimport { protocolLogger } from '../../shared/observability/protocol.logger.js';\nimport { timed } from '../../shared/observability/performance.js';\nimport { requestContext } from \"../../shared/observability/request-context.js\";\nimport { adjustedConfidence, latestPoolDemotionDetail, readPoolAdjustments } from '../discriminator/discriminator.adjustments.js';\nimport type { PoolAdjustmentProvenance } from '../discriminator/discriminator.adjustments.js';\nimport { poolQuestionsRanking } from '../discriminator/discriminator.env.js';\n\nconst logger = protocolLogger('HomeGraph');\nconst checkCategorizerCacheLog = protocolLogger('HomeGraph:checkCategorizerCache');\nconst cacheCategorizerResultsLog = protocolLogger('HomeGraph:cacheCategorizerResults');\nconst checkPresenterCacheLog = protocolLogger('HomeGraph:checkPresenterCache');\nconst cachePresenterResultsLog = protocolLogger('HomeGraph:cachePresenterResults');\nconst categorizeDynamicallyLog = protocolLogger('HomeGraph:categorizeDynamically');\nconst normalizeAndSortLog = protocolLogger('HomeGraph:normalizeAndSort');\nconst generateCardTextLog = protocolLogger('HomeGraph:generateCardText');\n\n/** Database must satisfy both HomeGraphDatabase and presenter context (getProfile, getActiveIntents, getNetwork, getUser). */\ntype HomeGraphDb = HomeGraphDatabase;\n\nexport type HomeGraphInvokeInput = {\n userId: string;\n networkId?: string;\n scopeType?: 'intent';\n scopeId?: string;\n limit?: number;\n noCache?: boolean;\n /**\n * 'skeleton' returns immediately without LLM work: cached cards complete,\n * uncached cards with identity fields only + `presentationPending: true`,\n * single flat section (no categorizer). Meant as the fast first phase of a\n * two-phase fetch — follow up with a full request to fill in the text.\n */\n presentation?: 'full' | 'skeleton';\n /**\n * When set, filter loaded opportunities to these lifecycle statuses. Defaults to `DEFAULT_HOME_STATUSES`.\n * Explicit statuses switch the graph to \"lifecycle view\" mode: terminal/internal\n * statuses pass through (only latent/pending stay gated by viewer actionability),\n * ordering is newest-first, and feed composition capping is skipped.\n */\n statuses?: OpportunityStatus[];\n};\n\nexport type HomeGraphInvokeResult = {\n sections: HomeSection[];\n meta: { totalOpportunities: number; totalSections: number };\n error?: string;\n};\n\n/** Default home-feed statuses: the lifecycle stages a viewer can act on today. */\nexport const DEFAULT_HOME_STATUSES: OpportunityStatus[] = ['latent', 'pending'];\n\n// Exhaustive registry — keys must cover every OpportunityStatus union member.\n// Adding a new status to OpportunityStatus without adding a key here is a TS error,\n// which is the whole point: prevents ALL_OPPORTUNITY_STATUSES from silently drifting.\nconst OPPORTUNITY_STATUS_REGISTRY: Record<OpportunityStatus, true> = {\n latent: true,\n draft: true,\n negotiating: true,\n pending: true,\n stalled: true,\n accepted: true,\n rejected: true,\n expired: true,\n};\n\n/** Full status enumeration. Pass this to `HomeGraphInvokeInput.statuses` to restore pre-Issue-3 (unfiltered) behavior. */\nexport const ALL_OPPORTUNITY_STATUSES: OpportunityStatus[] = Object.keys(\n OPPORTUNITY_STATUS_REGISTRY,\n) as OpportunityStatus[];\n\nconst MAX_ITEMS_PER_SECTION = 20;\nconst PRESENTATION_CONCURRENCY = 50;\nconst MAX_REASONING_SNIPPET_LENGTH = 240;\nconst HOME_CACHE_TTL = 24 * 60 * 60; // 24 hours in seconds\n\n/** Pure cache policy for presenter cards; degraded current-request copy retries later. */\nexport function isHomePresentationCacheable(\n card: Pick<HomeCardItem, 'presentationPending' | '_presentationFallback' | 'name'>,\n status: OpportunityStatus | undefined,\n): boolean {\n return Boolean(\n status &&\n status !== 'negotiating' &&\n !card.presentationPending &&\n !card._presentationFallback &&\n card.name &&\n card.name !== 'Unknown',\n );\n}\n\n/** Redis key for the categorizer cache, derived from the user and the ordered opportunity-id set. */\nfunction buildCategorizerCacheKey(userId: string, cards: HomeCardItem[]): string {\n const oppIds = cards.map((c) => c.opportunityId).join(',');\n const hash = createHash('sha256').update(oppIds).digest('hex').slice(0, 16);\n return buildHomeCategoryPresentationCacheKey(userId, hash);\n}\n\n/**\n * Strip leading narrator name from remark when the UI already prepends \"Name: \" to the chip.\n * Avoids duplication like \"Yankı Ekin Yüksel: Yankı Ekin Yüksel introduced you two...\"\n * Repeats until no leading name (handles \"Name: Name rest\").\n */\nexport function stripLeadingNarratorName(remark: string, narratorName: string): string {\n let t = remark.trim();\n if (!t || !narratorName.trim()) return remark;\n const name = narratorName.trim();\n const nameLower = name.toLowerCase();\n for (;;) {\n const lower = t.toLowerCase();\n if (!lower.startsWith(nameLower)) break;\n const rest = t.slice(name.length).replace(/^\\s*[:,\\-–—]\\s*/i, '').trim();\n if (rest.length === 0 || rest === t) break;\n t = rest;\n }\n return t;\n}\n\n/** Normalize timestamp for sorting; returns numeric ms or 0 for invalid/missing. */\nconst safeParseDate = (value: unknown): number => {\n if (value == null) return 0;\n if (value instanceof Date) {\n const t = value.getTime();\n return Number.isFinite(t) ? t : 0;\n }\n if (typeof value === 'number' && Number.isFinite(value)) return value;\n if (typeof value === 'string') {\n const t = new Date(value).getTime();\n return Number.isFinite(t) ? t : 0;\n }\n return 0;\n};\n\n/** Confidence score for sorting (interpretation.confidence or opportunity.confidence). */\nconst getRawConfidence = (opp: typeof HomeGraphState.State['opportunities'][number]): number => {\n const fromInterp = opp.interpretation?.confidence;\n if (typeof fromInterp === 'number' && !Number.isNaN(fromInterp)) return fromInterp;\n if (typeof fromInterp === 'string') {\n const n = parseFloat(fromInterp);\n if (!Number.isNaN(n)) return n;\n }\n const fromRow = opp.confidence;\n if (typeof fromRow === 'number' && !Number.isNaN(fromRow)) return fromRow;\n if (typeof fromRow === 'string') {\n const n = parseFloat(fromRow);\n if (!Number.isNaN(n)) return n;\n }\n return 0;\n};\n\n/**\n * Sort confidence, optionally pool-adjusted (IND-419): when\n * POOL_QUESTIONS_RANKING=on, answered discriminators multiply confidence by\n * their stored factors (floor 0.3) so the user's answers re-rank the feed.\n * Flag off → identical to raw confidence (adjustments are write-only).\n */\nconst getPoolRankingProvenance = (\n state: typeof HomeGraphState.State,\n): PoolAdjustmentProvenance | null => {\n if (\n poolQuestionsRanking() !== 'on' ||\n !state.userId ||\n state.scopeType !== 'intent' ||\n !state.scopeId\n ) return null;\n return { recipientUserId: state.userId, intentId: state.scopeId };\n};\n\nconst hasPoolAdjustment = (\n opp: typeof HomeGraphState.State['opportunities'][number],\n provenance: PoolAdjustmentProvenance,\n): boolean => readPoolAdjustments(\n (opp as { metadata?: Record<string, unknown> | null }).metadata,\n provenance,\n).length > 0;\n\nconst getConfidence = (\n opp: typeof HomeGraphState.State['opportunities'][number],\n provenance: PoolAdjustmentProvenance | null,\n): number => {\n const raw = getRawConfidence(opp);\n if (!provenance) return raw;\n return adjustedConfidence(\n raw,\n (opp as { metadata?: Record<string, unknown> | null }).metadata,\n provenance,\n );\n};\n\n/** Unique non-introducer, non-viewer userIds for an opportunity (actors can repeat). */\nconst getUniqueCounterpartUserIds = (\n opp: typeof HomeGraphState.State['opportunities'][number],\n viewerId: string\n): Set<string> => {\n const ids = new Set<string>();\n for (const a of opp.actors) {\n if (a.role !== 'introducer' && a.userId !== viewerId && a.userId) {\n ids.add(a.userId);\n }\n }\n return ids;\n};\n\nconst pickDisplayCounterpartActor = (\n opportunity: typeof HomeGraphState.State['opportunities'][number],\n viewerId: string\n): { userId: string; role: string } | null => {\n const candidates = opportunity.actors.filter(\n (actor) => actor.userId !== viewerId && actor.role !== 'introducer'\n );\n if (candidates.length === 0) {\n return null;\n }\n\n // Prefer direct counterpart roles when available, then stable sort by user id.\n const rolePriority = new Map<string, number>([\n ['patient', 0],\n ['party', 1],\n ['agent', 2],\n ['peer', 3],\n ]);\n\n const sorted = [...candidates].sort((a, b) => {\n const aPriority = rolePriority.get(a.role) ?? 99;\n const bPriority = rolePriority.get(b.role) ?? 99;\n if (aPriority !== bPriority) return aPriority - bPriority;\n return a.userId.localeCompare(b.userId);\n });\n return sorted[0] ?? null;\n};\n\nexport class HomeGraphFactory {\n constructor(private database: HomeGraphDb, private cache: OpportunityCache) {}\n\n createGraph() {\n const presenter = new OpportunityPresenter();\n const categorizer = new HomeCategorizerAgent();\n\n const loadOpportunitiesNode = async (state: typeof HomeGraphState.State) => {\n return timed(\"HomeGraph.loadOpportunities\", async () => {\n if (!state.userId) {\n return { error: 'userId is required' };\n }\n try {\n // Minimum of 50 ensures enough candidates across all feed categories\n // (connection, connector-flow, expired) for selectByComposition to fill\n // its soft targets, even after visibility filtering and dedup.\n const fetchLimit = Math.min(150, Math.max(50, state.limit * 3));\n const statuses = state.statuses ?? DEFAULT_HOME_STATUSES;\n const poolRankingProvenance = getPoolRankingProvenance(state);\n const options: { limit?: number; networkId?: string; scopeType?: 'intent'; scopeId?: string; statuses?: OpportunityStatus[] } = {\n limit: fetchLimit,\n statuses,\n };\n if (state.networkId) options.networkId = state.networkId;\n if (state.scopeType === 'intent' && state.scopeId) {\n options.scopeType = 'intent';\n options.scopeId = state.scopeId;\n }\n // Do not pass conversationId: home view excludes draft opportunities (chat-only drafts).\n const raw = await this.database.getOpportunitiesForUser(state.userId, options);\n const visible = raw.filter((opp) =>\n canUserSeeOpportunity(opp.actors, opp.status, state.userId)\n );\n // Actionability only gates the live statuses a viewer could act on:\n // latent/pending cards the viewer cannot act on are noise, but\n // terminal/internal statuses (accepted, rejected, expired, negotiating,\n // stalled, draft) are deliberate history — when a caller explicitly\n // requests them via `statuses`, they must pass through (they are never\n // actionable by rule 5, so filtering them here would return nothing).\n // The requested-status membership check is defense-in-depth: rows\n // outside the requested set are dropped even if the adapter drifts.\n const requestedStatuses = new Set<OpportunityStatus>(statuses);\n const visibleForFeed = visible.filter((opp) => {\n if (!requestedStatuses.has(opp.status)) return false;\n if (opp.status === 'latent' || opp.status === 'pending') {\n return isActionableForViewer(opp.actors, opp.status, state.userId);\n }\n return true;\n });\n const explicitStatuses = (state.statuses?.length ?? 0) > 0;\n if (explicitStatuses) {\n // Lifecycle view (e.g. intent radar): newest-first so counterpart\n // dedup keeps each person's most recent state (an accepted\n // opportunity supersedes an older pending one), no composition\n // capping — the caller wants the full pipeline up to `limit`.\n const newestFirst = [...visibleForFeed].sort(\n (a, b) => safeParseDate(b.updatedAt) - safeParseDate(a.updatedAt)\n );\n const seenIds = new Set<string>();\n const dedupedByCounterpart = newestFirst.filter((opp) => {\n const counterpartIds = getUniqueCounterpartUserIds(opp, state.userId);\n const hasOverlap = [...counterpartIds].some((id) => seenIds.has(id));\n if (hasOverlap) return false;\n for (const id of counterpartIds) seenIds.add(id);\n return true;\n });\n // Preserve byte-identical newest-first behavior while the flag is\n // off. When on, re-order the already-deduped lifecycle set by\n // adjusted confidence so each client-side radar bucket reflects\n // pool answers immediately.\n if (\n !poolRankingProvenance ||\n !dedupedByCounterpart.some((opportunity) => hasPoolAdjustment(opportunity, poolRankingProvenance))\n ) {\n return { opportunities: dedupedByCounterpart.slice(0, state.limit) };\n }\n const adjustedOrder = [...dedupedByCounterpart].sort((a, b) => {\n const confidenceDelta = getConfidence(b, poolRankingProvenance) - getConfidence(a, poolRankingProvenance);\n if (confidenceDelta !== 0) return confidenceDelta;\n return safeParseDate(b.updatedAt) - safeParseDate(a.updatedAt);\n });\n return { opportunities: adjustedOrder.slice(0, state.limit) };\n }\n const sorted = [...visibleForFeed].sort((a, b) => {\n // Connections before connector-flow so dedup claims counterpart IDs\n // for direct connections first — prevents introducer cards from\n // shadowing a user's own connection opportunities.\n const aIsIntroducer = a.actors.some((ac) => ac.userId === state.userId && ac.role === 'introducer');\n const bIsIntroducer = b.actors.some((ac) => ac.userId === state.userId && ac.role === 'introducer');\n if (aIsIntroducer !== bIsIntroducer) return aIsIntroducer ? 1 : -1;\n const confA = getConfidence(a, poolRankingProvenance);\n const confB = getConfidence(b, poolRankingProvenance);\n if (confB !== confA) return confB - confA;\n const aTime = safeParseDate(a.updatedAt);\n const bTime = safeParseDate(b.updatedAt);\n return bTime - aTime;\n });\n const seenUserIds = new Set<string>();\n const deduped = sorted.filter((opp) => {\n const counterpartIds = getUniqueCounterpartUserIds(opp, state.userId);\n const hasOverlap = [...counterpartIds].some((id) => seenUserIds.has(id));\n if (hasOverlap) return false;\n for (const id of counterpartIds) seenUserIds.add(id);\n return true;\n });\n const opportunities = selectByComposition(deduped, state.userId);\n return { opportunities };\n } catch (e) {\n logger.error('HomeGraph loadOpportunities failed', { error: e });\n return { error: 'Failed to load opportunities', opportunities: [] };\n }\n });\n };\n\n const checkPresenterCacheNode = async (state: typeof HomeGraphState.State) => {\n return timed(\"HomeGraph.checkPresenterCache\", async () => {\n const { opportunities, userId } = state;\n const poolRankingProvenance = getPoolRankingProvenance(state);\n if (opportunities.length === 0) {\n return { cachedCards: new Map(), uncachedOpportunities: [] };\n }\n\n if (state.noCache) {\n checkPresenterCacheLog.verbose('noCache=true, skipping cache');\n return { cachedCards: new Map(), uncachedOpportunities: opportunities };\n }\n\n try {\n // Negotiating cards are templated (no LLM call) and their text\n // depends on the live turn count, which changes between requests\n // without changing the opportunity status. Skip cache entirely\n // for them so each render reflects the current turn.\n //\n // For all other statuses, include status in the key so status\n // transitions (e.g. negotiating → pending) don't serve stale cards.\n const cacheable = opportunities.filter((opp) => opp.status !== 'negotiating');\n const liveNegotiating = opportunities.filter((opp) => opp.status === 'negotiating');\n\n const keys = cacheable.map((opp) =>\n buildHomeCardPresentationCacheKey(opp.id, opp.status, userId)\n );\n const results = keys.length > 0 ? await this.cache.mget<HomeCardItem>(keys) : [];\n\n const cachedCards = new Map<string, HomeCardItem>();\n const uncachedOpportunities: typeof opportunities = [...liveNegotiating];\n\n for (let i = 0; i < cacheable.length; i++) {\n const cached = results[i];\n if (cached) {\n const originalIndex = opportunities.indexOf(cacheable[i]);\n // Stamp the live status: pre-status cache entries lack the field,\n // and the key already guarantees it matches the current status.\n const deprioritizedReason = poolRankingProvenance\n ? latestPoolDemotionDetail(\n (cacheable[i] as { metadata?: Record<string, unknown> | null }).metadata,\n poolRankingProvenance,\n )\n : undefined;\n cachedCards.set(cacheable[i].id, {\n ...cached,\n status: cacheable[i].status,\n deprioritizedReason,\n _cardIndex: originalIndex,\n });\n } else {\n uncachedOpportunities.push(cacheable[i]);\n }\n }\n\n checkPresenterCacheLog.verbose('', {\n total: opportunities.length,\n cacheHits: cachedCards.size,\n cacheMisses: uncachedOpportunities.length,\n });\n\n return { cachedCards, uncachedOpportunities };\n } catch (e) {\n checkPresenterCacheLog.warn('cache unavailable, skipping', { error: e });\n return { cachedCards: new Map(), uncachedOpportunities: opportunities };\n }\n });\n };\n\n const shouldGenerateCards = (state: typeof HomeGraphState.State): string => {\n if (state.uncachedOpportunities.length > 0) {\n return 'generate';\n }\n logger.verbose('All presenter results cached, skipping generation');\n return 'skip';\n };\n\n const generateCardTextNode = async (state: typeof HomeGraphState.State) => {\n return timed(\"HomeGraph.generateCardText\", async () => {\n const opportunities = state.uncachedOpportunities.length > 0\n ? state.uncachedOpportunities\n : state.opportunities;\n generateCardTextLog.verbose('entry', { opportunitiesLength: opportunities.length, userId: state.userId });\n if (opportunities.length === 0) {\n generateCardTextLog.verbose('exit', { totalOpportunities: 0, totalSections: 0 });\n return { cards: [], agentTimings: [], meta: { totalOpportunities: 0, totalSections: 0 } };\n }\n const db = this.database as PresenterDatabase & HomeGraphDb;\n const cards: HomeCardItem[] = [];\n const relevantActorIds = new Set<string>();\n for (const opp of opportunities) {\n for (const a of opp.actors) {\n if (a.userId) relevantActorIds.add(a.userId);\n }\n }\n\n const userEntries = await Promise.all(\n Array.from(relevantActorIds).map(async (userId) => {\n try {\n const user = await this.database.getUser(userId);\n return [userId, user ?? null] as const;\n } catch {\n return [userId, null] as const;\n }\n })\n );\n const userMap = new Map(userEntries);\n\n const oppIndexMap = new Map(\n state.opportunities.map((opp, idx) => [opp.id, idx])\n );\n\n const agentTimingsAccum: DebugMetaAgent[] = [];\n\n for (let i = 0; i < opportunities.length; i += PRESENTATION_CONCURRENCY) {\n const chunk = opportunities.slice(i, i + PRESENTATION_CONCURRENCY);\n const chunkCards = await Promise.all(\n chunk.map(async (opportunity, offset) => {\n const cardIndex = oppIndexMap.get(opportunity.id) ?? (i + offset);\n const viewerActor = opportunity.actors.find((a) => a.userId === state.userId);\n const viewerRole = viewerActor?.role ?? 'party';\n const isIntroducer = viewerRole === 'introducer';\n const preferredActor = pickDisplayCounterpartActor(opportunity, state.userId)\n ?? opportunity.actors.find((a) => a.userId !== state.userId && a.role !== 'introducer');\n const actorWithProfile = opportunity.actors.find(\n (a) => a.userId !== state.userId && a.role !== 'introducer' && !!userMap.get(a.userId)\n );\n const introducer = opportunity.actors.find((a) => a.role === 'introducer');\n let otherActor = (preferredActor && userMap.get(preferredActor.userId))\n ? preferredActor\n : (actorWithProfile ?? preferredActor);\n // When the only other participant is the introducer (no separate party), use introducer as display counterpart so the card shows a name instead of \"Unknown\"\n if (!otherActor && introducer && introducer.userId !== state.userId && introducer.userId) {\n otherActor = { userId: introducer.userId, role: introducer.role };\n }\n const otherUser = otherActor ? userMap.get(otherActor.userId) ?? null : null;\n const introducerCounterparts = opportunity.actors.filter(\n (a) => a.userId !== state.userId && a.role !== 'introducer'\n );\n // Deduplicate by userId — actors array can contain multiple rows per user\n // (e.g. from different intents), which would produce repeated names.\n const uniqueCounterpartIds = [...new Set(introducerCounterparts.map((a) => a.userId))];\n const participantNames = uniqueCounterpartIds\n .map((uid) => userMap.get(uid)?.name ?? 'Unknown')\n .sort();\n // When secondPartyData will be present (2+ counterparts), use single counterpart name\n // because the frontend arrow layout renders \"card.name → secondParty.name\".\n // Using the joined \"A ↔ B\" format here would produce redundant \"A ↔ B → B\".\n // Only use the joined format when there is a single counterpart (no arrow layout).\n const willHaveSecondParty = isIntroducer && uniqueCounterpartIds.length > 1;\n let userName = isIntroducer && participantNames.length > 0 && !willHaveSecondParty\n ? participantNames.join(' ↔ ')\n : (otherUser?.name ?? 'Unknown');\n // Fallback to profile identity name when users.name is missing (e.g. profile has display name, users row does not)\n if ((userName === 'Unknown' || !userName?.trim()) && otherActor?.userId && db.getProfile) {\n const profile = await db.getProfile(otherActor.userId).catch((err) => {\n logger.debug('getProfile fallback failed', { otherActorUserId: otherActor.userId, error: err });\n return null;\n });\n const profileName = profile?.identity?.name?.trim();\n if (profileName) userName = profileName;\n }\n // Unresolvable display counterpart (deleted user: no users row, no\n // profile fallback). Drop the card entirely instead of rendering an\n // \"Unknown\" placeholder: such cards are unusable, excluded from the\n // presenter cache (see cachePresenterResults), and would otherwise\n // trigger a fresh presenter LLM call on every request — a permanent\n // cache miss that keeps the whole feed slow (~9s per load).\n if (userName === 'Unknown' || !userName?.trim()) {\n logger.verbose('[HomeGraph:generateCardText] dropping card with unresolvable counterpart', {\n opportunityId: opportunity.id,\n otherActorUserId: otherActor?.userId,\n });\n return null;\n }\n const userAvatar = otherUser?.avatar ?? null;\n // Shared sanitization standard (UUID strip, viewer-centric rewrite,\n // boundary truncation) — raw reasoning must never render verbatim.\n const reasoningSnippet = safeFallbackSummary(\n typeof opportunity.interpretation?.reasoning === 'string'\n ? opportunity.interpretation.reasoning\n : '',\n {\n counterpartName: userName !== 'Unknown' ? userName : undefined,\n maxChars: MAX_REASONING_SNIPPET_LENGTH,\n emptyText: 'A promising connection.',\n },\n );\n\n // Build secondParty for introducer arrow layout (the party that isn't the display counterpart)\n let secondPartyData: { name: string; avatar?: string | null; userId?: string } | undefined;\n if (isIntroducer && introducerCounterparts.length > 1 && otherActor) {\n const secondActor = introducerCounterparts.find((a) => a.userId !== otherActor.userId);\n if (secondActor) {\n const secondUser = userMap.get(secondActor.userId) ?? null;\n secondPartyData = {\n name: secondUser?.name ?? 'Unknown',\n avatar: secondUser?.avatar ?? null,\n userId: secondActor.userId,\n };\n }\n }\n\n const isCounterpartGhost = otherUser?.isGhost ?? false;\n // Skeleton presentation: return an identity-only card without the\n // presenter LLM or negotiation-context load. Name resolution and\n // the unresolvable-counterpart drop above still apply, so the card\n // set matches what the follow-up full request will return.\n if (state.presentation === 'skeleton') {\n return {\n opportunityId: opportunity.id,\n status: opportunity.status,\n userId: otherActor?.userId ?? '',\n name: userName,\n avatar: userAvatar,\n mainText: '',\n cta: '',\n primaryActionLabel: getPrimaryActionLabel(viewerRole),\n secondaryActionLabel: SECONDARY_ACTION_LABEL,\n mutualIntentsLabel: isIntroducer ? 'Connector match' : 'Shared interests',\n viewerRole,\n isGhost: isCounterpartGhost,\n ...(secondPartyData ? { secondParty: secondPartyData } : {}),\n presentationPending: true,\n _cardIndex: cardIndex,\n } satisfies HomeCardItem;\n }\n const isPendingIntroducerFallback = isIntroducer && opportunity.status !== 'latent';\n const fallbackCard = (): HomeCardItem => ({\n opportunityId: opportunity.id,\n status: opportunity.status,\n userId: otherActor?.userId ?? '',\n name: userName,\n avatar: userAvatar,\n mainText: reasoningSnippet,\n cta: isIntroducer\n ? (isPendingIntroducerFallback ? 'Share this introduction to get things started.' : 'Take a look and decide if this is a good match.')\n : 'Take a look and decide whether to reach out.',\n primaryActionLabel: getPrimaryActionLabel(viewerRole),\n secondaryActionLabel: SECONDARY_ACTION_LABEL,\n mutualIntentsLabel: isIntroducer ? 'Connector match' : 'Shared interests',\n narratorChip: isIntroducer\n ? { name: 'You', text: 'Worth a look.', userId: state.userId }\n : { name: 'Index', text: 'Worth a look.' },\n viewerRole,\n isGhost: isCounterpartGhost,\n ...(secondPartyData ? { secondParty: secondPartyData } : {}),\n _presentationFallback: true,\n _cardIndex: cardIndex,\n });\n\n try {\n const [ctx, negotiationContext] = await Promise.all([\n gatherPresenterContext(\n db,\n opportunity,\n state.userId,\n otherActor?.userId,\n ),\n loadNegotiationContext(db, opportunity.id, opportunity.status),\n ]);\n const homeInput = {\n ...ctx,\n mutualIntentCount: undefined,\n opportunityStatus: opportunity.status,\n ...(negotiationContext ? { negotiationContext } : {}),\n };\n const _traceEmitterPresenter = requestContext.getStore()?.traceEmitter;\n const presenterStart = Date.now();\n _traceEmitterPresenter?.({ type: \"agent_start\", name: \"opportunity-presenter\" });\n const presentation = await presenter.presentHomeCard(homeInput);\n const _presenterDuration = Date.now() - presenterStart;\n agentTimingsAccum.push({ name: 'opportunity.presenter', durationMs: _presenterDuration });\n _traceEmitterPresenter?.({ type: \"agent_end\", name: \"opportunity-presenter\", durationMs: _presenterDuration, summary: `Presented: ${userName}` });\n if (presentation.isFallback) {\n return fallbackCard();\n }\n let narratorChip: { name: string; text: string; avatar?: string | null; userId?: string } | undefined;\n // Only show a person as narrator when they are the introducer and not the display counterpart\n // (bad data can have same user as introducer and party, e.g. \"Amina introduced you to Amina\")\n const introducerIsCounterpart = introducer && otherActor && introducer.userId === otherActor.userId;\n if (introducer && introducer.userId !== state.userId && !introducerIsCounterpart) {\n const introUser = userMap.get(introducer.userId) ?? null;\n const narratorName = introUser?.name ?? 'Someone';\n narratorChip = {\n name: narratorName,\n text: stripLeadingNarratorName(presentation.narratorRemark, narratorName),\n avatar: introUser?.avatar ?? null,\n userId: introducer.userId,\n };\n } else if (introducer?.userId === state.userId) {\n narratorChip = { name: 'You', text: presentation.narratorRemark, userId: state.userId };\n } else {\n narratorChip = { name: 'Index', text: presentation.narratorRemark };\n }\n return {\n opportunityId: opportunity.id,\n status: opportunity.status,\n userId: otherActor?.userId ?? '',\n name: userName,\n avatar: userAvatar,\n mainText: presentation.personalizedSummary,\n cta: presentation.suggestedAction,\n headline: presentation.headline,\n primaryActionLabel: getPrimaryActionLabel(viewerRole),\n secondaryActionLabel: SECONDARY_ACTION_LABEL,\n mutualIntentsLabel: presentation.mutualIntentsLabel,\n narratorChip,\n viewerRole,\n isGhost: isCounterpartGhost,\n ...(secondPartyData ? { secondParty: secondPartyData } : {}),\n _cardIndex: cardIndex,\n } satisfies HomeCardItem;\n } catch (e) {\n logger.warn('HomeGraph presenter failed for opportunity', { opportunityId: opportunity.id, error: e });\n return fallbackCard();\n }\n })\n );\n cards.push(...chunkCards.filter((c): c is HomeCardItem => c !== null));\n }\n generateCardTextLog.verbose('exit', { totalOpportunities: state.opportunities.length, totalSections: 0 });\n return {\n cards,\n agentTimings: agentTimingsAccum,\n meta: { totalOpportunities: state.opportunities.length, totalSections: 0 },\n };\n });\n };\n\n const cachePresenterResultsNode = async (state: typeof HomeGraphState.State) => {\n return timed(\"HomeGraph.cachePresenterResults\", async () => {\n const { cards, cachedCards, userId, opportunities } = state;\n const poolRankingProvenance = getPoolRankingProvenance(state);\n const liveById = new Map(opportunities.map((opportunity) => [opportunity.id, opportunity]));\n const cardsWithAdjustments = cards.map((card) => {\n const opportunity = liveById.get(card.opportunityId);\n const deprioritizedReason = poolRankingProvenance\n ? latestPoolDemotionDetail(\n (opportunity as { metadata?: Record<string, unknown> | null } | undefined)?.metadata,\n poolRankingProvenance,\n )\n : undefined;\n return { ...card, deprioritizedReason };\n });\n\n // Only cache cards that weren't already from cache\n const newCards = cardsWithAdjustments.filter((card) => !cachedCards.has(card.opportunityId));\n const statusById = new Map(opportunities.map((opp) => [opp.id, opp.status]));\n\n try {\n await Promise.all(\n newCards.map((card) => {\n const status = statusById.get(card.opportunityId);\n // Negotiating, skeleton, fallback, and unresolved-name cards are\n // safe for the current response but must not become 24h entries.\n if (!status || !isHomePresentationCacheable(card, status)) return Promise.resolve();\n return this.cache.set(\n buildHomeCardPresentationCacheKey(card.opportunityId, status, userId),\n card,\n { ttl: HOME_CACHE_TTL }\n );\n })\n );\n } catch (e) {\n cachePresenterResultsLog.warn('cache write failed, continuing', { error: e });\n }\n\n // Merge cached cards into full card list\n const allCards: HomeCardItem[] = [...cardsWithAdjustments];\n for (const [oppId, cachedCard] of cachedCards) {\n if (!cardsWithAdjustments.some((card) => card.opportunityId === oppId)) {\n allCards.push(cachedCard);\n }\n }\n\n // Re-sort by _cardIndex to maintain original ordering\n allCards.sort((a, b) => a._cardIndex - b._cardIndex);\n\n cachePresenterResultsLog.verbose('', {\n newlyCached: newCards.length,\n totalCards: allCards.length,\n });\n\n return {\n cards: allCards,\n meta: { totalOpportunities: state.opportunities.length, totalSections: 0 },\n };\n });\n };\n\n const checkCategorizerCacheNode = async (state: typeof HomeGraphState.State) => {\n return timed(\"HomeGraph.checkCategorizerCache\", async () => {\n if (state.cards.length === 0) {\n return { categoryCacheHit: false };\n }\n\n // Skeleton runs never categorize (some cards have no text to categorize\n // and the response must stay LLM-free). Ranking-enabled lifecycle views\n // also stay flat: the intent Radar flattens sections and buckets by\n // status, so dynamic categorization would erase the adjusted order on\n // the full second-phase response. Flag off retains the legacy path.\n // Chunk by MAX_ITEMS_PER_SECTION because normalizeAndSort caps sections.\n const poolRankingProvenance = getPoolRankingProvenance(state);\n const preserveAdjustedLifecycleOrder =\n (state.statuses?.length ?? 0) > 0 &&\n poolRankingProvenance !== null &&\n state.opportunities.some((opportunity) => hasPoolAdjustment(opportunity, poolRankingProvenance));\n if (state.presentation === 'skeleton' || preserveAdjustedLifecycleOrder) {\n const sectionProposals: HomeSectionProposal[] = [];\n for (let start = 0; start < state.cards.length; start += MAX_ITEMS_PER_SECTION) {\n sectionProposals.push({\n id: `all-${sectionProposals.length + 1}`,\n title: 'All matches',\n iconName: DEFAULT_HOME_SECTION_ICON,\n itemIndices: state.cards.slice(start, start + MAX_ITEMS_PER_SECTION).map((_, i) => start + i),\n });\n }\n return { sectionProposals, categoryCacheHit: true };\n }\n\n if (state.noCache) {\n checkCategorizerCacheLog.verbose('noCache=true, skipping cache');\n return { categoryCacheHit: false };\n }\n\n try {\n const key = buildCategorizerCacheKey(state.userId, state.cards);\n\n const cached = await this.cache.get<HomeSectionProposal[]>(key);\n if (cached) {\n checkCategorizerCacheLog.verbose('cache hit');\n return { sectionProposals: cached, categoryCacheHit: true };\n }\n\n checkCategorizerCacheLog.verbose('cache miss');\n } catch (e) {\n checkCategorizerCacheLog.warn('cache unavailable, skipping', { error: e });\n }\n return { categoryCacheHit: false };\n });\n };\n\n const shouldCategorize = (state: typeof HomeGraphState.State): string => {\n if (state.categoryCacheHit) {\n logger.verbose('Categorizer results cached, skipping');\n return 'skip';\n }\n return 'categorize';\n };\n\n const categorizeDynamicallyNode = async (state: typeof HomeGraphState.State) => {\n return timed(\"HomeGraph.categorizeDynamically\", async () => {\n categorizeDynamicallyLog.verbose('entry', { cardsLength: state.cards.length });\n if (state.cards.length === 0) {\n categorizeDynamicallyLog.verbose('exit', { sectionProposalsCount: 0 });\n return { sectionProposals: [], agentTimings: [] };\n }\n const agentTimingsAccum: DebugMetaAgent[] = [];\n const categorizerInput = state.cards.map((c) => ({\n index: c._cardIndex,\n headline: c.headline,\n mainText: c.mainText,\n name: c.name,\n viewerRole: c.viewerRole === 'introducer' ? 'introducer' : undefined,\n opportunityStatus: c.viewerRole === 'introducer' ? 'pending' : undefined,\n }));\n const _traceEmitterCategorizer = requestContext.getStore()?.traceEmitter;\n const categorizerStart = Date.now();\n _traceEmitterCategorizer?.({ type: \"agent_start\", name: \"home-categorizer\" });\n const { sections } = await categorizer.categorize(categorizerInput);\n const _categorizerDuration = Date.now() - categorizerStart;\n agentTimingsAccum.push({ name: 'home.categorizer', durationMs: _categorizerDuration });\n _traceEmitterCategorizer?.({ type: \"agent_end\", name: \"home-categorizer\", durationMs: _categorizerDuration, summary: `Categorized into ${sections.length} section(s)` });\n const proposals: HomeSectionProposal[] = sections.map((s) => ({\n ...s,\n itemIndices: s.itemIndices.filter((i) => i >= 0 && i < state.cards.length),\n }));\n categorizeDynamicallyLog.verbose('exit', { sectionProposalsCount: proposals.length });\n return { sectionProposals: proposals, agentTimings: agentTimingsAccum };\n });\n };\n\n const cacheCategorizerResultsNode = async (state: typeof HomeGraphState.State) => {\n return timed(\"HomeGraph.cacheCategorizerResults\", async () => {\n if (\n state.categoryCacheHit ||\n state.sectionProposals.length === 0 ||\n state.cards.some((card) => card._presentationFallback)\n ) {\n return {};\n }\n\n try {\n const key = buildCategorizerCacheKey(state.userId, state.cards);\n\n await this.cache.set(key, state.sectionProposals, { ttl: HOME_CACHE_TTL });\n\n cacheCategorizerResultsLog.verbose('cached', {\n sectionCount: state.sectionProposals.length,\n });\n } catch (e) {\n cacheCategorizerResultsLog.warn('cache write failed, continuing', { error: e });\n }\n\n return {};\n });\n };\n\n const normalizeAndSortNode = async (state: typeof HomeGraphState.State) => {\n return timed(\"HomeGraph.normalizeAndSort\", async () => {\n const cards = state.cards;\n const proposals = state.sectionProposals;\n normalizeAndSortLog.verbose('entry', { cardsLength: cards.length, proposalsLength: proposals.length });\n if (cards.length === 0) {\n normalizeAndSortLog.verbose('exit', { totalOpportunities: 0, totalSections: 0 });\n return { sections: [], meta: { totalOpportunities: 0, totalSections: 0 } };\n }\n const usedIndices = new Set<number>();\n const sections: HomeSection[] = proposals.map((p) => {\n const iconName = resolveHomeSectionIcon(p.iconName);\n const items: HomeSectionItem[] = p.itemIndices\n .filter((i) => i >= 0 && i < cards.length && !usedIndices.has(i))\n .slice(0, MAX_ITEMS_PER_SECTION)\n .map((i) => {\n usedIndices.add(i);\n const card = cards[i];\n const { _cardIndex, _presentationFallback, ...rest } = card;\n return rest;\n });\n return {\n id: p.id,\n title: p.title,\n subtitle: p.subtitle,\n iconName,\n items,\n };\n });\n\n // Enforce category ordering: sections with connections first, then\n // connector-flow only, then expired only. This prevents the LLM\n // categorizer from placing introducer sections before connection sections.\n const sectionCategoryPriority = (section: HomeSection): number => {\n const hasConnection = section.items.some((item) => item.viewerRole !== 'introducer');\n if (hasConnection) return 0; // mixed or connection-only sections first\n const hasConnectorFlow = section.items.some((item) => item.viewerRole === 'introducer');\n if (hasConnectorFlow) return 1; // connector-flow only sections next\n return 2; // empty or expired sections last\n };\n sections.sort((a, b) => sectionCategoryPriority(a) - sectionCategoryPriority(b));\n const meta = {\n totalOpportunities: state.opportunities.length,\n totalSections: sections.length,\n };\n normalizeAndSortLog.verbose('exit', { totalOpportunities: meta.totalOpportunities, totalSections: meta.totalSections });\n return { sections, meta };\n });\n };\n\n const graph = new StateGraph(HomeGraphState)\n .addNode('loadOpportunities', loadOpportunitiesNode)\n .addNode('checkPresenterCache', checkPresenterCacheNode)\n .addNode('generateCardText', generateCardTextNode)\n .addNode('cachePresenterResults', cachePresenterResultsNode)\n .addNode('checkCategorizerCache', checkCategorizerCacheNode)\n .addNode('categorizeDynamically', categorizeDynamicallyNode)\n .addNode('cacheCategorizerResults', cacheCategorizerResultsNode)\n .addNode('normalizeAndSort', normalizeAndSortNode)\n .addEdge(START, 'loadOpportunities')\n .addEdge('loadOpportunities', 'checkPresenterCache')\n .addConditionalEdges('checkPresenterCache', shouldGenerateCards, {\n generate: 'generateCardText',\n skip: 'cachePresenterResults',\n })\n .addEdge('generateCardText', 'cachePresenterResults')\n .addEdge('cachePresenterResults', 'checkCategorizerCache')\n .addConditionalEdges('checkCategorizerCache', shouldCategorize, {\n categorize: 'categorizeDynamically',\n skip: 'normalizeAndSort',\n })\n .addEdge('categorizeDynamically', 'cacheCategorizerResults')\n .addEdge('cacheCategorizerResults', 'normalizeAndSort')\n .addEdge('normalizeAndSort', END);\n\n return graph.compile();\n }\n}\n"]}
1
+ {"version":3,"file":"feed.graph.js","sourceRoot":"/","sources":["opportunity/feed/feed.graph.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Home Graph: Build the opportunity home view with dynamic sections.\n *\n * Independent of ChatGraph. Flow:\n * loadOpportunities → checkPresenterCache → [generateCardText if misses] → cachePresenterResults\n * → checkCategorizerCache → [categorizeDynamically if miss] → cacheCategorizerResults → normalizeAndSort\n *\n * Uses OpportunityPresenter for card text and an LLM to categorize cards into dynamic sections\n * with titles and Lucide icon names. Caches presenter and categorizer results via OpportunityCache.\n */\n\nimport { createHash } from 'crypto';\n\nimport { StateGraph, START, END } from '@langchain/langgraph';\n\nimport type { HomeGraphDatabase, OpportunityStatus } from '../../shared/interfaces/database.interface.js';\nimport type { OpportunityCache } from '../../shared/interfaces/cache.interface.js';\nimport { HomeGraphState, type HomeCardItem, type HomeSection, type HomeSectionProposal, type HomeSectionItem } from './feed.state.js';\nimport { OpportunityPresenter, gatherPresenterContext, type PresenterDatabase } from '../opportunity.presenter.js';\nimport { loadNegotiationContext } from '../negotiation-context.loader.js';\nimport { HomeCategorizerAgent } from './feed.categorizer.js';\nimport { canUserSeeOpportunity, isActionableForViewer, selectByComposition } from '../opportunity.utils.js';\nimport { resolveHomeSectionIcon, DEFAULT_HOME_SECTION_ICON } from '../../shared/ui/lucide.icon-catalog.js';\nimport { getPrimaryActionLabel, SECONDARY_ACTION_LABEL } from '../opportunity.labels.js';\nimport { safeFallbackSummary } from '../opportunity.safe-presentation.js';\nimport { buildHomeCardPresentationCacheKey, buildHomeCategoryPresentationCacheKey } from '../opportunity.presentation-cache.js';\nimport type { DebugMetaAgent } from '../../chat/chat-streaming.types.js';\nimport { protocolLogger } from '../../shared/observability/protocol.logger.js';\nimport { timed } from '../../shared/observability/performance.js';\nimport { requestContext } from \"../../shared/observability/request-context.js\";\nimport { adjustedConfidence, latestPoolDemotionDetail, readActivePoolAdjustments } from '../discriminator/discriminator.adjustments.js';\nimport type { PoolAdjustmentProvenance } from '../discriminator/discriminator.adjustments.js';\nimport { poolQuestionsRanking } from '../discriminator/discriminator.env.js';\n\nconst logger = protocolLogger('HomeGraph');\nconst checkCategorizerCacheLog = protocolLogger('HomeGraph:checkCategorizerCache');\nconst cacheCategorizerResultsLog = protocolLogger('HomeGraph:cacheCategorizerResults');\nconst checkPresenterCacheLog = protocolLogger('HomeGraph:checkPresenterCache');\nconst cachePresenterResultsLog = protocolLogger('HomeGraph:cachePresenterResults');\nconst categorizeDynamicallyLog = protocolLogger('HomeGraph:categorizeDynamically');\nconst normalizeAndSortLog = protocolLogger('HomeGraph:normalizeAndSort');\nconst generateCardTextLog = protocolLogger('HomeGraph:generateCardText');\n\n/** Database must satisfy both HomeGraphDatabase and presenter context (getProfile, getActiveIntents, getNetwork, getUser). */\ntype HomeGraphDb = HomeGraphDatabase;\n\nexport type HomeGraphInvokeInput = {\n userId: string;\n networkId?: string;\n scopeType?: 'intent';\n scopeId?: string;\n limit?: number;\n noCache?: boolean;\n /**\n * 'skeleton' returns immediately without LLM work: cached cards complete,\n * uncached cards with identity fields only + `presentationPending: true`,\n * single flat section (no categorizer). Meant as the fast first phase of a\n * two-phase fetch — follow up with a full request to fill in the text.\n */\n presentation?: 'full' | 'skeleton';\n /**\n * When set, filter loaded opportunities to these lifecycle statuses. Defaults to `DEFAULT_HOME_STATUSES`.\n * Explicit statuses switch the graph to \"lifecycle view\" mode: terminal/internal\n * statuses pass through (only latent/pending stay gated by viewer actionability),\n * ordering is newest-first, and feed composition capping is skipped.\n */\n statuses?: OpportunityStatus[];\n};\n\nexport type HomeGraphInvokeResult = {\n sections: HomeSection[];\n meta: { totalOpportunities: number; totalSections: number };\n error?: string;\n};\n\n/** Default home-feed statuses: the lifecycle stages a viewer can act on today. */\nexport const DEFAULT_HOME_STATUSES: OpportunityStatus[] = ['latent', 'pending'];\n\n// Exhaustive registry — keys must cover every OpportunityStatus union member.\n// Adding a new status to OpportunityStatus without adding a key here is a TS error,\n// which is the whole point: prevents ALL_OPPORTUNITY_STATUSES from silently drifting.\nconst OPPORTUNITY_STATUS_REGISTRY: Record<OpportunityStatus, true> = {\n latent: true,\n draft: true,\n negotiating: true,\n pending: true,\n stalled: true,\n accepted: true,\n rejected: true,\n expired: true,\n};\n\n/** Full status enumeration. Pass this to `HomeGraphInvokeInput.statuses` to restore pre-Issue-3 (unfiltered) behavior. */\nexport const ALL_OPPORTUNITY_STATUSES: OpportunityStatus[] = Object.keys(\n OPPORTUNITY_STATUS_REGISTRY,\n) as OpportunityStatus[];\n\nconst MAX_ITEMS_PER_SECTION = 20;\nconst PRESENTATION_CONCURRENCY = 50;\nconst MAX_REASONING_SNIPPET_LENGTH = 240;\nconst HOME_CACHE_TTL = 24 * 60 * 60; // 24 hours in seconds\n\n/** Pure cache policy for presenter cards; degraded current-request copy retries later. */\nexport function isHomePresentationCacheable(\n card: Pick<HomeCardItem, 'presentationPending' | '_presentationFallback' | 'name'>,\n status: OpportunityStatus | undefined,\n): boolean {\n return Boolean(\n status &&\n status !== 'negotiating' &&\n !card.presentationPending &&\n !card._presentationFallback &&\n card.name &&\n card.name !== 'Unknown',\n );\n}\n\n/** Redis key for the categorizer cache, derived from the user and the ordered opportunity-id set. */\nfunction buildCategorizerCacheKey(userId: string, cards: HomeCardItem[]): string {\n const oppIds = cards.map((c) => c.opportunityId).join(',');\n const hash = createHash('sha256').update(oppIds).digest('hex').slice(0, 16);\n return buildHomeCategoryPresentationCacheKey(userId, hash);\n}\n\n/**\n * Strip leading narrator name from remark when the UI already prepends \"Name: \" to the chip.\n * Avoids duplication like \"Yankı Ekin Yüksel: Yankı Ekin Yüksel introduced you two...\"\n * Repeats until no leading name (handles \"Name: Name rest\").\n */\nexport function stripLeadingNarratorName(remark: string, narratorName: string): string {\n let t = remark.trim();\n if (!t || !narratorName.trim()) return remark;\n const name = narratorName.trim();\n const nameLower = name.toLowerCase();\n for (;;) {\n const lower = t.toLowerCase();\n if (!lower.startsWith(nameLower)) break;\n const rest = t.slice(name.length).replace(/^\\s*[:,\\-–—]\\s*/i, '').trim();\n if (rest.length === 0 || rest === t) break;\n t = rest;\n }\n return t;\n}\n\n/** Normalize timestamp for sorting; returns numeric ms or 0 for invalid/missing. */\nconst safeParseDate = (value: unknown): number => {\n if (value == null) return 0;\n if (value instanceof Date) {\n const t = value.getTime();\n return Number.isFinite(t) ? t : 0;\n }\n if (typeof value === 'number' && Number.isFinite(value)) return value;\n if (typeof value === 'string') {\n const t = new Date(value).getTime();\n return Number.isFinite(t) ? t : 0;\n }\n return 0;\n};\n\n/** Confidence score for sorting (interpretation.confidence or opportunity.confidence). */\nconst getRawConfidence = (opp: typeof HomeGraphState.State['opportunities'][number]): number => {\n const fromInterp = opp.interpretation?.confidence;\n if (typeof fromInterp === 'number' && !Number.isNaN(fromInterp)) return fromInterp;\n if (typeof fromInterp === 'string') {\n const n = parseFloat(fromInterp);\n if (!Number.isNaN(n)) return n;\n }\n const fromRow = opp.confidence;\n if (typeof fromRow === 'number' && !Number.isNaN(fromRow)) return fromRow;\n if (typeof fromRow === 'string') {\n const n = parseFloat(fromRow);\n if (!Number.isNaN(n)) return n;\n }\n return 0;\n};\n\n/**\n * Sort confidence, optionally pool-adjusted (IND-419): when\n * POOL_QUESTIONS_RANKING=on, answered discriminators multiply confidence by\n * their stored factors (floor 0.3) so the user's answers re-rank the feed.\n * Flag off → identical to raw confidence (adjustments are write-only).\n */\nconst getPoolRankingProvenance = (\n state: typeof HomeGraphState.State,\n): PoolAdjustmentProvenance | null => {\n if (\n poolQuestionsRanking() !== 'on' ||\n !state.userId ||\n state.scopeType !== 'intent' ||\n !state.scopeId\n ) return null;\n return { recipientUserId: state.userId, intentId: state.scopeId };\n};\n\nconst hasPoolAdjustment = (\n opp: typeof HomeGraphState.State['opportunities'][number],\n provenance: PoolAdjustmentProvenance,\n): boolean => readActivePoolAdjustments(\n (opp as { metadata?: Record<string, unknown> | null }).metadata,\n provenance,\n).length > 0;\n\nconst getConfidence = (\n opp: typeof HomeGraphState.State['opportunities'][number],\n provenance: PoolAdjustmentProvenance | null,\n): number => {\n const raw = getRawConfidence(opp);\n if (!provenance) return raw;\n return adjustedConfidence(\n raw,\n (opp as { metadata?: Record<string, unknown> | null }).metadata,\n provenance,\n );\n};\n\n/** Unique non-introducer, non-viewer userIds for an opportunity (actors can repeat). */\nconst getUniqueCounterpartUserIds = (\n opp: typeof HomeGraphState.State['opportunities'][number],\n viewerId: string\n): Set<string> => {\n const ids = new Set<string>();\n for (const a of opp.actors) {\n if (a.role !== 'introducer' && a.userId !== viewerId && a.userId) {\n ids.add(a.userId);\n }\n }\n return ids;\n};\n\nconst pickDisplayCounterpartActor = (\n opportunity: typeof HomeGraphState.State['opportunities'][number],\n viewerId: string\n): { userId: string; role: string } | null => {\n const candidates = opportunity.actors.filter(\n (actor) => actor.userId !== viewerId && actor.role !== 'introducer'\n );\n if (candidates.length === 0) {\n return null;\n }\n\n // Prefer direct counterpart roles when available, then stable sort by user id.\n const rolePriority = new Map<string, number>([\n ['patient', 0],\n ['party', 1],\n ['agent', 2],\n ['peer', 3],\n ]);\n\n const sorted = [...candidates].sort((a, b) => {\n const aPriority = rolePriority.get(a.role) ?? 99;\n const bPriority = rolePriority.get(b.role) ?? 99;\n if (aPriority !== bPriority) return aPriority - bPriority;\n return a.userId.localeCompare(b.userId);\n });\n return sorted[0] ?? null;\n};\n\nexport class HomeGraphFactory {\n constructor(private database: HomeGraphDb, private cache: OpportunityCache) {}\n\n createGraph() {\n const presenter = new OpportunityPresenter();\n const categorizer = new HomeCategorizerAgent();\n\n const loadOpportunitiesNode = async (state: typeof HomeGraphState.State) => {\n return timed(\"HomeGraph.loadOpportunities\", async () => {\n if (!state.userId) {\n return { error: 'userId is required' };\n }\n try {\n // Minimum of 50 ensures enough candidates across all feed categories\n // (connection, connector-flow, expired) for selectByComposition to fill\n // its soft targets, even after visibility filtering and dedup.\n const fetchLimit = Math.min(150, Math.max(50, state.limit * 3));\n const statuses = state.statuses ?? DEFAULT_HOME_STATUSES;\n const poolRankingProvenance = getPoolRankingProvenance(state);\n const options: { limit?: number; networkId?: string; scopeType?: 'intent'; scopeId?: string; statuses?: OpportunityStatus[] } = {\n limit: fetchLimit,\n statuses,\n };\n if (state.networkId) options.networkId = state.networkId;\n if (state.scopeType === 'intent' && state.scopeId) {\n options.scopeType = 'intent';\n options.scopeId = state.scopeId;\n }\n // Do not pass conversationId: home view excludes draft opportunities (chat-only drafts).\n const raw = await this.database.getOpportunitiesForUser(state.userId, options);\n const visible = raw.filter((opp) =>\n canUserSeeOpportunity(opp.actors, opp.status, state.userId)\n );\n // Actionability only gates the live statuses a viewer could act on:\n // latent/pending cards the viewer cannot act on are noise, but\n // terminal/internal statuses (accepted, rejected, expired, negotiating,\n // stalled, draft) are deliberate history — when a caller explicitly\n // requests them via `statuses`, they must pass through (they are never\n // actionable by rule 5, so filtering them here would return nothing).\n // The requested-status membership check is defense-in-depth: rows\n // outside the requested set are dropped even if the adapter drifts.\n const requestedStatuses = new Set<OpportunityStatus>(statuses);\n const visibleForFeed = visible.filter((opp) => {\n if (!requestedStatuses.has(opp.status)) return false;\n if (opp.status === 'latent' || opp.status === 'pending') {\n return isActionableForViewer(opp.actors, opp.status, state.userId);\n }\n return true;\n });\n const explicitStatuses = (state.statuses?.length ?? 0) > 0;\n if (explicitStatuses) {\n // Lifecycle view (e.g. intent radar): newest-first so counterpart\n // dedup keeps each person's most recent state (an accepted\n // opportunity supersedes an older pending one), no composition\n // capping — the caller wants the full pipeline up to `limit`.\n const newestFirst = [...visibleForFeed].sort(\n (a, b) => safeParseDate(b.updatedAt) - safeParseDate(a.updatedAt)\n );\n const seenIds = new Set<string>();\n const dedupedByCounterpart = newestFirst.filter((opp) => {\n const counterpartIds = getUniqueCounterpartUserIds(opp, state.userId);\n const hasOverlap = [...counterpartIds].some((id) => seenIds.has(id));\n if (hasOverlap) return false;\n for (const id of counterpartIds) seenIds.add(id);\n return true;\n });\n // Preserve byte-identical newest-first behavior while the flag is\n // off. When on, re-order the already-deduped lifecycle set by\n // adjusted confidence so each client-side radar bucket reflects\n // pool answers immediately.\n if (\n !poolRankingProvenance ||\n !dedupedByCounterpart.some((opportunity) => hasPoolAdjustment(opportunity, poolRankingProvenance))\n ) {\n return { opportunities: dedupedByCounterpart.slice(0, state.limit) };\n }\n const adjustedOrder = [...dedupedByCounterpart].sort((a, b) => {\n const confidenceDelta = getConfidence(b, poolRankingProvenance) - getConfidence(a, poolRankingProvenance);\n if (confidenceDelta !== 0) return confidenceDelta;\n return safeParseDate(b.updatedAt) - safeParseDate(a.updatedAt);\n });\n return { opportunities: adjustedOrder.slice(0, state.limit) };\n }\n const sorted = [...visibleForFeed].sort((a, b) => {\n // Connections before connector-flow so dedup claims counterpart IDs\n // for direct connections first — prevents introducer cards from\n // shadowing a user's own connection opportunities.\n const aIsIntroducer = a.actors.some((ac) => ac.userId === state.userId && ac.role === 'introducer');\n const bIsIntroducer = b.actors.some((ac) => ac.userId === state.userId && ac.role === 'introducer');\n if (aIsIntroducer !== bIsIntroducer) return aIsIntroducer ? 1 : -1;\n const confA = getConfidence(a, poolRankingProvenance);\n const confB = getConfidence(b, poolRankingProvenance);\n if (confB !== confA) return confB - confA;\n const aTime = safeParseDate(a.updatedAt);\n const bTime = safeParseDate(b.updatedAt);\n return bTime - aTime;\n });\n const seenUserIds = new Set<string>();\n const deduped = sorted.filter((opp) => {\n const counterpartIds = getUniqueCounterpartUserIds(opp, state.userId);\n const hasOverlap = [...counterpartIds].some((id) => seenUserIds.has(id));\n if (hasOverlap) return false;\n for (const id of counterpartIds) seenUserIds.add(id);\n return true;\n });\n const opportunities = selectByComposition(deduped, state.userId);\n return { opportunities };\n } catch (e) {\n logger.error('HomeGraph loadOpportunities failed', { error: e });\n return { error: 'Failed to load opportunities', opportunities: [] };\n }\n });\n };\n\n const checkPresenterCacheNode = async (state: typeof HomeGraphState.State) => {\n return timed(\"HomeGraph.checkPresenterCache\", async () => {\n const { opportunities, userId } = state;\n const poolRankingProvenance = getPoolRankingProvenance(state);\n if (opportunities.length === 0) {\n return { cachedCards: new Map(), uncachedOpportunities: [] };\n }\n\n if (state.noCache) {\n checkPresenterCacheLog.verbose('noCache=true, skipping cache');\n return { cachedCards: new Map(), uncachedOpportunities: opportunities };\n }\n\n try {\n // Negotiating cards are templated (no LLM call) and their text\n // depends on the live turn count, which changes between requests\n // without changing the opportunity status. Skip cache entirely\n // for them so each render reflects the current turn.\n //\n // For all other statuses, include status in the key so status\n // transitions (e.g. negotiating → pending) don't serve stale cards.\n const cacheable = opportunities.filter((opp) => opp.status !== 'negotiating');\n const liveNegotiating = opportunities.filter((opp) => opp.status === 'negotiating');\n\n const keys = cacheable.map((opp) =>\n buildHomeCardPresentationCacheKey(opp.id, opp.status, userId)\n );\n const results = keys.length > 0 ? await this.cache.mget<HomeCardItem>(keys) : [];\n\n const cachedCards = new Map<string, HomeCardItem>();\n const uncachedOpportunities: typeof opportunities = [...liveNegotiating];\n\n for (let i = 0; i < cacheable.length; i++) {\n const cached = results[i];\n if (cached) {\n const originalIndex = opportunities.indexOf(cacheable[i]);\n // Stamp the live status: pre-status cache entries lack the field,\n // and the key already guarantees it matches the current status.\n const deprioritizedReason = poolRankingProvenance\n ? latestPoolDemotionDetail(\n (cacheable[i] as { metadata?: Record<string, unknown> | null }).metadata,\n poolRankingProvenance,\n )\n : undefined;\n cachedCards.set(cacheable[i].id, {\n ...cached,\n status: cacheable[i].status,\n deprioritizedReason,\n _cardIndex: originalIndex,\n });\n } else {\n uncachedOpportunities.push(cacheable[i]);\n }\n }\n\n checkPresenterCacheLog.verbose('', {\n total: opportunities.length,\n cacheHits: cachedCards.size,\n cacheMisses: uncachedOpportunities.length,\n });\n\n return { cachedCards, uncachedOpportunities };\n } catch (e) {\n checkPresenterCacheLog.warn('cache unavailable, skipping', { error: e });\n return { cachedCards: new Map(), uncachedOpportunities: opportunities };\n }\n });\n };\n\n const shouldGenerateCards = (state: typeof HomeGraphState.State): string => {\n if (state.uncachedOpportunities.length > 0) {\n return 'generate';\n }\n logger.verbose('All presenter results cached, skipping generation');\n return 'skip';\n };\n\n const generateCardTextNode = async (state: typeof HomeGraphState.State) => {\n return timed(\"HomeGraph.generateCardText\", async () => {\n const opportunities = state.uncachedOpportunities.length > 0\n ? state.uncachedOpportunities\n : state.opportunities;\n generateCardTextLog.verbose('entry', { opportunitiesLength: opportunities.length, userId: state.userId });\n if (opportunities.length === 0) {\n generateCardTextLog.verbose('exit', { totalOpportunities: 0, totalSections: 0 });\n return { cards: [], agentTimings: [], meta: { totalOpportunities: 0, totalSections: 0 } };\n }\n const db = this.database as PresenterDatabase & HomeGraphDb;\n const cards: HomeCardItem[] = [];\n const relevantActorIds = new Set<string>();\n for (const opp of opportunities) {\n for (const a of opp.actors) {\n if (a.userId) relevantActorIds.add(a.userId);\n }\n }\n\n const userEntries = await Promise.all(\n Array.from(relevantActorIds).map(async (userId) => {\n try {\n const user = await this.database.getUser(userId);\n return [userId, user ?? null] as const;\n } catch {\n return [userId, null] as const;\n }\n })\n );\n const userMap = new Map(userEntries);\n\n const oppIndexMap = new Map(\n state.opportunities.map((opp, idx) => [opp.id, idx])\n );\n\n const agentTimingsAccum: DebugMetaAgent[] = [];\n\n for (let i = 0; i < opportunities.length; i += PRESENTATION_CONCURRENCY) {\n const chunk = opportunities.slice(i, i + PRESENTATION_CONCURRENCY);\n const chunkCards = await Promise.all(\n chunk.map(async (opportunity, offset) => {\n const cardIndex = oppIndexMap.get(opportunity.id) ?? (i + offset);\n const viewerActor = opportunity.actors.find((a) => a.userId === state.userId);\n const viewerRole = viewerActor?.role ?? 'party';\n const isIntroducer = viewerRole === 'introducer';\n const preferredActor = pickDisplayCounterpartActor(opportunity, state.userId)\n ?? opportunity.actors.find((a) => a.userId !== state.userId && a.role !== 'introducer');\n const actorWithProfile = opportunity.actors.find(\n (a) => a.userId !== state.userId && a.role !== 'introducer' && !!userMap.get(a.userId)\n );\n const introducer = opportunity.actors.find((a) => a.role === 'introducer');\n let otherActor = (preferredActor && userMap.get(preferredActor.userId))\n ? preferredActor\n : (actorWithProfile ?? preferredActor);\n // When the only other participant is the introducer (no separate party), use introducer as display counterpart so the card shows a name instead of \"Unknown\"\n if (!otherActor && introducer && introducer.userId !== state.userId && introducer.userId) {\n otherActor = { userId: introducer.userId, role: introducer.role };\n }\n const otherUser = otherActor ? userMap.get(otherActor.userId) ?? null : null;\n const introducerCounterparts = opportunity.actors.filter(\n (a) => a.userId !== state.userId && a.role !== 'introducer'\n );\n // Deduplicate by userId — actors array can contain multiple rows per user\n // (e.g. from different intents), which would produce repeated names.\n const uniqueCounterpartIds = [...new Set(introducerCounterparts.map((a) => a.userId))];\n const participantNames = uniqueCounterpartIds\n .map((uid) => userMap.get(uid)?.name ?? 'Unknown')\n .sort();\n // When secondPartyData will be present (2+ counterparts), use single counterpart name\n // because the frontend arrow layout renders \"card.name → secondParty.name\".\n // Using the joined \"A ↔ B\" format here would produce redundant \"A ↔ B → B\".\n // Only use the joined format when there is a single counterpart (no arrow layout).\n const willHaveSecondParty = isIntroducer && uniqueCounterpartIds.length > 1;\n let userName = isIntroducer && participantNames.length > 0 && !willHaveSecondParty\n ? participantNames.join(' ↔ ')\n : (otherUser?.name ?? 'Unknown');\n // Fallback to profile identity name when users.name is missing (e.g. profile has display name, users row does not)\n if ((userName === 'Unknown' || !userName?.trim()) && otherActor?.userId && db.getProfile) {\n const profile = await db.getProfile(otherActor.userId).catch((err) => {\n logger.debug('getProfile fallback failed', { otherActorUserId: otherActor.userId, error: err });\n return null;\n });\n const profileName = profile?.identity?.name?.trim();\n if (profileName) userName = profileName;\n }\n // Unresolvable display counterpart (deleted user: no users row, no\n // profile fallback). Drop the card entirely instead of rendering an\n // \"Unknown\" placeholder: such cards are unusable, excluded from the\n // presenter cache (see cachePresenterResults), and would otherwise\n // trigger a fresh presenter LLM call on every request — a permanent\n // cache miss that keeps the whole feed slow (~9s per load).\n if (userName === 'Unknown' || !userName?.trim()) {\n logger.verbose('[HomeGraph:generateCardText] dropping card with unresolvable counterpart', {\n opportunityId: opportunity.id,\n otherActorUserId: otherActor?.userId,\n });\n return null;\n }\n const userAvatar = otherUser?.avatar ?? null;\n // Shared sanitization standard (UUID strip, viewer-centric rewrite,\n // boundary truncation) — raw reasoning must never render verbatim.\n const reasoningSnippet = safeFallbackSummary(\n typeof opportunity.interpretation?.reasoning === 'string'\n ? opportunity.interpretation.reasoning\n : '',\n {\n counterpartName: userName !== 'Unknown' ? userName : undefined,\n maxChars: MAX_REASONING_SNIPPET_LENGTH,\n emptyText: 'A promising connection.',\n },\n );\n\n // Build secondParty for introducer arrow layout (the party that isn't the display counterpart)\n let secondPartyData: { name: string; avatar?: string | null; userId?: string } | undefined;\n if (isIntroducer && introducerCounterparts.length > 1 && otherActor) {\n const secondActor = introducerCounterparts.find((a) => a.userId !== otherActor.userId);\n if (secondActor) {\n const secondUser = userMap.get(secondActor.userId) ?? null;\n secondPartyData = {\n name: secondUser?.name ?? 'Unknown',\n avatar: secondUser?.avatar ?? null,\n userId: secondActor.userId,\n };\n }\n }\n\n const isCounterpartGhost = otherUser?.isGhost ?? false;\n // Skeleton presentation: return an identity-only card without the\n // presenter LLM or negotiation-context load. Name resolution and\n // the unresolvable-counterpart drop above still apply, so the card\n // set matches what the follow-up full request will return.\n if (state.presentation === 'skeleton') {\n return {\n opportunityId: opportunity.id,\n status: opportunity.status,\n userId: otherActor?.userId ?? '',\n name: userName,\n avatar: userAvatar,\n mainText: '',\n cta: '',\n primaryActionLabel: getPrimaryActionLabel(viewerRole),\n secondaryActionLabel: SECONDARY_ACTION_LABEL,\n mutualIntentsLabel: isIntroducer ? 'Connector match' : 'Shared interests',\n viewerRole,\n isGhost: isCounterpartGhost,\n ...(secondPartyData ? { secondParty: secondPartyData } : {}),\n presentationPending: true,\n _cardIndex: cardIndex,\n } satisfies HomeCardItem;\n }\n const isPendingIntroducerFallback = isIntroducer && opportunity.status !== 'latent';\n const fallbackCard = (): HomeCardItem => ({\n opportunityId: opportunity.id,\n status: opportunity.status,\n userId: otherActor?.userId ?? '',\n name: userName,\n avatar: userAvatar,\n mainText: reasoningSnippet,\n cta: isIntroducer\n ? (isPendingIntroducerFallback ? 'Share this introduction to get things started.' : 'Take a look and decide if this is a good match.')\n : 'Take a look and decide whether to reach out.',\n primaryActionLabel: getPrimaryActionLabel(viewerRole),\n secondaryActionLabel: SECONDARY_ACTION_LABEL,\n mutualIntentsLabel: isIntroducer ? 'Connector match' : 'Shared interests',\n narratorChip: isIntroducer\n ? { name: 'You', text: 'Worth a look.', userId: state.userId }\n : { name: 'Index', text: 'Worth a look.' },\n viewerRole,\n isGhost: isCounterpartGhost,\n ...(secondPartyData ? { secondParty: secondPartyData } : {}),\n _presentationFallback: true,\n _cardIndex: cardIndex,\n });\n\n try {\n const [ctx, negotiationContext] = await Promise.all([\n gatherPresenterContext(\n db,\n opportunity,\n state.userId,\n otherActor?.userId,\n ),\n loadNegotiationContext(db, opportunity.id, opportunity.status),\n ]);\n const homeInput = {\n ...ctx,\n mutualIntentCount: undefined,\n opportunityStatus: opportunity.status,\n ...(negotiationContext ? { negotiationContext } : {}),\n };\n const _traceEmitterPresenter = requestContext.getStore()?.traceEmitter;\n const presenterStart = Date.now();\n _traceEmitterPresenter?.({ type: \"agent_start\", name: \"opportunity-presenter\" });\n const presentation = await presenter.presentHomeCard(homeInput);\n const _presenterDuration = Date.now() - presenterStart;\n agentTimingsAccum.push({ name: 'opportunity.presenter', durationMs: _presenterDuration });\n _traceEmitterPresenter?.({ type: \"agent_end\", name: \"opportunity-presenter\", durationMs: _presenterDuration, summary: `Presented: ${userName}` });\n if (presentation.isFallback) {\n return fallbackCard();\n }\n let narratorChip: { name: string; text: string; avatar?: string | null; userId?: string } | undefined;\n // Only show a person as narrator when they are the introducer and not the display counterpart\n // (bad data can have same user as introducer and party, e.g. \"Amina introduced you to Amina\")\n const introducerIsCounterpart = introducer && otherActor && introducer.userId === otherActor.userId;\n if (introducer && introducer.userId !== state.userId && !introducerIsCounterpart) {\n const introUser = userMap.get(introducer.userId) ?? null;\n const narratorName = introUser?.name ?? 'Someone';\n narratorChip = {\n name: narratorName,\n text: stripLeadingNarratorName(presentation.narratorRemark, narratorName),\n avatar: introUser?.avatar ?? null,\n userId: introducer.userId,\n };\n } else if (introducer?.userId === state.userId) {\n narratorChip = { name: 'You', text: presentation.narratorRemark, userId: state.userId };\n } else {\n narratorChip = { name: 'Index', text: presentation.narratorRemark };\n }\n return {\n opportunityId: opportunity.id,\n status: opportunity.status,\n userId: otherActor?.userId ?? '',\n name: userName,\n avatar: userAvatar,\n mainText: presentation.personalizedSummary,\n cta: presentation.suggestedAction,\n headline: presentation.headline,\n primaryActionLabel: getPrimaryActionLabel(viewerRole),\n secondaryActionLabel: SECONDARY_ACTION_LABEL,\n mutualIntentsLabel: presentation.mutualIntentsLabel,\n narratorChip,\n viewerRole,\n isGhost: isCounterpartGhost,\n ...(secondPartyData ? { secondParty: secondPartyData } : {}),\n _cardIndex: cardIndex,\n } satisfies HomeCardItem;\n } catch (e) {\n logger.warn('HomeGraph presenter failed for opportunity', { opportunityId: opportunity.id, error: e });\n return fallbackCard();\n }\n })\n );\n cards.push(...chunkCards.filter((c): c is HomeCardItem => c !== null));\n }\n generateCardTextLog.verbose('exit', { totalOpportunities: state.opportunities.length, totalSections: 0 });\n return {\n cards,\n agentTimings: agentTimingsAccum,\n meta: { totalOpportunities: state.opportunities.length, totalSections: 0 },\n };\n });\n };\n\n const cachePresenterResultsNode = async (state: typeof HomeGraphState.State) => {\n return timed(\"HomeGraph.cachePresenterResults\", async () => {\n const { cards, cachedCards, userId, opportunities } = state;\n const poolRankingProvenance = getPoolRankingProvenance(state);\n const liveById = new Map(opportunities.map((opportunity) => [opportunity.id, opportunity]));\n const cardsWithAdjustments = cards.map((card) => {\n const opportunity = liveById.get(card.opportunityId);\n const deprioritizedReason = poolRankingProvenance\n ? latestPoolDemotionDetail(\n (opportunity as { metadata?: Record<string, unknown> | null } | undefined)?.metadata,\n poolRankingProvenance,\n )\n : undefined;\n return { ...card, deprioritizedReason };\n });\n\n // Only cache cards that weren't already from cache\n const newCards = cardsWithAdjustments.filter((card) => !cachedCards.has(card.opportunityId));\n const statusById = new Map(opportunities.map((opp) => [opp.id, opp.status]));\n\n try {\n await Promise.all(\n newCards.map((card) => {\n const status = statusById.get(card.opportunityId);\n // Negotiating, skeleton, fallback, and unresolved-name cards are\n // safe for the current response but must not become 24h entries.\n if (!status || !isHomePresentationCacheable(card, status)) return Promise.resolve();\n return this.cache.set(\n buildHomeCardPresentationCacheKey(card.opportunityId, status, userId),\n card,\n { ttl: HOME_CACHE_TTL }\n );\n })\n );\n } catch (e) {\n cachePresenterResultsLog.warn('cache write failed, continuing', { error: e });\n }\n\n // Merge cached cards into full card list\n const allCards: HomeCardItem[] = [...cardsWithAdjustments];\n for (const [oppId, cachedCard] of cachedCards) {\n if (!cardsWithAdjustments.some((card) => card.opportunityId === oppId)) {\n allCards.push(cachedCard);\n }\n }\n\n // Re-sort by _cardIndex to maintain original ordering\n allCards.sort((a, b) => a._cardIndex - b._cardIndex);\n\n cachePresenterResultsLog.verbose('', {\n newlyCached: newCards.length,\n totalCards: allCards.length,\n });\n\n return {\n cards: allCards,\n meta: { totalOpportunities: state.opportunities.length, totalSections: 0 },\n };\n });\n };\n\n const checkCategorizerCacheNode = async (state: typeof HomeGraphState.State) => {\n return timed(\"HomeGraph.checkCategorizerCache\", async () => {\n if (state.cards.length === 0) {\n return { categoryCacheHit: false };\n }\n\n // Skeleton runs never categorize (some cards have no text to categorize\n // and the response must stay LLM-free). Ranking-enabled lifecycle views\n // also stay flat: the intent Radar flattens sections and buckets by\n // status, so dynamic categorization would erase the adjusted order on\n // the full second-phase response. Flag off retains the legacy path.\n // Chunk by MAX_ITEMS_PER_SECTION because normalizeAndSort caps sections.\n const poolRankingProvenance = getPoolRankingProvenance(state);\n const preserveAdjustedLifecycleOrder =\n (state.statuses?.length ?? 0) > 0 &&\n poolRankingProvenance !== null &&\n state.opportunities.some((opportunity) => hasPoolAdjustment(opportunity, poolRankingProvenance));\n if (state.presentation === 'skeleton' || preserveAdjustedLifecycleOrder) {\n const sectionProposals: HomeSectionProposal[] = [];\n for (let start = 0; start < state.cards.length; start += MAX_ITEMS_PER_SECTION) {\n sectionProposals.push({\n id: `all-${sectionProposals.length + 1}`,\n title: 'All matches',\n iconName: DEFAULT_HOME_SECTION_ICON,\n itemIndices: state.cards.slice(start, start + MAX_ITEMS_PER_SECTION).map((_, i) => start + i),\n });\n }\n return { sectionProposals, categoryCacheHit: true };\n }\n\n if (state.noCache) {\n checkCategorizerCacheLog.verbose('noCache=true, skipping cache');\n return { categoryCacheHit: false };\n }\n\n try {\n const key = buildCategorizerCacheKey(state.userId, state.cards);\n\n const cached = await this.cache.get<HomeSectionProposal[]>(key);\n if (cached) {\n checkCategorizerCacheLog.verbose('cache hit');\n return { sectionProposals: cached, categoryCacheHit: true };\n }\n\n checkCategorizerCacheLog.verbose('cache miss');\n } catch (e) {\n checkCategorizerCacheLog.warn('cache unavailable, skipping', { error: e });\n }\n return { categoryCacheHit: false };\n });\n };\n\n const shouldCategorize = (state: typeof HomeGraphState.State): string => {\n if (state.categoryCacheHit) {\n logger.verbose('Categorizer results cached, skipping');\n return 'skip';\n }\n return 'categorize';\n };\n\n const categorizeDynamicallyNode = async (state: typeof HomeGraphState.State) => {\n return timed(\"HomeGraph.categorizeDynamically\", async () => {\n categorizeDynamicallyLog.verbose('entry', { cardsLength: state.cards.length });\n if (state.cards.length === 0) {\n categorizeDynamicallyLog.verbose('exit', { sectionProposalsCount: 0 });\n return { sectionProposals: [], agentTimings: [] };\n }\n const agentTimingsAccum: DebugMetaAgent[] = [];\n const categorizerInput = state.cards.map((c) => ({\n index: c._cardIndex,\n headline: c.headline,\n mainText: c.mainText,\n name: c.name,\n viewerRole: c.viewerRole === 'introducer' ? 'introducer' : undefined,\n opportunityStatus: c.viewerRole === 'introducer' ? 'pending' : undefined,\n }));\n const _traceEmitterCategorizer = requestContext.getStore()?.traceEmitter;\n const categorizerStart = Date.now();\n _traceEmitterCategorizer?.({ type: \"agent_start\", name: \"home-categorizer\" });\n const { sections } = await categorizer.categorize(categorizerInput);\n const _categorizerDuration = Date.now() - categorizerStart;\n agentTimingsAccum.push({ name: 'home.categorizer', durationMs: _categorizerDuration });\n _traceEmitterCategorizer?.({ type: \"agent_end\", name: \"home-categorizer\", durationMs: _categorizerDuration, summary: `Categorized into ${sections.length} section(s)` });\n const proposals: HomeSectionProposal[] = sections.map((s) => ({\n ...s,\n itemIndices: s.itemIndices.filter((i) => i >= 0 && i < state.cards.length),\n }));\n categorizeDynamicallyLog.verbose('exit', { sectionProposalsCount: proposals.length });\n return { sectionProposals: proposals, agentTimings: agentTimingsAccum };\n });\n };\n\n const cacheCategorizerResultsNode = async (state: typeof HomeGraphState.State) => {\n return timed(\"HomeGraph.cacheCategorizerResults\", async () => {\n if (\n state.categoryCacheHit ||\n state.sectionProposals.length === 0 ||\n state.cards.some((card) => card._presentationFallback)\n ) {\n return {};\n }\n\n try {\n const key = buildCategorizerCacheKey(state.userId, state.cards);\n\n await this.cache.set(key, state.sectionProposals, { ttl: HOME_CACHE_TTL });\n\n cacheCategorizerResultsLog.verbose('cached', {\n sectionCount: state.sectionProposals.length,\n });\n } catch (e) {\n cacheCategorizerResultsLog.warn('cache write failed, continuing', { error: e });\n }\n\n return {};\n });\n };\n\n const normalizeAndSortNode = async (state: typeof HomeGraphState.State) => {\n return timed(\"HomeGraph.normalizeAndSort\", async () => {\n const cards = state.cards;\n const proposals = state.sectionProposals;\n normalizeAndSortLog.verbose('entry', { cardsLength: cards.length, proposalsLength: proposals.length });\n if (cards.length === 0) {\n normalizeAndSortLog.verbose('exit', { totalOpportunities: 0, totalSections: 0 });\n return { sections: [], meta: { totalOpportunities: 0, totalSections: 0 } };\n }\n const usedIndices = new Set<number>();\n const sections: HomeSection[] = proposals.map((p) => {\n const iconName = resolveHomeSectionIcon(p.iconName);\n const items: HomeSectionItem[] = p.itemIndices\n .filter((i) => i >= 0 && i < cards.length && !usedIndices.has(i))\n .slice(0, MAX_ITEMS_PER_SECTION)\n .map((i) => {\n usedIndices.add(i);\n const card = cards[i];\n const { _cardIndex, _presentationFallback, ...rest } = card;\n return rest;\n });\n return {\n id: p.id,\n title: p.title,\n subtitle: p.subtitle,\n iconName,\n items,\n };\n });\n\n // Enforce category ordering: sections with connections first, then\n // connector-flow only, then expired only. This prevents the LLM\n // categorizer from placing introducer sections before connection sections.\n const sectionCategoryPriority = (section: HomeSection): number => {\n const hasConnection = section.items.some((item) => item.viewerRole !== 'introducer');\n if (hasConnection) return 0; // mixed or connection-only sections first\n const hasConnectorFlow = section.items.some((item) => item.viewerRole === 'introducer');\n if (hasConnectorFlow) return 1; // connector-flow only sections next\n return 2; // empty or expired sections last\n };\n sections.sort((a, b) => sectionCategoryPriority(a) - sectionCategoryPriority(b));\n const meta = {\n totalOpportunities: state.opportunities.length,\n totalSections: sections.length,\n };\n normalizeAndSortLog.verbose('exit', { totalOpportunities: meta.totalOpportunities, totalSections: meta.totalSections });\n return { sections, meta };\n });\n };\n\n const graph = new StateGraph(HomeGraphState)\n .addNode('loadOpportunities', loadOpportunitiesNode)\n .addNode('checkPresenterCache', checkPresenterCacheNode)\n .addNode('generateCardText', generateCardTextNode)\n .addNode('cachePresenterResults', cachePresenterResultsNode)\n .addNode('checkCategorizerCache', checkCategorizerCacheNode)\n .addNode('categorizeDynamically', categorizeDynamicallyNode)\n .addNode('cacheCategorizerResults', cacheCategorizerResultsNode)\n .addNode('normalizeAndSort', normalizeAndSortNode)\n .addEdge(START, 'loadOpportunities')\n .addEdge('loadOpportunities', 'checkPresenterCache')\n .addConditionalEdges('checkPresenterCache', shouldGenerateCards, {\n generate: 'generateCardText',\n skip: 'cachePresenterResults',\n })\n .addEdge('generateCardText', 'cachePresenterResults')\n .addEdge('cachePresenterResults', 'checkCategorizerCache')\n .addConditionalEdges('checkCategorizerCache', shouldCategorize, {\n categorize: 'categorizeDynamically',\n skip: 'normalizeAndSort',\n })\n .addEdge('categorizeDynamically', 'cacheCategorizerResults')\n .addEdge('cacheCategorizerResults', 'normalizeAndSort')\n .addEdge('normalizeAndSort', END);\n\n return graph.compile();\n }\n}\n"]}