@duckcodeailabs/dql-agent 1.14.2 → 1.14.4

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 (196) hide show
  1. package/dist/agent-run-engine.d.ts +239 -4
  2. package/dist/agent-run-engine.d.ts.map +1 -1
  3. package/dist/agent-run-engine.js +2924 -85
  4. package/dist/agent-run-engine.js.map +1 -1
  5. package/dist/agent-run-gates.d.ts.map +1 -1
  6. package/dist/agent-run-gates.js +51 -3
  7. package/dist/agent-run-gates.js.map +1 -1
  8. package/dist/agent-run-planner.d.ts +6 -0
  9. package/dist/agent-run-planner.d.ts.map +1 -1
  10. package/dist/agent-run-planner.js +2 -0
  11. package/dist/agent-run-planner.js.map +1 -1
  12. package/dist/agent-run-store.d.ts.map +1 -1
  13. package/dist/agent-run-store.js +591 -11
  14. package/dist/agent-run-store.js.map +1 -1
  15. package/dist/agentic/analyst-loop.d.ts +9 -1
  16. package/dist/agentic/analyst-loop.d.ts.map +1 -1
  17. package/dist/agentic/analyst-loop.js +204 -4
  18. package/dist/agentic/analyst-loop.js.map +1 -1
  19. package/dist/agentic/assumptions.d.ts +1 -1
  20. package/dist/agentic/assumptions.d.ts.map +1 -1
  21. package/dist/agentic/assumptions.js.map +1 -1
  22. package/dist/agentic/ledger-tools.d.ts.map +1 -1
  23. package/dist/agentic/ledger-tools.js +8 -1
  24. package/dist/agentic/ledger-tools.js.map +1 -1
  25. package/dist/agentic/orchestrator-policy.d.ts +3 -1
  26. package/dist/agentic/orchestrator-policy.d.ts.map +1 -1
  27. package/dist/agentic/orchestrator-policy.js +1 -1
  28. package/dist/agentic/orchestrator-policy.js.map +1 -1
  29. package/dist/agentic/research-agent.d.ts.map +1 -1
  30. package/dist/agentic/research-agent.js +10 -1
  31. package/dist/agentic/research-agent.js.map +1 -1
  32. package/dist/agentic/sql-authorization.d.ts +8 -0
  33. package/dist/agentic/sql-authorization.d.ts.map +1 -1
  34. package/dist/agentic/sql-authorization.js +3 -0
  35. package/dist/agentic/sql-authorization.js.map +1 -1
  36. package/dist/agentic/tool-loop.d.ts +13 -1
  37. package/dist/agentic/tool-loop.d.ts.map +1 -1
  38. package/dist/agentic/tool-loop.js +441 -32
  39. package/dist/agentic/tool-loop.js.map +1 -1
  40. package/dist/analytical-compatibility.d.ts.map +1 -1
  41. package/dist/analytical-compatibility.js +8 -1
  42. package/dist/analytical-compatibility.js.map +1 -1
  43. package/dist/analytical-failure-repair.d.ts.map +1 -1
  44. package/dist/analytical-failure-repair.js +6 -2
  45. package/dist/analytical-failure-repair.js.map +1 -1
  46. package/dist/analytical-frame.d.ts +42 -1
  47. package/dist/analytical-frame.d.ts.map +1 -1
  48. package/dist/analytical-frame.js +490 -26
  49. package/dist/analytical-frame.js.map +1 -1
  50. package/dist/analytical-orchestration.d.ts +1259 -9
  51. package/dist/analytical-orchestration.d.ts.map +1 -1
  52. package/dist/analytical-orchestration.js +970 -84
  53. package/dist/analytical-orchestration.js.map +1 -1
  54. package/dist/answer-loop.d.ts +230 -10
  55. package/dist/answer-loop.d.ts.map +1 -1
  56. package/dist/answer-loop.js +1182 -85
  57. package/dist/answer-loop.js.map +1 -1
  58. package/dist/answer-shape.d.ts +27 -0
  59. package/dist/answer-shape.d.ts.map +1 -1
  60. package/dist/answer-shape.js +55 -0
  61. package/dist/answer-shape.js.map +1 -1
  62. package/dist/ask-observability/index.d.ts +11 -0
  63. package/dist/ask-observability/index.d.ts.map +1 -0
  64. package/dist/ask-observability/index.js +7 -0
  65. package/dist/ask-observability/index.js.map +1 -0
  66. package/dist/ask-observability/instrumentation.d.ts +35 -0
  67. package/dist/ask-observability/instrumentation.d.ts.map +1 -0
  68. package/dist/ask-observability/instrumentation.js +523 -0
  69. package/dist/ask-observability/instrumentation.js.map +1 -0
  70. package/dist/ask-observability/observer.d.ts +62 -0
  71. package/dist/ask-observability/observer.d.ts.map +1 -0
  72. package/dist/ask-observability/observer.js +537 -0
  73. package/dist/ask-observability/observer.js.map +1 -0
  74. package/dist/ask-observability/portable.d.ts +98 -0
  75. package/dist/ask-observability/portable.d.ts.map +1 -0
  76. package/dist/ask-observability/portable.js +1089 -0
  77. package/dist/ask-observability/portable.js.map +1 -0
  78. package/dist/ask-observability/store.d.ts +130 -0
  79. package/dist/ask-observability/store.d.ts.map +1 -0
  80. package/dist/ask-observability/store.js +1114 -0
  81. package/dist/ask-observability/store.js.map +1 -0
  82. package/dist/ask-observability/types.d.ts +380 -0
  83. package/dist/ask-observability/types.d.ts.map +1 -0
  84. package/dist/ask-observability/types.js +2 -0
  85. package/dist/ask-observability/types.js.map +1 -0
  86. package/dist/ask-observability/utils.d.ts +21 -0
  87. package/dist/ask-observability/utils.d.ts.map +1 -0
  88. package/dist/ask-observability/utils.js +102 -0
  89. package/dist/ask-observability/utils.js.map +1 -0
  90. package/dist/ask-runtime/ask-agent-runtime-v2.d.ts +850 -0
  91. package/dist/ask-runtime/ask-agent-runtime-v2.d.ts.map +1 -0
  92. package/dist/ask-runtime/ask-agent-runtime-v2.js +1716 -0
  93. package/dist/ask-runtime/ask-agent-runtime-v2.js.map +1 -0
  94. package/dist/ask-runtime/ask-analyst-runtime.d.ts +95 -0
  95. package/dist/ask-runtime/ask-analyst-runtime.d.ts.map +1 -0
  96. package/dist/ask-runtime/ask-analyst-runtime.js +8280 -0
  97. package/dist/ask-runtime/ask-analyst-runtime.js.map +1 -0
  98. package/dist/conversation/session-store.d.ts +31 -0
  99. package/dist/conversation/session-store.d.ts.map +1 -1
  100. package/dist/conversation/session-store.js +38 -0
  101. package/dist/conversation/session-store.js.map +1 -1
  102. package/dist/conversation/snapshot.d.ts +4 -1
  103. package/dist/conversation/snapshot.d.ts.map +1 -1
  104. package/dist/conversation/snapshot.js +85 -3
  105. package/dist/conversation/snapshot.js.map +1 -1
  106. package/dist/conversation/turn-trust.d.ts.map +1 -1
  107. package/dist/conversation/turn-trust.js +2 -0
  108. package/dist/conversation/turn-trust.js.map +1 -1
  109. package/dist/embeddings/provider.d.ts +1 -0
  110. package/dist/embeddings/provider.d.ts.map +1 -1
  111. package/dist/embeddings/provider.js +18 -0
  112. package/dist/embeddings/provider.js.map +1 -1
  113. package/dist/generated-analytical-proposal.d.ts +37 -1
  114. package/dist/generated-analytical-proposal.d.ts.map +1 -1
  115. package/dist/generated-analytical-proposal.js +246 -3
  116. package/dist/generated-analytical-proposal.js.map +1 -1
  117. package/dist/governed-relational-compiler.d.ts +15 -0
  118. package/dist/governed-relational-compiler.d.ts.map +1 -1
  119. package/dist/governed-relational-compiler.js +99 -1
  120. package/dist/governed-relational-compiler.js.map +1 -1
  121. package/dist/index.d.ts +21 -12
  122. package/dist/index.d.ts.map +1 -1
  123. package/dist/index.js +14 -7
  124. package/dist/index.js.map +1 -1
  125. package/dist/intent-controller.d.ts +87 -1
  126. package/dist/intent-controller.d.ts.map +1 -1
  127. package/dist/intent-controller.js +2 -2
  128. package/dist/intent-controller.js.map +1 -1
  129. package/dist/kg/build.js +32 -2
  130. package/dist/kg/build.js.map +1 -1
  131. package/dist/meaning-resolution.d.ts +207 -6
  132. package/dist/meaning-resolution.d.ts.map +1 -1
  133. package/dist/meaning-resolution.js +439 -53
  134. package/dist/meaning-resolution.js.map +1 -1
  135. package/dist/metadata/analysis-planner.d.ts.map +1 -1
  136. package/dist/metadata/analysis-planner.js +78 -7
  137. package/dist/metadata/analysis-planner.js.map +1 -1
  138. package/dist/metadata/catalog.d.ts +14 -0
  139. package/dist/metadata/catalog.d.ts.map +1 -1
  140. package/dist/metadata/catalog.js +29 -2
  141. package/dist/metadata/catalog.js.map +1 -1
  142. package/dist/metadata/meaning-evidence.d.ts +28 -2
  143. package/dist/metadata/meaning-evidence.d.ts.map +1 -1
  144. package/dist/metadata/meaning-evidence.js +373 -16
  145. package/dist/metadata/meaning-evidence.js.map +1 -1
  146. package/dist/plan-execution-adapter.d.ts +9 -1
  147. package/dist/plan-execution-adapter.d.ts.map +1 -1
  148. package/dist/plan-execution-adapter.js +93 -13
  149. package/dist/plan-execution-adapter.js.map +1 -1
  150. package/dist/provider-egress.d.ts +28 -11
  151. package/dist/provider-egress.d.ts.map +1 -1
  152. package/dist/provider-egress.js +72 -22
  153. package/dist/provider-egress.js.map +1 -1
  154. package/dist/providers/claude.d.ts +2 -2
  155. package/dist/providers/claude.d.ts.map +1 -1
  156. package/dist/providers/claude.js +201 -37
  157. package/dist/providers/claude.js.map +1 -1
  158. package/dist/providers/dispatch.d.ts +27 -1
  159. package/dist/providers/dispatch.d.ts.map +1 -1
  160. package/dist/providers/dispatch.js +63 -1
  161. package/dist/providers/dispatch.js.map +1 -1
  162. package/dist/providers/gemini.js +10 -10
  163. package/dist/providers/gemini.js.map +1 -1
  164. package/dist/providers/index.d.ts +2 -2
  165. package/dist/providers/index.d.ts.map +1 -1
  166. package/dist/providers/index.js +1 -1
  167. package/dist/providers/index.js.map +1 -1
  168. package/dist/providers/ollama.js +15 -15
  169. package/dist/providers/ollama.js.map +1 -1
  170. package/dist/providers/openai.d.ts +2 -2
  171. package/dist/providers/openai.d.ts.map +1 -1
  172. package/dist/providers/openai.js +213 -43
  173. package/dist/providers/openai.js.map +1 -1
  174. package/dist/providers/types.d.ts +131 -1
  175. package/dist/providers/types.d.ts.map +1 -1
  176. package/dist/providers/types.js.map +1 -1
  177. package/dist/relationship-proof.d.ts +81 -0
  178. package/dist/relationship-proof.d.ts.map +1 -1
  179. package/dist/relationship-proof.js +228 -4
  180. package/dist/relationship-proof.js.map +1 -1
  181. package/dist/requirement-clauses.d.ts +23 -0
  182. package/dist/requirement-clauses.d.ts.map +1 -0
  183. package/dist/requirement-clauses.js +70 -0
  184. package/dist/requirement-clauses.js.map +1 -0
  185. package/dist/resolved-analytical-plan.d.ts +18 -4
  186. package/dist/resolved-analytical-plan.d.ts.map +1 -1
  187. package/dist/resolved-analytical-plan.js +953 -50
  188. package/dist/resolved-analytical-plan.js.map +1 -1
  189. package/dist/router.d.ts +118 -2
  190. package/dist/router.d.ts.map +1 -1
  191. package/dist/router.js +2481 -232
  192. package/dist/router.js.map +1 -1
  193. package/dist/semantic-bridge/compose.d.ts.map +1 -1
  194. package/dist/semantic-bridge/compose.js +23 -4
  195. package/dist/semantic-bridge/compose.js.map +1 -1
  196. package/package.json +4 -4
@@ -11,7 +11,7 @@
11
11
  *
12
12
  * Acceptance: AGT-027..033, CTX-007, PERF-003, E2E-022.
13
13
  */
14
- import type { DqlArtifactExecutionReceipt } from '@duckcodeailabs/dql-core';
14
+ import type { AgentRunTelemetryV1, DqlArtifactExecutionReceipt } from '@duckcodeailabs/dql-core';
15
15
  export declare const ANALYTICAL_ORCHESTRATION_CONTRACT_VERSION: 1;
16
16
  export type AnalyticalTurnKind = 'conversation' | 'definition' | 'lookup' | 'ranking' | 'breakdown' | 'comparison' | 'drilldown' | 'diagnosis' | 'research' | 'compound' | 'clarification' | 'aggregation';
17
17
  export type AnalyticalTaskKind = 'definition' | 'aggregation' | 'ranking' | 'attribute_lookup' | 'breakdown' | 'comparison' | 'drilldown' | 'diagnosis' | 'research_branch';
@@ -74,14 +74,53 @@ export interface AnalyticalTaskV1 {
74
74
  source: 'conversation' | 'result' | 'user';
75
75
  }>;
76
76
  }
77
+ /**
78
+ * Trust projected for one task outcome. This is intentionally the same
79
+ * local-first vocabulary used by the canonical answer, but it is declared
80
+ * independently so task receipts remain readable without importing the run
81
+ * engine (and old JSON records remain valid).
82
+ */
83
+ export type AnalyticalTaskOutcomeTrustStateV1 = 'certified' | 'governed' | 'review_required' | 'blocked' | 'not_applicable';
84
+ /** Finalized state for one bounded Ask clause or Research branch. */
85
+ export type AnalyticalTaskOutcomeStatusV1 = 'completed' | 'partial' | 'gap' | 'blocked'
86
+ /** A child was deliberately not executed because its required parent failed. */
87
+ | 'dependency_blocked';
88
+ /** Typed, content-safe failure retained per task rather than collapsed into the root. */
89
+ export interface AnalyticalTaskFailureV1 {
90
+ version: 1;
91
+ code: string;
92
+ message: string;
93
+ phase: 'planning' | 'execution' | 'dependency';
94
+ }
77
95
  /** Durable, content-only outcome for one independent clause/branch. */
78
96
  export interface AnalyticalTaskOutcomeV1 {
79
97
  version: 1;
80
98
  taskId: string;
81
- status: 'completed' | 'partial' | 'gap' | 'blocked';
99
+ status: AnalyticalTaskOutcomeStatusV1;
100
+ /** Present once a compiler or executor established task-local provenance. */
101
+ trustState?: AnalyticalTaskOutcomeTrustStateV1;
82
102
  summary?: string;
83
103
  resultFingerprint?: string;
84
104
  gap?: AnalyticalCoverageGapV1;
105
+ /** Typed cause when the task did not produce an independent result. */
106
+ failure?: AnalyticalTaskFailureV1;
107
+ /** Parent task IDs that prevented this child from executing. */
108
+ dependencyTaskIds?: string[];
109
+ }
110
+ /**
111
+ * Additive turn-level task receipt for ordinary Ask. The run's historical
112
+ * terminal status stays wire-compatible; this summary distinguishes a
113
+ * completed, partial, or fully blocked multi-task answer without hiding any
114
+ * independently validated sibling result.
115
+ */
116
+ export interface AnalyticalTaskOutcomeSummaryV1 {
117
+ version: 1;
118
+ status: 'completed' | 'partial' | 'blocked';
119
+ trustState: AnalyticalTaskOutcomeTrustStateV1;
120
+ taskCount: number;
121
+ successfulTaskIds: string[];
122
+ failedTaskIds: string[];
123
+ dependencyBlockedTaskIds: string[];
85
124
  }
86
125
  export interface AnalyticalCoverageGapV1 {
87
126
  version: 1;
@@ -104,6 +143,13 @@ export interface AnalyticalCoverageGapV1 {
104
143
  * Acceptance: CTX-005, CTX-007, AGT-009, AGT-010.
105
144
  */
106
145
  export type EvidenceCandidateRoleV1 = 'metric' | 'entity_key' | 'entity_label' | 'categorical_dimension' | 'time_dimension' | 'member' | 'relationship' | 'context';
146
+ /**
147
+ * Content-safe statement of what the bounded planner package established for
148
+ * one requested role. `alternatives` deliberately means that qualified cards
149
+ * were retained for a user choice; it never claims the business meaning was
150
+ * proven merely because retrieval found related fields.
151
+ */
152
+ export type EvidenceRoleCoverageStateV1 = 'proven' | 'alternatives';
107
153
  /**
108
154
  * A typed, content-safe reading of the analytical requirements in a question.
109
155
  * It is advisory for retrieval/ranking only: the compatibility solver and the
@@ -116,6 +162,17 @@ export interface AnalyticalRequirementSetV1 {
116
162
  entityTerms: string[];
117
163
  entityDisplayTerms: string[];
118
164
  memberTerms: string[];
165
+ /**
166
+ * A host-validated predicate reconstructed from one stable prior result
167
+ * selection. This is execution context, not an LLM-selected meaning: the
168
+ * runtime keeps it through retrieval/planning so a deictic follow-up cannot
169
+ * widen back to the full warehouse after reload.
170
+ */
171
+ priorResultMemberBinding?: AnalyticalPriorResultMemberBindingV1;
172
+ /** Explicit projection fields are requirements, not optional prompt hints. */
173
+ outputTerms?: string[];
174
+ /** `individual` requests a row-level relation rather than an aggregate. */
175
+ grain?: 'individual' | 'aggregate';
119
176
  ranking?: {
120
177
  metricTerms: string[];
121
178
  entityTerms: string[];
@@ -123,15 +180,165 @@ export interface AnalyticalRequirementSetV1 {
123
180
  limit: number;
124
181
  /** True means the reader did not specify a count and DQL assumed 10. */
125
182
  defaultedLimit: boolean;
183
+ /** Per-group top-N ("top 2 per month") vs one overall ranking. */
184
+ scope?: 'overall' | 'per_group';
126
185
  };
127
186
  time?: {
128
187
  role: 'time_axis' | 'time_filter';
129
188
  grain?: 'day' | 'week' | 'month' | 'quarter' | 'year';
189
+ /**
190
+ * A bounded period the answer must be restricted to. This clause was
191
+ * previously UNREPRESENTABLE: "last two months" had no slot anywhere in
192
+ * the requirement layer, so it degraded into a grouping dimension while
193
+ * its count was misread as a row limit. A window is a restriction on
194
+ * WHEN, independent of whether the answer also groups by a grain.
195
+ */
196
+ window?: AnalyticalTimeWindowV1;
130
197
  fiscalPeriod?: string;
131
198
  /** A fiscal token is not executable until a declared calendar binds it. */
132
199
  requiresDeclaredFiscalCalendar: boolean;
133
200
  };
201
+ /**
202
+ * Where each clause came from, so runtime re-derivation can refresh a
203
+ * clause read from the current question without silently deleting one the
204
+ * user established earlier in the conversation or via a clarification.
205
+ */
206
+ clauseMeta?: {
207
+ time?: RequirementClauseMetaV1;
208
+ ranking?: RequirementClauseMetaV1;
209
+ };
210
+ }
211
+ /** A typed time restriction; `expression` is the canonical resolver input. */
212
+ export interface AnalyticalTimeWindowV1 {
213
+ version: 1;
214
+ kind: 'relative' | 'absolute' | 'named_period';
215
+ /** Canonical digits form accepted by `resolvePlanTimeRange`, e.g. "last 2 months". */
216
+ expression: string;
217
+ relative?: {
218
+ count: number;
219
+ unit: 'day' | 'week' | 'month' | 'quarter' | 'year';
220
+ /** True = complete calendar periods; false = trailing from now. */
221
+ complete: boolean;
222
+ };
223
+ absolute?: {
224
+ startInclusive: string;
225
+ endExclusive: string;
226
+ };
227
+ namedPeriod?: string;
134
228
  }
229
+ export type RequirementClauseProvenance = 'question' | 'inherited' | 'clarification' | 'defaulted';
230
+ export interface RequirementClauseMetaV1 {
231
+ provenance: RequirementClauseProvenance;
232
+ required: boolean;
233
+ sourceTurnId?: string;
234
+ }
235
+ /**
236
+ * Additive, host-owned representation of a selected value from a prior
237
+ * canonical result. It intentionally mirrors the engine boundary without
238
+ * importing that module, so analytical framing remains cycle-free.
239
+ */
240
+ export interface AnalyticalPriorResultMemberBindingV1 {
241
+ version: 1;
242
+ displayDimension: string;
243
+ values: string[];
244
+ sourceTurnId?: string;
245
+ resultFingerprint?: string;
246
+ }
247
+ /**
248
+ * Preserve a validated prior-result predicate as typed analytical context.
249
+ * The selected display key supplies the entity/display requirements needed to
250
+ * retrieve relationship closure; the literal values remain an immutable host
251
+ * filter and are never treated as a provider-selected member meaning.
252
+ */
253
+ export declare function withAnalyticalPriorResultMemberBinding(requirements: AnalyticalRequirementSetV1, binding: AnalyticalPriorResultMemberBindingV1 | undefined): AnalyticalRequirementSetV1;
254
+ /**
255
+ * Host-owned analytical input to the one bounded meaning call. The seed is
256
+ * built before any provider response and is the only source of explicit user
257
+ * requirements downstream. The model may bind supplied candidate IDs and
258
+ * explain ambiguity; it may not erase, add, or replace the request tuple.
259
+ *
260
+ * This is deliberately not an execution plan. It contains business terms and
261
+ * parsed filters only; the compatibility solver and immutable resolved plan
262
+ * still own qualified identifiers, joins, SQL, trust, and route selection.
263
+ */
264
+ export interface AnalyticalRequirementSeedV1 {
265
+ version: 1;
266
+ sourceQuestion: string;
267
+ requirements: AnalyticalRequirementSetV1;
268
+ queryIntent: {
269
+ measures: string[];
270
+ dimensions: string[];
271
+ filters: Array<{
272
+ field: string;
273
+ value: string;
274
+ }>;
275
+ timeRange?: string;
276
+ timeGrain?: string;
277
+ order?: 'asc' | 'desc';
278
+ limit?: number;
279
+ fiscalCalendarId?: string;
280
+ fiscalDateRoleId?: string;
281
+ };
282
+ }
283
+ /** Build the immutable host request tuple before a meaning model can respond. */
284
+ export declare function buildAnalyticalRequirementSeedV1(input: {
285
+ question: string;
286
+ parsedIntent?: Partial<{
287
+ measures: string[];
288
+ dimensions: string[];
289
+ filters: Array<{
290
+ field: string;
291
+ value: string;
292
+ }>;
293
+ timeRange: string;
294
+ timeGrain: string;
295
+ order: 'asc' | 'desc';
296
+ limit: number;
297
+ fiscalCalendarId: string;
298
+ fiscalDateRoleId: string;
299
+ }>;
300
+ requirements?: AnalyticalRequirementSetV1;
301
+ priorResultMemberBinding?: AnalyticalPriorResultMemberBindingV1;
302
+ fiscalCalendar?: {
303
+ id: string;
304
+ dateRoleId?: string;
305
+ fiscalPeriodFieldId?: string;
306
+ };
307
+ }): AnalyticalRequirementSeedV1;
308
+ type RetrievalParsedIntentRefinement = Partial<{
309
+ measures: string[];
310
+ dimensions: string[];
311
+ filters: Array<{
312
+ field: string;
313
+ value: string;
314
+ }>;
315
+ timeRange: string;
316
+ timeGrain: string;
317
+ order: 'asc' | 'desc';
318
+ limit: number;
319
+ fiscalCalendarId: string;
320
+ fiscalDateRoleId: string;
321
+ }>;
322
+ /**
323
+ * Return only parser refinements whose business words occur in the current
324
+ * source question. This deliberately does not try to recover previous turn
325
+ * context: continuation is represented by a server-issued structured choice
326
+ * and merged separately by the host. The helper is exported for regression
327
+ * tests and for router paths that construct a requirement set before a seed.
328
+ */
329
+ export declare function currentQuestionGroundedParsedIntent(question: string, parsedIntent: RetrievalParsedIntentRefinement | undefined): RetrievalParsedIntentRefinement | undefined;
330
+ /**
331
+ * Preserve a small set of explicit current-question literals even when a
332
+ * retriever did not emit a parser filter. This is deliberately not a value
333
+ * search or synonym engine: it records only quoted values, capitalized proper
334
+ * names, and values introduced by an explicit predicate phrase. The planner
335
+ * must still bind each term to an admitted, qualified member/dimension card
336
+ * before it can become an executable filter.
337
+ *
338
+ * Without this host-owned atom, "customers in Philadelphia" could reach a
339
+ * broad certified fit after retrieval silently omitted the parser filter.
340
+ */
341
+ export declare function currentQuestionLiteralMemberTerms(question: string): string[];
135
342
  export type ContextSourceCoverageStatusV1 = 'available' | 'empty' | 'stale' | 'unavailable' | 'errored' | 'skipped';
136
343
  /** Source coverage is distinct from a missing capability. A bounded package
137
344
  * may omit a relevant candidate; that is not proof that the source lacks it. */
@@ -172,6 +379,162 @@ export interface ExploratoryExecutionFreezeV1 {
172
379
  candidateIds: string[];
173
380
  /** The host minted one single-use capability before connector execution. */
174
381
  authorization: 'capability_minted';
382
+ /**
383
+ * Per-output proof emitted by the host SQL validator. When a frozen plan
384
+ * names explicit projected identifiers, a result is displayable only if the
385
+ * authorization receipt carries one exact physical source binding for each
386
+ * of them. Optional for pre-V4 persisted receipts; required for new
387
+ * exploratory execution with required outputs.
388
+ */
389
+ requiredOutputBindings?: ExploratoryRequiredOutputBindingProofV1[];
390
+ /**
391
+ * SQL authorization is distinct from the router plan freeze. Index zero is
392
+ * the first exact SQL handoff; index one is the only permitted same-plan
393
+ * correction after a retryable warehouse execution failure. Older receipts
394
+ * omit this additive field and are interpreted as the original handoff.
395
+ */
396
+ authorizationAttempt?: ExploratoryExecutionAuthorizationAttemptV1;
397
+ }
398
+ /**
399
+ * Host-owned proof that one output alias in the authorized SQL came from the
400
+ * exact physical source selected in the frozen analytical plan. The SQL text
401
+ * remains in the local execution boundary; this portable receipt carries only
402
+ * qualified identifiers and normalized relation/column names.
403
+ */
404
+ export interface ExploratoryRequiredOutputBindingProofV1 {
405
+ version: 1;
406
+ outputName: string;
407
+ qualifiedId: string;
408
+ relation: string;
409
+ column: string;
410
+ }
411
+ /**
412
+ * Server-owned lifecycle marker for an exploratory SQL capability. A repair
413
+ * does not reopen routing or meaning: it may only replace the SQL bytes while
414
+ * preserving the frozen plan, snapshot, target, candidate closure, and
415
+ * read-only validation proof.
416
+ */
417
+ export type ExploratoryExecutionAuthorizationAttemptV1 = {
418
+ version: 1;
419
+ index: 0;
420
+ parentSqlFingerprint?: never;
421
+ } | {
422
+ version: 1;
423
+ index: 1;
424
+ parentSqlFingerprint: string;
425
+ };
426
+ /**
427
+ * A host authorization attaches to a plan the router has already frozen. The
428
+ * plan freeze establishes the meaning, candidate closure, and source snapshot;
429
+ * this receipt establishes only the exact read-only SQL and live target. It
430
+ * is intentionally an alias of the existing wire shape so persisted V1/V3
431
+ * runs remain readable while callers stop treating authorization as the point
432
+ * at which a plan becomes frozen.
433
+ *
434
+ * Acceptance: AGT-029, AGT-031, AGT-034.
435
+ */
436
+ export type ExploratoryExecutionAuthorizationReceiptV1 = ExploratoryExecutionFreezeV1;
437
+ /** A content-safe, server-produced terminal incident for Ask observability. */
438
+ export interface AskTerminalIncidentV1 {
439
+ version: 1;
440
+ code: 'INTERNAL_EXPLORATORY_AUTHORIZATION_STATE_MISMATCH' | 'CONNECTION_NOT_CONFIGURED'
441
+ /** A frozen plan failed before any statement reached the warehouse. */
442
+ | 'COMPILATION_FAILED'
443
+ /** The executed rows did not satisfy the immutable frozen result contract. */
444
+ | 'RESULT_CONTRACT_MISMATCH' | 'ANALYTICAL_EXECUTION_FAILED' | 'ANALYTICAL_COVERAGE_GAP' | 'PROVIDER_FAILURE'
445
+ /** Every admitted Research branch used its bounded window without a finding. */
446
+ | 'RESEARCH_BRANCH_TIMEOUT'
447
+ /** Explicit Research exhausted its root deadline before finalization. */
448
+ | 'RESEARCH_RUN_DEADLINE' | 'CANCELLED';
449
+ boundary: 'plan.compile' | 'semantic.compile' | 'sql.authorize' | 'sql.execute' | 'result.validate' | 'provider' | 'cascade' | 'run';
450
+ origin: 'internal_invariant' | 'governance_gate' | 'semantic_compiler' | 'plan_compiler' | 'result_validator' | 'provider' | 'warehouse' | 'unknown';
451
+ impact: 'execution_not_attempted' | 'execution_failed' | 'answer_not_produced' | 'run_cancelled';
452
+ safeAction: 'export_redacted_trace' | 'configure_connection' | 'change_authorized_connection' | 'inspect_failure' | 'retry_same_plan' | 'refresh_snapshot' | 'edit_dql' | 'open_sql_notebook' | 'request_access' | 'reapply_semantic_runtime' | 'review_analytical_failure' | 'inspect_research_failures' | 'none';
453
+ }
454
+ /**
455
+ * A compact, producer-owned account of a completed-but-limited Research run.
456
+ *
457
+ * This is deliberately distinct from `AskTerminalIncidentV1`: the root Ask
458
+ * can retain a receipt-backed finding and its selected trust state while one
459
+ * or more independently bounded Research children failed, timed out, or were
460
+ * skipped. The summary carries only typed counts, reason codes, and frozen
461
+ * child-plan evidence; it never retains branch prompts, result rows, SQL, or
462
+ * provider content.
463
+ */
464
+ export interface AskResearchBranchSummaryV1 {
465
+ version: 1;
466
+ totalBranches: number;
467
+ /** Children that completed their bounded lifecycle. */
468
+ completedBranches: number;
469
+ /** Completed children with a persisted execution receipt in the V2 ledger. */
470
+ receiptBackedBranches: number;
471
+ failedBranches: number;
472
+ timedOutBranches: number;
473
+ skippedBranches: number;
474
+ /** True only when a receipt-backed finding survived alongside a limited child. */
475
+ partialSuccess: boolean;
476
+ failureReasons: Array<{
477
+ code: 'execution_failed' | 'research_branch_timeout' | 'budget_exhausted' | 'run_deadline' | 'cancelled';
478
+ branchCount: number;
479
+ }>;
480
+ /** Frozen child plans actually persisted by the Research root. */
481
+ availableChildPlans: Array<{
482
+ tier: Exclude<AnalyticalCascadeTierV1, 'clarify_or_gap'>;
483
+ frozenPlanCount: number;
484
+ branchCount: number;
485
+ reviewRequired: boolean;
486
+ }>;
487
+ /** Distinct child run IDs carried by durable branch receipts. */
488
+ linkedChildRunCount: number;
489
+ safeAction: 'inspect_research_failures';
490
+ }
491
+ /** One compact canonical story used by both the inspector and full trace. */
492
+ export interface AskDecisionSummaryV1 {
493
+ version: 1;
494
+ summaryFingerprint: string;
495
+ understoodRequest: {
496
+ measures: number;
497
+ dimensions: number;
498
+ entityRequested: boolean;
499
+ outputCount: number;
500
+ ranking?: {
501
+ direction: 'top' | 'bottom';
502
+ limit: number;
503
+ defaultedLimit: boolean;
504
+ };
505
+ conversationBinding: 'none' | 'structured_clarification' | 'prior_result' | 'task_dependency';
506
+ };
507
+ evidenceByRole: Array<{
508
+ role: EvidenceCandidateRoleV1;
509
+ candidateCount: number;
510
+ }>;
511
+ tierDecisions: Array<{
512
+ tier: AnalyticalCascadeTierV1;
513
+ outcome: AnalyticalCascadeTierOutcomeV1;
514
+ planFrozen: boolean;
515
+ }>;
516
+ selectedPlan?: {
517
+ tier: Exclude<AnalyticalCascadeTierV1, 'clarify_or_gap'>;
518
+ planFrozen: boolean;
519
+ reviewRequired: boolean;
520
+ };
521
+ terminalIncident?: AskTerminalIncidentV1;
522
+ /** Present for persisted Research branch evidence; does not change root status. */
523
+ researchBranchSummary?: AskResearchBranchSummaryV1;
524
+ safeNextAction: AskTerminalIncidentV1['safeAction'] | 'none';
525
+ }
526
+ /**
527
+ * A narrow, producer-owned terminal relationship witness carried with the
528
+ * authoritative cascade. It is deliberately enumerated rather than a copy
529
+ * of router prose: durable Ask receipts must explain an allocation/relationship
530
+ * block without persisting a question, candidate label, or inferred join.
531
+ */
532
+ export interface AnalyticalCascadeTerminalGapV1 {
533
+ version: 1;
534
+ code: 'MISSING_RELATIONSHIP';
535
+ requirement: 'certified_relationship_or_allocation_proof';
536
+ /** Qualified evidence IDs only; presentation never infers new paths. */
537
+ witnessCandidateIds: string[];
175
538
  }
176
539
  /**
177
540
  * The shared cascade receipt. This does not itself compile SQL; it prevents
@@ -187,6 +550,14 @@ export interface AnalyticalCascadeDecisionV1 {
187
550
  planFrozen: boolean;
188
551
  /** Present only after a selected exploratory proposal is host-authorized. */
189
552
  exploratoryExecutionFreeze?: ExploratoryExecutionFreezeV1;
553
+ /**
554
+ * Present only when one retryable warehouse failure received the sole
555
+ * permitted same-plan exploratory SQL repair authorization. The original
556
+ * receipt remains above so persisted evidence proves parent-before-repair.
557
+ */
558
+ exploratoryRepairExecutionFreeze?: ExploratoryExecutionFreezeV1;
559
+ /** Present only when the router supplied a typed, relationship-safe gap. */
560
+ terminalGap?: AnalyticalCascadeTerminalGapV1;
190
561
  stopReason: 'selected' | 'ambiguous' | 'coverage_gap' | 'denied' | 'post_freeze_failure';
191
562
  }
192
563
  export type ProviderFailureCauseV1 = 'authentication' | 'model_not_found' | 'rate_limited' | 'gateway' | 'network' | 'provider_timeout' | 'run_deadline' | 'admission_denied' | 'dispatch_budget' | 'cancelled' | 'unknown';
@@ -194,7 +565,7 @@ export type ProviderFailureCauseV1 = 'authentication' | 'model_not_found' | 'rat
194
565
  export interface ProviderFailureDiagnosticV1 {
195
566
  version: 1;
196
567
  cause: ProviderFailureCauseV1;
197
- phase: 'preflight' | 'meaning_resolution' | 'planning' | 'generation' | 'repair' | 'narration' | 'unknown';
568
+ phase: 'preflight' | 'classification' | 'meaning_resolution' | 'planning' | 'generation' | 'repair' | 'narration' | 'agent_control' | 'tool_followup' | 'unknown';
198
569
  retryable: boolean;
199
570
  safeAction: 'retry_same_provider' | 'fix_provider_configuration' | 'wait_and_retry' | 'inspect_run' | 'none';
200
571
  httpStatusClass?: '4xx' | '5xx';
@@ -211,11 +582,682 @@ export interface AgentRunDiagnosticReceiptV3 {
211
582
  runId: string;
212
583
  sourceCoverage: ContextSourceCoverageV1[];
213
584
  cascade?: AnalyticalCascadeDecisionV1;
585
+ /** Direct projection for run-detail consumers that do not traverse cascade. */
586
+ terminalGap?: AnalyticalCascadeTerminalGapV1;
214
587
  planFrozen: boolean;
215
588
  orchestrationMode?: 'legacy' | 'shadow' | 'agentic';
216
589
  provider?: ProviderFailureDiagnosticV1;
217
590
  finalStopReason: string;
218
591
  }
592
+ /**
593
+ * Additive canonical Ask story. V1/V2/V3 remain readable; this receipt is
594
+ * deliberately JSON-only so no metadata/index migration is needed.
595
+ */
596
+ export interface AgentRunDiagnosticReceiptV4 {
597
+ version: 4;
598
+ runId: string;
599
+ summary: AskDecisionSummaryV1;
600
+ terminalIncident?: AskTerminalIncidentV1;
601
+ finalStopReason: string;
602
+ }
603
+ /**
604
+ * Ask Analyst Runtime V1 contracts.
605
+ *
606
+ * These records deliberately separate an agent's business interpretation from
607
+ * the deterministic compiler/execution authority. They contain typed intent,
608
+ * stable candidate identities, and receipts — never prompts, provider
609
+ * responses, SQL text, result rows, credentials, or hidden reasoning.
610
+ *
611
+ * Acceptance: AGT-035..040, API-015, OBS-015, E2E-023.
612
+ */
613
+ export type AskAnalystRuntimeModeV1 = 'legacy' | 'shadow' | 'authoritative';
614
+ export interface BusinessQuestionFrameV3 {
615
+ version: 3;
616
+ /** Stable only within the persisted run; raw question text stays on AgentRun. */
617
+ questionFingerprint: string;
618
+ kind: AnalyticalTurnKind;
619
+ requirements: AnalyticalRequirementSetV1;
620
+ /** A source question supplied a top-N default; presentation must disclose it. */
621
+ defaultedTop?: {
622
+ limit: number;
623
+ };
624
+ conversation: {
625
+ binding: 'none' | 'structured_clarification' | 'prior_result' | 'task_dependency';
626
+ sourceTurnId?: string;
627
+ selectedStableId?: string;
628
+ };
629
+ }
630
+ export type AnalyticalHypothesisKindV1 = 'direct_answer' | 'trend' | 'comparison' | 'contributor' | 'anomaly' | 'freshness' | 'counter_evidence';
631
+ /** Agent-proposed question to test; deterministic execution validates it. */
632
+ export interface AnalyticalHypothesisV1 {
633
+ version: 1;
634
+ id: string;
635
+ kind: AnalyticalHypothesisKindV1;
636
+ taskId: string;
637
+ status: 'planned' | 'supported' | 'contradicted' | 'inconclusive' | 'failed' | 'skipped';
638
+ requiredRoles: EvidenceCandidateRoleV1[];
639
+ }
640
+ /** Bounded mission owned by the Ask runtime before a compiler is selected. */
641
+ export interface AnalyticalMissionV1 {
642
+ version: 1;
643
+ mode: 'ask' | 'research';
644
+ taskLimit: number;
645
+ planningContinuationLimit: number;
646
+ /**
647
+ * The ingress task graph exceeded this mission's bounded capacity. This is
648
+ * separate from `deferredTasks`: ordinary Ask must present a scope outcome
649
+ * before planning/execution rather than silently dropping clauses.
650
+ */
651
+ scopeOverflow?: boolean;
652
+ tasks: AnalyticalTaskV1[];
653
+ /**
654
+ * Ordinary Ask currently freezes one route-neutral executable program per
655
+ * turn. When ingress splits a compound request, retain the unexecuted
656
+ * clauses explicitly instead of silently running task-1 and losing the
657
+ * rest. Research owns the multi-branch execution contract.
658
+ */
659
+ deferredTasks?: Array<Pick<AnalyticalTaskV1, 'id' | 'kind'>>;
660
+ hypotheses: AnalyticalHypothesisV1[];
661
+ }
662
+ export interface EvidenceWorkspaceToolReceiptV1 {
663
+ version: 1;
664
+ id: string;
665
+ kind: 'retrieve_snapshot' | 'candidate_extension' | 'compiler_broker' | 'provider_meaning' | 'execute' | 'repair';
666
+ status: 'completed' | 'skipped' | 'failed';
667
+ candidateIds: string[];
668
+ reasonCode: string;
669
+ }
670
+ /** Same-snapshot evidence admission; excluded is never interpreted as absent. */
671
+ export interface EvidenceWorkspaceV1 {
672
+ version: 1;
673
+ snapshotId?: string;
674
+ sourceFingerprint?: string;
675
+ sourceCoverage: ContextSourceCoverageV1[];
676
+ /**
677
+ * Additive V2 admission projection. Legacy readers use
678
+ * `admittedCandidateIds`; new Ask runs retain the qualified 32-card
679
+ * execution workspace separately from the 16 cards released to the
680
+ * planner. Both are stable IDs from one immutable snapshot.
681
+ */
682
+ workspaceCandidateIds?: string[];
683
+ plannerCandidateIds?: string[];
684
+ admittedCandidateIds: string[];
685
+ excludedCandidates: Array<{
686
+ id: string;
687
+ reasonCode: 'role_cap' | 'incompatible' | 'ranking_conflict' | 'duplicate' | 'not_admitted';
688
+ }>;
689
+ tools: EvidenceWorkspaceToolReceiptV1[];
690
+ }
691
+ /**
692
+ * Route-neutral analytical intent. Certified, MetricFlow, governed
693
+ * relational, and exploratory SQL are all compilers of this one program.
694
+ */
695
+ export interface AnalyticalProgramV1 {
696
+ version: 1;
697
+ id: string;
698
+ frameFingerprint: string;
699
+ taskIds: string[];
700
+ /** Immutable selected evidence identities. Compilers may only consume these. */
701
+ candidateIds: string[];
702
+ /**
703
+ * Same-snapshot compiler context. This is deliberately separate from the
704
+ * bounded meaning cards: a physical relation/column closure may be needed
705
+ * for a pre-freeze fallback even when it was not sent to the meaning model.
706
+ * It is still immutable, target-scoped by the compiler, and never a license
707
+ * to retrieve or nominate a new business meaning.
708
+ */
709
+ executionCandidateIds?: string[];
710
+ requiredRoles: EvidenceCandidateRoleV1[];
711
+ /** Route-neutral predicate/member contract; never inferred by a compiler. */
712
+ filters: Array<{
713
+ fieldTerms: string[];
714
+ memberIds: string[];
715
+ /** Literal/member binding owned by the program, never guessed by a compiler. */
716
+ value: string;
717
+ operator: 'equals' | 'in' | 'between' | 'contains' | 'unknown';
718
+ }>;
719
+ ranking?: {
720
+ metricTerms: string[];
721
+ direction: 'asc' | 'desc';
722
+ limit: number;
723
+ defaultedLimit?: boolean;
724
+ };
725
+ time?: {
726
+ roleTerms: string[];
727
+ calendarId?: string;
728
+ fiscalPeriodTerms: string[];
729
+ grain?: NonNullable<AnalyticalRequirementSetV1['time']>['grain'];
730
+ };
731
+ comparison?: {
732
+ kind: 'none' | 'period_over_period' | 'segment' | 'baseline';
733
+ terms: string[];
734
+ };
735
+ /** Stable relationship evidence IDs required to combine selected objects. */
736
+ relationshipRequirements: string[];
737
+ outputs: {
738
+ measures: string[];
739
+ dimensions: string[];
740
+ entityDisplayTerms: string[];
741
+ timeGrain?: NonNullable<AnalyticalRequirementSetV1['time']>['grain'];
742
+ limit?: number;
743
+ assertions: Array<'all_requested_measures' | 'all_requested_dimensions' | 'safe_relationship_closure' | 'result_contract'>;
744
+ };
745
+ }
746
+ /** Runtime-owned selection receipt around the existing immutable RAP. */
747
+ export interface ResolvedAnalyticalPlanV2 {
748
+ version: 2;
749
+ programId: string;
750
+ compiler: 'certified' | 'metricflow' | 'governed_relational' | 'exploratory_sql' | 'none';
751
+ selectedTier?: Exclude<AnalyticalCascadeTierV1, 'clarify_or_gap'>;
752
+ planFrozen: boolean;
753
+ reviewRequired: boolean;
754
+ planFingerprint?: string;
755
+ }
756
+ /** Typed continuation material that survives reload without reparsing prose. */
757
+ export interface AskAnalystConversationDeltaV1 {
758
+ version: 1;
759
+ sourceQuestionFingerprint: string;
760
+ selectedStableId?: string;
761
+ selectedResultBindingId?: string;
762
+ partialFrame: Pick<BusinessQuestionFrameV3, 'kind' | 'requirements'>;
763
+ }
764
+ export interface AskAnalystStateV1 {
765
+ version: 1;
766
+ mode: AskAnalystRuntimeModeV1;
767
+ phase: 'framed' | 'evidence_ready' | 'program_ready' | 'compiled' | 'executed' | 'clarify' | 'blocked';
768
+ frame: BusinessQuestionFrameV3;
769
+ mission: AnalyticalMissionV1;
770
+ workspace: EvidenceWorkspaceV1;
771
+ program: AnalyticalProgramV1;
772
+ resolvedPlan?: ResolvedAnalyticalPlanV2;
773
+ conversationDelta: AskAnalystConversationDeltaV1;
774
+ planningContinuations: number;
775
+ toolCalls: number;
776
+ executionAttempts: number;
777
+ repairAttempts: number;
778
+ }
779
+ /** A fact-bound answer envelope. Narrative can only summarize these receipts. */
780
+ export interface BusinessAnswerV1 {
781
+ version: 1;
782
+ mode: 'facts_only' | 'deterministic_fallback';
783
+ trustState: 'certified' | 'governed' | 'review_required' | 'blocked' | 'not_applicable';
784
+ factIds: string[];
785
+ resultFingerprint?: string;
786
+ /** The accepted answer text, already visible in the corresponding artifact. */
787
+ answer?: string;
788
+ limitations: string[];
789
+ /** Additive per-task aggregate; omitted by legacy/single-task records. */
790
+ taskOutcomeSummary?: AnalyticalTaskOutcomeSummaryV1;
791
+ }
792
+ /**
793
+ * Content-free runtime projection for diagnostics/trace export. The durable
794
+ * local run retains typed continuation state; this projection intentionally
795
+ * omits raw question, requirement/member values, answer text, SQL, and rows.
796
+ */
797
+ export interface AskAnalystDiagnosticStateV1 {
798
+ version: 1;
799
+ mode: AskAnalystRuntimeModeV1;
800
+ phase: AskAnalystStateV1['phase'];
801
+ questionFingerprint: string;
802
+ kind: AnalyticalTurnKind;
803
+ requirementCounts: {
804
+ measures: number;
805
+ dimensions: number;
806
+ entityTerms: number;
807
+ members: number;
808
+ filters: number;
809
+ };
810
+ mission: {
811
+ mode: AnalyticalMissionV1['mode'];
812
+ taskCount: number;
813
+ deferredTaskCount: number;
814
+ hypothesisCount: number;
815
+ };
816
+ workspace: {
817
+ snapshotId?: string;
818
+ sourceFingerprint?: string;
819
+ admittedCandidateCount: number;
820
+ excludedCandidateCount: number;
821
+ sourceCoverage: Array<{
822
+ source: ContextSourceCoverageV1['source'];
823
+ status: ContextSourceCoverageV1['status'];
824
+ candidateCount: number;
825
+ }>;
826
+ tools: Array<Pick<EvidenceWorkspaceToolReceiptV1, 'id' | 'kind' | 'status' | 'reasonCode'>>;
827
+ };
828
+ program: {
829
+ id: string;
830
+ taskCount: number;
831
+ candidateCount: number;
832
+ requiredRoles: EvidenceCandidateRoleV1[];
833
+ outputAssertionCount: number;
834
+ };
835
+ resolvedPlan?: ResolvedAnalyticalPlanV2;
836
+ counters: {
837
+ planningContinuations: number;
838
+ toolCalls: number;
839
+ executionAttempts: number;
840
+ repairAttempts: number;
841
+ };
842
+ }
843
+ export interface BusinessAnswerDiagnosticProjectionV1 {
844
+ version: 1;
845
+ mode: BusinessAnswerV1['mode'];
846
+ trustState: BusinessAnswerV1['trustState'];
847
+ factIds: string[];
848
+ resultFingerprint?: string;
849
+ limitationCount: number;
850
+ }
851
+ /** Compact default trace story; advanced spans remain in local observability. */
852
+ export interface AskDecisionSummaryV2 {
853
+ version: 2;
854
+ summaryFingerprint: string;
855
+ runtimeMode: AskAnalystRuntimeModeV1;
856
+ whatHappened: string;
857
+ why: string;
858
+ impact: string;
859
+ nextAction: AskTerminalIncidentV1['safeAction'] | 'none';
860
+ selectedCompiler?: ResolvedAnalyticalPlanV2['compiler'];
861
+ programTaskCount: number;
862
+ admittedCandidateCount: number;
863
+ toolCallCount: number;
864
+ executionAttempts: number;
865
+ }
866
+ /** Additive V5 receipt; V1-V4 remain readable JSON records. */
867
+ export interface AgentRunDiagnosticReceiptV5 {
868
+ version: 5;
869
+ runId: string;
870
+ state: AskAnalystDiagnosticStateV1;
871
+ summary: AskDecisionSummaryV2;
872
+ businessAnswer?: BusinessAnswerDiagnosticProjectionV1;
873
+ /** Typed terminal provider evidence from the physical provider boundary. */
874
+ provider?: ProviderFailureDiagnosticV1;
875
+ finalStopReason: string;
876
+ }
877
+ /**
878
+ * Additive retrieval-first Ask contracts. V1 records remain the persisted
879
+ * compatibility shape; V2 is the authoritative runtime shape for new turns.
880
+ * The planner gets qualified cards only and cannot turn a raw retrieval term
881
+ * into an execution identity.
882
+ */
883
+ export type AskPlanningModeV1 = 'exact_fast_path' | 'initial_planner' | 'targeted_revision' | 'deterministic_binding';
884
+ export interface AnalyticalPlannerCandidateCardV1 {
885
+ version: 1;
886
+ id: string;
887
+ qualifiedId?: string;
888
+ /** Compact retrieval label/aliases; never a raw definition dump or row data. */
889
+ label?: string;
890
+ aliases?: string[];
891
+ roles: EvidenceCandidateRoleV1[];
892
+ source: ContextSourceCoverageV1['source'];
893
+ trustTier: 'certified' | 'semantic' | 'governed' | 'exploratory';
894
+ exactMatch: boolean;
895
+ /**
896
+ * The card was retained so the planner can resolve one otherwise-unmet
897
+ * business role. This is admission context only: it is not a declared
898
+ * alias, selected meaning, or execution authorization. The verifier must
899
+ * still prove an exact declaration or one unique inferred substitution.
900
+ */
901
+ admissionReasonCode?: 'candidate_for_unresolved_role';
902
+ unresolvedRoles?: EvidenceCandidateRoleV1[];
903
+ relationHints?: string[];
904
+ /** Present only for a host-authored relationship-path card; exploratory never implies governed authority. */
905
+ relationshipProofClass?: 'governed' | 'exploratory';
906
+ }
907
+ export interface AnalyticalPlannerRequestV1 {
908
+ version: 1;
909
+ planningMode: AskPlanningModeV1;
910
+ /** Raw business question is intentionally available only at the bounded planner boundary. */
911
+ question: string;
912
+ questionFingerprint: string;
913
+ /**
914
+ * Advisory frame for the planner. It is deliberately not an immutable
915
+ * execution tuple: parser-derived metric/entity/dimension guesses can be
916
+ * corrected only by selecting locally-qualified cards. Explicit user
917
+ * predicates, time, ranking and output constraints remain host verified.
918
+ */
919
+ frame: Pick<BusinessQuestionFrameV4, 'kind' | 'requirements' | 'conversation' | 'planningMode'>;
920
+ /** Host-owned, content-safe hints; they are advisory and never execution authority. */
921
+ advisoryHints: string[];
922
+ sourceCoverage: Array<Pick<ContextSourceCoverageV1, 'source' | 'status'>>;
923
+ /**
924
+ * Bounded server-derived task options. They are not an execution plan: the
925
+ * planner may select one compatible option or two/three independent options,
926
+ * and the verifier later requires every selected ID to freeze and execute.
927
+ */
928
+ taskOptions: Array<{
929
+ id: string;
930
+ kind: AnalyticalTaskV1['kind'];
931
+ question: string;
932
+ }>;
933
+ /**
934
+ * Present only for the one verifier-directed revision. Prior selected
935
+ * bindings are immutable context; only a card in `targetedCandidates` may
936
+ * fill the verifier-proven missing role.
937
+ */
938
+ priorProposal?: Pick<AnalyticalPlannerProposalV1, 'version' | 'selectedConceptIds' | 'tasks'>;
939
+ priorSelectedConceptIds?: string[];
940
+ verificationFeedback?: ProgramVerificationFeedbackV1;
941
+ /** At most four verifier-admitted cards released for a targeted revision. */
942
+ targetedCandidates?: AnalyticalPlannerCandidateCardV1[];
943
+ candidates: AnalyticalPlannerCandidateCardV1[];
944
+ deadlineMs: number;
945
+ }
946
+ export type AnalyticalPlannerOperationV1 = 'aggregate' | 'rank' | 'group' | 'filter' | 'trend' | 'compare' | 'project';
947
+ export interface AnalyticalPlannerTaskProposalV1 {
948
+ version: 1;
949
+ taskId: string;
950
+ /**
951
+ * Server task options this one program deliberately covers. Omitted means
952
+ * only `taskId`. The verifier must prove complete coverage before a
953
+ * compatible multi-clause Ask may collapse to one execution.
954
+ */
955
+ coveredTaskIds?: string[];
956
+ selectedConceptIds: string[];
957
+ /** Candidate-ID role bindings only; the verifier owns role compatibility. */
958
+ roleBindings: Partial<Record<EvidenceCandidateRoleV1, string[]>>;
959
+ /** Typed analytical intent, never SQL/DQL or a compiler authorization. */
960
+ operations: AnalyticalPlannerOperationV1[];
961
+ preferredCompiler?: 'certified' | 'metricflow' | 'governed_relational' | 'exploratory_sql';
962
+ assumptions?: string[];
963
+ }
964
+ export interface TargetedContextRequestV1 {
965
+ version: 1;
966
+ /** Exactly one verifier-proven role may be recovered per Ask turn. */
967
+ missingRoles: EvidenceCandidateRoleV1[];
968
+ /**
969
+ * Normalized business terms used to search the existing immutable 32-card
970
+ * workspace. The planner never receives or mints hidden workspace IDs.
971
+ */
972
+ searchTerms?: string[];
973
+ /** Optional references to cards already in the supplied 16-card package. */
974
+ relatedCandidateIds?: string[];
975
+ /**
976
+ * Legacy compatibility carrier. New planner JSON must not use this to name
977
+ * an unadmitted card; the verifier rejects anything outside the planner
978
+ * package before it can be treated as a recovery hint.
979
+ */
980
+ candidateIds?: string[];
981
+ /** Existing same-snapshot relationship paths, bounded to three. */
982
+ relationshipPathIds?: string[];
983
+ }
984
+ export interface TargetedContextResultV1 {
985
+ version: 1;
986
+ status: 'admitted' | 'unavailable' | 'denied';
987
+ candidateIds: string[];
988
+ relationshipPathIds: string[];
989
+ reasonCode: string;
990
+ }
991
+ export interface AnalyticalPlannerProposalV1 {
992
+ version: 1;
993
+ tasks: AnalyticalPlannerTaskProposalV1[];
994
+ selectedConceptIds: string[];
995
+ confidence?: 'high' | 'medium' | 'low';
996
+ missingInformation?: string[];
997
+ recovery?: TargetedContextRequestV1;
998
+ }
999
+ export interface ProgramVerificationFeedbackV1 {
1000
+ version: 1;
1001
+ status: 'valid' | 'needs_targeted_context' | 'ambiguous' | 'denied' | 'invalid';
1002
+ missingRoles: EvidenceCandidateRoleV1[];
1003
+ candidateIds: string[];
1004
+ reasonCode: string;
1005
+ }
1006
+ export interface EvidenceWorkspaceV2 extends Omit<EvidenceWorkspaceV1, 'version' | 'admittedCandidateIds'> {
1007
+ version: 2;
1008
+ /** The qualified immutable closure; never exceeds 32 candidates. */
1009
+ workspaceCandidateIds: string[];
1010
+ /** Cards released to the one planner call; never exceeds 16. */
1011
+ plannerCandidateIds: string[];
1012
+ /** V1 consumers read this as the planner admission. */
1013
+ admittedCandidateIds: string[];
1014
+ /**
1015
+ * Content-safe role admission counters. These are captured at the runtime
1016
+ * boundary, rather than reconstructed later from raw retrieval cards, so a
1017
+ * V7 trace can distinguish a missing requested role from a role-cap
1018
+ * exclusion after reload without retaining business labels or values.
1019
+ */
1020
+ roleCoverage?: Array<{
1021
+ role: EvidenceCandidateRoleV1;
1022
+ candidateCount: number;
1023
+ state?: EvidenceRoleCoverageStateV1;
1024
+ }>;
1025
+ targetedContext?: TargetedContextResultV1;
1026
+ }
1027
+ export interface BusinessQuestionFrameV4 extends Omit<BusinessQuestionFrameV3, 'version'> {
1028
+ version: 4;
1029
+ planningMode: AskPlanningModeV1;
1030
+ }
1031
+ export interface AnalyticalProgramV2 extends Omit<AnalyticalProgramV1, 'version' | 'candidateIds' | 'executionCandidateIds'> {
1032
+ version: 2;
1033
+ /** Validated meaning cards selected by the planner. */
1034
+ candidateIds: string[];
1035
+ /** Full immutable qualified workspace consumed by compilers. */
1036
+ executionCandidateIds: string[];
1037
+ plannerCandidateIds: string[];
1038
+ workspaceCandidateIds: string[];
1039
+ /**
1040
+ * Provider-neutral business interpretation accepted by the deterministic
1041
+ * verifier. IDs remain canonicalized below; the planner never gains join,
1042
+ * grain, additivity, trust, or compiler authority.
1043
+ */
1044
+ planner: {
1045
+ version: 1;
1046
+ tasks: Array<{
1047
+ taskId: string;
1048
+ coveredTaskIds?: string[];
1049
+ selectedConceptIds: string[];
1050
+ roleBindings: Partial<Record<EvidenceCandidateRoleV1, string[]>>;
1051
+ operations: AnalyticalPlannerOperationV1[];
1052
+ preferredCompiler?: AnalyticalPlannerTaskProposalV1['preferredCompiler'];
1053
+ assumptions: string[];
1054
+ }>;
1055
+ confidence?: AnalyticalPlannerProposalV1['confidence'];
1056
+ missingInformation: string[];
1057
+ };
1058
+ }
1059
+ /**
1060
+ * Planner V2 is the post-verification business interpretation. The provider
1061
+ * V1 wire format remains readable during rollout, but a frozen program does
1062
+ * not preserve a provider-selected relationship/join binding: relationship
1063
+ * closure is compiler-owned evidence, not business meaning.
1064
+ */
1065
+ export type AnalyticalPlannerBusinessRoleV2 = Exclude<EvidenceCandidateRoleV1, 'relationship'>;
1066
+ export interface AnalyticalPlannerTaskV2 {
1067
+ taskId: string;
1068
+ coveredTaskIds?: string[];
1069
+ selectedConceptIds: string[];
1070
+ roleBindings: Partial<Record<AnalyticalPlannerBusinessRoleV2, string[]>>;
1071
+ operations: AnalyticalPlannerOperationV1[];
1072
+ preferredCompiler?: AnalyticalPlannerTaskProposalV1['preferredCompiler'];
1073
+ assumptions: string[];
1074
+ }
1075
+ export interface AnalyticalPlannerInterpretationV2 {
1076
+ version: 2;
1077
+ /** The source is diagnostic only; it cannot change authority after verify. */
1078
+ source: 'provider' | 'deterministic' | 'legacy_adapter';
1079
+ tasks: AnalyticalPlannerTaskV2[];
1080
+ confidence?: AnalyticalPlannerProposalV1['confidence'];
1081
+ missingInformation: string[];
1082
+ }
1083
+ /**
1084
+ * One host-derived safe relationship closure. `candidateId` refers to the
1085
+ * compact same-snapshot path card; `relationshipEvidence` contains only its
1086
+ * canonical proof IDs. A planner never selects either value.
1087
+ */
1088
+ export interface CanonicalRelationshipPathReceiptV1 {
1089
+ version: 1;
1090
+ candidateId: string;
1091
+ proofClass: 'governed' | 'exploratory';
1092
+ relationshipEvidence: string[];
1093
+ }
1094
+ /**
1095
+ * Lossless typed inputs that survive planner/legacy adapter conversions. The
1096
+ * words remain local program data; diagnostic projections expose counts only.
1097
+ */
1098
+ export interface AnalyticalInputAtomV1 {
1099
+ version: 1;
1100
+ source: 'current_question' | 'trusted_successful_task';
1101
+ role: Exclude<EvidenceCandidateRoleV1, 'relationship' | 'context'> | 'filter';
1102
+ term: string;
1103
+ required: true;
1104
+ }
1105
+ /** A host-validated anchor from a successful prior task/result. */
1106
+ export interface TrustedAnalyticalTaskAnchorV1 {
1107
+ version: 1;
1108
+ /**
1109
+ * `member_binding` retains a validated selected result value.
1110
+ * `analytical_shape` retains only a successful task's metric/projection
1111
+ * shape for an explicit additive follow-up such as "add region here".
1112
+ * Neither form is provider supplied.
1113
+ */
1114
+ kind?: 'member_binding' | 'analytical_shape';
1115
+ displayDimension?: string;
1116
+ values: string[];
1117
+ /** Existing successful-task shape; no rows or free-form prior answer. */
1118
+ measures?: string[];
1119
+ dimensions?: string[];
1120
+ sourceTurnId?: string;
1121
+ resultFingerprint?: string;
1122
+ }
1123
+ /**
1124
+ * The authoritative frozen Ask contract. V1/V2 remain valid persisted JSON
1125
+ * readers; all new authoritative turns construct V3 before compiler entry.
1126
+ */
1127
+ export interface AnalyticalProgramV3 extends Omit<AnalyticalProgramV2, 'version' | 'planner'> {
1128
+ version: 3;
1129
+ planner: AnalyticalPlannerInterpretationV2;
1130
+ /** Compiler-owned path receipts; never provider-selected join instructions. */
1131
+ relationshipPaths: CanonicalRelationshipPathReceiptV1[];
1132
+ /** Current-turn atoms cannot be erased by a compatibility MeaningResolution. */
1133
+ inputAtoms: AnalyticalInputAtomV1[];
1134
+ /** Validated prior-result anchors are distinct from free-text member guesses. */
1135
+ trustedTaskAnchors: TrustedAnalyticalTaskAnchorV1[];
1136
+ }
1137
+ export interface AskAnalystConversationDeltaV2 extends Omit<AskAnalystConversationDeltaV1, 'version' | 'partialFrame'> {
1138
+ version: 2;
1139
+ partialFrame: Pick<BusinessQuestionFrameV4, 'kind' | 'requirements' | 'planningMode'>;
1140
+ programId?: string;
1141
+ }
1142
+ export interface AskAnalystStateV2 extends Omit<AskAnalystStateV1, 'version' | 'frame' | 'workspace' | 'program' | 'conversationDelta'> {
1143
+ version: 2;
1144
+ frame: BusinessQuestionFrameV4;
1145
+ workspace: EvidenceWorkspaceV2;
1146
+ program: AnalyticalProgramV2;
1147
+ conversationDelta: AskAnalystConversationDeltaV2;
1148
+ planningMode: AskPlanningModeV1;
1149
+ plannerRevisionCount: number;
1150
+ planningReceipt?: AskAnalystPlanningReceiptV1;
1151
+ }
1152
+ /** New authoritative state; V2 remains readable for interrupted old runs. */
1153
+ export interface AskAnalystStateV3 extends Omit<AskAnalystStateV2, 'version' | 'program'> {
1154
+ version: 3;
1155
+ program: AnalyticalProgramV3;
1156
+ }
1157
+ export interface AskAnalystPlanningReceiptV1 {
1158
+ version: 1;
1159
+ mode: AskPlanningModeV1;
1160
+ plannerCalls: number;
1161
+ revisionCalls: number;
1162
+ verification: ProgramVerificationFeedbackV1;
1163
+ }
1164
+ export interface BusinessAnswerV2 extends Omit<BusinessAnswerV1, 'version'> {
1165
+ version: 2;
1166
+ /** Facts and result fingerprint are the only authoritative narrative source. */
1167
+ factBinding: 'validated_result_facts' | 'deterministic_fallback';
1168
+ }
1169
+ export interface AgentRunDiagnosticReceiptV6 extends Omit<AgentRunDiagnosticReceiptV5, 'version'> {
1170
+ version: 6;
1171
+ planning?: AskAnalystPlanningReceiptV1;
1172
+ /** Role coverage is count-only: raw terms and candidate labels stay Advanced-only. */
1173
+ roleCoverage: Array<{
1174
+ role: EvidenceCandidateRoleV1;
1175
+ candidateCount: number;
1176
+ /** `alternatives` is a clarification state, not a proof of business meaning. */
1177
+ state?: EvidenceRoleCoverageStateV1;
1178
+ }>;
1179
+ /** The exact pre-execution cascade record behind the selected compiler. */
1180
+ cascade: {
1181
+ attempts: Array<Pick<CascadeTierAttemptV1, 'tier' | 'outcome' | 'planFrozen'>>;
1182
+ selectedTier?: AnalyticalCascadeDecisionV1['selectedTier'];
1183
+ stopReason?: string;
1184
+ planFrozen: boolean;
1185
+ };
1186
+ /** Present only for a typed terminal incident; never inferred from prose. */
1187
+ origin?: Pick<AskTerminalIncidentV1, 'boundary' | 'origin' | 'impact'>;
1188
+ connection: {
1189
+ attempted: boolean;
1190
+ };
1191
+ execution: {
1192
+ attempts: number;
1193
+ };
1194
+ /**
1195
+ * Content-safe physical counters. Research roots aggregate server-owned
1196
+ * child execution counters (with durable receipt fallback for older child
1197
+ * records); the root dispatch ledger remains the authority for provider
1198
+ * egress so child spans are never double-counted.
1199
+ */
1200
+ telemetry?: AgentRunTelemetryV1;
1201
+ facts: {
1202
+ factCount: number;
1203
+ resultFingerprint?: string;
1204
+ };
1205
+ safeNextAction: AskDecisionSummaryV2['nextAction'];
1206
+ /** Compact default story; raw spans and candidate lifecycle remain Advanced-only. */
1207
+ story: Array<{
1208
+ stage: 'retrieval' | 'role_coverage' | 'planner' | 'verification' | 'targeted_recovery' | 'cascade' | 'freeze' | 'connection' | 'execution' | 'facts';
1209
+ status: 'completed' | 'skipped' | 'blocked' | 'unavailable';
1210
+ reasonCode: string;
1211
+ }>;
1212
+ }
1213
+ /**
1214
+ * Additive V7 reader receipt. V6 remains the detailed, content-free trace
1215
+ * record; V7 projects it into the few decisions an analyst needs first:
1216
+ * whether the question was understood, whether evidence was sufficient, what
1217
+ * the planner/cascade decided, and whether a result was actually narrated.
1218
+ * It deliberately carries counts and enum outcomes only—never prompt text,
1219
+ * SQL, result rows, provider payloads, candidate labels, or member values.
1220
+ */
1221
+ export interface AgentRunDiagnosticReceiptV7 extends Omit<AgentRunDiagnosticReceiptV6, 'version'> {
1222
+ version: 7;
1223
+ inspector: {
1224
+ understood: {
1225
+ questionKind: BusinessQuestionFrameV4['kind'];
1226
+ conversationBinding: BusinessQuestionFrameV4['conversation']['binding'];
1227
+ measureCount: number;
1228
+ dimensionCount: number;
1229
+ entityRequested: boolean;
1230
+ hasBoundFilter: boolean;
1231
+ };
1232
+ evidence: {
1233
+ admittedCandidateCount: number;
1234
+ roleCount: number;
1235
+ recoveryAttempted: boolean;
1236
+ };
1237
+ planning: {
1238
+ mode: AskPlanningModeV1;
1239
+ plannerCalls: number;
1240
+ verification: ProgramVerificationFeedbackV1['status'];
1241
+ };
1242
+ route: {
1243
+ selectedTier?: AnalyticalCascadeDecisionV1['selectedTier'];
1244
+ tierAttemptCount: number;
1245
+ planFrozen: boolean;
1246
+ reviewRequired: boolean;
1247
+ };
1248
+ outcome: {
1249
+ connectionAttempted: boolean;
1250
+ executionAttempts: number;
1251
+ factCount: number;
1252
+ narration: 'fact_bound' | 'result_without_facts' | 'not_applicable';
1253
+ };
1254
+ };
1255
+ }
1256
+ /** New runtime values are V2; V1 values remain readable from old JSON runs. */
1257
+ export type AskAnalystState = AskAnalystStateV1 | AskAnalystStateV2 | AskAnalystStateV3;
1258
+ export type AnalyticalProgram = AnalyticalProgramV1 | AnalyticalProgramV2 | AnalyticalProgramV3;
1259
+ export type BusinessQuestionFrame = BusinessQuestionFrameV3 | BusinessQuestionFrameV4;
1260
+ export type BusinessAnswer = BusinessAnswerV1 | BusinessAnswerV2;
219
1261
  export interface AnalyticalTurnPlanV1 {
220
1262
  version: 1;
221
1263
  turnId?: string;
@@ -260,16 +1302,27 @@ export interface AnalyticalTurnAnswerV1 {
260
1302
  * report partial success instead of collapsing the whole turn to one error.
261
1303
  */
262
1304
  export declare function inferAnalyticalTurnKind(question: string): AnalyticalTurnKind;
263
- type RoleBalancedEvidenceCandidate = {
1305
+ export type RoleBalancedEvidenceCandidate = {
264
1306
  id: string;
265
1307
  qualifiedId?: string;
266
1308
  kind?: string;
267
1309
  semanticObjectType?: string;
268
1310
  name?: string;
269
1311
  aliases?: string[];
1312
+ /** Source-authored semantic or physical value type when the snapshot has it. */
1313
+ dataType?: string;
270
1314
  dimensions?: string[];
271
1315
  timeGrains?: string[];
272
1316
  relationshipEvidence?: string[];
1317
+ /**
1318
+ * Host-only runtime-value proof attached to one qualified physical column.
1319
+ * It is intentionally structural here so the retrieval selector can reserve
1320
+ * the field for a current literal without exposing values to a provider.
1321
+ */
1322
+ safeValueEvidence?: Array<{
1323
+ normalizedValue?: string;
1324
+ value?: string;
1325
+ }>;
273
1326
  relevanceScore?: number;
274
1327
  exactMatch?: boolean;
275
1328
  compatibility?: string;
@@ -279,6 +1332,15 @@ type RoleBalancedEvidenceCandidate = {
279
1332
  * may use the narrowly typed declarations below.
280
1333
  */
281
1334
  compatibilityFacts?: string[];
1335
+ /**
1336
+ * A narrowly-scoped host extension derived from the same immutable semantic
1337
+ * capability snapshot. It is not a lexical synonym or model assertion:
1338
+ * the retriever may mint it only when one MetricFlow-capable grouping field
1339
+ * is uniquely available for the requested business role. Keeping the
1340
+ * source metric and exact dimension identity here lets routing record the
1341
+ * assumption while the frozen capability still owns execution safety.
1342
+ */
1343
+ sameSnapshotRoleExtension?: SameSnapshotRoleExtensionV1;
282
1344
  analyticalCapability?: {
283
1345
  dimensions?: Array<{
284
1346
  dimensionId?: string;
@@ -288,6 +1350,39 @@ type RoleBalancedEvidenceCandidate = {
288
1350
  }>;
289
1351
  };
290
1352
  };
1353
+ export interface SameSnapshotRoleExtensionV1 {
1354
+ version: 1;
1355
+ role: 'categorical_dimension';
1356
+ requestedTerm: string;
1357
+ metricId: string;
1358
+ dimensionId: string;
1359
+ /**
1360
+ * `sole_metricflow_grouping_dimension` is the deliberately narrow
1361
+ * geography recovery path. `exact_metricflow_grouping_dimension` is an
1362
+ * equally snapshot-bound extension for a current-question categorical
1363
+ * phrase whose exact, qualified dimension is declared by the admitted
1364
+ * metric capability. Neither value permits lexical joins or a model-owned
1365
+ * field identity.
1366
+ */
1367
+ basis: 'sole_metricflow_grouping_dimension' | 'exact_metricflow_grouping_dimension';
1368
+ }
1369
+ /**
1370
+ * Entity/display terms are represented in the historical `dimensions` seed
1371
+ * so ranking plans can retain their requested grain. They must not consume
1372
+ * the separate categorical-dimension admission lane. For example, in "top
1373
+ * customers by product category", `customer` is the entity/rank role while
1374
+ * `product category` is the required categorical grouping role.
1375
+ */
1376
+ export declare function categoricalDimensionRequirementTerms(requirements: Pick<AnalyticalRequirementSetV1, 'dimensions' | 'entityTerms' | 'entityDisplayTerms'>): string[];
1377
+ /**
1378
+ * A small, typed vocabulary bridge for categorical field identities. It is
1379
+ * intentionally not a general synonym engine: only the field-kind suffix is
1380
+ * canonicalized, while the scoped business noun must still match. Thus
1381
+ * `product category` can bind the snapshot-declared `product_type`, whereas
1382
+ * `customer_type` cannot satisfy it. A bare `category` remains potentially
1383
+ * ambiguous when more than one qualified `*_type` field exists.
1384
+ */
1385
+ export declare function categoricalDimensionTermsMatch(left: string, right: string): boolean;
291
1386
  /**
292
1387
  * Normalize grammatical aggregation wrappers before they become a plan
293
1388
  * requirement. Retrieval/parser output is allowed to retain useful search
@@ -295,10 +1390,13 @@ type RoleBalancedEvidenceCandidate = {
295
1390
  * or "for each customer" as separate physical measures. The grouping entity
296
1391
  * is represented by the dimension/entity roles instead.
297
1392
  *
298
- * `order count for each customer` is the common prose form for a count
299
- * aggregation at customer grain. Keep the aggregation (`count`) and remove
300
- * the object noun (`order`) only for that exact grouped construction; a named
301
- * metric such as `order_value` remains untouched.
1393
+ * `order count for each customer` is the common prose form for the authored
1394
+ * `order_count` semantic measure at customer grain. Keep that compound
1395
+ * identity intact: reducing it to the generic aggregation `count` makes the
1396
+ * unfiltered `Orders` MetricFlow metric indistinguishable from scoped metrics
1397
+ * such as `Drink Orders` and `Food Orders`. The grouping entity is still
1398
+ * represented by the dimension/entity roles rather than becoming another
1399
+ * measure.
302
1400
  */
303
1401
  export declare function normalizeAnalyticalMeasureTerms(question: string, values: readonly string[], options?: {
304
1402
  preserveIdentity?: boolean;
@@ -321,8 +1419,23 @@ export declare function buildAnalyticalRequirementSet(input: {
321
1419
  limit: number;
322
1420
  }>;
323
1421
  }): AnalyticalRequirementSetV1;
1422
+ /**
1423
+ * Keep account display-key selection separate from common account attributes.
1424
+ * Candidate names originate in dbt/semantic identifiers, so underscores and
1425
+ * dots must be normalized before testing (`account_sentiment_rating` is just
1426
+ * as much an attribute as "Account Sentiment Rating").
1427
+ */
1428
+ export declare function hasEntityAttributeTerm(value: string): boolean;
1429
+ export declare function isEntityAttributeCandidate(candidate: RoleBalancedEvidenceCandidate): boolean;
324
1430
  /** Classify the role an already-qualified candidate may fill. */
325
1431
  export declare function evidenceCandidateRoles(candidate: RoleBalancedEvidenceCandidate): EvidenceCandidateRoleV1[];
1432
+ /**
1433
+ * A direct ranking measure is authoritative for metric admission. Other
1434
+ * retrieved metrics remain visible in the lifecycle receipt, but they cannot
1435
+ * become a second metric choice merely because they are correlated with the
1436
+ * entity phrase in the question.
1437
+ */
1438
+ export declare function candidateConflictsWithExplicitRankingMeasure(candidate: RoleBalancedEvidenceCandidate, requirements: AnalyticalRequirementSetV1): boolean;
326
1439
  /**
327
1440
  * A categorical dimension may satisfy a requested business role only through
328
1441
  * its own snapshot-authored declaration. In particular, `location_name` is
@@ -331,7 +1444,7 @@ export declare function evidenceCandidateRoles(candidate: RoleBalancedEvidenceCa
331
1444
  * declared with the semantic geography role. This protects admission from
332
1445
  * broad lexical geography expansion while retaining role-balanced recall.
333
1446
  */
334
- export declare function candidateMatchesCategoricalDimensionRequirement(candidate: Pick<RoleBalancedEvidenceCandidate, 'compatibilityFacts'>, terms: readonly string[]): boolean;
1447
+ export declare function candidateMatchesCategoricalDimensionRequirement(candidate: Pick<RoleBalancedEvidenceCandidate, 'compatibilityFacts' | 'sameSnapshotRoleExtension'>, terms: readonly string[]): boolean;
335
1448
  /**
336
1449
  * Keep an internal retrieval result broad while making the provider package
337
1450
  * role-balanced. Exact/alias matches stay pinned; each requested role gets up
@@ -344,6 +1457,16 @@ export declare function selectRoleBalancedMeaningCandidates<T extends RoleBalanc
344
1457
  /** Use before any kind cap to reserve exact/required-role cards. */
345
1458
  pinOnly?: boolean;
346
1459
  }): T[];
1460
+ /**
1461
+ * Build the Ask execution workspace before planner admission. It is the
1462
+ * only helper that may create the 32-card closure; all later compiler paths
1463
+ * must intersect with this immutable result rather than reaching back into a
1464
+ * broad snapshot.
1465
+ */
1466
+ export declare function selectRoleBalancedWorkspaceCandidates<T extends RoleBalancedEvidenceCandidate>(input: {
1467
+ candidates: T[];
1468
+ requirements: AnalyticalRequirementSetV1;
1469
+ }): T[];
347
1470
  export declare function classifyProviderFailure(input: {
348
1471
  message?: string;
349
1472
  code?: string;
@@ -577,6 +1700,133 @@ export interface ResearchEvidenceLedgerV2 {
577
1700
  limitedScope: boolean;
578
1701
  stoppingReason: ResearchEvidenceLedgerV1['stoppingReason'];
579
1702
  }
1703
+ /**
1704
+ * A local structural lineage observation is not a query result. This receipt
1705
+ * deliberately carries only bounded counts, opaque fingerprints, and
1706
+ * allowlisted status values: it must never become a place where prompts, SQL,
1707
+ * rows, graph labels, paths, or provider output are persisted.
1708
+ */
1709
+ export type ResearchLineageEvidenceStatusV1 = 'completed' | 'missing' | 'ambiguous' | 'stale' | 'truncated' | 'unavailable';
1710
+ export type ResearchLineageResolutionV1 = 'exact_id' | 'exact_name' | 'canonical_alias' | 'missing' | 'ambiguous' | 'stale' | 'unavailable';
1711
+ export type ResearchLineageNodeTypeV1 = 'source_table' | 'dbt_model' | 'dbt_source' | 'term' | 'block' | 'business_view' | 'metric' | 'dimension' | 'domain' | 'chart' | 'notebook' | 'dashboard' | 'app';
1712
+ export interface ResearchLineageEvidenceReceiptV1 {
1713
+ version: 1;
1714
+ evidenceKind: 'lineage_graph';
1715
+ /** Opaque local identity only; no source path or graph content is retained. */
1716
+ snapshotId?: string;
1717
+ snapshotFingerprint?: string;
1718
+ graphFingerprint: string;
1719
+ targetFingerprint: string;
1720
+ status: ResearchLineageEvidenceStatusV1;
1721
+ resolution: ResearchLineageResolutionV1;
1722
+ candidateCount: number;
1723
+ targetType?: ResearchLineageNodeTypeV1;
1724
+ upstreamNodeCount: number;
1725
+ downstreamNodeCount: number;
1726
+ upstreamPathCount: number;
1727
+ downstreamPathCount: number;
1728
+ traversedNodeCount: number;
1729
+ traversedEdgeCount: number;
1730
+ maxDepth: number;
1731
+ maxPaths: number;
1732
+ maxNodes: number;
1733
+ maxEdges: number;
1734
+ truncated: boolean;
1735
+ /** One-way digest of the bounded structural program, never a result digest. */
1736
+ structuralFingerprint?: string;
1737
+ validator: {
1738
+ version: 1;
1739
+ kind: 'structural_dependency';
1740
+ evaluated: boolean;
1741
+ outcome: 'dependency_observed' | 'inconclusive';
1742
+ /** A lineage edge is structural evidence only, never a causal conclusion. */
1743
+ nonCausal: true;
1744
+ };
1745
+ /** This program must not dispatch AI, SQL, warehouse, or repair work. */
1746
+ zeroCallCounters: {
1747
+ providerCalls: 0;
1748
+ sqlExecutions: 0;
1749
+ warehouseExecutions: 0;
1750
+ repairAttempts: 0;
1751
+ };
1752
+ }
1753
+ export type ResearchEvidenceKindV3 = 'analytical_result' | 'lineage_graph';
1754
+ /**
1755
+ * V3 is additive and content-safe. V1/V2 remain available to old readers,
1756
+ * while V3 distinguishes a receipt-bound analytical result from a bounded
1757
+ * structural lineage observation. In particular, the lineage variant has no
1758
+ * result fingerprint, execution receipt, row count, SQL, or provider payload.
1759
+ */
1760
+ export interface ResearchEvidenceLedgerAnalyticalEntryV3 {
1761
+ version: 3;
1762
+ id: string;
1763
+ branchId: string;
1764
+ evidenceKind: 'analytical_result';
1765
+ status: ResearchLedgerEntryV1['status'];
1766
+ verdict: ResearchEvidenceVerdictV2;
1767
+ hypothesisFingerprint?: string;
1768
+ factIds: string[];
1769
+ counterEvidenceFactIds: string[];
1770
+ receiptFingerprints: string[];
1771
+ resultFingerprint?: string;
1772
+ }
1773
+ export interface ResearchEvidenceLedgerLineageEntryV3 {
1774
+ version: 3;
1775
+ id: string;
1776
+ branchId: string;
1777
+ evidenceKind: 'lineage_graph';
1778
+ /** The structural program completed even when a target is missing/stale. */
1779
+ status: 'observed' | 'failed' | 'skipped';
1780
+ verdict: ResearchEvidenceVerdictV2;
1781
+ hypothesisFingerprint?: string;
1782
+ factIds: string[];
1783
+ counterEvidenceFactIds: string[];
1784
+ receiptFingerprints: string[];
1785
+ lineageReceipt: ResearchLineageEvidenceReceiptV1;
1786
+ }
1787
+ export type ResearchEvidenceLedgerEntryV3 = ResearchEvidenceLedgerAnalyticalEntryV3 | ResearchEvidenceLedgerLineageEntryV3;
1788
+ export interface ResearchEvidenceLedgerV3 {
1789
+ version: 3;
1790
+ /** One-way root-question identity; V3 does not retain research prose. */
1791
+ rootQuestionFingerprint: string;
1792
+ planId?: string;
1793
+ snapshotId?: string;
1794
+ entries: ResearchEvidenceLedgerEntryV3[];
1795
+ factIds: string[];
1796
+ groundableBranchCount: number;
1797
+ limitedScope: boolean;
1798
+ stoppingReason: ResearchEvidenceLedgerV1['stoppingReason'];
1799
+ }
1800
+ export interface ResearchEvidenceLedgerAnalyticalInputV3 {
1801
+ kind: 'analytical_result';
1802
+ index: number;
1803
+ entry: ResearchEvidenceLedgerEntryV2;
1804
+ hypothesisFingerprint?: string;
1805
+ }
1806
+ export interface ResearchEvidenceLedgerLineageInputV3 {
1807
+ kind: 'lineage_graph';
1808
+ index: number;
1809
+ id: string;
1810
+ branchId: string;
1811
+ receipt: ResearchLineageEvidenceReceiptV1;
1812
+ hypothesisFingerprint?: string;
1813
+ /** Omitted means the direct structural program completed normally. */
1814
+ status?: 'observed' | 'failed' | 'skipped';
1815
+ }
1816
+ /**
1817
+ * Build a mixed V3 ledger without reinterpreting V1/V2. The legacy ledgers
1818
+ * continue to contain analytical branches only, because their `observed`
1819
+ * state requires an execution/result receipt and would otherwise falsely
1820
+ * represent a graph walk as query execution.
1821
+ */
1822
+ export declare function buildResearchEvidenceLedgerV3(input: {
1823
+ rootQuestionFingerprint: string;
1824
+ planId?: string;
1825
+ snapshotId?: string;
1826
+ groundableBranchCount?: number;
1827
+ entries: Array<ResearchEvidenceLedgerAnalyticalInputV3 | ResearchEvidenceLedgerLineageInputV3>;
1828
+ stoppingReason?: ResearchEvidenceLedgerV1['stoppingReason'];
1829
+ }): ResearchEvidenceLedgerV3;
580
1830
  export declare function capResearchBranches<T>(branches: T[], max?: number): T[];
581
1831
  export declare function buildResearchEvidenceLedger(input: {
582
1832
  rootQuestion: string;