@indexnetwork/protocol 4.10.0-rc.350.1 → 4.12.0-rc.352.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 (30) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/intent/intent.graph.d.ts +12 -5
  3. package/dist/intent/intent.graph.d.ts.map +1 -1
  4. package/dist/intent/intent.graph.js +19 -6
  5. package/dist/intent/intent.graph.js.map +1 -1
  6. package/dist/opportunity/discriminator/discriminator.question.d.ts +2 -0
  7. package/dist/opportunity/discriminator/discriminator.question.d.ts.map +1 -1
  8. package/dist/opportunity/discriminator/discriminator.question.js +3 -0
  9. package/dist/opportunity/discriminator/discriminator.question.js.map +1 -1
  10. package/dist/opportunity/discriminator/discriminator.shadow.d.ts +8 -0
  11. package/dist/opportunity/discriminator/discriminator.shadow.d.ts.map +1 -1
  12. package/dist/opportunity/discriminator/discriminator.shadow.js +41 -7
  13. package/dist/opportunity/discriminator/discriminator.shadow.js.map +1 -1
  14. package/dist/opportunity/discriminator/discriminator.types.d.ts +4 -0
  15. package/dist/opportunity/discriminator/discriminator.types.d.ts.map +1 -1
  16. package/dist/opportunity/discriminator/discriminator.types.js.map +1 -1
  17. package/dist/opportunity/opportunity.tools.d.ts.map +1 -1
  18. package/dist/opportunity/opportunity.tools.js +19 -9
  19. package/dist/opportunity/opportunity.tools.js.map +1 -1
  20. package/dist/questioner/questioner.types.d.ts +3 -1
  21. package/dist/questioner/questioner.types.d.ts.map +1 -1
  22. package/dist/questioner/questioner.types.js.map +1 -1
  23. package/dist/shared/interfaces/database.interface.d.ts +2 -0
  24. package/dist/shared/interfaces/database.interface.d.ts.map +1 -1
  25. package/dist/shared/interfaces/database.interface.js.map +1 -1
  26. package/dist/shared/schemas/question.schema.d.ts +74 -0
  27. package/dist/shared/schemas/question.schema.d.ts.map +1 -1
  28. package/dist/shared/schemas/question.schema.js +6 -0
  29. package/dist/shared/schemas/question.schema.js.map +1 -1
  30. package/package.json +1 -1
@@ -12,6 +12,14 @@ export interface DiscriminatorShadowInput {
12
12
  * sentences. An axis semantically equal to any reference scores ~0.
13
13
  */
14
14
  referenceTexts: string[];
15
+ /** Legacy/model-mismatched resolved axes re-embedded with an independent budget. */
16
+ priorReferenceTexts?: string[];
17
+ /** Fresh resolved-axis vectors generated by the current embedding model. */
18
+ priorReferenceEmbeddings?: number[][];
19
+ /** Model used for current axis embeddings and persisted metadata. */
20
+ embeddingModel?: string;
21
+ /** Retain generated axis vectors on results for durable question snapshots. */
22
+ retainEmbeddings?: boolean;
15
23
  miner: Pick<PoolDiscriminatorMiner, "mine">;
16
24
  embedder: EmbeddingGenerator;
17
25
  signal?: AbortSignal;
@@ -1 +1 @@
1
- {"version":3,"file":"discriminator.shadow.d.ts","sourceRoot":"/","sources":["opportunity/discriminator/discriminator.shadow.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,+CAA+C,CAAC;AACxF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAEvE,OAAO,KAAK,EAAsB,aAAa,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AAO7G,gDAAgD;AAChD,MAAM,WAAW,wBAAwB;IACvC,yEAAyE;IACzE,UAAU,EAAE,MAAM,CAAC;IACnB,wDAAwD;IACxD,UAAU,EAAE,aAAa,EAAE,CAAC;IAC5B;;;OAGG;IACH,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,KAAK,EAAE,IAAI,CAAC,sBAAsB,EAAE,MAAM,CAAC,CAAC;IAC5C,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAOD;;;;GAIG;AACH,wBAAsB,0BAA0B,CAAC,KAAK,EAAE,wBAAwB,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAmCpH"}
1
+ {"version":3,"file":"discriminator.shadow.d.ts","sourceRoot":"/","sources":["opportunity/discriminator/discriminator.shadow.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,+CAA+C,CAAC;AACxF,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAEvE,OAAO,KAAK,EAAsB,aAAa,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AAS7G,gDAAgD;AAChD,MAAM,WAAW,wBAAwB;IACvC,yEAAyE;IACzE,UAAU,EAAE,MAAM,CAAC;IACnB,wDAAwD;IACxD,UAAU,EAAE,aAAa,EAAE,CAAC;IAC5B;;;OAGG;IACH,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,oFAAoF;IACpF,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,4EAA4E;IAC5E,wBAAwB,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC;IACtC,qEAAqE;IACrE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,+EAA+E;IAC/E,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,KAAK,EAAE,IAAI,CAAC,sBAAsB,EAAE,MAAM,CAAC,CAAC;IAC5C,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAOD;;;;GAIG;AACH,wBAAsB,0BAA0B,CAAC,KAAK,EAAE,wBAAwB,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAoEpH"}
@@ -6,8 +6,10 @@
6
6
  import { protocolLogger } from "../../shared/observability/protocol.logger.js";
7
7
  import { computeNovelty, scoreDiscriminator } from "./discriminator.scorer.js";
8
8
  const logger = protocolLogger("PoolDiscriminatorShadow");
9
- /** Max reference texts embedded for novelty (premises + intent sentences). */
9
+ /** Max text/vector references compared for novelty. */
10
10
  const MAX_REFERENCE_TEXTS = 24;
11
+ const MAX_PRIOR_REFERENCE_TEXTS = 24;
12
+ const MAX_REFERENCE_EMBEDDINGS = 24;
11
13
  /** Text embedded per discriminator for the novelty comparison. */
12
14
  function discriminatorEmbeddingText(d) {
13
15
  return `${d.label} — ${d.questionSeed}`;
@@ -27,14 +29,36 @@ export async function runPoolDiscriminatorShadow(input) {
27
29
  .map((t) => t.trim())
28
30
  .filter((t) => t.length > 0)
29
31
  .slice(0, MAX_REFERENCE_TEXTS);
32
+ const priorReferenceTexts = (input.priorReferenceTexts ?? [])
33
+ .map((text) => text.trim())
34
+ .filter((text) => text.length > 0)
35
+ .slice(0, MAX_PRIOR_REFERENCE_TEXTS);
36
+ const priorReferenceEmbeddings = (input.priorReferenceEmbeddings ?? [])
37
+ .filter((embedding) => embedding.length > 0)
38
+ .slice(0, MAX_REFERENCE_EMBEDDINGS);
30
39
  let novelties = mined.map(() => 1);
31
- if (references.length > 0) {
40
+ let discriminatorEmbeddings = null;
41
+ const shouldEmbed = input.retainEmbeddings
42
+ || references.length > 0
43
+ || priorReferenceTexts.length > 0
44
+ || priorReferenceEmbeddings.length > 0;
45
+ if (shouldEmbed) {
32
46
  try {
33
- const texts = [...mined.map(discriminatorEmbeddingText), ...references];
47
+ const texts = [
48
+ ...mined.map(discriminatorEmbeddingText),
49
+ ...references,
50
+ ...priorReferenceTexts,
51
+ ];
34
52
  const embeddings = (await input.embedder.generate(texts));
35
- const discriminatorEmbeddings = embeddings.slice(0, mined.length);
36
- const referenceEmbeddings = embeddings.slice(mined.length);
37
- novelties = discriminatorEmbeddings.map((e) => computeNovelty(e, referenceEmbeddings));
53
+ if (embeddings.length !== texts.length || embeddings.some((embedding) => !Array.isArray(embedding) || embedding.length === 0)) {
54
+ throw new Error("Embedding provider returned an invalid batch");
55
+ }
56
+ discriminatorEmbeddings = embeddings.slice(0, mined.length);
57
+ const referenceEmbeddings = [
58
+ ...priorReferenceEmbeddings,
59
+ ...embeddings.slice(mined.length),
60
+ ];
61
+ novelties = discriminatorEmbeddings.map((embedding) => computeNovelty(embedding, referenceEmbeddings));
38
62
  }
39
63
  catch (err) {
40
64
  logger.warn("Novelty embedding failed; defaulting novelty to 1", {
@@ -43,7 +67,17 @@ export async function runPoolDiscriminatorShadow(input) {
43
67
  }
44
68
  }
45
69
  const discriminators = mined
46
- .map((d, i) => scoreDiscriminator(d, candidates, novelties[i]))
70
+ .map((d, i) => {
71
+ const scored = scoreDiscriminator(d, candidates, novelties[i]);
72
+ const embedding = input.retainEmbeddings ? discriminatorEmbeddings?.[i] : undefined;
73
+ return embedding
74
+ ? {
75
+ ...scored,
76
+ embedding,
77
+ ...(input.embeddingModel ? { embeddingModel: input.embeddingModel } : {}),
78
+ }
79
+ : scored;
80
+ })
47
81
  .sort((a, b) => b.voi - a.voi);
48
82
  return { poolSize: candidates.length, discriminators };
49
83
  }
@@ -1 +1 @@
1
- {"version":3,"file":"discriminator.shadow.js","sourceRoot":"/","sources":["opportunity/discriminator/discriminator.shadow.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shadow orchestrator: mine discriminators for a pool, embed them, score VoI, and\n * return the log payload (IND-417). No persistence, no questions, no UI —\n * P1 output is consumed only by structured logs for human review.\n */\nimport { protocolLogger } from \"../../shared/observability/protocol.logger.js\";\nimport type { EmbeddingGenerator } from \"../../shared/interfaces/embedder.interface.js\";\nimport type { PoolDiscriminatorMiner } from \"./discriminator.miner.js\";\nimport { computeNovelty, scoreDiscriminator } from \"./discriminator.scorer.js\";\nimport type { MinedDiscriminator, PoolCandidate, DiscriminatorShadowResult } from \"./discriminator.types.js\";\n\nconst logger = protocolLogger(\"PoolDiscriminatorShadow\");\n\n/** Max reference texts embedded for novelty (premises + intent sentences). */\nconst MAX_REFERENCE_TEXTS = 24;\n\n/** Input for one shadow mining+scoring pass. */\nexport interface DiscriminatorShadowInput {\n /** Intent payload (+ summary) or search query that produced the pool. */\n intentText: string;\n /** The pool (already filtered/capped by the caller). */\n candidates: PoolCandidate[];\n /**\n * Novelty references: the intent owner's active premise texts and intent\n * sentences. An axis semantically equal to any reference scores ~0.\n */\n referenceTexts: string[];\n miner: Pick<PoolDiscriminatorMiner, \"mine\">;\n embedder: EmbeddingGenerator;\n signal?: AbortSignal;\n}\n\n/** Text embedded per discriminator for the novelty comparison. */\nfunction discriminatorEmbeddingText(d: MinedDiscriminator): string {\n return `${d.label} — ${d.questionSeed}`;\n}\n\n/**\n * Runs miner → embeddings → scorer. Throws only when *mining* fails (callers\n * are fire-and-forget); embedding failures degrade to novelty = 1 for all\n * discriminators rather than dropping the pass.\n */\nexport async function runPoolDiscriminatorShadow(input: DiscriminatorShadowInput): Promise<DiscriminatorShadowResult> {\n const { candidates } = input;\n const mined = await input.miner.mine(\n { intentText: input.intentText, candidates },\n input.signal ? { signal: input.signal } : undefined,\n );\n if (mined.length === 0) {\n return { poolSize: candidates.length, discriminators: [] };\n }\n\n const references = input.referenceTexts\n .map((t) => t.trim())\n .filter((t) => t.length > 0)\n .slice(0, MAX_REFERENCE_TEXTS);\n\n let novelties: number[] = mined.map(() => 1);\n if (references.length > 0) {\n try {\n const texts = [...mined.map(discriminatorEmbeddingText), ...references];\n const embeddings = (await input.embedder.generate(texts)) as number[][];\n const discriminatorEmbeddings = embeddings.slice(0, mined.length);\n const referenceEmbeddings = embeddings.slice(mined.length);\n novelties = discriminatorEmbeddings.map((e) => computeNovelty(e, referenceEmbeddings));\n } catch (err) {\n logger.warn(\"Novelty embedding failed; defaulting novelty to 1\", {\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n const discriminators = mined\n .map((d, i) => scoreDiscriminator(d, candidates, novelties[i]))\n .sort((a, b) => b.voi - a.voi);\n\n return { poolSize: candidates.length, discriminators };\n}\n"]}
1
+ {"version":3,"file":"discriminator.shadow.js","sourceRoot":"/","sources":["opportunity/discriminator/discriminator.shadow.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shadow orchestrator: mine discriminators for a pool, embed them, score VoI, and\n * return the log payload (IND-417). No persistence, no questions, no UI —\n * P1 output is consumed only by structured logs for human review.\n */\nimport { protocolLogger } from \"../../shared/observability/protocol.logger.js\";\nimport type { EmbeddingGenerator } from \"../../shared/interfaces/embedder.interface.js\";\nimport type { PoolDiscriminatorMiner } from \"./discriminator.miner.js\";\nimport { computeNovelty, scoreDiscriminator } from \"./discriminator.scorer.js\";\nimport type { MinedDiscriminator, PoolCandidate, DiscriminatorShadowResult } from \"./discriminator.types.js\";\n\nconst logger = protocolLogger(\"PoolDiscriminatorShadow\");\n\n/** Max text/vector references compared for novelty. */\nconst MAX_REFERENCE_TEXTS = 24;\nconst MAX_PRIOR_REFERENCE_TEXTS = 24;\nconst MAX_REFERENCE_EMBEDDINGS = 24;\n\n/** Input for one shadow mining+scoring pass. */\nexport interface DiscriminatorShadowInput {\n /** Intent payload (+ summary) or search query that produced the pool. */\n intentText: string;\n /** The pool (already filtered/capped by the caller). */\n candidates: PoolCandidate[];\n /**\n * Novelty references: the intent owner's active premise texts and intent\n * sentences. An axis semantically equal to any reference scores ~0.\n */\n referenceTexts: string[];\n /** Legacy/model-mismatched resolved axes re-embedded with an independent budget. */\n priorReferenceTexts?: string[];\n /** Fresh resolved-axis vectors generated by the current embedding model. */\n priorReferenceEmbeddings?: number[][];\n /** Model used for current axis embeddings and persisted metadata. */\n embeddingModel?: string;\n /** Retain generated axis vectors on results for durable question snapshots. */\n retainEmbeddings?: boolean;\n miner: Pick<PoolDiscriminatorMiner, \"mine\">;\n embedder: EmbeddingGenerator;\n signal?: AbortSignal;\n}\n\n/** Text embedded per discriminator for the novelty comparison. */\nfunction discriminatorEmbeddingText(d: MinedDiscriminator): string {\n return `${d.label} — ${d.questionSeed}`;\n}\n\n/**\n * Runs miner → embeddings → scorer. Throws only when *mining* fails (callers\n * are fire-and-forget); embedding failures degrade to novelty = 1 for all\n * discriminators rather than dropping the pass.\n */\nexport async function runPoolDiscriminatorShadow(input: DiscriminatorShadowInput): Promise<DiscriminatorShadowResult> {\n const { candidates } = input;\n const mined = await input.miner.mine(\n { intentText: input.intentText, candidates },\n input.signal ? { signal: input.signal } : undefined,\n );\n if (mined.length === 0) {\n return { poolSize: candidates.length, discriminators: [] };\n }\n\n const references = input.referenceTexts\n .map((t) => t.trim())\n .filter((t) => t.length > 0)\n .slice(0, MAX_REFERENCE_TEXTS);\n\n const priorReferenceTexts = (input.priorReferenceTexts ?? [])\n .map((text) => text.trim())\n .filter((text) => text.length > 0)\n .slice(0, MAX_PRIOR_REFERENCE_TEXTS);\n const priorReferenceEmbeddings = (input.priorReferenceEmbeddings ?? [])\n .filter((embedding) => embedding.length > 0)\n .slice(0, MAX_REFERENCE_EMBEDDINGS);\n\n let novelties: number[] = mined.map(() => 1);\n let discriminatorEmbeddings: number[][] | null = null;\n const shouldEmbed = input.retainEmbeddings\n || references.length > 0\n || priorReferenceTexts.length > 0\n || priorReferenceEmbeddings.length > 0;\n if (shouldEmbed) {\n try {\n const texts = [\n ...mined.map(discriminatorEmbeddingText),\n ...references,\n ...priorReferenceTexts,\n ];\n const embeddings = (await input.embedder.generate(texts)) as number[][];\n if (embeddings.length !== texts.length || embeddings.some((embedding) => !Array.isArray(embedding) || embedding.length === 0)) {\n throw new Error(\"Embedding provider returned an invalid batch\");\n }\n discriminatorEmbeddings = embeddings.slice(0, mined.length);\n const referenceEmbeddings = [\n ...priorReferenceEmbeddings,\n ...embeddings.slice(mined.length),\n ];\n novelties = discriminatorEmbeddings.map((embedding) => computeNovelty(embedding, referenceEmbeddings));\n } catch (err) {\n logger.warn(\"Novelty embedding failed; defaulting novelty to 1\", {\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n\n const discriminators = mined\n .map((d, i) => {\n const scored = scoreDiscriminator(d, candidates, novelties[i]);\n const embedding = input.retainEmbeddings ? discriminatorEmbeddings?.[i] : undefined;\n return embedding\n ? {\n ...scored,\n embedding,\n ...(input.embeddingModel ? { embeddingModel: input.embeddingModel } : {}),\n }\n : scored;\n })\n .sort((a, b) => b.voi - a.voi);\n\n return { poolSize: candidates.length, discriminators };\n}\n"]}
@@ -70,6 +70,10 @@ export interface MinedDiscriminator {
70
70
  }
71
71
  /** A mined discriminator with its deterministic VoI score components. */
72
72
  export interface ScoredDiscriminator extends MinedDiscriminator {
73
+ /** Current discriminator embedding retained for durable semantic dedup. */
74
+ embedding?: number[];
75
+ /** Model that generated {@link embedding}. */
76
+ embeddingModel?: string;
73
77
  /** Normalized score-weighted entropy over sides, in [0,1]. */
74
78
  entropy: number;
75
79
  /** Assigned score mass / total pool score mass, in [0,1]. */
@@ -1 +1 @@
1
- {"version":3,"file":"discriminator.types.d.ts","sourceRoot":"/","sources":["opportunity/discriminator/discriminator.types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,8DAA8D;AAC9D,MAAM,WAAW,aAAa;IAC5B,gEAAgE;IAChE,EAAE,EAAE,MAAM,CAAC;IACX;;;;OAIG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB,6EAA6E;IAC7E,KAAK,EAAE,MAAM,CAAC;CACf;AAED,0CAA0C;AAC1C,MAAM,WAAW,wBAAwB;IACvC,gFAAgF;IAChF,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,aAAa,EAAE,CAAC;CAC7B;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,kCAAkC;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,iFAAiF;IACjF,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,4EAA4E;IAC5E,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;;OAGG;IACH,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,yEAAyE;AACzE,MAAM,WAAW,kBAAkB;IACjC,iFAAiF;IACjF,KAAK,EAAE,MAAM,CAAC;IACd,+EAA+E;IAC/E,YAAY,EAAE,MAAM,CAAC;IACrB,0CAA0C;IAC1C,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,4CAA4C;IAC5C,WAAW,EAAE,kBAAkB,EAAE,CAAC;IAClC;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,yEAAyE;AACzE,MAAM,WAAW,mBAAoB,SAAQ,kBAAkB;IAC7D,8DAA8D;IAC9D,OAAO,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,QAAQ,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,OAAO,EAAE,MAAM,CAAC;IAChB,wCAAwC;IACxC,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wEAAwE;AACxE,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,cAAc,EAAE,mBAAmB,EAAE,CAAC;CACvC"}
1
+ {"version":3,"file":"discriminator.types.d.ts","sourceRoot":"/","sources":["opportunity/discriminator/discriminator.types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,8DAA8D;AAC9D,MAAM,WAAW,aAAa;IAC5B,gEAAgE;IAChE,EAAE,EAAE,MAAM,CAAC;IACX;;;;OAIG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB,6EAA6E;IAC7E,KAAK,EAAE,MAAM,CAAC;CACf;AAED,0CAA0C;AAC1C,MAAM,WAAW,wBAAwB;IACvC,gFAAgF;IAChF,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,aAAa,EAAE,CAAC;CAC7B;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,kCAAkC;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,iFAAiF;IACjF,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,4EAA4E;IAC5E,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;;OAGG;IACH,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,yEAAyE;AACzE,MAAM,WAAW,kBAAkB;IACjC,iFAAiF;IACjF,KAAK,EAAE,MAAM,CAAC;IACd,+EAA+E;IAC/E,YAAY,EAAE,MAAM,CAAC;IACrB,0CAA0C;IAC1C,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,4CAA4C;IAC5C,WAAW,EAAE,kBAAkB,EAAE,CAAC;IAClC;;;OAGG;IACH,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,yEAAyE;AACzE,MAAM,WAAW,mBAAoB,SAAQ,kBAAkB;IAC7D,2EAA2E;IAC3E,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,8CAA8C;IAC9C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8DAA8D;IAC9D,OAAO,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,QAAQ,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,OAAO,EAAE,MAAM,CAAC;IAChB,wCAAwC;IACxC,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wEAAwE;AACxE,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,cAAc,EAAE,mBAAmB,EAAE,CAAC;CACvC"}
@@ -1 +1 @@
1
- {"version":3,"file":"discriminator.types.js","sourceRoot":"/","sources":["opportunity/discriminator/discriminator.types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG","sourcesContent":["/**\n * Pool discriminator mining — shared types (IND-416 / IND-417).\n *\n * A \"pool discriminator\" is a preference dimension that splits a discovery-run\n * candidate pool into meaningfully different groups (e.g. \"hands-on builders\n * vs advisors\"). Discriminators are mined by one structured LLM pass, then\n * scored deterministically (VoI = entropy × coverage^1.5 × novelty) so the\n * highest value question can eventually be asked to the intent owner.\n *\n * Vocabulary note: the LLM wire format (prompt + response schema in the miner)\n * speaks of \"axes\" with mutually exclusive \"sides\" — the clearest way to\n * explain the concept to the model. Everything the rest of the codebase\n * touches (types, exports, logs) uses \"discriminator\".\n *\n * P1 (shadow) uses these types for log-only output; later phases reuse them\n * for question synthesis and answer application.\n */\n\n/** One candidate in the pool as supplied to the miner LLM. */\nexport interface PoolCandidate {\n /** Opportunity id (stable key for later answer application). */\n id: string;\n /**\n * The exact public-context string shown to the LLM for this candidate\n * (name + bio + matchReason + headline + premise snippets, ≤400 chars).\n * Evidence spans are substring-verified against this exact string.\n */\n publicContext: string;\n /** Candidate confidence/score — the mass used for score-weighted entropy. */\n score: number;\n}\n\n/** Input envelope for one mining pass. */\nexport interface DiscriminatorMiningInput {\n /** Intent payload (+ summary) or ad-hoc search query that produced the pool. */\n intentText: string;\n candidates: PoolCandidate[];\n}\n\n/**\n * One candidate assignment on a discriminator, after code-side evidence verification.\n * `side === null` means unknown (LLM abstained, evidence failed verification,\n * or the candidate was missing from the LLM output).\n */\nexport interface VerifiedAssignment {\n /** Candidate (opportunity) id. */\n id: string;\n /** Verified side label (one of the discriminator's sides), or null = unknown. */\n side: string | null;\n /** The evidence span quoted by the LLM (kept for logging/audit), if any. */\n evidence: string | null;\n /**\n * True when the LLM proposed a side AND its evidence span substring-matched\n * the candidate's publicContext. False for demoted-to-unknown proposals.\n */\n verified: boolean;\n}\n\n/** One mined discriminator after evidence verification (pre-scoring). */\nexport interface MinedDiscriminator {\n /** Short discriminator label, e.g. \"Hands-on builders vs strategic advisors\". */\n label: string;\n /** A question the intent owner could be asked to resolve the discriminator. */\n questionSeed: string;\n /** 2–3 mutually exclusive side labels. */\n sides: string[];\n /** Exactly one entry per pool candidate. */\n assignments: VerifiedAssignment[];\n /**\n * verified-proposals / total side proposals from the LLM for this discriminator\n * (0 when the LLM proposed no sides at all). The hallucination health metric.\n */\n evidenceRate: number;\n}\n\n/** A mined discriminator with its deterministic VoI score components. */\nexport interface ScoredDiscriminator extends MinedDiscriminator {\n /** Normalized score-weighted entropy over sides, in [0,1]. */\n entropy: number;\n /** Assigned score mass / total pool score mass, in [0,1]. */\n coverage: number;\n /** 1 − max cosine similarity vs reference texts (premises/intent), in [0,1]. */\n novelty: number;\n /** entropy × coverage^1.5 × novelty. */\n voi: number;\n}\n\n/** Result of one shadow mining+scoring pass (the log payload shape). */\nexport interface DiscriminatorShadowResult {\n poolSize: number;\n /** Scored discriminators, sorted by VoI descending. */\n discriminators: ScoredDiscriminator[];\n}\n"]}
1
+ {"version":3,"file":"discriminator.types.js","sourceRoot":"/","sources":["opportunity/discriminator/discriminator.types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG","sourcesContent":["/**\n * Pool discriminator mining — shared types (IND-416 / IND-417).\n *\n * A \"pool discriminator\" is a preference dimension that splits a discovery-run\n * candidate pool into meaningfully different groups (e.g. \"hands-on builders\n * vs advisors\"). Discriminators are mined by one structured LLM pass, then\n * scored deterministically (VoI = entropy × coverage^1.5 × novelty) so the\n * highest value question can eventually be asked to the intent owner.\n *\n * Vocabulary note: the LLM wire format (prompt + response schema in the miner)\n * speaks of \"axes\" with mutually exclusive \"sides\" — the clearest way to\n * explain the concept to the model. Everything the rest of the codebase\n * touches (types, exports, logs) uses \"discriminator\".\n *\n * P1 (shadow) uses these types for log-only output; later phases reuse them\n * for question synthesis and answer application.\n */\n\n/** One candidate in the pool as supplied to the miner LLM. */\nexport interface PoolCandidate {\n /** Opportunity id (stable key for later answer application). */\n id: string;\n /**\n * The exact public-context string shown to the LLM for this candidate\n * (name + bio + matchReason + headline + premise snippets, ≤400 chars).\n * Evidence spans are substring-verified against this exact string.\n */\n publicContext: string;\n /** Candidate confidence/score — the mass used for score-weighted entropy. */\n score: number;\n}\n\n/** Input envelope for one mining pass. */\nexport interface DiscriminatorMiningInput {\n /** Intent payload (+ summary) or ad-hoc search query that produced the pool. */\n intentText: string;\n candidates: PoolCandidate[];\n}\n\n/**\n * One candidate assignment on a discriminator, after code-side evidence verification.\n * `side === null` means unknown (LLM abstained, evidence failed verification,\n * or the candidate was missing from the LLM output).\n */\nexport interface VerifiedAssignment {\n /** Candidate (opportunity) id. */\n id: string;\n /** Verified side label (one of the discriminator's sides), or null = unknown. */\n side: string | null;\n /** The evidence span quoted by the LLM (kept for logging/audit), if any. */\n evidence: string | null;\n /**\n * True when the LLM proposed a side AND its evidence span substring-matched\n * the candidate's publicContext. False for demoted-to-unknown proposals.\n */\n verified: boolean;\n}\n\n/** One mined discriminator after evidence verification (pre-scoring). */\nexport interface MinedDiscriminator {\n /** Short discriminator label, e.g. \"Hands-on builders vs strategic advisors\". */\n label: string;\n /** A question the intent owner could be asked to resolve the discriminator. */\n questionSeed: string;\n /** 2–3 mutually exclusive side labels. */\n sides: string[];\n /** Exactly one entry per pool candidate. */\n assignments: VerifiedAssignment[];\n /**\n * verified-proposals / total side proposals from the LLM for this discriminator\n * (0 when the LLM proposed no sides at all). The hallucination health metric.\n */\n evidenceRate: number;\n}\n\n/** A mined discriminator with its deterministic VoI score components. */\nexport interface ScoredDiscriminator extends MinedDiscriminator {\n /** Current discriminator embedding retained for durable semantic dedup. */\n embedding?: number[];\n /** Model that generated {@link embedding}. */\n embeddingModel?: string;\n /** Normalized score-weighted entropy over sides, in [0,1]. */\n entropy: number;\n /** Assigned score mass / total pool score mass, in [0,1]. */\n coverage: number;\n /** 1 − max cosine similarity vs reference texts (premises/intent), in [0,1]. */\n novelty: number;\n /** entropy × coverage^1.5 × novelty. */\n voi: number;\n}\n\n/** Result of one shadow mining+scoring pass (the log payload shape). */\nexport interface DiscriminatorShadowResult {\n poolSize: number;\n /** Scored discriminators, sorted by VoI descending. */\n discriminators: ScoredDiscriminator[];\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"opportunity.tools.d.ts","sourceRoot":"/","sources":["opportunity/opportunity.tools.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"opportunity.tools.d.ts","sourceRoot":"/","sources":["opportunity/opportunity.tools.ts"],"names":[],"mappings":"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"}
@@ -552,6 +552,25 @@ export function createOpportunityTools(defineTool, deps) {
552
552
  if (effectiveIndexId && !UUID_REGEX.test(effectiveIndexId)) {
553
553
  return error("Invalid network ID format.");
554
554
  }
555
+ const contextIntentId = focusedIntentId(context);
556
+ const requestedIntentId = query.intentId?.trim() || undefined;
557
+ if (requestedIntentId != null && !UUID_REGEX.test(requestedIntentId)) {
558
+ return error("Invalid intent ID format.");
559
+ }
560
+ if (contextIntentId && requestedIntentId && requestedIntentId !== contextIntentId) {
561
+ return error("This chat is scoped to a different intent.");
562
+ }
563
+ const triggerIntentId = contextIntentId ?? requestedIntentId;
564
+ if (triggerIntentId) {
565
+ const triggerIntent = await systemDb.getIntent(triggerIntentId);
566
+ if (!triggerIntent || triggerIntent.userId !== context.userId) {
567
+ return error("Intent not found or you are not authorized to use it for discovery.");
568
+ }
569
+ if (triggerIntent.archivedAt ||
570
+ (triggerIntent.status != null && triggerIntent.status !== 'ACTIVE')) {
571
+ return error("This intent is not active. Resume it before starting discovery.");
572
+ }
573
+ }
555
574
  if (context.isMcp && deps.discoveryRuns && deps.discoveryRunQueue) {
556
575
  // Coalesce: if an equivalent discovery is already queued/running for this
557
576
  // user, return that run instead of spawning a duplicate. An over-eager
@@ -921,15 +940,6 @@ export function createOpportunityTools(defineTool, deps) {
921
940
  const toolDebugSteps = [
922
941
  { step: "resolve_index_scope", detail: `${indexScope.length} index(es)` },
923
942
  ];
924
- const contextIntentId = focusedIntentId(context);
925
- const requestedIntentId = query.intentId?.trim() || undefined;
926
- if (requestedIntentId != null && !UUID_REGEX.test(requestedIntentId)) {
927
- return error("Invalid intent ID format.");
928
- }
929
- if (contextIntentId && requestedIntentId && requestedIntentId !== contextIntentId) {
930
- return error("This chat is scoped to a different intent.");
931
- }
932
- const triggerIntentId = contextIntentId ?? requestedIntentId;
933
943
  if (query.introTargetUserId?.trim() && query.introTargetUserId.trim() === context.userId) {
934
944
  return error("You cannot discover introductions for yourself. Try regular discovery instead.");
935
945
  }