@indexnetwork/protocol 4.7.0 → 4.8.0-rc.347.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.
- package/dist/opportunity/discriminator/discriminator.question.d.ts +5 -0
- package/dist/opportunity/discriminator/discriminator.question.d.ts.map +1 -1
- package/dist/opportunity/discriminator/discriminator.question.js +15 -2
- package/dist/opportunity/discriminator/discriminator.question.js.map +1 -1
- package/dist/shared/schemas/question.schema.d.ts +10 -0
- package/dist/shared/schemas/question.schema.d.ts.map +1 -1
- package/dist/shared/schemas/question.schema.js +2 -0
- package/dist/shared/schemas/question.schema.js.map +1 -1
- package/package.json +1 -1
|
@@ -35,6 +35,11 @@ export interface SynthesizePoolQuestionInput {
|
|
|
35
35
|
minedAt: string;
|
|
36
36
|
/** Discovery run id, when known. */
|
|
37
37
|
runId?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Intent payload snippet — folded into the evidence chip so the question
|
|
40
|
+
* self-identifies on any surface ("based on 16 people matching ‘…’").
|
|
41
|
+
*/
|
|
42
|
+
intentText?: string;
|
|
38
43
|
}
|
|
39
44
|
/** Synthesized question: client payload + server-side snapshot. */
|
|
40
45
|
export interface SynthesizedPoolQuestion {
|
|
@@ -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,CAmBzF;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,cAAc,EAAE,mBAAmB,EAAE,GAAG,mBAAmB,EAAE,CAIzG;
|
|
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,CAmBzF;AAED;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,cAAc,EAAE,mBAAmB,EAAE,GAAG,mBAAmB,EAAE,CAIzG;AAwDD,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;CACrB;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,CAyCzG"}
|
|
@@ -58,7 +58,13 @@ function toSecondPerson(seed) {
|
|
|
58
58
|
.replace(/\b(do|should|would|could|can|will) I\b/gi, (_, verb) => `${verb.toLowerCase()} you`)
|
|
59
59
|
.replace(/\bam I\b/gi, "are you")
|
|
60
60
|
.replace(/\bI\b/g, "you")
|
|
61
|
-
.replace(/\bmy\b/gi, "your")
|
|
61
|
+
.replace(/\bmy\b/gi, "your")
|
|
62
|
+
// Third-person seeds ("Is the user primarily involved…") — the question is
|
|
63
|
+
// asked TO the owner, never ABOUT them.
|
|
64
|
+
.replace(/\b(is|was) the (user|owner|discoverer)\b/gi, "are you")
|
|
65
|
+
.replace(/\bdoes the (user|owner|discoverer)\b/gi, "do you")
|
|
66
|
+
.replace(/\bthe (user|owner|discoverer)'s\b/gi, "your")
|
|
67
|
+
.replace(/\bthe (user|owner|discoverer)\b/gi, "you");
|
|
62
68
|
}
|
|
63
69
|
/**
|
|
64
70
|
* A good discriminator prompt names BOTH sides so the chips read as a real
|
|
@@ -99,6 +105,12 @@ export function synthesizePoolQuestion(input) {
|
|
|
99
105
|
return null;
|
|
100
106
|
if (d.sides.length < 2 || d.sides.length > 3)
|
|
101
107
|
return null;
|
|
108
|
+
// Evidence chip: aggregate count + the intent it belongs to, so the card is
|
|
109
|
+
// self-identifying on every surface (QuestionSchema caps evidence at 160).
|
|
110
|
+
const snippet = input.intentText?.trim().replace(/\s+/g, " ") ?? "";
|
|
111
|
+
const evidence = snippet.length > 0
|
|
112
|
+
? `based on ${poolSize} people matching “${snippet.slice(0, 110)}${snippet.length > 110 ? "…" : ""}”`
|
|
113
|
+
: `based on ${poolSize} people matching this intent`;
|
|
102
114
|
const sideOptions = d.sides.map((side) => ({
|
|
103
115
|
label: chipLabel(side),
|
|
104
116
|
description: `${d.sideCounts[side] ?? 0} of your ${poolSize} current matches lean this way`,
|
|
@@ -116,12 +128,13 @@ export function synthesizePoolQuestion(input) {
|
|
|
116
128
|
prompt: toPrompt(d.questionSeed, d.sides),
|
|
117
129
|
options,
|
|
118
130
|
multiSelect: false,
|
|
119
|
-
evidence
|
|
131
|
+
evidence,
|
|
120
132
|
},
|
|
121
133
|
pool: {
|
|
122
134
|
poolSize,
|
|
123
135
|
minedAt: input.minedAt,
|
|
124
136
|
...(input.runId ? { runId: input.runId } : {}),
|
|
137
|
+
...(snippet.length > 0 ? { intentText: snippet.slice(0, 160) } : {}),
|
|
125
138
|
discriminator: d,
|
|
126
139
|
alternates: input.alternates,
|
|
127
140
|
},
|
|
@@ -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 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}\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) {\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\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 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: `based on ${poolSize} people matching this intent`,\n },\n pool: {\n poolSize,\n minedAt: input.minedAt,\n ...(input.runId ? { runId: input.runId } : {}),\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":"AAWA,OAAO,EAAE,gCAAgC,EAAE,gCAAgC,EAAE,+BAA+B,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAGpK,+EAA+E;AAC/E,MAAM,CAAC,MAAM,iBAAiB,GAAG,aAAa,CAAC;AAE/C,mFAAmF;AACnF,MAAM,eAAe,GAAG,CAAC,CAAC;AAE1B,sDAAsD;AACtD,MAAM,mBAAmB,GAAG,SAAS,CAAC;AAEtC;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CAAC,CAAsB;IAC5D,MAAM,UAAU,GAA2B,EAAE,CAAC;IAC9C,KAAK,MAAM,IAAI,IAAI,CAAC,CAAC,KAAK;QAAE,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACjD,MAAM,WAAW,GAAmD,EAAE,CAAC;IACvE,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;QAC9B,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,QAAQ;YAAE,SAAS;QAC7C,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,UAAU,CAAC;YAAE,SAAS;QACtC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACxB,WAAW,CAAC,IAAI,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO;QACL,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,YAAY,EAAE,CAAC,CAAC,YAAY;QAC5B,KAAK,EAAE,CAAC,CAAC,KAAK;QACd,UAAU;QACV,GAAG,EAAE,CAAC,CAAC,GAAG;QACV,YAAY,EAAE,CAAC,CAAC,YAAY;QAC5B,WAAW;KACZ,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,4BAA4B,CAAC,cAAqC;IAChF,OAAO,cAAc;SAClB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,qBAAqB,IAAI,CAAC,CAAC,YAAY,IAAI,+BAA+B,CAAC;SAClG,KAAK,CAAC,CAAC,EAAE,gCAAgC,CAAC,CAAC;AAChD,CAAC;AAED,sDAAsD;AACtD,SAAS,SAAS,CAAC,IAAY;IAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACvC,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACnD,CAAC;AAED;;;;GAIG;AACH,SAAS,cAAc,CAAC,IAAY;IAClC,OAAO,IAAI;SACR,OAAO,CAAC,0CAA0C,EAAE,CAAC,CAAC,EAAE,IAAY,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC;SACrG,OAAO,CAAC,YAAY,EAAE,SAAS,CAAC;SAChC,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC;SACxB,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC;QAC5B,2EAA2E;QAC3E,wCAAwC;SACvC,OAAO,CAAC,4CAA4C,EAAE,SAAS,CAAC;SAChE,OAAO,CAAC,wCAAwC,EAAE,QAAQ,CAAC;SAC3D,OAAO,CAAC,qCAAqC,EAAE,MAAM,CAAC;SACtD,OAAO,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAC;AACzD,CAAC;AAED;;;;GAIG;AACH,SAAS,YAAY,CAAC,IAAY,EAAE,IAAY;IAC9C,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACrC,OAAO,IAAI;SACR,WAAW,EAAE;SACb,KAAK,CAAC,aAAa,CAAC;SACpB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;SAC3B,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AACxC,CAAC;AAED,yEAAyE;AACzE,SAAS,QAAQ,CAAC,YAAoB,EAAE,KAAe;IACrD,IAAI,CAAC,GAAG,cAAc,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IACjE,MAAM,cAAc,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IACtE,IAAI,cAAc,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACrC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3C,CAAC,GAAG,4BAA4B,IAAI,OAAO,IAAI,EAAE,CAAC;IACpD,CAAC;IACD,iFAAiF;IACjF,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC3C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC;IACvD,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;AACzB,CAAC;AA0BD;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAAkC;IACvE,MAAM,EAAE,aAAa,EAAE,CAAC,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAC;IAC7C,IAAI,QAAQ,GAAG,gCAAgC;QAAE,OAAO,IAAI,CAAC;IAC7D,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAE1D,4EAA4E;IAC5E,2EAA2E;IAC3E,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI,EAAE,CAAC;IACpE,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC;QACjC,CAAC,CAAC,YAAY,QAAQ,qBAAqB,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG;QACrG,CAAC,CAAC,YAAY,QAAQ,8BAA8B,CAAC;IAEvD,MAAM,WAAW,GAAqB,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC3D,KAAK,EAAE,SAAS,CAAC,IAAI,CAAC;QACtB,WAAW,EAAE,GAAG,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,QAAQ,gCAAgC;KAC5F,CAAC,CAAC,CAAC;IACJ,MAAM,OAAO,GAAqB;QAChC,GAAG,WAAW;QACd;YACE,KAAK,EAAE,iBAAiB;YACxB,WAAW,EAAE,0CAA0C;SACxD;KACF,CAAC;IAEF,OAAO;QACL,OAAO,EAAE;YACP,KAAK,EAAE,mBAAmB;YAC1B,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,KAAK,CAAC;YACzC,OAAO;YACP,WAAW,EAAE,KAAK;YAClB,QAAQ;SACT;QACD,IAAI,EAAE;YACJ,QAAQ;YACR,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC9C,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACpE,aAAa,EAAE,CAAC;YAChB,UAAU,EAAE,KAAK,CAAC,UAAU;SAC7B;KACF,CAAC;AACJ,CAAC","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 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 (user|owner|discoverer)\\b/gi, \"are you\")\n .replace(/\\bdoes the (user|owner|discoverer)\\b/gi, \"do you\")\n .replace(/\\bthe (user|owner|discoverer)'s\\b/gi, \"your\")\n .replace(/\\bthe (user|owner|discoverer)\\b/gi, \"you\");\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) {\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}\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 discriminator: d,\n alternates: input.alternates,\n },\n };\n}\n"]}
|
|
@@ -272,6 +272,8 @@ export declare const QuestionPoolSnapshotSchema: z.ZodObject<{
|
|
|
272
272
|
minedAt: z.ZodString;
|
|
273
273
|
/** Discovery run that produced the pool, when known. */
|
|
274
274
|
runId: z.ZodOptional<z.ZodString>;
|
|
275
|
+
/** Intent payload snippet (≤160 chars) — reused by chained questions' evidence chips. */
|
|
276
|
+
intentText: z.ZodOptional<z.ZodString>;
|
|
275
277
|
/** The discriminator this question asks about. */
|
|
276
278
|
discriminator: z.ZodObject<{
|
|
277
279
|
label: z.ZodString;
|
|
@@ -386,6 +388,7 @@ export declare const QuestionPoolSnapshotSchema: z.ZodObject<{
|
|
|
386
388
|
}[];
|
|
387
389
|
}[];
|
|
388
390
|
runId?: string | undefined;
|
|
391
|
+
intentText?: string | undefined;
|
|
389
392
|
}, {
|
|
390
393
|
poolSize: number;
|
|
391
394
|
minedAt: string;
|
|
@@ -414,6 +417,7 @@ export declare const QuestionPoolSnapshotSchema: z.ZodObject<{
|
|
|
414
417
|
}[];
|
|
415
418
|
}[];
|
|
416
419
|
runId?: string | undefined;
|
|
420
|
+
intentText?: string | undefined;
|
|
417
421
|
}>;
|
|
418
422
|
export declare const QuestionDetectionSchema: z.ZodObject<{
|
|
419
423
|
/** Which preset mode generated this question. */
|
|
@@ -438,6 +442,8 @@ export declare const QuestionDetectionSchema: z.ZodObject<{
|
|
|
438
442
|
minedAt: z.ZodString;
|
|
439
443
|
/** Discovery run that produced the pool, when known. */
|
|
440
444
|
runId: z.ZodOptional<z.ZodString>;
|
|
445
|
+
/** Intent payload snippet (≤160 chars) — reused by chained questions' evidence chips. */
|
|
446
|
+
intentText: z.ZodOptional<z.ZodString>;
|
|
441
447
|
/** The discriminator this question asks about. */
|
|
442
448
|
discriminator: z.ZodObject<{
|
|
443
449
|
label: z.ZodString;
|
|
@@ -552,6 +558,7 @@ export declare const QuestionDetectionSchema: z.ZodObject<{
|
|
|
552
558
|
}[];
|
|
553
559
|
}[];
|
|
554
560
|
runId?: string | undefined;
|
|
561
|
+
intentText?: string | undefined;
|
|
555
562
|
}, {
|
|
556
563
|
poolSize: number;
|
|
557
564
|
minedAt: string;
|
|
@@ -580,6 +587,7 @@ export declare const QuestionDetectionSchema: z.ZodObject<{
|
|
|
580
587
|
}[];
|
|
581
588
|
}[];
|
|
582
589
|
runId?: string | undefined;
|
|
590
|
+
intentText?: string | undefined;
|
|
583
591
|
}>>;
|
|
584
592
|
}, "strip", z.ZodTypeAny, {
|
|
585
593
|
mode: "intent" | "chat" | "enrichment" | "discovery" | "negotiation" | "negotiation_inflight" | "pool_discovery";
|
|
@@ -616,6 +624,7 @@ export declare const QuestionDetectionSchema: z.ZodObject<{
|
|
|
616
624
|
}[];
|
|
617
625
|
}[];
|
|
618
626
|
runId?: string | undefined;
|
|
627
|
+
intentText?: string | undefined;
|
|
619
628
|
} | undefined;
|
|
620
629
|
}, {
|
|
621
630
|
mode: "intent" | "chat" | "enrichment" | "discovery" | "negotiation" | "negotiation_inflight" | "pool_discovery";
|
|
@@ -652,6 +661,7 @@ export declare const QuestionDetectionSchema: z.ZodObject<{
|
|
|
652
661
|
}[];
|
|
653
662
|
}[];
|
|
654
663
|
runId?: string | undefined;
|
|
664
|
+
intentText?: string | undefined;
|
|
655
665
|
} | undefined;
|
|
656
666
|
}>;
|
|
657
667
|
export declare const QuestionActorSchema: z.ZodObject<{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"question.schema.d.ts","sourceRoot":"/","sources":["shared/schemas/question.schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,oBAAoB;IAC/B,+EAA+E;;IAE/E,iFAAiF;;;;;;;;EAEjF,CAAC;AAEH,eAAO,MAAM,cAAc;IACzB,+EAA+E;;IAE/E,yDAAyD;;IAEzD,6EAA6E;;QAX7E,+EAA+E;;QAE/E,iFAAiF;;;;;;;;;IAWjF,0EAA0E;;IAE1E;;;;OAIG;;;;;;;;;;;;;;;;;;;;EAEH,CAAC;AAEH,eAAO,MAAM,sBAAsB,oIAMjC,CAAC;AAEH,eAAO,MAAM,0BAA0B;IAxBrC,+EAA+E;;IAE/E,yDAAyD;;IAEzD,6EAA6E;;QAX7E,+EAA+E;;QAE/E,iFAAiF;;;;;;;;;IAWjF,0EAA0E;;IAE1E;;;;OAIG;;;;;;;;;;;;;;;;;;;;;;;;EAcH,CAAC;AAEH,eAAO,MAAM,+BAA+B;;QA5B1C,+EAA+E;;QAE/E,yDAAyD;;QAEzD,6EAA6E;;YAX7E,+EAA+E;;YAE/E,iFAAiF;;;;;;;;;QAWjF,0EAA0E;;QAE1E;;;;WAIG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkBH,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAClE,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AACtD,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AACtE,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAC9E,MAAM,MAAM,yBAAyB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,+BAA+B,CAAC,CAAC;AAExF;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACvC,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,UAAU,EAAE,gBAAgB,EAAE,CAAC;CAChC;AAID,eAAO,MAAM,kBAAkB,mHAa7B,CAAC;AAEH,+EAA+E;AAC/E,eAAO,MAAM,4BAA4B;;;;;;;;;EAGvC,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,+BAA+B;;;;IAI1C,gDAAgD;;;;IAIhD,wDAAwD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAExD,CAAC;AAEH,2EAA2E;AAC3E,eAAO,MAAM,0BAA0B;;IAErC,6CAA6C;;IAE7C,wDAAwD;;IAExD,kDAAkD;;;;;
|
|
1
|
+
{"version":3,"file":"question.schema.d.ts","sourceRoot":"/","sources":["shared/schemas/question.schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -88,6 +88,8 @@ export const QuestionPoolSnapshotSchema = z.object({
|
|
|
88
88
|
minedAt: z.string().min(1),
|
|
89
89
|
/** Discovery run that produced the pool, when known. */
|
|
90
90
|
runId: z.string().optional(),
|
|
91
|
+
/** Intent payload snippet (≤160 chars) — reused by chained questions' evidence chips. */
|
|
92
|
+
intentText: z.string().optional(),
|
|
91
93
|
/** The discriminator this question asks about. */
|
|
92
94
|
discriminator: QuestionPoolDiscriminatorSchema,
|
|
93
95
|
/** Remaining ranked discriminators for interview-mode chaining. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"question.schema.js","sourceRoot":"/","sources":["shared/schemas/question.schema.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Question — public structured shape consumed by frontend renderers and MCP\n * elicitation dispatch. Mirrors the brainstorming AskUserQuestion skill so a\n * Question can be rendered identically across surfaces.\n *\n * `QuestionWithStrategy` extends the public shape with an internal `strategy`\n * tag used by the generator's guardrails (dedup/diversity) and recorded in\n * `debugMeta`. The tag is stripped before the public payload leaves the\n * generator — users never see it.\n */\nimport { z } from \"zod\";\n\nexport const QuestionOptionSchema = z.object({\n /** Display text. Suffix \" (Recommended)\" on the safest path; list it first. */\n label: z.string().min(1).max(120),\n /** Explains the consequence of choosing this option, not just its definition. */\n description: z.string().min(1).max(280),\n});\n\nexport const QuestionSchema = z.object({\n /** ≤12 chars. Noun of the decision domain — e.g. \"Stage\", \"Timing\", \"Role\". */\n title: z.string().min(1).max(12),\n /** ≤2 sentences, ≤400 chars. Ends in a question mark. */\n prompt: z.string().min(1).max(400),\n /** 2–4 options. No explicit \"Other\" — clients provide that automatically. */\n options: z.array(QuestionOptionSchema).min(2).max(4),\n /** True when options are not mutually exclusive (priorities, bundles). */\n multiSelect: z.boolean(),\n /**\n * Optional provenance line rendered as a muted chip above the prompt\n * (e.g. \"based on 18 people matching this intent\"). Aggregate counts only —\n * never individual identities (pool_discovery k-anonymity invariant).\n */\n evidence: z.string().min(1).max(160).optional(),\n});\n\nexport const QuestionStrategySchema = z.enum([\n \"refine_intent\",\n \"surface_missing_detail\",\n \"open_adjacent_thread\",\n \"reflective_summary\",\n \"surface_emergent_knowledge\",\n]);\n\nexport const QuestionWithStrategySchema = QuestionSchema.extend({\n strategy: QuestionStrategySchema,\n});\n\nexport const QuestionGeneratorResponseSchema = z.object({\n questions: z.array(QuestionWithStrategySchema).max(3),\n});\n\nexport type QuestionOption = z.infer<typeof QuestionOptionSchema>;\nexport type Question = z.infer<typeof QuestionSchema>;\nexport type QuestionStrategy = z.infer<typeof QuestionStrategySchema>;\nexport type QuestionWithStrategy = z.infer<typeof QuestionWithStrategySchema>;\nexport type QuestionGeneratorResponse = z.infer<typeof QuestionGeneratorResponseSchema>;\n\n/**\n * Internal generator output: public questions plus a parallel strategies\n * array for debug-only consumption. The generator emits this; callers\n * forward `questions` to renderers and `strategies` to `debugMeta` only.\n */\nexport interface QuestionGenerationResult {\n questions: Question[];\n strategies: QuestionStrategy[];\n}\n\n// ─── Persistence types (opportunity-style composable jsonb) ──────────────────\n\nexport const QuestionModeSchema = z.enum([\n \"discovery\",\n \"intent\",\n \"enrichment\",\n \"negotiation\",\n // Negotiator-initiated mid-negotiation client questions (ask_user action, P3).\n // Distinct from \"negotiation\", which covers post-stall questions only.\n \"negotiation_inflight\",\n // Orchestrator-initiated mid-conversation questions (ask_user_question tool).\n \"chat\",\n // Pool-discriminator questions mined from the intent's candidate pool\n // (IND-418). Synthesized deterministically — no generator LLM call.\n \"pool_discovery\",\n]);\n\n/** One server-side candidate→side assignment (never serialized to clients). */\nexport const QuestionPoolAssignmentSchema = z.object({\n opportunityId: z.string().min(1),\n side: z.string().min(1),\n});\n\n/**\n * One mined discriminator carried inside a pool_discovery question's\n * detection (the asked one plus ranked alternates for interview-mode\n * chaining). INTERNAL — the read path strips `detection.pool` before any\n * payload leaves the server.\n */\nexport const QuestionPoolDiscriminatorSchema = z.object({\n label: z.string().min(1),\n questionSeed: z.string().min(1),\n sides: z.array(z.string().min(1)).min(2).max(3),\n /** Verified-assignment count per side label. */\n sideCounts: z.record(z.string(), z.number()),\n voi: z.number(),\n evidenceRate: z.number(),\n /** Verified assignments only — the P3 re-rank input. */\n assignments: z.array(QuestionPoolAssignmentSchema),\n});\n\n/** Pool snapshot stored on pool_discovery questions (server-side only). */\nexport const QuestionPoolSnapshotSchema = z.object({\n poolSize: z.number().int().min(0),\n /** ISO-8601 timestamp of the mining pass. */\n minedAt: z.string().min(1),\n /** Discovery run that produced the pool, when known. */\n runId: z.string().optional(),\n /** The discriminator this question asks about. */\n discriminator: QuestionPoolDiscriminatorSchema,\n /** Remaining ranked discriminators for interview-mode chaining. */\n alternates: z.array(QuestionPoolDiscriminatorSchema),\n});\n\nexport const QuestionDetectionSchema = z.object({\n /** Which preset mode generated this question. */\n mode: QuestionModeSchema,\n /** Entity type that triggered generation (e.g. \"opportunity\", \"intent\", \"profile\"). */\n sourceType: z.string().min(1),\n /** ID of the triggering entity. */\n sourceId: z.string().min(1),\n /** Optional intent ID that was the root cause. */\n triggeredBy: z.string().optional(),\n /** ISO-8601 timestamp of generation. */\n timestamp: z.string().min(1),\n /** ID of the assistant message that triggered this question. Used by the frontend to anchor the question card inline. */\n messageId: z.string().optional(),\n /**\n * pool_discovery only: the mined pool snapshot (assignments + alternates).\n * INTERNAL — stripped from every client-facing read (web + MCP).\n */\n pool: QuestionPoolSnapshotSchema.optional(),\n});\n\nexport const QuestionActorSchema = z.object({\n /** The user this question is for. */\n userId: z.string().min(1),\n /** Optional network context. */\n networkId: z.string().optional(),\n /** Actor's role in the question — currently always \"subject\". */\n role: z.literal(\"subject\"),\n});\n\nexport const QuestionAnswerSchema = z.object({\n /** Option labels the user selected. */\n selectedOptions: z.array(z.string()),\n /** Free-text input when the user chose \"Other\" or elaborated. */\n freeText: z.string().optional(),\n /** User ID of the answerer. */\n answeredBy: z.string().min(1),\n /** ISO-8601 timestamp of when the answer was submitted. */\n answeredAt: z.string().min(1),\n});\n\nexport type QuestionMode = z.infer<typeof QuestionModeSchema>;\nexport type QuestionDetection = z.infer<typeof QuestionDetectionSchema>;\nexport type QuestionActor = z.infer<typeof QuestionActorSchema>;\nexport type QuestionAnswer = z.infer<typeof QuestionAnswerSchema>;\nexport type QuestionPoolAssignment = z.infer<typeof QuestionPoolAssignmentSchema>;\nexport type QuestionPoolDiscriminator = z.infer<typeof QuestionPoolDiscriminatorSchema>;\nexport type QuestionPoolSnapshot = z.infer<typeof QuestionPoolSnapshotSchema>;\n"]}
|
|
1
|
+
{"version":3,"file":"question.schema.js","sourceRoot":"/","sources":["shared/schemas/question.schema.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Question — public structured shape consumed by frontend renderers and MCP\n * elicitation dispatch. Mirrors the brainstorming AskUserQuestion skill so a\n * Question can be rendered identically across surfaces.\n *\n * `QuestionWithStrategy` extends the public shape with an internal `strategy`\n * tag used by the generator's guardrails (dedup/diversity) and recorded in\n * `debugMeta`. The tag is stripped before the public payload leaves the\n * generator — users never see it.\n */\nimport { z } from \"zod\";\n\nexport const QuestionOptionSchema = z.object({\n /** Display text. Suffix \" (Recommended)\" on the safest path; list it first. */\n label: z.string().min(1).max(120),\n /** Explains the consequence of choosing this option, not just its definition. */\n description: z.string().min(1).max(280),\n});\n\nexport const QuestionSchema = z.object({\n /** ≤12 chars. Noun of the decision domain — e.g. \"Stage\", \"Timing\", \"Role\". */\n title: z.string().min(1).max(12),\n /** ≤2 sentences, ≤400 chars. Ends in a question mark. */\n prompt: z.string().min(1).max(400),\n /** 2–4 options. No explicit \"Other\" — clients provide that automatically. */\n options: z.array(QuestionOptionSchema).min(2).max(4),\n /** True when options are not mutually exclusive (priorities, bundles). */\n multiSelect: z.boolean(),\n /**\n * Optional provenance line rendered as a muted chip above the prompt\n * (e.g. \"based on 18 people matching this intent\"). Aggregate counts only —\n * never individual identities (pool_discovery k-anonymity invariant).\n */\n evidence: z.string().min(1).max(160).optional(),\n});\n\nexport const QuestionStrategySchema = z.enum([\n \"refine_intent\",\n \"surface_missing_detail\",\n \"open_adjacent_thread\",\n \"reflective_summary\",\n \"surface_emergent_knowledge\",\n]);\n\nexport const QuestionWithStrategySchema = QuestionSchema.extend({\n strategy: QuestionStrategySchema,\n});\n\nexport const QuestionGeneratorResponseSchema = z.object({\n questions: z.array(QuestionWithStrategySchema).max(3),\n});\n\nexport type QuestionOption = z.infer<typeof QuestionOptionSchema>;\nexport type Question = z.infer<typeof QuestionSchema>;\nexport type QuestionStrategy = z.infer<typeof QuestionStrategySchema>;\nexport type QuestionWithStrategy = z.infer<typeof QuestionWithStrategySchema>;\nexport type QuestionGeneratorResponse = z.infer<typeof QuestionGeneratorResponseSchema>;\n\n/**\n * Internal generator output: public questions plus a parallel strategies\n * array for debug-only consumption. The generator emits this; callers\n * forward `questions` to renderers and `strategies` to `debugMeta` only.\n */\nexport interface QuestionGenerationResult {\n questions: Question[];\n strategies: QuestionStrategy[];\n}\n\n// ─── Persistence types (opportunity-style composable jsonb) ──────────────────\n\nexport const QuestionModeSchema = z.enum([\n \"discovery\",\n \"intent\",\n \"enrichment\",\n \"negotiation\",\n // Negotiator-initiated mid-negotiation client questions (ask_user action, P3).\n // Distinct from \"negotiation\", which covers post-stall questions only.\n \"negotiation_inflight\",\n // Orchestrator-initiated mid-conversation questions (ask_user_question tool).\n \"chat\",\n // Pool-discriminator questions mined from the intent's candidate pool\n // (IND-418). Synthesized deterministically — no generator LLM call.\n \"pool_discovery\",\n]);\n\n/** One server-side candidate→side assignment (never serialized to clients). */\nexport const QuestionPoolAssignmentSchema = z.object({\n opportunityId: z.string().min(1),\n side: z.string().min(1),\n});\n\n/**\n * One mined discriminator carried inside a pool_discovery question's\n * detection (the asked one plus ranked alternates for interview-mode\n * chaining). INTERNAL — the read path strips `detection.pool` before any\n * payload leaves the server.\n */\nexport const QuestionPoolDiscriminatorSchema = z.object({\n label: z.string().min(1),\n questionSeed: z.string().min(1),\n sides: z.array(z.string().min(1)).min(2).max(3),\n /** Verified-assignment count per side label. */\n sideCounts: z.record(z.string(), z.number()),\n voi: z.number(),\n evidenceRate: z.number(),\n /** Verified assignments only — the P3 re-rank input. */\n assignments: z.array(QuestionPoolAssignmentSchema),\n});\n\n/** Pool snapshot stored on pool_discovery questions (server-side only). */\nexport const QuestionPoolSnapshotSchema = z.object({\n poolSize: z.number().int().min(0),\n /** ISO-8601 timestamp of the mining pass. */\n minedAt: z.string().min(1),\n /** Discovery run that produced the pool, when known. */\n runId: z.string().optional(),\n /** Intent payload snippet (≤160 chars) — reused by chained questions' evidence chips. */\n intentText: z.string().optional(),\n /** The discriminator this question asks about. */\n discriminator: QuestionPoolDiscriminatorSchema,\n /** Remaining ranked discriminators for interview-mode chaining. */\n alternates: z.array(QuestionPoolDiscriminatorSchema),\n});\n\nexport const QuestionDetectionSchema = z.object({\n /** Which preset mode generated this question. */\n mode: QuestionModeSchema,\n /** Entity type that triggered generation (e.g. \"opportunity\", \"intent\", \"profile\"). */\n sourceType: z.string().min(1),\n /** ID of the triggering entity. */\n sourceId: z.string().min(1),\n /** Optional intent ID that was the root cause. */\n triggeredBy: z.string().optional(),\n /** ISO-8601 timestamp of generation. */\n timestamp: z.string().min(1),\n /** ID of the assistant message that triggered this question. Used by the frontend to anchor the question card inline. */\n messageId: z.string().optional(),\n /**\n * pool_discovery only: the mined pool snapshot (assignments + alternates).\n * INTERNAL — stripped from every client-facing read (web + MCP).\n */\n pool: QuestionPoolSnapshotSchema.optional(),\n});\n\nexport const QuestionActorSchema = z.object({\n /** The user this question is for. */\n userId: z.string().min(1),\n /** Optional network context. */\n networkId: z.string().optional(),\n /** Actor's role in the question — currently always \"subject\". */\n role: z.literal(\"subject\"),\n});\n\nexport const QuestionAnswerSchema = z.object({\n /** Option labels the user selected. */\n selectedOptions: z.array(z.string()),\n /** Free-text input when the user chose \"Other\" or elaborated. */\n freeText: z.string().optional(),\n /** User ID of the answerer. */\n answeredBy: z.string().min(1),\n /** ISO-8601 timestamp of when the answer was submitted. */\n answeredAt: z.string().min(1),\n});\n\nexport type QuestionMode = z.infer<typeof QuestionModeSchema>;\nexport type QuestionDetection = z.infer<typeof QuestionDetectionSchema>;\nexport type QuestionActor = z.infer<typeof QuestionActorSchema>;\nexport type QuestionAnswer = z.infer<typeof QuestionAnswerSchema>;\nexport type QuestionPoolAssignment = z.infer<typeof QuestionPoolAssignmentSchema>;\nexport type QuestionPoolDiscriminator = z.infer<typeof QuestionPoolDiscriminatorSchema>;\nexport type QuestionPoolSnapshot = z.infer<typeof QuestionPoolSnapshotSchema>;\n"]}
|